]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
clk: clk_stm32f: Use PLLSAIP as USB 48MHz clock
authorPatrice Chotard <patrice.chotard@st.com>
Wed, 11 Apr 2018 15:07:45 +0000 (17:07 +0200)
committerTom Rini <trini@konsulko.com>
Tue, 8 May 2018 13:07:34 +0000 (09:07 -0400)
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@st.com>
Tested By: Bruno Herrera <bruherrera@gmail.com>

drivers/clk/clk_stm32f.c
drivers/misc/stm32_rcc.c
include/stm32_rcc.h

index 6c1e2575ff84686321cb21601e41b2346eeee109..cbcfe3a89dd780ae4bff1defde0af0d2de9f9aa4 100644 (file)
@@ -133,6 +133,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
@@ -179,8 +180,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);
@@ -188,17 +193,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,
@@ -206,18 +217,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) {
@@ -617,12 +626,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));
index b436900d7cba6adab3d8c8a305213f6e01f1946b..dee82c0b7b1e1edf17f238a102dd52934ede49f6 100644 (file)
 #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 = {
@@ -61,7 +66,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 },
        { }
index 748c2ebd0c9c4044328a23224600480c89d4e453..71da3c1a87143960dbef3151b26b04db09695820 100644 (file)
@@ -40,7 +40,8 @@ struct stm32_clk_info {
 };
 
 enum soc_family {
-       STM32F4,
+       STM32F42X,
+       STM32F469,
        STM32F7,
 };