[U-Boot] [PATCH 4/7] clk: clk_stm32f: Rework SDMMC stm32_clk_get_rate() part

patrice.chotard at st.com patrice.chotard at st.com
Thu Feb 8 16:20:48 UTC 2018


From: Patrice Chotard <patrice.chotard at st.com>

Rework the way SDMMC clock get rate is done in a more
generic way :

_ Add stm32_clk_get_pllsai_rate() which give the PLLSAI
  indicated output rate.

_ Add stm32_clk_get_pllsai_vco_rate() which give the VCO
  internal rate.

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---
 drivers/clk/clk_stm32f.c | 105 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 74 insertions(+), 31 deletions(-)

diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c
index e8f6b47acc17..a687e2acd406 100644
--- a/drivers/clk/clk_stm32f.c
+++ b/drivers/clk/clk_stm32f.c
@@ -57,8 +57,12 @@
 
 #define RCC_PLLSAICFGR_PLLSAIN_MASK	GENMASK(14, 6)
 #define RCC_PLLSAICFGR_PLLSAIP_MASK	GENMASK(17, 16)
+#define RCC_PLLSAICFGR_PLLSAIQ_MASK	GENMASK(27, 24)
+#define RCC_PLLSAICFGR_PLLSAIR_MASK	GENMASK(30, 28)
 #define RCC_PLLSAICFGR_PLLSAIN_SHIFT	6
 #define RCC_PLLSAICFGR_PLLSAIP_SHIFT	16
+#define RCC_PLLSAICFGR_PLLSAIQ_SHIFT	24
+#define RCC_PLLSAICFGR_PLLSAIR_SHIFT	28
 #define RCC_PLLSAICFGR_PLLSAIP_4	BIT(16)
 #define RCC_PLLSAICFGR_PLLSAIQ_4	BIT(26)
 #define RCC_PLLSAICFGR_PLLSAIR_2	BIT(29)
@@ -87,6 +91,12 @@
 #define RCC_APB2ENR_SYSCFGEN		BIT(14)
 #define RCC_APB2ENR_SAI1EN		BIT(22)
 
