183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2f264e235SPatrice Chotard /*
3f264e235SPatrice Chotard * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
4f264e235SPatrice Chotard * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
5f264e235SPatrice Chotard */
6f264e235SPatrice Chotard
7f264e235SPatrice Chotard #include <common.h>
8f264e235SPatrice Chotard #include <clk-uclass.h>
9f264e235SPatrice Chotard #include <dm.h>
10928954feSPatrice Chotard #include <stm32_rcc.h>
11f264e235SPatrice Chotard
12f264e235SPatrice Chotard #include <asm/io.h>
13f264e235SPatrice Chotard #include <asm/arch/stm32.h>
14f264e235SPatrice Chotard #include <asm/arch/stm32_pwr.h>
15f264e235SPatrice Chotard
16f264e235SPatrice Chotard #include <dt-bindings/mfd/stm32f7-rcc.h>
17f264e235SPatrice Chotard
18f264e235SPatrice Chotard #define RCC_CR_HSION BIT(0)
19f264e235SPatrice Chotard #define RCC_CR_HSEON BIT(16)
20f264e235SPatrice Chotard #define RCC_CR_HSERDY BIT(17)
21f264e235SPatrice Chotard #define RCC_CR_HSEBYP BIT(18)
22f264e235SPatrice Chotard #define RCC_CR_CSSON BIT(19)
23f264e235SPatrice Chotard #define RCC_CR_PLLON BIT(24)
24f264e235SPatrice Chotard #define RCC_CR_PLLRDY BIT(25)
254e97e257SPatrice Chotard #define RCC_CR_PLLSAION BIT(28)
264e97e257SPatrice Chotard #define RCC_CR_PLLSAIRDY BIT(29)
27f264e235SPatrice Chotard
28f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0)
29f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6)
30f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16)
31f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24)
32f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLSRC BIT(22)
33f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLM_SHIFT 0
34f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLN_SHIFT 6
35f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLP_SHIFT 16
36f264e235SPatrice Chotard #define RCC_PLLCFGR_PLLQ_SHIFT 24
37f264e235SPatrice Chotard
38f264e235SPatrice Chotard #define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4)
39f264e235SPatrice Chotard #define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10)
40f264e235SPatrice Chotard #define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13)
41f264e235SPatrice Chotard #define RCC_CFGR_SW0 BIT(0)
42f264e235SPatrice Chotard #define RCC_CFGR_SW1 BIT(1)
43f264e235SPatrice Chotard #define RCC_CFGR_SW_MASK GENMASK(1, 0)
44f264e235SPatrice Chotard #define RCC_CFGR_SW_HSI 0
45f264e235SPatrice Chotard #define RCC_CFGR_SW_HSE RCC_CFGR_SW0
46f264e235SPatrice Chotard #define RCC_CFGR_SW_PLL RCC_CFGR_SW1
47f264e235SPatrice Chotard #define RCC_CFGR_SWS0 BIT(2)
48f264e235SPatrice Chotard #define RCC_CFGR_SWS1 BIT(3)
49f264e235SPatrice Chotard #define RCC_CFGR_SWS_MASK GENMASK(3, 2)
50f264e235SPatrice Chotard #define RCC_CFGR_SWS_HSI 0
51f264e235SPatrice Chotard #define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0
52f264e235SPatrice Chotard #define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1
53f264e235SPatrice Chotard #define RCC_CFGR_HPRE_SHIFT 4
54f264e235SPatrice Chotard #define RCC_CFGR_PPRE1_SHIFT 10
55f264e235SPatrice Chotard #define RCC_CFGR_PPRE2_SHIFT 13
56f264e235SPatrice Chotard
57526aa929SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIN_MASK GENMASK(14, 6)
58526aa929SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_MASK GENMASK(17, 16)
591038e033SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIQ_MASK GENMASK(27, 24)
601038e033SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIR_MASK GENMASK(30, 28)
614e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIN_SHIFT 6
624e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_SHIFT 16
631038e033SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIQ_SHIFT 24
641038e033SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIR_SHIFT 28
65990dba64SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIP_4 BIT(16)
664e97e257SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26)
67e8fb9ed2SPatrice Chotard #define RCC_PLLSAICFGR_PLLSAIR_3 BIT(29) | BIT(28)
684e97e257SPatrice Chotard
6961803a95SPatrice Chotard #define RCC_DCKCFGRX_TIMPRE BIT(24)
704e97e257SPatrice Chotard #define RCC_DCKCFGRX_CK48MSEL BIT(27)
714e97e257SPatrice Chotard #define RCC_DCKCFGRX_SDMMC1SEL BIT(28)
724e97e257SPatrice Chotard #define RCC_DCKCFGR2_SDMMC2SEL BIT(29)
734e97e257SPatrice Chotard
74e8fb9ed2SPatrice Chotard #define RCC_DCKCFGR_PLLSAIDIVR_SHIFT 16
75e8fb9ed2SPatrice Chotard #define RCC_DCKCFGR_PLLSAIDIVR_MASK GENMASK(17, 16)
76e8fb9ed2SPatrice Chotard #define RCC_DCKCFGR_PLLSAIDIVR_2 0
77e8fb9ed2SPatrice Chotard
78c88c6a9eSPatrice Chotard /*
79c88c6a9eSPatrice Chotard * RCC AHB1ENR specific definitions
80c88c6a9eSPatrice Chotard */
81c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_EN BIT(25)
82c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_TX_EN BIT(26)
83c88c6a9eSPatrice Chotard #define RCC_AHB1ENR_ETHMAC_RX_EN BIT(27)
84c88c6a9eSPatrice Chotard
85c88c6a9eSPatrice Chotard /*
86c88c6a9eSPatrice Chotard * RCC APB1ENR specific definitions
87c88c6a9eSPatrice Chotard */
88c88c6a9eSPatrice Chotard #define RCC_APB1ENR_TIM2EN BIT(0)
89c88c6a9eSPatrice Chotard #define RCC_APB1ENR_PWREN BIT(28)
90c88c6a9eSPatrice Chotard
91c88c6a9eSPatrice Chotard /*
92c88c6a9eSPatrice Chotard * RCC APB2ENR specific definitions
93c88c6a9eSPatrice Chotard */
94c88c6a9eSPatrice Chotard #define RCC_APB2ENR_SYSCFGEN BIT(14)
9520fe38e7SPatrice Chotard #define RCC_APB2ENR_SAI1EN BIT(22)
96c88c6a9eSPatrice Chotard
971038e033SPatrice Chotard enum pllsai_div {
981038e033SPatrice Chotard PLLSAIP,
991038e033SPatrice Chotard PLLSAIQ,
1001038e033SPatrice Chotard PLLSAIR,
1011038e033SPatrice Chotard };
1021038e033SPatrice Chotard
103cb97ff9dSPatrice Chotard static const struct stm32_clk_info stm32f4_clk_info = {
104f264e235SPatrice Chotard /* 180 MHz */
105f264e235SPatrice Chotard .sys_pll_psc = {
106f264e235SPatrice Chotard .pll_n = 360,
107f264e235SPatrice Chotard .pll_p = 2,
108f264e235SPatrice Chotard .pll_q = 8,
109f264e235SPatrice Chotard .ahb_psc = AHB_PSC_1,
110f264e235SPatrice Chotard .apb1_psc = APB_PSC_4,
111f264e235SPatrice Chotard .apb2_psc = APB_PSC_2,
112f264e235SPatrice Chotard },
113f264e235SPatrice Chotard .has_overdrive = false,
1144e97e257SPatrice Chotard .v2 = false,
115f264e235SPatrice Chotard };
116f264e235SPatrice Chotard
117cb97ff9dSPatrice Chotard static const struct stm32_clk_info stm32f7_clk_info = {
118f264e235SPatrice Chotard /* 200 MHz */
119f264e235SPatrice Chotard .sys_pll_psc = {
120f264e235SPatrice Chotard .pll_n = 400,
121f264e235SPatrice Chotard .pll_p = 2,
122f264e235SPatrice Chotard .pll_q = 8,
123f264e235SPatrice Chotard .ahb_psc = AHB_PSC_1,
124f264e235SPatrice Chotard .apb1_psc = APB_PSC_4,
125f264e235SPatrice Chotard .apb2_psc = APB_PSC_2,
126f264e235SPatrice Chotard },
127f264e235SPatrice Chotard .has_overdrive = true,
1284e97e257SPatrice Chotard .v2 = true,
129f264e235SPatrice Chotard };
130f264e235SPatrice Chotard
131f264e235SPatrice Chotard struct stm32_clk {
132f264e235SPatrice Chotard struct stm32_rcc_regs *base;
133f264e235SPatrice Chotard struct stm32_pwr_regs *pwr_regs;
134cb97ff9dSPatrice Chotard struct stm32_clk_info info;
135cb97ff9dSPatrice Chotard unsigned long hse_rate;
136*8b414645SPatrice Chotard bool pllsaip;
137f264e235SPatrice Chotard };
138f264e235SPatrice Chotard
1395e993508SPatrice Chotard #ifdef CONFIG_VIDEO_STM32
1405e993508SPatrice Chotard static const u8 plldivr_table[] = { 0, 0, 2, 3, 4, 5, 6, 7 };
1415e993508SPatrice Chotard #endif
142e8fb9ed2SPatrice Chotard static const u8 pllsaidivr_table[] = { 2, 4, 8, 16 };
143e8fb9ed2SPatrice Chotard
configure_clocks(struct udevice * dev)144f264e235SPatrice Chotard static int configure_clocks(struct udevice *dev)
145f264e235SPatrice Chotard {
146f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev);
147f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
148f264e235SPatrice Chotard struct stm32_pwr_regs *pwr = priv->pwr_regs;
149cb97ff9dSPatrice Chotard struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc;
150f264e235SPatrice Chotard
151f264e235SPatrice Chotard /* Reset RCC configuration */
152f264e235SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSION);
153f264e235SPatrice Chotard writel(0, ®s->cfgr); /* Reset CFGR */
154f264e235SPatrice Chotard clrbits_le32(®s->cr, (RCC_CR_HSEON | RCC_CR_CSSON
1554e97e257SPatrice Chotard | RCC_CR_PLLON | RCC_CR_PLLSAION));
156f264e235SPatrice Chotard writel(0x24003010, ®s->pllcfgr); /* Reset value from RM */
157f264e235SPatrice Chotard clrbits_le32(®s->cr, RCC_CR_HSEBYP);
158f264e235SPatrice Chotard writel(0, ®s->cir); /* Disable all interrupts */
159f264e235SPatrice Chotard
160f264e235SPatrice Chotard /* Configure for HSE+PLL operation */
161f264e235SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSEON);
162f264e235SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_HSERDY))
163f264e235SPatrice Chotard ;
164f264e235SPatrice Chotard
165f264e235SPatrice Chotard setbits_le32(®s->cfgr, ((
166cb97ff9dSPatrice Chotard sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT)
167cb97ff9dSPatrice Chotard | (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT)
168cb97ff9dSPatrice Chotard | (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
169f264e235SPatrice Chotard
170f264e235SPatrice Chotard /* Configure the main PLL */
171f264e235SPatrice Chotard setbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
172f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
173cb97ff9dSPatrice Chotard sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
174f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
175cb97ff9dSPatrice Chotard sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
176f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
177cb97ff9dSPatrice Chotard ((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
178f264e235SPatrice Chotard clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
179cb97ff9dSPatrice Chotard sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
180f264e235SPatrice Chotard
181651a70e8SPatrice Chotard /* configure SDMMC clock */
182cb97ff9dSPatrice Chotard if (priv->info.v2) { /*stm32f7 case */
183*8b414645SPatrice Chotard if (priv->pllsaip)
184*8b414645SPatrice Chotard /* select PLLSAIP as 48MHz clock source */
185*8b414645SPatrice Chotard setbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
186*8b414645SPatrice Chotard else
187651a70e8SPatrice Chotard /* select PLLQ as 48MHz clock source */
188651a70e8SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
1894e97e257SPatrice Chotard
1904e97e257SPatrice Chotard /* select 48MHz as SDMMC1 clock source */
1914e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
1924e97e257SPatrice Chotard
1934e97e257SPatrice Chotard /* select 48MHz as SDMMC2 clock source */
1944e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
1954e97e257SPatrice Chotard } else { /* stm32f4 case */
196*8b414645SPatrice Chotard if (priv->pllsaip)
197*8b414645SPatrice Chotard /* select PLLSAIP as 48MHz clock source */
198*8b414645SPatrice Chotard setbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
199*8b414645SPatrice Chotard else
200651a70e8SPatrice Chotard /* select PLLQ as 48MHz clock source */
201651a70e8SPatrice Chotard clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
2024e97e257SPatrice Chotard
2034e97e257SPatrice Chotard /* select 48MHz as SDMMC1 clock source */
2044e97e257SPatrice Chotard clrbits_le32(®s->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
2054e97e257SPatrice Chotard }
2064e97e257SPatrice Chotard
207e8fb9ed2SPatrice Chotard /*
208*8b414645SPatrice Chotard * Configure the SAI PLL to generate LTDC pixel clock and
209*8b414645SPatrice Chotard * 48 Mhz for SDMMC and USB
210e8fb9ed2SPatrice Chotard */
211*8b414645SPatrice Chotard clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIP_MASK,
212*8b414645SPatrice Chotard RCC_PLLSAICFGR_PLLSAIP_4);
213e8fb9ed2SPatrice Chotard clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
214e8fb9ed2SPatrice Chotard RCC_PLLSAICFGR_PLLSAIR_3);
215e8fb9ed2SPatrice Chotard clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK,
216e8fb9ed2SPatrice Chotard 195 << RCC_PLLSAICFGR_PLLSAIN_SHIFT);
217e8fb9ed2SPatrice Chotard
218e8fb9ed2SPatrice Chotard clrsetbits_le32(®s->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
219e8fb9ed2SPatrice Chotard RCC_DCKCFGR_PLLSAIDIVR_2 << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
220*8b414645SPatrice Chotard
221651a70e8SPatrice Chotard /* Enable the main PLL */
222651a70e8SPatrice Chotard setbits_le32(®s->cr, RCC_CR_PLLON);
223651a70e8SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_PLLRDY))
2244e97e257SPatrice Chotard ;
2254e97e257SPatrice Chotard
226e8fb9ed2SPatrice Chotard /* Enable the SAI PLL */
227e8fb9ed2SPatrice Chotard setbits_le32(®s->cr, RCC_CR_PLLSAION);
228e8fb9ed2SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_PLLSAIRDY))
229e8fb9ed2SPatrice Chotard ;
230f264e235SPatrice Chotard setbits_le32(®s->apb1enr, RCC_APB1ENR_PWREN);
231f264e235SPatrice Chotard
232cb97ff9dSPatrice Chotard if (priv->info.has_overdrive) {
233f264e235SPatrice Chotard /*
234f264e235SPatrice Chotard * Enable high performance mode
235f264e235SPatrice Chotard * System frequency up to 200 MHz
236f264e235SPatrice Chotard */
237f264e235SPatrice Chotard setbits_le32(&pwr->cr1, PWR_CR1_ODEN);
238f264e235SPatrice Chotard /* Infinite wait! */
239f264e235SPatrice Chotard while (!(readl(&pwr->csr1) & PWR_CSR1_ODRDY))
240f264e235SPatrice Chotard ;
241f264e235SPatrice Chotard /* Enable the Over-drive switch */
242f264e235SPatrice Chotard setbits_le32(&pwr->cr1, PWR_CR1_ODSWEN);
243f264e235SPatrice Chotard /* Infinite wait! */
244f264e235SPatrice Chotard while (!(readl(&pwr->csr1) & PWR_CSR1_ODSWRDY))
245f264e235SPatrice Chotard ;
246f264e235SPatrice Chotard }
247f264e235SPatrice Chotard
248f264e235SPatrice Chotard stm32_flash_latency_cfg(5);
249f264e235SPatrice Chotard clrbits_le32(®s->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
250f264e235SPatrice Chotard setbits_le32(®s->cfgr, RCC_CFGR_SW_PLL);
251f264e235SPatrice Chotard
252f264e235SPatrice Chotard while ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) !=
253f264e235SPatrice Chotard RCC_CFGR_SWS_PLL)
254f264e235SPatrice Chotard ;
255f264e235SPatrice Chotard
25620fe38e7SPatrice Chotard #ifdef CONFIG_ETH_DESIGNWARE
25720fe38e7SPatrice Chotard /* gate the SYSCFG clock, needed to set RMII ethernet interface */
25820fe38e7SPatrice Chotard setbits_le32(®s->apb2enr, RCC_APB2ENR_SYSCFGEN);
25920fe38e7SPatrice Chotard #endif
26020fe38e7SPatrice Chotard
261f264e235SPatrice Chotard return 0;
262f264e235SPatrice Chotard }
263f264e235SPatrice Chotard
stm32_clk_get_ck48msel(struct stm32_clk * priv)2641038e033SPatrice Chotard static bool stm32_clk_get_ck48msel(struct stm32_clk *priv)
2654e97e257SPatrice Chotard {
2664e97e257SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
2674e97e257SPatrice Chotard
268cb97ff9dSPatrice Chotard if (priv->info.v2) /*stm32f7 case */
2691038e033SPatrice Chotard return readl(®s->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
2704e97e257SPatrice Chotard else
2714e97e257SPatrice Chotard
2721038e033SPatrice Chotard return readl(®s->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
2731038e033SPatrice Chotard }
2741038e033SPatrice Chotard
stm32_clk_get_pllsai_vco_rate(struct stm32_clk * priv)2751038e033SPatrice Chotard static unsigned long stm32_clk_get_pllsai_vco_rate(struct stm32_clk *priv)
2761038e033SPatrice Chotard {
2771038e033SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
2781038e033SPatrice Chotard u16 pllm, pllsain;
2791038e033SPatrice Chotard
2804e97e257SPatrice Chotard pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
281526aa929SPatrice Chotard pllsain = ((readl(®s->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
2824e97e257SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
2831038e033SPatrice Chotard
2841038e033SPatrice Chotard return ((priv->hse_rate / pllm) * pllsain);
2854e97e257SPatrice Chotard }
2861038e033SPatrice Chotard
stm32_clk_get_pllsai_rate(struct stm32_clk * priv,enum pllsai_div output)2871038e033SPatrice Chotard static unsigned long stm32_clk_get_pllsai_rate(struct stm32_clk *priv,
2881038e033SPatrice Chotard enum pllsai_div output)
2891038e033SPatrice Chotard {
2901038e033SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
2911038e033SPatrice Chotard u16 pll_div_output;
2921038e033SPatrice Chotard
2931038e033SPatrice Chotard switch (output) {
2941038e033SPatrice Chotard case PLLSAIP:
2951038e033SPatrice Chotard pll_div_output = ((((readl(®s->pllsaicfgr)
2961038e033SPatrice Chotard & RCC_PLLSAICFGR_PLLSAIP_MASK)
2971038e033SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
2981038e033SPatrice Chotard break;
2991038e033SPatrice Chotard case PLLSAIQ:
3001038e033SPatrice Chotard pll_div_output = (readl(®s->pllsaicfgr)
3011038e033SPatrice Chotard & RCC_PLLSAICFGR_PLLSAIQ_MASK)
3021038e033SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIQ_SHIFT;
3031038e033SPatrice Chotard break;
3041038e033SPatrice Chotard case PLLSAIR:
3051038e033SPatrice Chotard pll_div_output = (readl(®s->pllsaicfgr)
3061038e033SPatrice Chotard & RCC_PLLSAICFGR_PLLSAIR_MASK)
3071038e033SPatrice Chotard >> RCC_PLLSAICFGR_PLLSAIR_SHIFT;
3081038e033SPatrice Chotard break;
3091038e033SPatrice Chotard default:
3101038e033SPatrice Chotard pr_err("incorrect PLLSAI output %d\n", output);
3111038e033SPatrice Chotard return -EINVAL;
3121038e033SPatrice Chotard }
3131038e033SPatrice Chotard
3141038e033SPatrice Chotard return (stm32_clk_get_pllsai_vco_rate(priv) / pll_div_output);
3154e97e257SPatrice Chotard }
3164e97e257SPatrice Chotard
stm32_get_timpre(struct stm32_clk * priv)31761803a95SPatrice Chotard static bool stm32_get_timpre(struct stm32_clk *priv)
318f264e235SPatrice Chotard {
319f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
32061803a95SPatrice Chotard u32 val;
32161803a95SPatrice Chotard
32261803a95SPatrice Chotard if (priv->info.v2) /*stm32f7 case */
32361803a95SPatrice Chotard val = readl(®s->dckcfgr2);
32461803a95SPatrice Chotard else
32561803a95SPatrice Chotard val = readl(®s->dckcfgr);
32661803a95SPatrice Chotard /* get timer prescaler */
32761803a95SPatrice Chotard return !!(val & RCC_DCKCFGRX_TIMPRE);
32861803a95SPatrice Chotard }
32961803a95SPatrice Chotard
stm32_get_hclk_rate(struct stm32_rcc_regs * regs,u32 sysclk)33061803a95SPatrice Chotard static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk)
33161803a95SPatrice Chotard {
33261803a95SPatrice Chotard u8 shift;
333f264e235SPatrice Chotard /* Prescaler table lookups for clock computation */
334f264e235SPatrice Chotard u8 ahb_psc_table[16] = {
335f264e235SPatrice Chotard 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
336f264e235SPatrice Chotard };
33761803a95SPatrice Chotard
33861803a95SPatrice Chotard shift = ahb_psc_table[(
33961803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK)
34061803a95SPatrice Chotard >> RCC_CFGR_HPRE_SHIFT)];
34161803a95SPatrice Chotard
34261803a95SPatrice Chotard return sysclk >> shift;
34361803a95SPatrice Chotard };
34461803a95SPatrice Chotard
stm32_get_apb_shift(struct stm32_rcc_regs * regs,enum apb apb)34561803a95SPatrice Chotard static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb)
34661803a95SPatrice Chotard {
34761803a95SPatrice Chotard /* Prescaler table lookups for clock computation */
348f264e235SPatrice Chotard u8 apb_psc_table[8] = {
349f264e235SPatrice Chotard 0, 0, 0, 0, 1, 2, 3, 4
350f264e235SPatrice Chotard };
351f264e235SPatrice Chotard
35261803a95SPatrice Chotard if (apb == APB1)
35361803a95SPatrice Chotard return apb_psc_table[(
35461803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK)
35561803a95SPatrice Chotard >> RCC_CFGR_PPRE1_SHIFT)];
35661803a95SPatrice Chotard else /* APB2 */
35761803a95SPatrice Chotard return apb_psc_table[(
35861803a95SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK)
35961803a95SPatrice Chotard >> RCC_CFGR_PPRE2_SHIFT)];
36061803a95SPatrice Chotard };
36161803a95SPatrice Chotard
stm32_get_timer_rate(struct stm32_clk * priv,u32 sysclk,enum apb apb)36261803a95SPatrice Chotard static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk,
36361803a95SPatrice Chotard enum apb apb)
36461803a95SPatrice Chotard {
36561803a95SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
36661803a95SPatrice Chotard u8 shift = stm32_get_apb_shift(regs, apb);
36761803a95SPatrice Chotard
36861803a95SPatrice Chotard if (stm32_get_timpre(priv))
36961803a95SPatrice Chotard /*
37061803a95SPatrice Chotard * if APB prescaler is configured to a
37161803a95SPatrice Chotard * division factor of 1, 2 or 4
37261803a95SPatrice Chotard */
37361803a95SPatrice Chotard switch (shift) {
37461803a95SPatrice Chotard case 0:
37561803a95SPatrice Chotard case 1:
37661803a95SPatrice Chotard case 2:
37761803a95SPatrice Chotard return stm32_get_hclk_rate(regs, sysclk);
37861803a95SPatrice Chotard default:
37961803a95SPatrice Chotard return (sysclk >> shift) * 4;
38061803a95SPatrice Chotard }
38161803a95SPatrice Chotard else
38261803a95SPatrice Chotard /*
38361803a95SPatrice Chotard * if APB prescaler is configured to a
38461803a95SPatrice Chotard * division factor of 1
38561803a95SPatrice Chotard */
38661803a95SPatrice Chotard if (shift == 0)
38761803a95SPatrice Chotard return sysclk;
38861803a95SPatrice Chotard else
38961803a95SPatrice Chotard return (sysclk >> shift) * 2;
39061803a95SPatrice Chotard };
39161803a95SPatrice Chotard
stm32_clk_get_rate(struct clk * clk)39261803a95SPatrice Chotard static ulong stm32_clk_get_rate(struct clk *clk)
39361803a95SPatrice Chotard {
39461803a95SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev);
39561803a95SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
39661803a95SPatrice Chotard u32 sysclk = 0;
397aa230be4SPatrice Chotard u32 vco;
3981038e033SPatrice Chotard u32 sdmmcxsel_bit;
399e8fb9ed2SPatrice Chotard u32 saidivr;
400e8fb9ed2SPatrice Chotard u32 pllsai_rate;
4011038e033SPatrice Chotard u16 pllm, plln, pllp, pllq;
40261803a95SPatrice Chotard
403f264e235SPatrice Chotard if ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) ==
404f264e235SPatrice Chotard RCC_CFGR_SWS_PLL) {
405f264e235SPatrice Chotard pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
406f264e235SPatrice Chotard plln = ((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
407f264e235SPatrice Chotard >> RCC_PLLCFGR_PLLN_SHIFT);
408f264e235SPatrice Chotard pllp = ((((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
409f264e235SPatrice Chotard >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
4101038e033SPatrice Chotard pllq = ((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
4111038e033SPatrice Chotard >> RCC_PLLCFGR_PLLQ_SHIFT);
412aa230be4SPatrice Chotard vco = (priv->hse_rate / pllm) * plln;
413aa230be4SPatrice Chotard sysclk = vco / pllp;
414f264e235SPatrice Chotard } else {
415f264e235SPatrice Chotard return -EINVAL;
416f264e235SPatrice Chotard }
417f264e235SPatrice Chotard
418f264e235SPatrice Chotard switch (clk->id) {
419f264e235SPatrice Chotard /*
420f264e235SPatrice Chotard * AHB CLOCK: 3 x 32 bits consecutive registers are used :
421f264e235SPatrice Chotard * AHB1, AHB2 and AHB3
422f264e235SPatrice Chotard */
423f264e235SPatrice Chotard case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
42461803a95SPatrice Chotard return stm32_get_hclk_rate(regs, sysclk);
425f264e235SPatrice Chotard /* APB1 CLOCK */
426f264e235SPatrice Chotard case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
42761803a95SPatrice Chotard /* For timer clock, an additionnal prescaler is used*/
42861803a95SPatrice Chotard switch (clk->id) {
42961803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM2):
43061803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM3):
43161803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM4):
43261803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM5):
43361803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM6):
43461803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM7):
43561803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM12):
43661803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM13):
43761803a95SPatrice Chotard case STM32F7_APB1_CLOCK(TIM14):
43861803a95SPatrice Chotard return stm32_get_timer_rate(priv, sysclk, APB1);
43961803a95SPatrice Chotard }
44061803a95SPatrice Chotard return (sysclk >> stm32_get_apb_shift(regs, APB1));
44161803a95SPatrice Chotard
442f264e235SPatrice Chotard /* APB2 CLOCK */
4436243c884SPatrice Chotard case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(DSI):
4441038e033SPatrice Chotard switch (clk->id) {
4454e97e257SPatrice Chotard /*
4464e97e257SPatrice Chotard * particular case for SDMMC1 and SDMMC2 :
4474e97e257SPatrice Chotard * 48Mhz source clock can be from main PLL or from
4481038e033SPatrice Chotard * PLLSAIP
4494e97e257SPatrice Chotard */
4504e97e257SPatrice Chotard case STM32F7_APB2_CLOCK(SDMMC1):
4511038e033SPatrice Chotard case STM32F7_APB2_CLOCK(SDMMC2):
4521038e033SPatrice Chotard if (clk->id == STM32F7_APB2_CLOCK(SDMMC1))
4531038e033SPatrice Chotard sdmmcxsel_bit = RCC_DCKCFGRX_SDMMC1SEL;
4541038e033SPatrice Chotard else
4551038e033SPatrice Chotard sdmmcxsel_bit = RCC_DCKCFGR2_SDMMC2SEL;
4561038e033SPatrice Chotard
4571038e033SPatrice Chotard if (readl(®s->dckcfgr2) & sdmmcxsel_bit)
4584e97e257SPatrice Chotard /* System clock is selected as SDMMC1 clock */
4594e97e257SPatrice Chotard return sysclk;
4601038e033SPatrice Chotard /*
4611038e033SPatrice Chotard * 48 MHz can be generated by either PLLSAIP
4621038e033SPatrice Chotard * or by PLLQ depending of CK48MSEL bit of RCC_DCKCFGR
4631038e033SPatrice Chotard */
4641038e033SPatrice Chotard if (stm32_clk_get_ck48msel(priv))
4651038e033SPatrice Chotard return stm32_clk_get_pllsai_rate(priv, PLLSAIP);
4664e97e257SPatrice Chotard else
4671038e033SPatrice Chotard return (vco / pllq);
4684e97e257SPatrice Chotard break;
4694e97e257SPatrice Chotard
47061803a95SPatrice Chotard /* For timer clock, an additionnal prescaler is used*/
47161803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM1):
47261803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM8):
47361803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM9):
47461803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM10):
47561803a95SPatrice Chotard case STM32F7_APB2_CLOCK(TIM11):
47661803a95SPatrice Chotard return stm32_get_timer_rate(priv, sysclk, APB2);
47761803a95SPatrice Chotard break;
478e8fb9ed2SPatrice Chotard
479e8fb9ed2SPatrice Chotard /* particular case for LTDC clock */
480e8fb9ed2SPatrice Chotard case STM32F7_APB2_CLOCK(LTDC):
481e8fb9ed2SPatrice Chotard saidivr = readl(®s->dckcfgr);
482e8fb9ed2SPatrice Chotard saidivr = (saidivr & RCC_DCKCFGR_PLLSAIDIVR_MASK)
483e8fb9ed2SPatrice Chotard >> RCC_DCKCFGR_PLLSAIDIVR_SHIFT;
484e8fb9ed2SPatrice Chotard pllsai_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR);
485e8fb9ed2SPatrice Chotard
486e8fb9ed2SPatrice Chotard return pllsai_rate / pllsaidivr_table[saidivr];
48761803a95SPatrice Chotard }
48861803a95SPatrice Chotard return (sysclk >> stm32_get_apb_shift(regs, APB2));
48961803a95SPatrice Chotard
490f264e235SPatrice Chotard default:
491f264e235SPatrice Chotard pr_err("clock index %ld out of range\n", clk->id);
492f264e235SPatrice Chotard return -EINVAL;
493f264e235SPatrice Chotard }
494f264e235SPatrice Chotard }
495f264e235SPatrice Chotard
stm32_set_rate(struct clk * clk,ulong rate)49605e23dd4SPatrice Chotard static ulong stm32_set_rate(struct clk *clk, ulong rate)
49705e23dd4SPatrice Chotard {
4985e993508SPatrice Chotard #ifdef CONFIG_VIDEO_STM32
4995e993508SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev);
5005e993508SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
5015e993508SPatrice Chotard u32 pllsair_rate, pllsai_vco_rate, current_rate;
5025e993508SPatrice Chotard u32 best_div, best_diff, diff;
5035e993508SPatrice Chotard u16 div;
5045e993508SPatrice Chotard u8 best_plldivr, best_pllsaidivr;
5055e993508SPatrice Chotard u8 i, j;
5065e993508SPatrice Chotard bool found = false;
5075e993508SPatrice Chotard
5085e993508SPatrice Chotard /* Only set_rate for LTDC clock is implemented */
5095e993508SPatrice Chotard if (clk->id != STM32F7_APB2_CLOCK(LTDC)) {
5105e993508SPatrice Chotard pr_err("set_rate not implemented for clock index %ld\n",
5115e993508SPatrice Chotard clk->id);
51205e23dd4SPatrice Chotard return 0;
51305e23dd4SPatrice Chotard }
51405e23dd4SPatrice Chotard
5155e993508SPatrice Chotard if (rate == stm32_clk_get_rate(clk))
5165e993508SPatrice Chotard /* already set to requested rate */
5175e993508SPatrice Chotard return rate;
5185e993508SPatrice Chotard
5195e993508SPatrice Chotard /* get the current PLLSAIR output freq */
5205e993508SPatrice Chotard pllsair_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR);
5215e993508SPatrice Chotard best_div = pllsair_rate / rate;
5225e993508SPatrice Chotard
5235e993508SPatrice Chotard /* look into pllsaidivr_table if this divider is available*/
5245e993508SPatrice Chotard for (i = 0 ; i < sizeof(pllsaidivr_table); i++)
5255e993508SPatrice Chotard if (best_div == pllsaidivr_table[i]) {
5265e993508SPatrice Chotard /* set pll_saidivr with found value */
5275e993508SPatrice Chotard clrsetbits_le32(®s->dckcfgr,
5285e993508SPatrice Chotard RCC_DCKCFGR_PLLSAIDIVR_MASK,
5295e993508SPatrice Chotard pllsaidivr_table[i]);
5305e993508SPatrice Chotard return rate;
5315e993508SPatrice Chotard }
5325e993508SPatrice Chotard
5335e993508SPatrice Chotard /*
5345e993508SPatrice Chotard * As no pllsaidivr value is suitable to obtain requested freq,
5355e993508SPatrice Chotard * test all combination of pllsaidivr * pllsair and find the one
5365e993508SPatrice Chotard * which give freq closest to requested rate.
5375e993508SPatrice Chotard */
5385e993508SPatrice Chotard
5395e993508SPatrice Chotard pllsai_vco_rate = stm32_clk_get_pllsai_vco_rate(priv);
5405e993508SPatrice Chotard best_diff = ULONG_MAX;
5415e993508SPatrice Chotard best_pllsaidivr = 0;
5425e993508SPatrice Chotard best_plldivr = 0;
5435e993508SPatrice Chotard /*
5445e993508SPatrice Chotard * start at index 2 of plldivr_table as divider value at index 0
5455e993508SPatrice Chotard * and 1 are 0)
5465e993508SPatrice Chotard */
5475e993508SPatrice Chotard for (i = 2; i < sizeof(plldivr_table); i++) {
5485e993508SPatrice Chotard for (j = 0; j < sizeof(pllsaidivr_table); j++) {
5495e993508SPatrice Chotard div = plldivr_table[i] * pllsaidivr_table[j];
5505e993508SPatrice Chotard current_rate = pllsai_vco_rate / div;
5515e993508SPatrice Chotard /* perfect combination is found ? */
5525e993508SPatrice Chotard if (current_rate == rate) {
5535e993508SPatrice Chotard best_pllsaidivr = j;
5545e993508SPatrice Chotard best_plldivr = i;
5555e993508SPatrice Chotard found = true;
5565e993508SPatrice Chotard break;
5575e993508SPatrice Chotard }
5585e993508SPatrice Chotard
5595e993508SPatrice Chotard diff = (current_rate > rate) ?
5605e993508SPatrice Chotard current_rate - rate : rate - current_rate;
5615e993508SPatrice Chotard
5625e993508SPatrice Chotard /* found a better combination ? */
5635e993508SPatrice Chotard if (diff < best_diff) {
5645e993508SPatrice Chotard best_diff = diff;
5655e993508SPatrice Chotard best_pllsaidivr = j;
5665e993508SPatrice Chotard best_plldivr = i;
5675e993508SPatrice Chotard }
5685e993508SPatrice Chotard }
5695e993508SPatrice Chotard
5705e993508SPatrice Chotard if (found)
5715e993508SPatrice Chotard break;
5725e993508SPatrice Chotard }
5735e993508SPatrice Chotard
5745e993508SPatrice Chotard /* Disable the SAI PLL */
5755e993508SPatrice Chotard clrbits_le32(®s->cr, RCC_CR_PLLSAION);
5765e993508SPatrice Chotard
5775e993508SPatrice Chotard /* set pll_saidivr with found value */
5785e993508SPatrice Chotard clrsetbits_le32(®s->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
5795e993508SPatrice Chotard best_pllsaidivr << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
5805e993508SPatrice Chotard
5815e993508SPatrice Chotard /* set pllsair with found value */
5825e993508SPatrice Chotard clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
5835e993508SPatrice Chotard plldivr_table[best_plldivr]
5845e993508SPatrice Chotard << RCC_PLLSAICFGR_PLLSAIR_SHIFT);
5855e993508SPatrice Chotard
5865e993508SPatrice Chotard /* Enable the SAI PLL */
5875e993508SPatrice Chotard setbits_le32(®s->cr, RCC_CR_PLLSAION);
5885e993508SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_PLLSAIRDY))
5895e993508SPatrice Chotard ;
5905e993508SPatrice Chotard
5915e993508SPatrice Chotard div = plldivr_table[best_plldivr] * pllsaidivr_table[best_pllsaidivr];
5925e993508SPatrice Chotard return pllsai_vco_rate / div;
5935e993508SPatrice Chotard #else
5945e993508SPatrice Chotard return 0;
5955e993508SPatrice Chotard #endif
5965e993508SPatrice Chotard }
5975e993508SPatrice Chotard
stm32_clk_enable(struct clk * clk)598f264e235SPatrice Chotard static int stm32_clk_enable(struct clk *clk)
599f264e235SPatrice Chotard {
600f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev);
601f264e235SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
602f264e235SPatrice Chotard u32 offset = clk->id / 32;
603f264e235SPatrice Chotard u32 bit_index = clk->id % 32;
604f264e235SPatrice Chotard
605f264e235SPatrice Chotard debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
606f264e235SPatrice Chotard __func__, clk->id, offset, bit_index);
607f264e235SPatrice Chotard setbits_le32(®s->ahb1enr + offset, BIT(bit_index));
608f264e235SPatrice Chotard
609f264e235SPatrice Chotard return 0;
610f264e235SPatrice Chotard }
611f264e235SPatrice Chotard
stm32_clk_probe(struct udevice * dev)612f264e235SPatrice Chotard static int stm32_clk_probe(struct udevice *dev)
613f264e235SPatrice Chotard {
614f264e235SPatrice Chotard struct ofnode_phandle_args args;
615cb97ff9dSPatrice Chotard struct udevice *fixed_clock_dev = NULL;
616cb97ff9dSPatrice Chotard struct clk clk;
617f264e235SPatrice Chotard int err;
618f264e235SPatrice Chotard
619f264e235SPatrice Chotard debug("%s\n", __func__);
620f264e235SPatrice Chotard
621f264e235SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev);
622f264e235SPatrice Chotard fdt_addr_t addr;
623f264e235SPatrice Chotard
624f264e235SPatrice Chotard addr = dev_read_addr(dev);
625f264e235SPatrice Chotard if (addr == FDT_ADDR_T_NONE)
626f264e235SPatrice Chotard return -EINVAL;
627f264e235SPatrice Chotard
628f264e235SPatrice Chotard priv->base = (struct stm32_rcc_regs *)addr;
629*8b414645SPatrice Chotard priv->pllsaip = true;
630928954feSPatrice Chotard
631928954feSPatrice Chotard switch (dev_get_driver_data(dev)) {
632*8b414645SPatrice Chotard case STM32F42X:
633*8b414645SPatrice Chotard priv->pllsaip = false;
634*8b414645SPatrice Chotard /* fallback into STM32F469 case */
635*8b414645SPatrice Chotard case STM32F469:
636cb97ff9dSPatrice Chotard memcpy(&priv->info, &stm32f4_clk_info,
637cb97ff9dSPatrice Chotard sizeof(struct stm32_clk_info));
638928954feSPatrice Chotard break;
639*8b414645SPatrice Chotard
640928954feSPatrice Chotard case STM32F7:
641cb97ff9dSPatrice Chotard memcpy(&priv->info, &stm32f7_clk_info,
642cb97ff9dSPatrice Chotard sizeof(struct stm32_clk_info));
643928954feSPatrice Chotard break;
644928954feSPatrice Chotard default:
645928954feSPatrice Chotard return -EINVAL;
646928954feSPatrice Chotard }
647f264e235SPatrice Chotard
648cb97ff9dSPatrice Chotard /* retrieve HSE frequency (external oscillator) */
649cb97ff9dSPatrice Chotard err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse",
650cb97ff9dSPatrice Chotard &fixed_clock_dev);
651cb97ff9dSPatrice Chotard
652cb97ff9dSPatrice Chotard if (err) {
653cb97ff9dSPatrice Chotard pr_err("Can't find fixed clock (%d)", err);
654cb97ff9dSPatrice Chotard return err;
655cb97ff9dSPatrice Chotard }
656cb97ff9dSPatrice Chotard
657cb97ff9dSPatrice Chotard err = clk_request(fixed_clock_dev, &clk);
658cb97ff9dSPatrice Chotard if (err) {
659cb97ff9dSPatrice Chotard pr_err("Can't request %s clk (%d)", fixed_clock_dev->name,
660cb97ff9dSPatrice Chotard err);
661cb97ff9dSPatrice Chotard return err;
662cb97ff9dSPatrice Chotard }
663cb97ff9dSPatrice Chotard
664cb97ff9dSPatrice Chotard /*
665cb97ff9dSPatrice Chotard * set pllm factor accordingly to the external oscillator
666cb97ff9dSPatrice Chotard * frequency (HSE). For STM32F4 and STM32F7, we want VCO
667cb97ff9dSPatrice Chotard * freq at 1MHz
668cb97ff9dSPatrice Chotard * if input PLL frequency is 25Mhz, divide it by 25
669cb97ff9dSPatrice Chotard */
670cb97ff9dSPatrice Chotard clk.id = 0;
671cb97ff9dSPatrice Chotard priv->hse_rate = clk_get_rate(&clk);
672cb97ff9dSPatrice Chotard
673cb97ff9dSPatrice Chotard if (priv->hse_rate < 1000000) {
674cb97ff9dSPatrice Chotard pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__,
675cb97ff9dSPatrice Chotard priv->hse_rate);
676cb97ff9dSPatrice Chotard return -EINVAL;
677cb97ff9dSPatrice Chotard }
678cb97ff9dSPatrice Chotard
679cb97ff9dSPatrice Chotard priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000;
680cb97ff9dSPatrice Chotard
681cb97ff9dSPatrice Chotard if (priv->info.has_overdrive) {
682f264e235SPatrice Chotard err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
683f264e235SPatrice Chotard &args);
684f264e235SPatrice Chotard if (err) {
685f264e235SPatrice Chotard debug("%s: can't find syscon device (%d)\n", __func__,
686f264e235SPatrice Chotard err);
687f264e235SPatrice Chotard return err;
688f264e235SPatrice Chotard }
689f264e235SPatrice Chotard
690f264e235SPatrice Chotard priv->pwr_regs = (struct stm32_pwr_regs *)ofnode_get_addr(args.node);
691f264e235SPatrice Chotard }
692f264e235SPatrice Chotard
693f264e235SPatrice Chotard configure_clocks(dev);
694f264e235SPatrice Chotard
695f264e235SPatrice Chotard return 0;
696f264e235SPatrice Chotard }
697f264e235SPatrice Chotard
stm32_clk_of_xlate(struct clk * clk,struct ofnode_phandle_args * args)698f264e235SPatrice Chotard static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
699f264e235SPatrice Chotard {
700f264e235SPatrice Chotard debug("%s(clk=%p)\n", __func__, clk);
701f264e235SPatrice Chotard
702f264e235SPatrice Chotard if (args->args_count != 2) {
703f264e235SPatrice Chotard debug("Invaild args_count: %d\n", args->args_count);
704f264e235SPatrice Chotard return -EINVAL;
705f264e235SPatrice Chotard }
706f264e235SPatrice Chotard
707f264e235SPatrice Chotard if (args->args_count)
708f264e235SPatrice Chotard clk->id = args->args[1];
709f264e235SPatrice Chotard else
710f264e235SPatrice Chotard clk->id = 0;
711f264e235SPatrice Chotard
712f264e235SPatrice Chotard return 0;
713f264e235SPatrice Chotard }
714f264e235SPatrice Chotard
715f264e235SPatrice Chotard static struct clk_ops stm32_clk_ops = {
716f264e235SPatrice Chotard .of_xlate = stm32_clk_of_xlate,
717f264e235SPatrice Chotard .enable = stm32_clk_enable,
718f264e235SPatrice Chotard .get_rate = stm32_clk_get_rate,
71905e23dd4SPatrice Chotard .set_rate = stm32_set_rate,
720f264e235SPatrice Chotard };
721f264e235SPatrice Chotard
722f264e235SPatrice Chotard U_BOOT_DRIVER(stm32fx_clk) = {
723928954feSPatrice Chotard .name = "stm32fx_rcc_clock",
724f264e235SPatrice Chotard .id = UCLASS_CLK,
725f264e235SPatrice Chotard .ops = &stm32_clk_ops,
726f264e235SPatrice Chotard .probe = stm32_clk_probe,
727f264e235SPatrice Chotard .priv_auto_alloc_size = sizeof(struct stm32_clk),
728f264e235SPatrice Chotard .flags = DM_FLAG_PRE_RELOC,
729f264e235SPatrice Chotard };
730