[PATCH] clk: stm32f4: don't assume 48MHz clock is derived from primary PLL

Andrea Merello andrea.merello at gmail.com
Thu Sep 8 00:01:03 PDT 2016


This driver just look at the PLLs configurations set by the
bootloader, but it assumes the 48MHz clock is derived from the primary
PLL; however using PLLSAI is another option for generating the 48MHz
clock.

This patch make the driver to check for this, and eventually adjust the
clock tree accordingly

Signed-off-by: Andrea Merello <andrea.merello at gmail.com>
Cc: Michael Turquette <mturquette at baylibre.com>
Cc: Stephen Boyd <sboyd at codeaurora.org>
Cc: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
Cc: Alexandre Torgue <alexandre.torgue at st.com>
Cc: Bruno Herrera <bruherrera at gmail.com>
---
 drivers/clk/clk-stm32f4.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 02d6810..7f1ba8f 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+#define STM32F4_RCC_CR			0x00
 #define STM32F4_RCC_PLLCFGR		0x04
 #define STM32F4_RCC_CFGR		0x08
 #define STM32F4_RCC_AHB1ENR		0x30
@@ -31,6 +32,8 @@
 #define STM32F4_RCC_AHB3ENR		0x38
 #define STM32F4_RCC_APB1ENR		0x40
 #define STM32F4_RCC_APB2ENR		0x44
+#define STM32F4_RCC_PLLSAICFGR		0x88
+#define STM32F4_RCC_DCKCFGR		0x8C
 
 struct stm32f4_gate_data {
 	u8	offset;
@@ -238,16 +241,35 @@ static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
 static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
 {
 	unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
-
+	unsigned long pllsaicfgr = readl(base + STM32F4_RCC_PLLSAICFGR);
+	unsigned long dckcfgr = readl(base + STM32F4_RCC_DCKCFGR);
+	unsigned long rcccr = readl(base + STM32F4_RCC_CR);
+	bool saien = rcccr & BIT(28);
 	unsigned long pllm   = pllcfgr & 0x3f;
 	unsigned long plln   = (pllcfgr >> 6) & 0x1ff;
 	unsigned long pllp   = BIT(((pllcfgr >> 16) & 3) + 1);
 	const char   *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
 	unsigned long pllq   = (pllcfgr >> 24) & 0xf;
+	bool src48_sai = dckcfgr & BIT(27);
+	unsigned long pllsain = (pllsaicfgr >> 6) & 0x1ff;
+	unsigned long pllsaip = BIT(((pllsaicfgr >> 16) & 3) + 1);
 
 	clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
 	clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
-	clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
+
+	if (src48_sai && !saien) {
+		pr_err("48MHz derived from SAI PLL, but SAI PLL disabled (blame the bootloader)\n");
+		return;
+	}
+
+	if (saien)
+		clk_register_fixed_factor(NULL, "sai",
+					pllsrc, 0, pllsain, pllm);
+
+	if (src48_sai)
+		clk_register_fixed_factor(NULL, "pll48", "sai", 0, 1, pllsaip);
+	else
+		clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
 }
 
 /*
-- 
2.7.4




More information about the linux-arm-kernel mailing list