+enum pllsai_div {
+	PLLSAIP,
+	PLLSAIQ,
+	PLLSAIR,
+};
+
 static const struct stm32_clk_info stm32f4_clk_info = {
 	/* 180 MHz */
 	.sys_pll_psc = {
@@ -216,32 +226,57 @@ static int configure_clocks(struct udevice *dev)
 	return 0;
 }
 
-static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv,
-					     u32 vco)
+static bool stm32_clk_get_ck48msel(struct stm32_clk *priv)
 {
 	struct stm32_rcc_regs *regs = priv->base;
-	u16 pllq, pllm, pllsain, pllsaip;
-	bool pllsai;
-
-	pllq = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
-	       >> RCC_PLLCFGR_PLLQ_SHIFT;
 
 	if (priv->info.v2) /*stm32f7 case */
-		pllsai = readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
+		return readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
 	else
-		pllsai = readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
 
-	if (pllsai) {
-		/* PLL48CLK is selected from PLLSAI, get PLLSAI value */
-		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
-		pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
-			>> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
-		pllsaip = ((((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIP_MASK)
-			>> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
-		return ((priv->hse_rate / pllm) * pllsain) / pllsaip;
+		return readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
+}
+
+static unsigned long stm32_clk_get_pllsai_vco_rate(struct stm32_clk *priv)
+{
+	struct stm32_rcc_regs *regs = priv->base;
+	u16 pllm, pllsain;
+
+	pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
+	pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
+		  >> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
+
+	return ((priv->hse_rate / pllm) * pllsain);
+}
+
+static unsigned long stm32_clk_get_pllsai_rate(struct stm32_clk *priv,
+					       enum pllsai_div output)
+{
+	struct stm32_rcc_regs *regs = priv->base;
+	u16 pll_div_output;
+
+	switch (output) {
+	case PLLSAIP:
+		pll_div_output = ((((readl(&regs->pllsaicfgr)
+				  & RCC_PLLSAICFGR_PLLSAIP_MASK)
+				  >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
+		break;
+	case PLLSAIQ:
+		pll_div_output = (readl(&regs->pllsaicfgr)
+				  & RCC_PLLSAICFGR_PLLSAIQ_MASK)
+				  >> RCC_PLLSAICFGR_PLLSAIQ_SHIFT;
+		break;
+	case PLLSAIR:
+		pll_div_output = (readl(&regs->pllsaicfgr)
+				  & RCC_PLLSAICFGR_PLLSAIR_MASK)
+				  >> RCC_PLLSAICFGR_PLLSAIR_SHIFT;
+		break;
+	default:
+		pr_err("incorrect PLLSAI output %d\n", output);
+		return -EINVAL;
 	}
-	/* PLL48CLK is selected from PLLQ */
-	return vco / pllq;
+
+	return (stm32_clk_get_pllsai_vco_rate(priv) / pll_div_output);
 }
 
 static bool stm32_get_timpre(struct stm32_clk *priv)
@@ -325,7 +360,8 @@ static ulong stm32_clk_get_rate(struct clk *clk)
 	struct stm32_rcc_regs *regs = priv->base;
 	u32 sysclk = 0;
 	u32 vco;
-	u16 pllm, plln, pllp;
+	u32 sdmmcxsel_bit;
+	u16 pllm, plln, pllp, pllq;
 
 	if ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
 			RCC_CFGR_SWS_PLL) {
@@ -334,6 +370,8 @@ static ulong stm32_clk_get_rate(struct clk *clk)
 			>> RCC_PLLCFGR_PLLN_SHIFT);
 		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
 			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
+		pllq = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
+			>> RCC_PLLCFGR_PLLQ_SHIFT);
 		vco = (priv->hse_rate / pllm) * plln;
 		sysclk = vco / pllp;
 	} else {
@@ -366,25 +404,30 @@ static ulong stm32_clk_get_rate(struct clk *clk)
 
 	/* APB2 CLOCK */
 	case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
+		switch (clk->id) {
 		/*
 		 * particular case for SDMMC1 and SDMMC2 :
 		 * 48Mhz source clock can be from main PLL or from
-		 * SAI PLL
+		 * PLLSAIP
 		 */
-		switch (clk->id) {
 		case STM32F7_APB2_CLOCK(SDMMC1):
-			if (readl(&regs->dckcfgr2) & RCC_DCKCFGRX_SDMMC1SEL)
-				/* System clock is selected as SDMMC1 clock */
-				return sysclk;
-			else
-				return stm32_clk_pll48clk_rate(priv, vco);
-			break;
 		case STM32F7_APB2_CLOCK(SDMMC2):
-			if (readl(&regs->dckcfgr2) & RCC_DCKCFGR2_SDMMC2SEL)
-				/* System clock is selected as SDMMC2 clock */
+			if (clk->id == STM32F7_APB2_CLOCK(SDMMC1))
+				sdmmcxsel_bit = RCC_DCKCFGRX_SDMMC1SEL;
+			else
+				sdmmcxsel_bit = RCC_DCKCFGR2_SDMMC2SEL;
+
+			if (readl(&regs->dckcfgr2) & sdmmcxsel_bit)
+				/* System clock is selected as SDMMC1 clock */
 				return sysclk;
+			/*
+			 * 48 MHz can be generated by either PLLSAIP
+			 * or by PLLQ depending of CK48MSEL bit of RCC_DCKCFGR
+			 */
+			if (stm32_clk_get_ck48msel(priv))
+				return stm32_clk_get_pllsai_rate(priv, PLLSAIP);
 			else
-				return stm32_clk_pll48clk_rate(priv, vco);
+				return (vco / pllq);
 			break;
 
 		/* For timer clock, an additionnal prescaler is used*/
-- 
1.9.1



More information about the U-Boot mailing list