[U-Boot] [PATCH 07/15] imx: imx8m: clock refactor dram pll part
Troy Kisky
troy.kisky at boundarydevices.com
Fri Nov 9 18:26:01 UTC 2018
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 at 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)
>
More information about the U-Boot
mailing list