[U-Boot,07/15] imx: imx8m: clock refactor dram pll part

Message ID 20181109092408.28322-7-peng.fan@nxp.com
State New
Delegated to: Stefano Babic
Headers show
Series
  • [U-Boot,01/15] Introduce CONFIG_FIT_EXTERNAL_OFFSET
Related show

Commit Message

Peng Fan Nov. 9, 2018, 9:16 a.m.
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(-)

Comments

Troy Kisky Nov. 9, 2018, 6:26 p.m. | #1
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)
>

Patch

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)