[U-Boot] [PATCH] clk: clk_stm32f: Use PLLSAIP as USB 48MHz clock

Patrice Chotard patrice.chotard at st.com
Wed Apr 11 15:07:45 UTC 2018


On all STM32F4 and F7 SoCs  family (except STM32F429), PLLSAI
output P can be used as 48MHz clock source for USB and SDMMC.

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
Tested By: Bruno Herrera <bruherrera at gmail.com>

---

 drivers/clk/clk_stm32f.c | 36 +++++++++++++++++++++++++-----------
 drivers/misc/stm32_rcc.c | 12 +++++++++---
 include/stm32_rcc.h      |  3 ++-
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c
index d8eab1a88d7c..b5773181e8fb 100644
--- a/drivers/clk/clk_stm32f.c
+++ b/drivers/clk/clk_stm32f.c
@@ -134,6 +134,7 @@ struct stm32_clk {
 	struct stm32_pwr_regs *pwr_regs;
 	struct stm32_clk_info info;
 	unsigned long hse_rate;
+	bool pllsaip;
 };
 
 #ifdef CONFIG_VIDEO_STM32
@@ -180,8 +181,12 @@ static int configure_clocks(struct udevice *dev)
 
 	/* configure SDMMC clock */
 	if (priv->info.v2) { /*stm32f7 case */
-		/* select PLLQ as 48MHz clock source */
-		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
+		if (priv->pllsaip)
+			/* select PLLSAIP as 48MHz clock source */
+			setbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
+		else
+			/* select PLLQ as 48MHz clock source */
+			clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
 
 		/* select 48MHz as SDMMC1 clock source */
 		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
@@ -189,17 +194,23 @@ static int configure_clocks(struct udevice *dev)
 		/* select 48MHz as SDMMC2 clock source */
 		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
 	} else  { /* stm32f4 case */
-		/* select PLLQ as 48MHz clock source */
-		clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
+		if (priv->pllsaip)
+			/* select PLLSAIP as 48MHz clock source */
+			setbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
+		else
+			/* select PLLQ as 48MHz clock source */
+			clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
 
 		/* select 48MHz as SDMMC1 clock source */
 		clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
 	}
 
-#ifdef CONFIG_VIDEO_STM32
 	/*
-	 * Configure the SAI PLL to generate LTDC pixel clock
+	 * Configure the SAI PLL to generate LTDC pixel clock and
+	 * 48 Mhz for SDMMC and USB
 	 */
+	clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIP_MASK,
+			RCC_PLLSAICFGR_PLLSAIP_4);
 	clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
 			RCC_PLLSAICFGR_PLLSAIR_3);
 	clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK,
@@ -207,18 +218,16 @@ static int configure_clocks(struct udevice *dev)
 
 	clrsetbits_le32(&regs->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
 			RCC_DCKCFGR_PLLSAIDIVR_2 << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
-#endif
+
 	/* Enable the main PLL */
 	setbits_le32(&regs->cr, RCC_CR_PLLON);
 	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
 		;
 
-#ifdef CONFIG_VIDEO_STM32
-/* Enable the SAI PLL */
+	/* Enable the SAI PLL */
 	setbits_le32(&regs->cr, RCC_CR_PLLSAION);
 	while (!(readl(&regs->cr) & RCC_CR_PLLSAIRDY))
 		;
-#endif
 	setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
 
 	if (priv->info.has_overdrive) {
@@ -618,12 +627,17 @@ static int stm32_clk_probe(struct udevice *dev)
 		return -EINVAL;
 
 	priv->base = (struct stm32_rcc_regs *)addr;
+	priv->pllsaip = true;
 
 	switch (dev_get_driver_data(dev)) {
-	case STM32F4:
+	case STM32F42X:
+		priv->pllsaip = false;
+		/* fallback into STM32F469 case */
+	case STM32F469:
 		memcpy(&priv->info, &stm32f4_clk_info,
 		       sizeof(struct stm32_clk_info));
 		break;
+
 	case STM32F7:
 		memcpy(&priv->info, &stm32f7_clk_info,
 		       sizeof(struct stm32_clk_info));
diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c
index 87d9928362be..454a9cccfcc2 100644
--- a/drivers/misc/stm32_rcc.c
+++ b/drivers/misc/stm32_rcc.c
@@ -12,9 +12,14 @@
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 
-struct stm32_rcc_clk stm32_rcc_clk_f4 = {
+struct stm32_rcc_clk stm32_rcc_clk_f42x = {
 	.drv_name = "stm32fx_rcc_clock",
-	.soc = STM32F4,
+	.soc = STM32F42X,
+};
+
+struct stm32_rcc_clk stm32_rcc_clk_f469 = {
+	.drv_name = "stm32fx_rcc_clock",
+	.soc = STM32F469,
 };
 
 struct stm32_rcc_clk stm32_rcc_clk_f7 = {
@@ -62,7 +67,8 @@ static const struct misc_ops stm32_rcc_ops = {
 };
 
 static const struct udevice_id stm32_rcc_ids[] = {
-	{.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f4 },
+	{.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f42x },
+	{.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_clk_f469 },
 	{.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 },
 	{.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 },
 	{ }
diff --git a/include/stm32_rcc.h b/include/stm32_rcc.h
index 484bc305f9c0..5cfbec0f15a1 100644
--- a/include/stm32_rcc.h
+++ b/include/stm32_rcc.h
@@ -41,7 +41,8 @@ struct stm32_clk_info {
 };
 
 enum soc_family {
-	STM32F4,
+	STM32F42X,
+	STM32F469,
 	STM32F7,
 };
 
-- 
1.9.1



More information about the U-Boot mailing list