clk: clk_stm32f: Rework SDMMC stm32_clk_get_rate() part
authorPatrice Chotard <patrice.chotard@st.com>
Thu, 8 Feb 2018 16:20:48 +0000 (17:20 +0100)
committerTom Rini <trini@konsulko.com>
Wed, 14 Mar 2018 01:45:37 +0000 (21:45 -0400)
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@st.com>
drivers/clk/clk_stm32f.c

index e8f6b47acc172b61faddcb89a46cbbc858413484..a687e2acd406669a818f5c716d0b3f5b348b2464 100644 (file)
 
 #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)
 #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*/