Message ID | 20181109092408.28322-7-peng.fan@nxp.com |
---|---|
State | Superseded |
Delegated to: | Stefano Babic |
Headers | show |
Series | [U-Boot,01/15] Introduce CONFIG_FIT_EXTERNAL_OFFSET | expand |
On 11/9/2018 1:16 AM, Peng Fan wrote: > Refactor dram_pll_init to accept args to configure different pll freq. > Introduce dram_enable_bypass and dram_disable_bypass > > Signed-off-by: Peng Fan <peng.fan@nxp.com> > --- > arch/arm/include/asm/arch-imx8m/clock.h | 44 +++++++++++ > arch/arm/mach-imx/imx8m/clock.c | 134 ++++++++++++++++++++++++++------ > 2 files changed, 154 insertions(+), 24 deletions(-) > > diff --git a/arch/arm/include/asm/arch-imx8m/clock.h b/arch/arm/include/asm/arch-imx8m/clock.h > index 45cfea3018..8f7768a264 100644 > --- a/arch/arm/include/asm/arch-imx8m/clock.h > +++ b/arch/arm/include/asm/arch-imx8m/clock.h > @@ -631,6 +631,50 @@ enum frac_pll_out_val { > FRAC_PLL_OUT_1600M, > }; > > +enum sscg_pll_out_val { > + SSCG_PLL_OUT_400M, > + SSCG_PLL_OUT_600M, > + SSCG_PLL_OUT_800M, > +}; > + Can we just pass frequencies we want instead of this enum > +enum dram_pll_out_val { > + DRAM_PLL_OUT_100M, > + DRAM_PLL_OUT_167M, > + DRAM_PLL_OUT_266M, > + DRAM_PLL_OUT_667M, > + DRAM_PLL_OUT_400M, > + DRAM_PLL_OUT_600M, > + DRAM_PLL_OUT_700M, > + DRAM_PLL_OUT_750M, > + DRAM_PLL_OUT_800M, > +}; Ditto > + > +enum dram_bypassclk_val { > + DRAM_BYPASSCLK_100M, > + DRAM_BYPASSCLK_250M, > + DRAM_BYPASSCLK_400M, > +}; > + Ditto > +#define DRAM_BYPASS_ROOT_CONFIG(_rate, _m, _p, _s, _k) \ > + { \ > + .clk = (_rate), \ > + .alt_root_sel = (_m), \ > + .alt_pre_div = (_p), \ > + .apb_root_sel = (_s), \ > + .apb_pre_div = (_k), \ > + } > + > +struct dram_bypass_clk_setting { > + enum dram_bypassclk_val clk; > + int alt_root_sel; > + enum root_pre_div alt_pre_div; > + int apb_root_sel; > + enum root_pre_div apb_pre_div; > +}; > + > +void dram_pll_init(enum dram_pll_out_val pll_val); > +void dram_enable_bypass(enum dram_bypassclk_val clk_val); > +void dram_disable_bypass(void); > u32 imx_get_fecclk(void); > u32 imx_get_uartclk(void); > int clock_init(void); > diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock.c > index f2cb4e1030..5368427c9f 100644 > --- a/arch/arm/mach-imx/imx8m/clock.c > +++ b/arch/arm/mach-imx/imx8m/clock.c > @@ -525,41 +525,127 @@ u32 imx_get_fecclk(void) > return get_root_clk(ENET_AXI_CLK_ROOT); > } > > -#ifdef CONFIG_SPL_BUILD > -void dram_pll_init(void) > +static struct dram_bypass_clk_setting imx8mq_dram_bypass_tbl[] = { > + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_100M, 2, CLK_ROOT_PRE_DIV1, 2, > + CLK_ROOT_PRE_DIV2), > + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_250M, 3, CLK_ROOT_PRE_DIV2, 2, > + CLK_ROOT_PRE_DIV2), > + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_400M, 1, CLK_ROOT_PRE_DIV2, 3, > + CLK_ROOT_PRE_DIV2), > +}; > + > +void dram_enable_bypass(enum dram_bypassclk_val clk_val) > { > - struct src *src = (struct src *)SRC_BASE_ADDR; > - void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; > - u32 pwdn_mask = 0, pll_clke = 0, bypass1 = 0, bypass2 = 0; > - u32 val; > - int ret; > + int i; > + struct dram_bypass_clk_setting *config; > > - setbits_le32(GPC_BASE_ADDR + 0xEC, BIT(7)); > - setbits_le32(GPC_BASE_ADDR + 0xF8, BIT(5)); > + for (i = 0; i < ARRAY_SIZE(imx8mq_dram_bypass_tbl); i++) { > + if (clk_val == imx8mq_dram_bypass_tbl[i].clk) > + break; > + } > + > + if (i == ARRAY_SIZE(imx8mq_dram_bypass_tbl)) { > + printf("No matched freq table %u\n", clk_val); > + return; > + } > > - pwdn_mask = SSCG_PLL_PD_MASK; > - pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK; > - bypass1 = SSCG_PLL_BYPASS1_MASK; > - bypass2 = SSCG_PLL_BYPASS2_MASK; > + config = &imx8mq_dram_bypass_tbl[i]; > > - /* Enable DDR1 and DDR2 domain */ > - writel(SRC_DDR1_ENABLE_MASK, &src->ddr1_rcr); > - writel(SRC_DDR1_ENABLE_MASK, &src->ddr2_rcr); > + clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | > + CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | > + CLK_ROOT_PRE_DIV(config->alt_pre_div)); > + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | > + CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | > + CLK_ROOT_PRE_DIV(config->apb_pre_div)); > + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | > + CLK_ROOT_SOURCE_SEL(1)); > +} > + > +void dram_disable_bypass(void) > +{ > + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | > + CLK_ROOT_SOURCE_SEL(0)); > + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | > + CLK_ROOT_SOURCE_SEL(4) | > + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); > +} > + > +#ifdef CONFIG_SPL_BUILD > +void dram_pll_init(enum dram_pll_out_val pll_val) > +{ > + u32 val; > + void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; > + void __iomem *pll_cfg_reg2 = &ana_pll->dram_pll_cfg2; > + > + /* Bypass */ > + setbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); > + setbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); > + > + switch (pll_val) { > + case DRAM_PLL_OUT_800M: > + val = readl(pll_cfg_reg2); > + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | > + SSCG_PLL_FEEDBACK_DIV_F2_MASK | > + SSCG_PLL_FEEDBACK_DIV_F1_MASK | > + SSCG_PLL_REF_DIVR2_MASK); > + val |= SSCG_PLL_OUTPUT_DIV_VAL(0); > + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); > + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); > + val |= SSCG_PLL_REF_DIVR2_VAL(29); > + writel(val, pll_cfg_reg2); > + break; > + case DRAM_PLL_OUT_600M: > + val = readl(pll_cfg_reg2); > + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | > + SSCG_PLL_FEEDBACK_DIV_F2_MASK | > + SSCG_PLL_FEEDBACK_DIV_F1_MASK | > + SSCG_PLL_REF_DIVR2_MASK); > + val |= SSCG_PLL_OUTPUT_DIV_VAL(1); > + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17); > + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); > + val |= SSCG_PLL_REF_DIVR2_VAL(29); > + writel(val, pll_cfg_reg2); > + break; > + case DRAM_PLL_OUT_400M: > + val = readl(pll_cfg_reg2); > + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | > + SSCG_PLL_FEEDBACK_DIV_F2_MASK | > + SSCG_PLL_FEEDBACK_DIV_F1_MASK | > + SSCG_PLL_REF_DIVR2_MASK); > + val |= SSCG_PLL_OUTPUT_DIV_VAL(1); > + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); > + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); > + val |= SSCG_PLL_REF_DIVR2_VAL(29); > + writel(val, pll_cfg_reg2); > + break; > + case DRAM_PLL_OUT_167M: > + val = readl(pll_cfg_reg2); > + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | > + SSCG_PLL_FEEDBACK_DIV_F2_MASK | > + SSCG_PLL_FEEDBACK_DIV_F1_MASK | > + SSCG_PLL_REF_DIVR2_MASK); > + val |= SSCG_PLL_OUTPUT_DIV_VAL(3); > + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8); > + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45); > + val |= SSCG_PLL_REF_DIVR2_VAL(30); > + writel(val, pll_cfg_reg2); > + break; > + default: > + break; > + } > > /* Clear power down bit */ > - clrbits_le32(pll_control_reg, pwdn_mask); > + clrbits_le32(pll_control_reg, SSCG_PLL_PD_MASK); > /* Eanble ARM_PLL/SYS_PLL */ > - setbits_le32(pll_control_reg, pll_clke); > + setbits_le32(pll_control_reg, SSCG_PLL_DRAM_PLL_CLKE_MASK); > > /* Clear bypass */ > - clrbits_le32(pll_control_reg, bypass1); > + clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); > __udelay(100); > - clrbits_le32(pll_control_reg, bypass2); > + clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); > /* Wait lock */ > - ret = readl_poll_timeout(pll_control_reg, val, > - val & SSCG_PLL_LOCK_MASK, 1); > - if (ret) > - printf("%s timeout\n", __func__); > + while (!(readl(pll_control_reg) & SSCG_PLL_LOCK_MASK)) > + ; > } > > int frac_pll_init(u32 pll, enum frac_pll_out_val val) >
diff --git a/arch/arm/include/asm/arch-imx8m/clock.h b/arch/arm/include/asm/arch-imx8m/clock.h index 45cfea3018..8f7768a264 100644 --- a/arch/arm/include/asm/arch-imx8m/clock.h +++ b/arch/arm/include/asm/arch-imx8m/clock.h @@ -631,6 +631,50 @@ enum frac_pll_out_val { FRAC_PLL_OUT_1600M, }; +enum sscg_pll_out_val { + SSCG_PLL_OUT_400M, + SSCG_PLL_OUT_600M, + SSCG_PLL_OUT_800M, +}; + +enum dram_pll_out_val { + DRAM_PLL_OUT_100M, + DRAM_PLL_OUT_167M, + DRAM_PLL_OUT_266M, + DRAM_PLL_OUT_667M, + DRAM_PLL_OUT_400M, + DRAM_PLL_OUT_600M, + DRAM_PLL_OUT_700M, + DRAM_PLL_OUT_750M, + DRAM_PLL_OUT_800M, +}; + +enum dram_bypassclk_val { + DRAM_BYPASSCLK_100M, + DRAM_BYPASSCLK_250M, + DRAM_BYPASSCLK_400M, +}; + +#define DRAM_BYPASS_ROOT_CONFIG(_rate, _m, _p, _s, _k) \ + { \ + .clk = (_rate), \ + .alt_root_sel = (_m), \ + .alt_pre_div = (_p), \ + .apb_root_sel = (_s), \ + .apb_pre_div = (_k), \ + } + +struct dram_bypass_clk_setting { + enum dram_bypassclk_val clk; + int alt_root_sel; + enum root_pre_div alt_pre_div; + int apb_root_sel; + enum root_pre_div apb_pre_div; +}; + +void dram_pll_init(enum dram_pll_out_val pll_val); +void dram_enable_bypass(enum dram_bypassclk_val clk_val); +void dram_disable_bypass(void); u32 imx_get_fecclk(void); u32 imx_get_uartclk(void); int clock_init(void); diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock.c index f2cb4e1030..5368427c9f 100644 --- a/arch/arm/mach-imx/imx8m/clock.c +++ b/arch/arm/mach-imx/imx8m/clock.c @@ -525,41 +525,127 @@ u32 imx_get_fecclk(void) return get_root_clk(ENET_AXI_CLK_ROOT); } -#ifdef CONFIG_SPL_BUILD -void dram_pll_init(void) +static struct dram_bypass_clk_setting imx8mq_dram_bypass_tbl[] = { + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_100M, 2, CLK_ROOT_PRE_DIV1, 2, + CLK_ROOT_PRE_DIV2), + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_250M, 3, CLK_ROOT_PRE_DIV2, 2, + CLK_ROOT_PRE_DIV2), + DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_400M, 1, CLK_ROOT_PRE_DIV2, 3, + CLK_ROOT_PRE_DIV2), +}; + +void dram_enable_bypass(enum dram_bypassclk_val clk_val) { - struct src *src = (struct src *)SRC_BASE_ADDR; - void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; - u32 pwdn_mask = 0, pll_clke = 0, bypass1 = 0, bypass2 = 0; - u32 val; - int ret; + int i; + struct dram_bypass_clk_setting *config; - setbits_le32(GPC_BASE_ADDR + 0xEC, BIT(7)); - setbits_le32(GPC_BASE_ADDR + 0xF8, BIT(5)); + for (i = 0; i < ARRAY_SIZE(imx8mq_dram_bypass_tbl); i++) { + if (clk_val == imx8mq_dram_bypass_tbl[i].clk) + break; + } + + if (i == ARRAY_SIZE(imx8mq_dram_bypass_tbl)) { + printf("No matched freq table %u\n", clk_val); + return; + } - pwdn_mask = SSCG_PLL_PD_MASK; - pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK; - bypass1 = SSCG_PLL_BYPASS1_MASK; - bypass2 = SSCG_PLL_BYPASS2_MASK; + config = &imx8mq_dram_bypass_tbl[i]; - /* Enable DDR1 and DDR2 domain */ - writel(SRC_DDR1_ENABLE_MASK, &src->ddr1_rcr); - writel(SRC_DDR1_ENABLE_MASK, &src->ddr2_rcr); + clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | + CLK_ROOT_PRE_DIV(config->alt_pre_div)); + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | + CLK_ROOT_PRE_DIV(config->apb_pre_div)); + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(1)); +} + +void dram_disable_bypass(void) +{ + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(4) | + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); +} + +#ifdef CONFIG_SPL_BUILD +void dram_pll_init(enum dram_pll_out_val pll_val) +{ + u32 val; + void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; + void __iomem *pll_cfg_reg2 = &ana_pll->dram_pll_cfg2; + + /* Bypass */ + setbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); + setbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); + + switch (pll_val) { + case DRAM_PLL_OUT_800M: + val = readl(pll_cfg_reg2); + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | + SSCG_PLL_FEEDBACK_DIV_F2_MASK | + SSCG_PLL_FEEDBACK_DIV_F1_MASK | + SSCG_PLL_REF_DIVR2_MASK); + val |= SSCG_PLL_OUTPUT_DIV_VAL(0); + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); + val |= SSCG_PLL_REF_DIVR2_VAL(29); + writel(val, pll_cfg_reg2); + break; + case DRAM_PLL_OUT_600M: + val = readl(pll_cfg_reg2); + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | + SSCG_PLL_FEEDBACK_DIV_F2_MASK | + SSCG_PLL_FEEDBACK_DIV_F1_MASK | + SSCG_PLL_REF_DIVR2_MASK); + val |= SSCG_PLL_OUTPUT_DIV_VAL(1); + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17); + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); + val |= SSCG_PLL_REF_DIVR2_VAL(29); + writel(val, pll_cfg_reg2); + break; + case DRAM_PLL_OUT_400M: + val = readl(pll_cfg_reg2); + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | + SSCG_PLL_FEEDBACK_DIV_F2_MASK | + SSCG_PLL_FEEDBACK_DIV_F1_MASK | + SSCG_PLL_REF_DIVR2_MASK); + val |= SSCG_PLL_OUTPUT_DIV_VAL(1); + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); + val |= SSCG_PLL_REF_DIVR2_VAL(29); + writel(val, pll_cfg_reg2); + break; + case DRAM_PLL_OUT_167M: + val = readl(pll_cfg_reg2); + val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | + SSCG_PLL_FEEDBACK_DIV_F2_MASK | + SSCG_PLL_FEEDBACK_DIV_F1_MASK | + SSCG_PLL_REF_DIVR2_MASK); + val |= SSCG_PLL_OUTPUT_DIV_VAL(3); + val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8); + val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45); + val |= SSCG_PLL_REF_DIVR2_VAL(30); + writel(val, pll_cfg_reg2); + break; + default: + break; + } /* Clear power down bit */ - clrbits_le32(pll_control_reg, pwdn_mask); + clrbits_le32(pll_control_reg, SSCG_PLL_PD_MASK); /* Eanble ARM_PLL/SYS_PLL */ - setbits_le32(pll_control_reg, pll_clke); + setbits_le32(pll_control_reg, SSCG_PLL_DRAM_PLL_CLKE_MASK); /* Clear bypass */ - clrbits_le32(pll_control_reg, bypass1); + clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); __udelay(100); - clrbits_le32(pll_control_reg, bypass2); + clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); /* Wait lock */ - ret = readl_poll_timeout(pll_control_reg, val, - val & SSCG_PLL_LOCK_MASK, 1); - if (ret) - printf("%s timeout\n", __func__); + while (!(readl(pll_control_reg) & SSCG_PLL_LOCK_MASK)) + ; } int frac_pll_init(u32 pll, enum frac_pll_out_val val)
Refactor dram_pll_init to accept args to configure different pll freq. Introduce dram_enable_bypass and dram_disable_bypass Signed-off-by: Peng Fan <peng.fan@nxp.com> --- arch/arm/include/asm/arch-imx8m/clock.h | 44 +++++++++++ arch/arm/mach-imx/imx8m/clock.c | 134 ++++++++++++++++++++++++++------ 2 files changed, 154 insertions(+), 24 deletions(-)