1f264e235SPatrice Chotard /* 2f264e235SPatrice Chotard * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 3f264e235SPatrice Chotard * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. 4f264e235SPatrice Chotard * 5f264e235SPatrice Chotard * SPDX-License-Identifier: GPL-2.0+ 6f264e235SPatrice Chotard */ 7f264e235SPatrice Chotard 8f264e235SPatrice Chotard #include <common.h> 9f264e235SPatrice Chotard #include <clk-uclass.h> 10f264e235SPatrice Chotard #include <dm.h> 11928954feSPatrice Chotard #include <stm32_rcc.h> 12f264e235SPatrice Chotard 13f264e235SPatrice Chotard #include <asm/io.h> 14f264e235SPatrice Chotard #include <asm/arch/stm32.h> 15f264e235SPatrice Chotard #include <asm/arch/stm32_pwr.h> 16f264e235SPatrice Chotard 17f264e235SPatrice Chotard #include <dt-bindings/mfd/stm32f7-rcc.h> 18f264e235SPatrice Chotard 19f264e235SPatrice Chotard #define RCC_CR_HSION BIT(0) 20f264e235SPatrice Chotard #define RCC_CR_HSEON BIT(16) 21f264e235SPatrice Chotard #define RCC_CR_HSERDY BIT(17) 22f264e235SPatrice Chotard #define RCC_CR_HSEBYP BIT(18) 23f264e235SPatrice Chotard #define RCC_CR_CSSON BIT(19) 24f264e235SPatrice Chotard #define RCC_CR_PLLON BIT(24) 25f264e235SPatrice Chotard #define RCC_CR_PLLRDY BIT(25) 264e97e257SPatrice Chotard #define RCC_CR_PLLSAION BIT(28) 274e97e257SPatrice Chotard #define RCC_CR_PLLSAIRDY BIT(29) 28f264e235SPatrice Chotard 29f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0) 30f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6) 31f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16) 32f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24) 33f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLSRC BIT(22) 34f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLM_SHIFT 0 35f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLN_SHIFT 6 36f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLP_SHIFT 16 37f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLQ_SHIFT 24 38f264e235SPatrice Chotard 39f264e235SPatrice Chotard #define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4) 40f264e235SPatrice Chotard #define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10) 41f264e235SPatrice Chotard #define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13) 42f264e235SPatrice Chotard #define RCC_CFGR_SW0 BIT(0) 43f264e235SPatrice Chotard #define RCC_CFGR_SW1 BIT(1) 44f264e235SPatrice Chotard #define RCC_CFGR_SW_MASK GENMASK(1, 0) 45f264e235SPatrice Chotard #define RCC_CFGR_SW_HSI 0 46f264e235SPatrice Chotard #define RCC_CFGR_SW_HSE RCC_CFGR_SW0 47f264e235SPatrice Chotard #define RCC_CFGR_SW_PLL RCC_CFGR_SW1 48f264e235SPatrice Chotard #define RCC_CFGR_SWS0 BIT(2) 49f264e235SPatrice Chotard #define RCC_CFGR_SWS1 BIT(3) 50f264e235SPatrice Chotard #define RCC_CFGR_SWS_MASK GENMASK(3, 2) 51f264e235SPatrice Chotard #define RCC_CFGR_SWS_HSI 0 52f264e235SPatrice Chotard #define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0 53f264e235SPatrice Chotard #define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1 54f264e235SPatrice Chotard #define RCC_CFGR_HPRE_SHIFT 4 55f264e235SPatrice Chotard #define RCC_CFGR_PPRE1_SHIFT 10 56f264e235SPatrice Chotard #define RCC_CFGR_PPRE2_SHIFT 13 57f264e235SPatrice Chotard 58526aa929SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIN_MASK GENMASK(14, 6) 59526aa929SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_MASK GENMASK(17, 16) 604e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIN_SHIFT 6 614e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_SHIFT 16 62990dba64SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_4 BIT(16) 634e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26) 644e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIR_2 BIT(29) 654e97e257SPatrice Chotard 6661803a95SPatrice Chotard #define RCC_DCKCFGRX_TIMPRE BIT(24) 674e97e257SPatrice Chotard #define RCC_DCKCFGRX_CK48MSEL BIT(27) 684e97e257SPatrice Chotard #define RCC_DCKCFGRX_SDMMC1SEL BIT(28) 694e97e257SPatrice Chotard #define RCC_DCKCFGR2_SDMMC2SEL BIT(29) 704e97e257SPatrice Chotard 71c88c6a9eSPatrice Chotard /* 72c88c6a9eSPatrice Chotard * RCC AHB1ENR specific definitions 73c88c6a9eSPatrice Chotard */ 74c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_EN BIT(25) 75c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_TX_EN BIT(26) 76c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_RX_EN BIT(27) 77c88c6a9eSPatrice Chotard 78c88c6a9eSPatrice Chotard /* 79c88c6a9eSPatrice Chotard * RCC APB1ENR specific definitions 80c88c6a9eSPatrice Chotard */ 81c88c6a9eSPatrice Chotard #define RCC_APB1ENR_TIM2EN BIT(0) 82c88c6a9eSPatrice Chotard #define RCC_APB1ENR_PWREN BIT(28) 83c88c6a9eSPatrice Chotard 84c88c6a9eSPatrice Chotard /* 85c88c6a9eSPatrice Chotard * RCC APB2ENR specific definitions 86c88c6a9eSPatrice Chotard */ 87c88c6a9eSPatrice Chotard #define RCC_APB2ENR_SYSCFGEN BIT(14) 8820fe38e7SPatrice Chotard #define RCC_APB2ENR_SAI1EN BIT(22) 89c88c6a9eSPatrice Chotard 90cb97ff9dSPatrice Chotard static const struct stm32_clk_info stm32f4_clk_info = { 91f264e235SPatrice Chotard /* 180 MHz */ 92f264e235SPatrice Chotard .sys_pll_psc = { 93f264e235SPatrice Chotard .pll_n = 360, 94f264e235SPatrice Chotard .pll_p = 2, 95f264e235SPatrice Chotard .pll_q = 8, 96f264e235SPatrice Chotard .ahb_psc = AHB_PSC_1, 97f264e235SPatrice Chotard .apb1_psc = APB_PSC_4, 98f264e235SPatrice Chotard .apb2_psc = APB_PSC_2, 99f264e235SPatrice Chotard }, 100f264e235SPatrice Chotard .has_overdrive = false, 1014e97e257SPatrice Chotard .v2 = false, 102f264e235SPatrice Chotard }; 103f264e235SPatrice Chotard 104cb97ff9dSPatrice Chotard static const struct stm32_clk_info stm32f7_clk_info = { 105f264e235SPatrice Chotard /* 200 MHz */ 106f264e235SPatrice Chotard .sys_pll_psc = { 107f264e235SPatrice Chotard .pll_n = 400, 108f264e235SPatrice Chotard .pll_p = 2, 109f264e235SPatrice Chotard .pll_q = 8, 110f264e235SPatrice Chotard .ahb_psc = AHB_PSC_1, 111f264e235SPatrice Chotard .apb1_psc = APB_PSC_4, 112f264e235SPatrice Chotard .apb2_psc = APB_PSC_2, 113f264e235SPatrice Chotard }, 114f264e235SPatrice Chotard .has_overdrive = true, 1154e97e257SPatrice Chotard .v2 = true, 116f264e235SPatrice Chotard }; 117f264e235SPatrice Chotard 118f264e235SPatrice Chotard struct stm32_clk { 119f264e235SPatrice Chotard struct stm32_rcc_regs *base; 120f264e235SPatrice Chotard struct stm32_pwr_regs *pwr_regs; 121cb97ff9dSPatrice Chotard struct stm32_clk_info info; 122cb97ff9dSPatrice Chotard unsigned long hse_rate; 123f264e235SPatrice Chotard }; 124f264e235SPatrice Chotard 125f264e235SPatrice Chotard static int configure_clocks(struct udevice *dev) 126f264e235SPatrice Chotard { 127f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev); 128f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 129f264e235SPatrice Chotard struct stm32_pwr_regs *pwr = priv->pwr_regs; 130cb97ff9dSPatrice Chotard struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc; 131f264e235SPatrice Chotard 132f264e235SPatrice Chotard /* Reset RCC configuration */ 133f264e235SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSION); 134f264e235SPatrice Chotard writel(0, ®s->cfgr); /* Reset CFGR */ 135f264e235SPatrice Chotard clrbits_le32(®s->cr, (RCC_CR_HSEON | RCC_CR_CSSON 1364e97e257SPatrice Chotard | RCC_CR_PLLON | RCC_CR_PLLSAION)); 137f264e235SPatrice Chotard writel(0x24003010, ®s->pllcfgr); /* Reset value from RM */ 138f264e235SPatrice Chotard clrbits_le32(®s->cr, RCC_CR_HSEBYP); 139f264e235SPatrice Chotard writel(0, ®s->cir); /* Disable all interrupts */ 140f264e235SPatrice Chotard 141f264e235SPatrice Chotard /* Configure for HSE+PLL operation */ 142f264e235SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSEON); 143f264e235SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_HSERDY)) 144f264e235SPatrice Chotard ; 145f264e235SPatrice Chotard 146f264e235SPatrice Chotard setbits_le32(®s->cfgr, (( 147cb97ff9dSPatrice Chotard sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT) 148cb97ff9dSPatrice Chotard | (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT) 149cb97ff9dSPatrice Chotard | (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT))); 150f264e235SPatrice Chotard 151f264e235SPatrice Chotard /* Configure the main PLL */ 152f264e235SPatrice Chotard setbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */ 153f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLM_MASK, 154cb97ff9dSPatrice Chotard sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT); 155f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLN_MASK, 156cb97ff9dSPatrice Chotard sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT); 157f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLP_MASK, 158cb97ff9dSPatrice Chotard ((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT); 159f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLQ_MASK, 160cb97ff9dSPatrice Chotard sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT); 161f264e235SPatrice Chotard 162*651a70e8SPatrice Chotard /* configure SDMMC clock */ 163cb97ff9dSPatrice Chotard if (priv->info.v2) { /*stm32f7 case */ 164*651a70e8SPatrice Chotard /* select PLLQ as 48MHz clock source */ 165*651a70e8SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL); 1664e97e257SPatrice Chotard 1674e97e257SPatrice Chotard /* select 48MHz as SDMMC1 clock source */ 1684e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL); 1694e97e257SPatrice Chotard 1704e97e257SPatrice Chotard /* select 48MHz as SDMMC2 clock source */ 1714e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL); 1724e97e257SPatrice Chotard } else { /* stm32f4 case */ 173*651a70e8SPatrice Chotard /* select PLLQ as 48MHz clock source */ 174*651a70e8SPatrice Chotard clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL); 1754e97e257SPatrice Chotard 1764e97e257SPatrice Chotard /* select 48MHz as SDMMC1 clock source */ 1774e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL); 1784e97e257SPatrice Chotard } 1794e97e257SPatrice Chotard 180*651a70e8SPatrice Chotard /* Enable the main PLL */ 181*651a70e8SPatrice Chotard setbits_le32(®s->cr, RCC_CR_PLLON); 182*651a70e8SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_PLLRDY)) 1834e97e257SPatrice Chotard ; 1844e97e257SPatrice Chotard 185f264e235SPatrice Chotard setbits_le32(®s->apb1enr, RCC_APB1ENR_PWREN); 186f264e235SPatrice Chotard 187cb97ff9dSPatrice Chotard if (priv->info.has_overdrive) { 188f264e235SPatrice Chotard /* 189f264e235SPatrice Chotard * Enable high performance mode 190f264e235SPatrice Chotard * System frequency up to 200 MHz 191f264e235SPatrice Chotard */ 192f264e235SPatrice Chotard setbits_le32(&pwr->cr1, PWR_CR1_ODEN); 193f264e235SPatrice Chotard /* Infinite wait! */ 194f264e235SPatrice Chotard while (!(readl(&pwr->csr1) & PWR_CSR1_ODRDY)) 195f264e235SPatrice Chotard ; 196f264e235SPatrice Chotard /* Enable the Over-drive switch */ 197f264e235SPatrice Chotard setbits_le32(&pwr->cr1, PWR_CR1_ODSWEN); 198f264e235SPatrice Chotard /* Infinite wait! */ 199f264e235SPatrice Chotard while (!(readl(&pwr->csr1) & PWR_CSR1_ODSWRDY)) 200f264e235SPatrice Chotard ; 201f264e235SPatrice Chotard } 202f264e235SPatrice Chotard 203f264e235SPatrice Chotard stm32_flash_latency_cfg(5); 204f264e235SPatrice Chotard clrbits_le32(®s->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1)); 205f264e235SPatrice Chotard setbits_le32(®s->cfgr, RCC_CFGR_SW_PLL); 206f264e235SPatrice Chotard 207f264e235SPatrice Chotard while ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) != 208f264e235SPatrice Chotard RCC_CFGR_SWS_PLL) 209f264e235SPatrice Chotard ; 210f264e235SPatrice Chotard 21120fe38e7SPatrice Chotard #ifdef CONFIG_ETH_DESIGNWARE 21220fe38e7SPatrice Chotard /* gate the SYSCFG clock, needed to set RMII ethernet interface */ 21320fe38e7SPatrice Chotard setbits_le32(®s->apb2enr, RCC_APB2ENR_SYSCFGEN); 21420fe38e7SPatrice Chotard #endif 21520fe38e7SPatrice Chotard 216f264e235SPatrice Chotard return 0; 217f264e235SPatrice Chotard } 218f264e235SPatrice Chotard 2194e97e257SPatrice Chotard static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv, 220aa230be4SPatrice Chotard u32 vco) 2214e97e257SPatrice Chotard { 2224e97e257SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 2234e97e257SPatrice Chotard u16 pllq, pllm, pllsain, pllsaip; 2244e97e257SPatrice Chotard bool pllsai; 2254e97e257SPatrice Chotard 2264e97e257SPatrice Chotard pllq = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK) 2274e97e257SPatrice Chotard >> RCC_PLLCFGR_PLLQ_SHIFT; 2284e97e257SPatrice Chotard 229cb97ff9dSPatrice Chotard if (priv->info.v2) /*stm32f7 case */ 2304e97e257SPatrice Chotard pllsai = readl(®s->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL; 2314e97e257SPatrice Chotard else 2324e97e257SPatrice Chotard pllsai = readl(®s->dckcfgr) & RCC_DCKCFGRX_CK48MSEL; 2334e97e257SPatrice Chotard 2344e97e257SPatrice Chotard if (pllsai) { 2354e97e257SPatrice Chotard /* PLL48CLK is selected from PLLSAI, get PLLSAI value */ 2364e97e257SPatrice Chotard pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); 237526aa929SPatrice Chotard pllsain = ((readl(®s->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK) 2384e97e257SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIN_SHIFT); 239526aa929SPatrice Chotard pllsaip = ((((readl(®s->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIP_MASK) 2404e97e257SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1); 241cb97ff9dSPatrice Chotard return ((priv->hse_rate / pllm) * pllsain) / pllsaip; 2424e97e257SPatrice Chotard } 2434e97e257SPatrice Chotard /* PLL48CLK is selected from PLLQ */ 244aa230be4SPatrice Chotard return vco / pllq; 2454e97e257SPatrice Chotard } 2464e97e257SPatrice Chotard 24761803a95SPatrice Chotard static bool stm32_get_timpre(struct stm32_clk *priv) 248f264e235SPatrice Chotard { 249f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 25061803a95SPatrice Chotard u32 val; 25161803a95SPatrice Chotard 25261803a95SPatrice Chotard if (priv->info.v2) /*stm32f7 case */ 25361803a95SPatrice Chotard val = readl(®s->dckcfgr2); 25461803a95SPatrice Chotard else 25561803a95SPatrice Chotard val = readl(®s->dckcfgr); 25661803a95SPatrice Chotard /* get timer prescaler */ 25761803a95SPatrice Chotard return !!(val & RCC_DCKCFGRX_TIMPRE); 25861803a95SPatrice Chotard } 25961803a95SPatrice Chotard 26061803a95SPatrice Chotard static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk) 26161803a95SPatrice Chotard { 26261803a95SPatrice Chotard u8 shift; 263f264e235SPatrice Chotard /* Prescaler table lookups for clock computation */ 264f264e235SPatrice Chotard u8 ahb_psc_table[16] = { 265f264e235SPatrice Chotard 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 266f264e235SPatrice Chotard }; 26761803a95SPatrice Chotard 26861803a95SPatrice Chotard shift = ahb_psc_table[( 26961803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK) 27061803a95SPatrice Chotard >> RCC_CFGR_HPRE_SHIFT)]; 27161803a95SPatrice Chotard 27261803a95SPatrice Chotard return sysclk >> shift; 27361803a95SPatrice Chotard }; 27461803a95SPatrice Chotard 27561803a95SPatrice Chotard static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb) 27661803a95SPatrice Chotard { 27761803a95SPatrice Chotard /* Prescaler table lookups for clock computation */ 278f264e235SPatrice Chotard u8 apb_psc_table[8] = { 279f264e235SPatrice Chotard 0, 0, 0, 0, 1, 2, 3, 4 280f264e235SPatrice Chotard }; 281f264e235SPatrice Chotard 28261803a95SPatrice Chotard if (apb == APB1) 28361803a95SPatrice Chotard return apb_psc_table[( 28461803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK) 28561803a95SPatrice Chotard >> RCC_CFGR_PPRE1_SHIFT)]; 28661803a95SPatrice Chotard else /* APB2 */ 28761803a95SPatrice Chotard return apb_psc_table[( 28861803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK) 28961803a95SPatrice Chotard >> RCC_CFGR_PPRE2_SHIFT)]; 29061803a95SPatrice Chotard }; 29161803a95SPatrice Chotard 29261803a95SPatrice Chotard static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk, 29361803a95SPatrice Chotard enum apb apb) 29461803a95SPatrice Chotard { 29561803a95SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 29661803a95SPatrice Chotard u8 shift = stm32_get_apb_shift(regs, apb); 29761803a95SPatrice Chotard 29861803a95SPatrice Chotard if (stm32_get_timpre(priv)) 29961803a95SPatrice Chotard /* 30061803a95SPatrice Chotard * if APB prescaler is configured to a 30161803a95SPatrice Chotard * division factor of 1, 2 or 4 30261803a95SPatrice Chotard */ 30361803a95SPatrice Chotard switch (shift) { 30461803a95SPatrice Chotard case 0: 30561803a95SPatrice Chotard case 1: 30661803a95SPatrice Chotard case 2: 30761803a95SPatrice Chotard return stm32_get_hclk_rate(regs, sysclk); 30861803a95SPatrice Chotard default: 30961803a95SPatrice Chotard return (sysclk >> shift) * 4; 31061803a95SPatrice Chotard } 31161803a95SPatrice Chotard else 31261803a95SPatrice Chotard /* 31361803a95SPatrice Chotard * if APB prescaler is configured to a 31461803a95SPatrice Chotard * division factor of 1 31561803a95SPatrice Chotard */ 31661803a95SPatrice Chotard if (shift == 0) 31761803a95SPatrice Chotard return sysclk; 31861803a95SPatrice Chotard else 31961803a95SPatrice Chotard return (sysclk >> shift) * 2; 32061803a95SPatrice Chotard }; 32161803a95SPatrice Chotard 32261803a95SPatrice Chotard static ulong stm32_clk_get_rate(struct clk *clk) 32361803a95SPatrice Chotard { 32461803a95SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev); 32561803a95SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 32661803a95SPatrice Chotard u32 sysclk = 0; 327aa230be4SPatrice Chotard u32 vco; 32861803a95SPatrice Chotard u16 pllm, plln, pllp; 32961803a95SPatrice Chotard 330f264e235SPatrice Chotard if ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) == 331f264e235SPatrice Chotard RCC_CFGR_SWS_PLL) { 332f264e235SPatrice Chotard pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); 333f264e235SPatrice Chotard plln = ((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLN_MASK) 334f264e235SPatrice Chotard >> RCC_PLLCFGR_PLLN_SHIFT); 335f264e235SPatrice Chotard pllp = ((((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) 336f264e235SPatrice Chotard >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); 337aa230be4SPatrice Chotard vco = (priv->hse_rate / pllm) * plln; 338aa230be4SPatrice Chotard sysclk = vco / pllp; 339f264e235SPatrice Chotard } else { 340f264e235SPatrice Chotard return -EINVAL; 341f264e235SPatrice Chotard } 342f264e235SPatrice Chotard 343f264e235SPatrice Chotard switch (clk->id) { 344f264e235SPatrice Chotard /* 345f264e235SPatrice Chotard * AHB CLOCK: 3 x 32 bits consecutive registers are used : 346f264e235SPatrice Chotard * AHB1, AHB2 and AHB3 347f264e235SPatrice Chotard */ 348f264e235SPatrice Chotard case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI): 34961803a95SPatrice Chotard return stm32_get_hclk_rate(regs, sysclk); 350f264e235SPatrice Chotard /* APB1 CLOCK */ 351f264e235SPatrice Chotard case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8): 35261803a95SPatrice Chotard /* For timer clock, an additionnal prescaler is used*/ 35361803a95SPatrice Chotard switch (clk->id) { 35461803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM2): 35561803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM3): 35661803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM4): 35761803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM5): 35861803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM6): 35961803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM7): 36061803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM12): 36161803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM13): 36261803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM14): 36361803a95SPatrice Chotard return stm32_get_timer_rate(priv, sysclk, APB1); 36461803a95SPatrice Chotard } 36561803a95SPatrice Chotard return (sysclk >> stm32_get_apb_shift(regs, APB1)); 36661803a95SPatrice Chotard 367f264e235SPatrice Chotard /* APB2 CLOCK */ 368f264e235SPatrice Chotard case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC): 3694e97e257SPatrice Chotard /* 3704e97e257SPatrice Chotard * particular case for SDMMC1 and SDMMC2 : 3714e97e257SPatrice Chotard * 48Mhz source clock can be from main PLL or from 3724e97e257SPatrice Chotard * SAI PLL 3734e97e257SPatrice Chotard */ 3744e97e257SPatrice Chotard switch (clk->id) { 3754e97e257SPatrice Chotard case STM32F7_APB2_CLOCK(SDMMC1): 3764e97e257SPatrice Chotard if (readl(®s->dckcfgr2) & RCC_DCKCFGRX_SDMMC1SEL) 3774e97e257SPatrice Chotard /* System clock is selected as SDMMC1 clock */ 3784e97e257SPatrice Chotard return sysclk; 3794e97e257SPatrice Chotard else 380aa230be4SPatrice Chotard return stm32_clk_pll48clk_rate(priv, vco); 3814e97e257SPatrice Chotard break; 3824e97e257SPatrice Chotard case STM32F7_APB2_CLOCK(SDMMC2): 3834e97e257SPatrice Chotard if (readl(®s->dckcfgr2) & RCC_DCKCFGR2_SDMMC2SEL) 3844e97e257SPatrice Chotard /* System clock is selected as SDMMC2 clock */ 3854e97e257SPatrice Chotard return sysclk; 3864e97e257SPatrice Chotard else 387aa230be4SPatrice Chotard return stm32_clk_pll48clk_rate(priv, vco); 3884e97e257SPatrice Chotard break; 3894e97e257SPatrice Chotard 39061803a95SPatrice Chotard /* For timer clock, an additionnal prescaler is used*/ 39161803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM1): 39261803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM8): 39361803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM9): 39461803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM10): 39561803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM11): 39661803a95SPatrice Chotard return stm32_get_timer_rate(priv, sysclk, APB2); 39761803a95SPatrice Chotard break; 39861803a95SPatrice Chotard } 39961803a95SPatrice Chotard return (sysclk >> stm32_get_apb_shift(regs, APB2)); 40061803a95SPatrice Chotard 401f264e235SPatrice Chotard default: 402f264e235SPatrice Chotard pr_err("clock index %ld out of range\n", clk->id); 403f264e235SPatrice Chotard return -EINVAL; 404f264e235SPatrice Chotard } 405f264e235SPatrice Chotard } 406f264e235SPatrice Chotard 40705e23dd4SPatrice Chotard static ulong stm32_set_rate(struct clk *clk, ulong rate) 40805e23dd4SPatrice Chotard { 40905e23dd4SPatrice Chotard return 0; 41005e23dd4SPatrice Chotard } 41105e23dd4SPatrice Chotard 412f264e235SPatrice Chotard static int stm32_clk_enable(struct clk *clk) 413f264e235SPatrice Chotard { 414f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev); 415f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base; 416f264e235SPatrice Chotard u32 offset = clk->id / 32; 417f264e235SPatrice Chotard u32 bit_index = clk->id % 32; 418f264e235SPatrice Chotard 419f264e235SPatrice Chotard debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n", 420f264e235SPatrice Chotard __func__, clk->id, offset, bit_index); 421f264e235SPatrice Chotard setbits_le32(®s->ahb1enr + offset, BIT(bit_index)); 422f264e235SPatrice Chotard 423f264e235SPatrice Chotard return 0; 424f264e235SPatrice Chotard } 425f264e235SPatrice Chotard 426f264e235SPatrice Chotard static int stm32_clk_probe(struct udevice *dev) 427f264e235SPatrice Chotard { 428f264e235SPatrice Chotard struct ofnode_phandle_args args; 429cb97ff9dSPatrice Chotard struct udevice *fixed_clock_dev = NULL; 430cb97ff9dSPatrice Chotard struct clk clk; 431f264e235SPatrice Chotard int err; 432f264e235SPatrice Chotard 433f264e235SPatrice Chotard debug("%s\n", __func__); 434f264e235SPatrice Chotard 435f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev); 436f264e235SPatrice Chotard fdt_addr_t addr; 437f264e235SPatrice Chotard 438f264e235SPatrice Chotard addr = dev_read_addr(dev); 439f264e235SPatrice Chotard if (addr == FDT_ADDR_T_NONE) 440f264e235SPatrice Chotard return -EINVAL; 441f264e235SPatrice Chotard 442f264e235SPatrice Chotard priv->base = (struct stm32_rcc_regs *)addr; 443928954feSPatrice Chotard 444928954feSPatrice Chotard switch (dev_get_driver_data(dev)) { 445928954feSPatrice Chotard case STM32F4: 446cb97ff9dSPatrice Chotard memcpy(&priv->info, &stm32f4_clk_info, 447cb97ff9dSPatrice Chotard sizeof(struct stm32_clk_info)); 448928954feSPatrice Chotard break; 449928954feSPatrice Chotard case STM32F7: 450cb97ff9dSPatrice Chotard memcpy(&priv->info, &stm32f7_clk_info, 451cb97ff9dSPatrice Chotard sizeof(struct stm32_clk_info)); 452928954feSPatrice Chotard break; 453928954feSPatrice Chotard default: 454928954feSPatrice Chotard return -EINVAL; 455928954feSPatrice Chotard } 456f264e235SPatrice Chotard 457cb97ff9dSPatrice Chotard /* retrieve HSE frequency (external oscillator) */ 458cb97ff9dSPatrice Chotard err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse", 459cb97ff9dSPatrice Chotard &fixed_clock_dev); 460cb97ff9dSPatrice Chotard 461cb97ff9dSPatrice Chotard if (err) { 462cb97ff9dSPatrice Chotard pr_err("Can't find fixed clock (%d)", err); 463cb97ff9dSPatrice Chotard return err; 464cb97ff9dSPatrice Chotard } 465cb97ff9dSPatrice Chotard 466cb97ff9dSPatrice Chotard err = clk_request(fixed_clock_dev, &clk); 467cb97ff9dSPatrice Chotard if (err) { 468cb97ff9dSPatrice Chotard pr_err("Can't request %s clk (%d)", fixed_clock_dev->name, 469cb97ff9dSPatrice Chotard err); 470cb97ff9dSPatrice Chotard return err; 471cb97ff9dSPatrice Chotard } 472cb97ff9dSPatrice Chotard 473cb97ff9dSPatrice Chotard /* 474cb97ff9dSPatrice Chotard * set pllm factor accordingly to the external oscillator 475cb97ff9dSPatrice Chotard * frequency (HSE). For STM32F4 and STM32F7, we want VCO 476cb97ff9dSPatrice Chotard * freq at 1MHz 477cb97ff9dSPatrice Chotard * if input PLL frequency is 25Mhz, divide it by 25 478cb97ff9dSPatrice Chotard */ 479cb97ff9dSPatrice Chotard clk.id = 0; 480cb97ff9dSPatrice Chotard priv->hse_rate = clk_get_rate(&clk); 481cb97ff9dSPatrice Chotard 482cb97ff9dSPatrice Chotard if (priv->hse_rate < 1000000) { 483cb97ff9dSPatrice Chotard pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__, 484cb97ff9dSPatrice Chotard priv->hse_rate); 485cb97ff9dSPatrice Chotard return -EINVAL; 486cb97ff9dSPatrice Chotard } 487cb97ff9dSPatrice Chotard 488cb97ff9dSPatrice Chotard priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000; 489cb97ff9dSPatrice Chotard 490cb97ff9dSPatrice Chotard if (priv->info.has_overdrive) { 491f264e235SPatrice Chotard err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0, 492f264e235SPatrice Chotard &args); 493f264e235SPatrice Chotard if (err) { 494f264e235SPatrice Chotard debug("%s: can't find syscon device (%d)\n", __func__, 495f264e235SPatrice Chotard err); 496f264e235SPatrice Chotard return err; 497f264e235SPatrice Chotard } 498f264e235SPatrice Chotard 499f264e235SPatrice Chotard priv->pwr_regs = (struct stm32_pwr_regs *)ofnode_get_addr(args.node); 500f264e235SPatrice Chotard } 501f264e235SPatrice Chotard 502f264e235SPatrice Chotard configure_clocks(dev); 503f264e235SPatrice Chotard 504f264e235SPatrice Chotard return 0; 505f264e235SPatrice Chotard } 506f264e235SPatrice Chotard 507f264e235SPatrice Chotard static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) 508f264e235SPatrice Chotard { 509f264e235SPatrice Chotard debug("%s(clk=%p)\n", __func__, clk); 510f264e235SPatrice Chotard 511f264e235SPatrice Chotard if (args->args_count != 2) { 512f264e235SPatrice Chotard debug("Invaild args_count: %d\n", args->args_count); 513f264e235SPatrice Chotard return -EINVAL; 514f264e235SPatrice Chotard } 515f264e235SPatrice Chotard 516f264e235SPatrice Chotard if (args->args_count) 517f264e235SPatrice Chotard clk->id = args->args[1]; 518f264e235SPatrice Chotard else 519f264e235SPatrice Chotard clk->id = 0; 520f264e235SPatrice Chotard 521f264e235SPatrice Chotard return 0; 522f264e235SPatrice Chotard } 523f264e235SPatrice Chotard 524f264e235SPatrice Chotard static struct clk_ops stm32_clk_ops = { 525f264e235SPatrice Chotard .of_xlate = stm32_clk_of_xlate, 526f264e235SPatrice Chotard .enable = stm32_clk_enable, 527f264e235SPatrice Chotard .get_rate = stm32_clk_get_rate, 52805e23dd4SPatrice Chotard .set_rate = stm32_set_rate, 529f264e235SPatrice Chotard }; 530f264e235SPatrice Chotard 531f264e235SPatrice Chotard U_BOOT_DRIVER(stm32fx_clk) = { 532928954feSPatrice Chotard .name = "stm32fx_rcc_clock", 533f264e235SPatrice Chotard .id = UCLASS_CLK, 534f264e235SPatrice Chotard .ops = &stm32_clk_ops, 535f264e235SPatrice Chotard .probe = stm32_clk_probe, 536f264e235SPatrice Chotard .priv_auto_alloc_size = sizeof(struct stm32_clk), 537f264e235SPatrice Chotard .flags = DM_FLAG_PRE_RELOC, 538f264e235SPatrice Chotard }; 539