feat(ast2700): set up CPU clock frequency by SCU

Modify generic timer frequency by SCU setting
1. check SCU_CPU_HW_STRAP1 using HPLL or MPLL
  SCU_CPU_HW_STRAP1[4]=1, using HPLL
  SCU_CPU_HW_STRAP1[4]=0, using MPLL

2. read HPLL or MPLL
  HPLL: frequency setting in SCU_CPU_HW_STRAP1[2:3]
  MPLL: CLKIN_25M with mul and div setting from SCU_CPU_MPLL

Change-Id: I31eb10107b9da7c6746887ba36ead8ca61d86aae
Signed-off-by: Kevin Chen <kevin_chen@aspeedtech.com>
This commit is contained in:
Kevin Chen 2024-06-18 17:02:49 +08:00
parent c4d9fbec5e
commit e3d1bbdb08
4 changed files with 100 additions and 9 deletions

View file

@ -21,9 +21,6 @@
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
PLATFORM_CORE_COUNT_PER_CLUSTER)
/* arch timer */
#define PLAT_SYSCNT_CLKIN_HZ U(1600000000)
/* power domain */
#define PLAT_MAX_PWR_LVL U(1)
#define PLAT_NUM_PWR_DOMAINS U(5)
@ -55,4 +52,12 @@
#define CONSOLE_UART_CLKIN_HZ U(1846153)
#define CONSOLE_UART_BAUDRATE U(115200)
/* CLK information */
#define CLKIN_25M UL(25000000)
#define PLAT_CLK_GATE_NUM U(29)
#define PLAT_CLK_HPLL (PLAT_CLK_GATE_NUM + 5)
#define PLAT_CLK_DPLL (PLAT_CLK_GATE_NUM + 6)
#define PLAT_CLK_MPLL (PLAT_CLK_GATE_NUM + 7)
#endif /* PLATFORM_DEF_H */

View file

@ -19,6 +19,10 @@
/* CPU-die SCU */
#define SCU_CPU_BASE U(0x12c02000)
#define SCU_CPU_HW_STRAP1 (SCU_CPU_BASE + 0x010)
#define SCU_CPU_HPLL (SCU_CPU_BASE + 0x300)
#define SCU_CPU_DPLL (SCU_CPU_BASE + 0x308)
#define SCU_CPU_MPLL (SCU_CPU_BASE + 0x310)
#define SCU_CPU_SMP_EP0 (SCU_CPU_BASE + 0x780)
#define SCU_CPU_SMP_EP1 (SCU_CPU_BASE + 0x788)
#define SCU_CPU_SMP_EP2 (SCU_CPU_BASE + 0x790)

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <arch.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
@ -112,3 +113,90 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
return ep_info;
}
/*
* Clock divider/multiplier configuration struct.
* For H-PLL and M-PLL the formula is
* (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
* M - Numerator
* N - Denumerator
* P - Post Divider
* They have the same layout in their control register.
*
*/
union plat_pll_reg {
uint32_t w;
struct {
uint16_t m : 13; /* bit[12:0] */
uint8_t n : 6; /* bit[18:13] */
uint8_t p : 4; /* bit[22:19] */
uint8_t off : 1; /* bit[23] */
uint8_t bypass : 1; /* bit[24] */
uint8_t reset : 1; /* bit[25] */
uint8_t reserved : 6; /* bit[31:26] */
} b;
};
static uint32_t plat_get_pll_rate(int pll_idx)
{
union plat_pll_reg pll_reg;
uint32_t mul = 1, div = 1;
uint32_t rate = 0;
switch (pll_idx) {
case PLAT_CLK_HPLL:
pll_reg.w = mmio_read_32(SCU_CPU_HPLL);
break;
case PLAT_CLK_DPLL:
pll_reg.w = mmio_read_32(SCU_CPU_DPLL);
break;
case PLAT_CLK_MPLL:
pll_reg.w = mmio_read_32(SCU_CPU_MPLL);
break;
default:
ERROR("%s: invalid PSP clock source (%d)\n", __func__, pll_idx);
return -EINVAL;
}
if (pll_idx == PLAT_CLK_HPLL && ((mmio_read_32(SCU_CPU_HW_STRAP1) & GENMASK(3, 2)) != 0U)) {
switch ((mmio_read_32(SCU_CPU_HW_STRAP1) & GENMASK(3, 2)) >> 2) {
case 1U:
rate = 1900000000;
break;
case 2U:
rate = 1800000000;
break;
case 3U:
rate = 1700000000;
break;
default:
rate = 2000000000;
break;
}
} else {
if (pll_reg.b.bypass != 0U) {
if (pll_idx == PLAT_CLK_MPLL) {
/* F = 25Mhz * [M / (n + 1)] / (p + 1) */
mul = (pll_reg.b.m) / ((pll_reg.b.n + 1));
div = (pll_reg.b.p + 1);
} else {
/* F = 25Mhz * [(M + 2) / 2 * (n + 1)] / (p + 1) */
mul = (pll_reg.b.m + 1) / ((pll_reg.b.n + 1) * 2);
div = (pll_reg.b.p + 1);
}
}
rate = ((CLKIN_25M * mul) / div);
}
return rate;
}
unsigned int plat_get_syscnt_freq2(void)
{
if (mmio_read_32(SCU_CPU_HW_STRAP1) & BIT(4)) {
return plat_get_pll_rate(PLAT_CLK_HPLL);
} else {
return plat_get_pll_rate(PLAT_CLK_MPLL);
}
}

View file

@ -59,12 +59,6 @@ poll_smp_mbox_go:
br x0
endfunc plat_secondary_cold_boot_setup
/* unsigned int plat_get_syscnt_freq2(void); */
func plat_get_syscnt_freq2
mov_imm w0, PLAT_SYSCNT_CLKIN_HZ
ret
endfunc plat_get_syscnt_freq2
/* int plat_crash_console_init(void); */
func plat_crash_console_init
mov_imm x0, CONSOLE_UART_BASE