xref: /openbmc/u-boot/drivers/clk/clk_stm32f.c (revision c590e62d)
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(&regs->cr, RCC_CR_HSION);
153f264e235SPatrice Chotard 	writel(0, &regs->cfgr); /* Reset CFGR */
154f264e235SPatrice Chotard 	clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
1554e97e257SPatrice Chotard 		| RCC_CR_PLLON | RCC_CR_PLLSAION));
156f264e235SPatrice Chotard 	writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
157f264e235SPatrice Chotard 	clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
158f264e235SPatrice Chotard 	writel(0, &regs->cir); /* Disable all interrupts */
159f264e235SPatrice Chotard 
160f264e235SPatrice Chotard 	/* Configure for HSE+PLL operation */
161f264e235SPatrice Chotard 	setbits_le32(&regs->cr, RCC_CR_HSEON);
162f264e235SPatrice Chotard 	while (!(readl(&regs->cr) & RCC_CR_HSERDY))
163f264e235SPatrice Chotard 		;
164f264e235SPatrice Chotard 
165f264e235SPatrice Chotard 	setbits_le32(&regs->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(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
172f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
173cb97ff9dSPatrice Chotard 			sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
174f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
175cb97ff9dSPatrice Chotard 			sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
176f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
177cb97ff9dSPatrice Chotard 			((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
178f264e235SPatrice Chotard 	clrsetbits_le32(&regs->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(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
186*8b414645SPatrice Chotard 		else
187651a70e8SPatrice Chotard 			/* select PLLQ as 48MHz clock source */
188651a70e8SPatrice Chotard 			clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
1894e97e257SPatrice Chotard 
1904e97e257SPatrice Chotard 		/* select 48MHz as SDMMC1 clock source */
1914e97e257SPatrice Chotard 		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
1924e97e257SPatrice Chotard 
1934e97e257SPatrice Chotard 		/* select 48MHz as SDMMC2 clock source */
1944e97e257SPatrice Chotard 		clrbits_le32(&regs->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(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
199*8b414645SPatrice Chotard 		else
200651a70e8SPatrice Chotard 			/* select PLLQ as 48MHz clock source */
201651a70e8SPatrice Chotard 			clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
2024e97e257SPatrice Chotard 
2034e97e257SPatrice Chotard 		/* select 48MHz as SDMMC1 clock source */
2044e97e257SPatrice Chotard 		clrbits_le32(&regs->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(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIP_MASK,
212*8b414645SPatrice Chotard 			RCC_PLLSAICFGR_PLLSAIP_4);
213e8fb9ed2SPatrice Chotard 	clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
214e8fb9ed2SPatrice Chotard 			RCC_PLLSAICFGR_PLLSAIR_3);
215e8fb9ed2SPatrice Chotard 	clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK,
216e8fb9ed2SPatrice Chotard 			195 << RCC_PLLSAICFGR_PLLSAIN_SHIFT);
217e8fb9ed2SPatrice Chotard 
218e8fb9ed2SPatrice Chotard 	clrsetbits_le32(&regs->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(&regs->cr, RCC_CR_PLLON);
223651a70e8SPatrice Chotard 	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
2244e97e257SPatrice Chotard 		;
2254e97e257SPatrice Chotard 
226e8fb9ed2SPatrice Chotard 	/* Enable the SAI PLL */
227e8fb9ed2SPatrice Chotard 	setbits_le32(&regs->cr, RCC_CR_PLLSAION);
228e8fb9ed2SPatrice Chotard 	while (!(readl(&regs->cr) & RCC_CR_PLLSAIRDY))
229e8fb9ed2SPatrice Chotard 		;
230f264e235SPatrice Chotard 	setbits_le32(&regs->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(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
250f264e235SPatrice Chotard 	setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
251f264e235SPatrice Chotard 
252f264e235SPatrice Chotard 	while ((readl(&regs->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(&regs->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(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
2704e97e257SPatrice Chotard 	else
2714e97e257SPatrice Chotard 
2721038e033SPatrice Chotard 		return readl(&regs->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(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
281526aa929SPatrice Chotard 	pllsain = ((readl(&regs->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(&regs->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(&regs->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(&regs->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(&regs->dckcfgr2);
32461803a95SPatrice Chotard 	else
32561803a95SPatrice Chotard 		val = readl(&regs->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(&regs->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(&regs->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(&regs->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(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
404f264e235SPatrice Chotard 			RCC_CFGR_SWS_PLL) {
405f264e235SPatrice Chotard 		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
406f264e235SPatrice Chotard 		plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
407f264e235SPatrice Chotard 			>> RCC_PLLCFGR_PLLN_SHIFT);
408f264e235SPatrice Chotard 		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
409f264e235SPatrice Chotard 			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
4101038e033SPatrice Chotard 		pllq = ((readl(&regs->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(&regs->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(&regs->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(&regs->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(&regs->cr, RCC_CR_PLLSAION);
5765e993508SPatrice Chotard 
5775e993508SPatrice Chotard 	/* set pll_saidivr with found value */
5785e993508SPatrice Chotard 	clrsetbits_le32(&regs->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(&regs->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(&regs->cr, RCC_CR_PLLSAION);
5885e993508SPatrice Chotard 	while (!(readl(&regs->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(&regs->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