From 8b41464547330a39cc7e0ef87a5dd8f34db324e1 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Wed, 11 Apr 2018 17:07:45 +0200 Subject: [PATCH] clk: clk_stm32f: Use PLLSAIP as USB 48MHz clock 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 Tested By: Bruno Herrera --- 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 6c1e2575ff..cbcfe3a89d 100644 --- a/drivers/clk/clk_stm32f.c +++ b/drivers/clk/clk_stm32f.c @@ -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(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL); + if (priv->pllsaip) + /* select PLLSAIP as 48MHz clock source */ + setbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL); + else + /* select PLLQ as 48MHz clock source */ + clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL); /* select 48MHz as SDMMC1 clock source */ clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL); @@ -188,17 +193,23 @@ static int configure_clocks(struct udevice *dev) /* select 48MHz as SDMMC2 clock source */ clrbits_le32(®s->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL); } else { /* stm32f4 case */ - /* select PLLQ as 48MHz clock source */ - clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL); + if (priv->pllsaip) + /* select PLLSAIP as 48MHz clock source */ + setbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL); + else + /* select PLLQ as 48MHz clock source */ + clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL); /* select 48MHz as SDMMC1 clock source */ clrbits_le32(®s->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(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIP_MASK, + RCC_PLLSAICFGR_PLLSAIP_4); clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK, RCC_PLLSAICFGR_PLLSAIR_3); clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK, @@ -206,18 +217,16 @@ static int configure_clocks(struct udevice *dev) clrsetbits_le32(®s->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK, RCC_DCKCFGR_PLLSAIDIVR_2 << RCC_DCKCFGR_PLLSAIDIVR_SHIFT); -#endif + /* Enable the main PLL */ setbits_le32(®s->cr, RCC_CR_PLLON); while (!(readl(®s->cr) & RCC_CR_PLLRDY)) ; -#ifdef CONFIG_VIDEO_STM32 -/* Enable the SAI PLL */ + /* Enable the SAI PLL */ setbits_le32(®s->cr, RCC_CR_PLLSAION); while (!(readl(®s->cr) & RCC_CR_PLLSAIRDY)) ; -#endif setbits_le32(®s->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)); diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c index b436900d7c..dee82c0b7b 100644 --- a/drivers/misc/stm32_rcc.c +++ b/drivers/misc/stm32_rcc.c @@ -11,9 +11,14 @@ #include #include -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 }, { } diff --git a/include/stm32_rcc.h b/include/stm32_rcc.h index 748c2ebd0c..71da3c1a87 100644 --- a/include/stm32_rcc.h +++ b/include/stm32_rcc.h @@ -40,7 +40,8 @@ struct stm32_clk_info { }; enum soc_family { - STM32F4, + STM32F42X, + STM32F469, STM32F7, }; -- 2.39.2