|
@@ -63,6 +63,7 @@
|
|
|
#define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26)
|
|
|
#define RCC_PLLSAICFGR_PLLSAIR_2 BIT(29)
|
|
|
|
|
|
+#define RCC_DCKCFGRX_TIMPRE BIT(24)
|
|
|
#define RCC_DCKCFGRX_CK48MSEL BIT(27)
|
|
|
#define RCC_DCKCFGRX_SDMMC1SEL BIT(28)
|
|
|
#define RCC_DCKCFGR2_SDMMC2SEL BIT(29)
|
|
@@ -260,21 +261,88 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv,
|
|
|
return sysclk / pllq;
|
|
|
}
|
|
|
|
|
|
-static unsigned long stm32_clk_get_rate(struct clk *clk)
|
|
|
+static bool stm32_get_timpre(struct stm32_clk *priv)
|
|
|
{
|
|
|
- struct stm32_clk *priv = dev_get_priv(clk->dev);
|
|
|
struct stm32_rcc_regs *regs = priv->base;
|
|
|
- u32 sysclk = 0;
|
|
|
- u32 shift = 0;
|
|
|
- u16 pllm, plln, pllp;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ if (priv->info.v2) /*stm32f7 case */
|
|
|
+ val = readl(®s->dckcfgr2);
|
|
|
+ else
|
|
|
+ val = readl(®s->dckcfgr);
|
|
|
+ /* get timer prescaler */
|
|
|
+ return !!(val & RCC_DCKCFGRX_TIMPRE);
|
|
|
+}
|
|
|
+
|
|
|
+static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk)
|
|
|
+{
|
|
|
+ u8 shift;
|
|
|
/* Prescaler table lookups for clock computation */
|
|
|
u8 ahb_psc_table[16] = {
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
|
|
|
};
|
|
|
+
|
|
|
+ shift = ahb_psc_table[(
|
|
|
+ (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK)
|
|
|
+ >> RCC_CFGR_HPRE_SHIFT)];
|
|
|
+
|
|
|
+ return sysclk >> shift;
|
|
|
+};
|
|
|
+
|
|
|
+static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb)
|
|
|
+{
|
|
|
+ /* Prescaler table lookups for clock computation */
|
|
|
u8 apb_psc_table[8] = {
|
|
|
0, 0, 0, 0, 1, 2, 3, 4
|
|
|
};
|
|
|
|
|
|
+ if (apb == APB1)
|
|
|
+ return apb_psc_table[(
|
|
|
+ (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK)
|
|
|
+ >> RCC_CFGR_PPRE1_SHIFT)];
|
|
|
+ else /* APB2 */
|
|
|
+ return apb_psc_table[(
|
|
|
+ (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK)
|
|
|
+ >> RCC_CFGR_PPRE2_SHIFT)];
|
|
|
+};
|
|
|
+
|
|
|
+static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk,
|
|
|
+ enum apb apb)
|
|
|
+{
|
|
|
+ struct stm32_rcc_regs *regs = priv->base;
|
|
|
+ u8 shift = stm32_get_apb_shift(regs, apb);
|
|
|
+
|
|
|
+ if (stm32_get_timpre(priv))
|
|
|
+ /*
|
|
|
+ * if APB prescaler is configured to a
|
|
|
+ * division factor of 1, 2 or 4
|
|
|
+ */
|
|
|
+ switch (shift) {
|
|
|
+ case 0:
|
|
|
+ case 1:
|
|
|
+ case 2:
|
|
|
+ return stm32_get_hclk_rate(regs, sysclk);
|
|
|
+ default:
|
|
|
+ return (sysclk >> shift) * 4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ /*
|
|
|
+ * if APB prescaler is configured to a
|
|
|
+ * division factor of 1
|
|
|
+ */
|
|
|
+ if (shift == 0)
|
|
|
+ return sysclk;
|
|
|
+ else
|
|
|
+ return (sysclk >> shift) * 2;
|
|
|
+};
|
|
|
+
|
|
|
+static ulong stm32_clk_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ struct stm32_clk *priv = dev_get_priv(clk->dev);
|
|
|
+ struct stm32_rcc_regs *regs = priv->base;
|
|
|
+ u32 sysclk = 0;
|
|
|
+ u16 pllm, plln, pllp;
|
|
|
+
|
|
|
if ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) ==
|
|
|
RCC_CFGR_SWS_PLL) {
|
|
|
pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
|
|
@@ -293,16 +361,24 @@ static unsigned long stm32_clk_get_rate(struct clk *clk)
|
|
|
* AHB1, AHB2 and AHB3
|
|
|
*/
|
|
|
case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
|
|
|
- shift = ahb_psc_table[(
|
|
|
- (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK)
|
|
|
- >> RCC_CFGR_HPRE_SHIFT)];
|
|
|
- return sysclk >>= shift;
|
|
|
+ return stm32_get_hclk_rate(regs, sysclk);
|
|
|
/* APB1 CLOCK */
|
|
|
case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
|
|
|
- shift = apb_psc_table[(
|
|
|
- (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK)
|
|
|
- >> RCC_CFGR_PPRE1_SHIFT)];
|
|
|
- return sysclk >>= shift;
|
|
|
+ /* For timer clock, an additionnal prescaler is used*/
|
|
|
+ switch (clk->id) {
|
|
|
+ case STM32F7_APB1_CLOCK(TIM2):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM3):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM4):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM5):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM6):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM7):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM12):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM13):
|
|
|
+ case STM32F7_APB1_CLOCK(TIM14):
|
|
|
+ return stm32_get_timer_rate(priv, sysclk, APB1);
|
|
|
+ }
|
|
|
+ return (sysclk >> stm32_get_apb_shift(regs, APB1));
|
|
|
+
|
|
|
/* APB2 CLOCK */
|
|
|
case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
|
|
|
/*
|
|
@@ -325,12 +401,18 @@ static unsigned long stm32_clk_get_rate(struct clk *clk)
|
|
|
else
|
|
|
return stm32_clk_pll48clk_rate(priv, sysclk);
|
|
|
break;
|
|
|
+
|
|
|
+ /* For timer clock, an additionnal prescaler is used*/
|
|
|
+ case STM32F7_APB2_CLOCK(TIM1):
|
|
|
+ case STM32F7_APB2_CLOCK(TIM8):
|
|
|
+ case STM32F7_APB2_CLOCK(TIM9):
|
|
|
+ case STM32F7_APB2_CLOCK(TIM10):
|
|
|
+ case STM32F7_APB2_CLOCK(TIM11):
|
|
|
+ return stm32_get_timer_rate(priv, sysclk, APB2);
|
|
|
+ break;
|
|
|
}
|
|
|
+ return (sysclk >> stm32_get_apb_shift(regs, APB2));
|
|
|
|
|
|
- shift = apb_psc_table[(
|
|
|
- (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK)
|
|
|
- >> RCC_CFGR_PPRE2_SHIFT)];
|
|
|
- return sysclk >>= shift;
|
|
|
default:
|
|
|
pr_err("clock index %ld out of range\n", clk->id);
|
|
|
return -EINVAL;
|