xref: /openbmc/u-boot/drivers/clk/clk_stm32f.c (revision 651a70e8)
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(&regs->cr, RCC_CR_HSION);
134f264e235SPatrice Chotard 	writel(0, &regs->cfgr); /* Reset CFGR */
135f264e235SPatrice Chotard 	clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
1364e97e257SPatrice Chotard 		| RCC_CR_PLLON | RCC_CR_PLLSAION));
137f264e235SPatrice Chotard 	writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
138f264e235SPatrice Chotard 	clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
139f264e235SPatrice Chotard 	writel(0, &regs->cir); /* Disable all interrupts */
140f264e235SPatrice Chotard 
141f264e235SPatrice Chotard 	/* Configure for HSE+PLL operation */
142f264e235SPatrice Chotard 	setbits_le32(&regs->cr, RCC_CR_HSEON);
143f264e235SPatrice Chotard 	while (!(readl(&regs->cr) & RCC_CR_HSERDY))
144f264e235SPatrice Chotard 		;
145f264e235SPatrice Chotard 
146f264e235SPatrice Chotard 	setbits_le32(&regs->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(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
153f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
154cb97ff9dSPatrice Chotard 			sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
155f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
156cb97ff9dSPatrice Chotard 			sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
157f264e235SPatrice Chotard 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
158cb97ff9dSPatrice Chotard 			((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
159f264e235SPatrice Chotard 	clrsetbits_le32(&regs->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(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
1664e97e257SPatrice Chotard 
1674e97e257SPatrice Chotard 		/* select 48MHz as SDMMC1 clock source */
1684e97e257SPatrice Chotard 		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
1694e97e257SPatrice Chotard 
1704e97e257SPatrice Chotard 		/* select 48MHz as SDMMC2 clock source */
1714e97e257SPatrice Chotard 		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
1724e97e257SPatrice Chotard 	} else  { /* stm32f4 case */
173*651a70e8SPatrice Chotard 		/* select PLLQ as 48MHz clock source */
174*651a70e8SPatrice Chotard 		clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
1754e97e257SPatrice Chotard 
1764e97e257SPatrice Chotard 		/* select 48MHz as SDMMC1 clock source */
1774e97e257SPatrice Chotard 		clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
1784e97e257SPatrice Chotard 	}
1794e97e257SPatrice Chotard 
180*651a70e8SPatrice Chotard 	/* Enable the main PLL */
181*651a70e8SPatrice Chotard 	setbits_le32(&regs->cr, RCC_CR_PLLON);
182*651a70e8SPatrice Chotard 	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
1834e97e257SPatrice Chotard 		;
1844e97e257SPatrice Chotard 
185f264e235SPatrice Chotard 	setbits_le32(&regs->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(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
205f264e235SPatrice Chotard 	setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
206f264e235SPatrice Chotard 
207f264e235SPatrice Chotard 	while ((readl(&regs->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(&regs->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(&regs->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(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
2314e97e257SPatrice Chotard 	else
2324e97e257SPatrice Chotard 		pllsai = readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
2334e97e257SPatrice Chotard 
2344e97e257SPatrice Chotard 	if (pllsai) {
2354e97e257SPatrice Chotard 		/* PLL48CLK is selected from PLLSAI, get PLLSAI value */
2364e97e257SPatrice Chotard 		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
237526aa929SPatrice Chotard 		pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
2384e97e257SPatrice Chotard 			>> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
239526aa929SPatrice Chotard 		pllsaip = ((((readl(&regs->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(&regs->dckcfgr2);
25461803a95SPatrice Chotard 	else
25561803a95SPatrice Chotard 		val = readl(&regs->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(&regs->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(&regs->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(&regs->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(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
331f264e235SPatrice Chotard 			RCC_CFGR_SWS_PLL) {
332f264e235SPatrice Chotard 		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
333f264e235SPatrice Chotard 		plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
334f264e235SPatrice Chotard 			>> RCC_PLLCFGR_PLLN_SHIFT);
335f264e235SPatrice Chotard 		pllp = ((((readl(&regs->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(&regs->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(&regs->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(&regs->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