
On 7/22/21 1:30 AM, Icenowy Zheng wrote:
R329 has a quite different clock tree than other SoCs. It has only 4 PLLs and its PLL-PERIPH has two post dividers, one for the normal PLL-PERIPH-2x output and another for a special PLL-PERIPH-800M output. In addition, its PLL configuration registers are in PRCM memory zone, not the ordinary CPUX CCU one.
Add support for basical R329 clock initialization.
Signed-off-by: Icenowy Zheng icenowy@sipeed.com
Reviewed-by: Samuel Holland samuel@sholland.org
One minor comment below.
arch/arm/mach-sunxi/clock_sun50i_h6.c | 49 ++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c index a947463e0a..28bc5fccd8 100644 --- a/arch/arm/mach-sunxi/clock_sun50i_h6.c +++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c @@ -9,6 +9,13 @@ void clock_init_safe(void) { struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; +#ifdef CONFIG_MACH_SUN50I_R329
- struct sunxi_prcm_reg *const prcm =
(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
- struct sunxi_prcm_reg *const pllccm = prcm;
+#else
- struct sunxi_ccm_reg *const pllccm = ccm;
+#endif
/* this seems to enable PLLs on H616 */ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616)) @@ -16,22 +23,26 @@ void clock_init_safe(void)
clock_set_pll1(408000000);
- writel(CCM_PLL6_DEFAULT, &ccm->pll6_cfg);
- while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_LOCK))
writel(CCM_PLL6_DEFAULT, &pllccm->pll6_cfg);
while (!(readl(&pllccm->pll6_cfg) & CCM_PLL6_LOCK)) ;
clrsetbits_le32(&ccm->cpu_axi_cfg, CCM_CPU_AXI_APB_MASK | CCM_CPU_AXI_AXI_MASK, CCM_CPU_AXI_DEFAULT_FACTORS);
writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+#ifdef CCM_AHB3_DEFAULT writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg); +#endif writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
+#ifndef CONFIG_MACH_SUN50I_R329 /* * The mux and factor are set, but the clock will be enabled in * DRAM initialization code. */ writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg); +#endif } #endif
@@ -60,8 +71,20 @@ void clock_set_pll1(unsigned int clk) { struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; +#ifdef CONFIG_MACH_SUN50I_R329
- struct sunxi_prcm_reg *const prcm =
(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
- struct sunxi_prcm_reg *const pllccm = prcm;
+#else
- struct sunxi_ccm_reg *const pllccm = ccm;
+#endif u32 val;
+#ifdef CONFIG_MACH_SUN50I_R329
- /* Fix undervoltage reset threshold */
- clrsetbits_le32(0x070901f4, 0xfff, 0xc0);
+#endif
- /* Do not support clocks < 288MHz as they need factor P */ if (clk < 288000000) clk = 288000000;
@@ -73,11 +96,11 @@ void clock_set_pll1(unsigned int clk)
/* clk = 24*n/p, p is ignored if clock is >288MHz */ writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 | -#ifdef CONFIG_MACH_SUN50I_H616 +#ifndef CONFIG_MACH_SUN50I_H6 CCM_PLL1_OUT_EN | #endif
CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
- while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
CCM_PLL1_CTRL_N(clk / 24000000), &pllccm->pll1_cfg);
while (!(readl(&pllccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
/* Switch CPU to PLL1 */ val = readl(&ccm->cpu_axi_cfg);
@@ -87,6 +110,7 @@ void clock_set_pll1(unsigned int clk) } #endif
+#ifndef CONFIG_MACH_SUN50I_R329
The negative condition here will make it messier to add more branches in the future, so I suggest flipping the conditional block.
unsigned int clock_get_pll6(void) { struct sunxi_ccm_reg *const ccm = @@ -102,6 +126,21 @@ unsigned int clock_get_pll6(void) /* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */ return 24000000 / m * n / div1 / div2; } +#else +unsigned int clock_get_pll6(void) +{
- struct sunxi_prcm_reg *const prcm =
(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
- uint32_t rval = readl(&prcm->pll6_cfg);
- int m = ((rval & CCM_PLL6_CTRL_M_MASK) >> CCM_PLL6_CTRL_M_SHIFT) + 1;
- int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
- int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
- /* The register defines PLL6-2X, not plain PLL6 */
- return 24000000 / m * n / div1 / 2;
+} +#endif
int clock_twi_onoff(int port, int state) {