Browse Source

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 <jit.loon.lim@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: Ibfaa47fb7a25176eebf06f4828bf9729d56f12ed
pull/1994/merge
Sieu Mun Tang 2 years ago
parent
commit
02a9d70c4d
  1. 1
      plat/intel/soc/agilex/include/agilex_clock_manager.h
  2. 2
      plat/intel/soc/agilex/include/socfpga_plat_def.h
  3. 11
      plat/intel/soc/common/socfpga_delay_timer.c
  4. 57
      plat/intel/soc/n5x/include/n5x_clock_manager.h
  5. 7
      plat/intel/soc/n5x/include/socfpga_plat_def.h
  6. 1
      plat/intel/soc/n5x/platform.mk
  7. 116
      plat/intel/soc/n5x/soc/n5x_clock_manager.c
  8. 1
      plat/intel/soc/stratix10/include/s10_clock_manager.h
  9. 2
      plat/intel/soc/stratix10/include/socfpga_plat_def.h

1
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

2
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 */

11
plat/intel/soc/common/socfpga_delay_timer.c

@ -10,6 +10,15 @@
#include <lib/mmio.h>
#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));

57
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

7
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 */

1
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 \

116
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 <assert.h>
#include <errno.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#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;
}

1
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

2
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 */

Loading…
Cancel
Save