From 02a9d70c4deaa2102386611ac6b305838003148d Mon Sep 17 00:00:00 2001 From: Sieu Mun Tang Date: Thu, 23 Jun 2022 18:05:02 +0800 Subject: [PATCH] feat(intel): implement timer init divider via CPU frequency for N5X Get CPU frequency and update the timer init div with it. The timer is vary based on the CPU frequency instead of hardcoded. Signed-off-by: Jit Loon Lim Signed-off-by: Sieu Mun Tang Change-Id: Ibfaa47fb7a25176eebf06f4828bf9729d56f12ed --- .../soc/agilex/include/agilex_clock_manager.h | 1 + .../soc/agilex/include/socfpga_plat_def.h | 2 - plat/intel/soc/common/socfpga_delay_timer.c | 11 ++ .../intel/soc/n5x/include/n5x_clock_manager.h | 57 +++++++++ plat/intel/soc/n5x/include/socfpga_plat_def.h | 7 +- plat/intel/soc/n5x/platform.mk | 1 + plat/intel/soc/n5x/soc/n5x_clock_manager.c | 116 ++++++++++++++++++ .../soc/stratix10/include/s10_clock_manager.h | 1 + .../soc/stratix10/include/socfpga_plat_def.h | 2 - 9 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 plat/intel/soc/n5x/include/n5x_clock_manager.h create mode 100644 plat/intel/soc/n5x/soc/n5x_clock_manager.c diff --git a/plat/intel/soc/agilex/include/agilex_clock_manager.h b/plat/intel/soc/agilex/include/agilex_clock_manager.h index f39d475e6..8ec8e592b 100644 --- a/plat/intel/soc/agilex/include/agilex_clock_manager.h +++ b/plat/intel/soc/agilex/include/agilex_clock_manager.h @@ -127,5 +127,6 @@ void config_clkmgr_handoff(handoff *hoff_ptr); uint32_t get_wdt_clk(void); uint32_t get_uart_clk(void); uint32_t get_mmc_clk(void); +uint32_t get_cpu_clk(void); #endif diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h index b216ab14b..4d7198cbe 100644 --- a/plat/intel/soc/agilex/include/socfpga_plat_def.h +++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h @@ -35,6 +35,4 @@ /* Platform specific system counter */ #define PLAT_SYS_COUNTER_FREQ_IN_MHZ get_cpu_clk() -uint32_t get_cpu_clk(void); - #endif /* PLAT_SOCFPGA_DEF_H */ diff --git a/plat/intel/soc/common/socfpga_delay_timer.c b/plat/intel/soc/common/socfpga_delay_timer.c index dcd51e270..8fce5cf88 100644 --- a/plat/intel/soc/common/socfpga_delay_timer.c +++ b/plat/intel/soc/common/socfpga_delay_timer.c @@ -10,6 +10,15 @@ #include #include "socfpga_plat_def.h" + +#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX +#include "agilex_clock_manager.h" +#elif PLATFORM_MODEL == PLAT_SOCFPGA_N5X +#include "n5x_clock_manager.h" +#elif PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 +#include "s10_clock_manager.h" +#endif + #define SOCFPGA_GLOBAL_TIMER 0xffd01000 #define SOCFPGA_GLOBAL_TIMER_EN 0x3 @@ -43,6 +52,8 @@ void socfpga_delay_timer_init(void) socfpga_delay_timer_init_args(); mmio_write_32(SOCFPGA_GLOBAL_TIMER, SOCFPGA_GLOBAL_TIMER_EN); + NOTICE("BL31 CLK freq = %d MHz\n", PLAT_SYS_COUNTER_FREQ_IN_MHZ); + asm volatile("msr cntp_ctl_el0, %0" : : "r" (SOCFPGA_GLOBAL_TIMER_EN)); asm volatile("msr cntp_tval_el0, %0" : : "r" (~0)); diff --git a/plat/intel/soc/n5x/include/n5x_clock_manager.h b/plat/intel/soc/n5x/include/n5x_clock_manager.h new file mode 100644 index 000000000..6e2b978cf --- /dev/null +++ b/plat/intel/soc/n5x/include/n5x_clock_manager.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CLOCKMANAGER_H +#define CLOCKMANAGER_H + +#include "socfpga_handoff.h" + +/* MACRO DEFINITION */ +#define SOCFPGA_GLOBAL_TIMER 0xffd01000 +#define SOCFPGA_GLOBAL_TIMER_EN 0x3 + +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16) +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16 +#define CLKMGR_PLLDIV_FDIV_MASK GENMASK(16, 8) +#define CLKMGR_PLLDIV_FDIV_OFFSET 8 +#define CLKMGR_PLLDIV_REFCLKDIV_MASK GENMASK(5, 0) +#define CLKMGR_PLLDIV_REFCLKDIV_OFFSET 0 +#define CLKMGR_PLLDIV_OUTDIV_QDIV_MASK GENMASK(26, 24) +#define CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET 24 + +#define CLKMGR_PLLOUTDIV_C1CNT_MASK GENMASK(12, 8) +#define CLKMGR_PLLOUTDIV_C1CNT_OFFSET 8 +#define CLKMGR_PLLDIV_OUTDIV_QDIV_MASK GENMASK(26, 24) +#define CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET 24 +#define CLKMGR_CLKSRC_MASK GENMASK(18, 16) +#define CLKMGR_CLKSRC_OFFSET 16 +#define CLKMGR_NOCDIV_DIVIDER_MASK GENMASK(1, 0) +#define CLKMGR_NOCDIV_L4MAIN_OFFSET 0 + +#define CLKMGR_INTOSC_HZ 400000000 +#define CLKMGR_VCO_PSRC_EOSC1 0 +#define CLKMGR_VCO_PSRC_INTOSC 1 +#define CLKMGR_VCO_PSRC_F2S 2 +#define CLKMGR_CLKSRC_MAIN 0 +#define CLKMGR_CLKSRC_PER 1 + +#define CLKMGR_N5X_BASE 0xffd10000 +#define CLKMGR_MAINPLL_NOCCLK 0x40 +#define CLKMGR_MAINPLL_NOCDIV 0x44 +#define CLKMGR_MAINPLL_PLLGLOB 0x48 +#define CLKMGR_MAINPLL_PLLOUTDIV 0x54 +#define CLKMGR_MAINPLL_PLLDIV 0x50 +#define CLKMGR_PERPLL_PLLGLOB 0x9c +#define CLKMGR_PERPLL_PLLDIV 0xa4 +#define CLKMGR_PERPLL_PLLOUTDIV 0xa8 + +/* FUNCTION DEFINITION */ +uint64_t clk_get_pll_output_hz(void); +uint64_t get_l4_clk(void); +uint32_t get_clk_freq(uint32_t psrc_reg); +uint32_t get_cpu_clk(void); + +#endif diff --git a/plat/intel/soc/n5x/include/socfpga_plat_def.h b/plat/intel/soc/n5x/include/socfpga_plat_def.h index 4c36f91f5..eec841111 100644 --- a/plat/intel/soc/n5x/include/socfpga_plat_def.h +++ b/plat/intel/soc/n5x/include/socfpga_plat_def.h @@ -32,11 +32,6 @@ #define SOCFPGA_SOC2FPGA_SCR_REG_BASE U(0xffd21200) #define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE U(0xffd21300) -/* Platform specific system counter */ -/* - * In N5X the clk init is done in Uboot SPL. - * BL31 shall bypass the clk init and only provides other APIs. - */ -#define PLAT_SYS_COUNTER_FREQ_IN_MHZ (400) +#define PLAT_SYS_COUNTER_FREQ_IN_MHZ get_cpu_clk() #endif /* PLAT_SOCFPGA_DEF_H */ diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk index 4f3da4edb..7afeb7474 100644 --- a/plat/intel/soc/n5x/platform.mk +++ b/plat/intel/soc/n5x/platform.mk @@ -36,6 +36,7 @@ BL31_SOURCES += \ lib/cpus/aarch64/cortex_a53.S \ plat/common/plat_psci_common.c \ plat/intel/soc/n5x/bl31_plat_setup.c \ + plat/intel/soc/n5x/soc/n5x_clock_manager.c \ plat/intel/soc/common/socfpga_psci.c \ plat/intel/soc/common/socfpga_sip_svc.c \ plat/intel/soc/common/socfpga_sip_svc_v2.c \ diff --git a/plat/intel/soc/n5x/soc/n5x_clock_manager.c b/plat/intel/soc/n5x/soc/n5x_clock_manager.c new file mode 100644 index 000000000..c09b25bbe --- /dev/null +++ b/plat/intel/soc/n5x/soc/n5x_clock_manager.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "n5x_clock_manager.h" +#include "socfpga_system_manager.h" + + +uint64_t clk_get_pll_output_hz(void) +{ + uint32_t clksrc; + uint32_t scr_reg; + uint32_t divf; + uint32_t divr; + uint32_t divq; + uint32_t power = 1; + uint64_t clock = 0; + + clksrc = ((get_clk_freq(CLKMGR_PERPLL_PLLGLOB)) & + CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET; + + switch (clksrc) { + case CLKMGR_VCO_PSRC_EOSC1: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); + clock = mmio_read_32(scr_reg); + break; + + case CLKMGR_VCO_PSRC_INTOSC: + clock = CLKMGR_INTOSC_HZ; + break; + + case CLKMGR_VCO_PSRC_F2S: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); + clock = mmio_read_32(scr_reg); + break; + } + + divf = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & + CLKMGR_PLLDIV_FDIV_MASK) >> CLKMGR_PLLDIV_FDIV_OFFSET; + divr = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & + CLKMGR_PLLDIV_REFCLKDIV_MASK) >> CLKMGR_PLLDIV_REFCLKDIV_OFFSET; + divq = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & + CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >> CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET; + + while (divq) { + power *= 2; + divq--; + } + + return ((clock * 2 * (divf + 1)) / ((divr + 1) * power)); +} + +uint64_t get_l4_clk(void) +{ + uint32_t clock = 0; + uint32_t mainpll_c1cnt; + uint32_t perpll_c1cnt; + uint32_t clksrc; + + mainpll_c1cnt = ((get_clk_freq(CLKMGR_MAINPLL_PLLOUTDIV)) & + CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET; + + perpll_c1cnt = ((get_clk_freq(CLKMGR_PERPLL_PLLOUTDIV)) & + CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET; + + clksrc = ((get_clk_freq(CLKMGR_MAINPLL_NOCCLK)) & CLKMGR_CLKSRC_MASK) >> + CLKMGR_CLKSRC_OFFSET; + + switch (clksrc) { + case CLKMGR_CLKSRC_MAIN: + clock = clk_get_pll_output_hz(); + clock /= 1 + mainpll_c1cnt; + break; + + case CLKMGR_CLKSRC_PER: + clock = clk_get_pll_output_hz(); + clock /= 1 + perpll_c1cnt; + break; + + default: + return 0; + } + + clock /= BIT(((get_clk_freq(CLKMGR_MAINPLL_NOCDIV)) >> + CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +/* Calculate clock frequency based on parameter */ +uint32_t get_clk_freq(uint32_t psrc_reg) +{ + uint32_t clk_psrc; + + clk_psrc = mmio_read_32(CLKMGR_N5X_BASE + psrc_reg); + + return clk_psrc; +} + +/* Get cpu freq clock */ +uint32_t get_cpu_clk(void) +{ + uint32_t cpu_clk = 0; + + cpu_clk = get_l4_clk()/PLAT_SYS_COUNTER_CONVERT_TO_MHZ; + + return cpu_clk; +} diff --git a/plat/intel/soc/stratix10/include/s10_clock_manager.h b/plat/intel/soc/stratix10/include/s10_clock_manager.h index cf57df342..661e2040f 100644 --- a/plat/intel/soc/stratix10/include/s10_clock_manager.h +++ b/plat/intel/soc/stratix10/include/s10_clock_manager.h @@ -95,5 +95,6 @@ uint32_t get_uart_clk(void); uint32_t get_mmc_clk(void); uint32_t get_l3_clk(uint32_t ref_clk); uint32_t get_ref_clk(uint32_t pllglob); +uint32_t get_cpu_clk(void); #endif diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h index 516cc7562..da6414f4e 100644 --- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h +++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h @@ -34,7 +34,5 @@ /* Platform specific system counter */ #define PLAT_SYS_COUNTER_FREQ_IN_MHZ get_cpu_clk() -uint32_t get_cpu_clk(void); - #endif /* PLATSOCFPGA_DEF_H */