xref: /rk3399_ARM-atf/drivers/st/clk/clk-stm32mp2.c (revision 2d462888429ed8afaf202b12654466060e437a48)
1615f31feSGabriel Fernandez /*
2615f31feSGabriel Fernandez  * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
3615f31feSGabriel Fernandez  *
4615f31feSGabriel Fernandez  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5615f31feSGabriel Fernandez  */
6615f31feSGabriel Fernandez 
7615f31feSGabriel Fernandez #include <assert.h>
8615f31feSGabriel Fernandez #include <errno.h>
9615f31feSGabriel Fernandez #include <limits.h>
10615f31feSGabriel Fernandez #include <stdint.h>
11615f31feSGabriel Fernandez 
12615f31feSGabriel Fernandez #include "clk-stm32-core.h"
13615f31feSGabriel Fernandez #include <common/fdt_wrappers.h>
14615f31feSGabriel Fernandez #include <drivers/clk.h>
15615f31feSGabriel Fernandez #include <drivers/delay_timer.h>
16615f31feSGabriel Fernandez #include <drivers/generic_delay_timer.h>
17615f31feSGabriel Fernandez #include <drivers/st/stm32mp2_clk.h>
18615f31feSGabriel Fernandez #include <drivers/st/stm32mp_clkfunc.h>
19615f31feSGabriel Fernandez #include <lib/mmio.h>
20615f31feSGabriel Fernandez #include <lib/spinlock.h>
21615f31feSGabriel Fernandez #include <lib/utils_def.h>
22615f31feSGabriel Fernandez #include <libfdt.h>
23615f31feSGabriel Fernandez 
24615f31feSGabriel Fernandez #include <platform_def.h>
25615f31feSGabriel Fernandez 
26615f31feSGabriel Fernandez struct stm32_osci_dt_cfg {
27615f31feSGabriel Fernandez 	unsigned long freq;
28615f31feSGabriel Fernandez 	uint32_t drive;
29615f31feSGabriel Fernandez 	bool bypass;
30615f31feSGabriel Fernandez 	bool digbyp;
31615f31feSGabriel Fernandez 	bool css;
32615f31feSGabriel Fernandez };
33615f31feSGabriel Fernandez 
34615f31feSGabriel Fernandez struct stm32_pll_dt_cfg {
35615f31feSGabriel Fernandez 	uint32_t src;
36615f31feSGabriel Fernandez 	uint32_t frac;
37615f31feSGabriel Fernandez 	uint32_t cfg[PLLCFG_NB];
38615f31feSGabriel Fernandez 	uint32_t csg[PLLCSG_NB];
39615f31feSGabriel Fernandez 	bool csg_enabled;
40615f31feSGabriel Fernandez 	bool enabled;
41615f31feSGabriel Fernandez };
42615f31feSGabriel Fernandez 
43615f31feSGabriel Fernandez struct stm32_clk_platdata {
44615f31feSGabriel Fernandez 	uintptr_t rcc_base;
45615f31feSGabriel Fernandez 	uint32_t nosci;
46615f31feSGabriel Fernandez 	struct stm32_osci_dt_cfg *osci;
47615f31feSGabriel Fernandez 	uint32_t npll;
48615f31feSGabriel Fernandez 	struct stm32_pll_dt_cfg *pll;
49615f31feSGabriel Fernandez 	uint32_t nflexgen;
50615f31feSGabriel Fernandez 	uint32_t *flexgen;
51615f31feSGabriel Fernandez 	uint32_t nbusclk;
52615f31feSGabriel Fernandez 	uint32_t *busclk;
53615f31feSGabriel Fernandez 	uint32_t nkernelclk;
54615f31feSGabriel Fernandez 	uint32_t *kernelclk;
55615f31feSGabriel Fernandez };
56615f31feSGabriel Fernandez 
57615f31feSGabriel Fernandez /* A35 Sub-System which manages its own PLL (PLL1) */
58615f31feSGabriel Fernandez #define A35_SS_CHGCLKREQ	0x0000
59615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ1	0x0080
60615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ2	0x0090
61615f31feSGabriel Fernandez #define A35_SS_PLL_ENABLE	0x00a0
62615f31feSGabriel Fernandez 
63615f31feSGabriel Fernandez #define A35_SS_CHGCLKREQ_ARM_CHGCLKREQ		BIT(0)
64615f31feSGabriel Fernandez #define A35_SS_CHGCLKREQ_ARM_CHGCLKACK		BIT(1)
6540d0cebeSPatrick Delaunay #define A35_SS_CHGCLKREQ_ARM_DIVSEL		BIT(16)
6640d0cebeSPatrick Delaunay #define A35_SS_CHGCLKREQ_ARM_DIVSELACK		BIT(17)
67615f31feSGabriel Fernandez 
68615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ1_FBDIV_MASK		GENMASK(11, 0)
69615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ1_FBDIV_SHIFT		0
70615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ1_REFDIV_MASK		GENMASK(21, 16)
71615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ1_REFDIV_SHIFT		16
72615f31feSGabriel Fernandez 
73615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ2_POSTDIV1_MASK		GENMASK(2, 0)
74615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ2_POSTDIV1_SHIFT		0
75615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ2_POSTDIV2_MASK		GENMASK(5, 3)
76615f31feSGabriel Fernandez #define A35_SS_PLL_FREQ2_POSTDIV2_SHIFT		3
77615f31feSGabriel Fernandez 
78615f31feSGabriel Fernandez #define A35_SS_PLL_ENABLE_PD			BIT(0)
79615f31feSGabriel Fernandez #define A35_SS_PLL_ENABLE_LOCKP			BIT(1)
80615f31feSGabriel Fernandez #define A35_SS_PLL_ENABLE_NRESET_SWPLL_FF	BIT(2)
81615f31feSGabriel Fernandez 
82615f31feSGabriel Fernandez #define TIMEOUT_US_200MS	U(200000)
83615f31feSGabriel Fernandez #define TIMEOUT_US_1S		U(1000000)
84615f31feSGabriel Fernandez 
85615f31feSGabriel Fernandez #define PLLRDY_TIMEOUT		TIMEOUT_US_200MS
86615f31feSGabriel Fernandez #define CLKSRC_TIMEOUT		TIMEOUT_US_200MS
87615f31feSGabriel Fernandez #define CLKDIV_TIMEOUT		TIMEOUT_US_200MS
88615f31feSGabriel Fernandez #define OSCRDY_TIMEOUT		TIMEOUT_US_1S
89615f31feSGabriel Fernandez 
90615f31feSGabriel Fernandez /* PLL minimal frequencies for clock sources */
91615f31feSGabriel Fernandez #define PLL_REFCLK_MIN			UL(5000000)
92615f31feSGabriel Fernandez #define PLL_FRAC_REFCLK_MIN		UL(10000000)
93615f31feSGabriel Fernandez 
94615f31feSGabriel Fernandez #define XBAR_CHANNEL_NB			64
95615f31feSGabriel Fernandez 
96615f31feSGabriel Fernandez /* Warning, should be start to 1 */
97615f31feSGabriel Fernandez enum clock {
98615f31feSGabriel Fernandez 	_CK_0_MHZ,
99615f31feSGabriel Fernandez 
100615f31feSGabriel Fernandez 	/* ROOT CLOCKS */
101615f31feSGabriel Fernandez 	_CK_HSI,
102615f31feSGabriel Fernandez 	_CK_HSE,
103615f31feSGabriel Fernandez 	_CK_MSI,
104615f31feSGabriel Fernandez 	_CK_LSI,
105615f31feSGabriel Fernandez 	_CK_LSE,
106615f31feSGabriel Fernandez 	_I2SCKIN,
107615f31feSGabriel Fernandez 	_SPDIFSYMB,
108615f31feSGabriel Fernandez 	_CK_PLL1,
109615f31feSGabriel Fernandez 	_CK_PLL2,
110088238adSNicolas Le Bayon #if !STM32MP21
111615f31feSGabriel Fernandez 	_CK_PLL3,
112088238adSNicolas Le Bayon #endif /* !STM32MP21 */
113615f31feSGabriel Fernandez 	_CK_PLL4,
114615f31feSGabriel Fernandez 	_CK_PLL5,
115615f31feSGabriel Fernandez 	_CK_PLL6,
116615f31feSGabriel Fernandez 	_CK_PLL7,
117615f31feSGabriel Fernandez 	_CK_PLL8,
118615f31feSGabriel Fernandez 	_CK_HSE_RTC,
119615f31feSGabriel Fernandez 	_CK_RTCCK,
120615f31feSGabriel Fernandez 	_CK_ICN_HS_MCU,
121615f31feSGabriel Fernandez 	_CK_ICN_SDMMC,
122615f31feSGabriel Fernandez 	_CK_ICN_DDR,
123615f31feSGabriel Fernandez 	_CK_ICN_HSL,
124615f31feSGabriel Fernandez 	_CK_ICN_NIC,
125615f31feSGabriel Fernandez 	_CK_ICN_LS_MCU,
126615f31feSGabriel Fernandez 	_CK_FLEXGEN_07,
127615f31feSGabriel Fernandez 	_CK_FLEXGEN_08,
128615f31feSGabriel Fernandez 	_CK_FLEXGEN_09,
129615f31feSGabriel Fernandez 	_CK_FLEXGEN_10,
130615f31feSGabriel Fernandez 	_CK_FLEXGEN_11,
131615f31feSGabriel Fernandez 	_CK_FLEXGEN_12,
132615f31feSGabriel Fernandez 	_CK_FLEXGEN_13,
133615f31feSGabriel Fernandez 	_CK_FLEXGEN_14,
134615f31feSGabriel Fernandez 	_CK_FLEXGEN_15,
135615f31feSGabriel Fernandez 	_CK_FLEXGEN_16,
136615f31feSGabriel Fernandez 	_CK_FLEXGEN_17,
137615f31feSGabriel Fernandez 	_CK_FLEXGEN_18,
138615f31feSGabriel Fernandez 	_CK_FLEXGEN_19,
139615f31feSGabriel Fernandez 	_CK_FLEXGEN_20,
140615f31feSGabriel Fernandez 	_CK_FLEXGEN_21,
141615f31feSGabriel Fernandez 	_CK_FLEXGEN_22,
142615f31feSGabriel Fernandez 	_CK_FLEXGEN_23,
143615f31feSGabriel Fernandez 	_CK_FLEXGEN_24,
144615f31feSGabriel Fernandez 	_CK_FLEXGEN_25,
145615f31feSGabriel Fernandez 	_CK_FLEXGEN_26,
146615f31feSGabriel Fernandez 	_CK_FLEXGEN_27,
147615f31feSGabriel Fernandez 	_CK_FLEXGEN_28,
148615f31feSGabriel Fernandez 	_CK_FLEXGEN_29,
149615f31feSGabriel Fernandez 	_CK_FLEXGEN_30,
150615f31feSGabriel Fernandez 	_CK_FLEXGEN_31,
151615f31feSGabriel Fernandez 	_CK_FLEXGEN_32,
152615f31feSGabriel Fernandez 	_CK_FLEXGEN_33,
153615f31feSGabriel Fernandez 	_CK_FLEXGEN_34,
154615f31feSGabriel Fernandez 	_CK_FLEXGEN_35,
155615f31feSGabriel Fernandez 	_CK_FLEXGEN_36,
156615f31feSGabriel Fernandez 	_CK_FLEXGEN_37,
157615f31feSGabriel Fernandez 	_CK_FLEXGEN_38,
158615f31feSGabriel Fernandez 	_CK_FLEXGEN_39,
159615f31feSGabriel Fernandez 	_CK_FLEXGEN_40,
160615f31feSGabriel Fernandez 	_CK_FLEXGEN_41,
161615f31feSGabriel Fernandez 	_CK_FLEXGEN_42,
162615f31feSGabriel Fernandez 	_CK_FLEXGEN_43,
163615f31feSGabriel Fernandez 	_CK_FLEXGEN_44,
164615f31feSGabriel Fernandez 	_CK_FLEXGEN_45,
165615f31feSGabriel Fernandez 	_CK_FLEXGEN_46,
166615f31feSGabriel Fernandez 	_CK_FLEXGEN_47,
167615f31feSGabriel Fernandez 	_CK_FLEXGEN_48,
168615f31feSGabriel Fernandez 	_CK_FLEXGEN_49,
169615f31feSGabriel Fernandez 	_CK_FLEXGEN_50,
170615f31feSGabriel Fernandez 	_CK_FLEXGEN_51,
171615f31feSGabriel Fernandez 	_CK_FLEXGEN_52,
172615f31feSGabriel Fernandez 	_CK_FLEXGEN_53,
173615f31feSGabriel Fernandez 	_CK_FLEXGEN_54,
174615f31feSGabriel Fernandez 	_CK_FLEXGEN_55,
175615f31feSGabriel Fernandez 	_CK_FLEXGEN_56,
176615f31feSGabriel Fernandez 	_CK_FLEXGEN_57,
177615f31feSGabriel Fernandez 	_CK_FLEXGEN_58,
178615f31feSGabriel Fernandez 	_CK_FLEXGEN_59,
179615f31feSGabriel Fernandez 	_CK_FLEXGEN_60,
180615f31feSGabriel Fernandez 	_CK_FLEXGEN_61,
181615f31feSGabriel Fernandez 	_CK_FLEXGEN_62,
182615f31feSGabriel Fernandez 	_CK_FLEXGEN_63,
183615f31feSGabriel Fernandez 	_CK_ICN_APB1,
184615f31feSGabriel Fernandez 	_CK_ICN_APB2,
185615f31feSGabriel Fernandez 	_CK_ICN_APB3,
186615f31feSGabriel Fernandez 	_CK_ICN_APB4,
187088238adSNicolas Le Bayon #if STM32MP21
188088238adSNicolas Le Bayon 	_CK_ICN_APB5,
189088238adSNicolas Le Bayon #endif /* STM32MP21 */
190615f31feSGabriel Fernandez 	_CK_ICN_APBDBG,
191615f31feSGabriel Fernandez 	_CK_BKPSRAM,
192615f31feSGabriel Fernandez 	_CK_BSEC,
193615f31feSGabriel Fernandez 	_CK_CRC,
194615f31feSGabriel Fernandez 	_CK_CRYP1,
195615f31feSGabriel Fernandez 	_CK_CRYP2,
196615f31feSGabriel Fernandez 	_CK_DDR,
197615f31feSGabriel Fernandez 	_CK_DDRCAPB,
198615f31feSGabriel Fernandez 	_CK_DDRCP,
199615f31feSGabriel Fernandez 	_CK_DDRPHYC,
200615f31feSGabriel Fernandez 	_CK_FMC,
201615f31feSGabriel Fernandez 	_CK_GPIOA,
202615f31feSGabriel Fernandez 	_CK_GPIOB,
203615f31feSGabriel Fernandez 	_CK_GPIOC,
204615f31feSGabriel Fernandez 	_CK_GPIOD,
205615f31feSGabriel Fernandez 	_CK_GPIOE,
206615f31feSGabriel Fernandez 	_CK_GPIOF,
207615f31feSGabriel Fernandez 	_CK_GPIOG,
208615f31feSGabriel Fernandez 	_CK_GPIOH,
209615f31feSGabriel Fernandez 	_CK_GPIOI,
210088238adSNicolas Le Bayon #if !STM32MP21
211615f31feSGabriel Fernandez 	_CK_GPIOJ,
212615f31feSGabriel Fernandez 	_CK_GPIOK,
213088238adSNicolas Le Bayon #endif /* !STM32MP21 */
214615f31feSGabriel Fernandez 	_CK_GPIOZ,
215088238adSNicolas Le Bayon #if STM32MP21
216088238adSNicolas Le Bayon 	_CK_HASH1,
217088238adSNicolas Le Bayon 	_CK_HASH2,
218088238adSNicolas Le Bayon #else /* STM32MP21 */
219615f31feSGabriel Fernandez 	_CK_HASH,
220088238adSNicolas Le Bayon #endif /* STM32MP21 */
221615f31feSGabriel Fernandez 	_CK_I2C1,
222615f31feSGabriel Fernandez 	_CK_I2C2,
223088238adSNicolas Le Bayon #if !STM32MP23
224615f31feSGabriel Fernandez 	_CK_I2C3,
225088238adSNicolas Le Bayon #endif /* !STM32MP23 */
226088238adSNicolas Le Bayon #if STM32MP25
227615f31feSGabriel Fernandez 	_CK_I2C4,
228615f31feSGabriel Fernandez 	_CK_I2C5,
229615f31feSGabriel Fernandez 	_CK_I2C6,
230088238adSNicolas Le Bayon #endif /* STM32MP25 */
231088238adSNicolas Le Bayon #if !STM32MP21
232615f31feSGabriel Fernandez 	_CK_I2C7,
233615f31feSGabriel Fernandez 	_CK_I2C8,
234088238adSNicolas Le Bayon #endif /* !STM32MP21 */
235615f31feSGabriel Fernandez 	_CK_IWDG1,
236615f31feSGabriel Fernandez 	_CK_IWDG2,
237615f31feSGabriel Fernandez 	_CK_OSPI1,
238088238adSNicolas Le Bayon #if !STM32MP21
239615f31feSGabriel Fernandez 	_CK_OSPI2,
240615f31feSGabriel Fernandez 	_CK_OSPIIOM,
241088238adSNicolas Le Bayon #endif /* !STM32MP21 */
242615f31feSGabriel Fernandez 	_CK_PKA,
243615f31feSGabriel Fernandez 	_CK_RETRAM,
244088238adSNicolas Le Bayon #if STM32MP21
245088238adSNicolas Le Bayon 	_CK_RNG1,
246088238adSNicolas Le Bayon 	_CK_RNG2,
247088238adSNicolas Le Bayon #else /* STM32MP21 */
248615f31feSGabriel Fernandez 	_CK_RNG,
249088238adSNicolas Le Bayon #endif /* STM32MP21 */
250615f31feSGabriel Fernandez 	_CK_RTC,
251615f31feSGabriel Fernandez 	_CK_SAES,
252615f31feSGabriel Fernandez 	_CK_SDMMC1,
253615f31feSGabriel Fernandez 	_CK_SDMMC2,
254615f31feSGabriel Fernandez 	_CK_SRAM1,
255088238adSNicolas Le Bayon #if !STM32MP21
256615f31feSGabriel Fernandez 	_CK_SRAM2,
257088238adSNicolas Le Bayon #endif /* !STM32MP21 */
258615f31feSGabriel Fernandez 	_CK_STGEN,
259615f31feSGabriel Fernandez 	_CK_SYSCPU1,
260615f31feSGabriel Fernandez 	_CK_SYSRAM,
261615f31feSGabriel Fernandez 	_CK_UART4,
262615f31feSGabriel Fernandez 	_CK_UART5,
263615f31feSGabriel Fernandez 	_CK_UART7,
264088238adSNicolas Le Bayon #if STM32MP25
265615f31feSGabriel Fernandez 	_CK_UART8,
266615f31feSGabriel Fernandez 	_CK_UART9,
267088238adSNicolas Le Bayon #endif /* STM32MP25 */
268615f31feSGabriel Fernandez 	_CK_USART1,
269615f31feSGabriel Fernandez 	_CK_USART2,
270615f31feSGabriel Fernandez 	_CK_USART3,
271615f31feSGabriel Fernandez 	_CK_USART6,
272088238adSNicolas Le Bayon #if STM32MP21
273088238adSNicolas Le Bayon 	_CK_USBHEHCI,
274088238adSNicolas Le Bayon 	_CK_USBHOHCI,
275088238adSNicolas Le Bayon #else /* STM32MP21 */
276615f31feSGabriel Fernandez 	_CK_USB2EHCI,
277615f31feSGabriel Fernandez 	_CK_USB2OHCI,
278088238adSNicolas Le Bayon #endif /* STM32MP21 */
279615f31feSGabriel Fernandez 	_CK_USB2PHY1,
280615f31feSGabriel Fernandez 	_CK_USB2PHY2,
281088238adSNicolas Le Bayon #if !STM32MP21
282615f31feSGabriel Fernandez 	_CK_USB3DR,
283615f31feSGabriel Fernandez 	_CK_USB3PCIEPHY,
284615f31feSGabriel Fernandez 	_CK_USBTC,
285088238adSNicolas Le Bayon #endif /* !STM32MP21 */
2862a20f3e6SGabriel Fernandez 	_CK_BUS_RISAF4,
287615f31feSGabriel Fernandez 
288615f31feSGabriel Fernandez 	CK_LAST
289615f31feSGabriel Fernandez };
290615f31feSGabriel Fernandez 
291615f31feSGabriel Fernandez static const uint16_t muxsel_src[] = {
292615f31feSGabriel Fernandez 	_CK_HSI, _CK_HSE, _CK_MSI, _CK_0_MHZ
293615f31feSGabriel Fernandez };
294615f31feSGabriel Fernandez 
295615f31feSGabriel Fernandez static const uint16_t xbarsel_src[] = {
296615f31feSGabriel Fernandez 	_CK_PLL4, _CK_PLL5, _CK_PLL6, _CK_PLL7, _CK_PLL8,
297615f31feSGabriel Fernandez 	_CK_HSI, _CK_HSE, _CK_MSI, _CK_HSI, _CK_HSE, _CK_MSI,
298615f31feSGabriel Fernandez 	_SPDIFSYMB, _I2SCKIN, _CK_LSI, _CK_LSE
299615f31feSGabriel Fernandez };
300615f31feSGabriel Fernandez 
301615f31feSGabriel Fernandez static const uint16_t rtc_src[] = {
302615f31feSGabriel Fernandez 	_CK_0_MHZ, _CK_LSE, _CK_LSI, _CK_HSE_RTC
303615f31feSGabriel Fernandez };
304615f31feSGabriel Fernandez 
305615f31feSGabriel Fernandez static const uint16_t usb2phy1_src[] = {
306615f31feSGabriel Fernandez 	_CK_FLEXGEN_57, _CK_HSE
307615f31feSGabriel Fernandez };
308615f31feSGabriel Fernandez 
309615f31feSGabriel Fernandez static const uint16_t usb2phy2_src[] = {
310615f31feSGabriel Fernandez 	_CK_FLEXGEN_58, _CK_HSE
311615f31feSGabriel Fernandez };
312615f31feSGabriel Fernandez 
313088238adSNicolas Le Bayon #if !STM32MP21
314615f31feSGabriel Fernandez static const uint16_t usb3pciphy_src[] = {
315615f31feSGabriel Fernandez 	_CK_FLEXGEN_34, _CK_HSE
316615f31feSGabriel Fernandez };
317615f31feSGabriel Fernandez 
318615f31feSGabriel Fernandez static const uint16_t d3per_src[] = {
319615f31feSGabriel Fernandez 	_CK_MSI, _CK_LSI, _CK_LSE
320615f31feSGabriel Fernandez };
321088238adSNicolas Le Bayon #endif /* !STM32MP21 */
322615f31feSGabriel Fernandez 
323615f31feSGabriel Fernandez #define MUX_CONF(id, src, _offset, _shift, _witdh)[id] = {\
324615f31feSGabriel Fernandez 	.id_parents	= src,\
325615f31feSGabriel Fernandez 	.num_parents	= ARRAY_SIZE(src),\
326615f31feSGabriel Fernandez 	.mux		= &(struct mux_cfg) {\
327615f31feSGabriel Fernandez 		.offset	= (_offset),\
328615f31feSGabriel Fernandez 		.shift	= (_shift),\
329615f31feSGabriel Fernandez 		.width	= (_witdh),\
330615f31feSGabriel Fernandez 		.bitrdy = UINT8_MAX,\
331615f31feSGabriel Fernandez 	},\
332615f31feSGabriel Fernandez }
333615f31feSGabriel Fernandez 
334088238adSNicolas Le Bayon static const struct parent_cfg parent_mp2[] = {
335615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL0, muxsel_src, RCC_MUXSELCFGR, 0, 2),
336615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL1, muxsel_src, RCC_MUXSELCFGR, 4, 2),
337615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL2, muxsel_src, RCC_MUXSELCFGR, 8, 2),
338615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL3, muxsel_src, RCC_MUXSELCFGR, 12, 2),
339615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL4, muxsel_src, RCC_MUXSELCFGR, 16, 2),
340615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL5, muxsel_src, RCC_MUXSELCFGR, 20, 2),
341615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL6, muxsel_src, RCC_MUXSELCFGR, 24, 2),
342615f31feSGabriel Fernandez 	MUX_CONF(MUX_MUXSEL7, muxsel_src, RCC_MUXSELCFGR, 28, 2),
343615f31feSGabriel Fernandez 	MUX_CONF(MUX_XBARSEL, xbarsel_src, RCC_XBAR0CFGR, 0, 4),
344615f31feSGabriel Fernandez 	MUX_CONF(MUX_RTC, rtc_src, RCC_BDCR, 16, 2),
345615f31feSGabriel Fernandez 	MUX_CONF(MUX_USB2PHY1, usb2phy1_src, RCC_USB2PHY1CFGR, 15, 1),
346615f31feSGabriel Fernandez 	MUX_CONF(MUX_USB2PHY2, usb2phy2_src, RCC_USB2PHY2CFGR, 15, 1),
347088238adSNicolas Le Bayon #if !STM32MP21
348615f31feSGabriel Fernandez 	MUX_CONF(MUX_USB3PCIEPHY, usb3pciphy_src, RCC_USB3PCIEPHYCFGR, 15, 1),
349615f31feSGabriel Fernandez 	MUX_CONF(MUX_D3PER, d3per_src, RCC_D3DCR, 16, 2),
350088238adSNicolas Le Bayon #endif /* !STM32MP21 */
351615f31feSGabriel Fernandez };
352615f31feSGabriel Fernandez 
353615f31feSGabriel Fernandez /* GATES */
354615f31feSGabriel Fernandez enum enum_gate_cfg {
355615f31feSGabriel Fernandez 	GATE_ZERO, /* reserved for no gate */
356615f31feSGabriel Fernandez 	GATE_LSE,
357615f31feSGabriel Fernandez 	GATE_RTCCK,
358615f31feSGabriel Fernandez 	GATE_LSI,
359615f31feSGabriel Fernandez 	GATE_HSI,
360615f31feSGabriel Fernandez 	GATE_MSI,
361615f31feSGabriel Fernandez 	GATE_HSE,
362615f31feSGabriel Fernandez 	GATE_LSI_RDY,
363615f31feSGabriel Fernandez 	GATE_MSI_RDY,
364615f31feSGabriel Fernandez 	GATE_LSE_RDY,
365615f31feSGabriel Fernandez 	GATE_HSE_RDY,
366615f31feSGabriel Fernandez 	GATE_HSI_RDY,
367615f31feSGabriel Fernandez 	GATE_SYSRAM,
368615f31feSGabriel Fernandez 	GATE_RETRAM,
369615f31feSGabriel Fernandez 	GATE_SRAM1,
370088238adSNicolas Le Bayon #if !STM32MP21
371615f31feSGabriel Fernandez 	GATE_SRAM2,
372088238adSNicolas Le Bayon #endif /* !STM32MP21 */
373615f31feSGabriel Fernandez 
374615f31feSGabriel Fernandez 	GATE_DDRPHYC,
375615f31feSGabriel Fernandez 	GATE_SYSCPU1,
376615f31feSGabriel Fernandez 	GATE_CRC,
377088238adSNicolas Le Bayon #if !STM32MP21
378615f31feSGabriel Fernandez 	GATE_OSPIIOM,
379088238adSNicolas Le Bayon #endif /* !STM32MP21 */
380615f31feSGabriel Fernandez 	GATE_BKPSRAM,
381088238adSNicolas Le Bayon #if STM32MP21
382088238adSNicolas Le Bayon 	GATE_HASH1,
383088238adSNicolas Le Bayon 	GATE_HASH2,
384088238adSNicolas Le Bayon 	GATE_RNG1,
385088238adSNicolas Le Bayon 	GATE_RNG2,
386088238adSNicolas Le Bayon #else /* STM32MP21 */
387615f31feSGabriel Fernandez 	GATE_HASH,
388615f31feSGabriel Fernandez 	GATE_RNG,
389088238adSNicolas Le Bayon #endif /* STM32MP21 */
390615f31feSGabriel Fernandez 	GATE_CRYP1,
391615f31feSGabriel Fernandez 	GATE_CRYP2,
392615f31feSGabriel Fernandez 	GATE_SAES,
393615f31feSGabriel Fernandez 	GATE_PKA,
394615f31feSGabriel Fernandez 
395615f31feSGabriel Fernandez 	GATE_GPIOA,
396615f31feSGabriel Fernandez 	GATE_GPIOB,
397615f31feSGabriel Fernandez 	GATE_GPIOC,
398615f31feSGabriel Fernandez 	GATE_GPIOD,
399615f31feSGabriel Fernandez 	GATE_GPIOE,
400615f31feSGabriel Fernandez 	GATE_GPIOF,
401615f31feSGabriel Fernandez 	GATE_GPIOG,
402615f31feSGabriel Fernandez 	GATE_GPIOH,
403615f31feSGabriel Fernandez 	GATE_GPIOI,
404088238adSNicolas Le Bayon #if !STM32MP21
405615f31feSGabriel Fernandez 	GATE_GPIOJ,
406615f31feSGabriel Fernandez 	GATE_GPIOK,
407088238adSNicolas Le Bayon #endif /* !STM32MP21 */
408615f31feSGabriel Fernandez 	GATE_GPIOZ,
409615f31feSGabriel Fernandez 	GATE_RTC,
410615f31feSGabriel Fernandez 
411615f31feSGabriel Fernandez 	GATE_DDRCP,
412615f31feSGabriel Fernandez 
413615f31feSGabriel Fernandez 	/* WARNING 2 CLOCKS FOR ONE GATE */
414088238adSNicolas Le Bayon #if STM32MP21
415088238adSNicolas Le Bayon 	GATE_USBHOHCI,
416088238adSNicolas Le Bayon 	GATE_USBHEHCI,
417088238adSNicolas Le Bayon #else /* STM32MP21 */
418615f31feSGabriel Fernandez 	GATE_USB2OHCI,
419615f31feSGabriel Fernandez 	GATE_USB2EHCI,
420088238adSNicolas Le Bayon #endif /* STM32MP21 */
421615f31feSGabriel Fernandez 
422088238adSNicolas Le Bayon #if !STM32MP21
423615f31feSGabriel Fernandez 	GATE_USB3DR,
424088238adSNicolas Le Bayon #endif /* !STM32MP21 */
425615f31feSGabriel Fernandez 
426615f31feSGabriel Fernandez 	GATE_BSEC,
427615f31feSGabriel Fernandez 	GATE_IWDG1,
428615f31feSGabriel Fernandez 	GATE_IWDG2,
429615f31feSGabriel Fernandez 
430615f31feSGabriel Fernandez 	GATE_DDRCAPB,
431615f31feSGabriel Fernandez 	GATE_DDR,
432615f31feSGabriel Fernandez 
433615f31feSGabriel Fernandez 	GATE_USART2,
434615f31feSGabriel Fernandez 	GATE_UART4,
435615f31feSGabriel Fernandez 	GATE_USART3,
436615f31feSGabriel Fernandez 	GATE_UART5,
437615f31feSGabriel Fernandez 	GATE_I2C1,
438615f31feSGabriel Fernandez 	GATE_I2C2,
439088238adSNicolas Le Bayon #if !STM32MP23
440615f31feSGabriel Fernandez 	GATE_I2C3,
441088238adSNicolas Le Bayon #endif /* !STM32MP23 */
442088238adSNicolas Le Bayon #if STM32MP25
443615f31feSGabriel Fernandez 	GATE_I2C5,
444615f31feSGabriel Fernandez 	GATE_I2C4,
445615f31feSGabriel Fernandez 	GATE_I2C6,
446088238adSNicolas Le Bayon #endif /* STM32MP25 */
447088238adSNicolas Le Bayon #if !STM32MP21
448615f31feSGabriel Fernandez 	GATE_I2C7,
449088238adSNicolas Le Bayon #endif /* !STM32MP21 */
450615f31feSGabriel Fernandez 	GATE_USART1,
451615f31feSGabriel Fernandez 	GATE_USART6,
452615f31feSGabriel Fernandez 	GATE_UART7,
453088238adSNicolas Le Bayon #if STM32MP25
454615f31feSGabriel Fernandez 	GATE_UART8,
455615f31feSGabriel Fernandez 	GATE_UART9,
456088238adSNicolas Le Bayon #endif /* STM32MP25 */
457615f31feSGabriel Fernandez 	GATE_STGEN,
458088238adSNicolas Le Bayon #if !STM32MP21
459615f31feSGabriel Fernandez 	GATE_USB3PCIEPHY,
460615f31feSGabriel Fernandez 	GATE_USBTC,
461615f31feSGabriel Fernandez 	GATE_I2C8,
462088238adSNicolas Le Bayon #endif /* !STM32MP21 */
463615f31feSGabriel Fernandez 	GATE_OSPI1,
464088238adSNicolas Le Bayon #if !STM32MP21
465615f31feSGabriel Fernandez 	GATE_OSPI2,
466088238adSNicolas Le Bayon #endif /* !STM32MP21 */
467615f31feSGabriel Fernandez 	GATE_FMC,
468615f31feSGabriel Fernandez 	GATE_SDMMC1,
469615f31feSGabriel Fernandez 	GATE_SDMMC2,
470615f31feSGabriel Fernandez 	GATE_USB2PHY1,
471615f31feSGabriel Fernandez 	GATE_USB2PHY2,
472615f31feSGabriel Fernandez 	LAST_GATE
473615f31feSGabriel Fernandez };
474615f31feSGabriel Fernandez 
475615f31feSGabriel Fernandez #define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\
476615f31feSGabriel Fernandez 	.offset		= (_offset),\
477615f31feSGabriel Fernandez 	.bit_idx	= (_bit_idx),\
478615f31feSGabriel Fernandez 	.set_clr	= (_offset_clr),\
479615f31feSGabriel Fernandez }
480615f31feSGabriel Fernandez 
481088238adSNicolas Le Bayon static const struct gate_cfg gates_mp2[LAST_GATE] = {
482615f31feSGabriel Fernandez 	GATE_CFG(GATE_LSE,		RCC_BDCR,		0,	0),
483088238adSNicolas Le Bayon #if STM32MP21
484088238adSNicolas Le Bayon 	GATE_CFG(GATE_LSI,		RCC_LSICR,		0,	0),
485088238adSNicolas Le Bayon #else /* STM32MP21 */
486615f31feSGabriel Fernandez 	GATE_CFG(GATE_LSI,		RCC_BDCR,		9,	0),
487088238adSNicolas Le Bayon #endif /* STM32MP21 */
488615f31feSGabriel Fernandez 	GATE_CFG(GATE_RTCCK,		RCC_BDCR,		20,	0),
489615f31feSGabriel Fernandez 	GATE_CFG(GATE_HSI,		RCC_OCENSETR,		0,	1),
490615f31feSGabriel Fernandez 	GATE_CFG(GATE_HSE,		RCC_OCENSETR,		8,	1),
491088238adSNicolas Le Bayon #if STM32MP21
492088238adSNicolas Le Bayon 	GATE_CFG(GATE_MSI,		RCC_OCENSETR,		2,	0),
493088238adSNicolas Le Bayon #else /* STM32MP21 */
494615f31feSGabriel Fernandez 	GATE_CFG(GATE_MSI,		RCC_D3DCR,		0,	0),
495088238adSNicolas Le Bayon #endif /* STM32MP21 */
496615f31feSGabriel Fernandez 
497088238adSNicolas Le Bayon #if STM32MP21
498088238adSNicolas Le Bayon 	GATE_CFG(GATE_LSI_RDY,		RCC_LSICR,		1,	0),
499088238adSNicolas Le Bayon #else /* STM32MP21 */
500615f31feSGabriel Fernandez 	GATE_CFG(GATE_LSI_RDY,		RCC_BDCR,		10,	0),
501088238adSNicolas Le Bayon #endif /* STM32MP21 */
502615f31feSGabriel Fernandez 	GATE_CFG(GATE_LSE_RDY,		RCC_BDCR,		2,	0),
503088238adSNicolas Le Bayon #if STM32MP21
504088238adSNicolas Le Bayon 	GATE_CFG(GATE_MSI_RDY,		RCC_OCRDYR,		2,	0),
505088238adSNicolas Le Bayon #else /* STM32MP21 */
506615f31feSGabriel Fernandez 	GATE_CFG(GATE_MSI_RDY,		RCC_D3DCR,		2,	0),
507088238adSNicolas Le Bayon #endif /* STM32MP21 */
508615f31feSGabriel Fernandez 	GATE_CFG(GATE_HSE_RDY,		RCC_OCRDYR,		8,	0),
509615f31feSGabriel Fernandez 	GATE_CFG(GATE_HSI_RDY,		RCC_OCRDYR,		0,	0),
510615f31feSGabriel Fernandez 	GATE_CFG(GATE_SYSRAM,		RCC_SYSRAMCFGR,		1,	0),
511615f31feSGabriel Fernandez 	GATE_CFG(GATE_RETRAM,		RCC_RETRAMCFGR,		1,	0),
512615f31feSGabriel Fernandez 	GATE_CFG(GATE_SRAM1,		RCC_SRAM1CFGR,		1,	0),
513088238adSNicolas Le Bayon #if !STM32MP21
514615f31feSGabriel Fernandez 	GATE_CFG(GATE_SRAM2,		RCC_SRAM2CFGR,		1,	0),
515088238adSNicolas Le Bayon #endif /* !STM32MP21 */
516615f31feSGabriel Fernandez 	GATE_CFG(GATE_DDRPHYC,		RCC_DDRPHYCAPBCFGR,	1,	0),
517615f31feSGabriel Fernandez 	GATE_CFG(GATE_SYSCPU1,		RCC_SYSCPU1CFGR,	1,	0),
518615f31feSGabriel Fernandez 	GATE_CFG(GATE_CRC,		RCC_CRCCFGR,		1,	0),
519088238adSNicolas Le Bayon #if !STM32MP21
520615f31feSGabriel Fernandez 	GATE_CFG(GATE_OSPIIOM,		RCC_OSPIIOMCFGR,	1,	0),
521088238adSNicolas Le Bayon #endif /* !STM32MP21 */
522615f31feSGabriel Fernandez 	GATE_CFG(GATE_BKPSRAM,		RCC_BKPSRAMCFGR,	1,	0),
523088238adSNicolas Le Bayon #if STM32MP21
524088238adSNicolas Le Bayon 	GATE_CFG(GATE_HASH1,		RCC_HASH1CFGR,		1,	0),
525088238adSNicolas Le Bayon 	GATE_CFG(GATE_HASH2,		RCC_HASH2CFGR,		1,	0),
526088238adSNicolas Le Bayon 	GATE_CFG(GATE_RNG1,		RCC_RNG1CFGR,		1,	0),
527088238adSNicolas Le Bayon 	GATE_CFG(GATE_RNG2,		RCC_RNG2CFGR,		1,	0),
528088238adSNicolas Le Bayon #else /* STM32MP21 */
529615f31feSGabriel Fernandez 	GATE_CFG(GATE_HASH,		RCC_HASHCFGR,		1,	0),
530615f31feSGabriel Fernandez 	GATE_CFG(GATE_RNG,		RCC_RNGCFGR,		1,	0),
531088238adSNicolas Le Bayon #endif /* STM32MP21 */
532615f31feSGabriel Fernandez 	GATE_CFG(GATE_CRYP1,		RCC_CRYP1CFGR,		1,	0),
533615f31feSGabriel Fernandez 	GATE_CFG(GATE_CRYP2,		RCC_CRYP2CFGR,		1,	0),
534615f31feSGabriel Fernandez 	GATE_CFG(GATE_SAES,		RCC_SAESCFGR,		1,	0),
535615f31feSGabriel Fernandez 	GATE_CFG(GATE_PKA,		RCC_PKACFGR,		1,	0),
536615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOA,		RCC_GPIOACFGR,		1,	0),
537615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOB,		RCC_GPIOBCFGR,		1,	0),
538615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOC,		RCC_GPIOCCFGR,		1,	0),
539615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOD,		RCC_GPIODCFGR,		1,	0),
540615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOE,		RCC_GPIOECFGR,		1,	0),
541615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOF,		RCC_GPIOFCFGR,		1,	0),
542615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOG,		RCC_GPIOGCFGR,		1,	0),
543615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOH,		RCC_GPIOHCFGR,		1,	0),
544615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOI,		RCC_GPIOICFGR,		1,	0),
545088238adSNicolas Le Bayon #if !STM32MP21
546615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOJ,		RCC_GPIOJCFGR,		1,	0),
547615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOK,		RCC_GPIOKCFGR,		1,	0),
548088238adSNicolas Le Bayon #endif /* !STM32MP21 */
549615f31feSGabriel Fernandez 	GATE_CFG(GATE_GPIOZ,		RCC_GPIOZCFGR,		1,	0),
550615f31feSGabriel Fernandez 	GATE_CFG(GATE_RTC,		RCC_RTCCFGR,		1,	0),
551615f31feSGabriel Fernandez 	GATE_CFG(GATE_DDRCP,		RCC_DDRCPCFGR,		1,	0),
552615f31feSGabriel Fernandez 
553615f31feSGabriel Fernandez 	/* WARNING 2 CLOCKS FOR ONE GATE */
554088238adSNicolas Le Bayon #if STM32MP21
555088238adSNicolas Le Bayon 	GATE_CFG(GATE_USBHOHCI,		RCC_USBHCFGR,		1,	0),
556088238adSNicolas Le Bayon 	GATE_CFG(GATE_USBHEHCI,		RCC_USBHCFGR,		1,	0),
557088238adSNicolas Le Bayon #else /* STM32MP21 */
558615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB2OHCI,		RCC_USB2CFGR,		1,	0),
559615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB2EHCI,		RCC_USB2CFGR,		1,	0),
560615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB3DR,		RCC_USB3DRCFGR,		1,	0),
561088238adSNicolas Le Bayon #endif /* STM32MP21 */
562615f31feSGabriel Fernandez 	GATE_CFG(GATE_BSEC,		RCC_BSECCFGR,		1,	0),
563615f31feSGabriel Fernandez 	GATE_CFG(GATE_IWDG1,		RCC_IWDG1CFGR,		1,	0),
564615f31feSGabriel Fernandez 	GATE_CFG(GATE_IWDG2,		RCC_IWDG2CFGR,		1,	0),
565615f31feSGabriel Fernandez 	GATE_CFG(GATE_DDRCAPB,		RCC_DDRCAPBCFGR,	1,	0),
566615f31feSGabriel Fernandez 	GATE_CFG(GATE_DDR,		RCC_DDRCFGR,		1,	0),
567615f31feSGabriel Fernandez 	GATE_CFG(GATE_USART2,		RCC_USART2CFGR,		1,	0),
568615f31feSGabriel Fernandez 	GATE_CFG(GATE_UART4,		RCC_UART4CFGR,		1,	0),
569615f31feSGabriel Fernandez 	GATE_CFG(GATE_USART3,		RCC_USART3CFGR,		1,	0),
570615f31feSGabriel Fernandez 	GATE_CFG(GATE_UART5,		RCC_UART5CFGR,		1,	0),
571615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C1,		RCC_I2C1CFGR,		1,	0),
572615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C2,		RCC_I2C2CFGR,		1,	0),
573088238adSNicolas Le Bayon #if !STM32MP23
574615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C3,		RCC_I2C3CFGR,		1,	0),
575088238adSNicolas Le Bayon #endif /* !STM32MP23 */
576088238adSNicolas Le Bayon #if STM32MP25
577615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C5,		RCC_I2C5CFGR,		1,	0),
578615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C4,		RCC_I2C4CFGR,		1,	0),
579615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C6,		RCC_I2C6CFGR,		1,	0),
580088238adSNicolas Le Bayon #endif /* STM32MP25 */
581088238adSNicolas Le Bayon #if !STM32MP21
582615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C7,		RCC_I2C7CFGR,		1,	0),
583088238adSNicolas Le Bayon #endif /* !STM32MP21 */
584615f31feSGabriel Fernandez 	GATE_CFG(GATE_USART1,		RCC_USART1CFGR,		1,	0),
585615f31feSGabriel Fernandez 	GATE_CFG(GATE_USART6,		RCC_USART6CFGR,		1,	0),
586615f31feSGabriel Fernandez 	GATE_CFG(GATE_UART7,		RCC_UART7CFGR,		1,	0),
587088238adSNicolas Le Bayon #if STM32MP25
588615f31feSGabriel Fernandez 	GATE_CFG(GATE_UART8,		RCC_UART8CFGR,		1,	0),
589615f31feSGabriel Fernandez 	GATE_CFG(GATE_UART9,		RCC_UART9CFGR,		1,	0),
590088238adSNicolas Le Bayon #endif /* STM32MP25 */
591615f31feSGabriel Fernandez 	GATE_CFG(GATE_STGEN,		RCC_STGENCFGR,		1,	0),
592088238adSNicolas Le Bayon #if !STM32MP21
593615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB3PCIEPHY,	RCC_USB3PCIEPHYCFGR,	1,	0),
594*d3e47fb7SGabriel Fernandez 	GATE_CFG(GATE_USBTC,		RCC_UCPDCFGR,		1,	0),
595615f31feSGabriel Fernandez 	GATE_CFG(GATE_I2C8,		RCC_I2C8CFGR,		1,	0),
596088238adSNicolas Le Bayon #endif /* !STM32MP21 */
597615f31feSGabriel Fernandez 	GATE_CFG(GATE_OSPI1,		RCC_OSPI1CFGR,		1,	0),
598088238adSNicolas Le Bayon #if !STM32MP21
599615f31feSGabriel Fernandez 	GATE_CFG(GATE_OSPI2,		RCC_OSPI2CFGR,		1,	0),
600088238adSNicolas Le Bayon #endif /* !STM32MP21 */
601615f31feSGabriel Fernandez 	GATE_CFG(GATE_FMC,		RCC_FMCCFGR,		1,	0),
602615f31feSGabriel Fernandez 	GATE_CFG(GATE_SDMMC1,		RCC_SDMMC1CFGR,		1,	0),
603615f31feSGabriel Fernandez 	GATE_CFG(GATE_SDMMC2,		RCC_SDMMC2CFGR,		1,	0),
604615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB2PHY1,		RCC_USB2PHY1CFGR,	1,	0),
605615f31feSGabriel Fernandez 	GATE_CFG(GATE_USB2PHY2,		RCC_USB2PHY2CFGR,	1,	0),
606615f31feSGabriel Fernandez };
607615f31feSGabriel Fernandez 
608615f31feSGabriel Fernandez static const struct clk_div_table apb_div_table[] = {
609615f31feSGabriel Fernandez 	{ 0, 1 },  { 1, 2 },  { 2, 4 },  { 3, 8 }, { 4, 16 },
610615f31feSGabriel Fernandez 	{ 5, 16 }, { 6, 16 }, { 7, 16 }, { 0 },
611615f31feSGabriel Fernandez };
612615f31feSGabriel Fernandez 
613615f31feSGabriel Fernandez #undef DIV_CFG
614615f31feSGabriel Fernandez #define DIV_CFG(id, _offset, _shift, _width, _flags, _table, _bitrdy)[id] = {\
615615f31feSGabriel Fernandez 		.offset	= _offset,\
616615f31feSGabriel Fernandez 		.shift	= _shift,\
617615f31feSGabriel Fernandez 		.width	= _width,\
618615f31feSGabriel Fernandez 		.flags	= _flags,\
619615f31feSGabriel Fernandez 		.table	= _table,\
620615f31feSGabriel Fernandez 		.bitrdy	= _bitrdy,\
621615f31feSGabriel Fernandez }
622615f31feSGabriel Fernandez 
623088238adSNicolas Le Bayon static const struct div_cfg dividers_mp2[] = {
624615f31feSGabriel Fernandez 	DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, 31),
625615f31feSGabriel Fernandez 	DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, 31),
626615f31feSGabriel Fernandez 	DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, 31),
627615f31feSGabriel Fernandez 	DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, 31),
628088238adSNicolas Le Bayon #if STM32MP21
629088238adSNicolas Le Bayon 	DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, 31),
630088238adSNicolas Le Bayon #endif /* STM32MP21 */
631615f31feSGabriel Fernandez 	DIV_CFG(DIV_APBDBG, RCC_APBDBGDIVR, 0, 3, 0, apb_div_table, 31),
632615f31feSGabriel Fernandez 	DIV_CFG(DIV_LSMCU, RCC_LSMCUDIVR, 0, 1, 0, NULL, 31),
633615f31feSGabriel Fernandez 	DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, 0),
634615f31feSGabriel Fernandez };
635615f31feSGabriel Fernandez 
636615f31feSGabriel Fernandez enum stm32_osc {
637615f31feSGabriel Fernandez 	OSC_HSI,
638615f31feSGabriel Fernandez 	OSC_HSE,
639615f31feSGabriel Fernandez 	OSC_MSI,
640615f31feSGabriel Fernandez 	OSC_LSI,
641615f31feSGabriel Fernandez 	OSC_LSE,
642615f31feSGabriel Fernandez 	OSC_I2SCKIN,
643615f31feSGabriel Fernandez 	OSC_SPDIFSYMB,
644615f31feSGabriel Fernandez 	NB_OSCILLATOR
645615f31feSGabriel Fernandez };
646615f31feSGabriel Fernandez 
647088238adSNicolas Le Bayon static struct clk_oscillator_data stm32mp2_osc_data[] = {
648615f31feSGabriel Fernandez 	OSCILLATOR(OSC_HSI, _CK_HSI, "clk-hsi", GATE_HSI, GATE_HSI_RDY,
649615f31feSGabriel Fernandez 		   NULL, NULL, NULL),
650615f31feSGabriel Fernandez 
651615f31feSGabriel Fernandez 	OSCILLATOR(OSC_LSI, _CK_LSI, "clk-lsi", GATE_LSI, GATE_LSI_RDY,
652615f31feSGabriel Fernandez 		   NULL, NULL, NULL),
653615f31feSGabriel Fernandez 
654615f31feSGabriel Fernandez 	OSCILLATOR(OSC_MSI, _CK_MSI, "clk-msi", GATE_MSI, GATE_MSI_RDY,
655615f31feSGabriel Fernandez 		   NULL, NULL, NULL),
656615f31feSGabriel Fernandez 
657615f31feSGabriel Fernandez 	OSCILLATOR(OSC_HSE, _CK_HSE, "clk-hse", GATE_HSE, GATE_HSE_RDY,
658615f31feSGabriel Fernandez 		   BYPASS(RCC_OCENSETR, 10, 7),
659615f31feSGabriel Fernandez 		   CSS(RCC_OCENSETR, 11),
660615f31feSGabriel Fernandez 		   NULL),
661615f31feSGabriel Fernandez 
662615f31feSGabriel Fernandez 	OSCILLATOR(OSC_LSE, _CK_LSE, "clk-lse", GATE_LSE, GATE_LSE_RDY,
663615f31feSGabriel Fernandez 		   BYPASS(RCC_BDCR, 1, 3),
664615f31feSGabriel Fernandez 		   CSS(RCC_BDCR, 8),
665615f31feSGabriel Fernandez 		   DRIVE(RCC_BDCR, 4, 2, 2)),
666615f31feSGabriel Fernandez 
667615f31feSGabriel Fernandez 	OSCILLATOR(OSC_I2SCKIN, _I2SCKIN, "i2s_ckin", NO_GATE, NO_GATE,
668615f31feSGabriel Fernandez 		   NULL, NULL, NULL),
669615f31feSGabriel Fernandez 
670615f31feSGabriel Fernandez 	OSCILLATOR(OSC_SPDIFSYMB, _SPDIFSYMB, "spdif_symb", NO_GATE, NO_GATE,
671615f31feSGabriel Fernandez 		   NULL, NULL, NULL),
672615f31feSGabriel Fernandez };
673615f31feSGabriel Fernandez 
674615f31feSGabriel Fernandez #ifdef IMAGE_BL2
clk_stm32_get_oscillator_name(enum stm32_osc id)675615f31feSGabriel Fernandez static const char *clk_stm32_get_oscillator_name(enum stm32_osc id)
676615f31feSGabriel Fernandez {
677615f31feSGabriel Fernandez 	if (id < NB_OSCILLATOR) {
678088238adSNicolas Le Bayon 		return stm32mp2_osc_data[id].name;
679615f31feSGabriel Fernandez 	}
680615f31feSGabriel Fernandez 
681615f31feSGabriel Fernandez 	return NULL;
682615f31feSGabriel Fernandez }
683615f31feSGabriel Fernandez #endif
684615f31feSGabriel Fernandez 
685615f31feSGabriel Fernandez enum pll_id {
686615f31feSGabriel Fernandez 	_PLL1,
687615f31feSGabriel Fernandez 	_PLL2,
688615f31feSGabriel Fernandez 	_PLL3,
689615f31feSGabriel Fernandez 	_PLL4,
690615f31feSGabriel Fernandez 	_PLL5,
691615f31feSGabriel Fernandez 	_PLL6,
692615f31feSGabriel Fernandez 	_PLL7,
693615f31feSGabriel Fernandez 	_PLL8,
694615f31feSGabriel Fernandez 	_PLL_NB
695615f31feSGabriel Fernandez };
696615f31feSGabriel Fernandez 
697615f31feSGabriel Fernandez /* PLL configuration registers offsets from RCC_PLLxCFGR1 */
698615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR1		0x00
699615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR2		0x04
700615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR3		0x08
701615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR4		0x0C
702615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR5		0x10
703615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR6		0x18
704615f31feSGabriel Fernandez #define RCC_OFFSET_PLLXCFGR7		0x1C
705615f31feSGabriel Fernandez 
706615f31feSGabriel Fernandez struct stm32_clk_pll {
707615f31feSGabriel Fernandez 	uint16_t clk_id;
708615f31feSGabriel Fernandez 	uint16_t reg_pllxcfgr1;
709615f31feSGabriel Fernandez };
710615f31feSGabriel Fernandez 
711615f31feSGabriel Fernandez #define CLK_PLL_CFG(_idx, _clk_id, _reg)\
712615f31feSGabriel Fernandez 	[(_idx)] = {\
713615f31feSGabriel Fernandez 		.clk_id = (_clk_id),\
714615f31feSGabriel Fernandez 		.reg_pllxcfgr1 = (_reg),\
715615f31feSGabriel Fernandez 	}
716615f31feSGabriel Fernandez 
717088238adSNicolas Le Bayon static const struct stm32_clk_pll stm32mp2_clk_pll[_PLL_NB] = {
718615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL1, _CK_PLL1, A35_SS_CHGCLKREQ),
719615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL2, _CK_PLL2, RCC_PLL2CFGR1),
720088238adSNicolas Le Bayon #if !STM32MP21
721615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL3, _CK_PLL3, RCC_PLL3CFGR1),
722088238adSNicolas Le Bayon #endif /* !STM32MP21 */
723615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL4, _CK_PLL4, RCC_PLL4CFGR1),
724615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL5, _CK_PLL5, RCC_PLL5CFGR1),
725615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL6, _CK_PLL6, RCC_PLL6CFGR1),
726615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL7, _CK_PLL7, RCC_PLL7CFGR1),
727615f31feSGabriel Fernandez 	CLK_PLL_CFG(_PLL8, _CK_PLL8, RCC_PLL8CFGR1),
728615f31feSGabriel Fernandez };
729615f31feSGabriel Fernandez 
clk_stm32_pll_data(unsigned int idx)730615f31feSGabriel Fernandez static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx)
731615f31feSGabriel Fernandez {
732088238adSNicolas Le Bayon 	return &stm32mp2_clk_pll[idx];
733615f31feSGabriel Fernandez }
734615f31feSGabriel Fernandez 
clk_get_pll_fvco(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll,unsigned long prate)735615f31feSGabriel Fernandez static unsigned long clk_get_pll_fvco(struct stm32_clk_priv *priv,
736615f31feSGabriel Fernandez 				      const struct stm32_clk_pll *pll,
737615f31feSGabriel Fernandez 				      unsigned long prate)
738615f31feSGabriel Fernandez {
739615f31feSGabriel Fernandez 	unsigned long refclk, fvco;
740615f31feSGabriel Fernandez 	uint32_t fracin, fbdiv, refdiv;
741615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
742615f31feSGabriel Fernandez 	uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
743615f31feSGabriel Fernandez 	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
744615f31feSGabriel Fernandez 
745615f31feSGabriel Fernandez 	refclk = prate;
746615f31feSGabriel Fernandez 
747615f31feSGabriel Fernandez 	fracin = mmio_read_32(pllxcfgr3) & RCC_PLLxCFGR3_FRACIN_MASK;
748615f31feSGabriel Fernandez 	fbdiv = (mmio_read_32(pllxcfgr2) & RCC_PLLxCFGR2_FBDIV_MASK) >>
749615f31feSGabriel Fernandez 		RCC_PLLxCFGR2_FBDIV_SHIFT;
750615f31feSGabriel Fernandez 	refdiv = mmio_read_32(pllxcfgr2) & RCC_PLLxCFGR2_FREFDIV_MASK;
751615f31feSGabriel Fernandez 
752615f31feSGabriel Fernandez 	if (fracin != 0U) {
753615f31feSGabriel Fernandez 		uint64_t numerator, denominator;
754615f31feSGabriel Fernandez 
755615f31feSGabriel Fernandez 		numerator = ((uint64_t)fbdiv << 24) + fracin;
756615f31feSGabriel Fernandez 		numerator = refclk * numerator;
757615f31feSGabriel Fernandez 		denominator = (uint64_t)refdiv << 24;
758615f31feSGabriel Fernandez 		fvco = (unsigned long)(numerator / denominator);
759615f31feSGabriel Fernandez 	} else {
760615f31feSGabriel Fernandez 		fvco = (unsigned long)(refclk * fbdiv / refdiv);
761615f31feSGabriel Fernandez 	}
762615f31feSGabriel Fernandez 
763615f31feSGabriel Fernandez 	return fvco;
764615f31feSGabriel Fernandez }
765615f31feSGabriel Fernandez 
766615f31feSGabriel Fernandez struct stm32_pll_cfg {
767615f31feSGabriel Fernandez 	uint16_t pll_id;
768615f31feSGabriel Fernandez };
769615f31feSGabriel Fernandez 
_clk_stm32_pll_is_enabled(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)770615f31feSGabriel Fernandez static bool _clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
771615f31feSGabriel Fernandez {
772615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
773615f31feSGabriel Fernandez 
774615f31feSGabriel Fernandez 	return ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLEN) != 0U);
775615f31feSGabriel Fernandez }
776615f31feSGabriel Fernandez 
_clk_stm32_pll_set_on(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)777615f31feSGabriel Fernandez static void _clk_stm32_pll_set_on(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
778615f31feSGabriel Fernandez {
779615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
780615f31feSGabriel Fernandez 
781615f31feSGabriel Fernandez 	mmio_setbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
782615f31feSGabriel Fernandez }
783615f31feSGabriel Fernandez 
_clk_stm32_pll_set_off(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)784615f31feSGabriel Fernandez static void _clk_stm32_pll_set_off(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
785615f31feSGabriel Fernandez {
786615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
787615f31feSGabriel Fernandez 
788615f31feSGabriel Fernandez 	/* Stop PLL */
789615f31feSGabriel Fernandez 	mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
790615f31feSGabriel Fernandez }
791615f31feSGabriel Fernandez 
_clk_stm32_pll_wait_ready_on(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)792615f31feSGabriel Fernandez static int _clk_stm32_pll_wait_ready_on(struct stm32_clk_priv *priv,
793615f31feSGabriel Fernandez 					const struct stm32_clk_pll *pll)
794615f31feSGabriel Fernandez {
795615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
796615f31feSGabriel Fernandez 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
797615f31feSGabriel Fernandez 
798615f31feSGabriel Fernandez 	/* Wait PLL lock */
799615f31feSGabriel Fernandez 	while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLRDY) == 0U) {
800615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
801615f31feSGabriel Fernandez 			ERROR("PLL%d start failed @ 0x%x: 0x%x\n",
802615f31feSGabriel Fernandez 			      pll->clk_id - _CK_PLL1 + 1, pll->reg_pllxcfgr1,
803615f31feSGabriel Fernandez 			      mmio_read_32(pllxcfgr1));
804615f31feSGabriel Fernandez 			return -ETIMEDOUT;
805615f31feSGabriel Fernandez 		}
806615f31feSGabriel Fernandez 	}
807615f31feSGabriel Fernandez 
808615f31feSGabriel Fernandez 	return 0;
809615f31feSGabriel Fernandez }
810615f31feSGabriel Fernandez 
_clk_stm32_pll_wait_ready_off(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)811615f31feSGabriel Fernandez static int _clk_stm32_pll_wait_ready_off(struct stm32_clk_priv *priv,
812615f31feSGabriel Fernandez 					 const struct stm32_clk_pll *pll)
813615f31feSGabriel Fernandez {
814615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
815615f31feSGabriel Fernandez 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
816615f31feSGabriel Fernandez 
817615f31feSGabriel Fernandez 	/* Wait PLL stopped */
818615f31feSGabriel Fernandez 	while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLRDY) != 0U) {
819615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
820615f31feSGabriel Fernandez 			ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
821615f31feSGabriel Fernandez 			      pll->clk_id - _CK_PLL1 + 1, pllxcfgr1, mmio_read_32(pllxcfgr1));
822615f31feSGabriel Fernandez 			return -ETIMEDOUT;
823615f31feSGabriel Fernandez 		}
824615f31feSGabriel Fernandez 	}
825615f31feSGabriel Fernandez 
826615f31feSGabriel Fernandez 	return 0;
827615f31feSGabriel Fernandez }
828615f31feSGabriel Fernandez 
_clk_stm32_pll_enable(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)829615f31feSGabriel Fernandez static int _clk_stm32_pll_enable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
830615f31feSGabriel Fernandez {
831615f31feSGabriel Fernandez 	if (_clk_stm32_pll_is_enabled(priv, pll)) {
832615f31feSGabriel Fernandez 		return 0;
833615f31feSGabriel Fernandez 	}
834615f31feSGabriel Fernandez 
835615f31feSGabriel Fernandez 	_clk_stm32_pll_set_on(priv, pll);
836615f31feSGabriel Fernandez 
837615f31feSGabriel Fernandez 	return _clk_stm32_pll_wait_ready_on(priv, pll);
838615f31feSGabriel Fernandez }
839615f31feSGabriel Fernandez 
_clk_stm32_pll_disable(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)840615f31feSGabriel Fernandez static void _clk_stm32_pll_disable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
841615f31feSGabriel Fernandez {
842615f31feSGabriel Fernandez 	if (!_clk_stm32_pll_is_enabled(priv, pll)) {
843615f31feSGabriel Fernandez 		return;
844615f31feSGabriel Fernandez 	}
845615f31feSGabriel Fernandez 
846615f31feSGabriel Fernandez 	_clk_stm32_pll_set_off(priv, pll);
847615f31feSGabriel Fernandez 
848615f31feSGabriel Fernandez 	_clk_stm32_pll_wait_ready_off(priv, pll);
849615f31feSGabriel Fernandez }
850615f31feSGabriel Fernandez 
clk_stm32_pll_is_enabled(struct stm32_clk_priv * priv,int id)851615f31feSGabriel Fernandez static bool clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, int id)
852615f31feSGabriel Fernandez {
853615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
854615f31feSGabriel Fernandez 	struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
855615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
856615f31feSGabriel Fernandez 
857615f31feSGabriel Fernandez 	return _clk_stm32_pll_is_enabled(priv, pll);
858615f31feSGabriel Fernandez }
859615f31feSGabriel Fernandez 
clk_stm32_pll_enable(struct stm32_clk_priv * priv,int id)860615f31feSGabriel Fernandez static int clk_stm32_pll_enable(struct stm32_clk_priv *priv, int id)
861615f31feSGabriel Fernandez {
862615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
863615f31feSGabriel Fernandez 	struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
864615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
865615f31feSGabriel Fernandez 
866615f31feSGabriel Fernandez 	return _clk_stm32_pll_enable(priv, pll);
867615f31feSGabriel Fernandez }
868615f31feSGabriel Fernandez 
clk_stm32_pll_disable(struct stm32_clk_priv * priv,int id)869615f31feSGabriel Fernandez static void clk_stm32_pll_disable(struct stm32_clk_priv *priv, int id)
870615f31feSGabriel Fernandez {
871615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
872615f31feSGabriel Fernandez 	struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
873615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
874615f31feSGabriel Fernandez 
875615f31feSGabriel Fernandez 	_clk_stm32_pll_disable(priv, pll);
876615f31feSGabriel Fernandez }
877615f31feSGabriel Fernandez 
clk_stm32_pll_recalc_rate(struct stm32_clk_priv * priv,int id,unsigned long prate)878615f31feSGabriel Fernandez static unsigned long clk_stm32_pll_recalc_rate(struct stm32_clk_priv *priv, int id,
879615f31feSGabriel Fernandez 					       unsigned long prate)
880615f31feSGabriel Fernandez {
881615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
882615f31feSGabriel Fernandez 	struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
883615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
884615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
885615f31feSGabriel Fernandez 	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
886615f31feSGabriel Fernandez 	uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
887615f31feSGabriel Fernandez 	uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
888615f31feSGabriel Fernandez 	unsigned long dfout;
889615f31feSGabriel Fernandez 	uint32_t postdiv1, postdiv2;
890615f31feSGabriel Fernandez 
891615f31feSGabriel Fernandez 	postdiv1 = mmio_read_32(pllxcfgr6) & RCC_PLLxCFGR6_POSTDIV1_MASK;
892615f31feSGabriel Fernandez 	postdiv2 = mmio_read_32(pllxcfgr7) & RCC_PLLxCFGR7_POSTDIV2_MASK;
893615f31feSGabriel Fernandez 
894615f31feSGabriel Fernandez 	if ((mmio_read_32(pllxcfgr4) & RCC_PLLxCFGR4_BYPASS) != 0U) {
895615f31feSGabriel Fernandez 		dfout = prate;
896615f31feSGabriel Fernandez 	} else {
897615f31feSGabriel Fernandez 		if ((postdiv1 == 0U) || (postdiv2 == 0U)) {
898615f31feSGabriel Fernandez 			dfout = prate;
899615f31feSGabriel Fernandez 		} else {
900615f31feSGabriel Fernandez 			dfout = clk_get_pll_fvco(priv, pll, prate) / (postdiv1 * postdiv2);
901615f31feSGabriel Fernandez 		}
902615f31feSGabriel Fernandez 	}
903615f31feSGabriel Fernandez 
904615f31feSGabriel Fernandez 	return dfout;
905615f31feSGabriel Fernandez }
906615f31feSGabriel Fernandez 
907615f31feSGabriel Fernandez static const struct stm32_clk_ops clk_stm32_pll_ops = {
908615f31feSGabriel Fernandez 	.recalc_rate	= clk_stm32_pll_recalc_rate,
909615f31feSGabriel Fernandez 	.enable		= clk_stm32_pll_enable,
910615f31feSGabriel Fernandez 	.disable	= clk_stm32_pll_disable,
911615f31feSGabriel Fernandez 	.is_enabled	= clk_stm32_pll_is_enabled,
912615f31feSGabriel Fernandez };
913615f31feSGabriel Fernandez 
914615f31feSGabriel Fernandez #define CLK_PLL(idx, _idx, _parent, _pll_id, _flags)[idx] = {\
915615f31feSGabriel Fernandez 	.binding	= _idx,\
916615f31feSGabriel Fernandez 	.parent		= _parent,\
917615f31feSGabriel Fernandez 	.flags		= (_flags),\
918615f31feSGabriel Fernandez 	.clock_cfg	= &(struct stm32_pll_cfg) {\
919615f31feSGabriel Fernandez 		.pll_id	= _pll_id,\
920615f31feSGabriel Fernandez 	},\
921615f31feSGabriel Fernandez 	.ops		= STM32_PLL_OPS,\
922615f31feSGabriel Fernandez }
923615f31feSGabriel Fernandez 
clk_get_pll1_fvco(unsigned long refclk)924615f31feSGabriel Fernandez static unsigned long clk_get_pll1_fvco(unsigned long refclk)
925615f31feSGabriel Fernandez {
926615f31feSGabriel Fernandez 	uintptr_t pll_freq1_reg = A35SSC_BASE + A35_SS_PLL_FREQ1;
927615f31feSGabriel Fernandez 	uint32_t reg, fbdiv, refdiv;
928615f31feSGabriel Fernandez 
929615f31feSGabriel Fernandez 	reg = mmio_read_32(pll_freq1_reg);
930615f31feSGabriel Fernandez 
931615f31feSGabriel Fernandez 	fbdiv = (reg & A35_SS_PLL_FREQ1_FBDIV_MASK) >> A35_SS_PLL_FREQ1_FBDIV_SHIFT;
932615f31feSGabriel Fernandez 	refdiv = (reg & A35_SS_PLL_FREQ1_REFDIV_MASK) >> A35_SS_PLL_FREQ1_REFDIV_SHIFT;
933615f31feSGabriel Fernandez 
934615f31feSGabriel Fernandez 	return (unsigned long)(refclk * fbdiv / refdiv);
935615f31feSGabriel Fernandez }
936615f31feSGabriel Fernandez 
clk_stm32_pll1_recalc_rate(struct stm32_clk_priv * priv,int id,unsigned long prate)937615f31feSGabriel Fernandez static unsigned long clk_stm32_pll1_recalc_rate(struct stm32_clk_priv *priv,
938615f31feSGabriel Fernandez 						int id, unsigned long prate)
939615f31feSGabriel Fernandez {
940615f31feSGabriel Fernandez 	uintptr_t pll_freq2_reg = A35SSC_BASE + A35_SS_PLL_FREQ2;
941615f31feSGabriel Fernandez 	uint32_t postdiv1, postdiv2;
942615f31feSGabriel Fernandez 	unsigned long dfout;
943615f31feSGabriel Fernandez 
944615f31feSGabriel Fernandez 	postdiv1 = (mmio_read_32(pll_freq2_reg) & A35_SS_PLL_FREQ2_POSTDIV1_MASK) >>
945615f31feSGabriel Fernandez 		   A35_SS_PLL_FREQ2_POSTDIV1_SHIFT;
946615f31feSGabriel Fernandez 	postdiv2 = (mmio_read_32(pll_freq2_reg) & A35_SS_PLL_FREQ2_POSTDIV2_MASK) >>
947615f31feSGabriel Fernandez 		   A35_SS_PLL_FREQ2_POSTDIV2_SHIFT;
948615f31feSGabriel Fernandez 
949615f31feSGabriel Fernandez 	if ((postdiv1 == 0U) || (postdiv2 == 0U)) {
950615f31feSGabriel Fernandez 		dfout = prate;
951615f31feSGabriel Fernandez 	} else {
952615f31feSGabriel Fernandez 		dfout = clk_get_pll1_fvco(prate) / (postdiv1 * postdiv2);
953615f31feSGabriel Fernandez 	}
954615f31feSGabriel Fernandez 
955615f31feSGabriel Fernandez 	return dfout;
956615f31feSGabriel Fernandez }
957615f31feSGabriel Fernandez 
958615f31feSGabriel Fernandez static const struct stm32_clk_ops clk_stm32_pll1_ops = {
959615f31feSGabriel Fernandez 	.recalc_rate = clk_stm32_pll1_recalc_rate,
960615f31feSGabriel Fernandez };
961615f31feSGabriel Fernandez 
962615f31feSGabriel Fernandez #define CLK_PLL1(idx, _idx, _parent, _pll_id, _flags)[idx] = {\
963615f31feSGabriel Fernandez 	.binding	= _idx,\
964615f31feSGabriel Fernandez 	.parent		= _parent,\
965615f31feSGabriel Fernandez 	.flags		= (_flags),\
966615f31feSGabriel Fernandez 	.clock_cfg	= &(struct stm32_pll_cfg) {\
967615f31feSGabriel Fernandez 		.pll_id	= _pll_id,\
968615f31feSGabriel Fernandez 	},\
969615f31feSGabriel Fernandez 	.ops		= STM32_PLL1_OPS,\
970615f31feSGabriel Fernandez }
971615f31feSGabriel Fernandez 
972615f31feSGabriel Fernandez struct stm32_clk_flexgen_cfg {
973615f31feSGabriel Fernandez 	uint8_t id;
974615f31feSGabriel Fernandez };
975615f31feSGabriel Fernandez 
clk_flexgen_recalc(struct stm32_clk_priv * priv,int idx,unsigned long prate)976615f31feSGabriel Fernandez static unsigned long clk_flexgen_recalc(struct stm32_clk_priv *priv, int idx,
977615f31feSGabriel Fernandez 					unsigned long prate)
978615f31feSGabriel Fernandez {
979615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, idx);
980615f31feSGabriel Fernandez 	struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
981615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
982615f31feSGabriel Fernandez 	uint32_t prediv, findiv;
983615f31feSGabriel Fernandez 	uint8_t channel = cfg->id;
984615f31feSGabriel Fernandez 	unsigned long freq = prate;
985615f31feSGabriel Fernandez 
986615f31feSGabriel Fernandez 	prediv = mmio_read_32(rcc_base + RCC_PREDIV0CFGR + (0x4U * channel)) &
987615f31feSGabriel Fernandez 		RCC_PREDIVxCFGR_PREDIVx_MASK;
988615f31feSGabriel Fernandez 	findiv = mmio_read_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel)) &
989615f31feSGabriel Fernandez 		RCC_FINDIVxCFGR_FINDIVx_MASK;
990615f31feSGabriel Fernandez 
991615f31feSGabriel Fernandez 	if (freq == 0UL) {
992615f31feSGabriel Fernandez 		return 0U;
993615f31feSGabriel Fernandez 	}
994615f31feSGabriel Fernandez 
995615f31feSGabriel Fernandez 	switch (prediv) {
996615f31feSGabriel Fernandez 	case 0x0:
997615f31feSGabriel Fernandez 	case 0x1:
998615f31feSGabriel Fernandez 	case 0x3:
999615f31feSGabriel Fernandez 	case 0x3FF:
1000615f31feSGabriel Fernandez 		break;
1001615f31feSGabriel Fernandez 
1002615f31feSGabriel Fernandez 	default:
1003615f31feSGabriel Fernandez 		ERROR("Unsupported PREDIV value (%x)\n", prediv);
1004615f31feSGabriel Fernandez 		panic();
1005615f31feSGabriel Fernandez 		break;
1006615f31feSGabriel Fernandez 	}
1007615f31feSGabriel Fernandez 
1008615f31feSGabriel Fernandez 	freq /= (prediv + 1U);
1009615f31feSGabriel Fernandez 	freq /= (findiv + 1U);
1010615f31feSGabriel Fernandez 
1011615f31feSGabriel Fernandez 	return freq;
1012615f31feSGabriel Fernandez }
1013615f31feSGabriel Fernandez 
clk_flexgen_get_parent(struct stm32_clk_priv * priv,int idx)1014615f31feSGabriel Fernandez static int clk_flexgen_get_parent(struct stm32_clk_priv *priv, int idx)
1015615f31feSGabriel Fernandez {
1016615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, idx);
1017615f31feSGabriel Fernandez 	struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
1018615f31feSGabriel Fernandez 	uint32_t sel;
1019615f31feSGabriel Fernandez 	uint32_t address;
1020615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1021615f31feSGabriel Fernandez 
1022615f31feSGabriel Fernandez 	address = RCC_XBAR0CFGR + (cfg->id * 4);
1023615f31feSGabriel Fernandez 
1024615f31feSGabriel Fernandez 	sel = mmio_read_32(rcc_base + address) & RCC_XBARxCFGR_XBARxSEL_MASK;
1025615f31feSGabriel Fernandez 
1026615f31feSGabriel Fernandez 	return sel;
1027615f31feSGabriel Fernandez }
1028615f31feSGabriel Fernandez 
clk_flexgen_gate_enable(struct stm32_clk_priv * priv,int idx)1029615f31feSGabriel Fernandez static int clk_flexgen_gate_enable(struct stm32_clk_priv *priv, int idx)
1030615f31feSGabriel Fernandez {
1031615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, idx);
1032615f31feSGabriel Fernandez 	struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
1033615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1034615f31feSGabriel Fernandez 	uint8_t channel = cfg->id;
1035615f31feSGabriel Fernandez 
1036615f31feSGabriel Fernandez 	mmio_setbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
1037615f31feSGabriel Fernandez 			RCC_FINDIVxCFGR_FINDIVxEN);
1038615f31feSGabriel Fernandez 
1039615f31feSGabriel Fernandez 	return 0;
1040615f31feSGabriel Fernandez }
1041615f31feSGabriel Fernandez 
clk_flexgen_gate_disable(struct stm32_clk_priv * priv,int id)1042615f31feSGabriel Fernandez static void clk_flexgen_gate_disable(struct stm32_clk_priv *priv, int id)
1043615f31feSGabriel Fernandez {
1044615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
1045615f31feSGabriel Fernandez 	struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
1046615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1047615f31feSGabriel Fernandez 	uint8_t channel = cfg->id;
1048615f31feSGabriel Fernandez 
1049615f31feSGabriel Fernandez 	mmio_clrbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
1050615f31feSGabriel Fernandez 			RCC_FINDIVxCFGR_FINDIVxEN);
1051615f31feSGabriel Fernandez }
1052615f31feSGabriel Fernandez 
clk_flexgen_gate_is_enabled(struct stm32_clk_priv * priv,int id)1053615f31feSGabriel Fernandez static bool clk_flexgen_gate_is_enabled(struct stm32_clk_priv *priv, int id)
1054615f31feSGabriel Fernandez {
1055615f31feSGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
1056615f31feSGabriel Fernandez 	struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
1057615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1058615f31feSGabriel Fernandez 	uint8_t channel = cfg->id;
1059615f31feSGabriel Fernandez 
1060615f31feSGabriel Fernandez 	return !!(mmio_read_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel)) &
1061615f31feSGabriel Fernandez 		RCC_FINDIVxCFGR_FINDIVxEN);
1062615f31feSGabriel Fernandez }
1063615f31feSGabriel Fernandez 
1064615f31feSGabriel Fernandez static const struct stm32_clk_ops clk_stm32_flexgen_ops = {
1065615f31feSGabriel Fernandez 	.recalc_rate = clk_flexgen_recalc,
1066615f31feSGabriel Fernandez 	.get_parent = clk_flexgen_get_parent,
1067615f31feSGabriel Fernandez 	.enable = clk_flexgen_gate_enable,
1068615f31feSGabriel Fernandez 	.disable = clk_flexgen_gate_disable,
1069615f31feSGabriel Fernandez 	.is_enabled = clk_flexgen_gate_is_enabled,
1070615f31feSGabriel Fernandez };
1071615f31feSGabriel Fernandez 
1072615f31feSGabriel Fernandez #define FLEXGEN(idx, _idx, _flags, _id)[idx] = {\
1073615f31feSGabriel Fernandez 	.binding = _idx,\
1074615f31feSGabriel Fernandez 	.parent =  MUX(MUX_XBARSEL),\
1075615f31feSGabriel Fernandez 	.flags = (_flags),\
1076615f31feSGabriel Fernandez 	.clock_cfg	= &(struct stm32_clk_flexgen_cfg) {\
1077615f31feSGabriel Fernandez 		.id	= _id,\
1078615f31feSGabriel Fernandez 	},\
1079615f31feSGabriel Fernandez 	.ops = STM32_FLEXGEN_OPS,\
1080615f31feSGabriel Fernandez }
1081615f31feSGabriel Fernandez 
1082615f31feSGabriel Fernandez #define RCC_0_MHZ	UL(0)
1083615f31feSGabriel Fernandez #define RCC_4_MHZ	UL(4000000)
1084615f31feSGabriel Fernandez #define RCC_16_MHZ	UL(16000000)
1085615f31feSGabriel Fernandez 
1086615f31feSGabriel Fernandez #ifdef IMAGE_BL2
1087088238adSNicolas Le Bayon #if !STM32MP21
clk_stm32_osc_msi_set_rate(struct stm32_clk_priv * priv,int id,unsigned long rate,unsigned long prate)1088615f31feSGabriel Fernandez static int clk_stm32_osc_msi_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate,
1089615f31feSGabriel Fernandez 				      unsigned long prate)
1090615f31feSGabriel Fernandez {
1091615f31feSGabriel Fernandez 	uintptr_t address = priv->base + RCC_BDCR;
1092615f31feSGabriel Fernandez 	uint32_t mask = RCC_BDCR_MSIFREQSEL;
1093615f31feSGabriel Fernandez 	int ret = -1;
1094615f31feSGabriel Fernandez 
1095615f31feSGabriel Fernandez 	switch (rate) {
1096615f31feSGabriel Fernandez 	case RCC_4_MHZ:
1097615f31feSGabriel Fernandez 		mmio_clrbits_32(address, mask);
1098615f31feSGabriel Fernandez 		ret = 0;
1099615f31feSGabriel Fernandez 		break;
1100615f31feSGabriel Fernandez 
1101615f31feSGabriel Fernandez 	case RCC_16_MHZ:
1102615f31feSGabriel Fernandez 		mmio_setbits_32(address, mask);
1103615f31feSGabriel Fernandez 		ret = 0;
1104615f31feSGabriel Fernandez 		break;
1105615f31feSGabriel Fernandez 
1106615f31feSGabriel Fernandez 	default:
1107615f31feSGabriel Fernandez 		break;
1108615f31feSGabriel Fernandez 	}
1109615f31feSGabriel Fernandez 
1110615f31feSGabriel Fernandez 	return ret;
1111615f31feSGabriel Fernandez }
1112088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1113615f31feSGabriel Fernandez #endif /* IMAGE_BL2 */
1114615f31feSGabriel Fernandez 
clk_stm32_osc_msi_recalc_rate(struct stm32_clk_priv * priv,int id __unused,unsigned long prate __unused)1115615f31feSGabriel Fernandez static unsigned long clk_stm32_osc_msi_recalc_rate(struct stm32_clk_priv *priv,
1116615f31feSGabriel Fernandez 						   int id __unused,
1117615f31feSGabriel Fernandez 						   unsigned long prate __unused)
1118615f31feSGabriel Fernandez {
1119088238adSNicolas Le Bayon #if STM32MP21
1120088238adSNicolas Le Bayon 	return RCC_16_MHZ;
1121088238adSNicolas Le Bayon #else /* STM32MP21 */
1122615f31feSGabriel Fernandez 	uintptr_t address = priv->base + RCC_BDCR;
1123615f31feSGabriel Fernandez 
1124615f31feSGabriel Fernandez 	if ((mmio_read_32(address) & RCC_BDCR_MSIFREQSEL) == 0U) {
1125615f31feSGabriel Fernandez 		return RCC_4_MHZ;
1126615f31feSGabriel Fernandez 	} else {
1127615f31feSGabriel Fernandez 		return RCC_16_MHZ;
1128615f31feSGabriel Fernandez 	}
1129088238adSNicolas Le Bayon #endif /* STM32MP21 */
1130615f31feSGabriel Fernandez }
1131615f31feSGabriel Fernandez 
1132615f31feSGabriel Fernandez static const struct stm32_clk_ops clk_stm32_osc_msi_ops = {
1133615f31feSGabriel Fernandez 	.recalc_rate	= clk_stm32_osc_msi_recalc_rate,
1134615f31feSGabriel Fernandez 	.is_enabled	= clk_stm32_osc_gate_is_enabled,
1135615f31feSGabriel Fernandez 	.enable		= clk_stm32_osc_gate_enable,
1136615f31feSGabriel Fernandez 	.disable	= clk_stm32_osc_gate_disable,
1137615f31feSGabriel Fernandez 	.init		= clk_stm32_osc_init,
1138615f31feSGabriel Fernandez };
1139615f31feSGabriel Fernandez 
1140615f31feSGabriel Fernandez #define CLK_OSC_MSI(idx, _idx, _parent, _osc_id) \
1141615f31feSGabriel Fernandez 	[(idx)] = (struct clk_stm32){ \
1142615f31feSGabriel Fernandez 		.binding	= (_idx),\
1143615f31feSGabriel Fernandez 		.parent		= (_parent),\
1144615f31feSGabriel Fernandez 		.flags		= CLK_IS_CRITICAL,\
1145615f31feSGabriel Fernandez 		.clock_cfg	= &(struct stm32_osc_cfg){\
1146615f31feSGabriel Fernandez 			.osc_id = (_osc_id),\
1147615f31feSGabriel Fernandez 		},\
1148615f31feSGabriel Fernandez 		.ops		= STM32_OSC_MSI_OPS,\
1149615f31feSGabriel Fernandez 	}
1150615f31feSGabriel Fernandez 
1151615f31feSGabriel Fernandez static const struct stm32_clk_ops clk_stm32_rtc_ops = {
1152615f31feSGabriel Fernandez 	.enable = clk_stm32_gate_enable,
1153615f31feSGabriel Fernandez 	.disable = clk_stm32_gate_disable,
1154615f31feSGabriel Fernandez 	.is_enabled = clk_stm32_gate_is_enabled,
1155615f31feSGabriel Fernandez };
1156615f31feSGabriel Fernandez 
1157615f31feSGabriel Fernandez #define CLK_RTC(idx, _binding, _parent, _flags, _gate_id)[idx] = {\
1158615f31feSGabriel Fernandez 	.binding = (_binding),\
1159615f31feSGabriel Fernandez 	.parent =  (_parent),\
1160615f31feSGabriel Fernandez 	.flags = (_flags),\
1161615f31feSGabriel Fernandez 	.clock_cfg	= &(struct clk_stm32_gate_cfg) {\
1162615f31feSGabriel Fernandez 		.id	= (_gate_id),\
1163615f31feSGabriel Fernandez 	},\
1164615f31feSGabriel Fernandez 	.ops = STM32_RTC_OPS,\
1165615f31feSGabriel Fernandez }
1166615f31feSGabriel Fernandez 
1167615f31feSGabriel Fernandez enum {
1168615f31feSGabriel Fernandez 	STM32_PLL_OPS = STM32_LAST_OPS,
1169615f31feSGabriel Fernandez 	STM32_PLL1_OPS,
1170615f31feSGabriel Fernandez 	STM32_FLEXGEN_OPS,
1171615f31feSGabriel Fernandez 	STM32_OSC_MSI_OPS,
1172615f31feSGabriel Fernandez 	STM32_RTC_OPS,
1173615f31feSGabriel Fernandez 
1174088238adSNicolas Le Bayon 	MP2_LAST_OPS
1175615f31feSGabriel Fernandez };
1176615f31feSGabriel Fernandez 
1177088238adSNicolas Le Bayon static const struct stm32_clk_ops *ops_array_mp2[MP2_LAST_OPS] = {
1178615f31feSGabriel Fernandez 	[NO_OPS] =  NULL,
1179615f31feSGabriel Fernandez 	[FIXED_FACTOR_OPS] = &clk_fixed_factor_ops,
1180615f31feSGabriel Fernandez 	[GATE_OPS] = &clk_gate_ops,
1181615f31feSGabriel Fernandez 	[STM32_MUX_OPS] = &clk_mux_ops,
1182615f31feSGabriel Fernandez 	[STM32_DIVIDER_OPS] = &clk_stm32_divider_ops,
1183615f31feSGabriel Fernandez 	[STM32_GATE_OPS] = &clk_stm32_gate_ops,
1184615f31feSGabriel Fernandez 	[STM32_TIMER_OPS] = &clk_timer_ops,
1185615f31feSGabriel Fernandez 	[STM32_FIXED_RATE_OPS] = &clk_stm32_fixed_rate_ops,
1186615f31feSGabriel Fernandez 	[STM32_OSC_OPS] = &clk_stm32_osc_ops,
1187615f31feSGabriel Fernandez 	[STM32_OSC_NOGATE_OPS] = &clk_stm32_osc_nogate_ops,
1188615f31feSGabriel Fernandez 
1189615f31feSGabriel Fernandez 	[STM32_PLL_OPS] = &clk_stm32_pll_ops,
1190615f31feSGabriel Fernandez 	[STM32_PLL1_OPS] = &clk_stm32_pll1_ops,
1191615f31feSGabriel Fernandez 	[STM32_FLEXGEN_OPS] = &clk_stm32_flexgen_ops,
1192615f31feSGabriel Fernandez 	[STM32_OSC_MSI_OPS] = &clk_stm32_osc_msi_ops,
1193615f31feSGabriel Fernandez 	[STM32_RTC_OPS] = &clk_stm32_rtc_ops
1194615f31feSGabriel Fernandez };
1195615f31feSGabriel Fernandez 
1196088238adSNicolas Le Bayon static const struct clk_stm32 stm32mp2_clk[CK_LAST] = {
1197615f31feSGabriel Fernandez 	CLK_FIXED_RATE(_CK_0_MHZ, _NO_ID, RCC_0_MHZ),
1198615f31feSGabriel Fernandez 
1199615f31feSGabriel Fernandez 	/* ROOT CLOCKS */
1200615f31feSGabriel Fernandez 	CLK_OSC(_CK_HSE, HSE_CK, CLK_IS_ROOT, OSC_HSE),
1201615f31feSGabriel Fernandez 	CLK_OSC(_CK_LSE, LSE_CK, CLK_IS_ROOT, OSC_LSE),
1202615f31feSGabriel Fernandez 	CLK_OSC(_CK_HSI, HSI_CK, CLK_IS_ROOT, OSC_HSI),
1203615f31feSGabriel Fernandez 	CLK_OSC(_CK_LSI, LSI_CK, CLK_IS_ROOT, OSC_LSI),
1204615f31feSGabriel Fernandez 	CLK_OSC_MSI(_CK_MSI, MSI_CK, CLK_IS_ROOT, OSC_MSI),
1205615f31feSGabriel Fernandez 
1206615f31feSGabriel Fernandez 	CLK_OSC_FIXED(_I2SCKIN, _NO_ID, CLK_IS_ROOT, OSC_I2SCKIN),
1207615f31feSGabriel Fernandez 	CLK_OSC_FIXED(_SPDIFSYMB, _NO_ID, CLK_IS_ROOT, OSC_SPDIFSYMB),
1208615f31feSGabriel Fernandez 
1209615f31feSGabriel Fernandez 	STM32_DIV(_CK_HSE_RTC, _NO_ID, _CK_HSE, 0, DIV_RTC),
1210615f31feSGabriel Fernandez 
1211615f31feSGabriel Fernandez 	CLK_RTC(_CK_RTCCK, RTC_CK, MUX(MUX_RTC), 0, GATE_RTCCK),
1212615f31feSGabriel Fernandez 
1213615f31feSGabriel Fernandez 	CLK_PLL1(_CK_PLL1, PLL1_CK, MUX(MUX_MUXSEL5), _PLL1, 0),
1214615f31feSGabriel Fernandez 
1215615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL2, PLL2_CK, MUX(MUX_MUXSEL6), _PLL2, 0),
1216088238adSNicolas Le Bayon #if !STM32MP21
1217615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL3, PLL3_CK, MUX(MUX_MUXSEL7), _PLL3, 0),
1218088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1219615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL4, PLL4_CK, MUX(MUX_MUXSEL0), _PLL4, 0),
1220615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL5, PLL5_CK, MUX(MUX_MUXSEL1), _PLL5, 0),
1221615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL6, PLL6_CK, MUX(MUX_MUXSEL2), _PLL6, 0),
1222615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL7, PLL7_CK, MUX(MUX_MUXSEL3), _PLL7, 0),
1223615f31feSGabriel Fernandez 	CLK_PLL(_CK_PLL8, PLL8_CK, MUX(MUX_MUXSEL4), _PLL8, 0),
1224615f31feSGabriel Fernandez 
1225615f31feSGabriel Fernandez 	FLEXGEN(_CK_ICN_HS_MCU,	CK_ICN_HS_MCU, CLK_IS_CRITICAL, 0),
1226615f31feSGabriel Fernandez 	FLEXGEN(_CK_ICN_SDMMC, CK_ICN_SDMMC, CLK_IS_CRITICAL, 1),
1227615f31feSGabriel Fernandez 	FLEXGEN(_CK_ICN_DDR, CK_ICN_DDR, CLK_IS_CRITICAL, 2),
1228615f31feSGabriel Fernandez 	FLEXGEN(_CK_ICN_HSL, CK_ICN_HSL, CLK_IS_CRITICAL, 4),
1229615f31feSGabriel Fernandez 	FLEXGEN(_CK_ICN_NIC, CK_ICN_NIC, CLK_IS_CRITICAL, 5),
1230615f31feSGabriel Fernandez 
1231615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_LS_MCU, CK_ICN_LS_MCU, _CK_ICN_HS_MCU, 0, DIV_LSMCU),
1232615f31feSGabriel Fernandez 
1233615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_07, CK_FLEXGEN_07, 0, 7),
1234615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_08, CK_FLEXGEN_08, 0, 8),
1235615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_09, CK_FLEXGEN_09, 0, 9),
1236615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_10, CK_FLEXGEN_10, 0, 10),
1237615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_11, CK_FLEXGEN_11, 0, 11),
1238615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_12, CK_FLEXGEN_12, 0, 12),
1239615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_13, CK_FLEXGEN_13, 0, 13),
1240615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_14, CK_FLEXGEN_14, 0, 14),
1241615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_15, CK_FLEXGEN_15, 0, 15),
1242615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_16, CK_FLEXGEN_16, 0, 16),
1243615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_17, CK_FLEXGEN_17, 0, 17),
1244615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_18, CK_FLEXGEN_18, 0, 18),
1245615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_19, CK_FLEXGEN_19, 0, 19),
1246615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_20, CK_FLEXGEN_20, 0, 20),
1247615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_21, CK_FLEXGEN_21, 0, 21),
1248615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_22, CK_FLEXGEN_22, 0, 22),
1249615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_23, CK_FLEXGEN_23, 0, 23),
1250615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_24, CK_FLEXGEN_24, 0, 24),
1251615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_25, CK_FLEXGEN_25, 0, 25),
1252615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_26, CK_FLEXGEN_26, 0, 26),
1253615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_27, CK_FLEXGEN_27, 0, 27),
1254615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_28, CK_FLEXGEN_28, 0, 28),
1255615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_29, CK_FLEXGEN_29, 0, 29),
1256615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_30, CK_FLEXGEN_30, 0, 30),
1257615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_31, CK_FLEXGEN_31, 0, 31),
1258615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_32, CK_FLEXGEN_32, 0, 32),
1259615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_33, CK_FLEXGEN_33, 0, 33),
1260615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_34, CK_FLEXGEN_34, 0, 34),
1261615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_35, CK_FLEXGEN_35, 0, 35),
1262615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_36, CK_FLEXGEN_36, 0, 36),
1263615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_37, CK_FLEXGEN_37, 0, 37),
1264615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_38, CK_FLEXGEN_38, 0, 38),
1265615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_39, CK_FLEXGEN_39, 0, 39),
1266615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_40, CK_FLEXGEN_40, 0, 40),
1267615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_41, CK_FLEXGEN_41, 0, 41),
1268615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_42, CK_FLEXGEN_42, 0, 42),
1269615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_43, CK_FLEXGEN_43, 0, 43),
1270615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_44, CK_FLEXGEN_44, 0, 44),
1271615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_45, CK_FLEXGEN_45, 0, 45),
1272615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_46, CK_FLEXGEN_46, 0, 46),
1273615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_47, CK_FLEXGEN_47, 0, 47),
1274615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_48, CK_FLEXGEN_48, 0, 48),
1275615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_49, CK_FLEXGEN_49, 0, 49),
1276615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_50, CK_FLEXGEN_50, 0, 50),
1277615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_51, CK_FLEXGEN_51, 0, 51),
1278615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_52, CK_FLEXGEN_52, 0, 52),
1279615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_53, CK_FLEXGEN_53, 0, 53),
1280615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_54, CK_FLEXGEN_54, 0, 54),
1281615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_55, CK_FLEXGEN_55, 0, 55),
1282615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_56, CK_FLEXGEN_56, 0, 56),
1283615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_57, CK_FLEXGEN_57, 0, 57),
1284615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_58, CK_FLEXGEN_58, 0, 58),
1285615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_59, CK_FLEXGEN_59, 0, 59),
1286615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_60, CK_FLEXGEN_60, 0, 60),
1287615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_61, CK_FLEXGEN_61, 0, 61),
1288615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_62, CK_FLEXGEN_62, 0, 62),
1289615f31feSGabriel Fernandez 	FLEXGEN(_CK_FLEXGEN_63, CK_FLEXGEN_63, 0, 63),
1290615f31feSGabriel Fernandez 
1291615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_APB1, CK_ICN_APB1, _CK_ICN_LS_MCU, 0, DIV_APB1),
1292615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_APB2, CK_ICN_APB2, _CK_ICN_LS_MCU, 0, DIV_APB2),
1293615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_APB3, CK_ICN_APB3, _CK_ICN_LS_MCU, 0, DIV_APB3),
1294615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_APB4, CK_ICN_APB4, _CK_ICN_LS_MCU, 0, DIV_APB4),
1295088238adSNicolas Le Bayon #if STM32MP21
1296088238adSNicolas Le Bayon 	STM32_DIV(_CK_ICN_APB5, CK_ICN_APB5, _CK_ICN_LS_MCU, 0, DIV_APB5),
1297088238adSNicolas Le Bayon #endif /* STM32MP21 */
1298615f31feSGabriel Fernandez 	STM32_DIV(_CK_ICN_APBDBG, CK_ICN_APBDBG, _CK_ICN_LS_MCU, 0, DIV_APBDBG),
1299615f31feSGabriel Fernandez 
1300615f31feSGabriel Fernandez 	/* KERNEL CLOCK */
1301615f31feSGabriel Fernandez 	STM32_GATE(_CK_SYSRAM, CK_BUS_SYSRAM, _CK_ICN_HS_MCU, 0, GATE_SYSRAM),
1302615f31feSGabriel Fernandez 	STM32_GATE(_CK_RETRAM, CK_BUS_RETRAM, _CK_ICN_HS_MCU, 0, GATE_RETRAM),
1303615f31feSGabriel Fernandez 	STM32_GATE(_CK_SRAM1, CK_BUS_SRAM1, _CK_ICN_HS_MCU, CLK_IS_CRITICAL, GATE_SRAM1),
1304088238adSNicolas Le Bayon #if !STM32MP21
1305615f31feSGabriel Fernandez 	STM32_GATE(_CK_SRAM2, CK_BUS_SRAM2, _CK_ICN_HS_MCU, CLK_IS_CRITICAL, GATE_SRAM2),
1306088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1307615f31feSGabriel Fernandez 
1308615f31feSGabriel Fernandez 	STM32_GATE(_CK_DDRPHYC, CK_BUS_DDRPHYC, _CK_ICN_LS_MCU, 0, GATE_DDRPHYC),
1309615f31feSGabriel Fernandez 	STM32_GATE(_CK_SYSCPU1, CK_BUS_SYSCPU1, _CK_ICN_LS_MCU, 0, GATE_SYSCPU1),
1310615f31feSGabriel Fernandez 	STM32_GATE(_CK_CRC, CK_BUS_CRC, _CK_ICN_LS_MCU, 0, GATE_CRC),
1311088238adSNicolas Le Bayon #if !STM32MP21
1312615f31feSGabriel Fernandez 	STM32_GATE(_CK_OSPIIOM, CK_BUS_OSPIIOM, _CK_ICN_LS_MCU, 0, GATE_OSPIIOM),
1313088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1314615f31feSGabriel Fernandez 	STM32_GATE(_CK_BKPSRAM, CK_BUS_BKPSRAM, _CK_ICN_LS_MCU, 0, GATE_BKPSRAM),
1315088238adSNicolas Le Bayon #if STM32MP21
1316088238adSNicolas Le Bayon 	STM32_GATE(_CK_HASH1, CK_BUS_HASH1, _CK_ICN_LS_MCU, 0, GATE_HASH1),
1317088238adSNicolas Le Bayon 	STM32_GATE(_CK_HASH2, CK_BUS_HASH2, _CK_ICN_LS_MCU, 0, GATE_HASH2),
1318088238adSNicolas Le Bayon 	STM32_GATE(_CK_RNG1, CK_BUS_RNG1, _CK_ICN_LS_MCU, 0, GATE_RNG1),
1319088238adSNicolas Le Bayon 	STM32_GATE(_CK_RNG2, CK_BUS_RNG2, _CK_ICN_LS_MCU, 0, GATE_RNG2),
1320088238adSNicolas Le Bayon #else /* STM32MP21 */
1321615f31feSGabriel Fernandez 	STM32_GATE(_CK_HASH, CK_BUS_HASH, _CK_ICN_LS_MCU, 0, GATE_HASH),
1322615f31feSGabriel Fernandez 	STM32_GATE(_CK_RNG, CK_BUS_RNG, _CK_ICN_LS_MCU, 0, GATE_RNG),
1323088238adSNicolas Le Bayon #endif /* STM32MP21 */
1324615f31feSGabriel Fernandez 	STM32_GATE(_CK_CRYP1, CK_BUS_CRYP1, _CK_ICN_LS_MCU, 0, GATE_CRYP1),
1325615f31feSGabriel Fernandez 	STM32_GATE(_CK_CRYP2, CK_BUS_CRYP2, _CK_ICN_LS_MCU, 0, GATE_CRYP2),
1326615f31feSGabriel Fernandez 	STM32_GATE(_CK_SAES, CK_BUS_SAES, _CK_ICN_LS_MCU, 0, GATE_SAES),
1327615f31feSGabriel Fernandez 	STM32_GATE(_CK_PKA, CK_BUS_PKA, _CK_ICN_LS_MCU, 0, GATE_PKA),
1328615f31feSGabriel Fernandez 
1329615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOA, CK_BUS_GPIOA, _CK_ICN_LS_MCU, 0, GATE_GPIOA),
1330615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOB, CK_BUS_GPIOB, _CK_ICN_LS_MCU, 0, GATE_GPIOB),
1331615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOC, CK_BUS_GPIOC, _CK_ICN_LS_MCU, 0, GATE_GPIOC),
1332615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOD, CK_BUS_GPIOD, _CK_ICN_LS_MCU, 0, GATE_GPIOD),
1333615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOE, CK_BUS_GPIOE, _CK_ICN_LS_MCU, 0, GATE_GPIOE),
1334615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOF, CK_BUS_GPIOF, _CK_ICN_LS_MCU, 0, GATE_GPIOF),
1335615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOG, CK_BUS_GPIOG, _CK_ICN_LS_MCU, 0, GATE_GPIOG),
1336615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOH, CK_BUS_GPIOH, _CK_ICN_LS_MCU, 0, GATE_GPIOH),
1337615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOI, CK_BUS_GPIOI, _CK_ICN_LS_MCU, 0, GATE_GPIOI),
1338088238adSNicolas Le Bayon #if !STM32MP21
1339615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOJ, CK_BUS_GPIOJ, _CK_ICN_LS_MCU, 0, GATE_GPIOJ),
1340615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOK, CK_BUS_GPIOK, _CK_ICN_LS_MCU, 0, GATE_GPIOK),
1341088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1342615f31feSGabriel Fernandez 	STM32_GATE(_CK_GPIOZ, CK_BUS_GPIOZ, _CK_ICN_LS_MCU, 0, GATE_GPIOZ),
1343615f31feSGabriel Fernandez 	STM32_GATE(_CK_RTC, CK_BUS_RTC, _CK_ICN_LS_MCU, 0, GATE_RTC),
1344615f31feSGabriel Fernandez 
13452a20f3e6SGabriel Fernandez 	STM32_GATE(_CK_BUS_RISAF4, CK_BUS_RISAF4, _CK_ICN_LS_MCU, CLK_IS_CRITICAL, GATE_DDRCP),
13462a20f3e6SGabriel Fernandez 	STM32_GATE(_CK_DDRCP, CK_BUS_DDR, _CK_ICN_DDR, CLK_IS_CRITICAL, GATE_DDRCP),
1347615f31feSGabriel Fernandez 
1348615f31feSGabriel Fernandez 	/* WARNING 2 CLOCKS FOR ONE GATE */
1349088238adSNicolas Le Bayon #if STM32MP21
1350088238adSNicolas Le Bayon 	STM32_GATE(_CK_USBHOHCI, CK_BUS_USBHOHCI, _CK_ICN_HSL, 0, GATE_USBHOHCI),
1351088238adSNicolas Le Bayon 	STM32_GATE(_CK_USBHEHCI, CK_BUS_USBHEHCI, _CK_ICN_HSL, 0, GATE_USBHEHCI),
1352088238adSNicolas Le Bayon #else /* STM32MP21 */
1353615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB2OHCI, CK_BUS_USB2OHCI, _CK_ICN_HSL, 0, GATE_USB2OHCI),
1354615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB2EHCI, CK_BUS_USB2EHCI, _CK_ICN_HSL, 0, GATE_USB2EHCI),
1355088238adSNicolas Le Bayon #endif /* STM32MP21 */
1356615f31feSGabriel Fernandez 
1357088238adSNicolas Le Bayon #if !STM32MP21
1358615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB3DR, CK_BUS_USB3DR, _CK_ICN_HSL, 0, GATE_USB3DR),
1359088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1360615f31feSGabriel Fernandez 
1361615f31feSGabriel Fernandez 	STM32_GATE(_CK_BSEC, CK_BUS_BSEC, _CK_ICN_APB3, 0, GATE_BSEC),
1362615f31feSGabriel Fernandez 	STM32_GATE(_CK_IWDG1, CK_BUS_IWDG1, _CK_ICN_APB3, 0, GATE_IWDG1),
1363615f31feSGabriel Fernandez 	STM32_GATE(_CK_IWDG2, CK_BUS_IWDG2, _CK_ICN_APB3, 0, GATE_IWDG2),
1364615f31feSGabriel Fernandez 
1365615f31feSGabriel Fernandez 	STM32_GATE(_CK_DDRCAPB, CK_BUS_DDRC, _CK_ICN_APB4, 0, GATE_DDRCAPB),
1366615f31feSGabriel Fernandez 	STM32_GATE(_CK_DDR, CK_BUS_DDRCFG, _CK_ICN_APB4, 0, GATE_DDR),
1367615f31feSGabriel Fernandez 
1368615f31feSGabriel Fernandez 	STM32_GATE(_CK_USART2, CK_KER_USART2, _CK_FLEXGEN_08, 0, GATE_USART2),
1369615f31feSGabriel Fernandez 	STM32_GATE(_CK_UART4, CK_KER_UART4, _CK_FLEXGEN_08, 0, GATE_UART4),
1370615f31feSGabriel Fernandez 	STM32_GATE(_CK_USART3, CK_KER_USART3, _CK_FLEXGEN_09, 0, GATE_USART3),
1371615f31feSGabriel Fernandez 	STM32_GATE(_CK_UART5, CK_KER_UART5, _CK_FLEXGEN_09, 0, GATE_UART5),
1372088238adSNicolas Le Bayon #if STM32MP21
1373088238adSNicolas Le Bayon 	STM32_GATE(_CK_I2C1, CK_KER_I2C1, _CK_FLEXGEN_13, 0, GATE_I2C1),
1374088238adSNicolas Le Bayon 	STM32_GATE(_CK_I2C2, CK_KER_I2C2, _CK_FLEXGEN_13, 0, GATE_I2C2),
1375088238adSNicolas Le Bayon 	STM32_GATE(_CK_USART1, CK_KER_USART1, _CK_FLEXGEN_18, 0, GATE_USART1),
1376088238adSNicolas Le Bayon 	STM32_GATE(_CK_USART6, CK_KER_USART6, _CK_FLEXGEN_19, 0, GATE_USART6),
1377088238adSNicolas Le Bayon 	STM32_GATE(_CK_UART7, CK_KER_UART7, _CK_FLEXGEN_20, 0, GATE_UART7),
1378088238adSNicolas Le Bayon 	STM32_GATE(_CK_I2C3, CK_KER_I2C3, _CK_FLEXGEN_38, 0, GATE_I2C3),
1379088238adSNicolas Le Bayon #else /* STM32MP21 */
1380615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C1, CK_KER_I2C1, _CK_FLEXGEN_12, 0, GATE_I2C1),
1381615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C2, CK_KER_I2C2, _CK_FLEXGEN_12, 0, GATE_I2C2),
1382088238adSNicolas Le Bayon #if STM32MP25
1383615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C3, CK_KER_I2C3, _CK_FLEXGEN_13, 0, GATE_I2C3),
1384615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C5, CK_KER_I2C5, _CK_FLEXGEN_13, 0, GATE_I2C5),
1385615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C4, CK_KER_I2C4, _CK_FLEXGEN_14, 0, GATE_I2C4),
1386615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C6, CK_KER_I2C6, _CK_FLEXGEN_14, 0, GATE_I2C6),
1387088238adSNicolas Le Bayon #endif /* STM32MP25 */
1388615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C7, CK_KER_I2C7, _CK_FLEXGEN_15, 0, GATE_I2C7),
1389615f31feSGabriel Fernandez 	STM32_GATE(_CK_USART1, CK_KER_USART1, _CK_FLEXGEN_19, 0, GATE_USART1),
1390615f31feSGabriel Fernandez 	STM32_GATE(_CK_USART6, CK_KER_USART6, _CK_FLEXGEN_20, 0, GATE_USART6),
1391615f31feSGabriel Fernandez 	STM32_GATE(_CK_UART7, CK_KER_UART7, _CK_FLEXGEN_21, 0, GATE_UART7),
1392088238adSNicolas Le Bayon #if STM32MP25
1393615f31feSGabriel Fernandez 	STM32_GATE(_CK_UART8, CK_KER_UART8, _CK_FLEXGEN_21, 0, GATE_UART8),
1394615f31feSGabriel Fernandez 	STM32_GATE(_CK_UART9, CK_KER_UART9, _CK_FLEXGEN_22, 0, GATE_UART9),
1395088238adSNicolas Le Bayon #endif /* STM32MP25 */
1396088238adSNicolas Le Bayon #endif /* STM32MP21 */
1397615f31feSGabriel Fernandez 	STM32_GATE(_CK_STGEN, CK_KER_STGEN, _CK_FLEXGEN_33, 0, GATE_STGEN),
1398088238adSNicolas Le Bayon #if !STM32MP21
1399615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB3PCIEPHY, CK_KER_USB3PCIEPHY, _CK_FLEXGEN_34, 0, GATE_USB3PCIEPHY),
1400615f31feSGabriel Fernandez 	STM32_GATE(_CK_USBTC, CK_KER_USBTC, _CK_FLEXGEN_35, 0, GATE_USBTC),
1401615f31feSGabriel Fernandez 	STM32_GATE(_CK_I2C8, CK_KER_I2C8, _CK_FLEXGEN_38, 0, GATE_I2C8),
1402088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1403615f31feSGabriel Fernandez 	STM32_GATE(_CK_OSPI1, CK_KER_OSPI1, _CK_FLEXGEN_48, 0, GATE_OSPI1),
1404088238adSNicolas Le Bayon #if !STM32MP21
1405615f31feSGabriel Fernandez 	STM32_GATE(_CK_OSPI2, CK_KER_OSPI2, _CK_FLEXGEN_49, 0, GATE_OSPI2),
1406088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1407615f31feSGabriel Fernandez 	STM32_GATE(_CK_FMC, CK_KER_FMC, _CK_FLEXGEN_50, 0, GATE_FMC),
1408615f31feSGabriel Fernandez 	STM32_GATE(_CK_SDMMC1, CK_KER_SDMMC1, _CK_FLEXGEN_51, 0, GATE_SDMMC1),
1409615f31feSGabriel Fernandez 	STM32_GATE(_CK_SDMMC2, CK_KER_SDMMC2, _CK_FLEXGEN_52, 0, GATE_SDMMC2),
1410615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB2PHY1, CK_KER_USB2PHY1, _CK_FLEXGEN_57, 0, GATE_USB2PHY1),
1411615f31feSGabriel Fernandez 	STM32_GATE(_CK_USB2PHY2, CK_KER_USB2PHY2, _CK_FLEXGEN_58, 0, GATE_USB2PHY2),
1412615f31feSGabriel Fernandez };
1413615f31feSGabriel Fernandez 
1414615f31feSGabriel Fernandez enum clksrc_id {
1415615f31feSGabriel Fernandez 	CLKSRC_CA35SS,
1416615f31feSGabriel Fernandez 	CLKSRC_PLL1,
1417615f31feSGabriel Fernandez 	CLKSRC_PLL2,
1418088238adSNicolas Le Bayon #if !STM32MP21
1419615f31feSGabriel Fernandez 	CLKSRC_PLL3,
1420088238adSNicolas Le Bayon #endif /* !STM32MP21 */
1421615f31feSGabriel Fernandez 	CLKSRC_PLL4,
1422615f31feSGabriel Fernandez 	CLKSRC_PLL5,
1423615f31feSGabriel Fernandez 	CLKSRC_PLL6,
1424615f31feSGabriel Fernandez 	CLKSRC_PLL7,
1425615f31feSGabriel Fernandez 	CLKSRC_PLL8,
1426615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL0,
1427615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL1,
1428615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL2,
1429615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL3,
1430615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL4,
1431615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL5,
1432615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL6,
1433615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL7,
1434615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL8,
1435615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL9,
1436615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL10,
1437615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL11,
1438615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL12,
1439615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL13,
1440615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL14,
1441615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL15,
1442615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL16,
1443615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL17,
1444615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL18,
1445615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL19,
1446615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL20,
1447615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL21,
1448615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL22,
1449615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL23,
1450615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL24,
1451615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL25,
1452615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL26,
1453615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL27,
1454615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL28,
1455615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL29,
1456615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL30,
1457615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL31,
1458615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL32,
1459615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL33,
1460615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL34,
1461615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL35,
1462615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL36,
1463615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL37,
1464615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL38,
1465615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL39,
1466615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL40,
1467615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL41,
1468615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL42,
1469615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL43,
1470615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL44,
1471615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL45,
1472615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL46,
1473615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL47,
1474615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL48,
1475615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL49,
1476615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL50,
1477615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL51,
1478615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL52,
1479615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL53,
1480615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL54,
1481615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL55,
1482615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL56,
1483615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL57,
1484615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL58,
1485615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL59,
1486615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL60,
1487615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL61,
1488615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL62,
1489615f31feSGabriel Fernandez 	CLKSRC_XBAR_CHANNEL63,
1490615f31feSGabriel Fernandez 	CLKSRC_RTC,
1491615f31feSGabriel Fernandez 	CLKSRC_MCO1,
1492615f31feSGabriel Fernandez 	CLKSRC_MCO2,
1493615f31feSGabriel Fernandez 	CLKSRC_NB
1494615f31feSGabriel Fernandez };
1495615f31feSGabriel Fernandez 
stm32mp2_a35_ss_on_hsi(void)1496615f31feSGabriel Fernandez static void stm32mp2_a35_ss_on_hsi(void)
1497615f31feSGabriel Fernandez {
1498615f31feSGabriel Fernandez 	uintptr_t a35_ss_address = A35SSC_BASE;
1499615f31feSGabriel Fernandez 	uintptr_t chgclkreq_reg = a35_ss_address + A35_SS_CHGCLKREQ;
1500615f31feSGabriel Fernandez 	uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
150140d0cebeSPatrick Delaunay 	uint32_t chgclkreq;
1502615f31feSGabriel Fernandez 	uint64_t timeout;
1503615f31feSGabriel Fernandez 
150440d0cebeSPatrick Delaunay 	chgclkreq = mmio_read_32(chgclkreq_reg);
150540d0cebeSPatrick Delaunay 	if ((chgclkreq & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) == A35_SS_CHGCLKREQ_ARM_CHGCLKACK) {
1506615f31feSGabriel Fernandez 		/* Nothing to do, clock source is already set on bypass clock */
1507615f31feSGabriel Fernandez 		return;
1508615f31feSGabriel Fernandez 	}
1509615f31feSGabriel Fernandez 
151040d0cebeSPatrick Delaunay 	/* for clkext2f frequency at 400MHZ, default flexgen63 config, divider by 2 is required */
151140d0cebeSPatrick Delaunay 	if ((chgclkreq & A35_SS_CHGCLKREQ_ARM_DIVSEL) == A35_SS_CHGCLKREQ_ARM_DIVSEL) {
151240d0cebeSPatrick Delaunay 		mmio_clrbits_32(chgclkreq_reg, A35_SS_CHGCLKREQ_ARM_DIVSEL);
151340d0cebeSPatrick Delaunay 		timeout = timeout_init_us(CLKSRC_TIMEOUT);
151440d0cebeSPatrick Delaunay 		while ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_DIVSELACK) ==
151540d0cebeSPatrick Delaunay 		       A35_SS_CHGCLKREQ_ARM_DIVSELACK) {
151640d0cebeSPatrick Delaunay 			if (timeout_elapsed(timeout)) {
151740d0cebeSPatrick Delaunay 				EARLY_ERROR("Cannot set div on A35 bypass clock\n");
151840d0cebeSPatrick Delaunay 				panic();
151940d0cebeSPatrick Delaunay 			}
152040d0cebeSPatrick Delaunay 		}
152140d0cebeSPatrick Delaunay 	}
152240d0cebeSPatrick Delaunay 
1523615f31feSGabriel Fernandez 	mmio_setbits_32(chgclkreq_reg, A35_SS_CHGCLKREQ_ARM_CHGCLKREQ);
1524615f31feSGabriel Fernandez 
1525615f31feSGabriel Fernandez 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
1526615f31feSGabriel Fernandez 	while ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) !=
1527615f31feSGabriel Fernandez 	       A35_SS_CHGCLKREQ_ARM_CHGCLKACK) {
1528615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1529615f31feSGabriel Fernandez 			EARLY_ERROR("Cannot switch A35 to bypass clock\n");
1530615f31feSGabriel Fernandez 			panic();
1531615f31feSGabriel Fernandez 		}
1532615f31feSGabriel Fernandez 	}
1533615f31feSGabriel Fernandez 
1534615f31feSGabriel Fernandez 	mmio_clrbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_NRESET_SWPLL_FF);
1535615f31feSGabriel Fernandez }
1536615f31feSGabriel Fernandez 
1537615f31feSGabriel Fernandez #ifdef IMAGE_BL2
stm32mp2_clk_muxsel_on_hsi(struct stm32_clk_priv * priv)1538615f31feSGabriel Fernandez static void stm32mp2_clk_muxsel_on_hsi(struct stm32_clk_priv *priv)
1539615f31feSGabriel Fernandez {
1540615f31feSGabriel Fernandez 	mmio_clrbits_32(priv->base + RCC_MUXSELCFGR,
1541615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL0_MASK |
1542615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL1_MASK |
1543615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL2_MASK |
1544615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL3_MASK |
1545615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL4_MASK |
1546615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL5_MASK |
1547615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL6_MASK |
1548615f31feSGabriel Fernandez 			RCC_MUXSELCFGR_MUXSEL7_MASK);
1549615f31feSGabriel Fernandez }
1550615f31feSGabriel Fernandez 
stm32mp2_clk_xbar_on_hsi(struct stm32_clk_priv * priv)1551615f31feSGabriel Fernandez static void stm32mp2_clk_xbar_on_hsi(struct stm32_clk_priv *priv)
1552615f31feSGabriel Fernandez {
1553615f31feSGabriel Fernandez 	uintptr_t xbar0cfgr = priv->base + RCC_XBAR0CFGR;
1554615f31feSGabriel Fernandez 	uint32_t i;
1555615f31feSGabriel Fernandez 
1556615f31feSGabriel Fernandez 	for (i = 0; i < XBAR_CHANNEL_NB; i++) {
1557615f31feSGabriel Fernandez 		mmio_clrsetbits_32(xbar0cfgr + (0x4 * i),
1558615f31feSGabriel Fernandez 				   RCC_XBAR0CFGR_XBAR0SEL_MASK,
1559615f31feSGabriel Fernandez 				   XBAR_SRC_HSI);
1560615f31feSGabriel Fernandez 	}
1561615f31feSGabriel Fernandez }
1562615f31feSGabriel Fernandez 
stm32mp2_a35_pll1_start(void)1563615f31feSGabriel Fernandez static int stm32mp2_a35_pll1_start(void)
1564615f31feSGabriel Fernandez {
1565615f31feSGabriel Fernandez 	uintptr_t a35_ss_address = A35SSC_BASE;
1566615f31feSGabriel Fernandez 	uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
1567615f31feSGabriel Fernandez 	uintptr_t chgclkreq_reg = a35_ss_address + A35_SS_CHGCLKREQ;
1568615f31feSGabriel Fernandez 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
1569615f31feSGabriel Fernandez 
1570615f31feSGabriel Fernandez 	mmio_setbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_PD);
1571615f31feSGabriel Fernandez 
1572615f31feSGabriel Fernandez 	/* Wait PLL lock */
1573615f31feSGabriel Fernandez 	while ((mmio_read_32(pll_enable_reg) & A35_SS_PLL_ENABLE_LOCKP) == 0U) {
1574615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1575615f31feSGabriel Fernandez 			EARLY_ERROR("PLL1 start failed @ 0x%lx: 0x%x\n",
1576615f31feSGabriel Fernandez 				    pll_enable_reg, mmio_read_32(pll_enable_reg));
1577615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1578615f31feSGabriel Fernandez 		}
1579615f31feSGabriel Fernandez 	}
1580615f31feSGabriel Fernandez 
1581615f31feSGabriel Fernandez 	/* De-assert reset on PLL output clock path */
1582615f31feSGabriel Fernandez 	mmio_setbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_NRESET_SWPLL_FF);
1583615f31feSGabriel Fernandez 
1584615f31feSGabriel Fernandez 	/* Switch CPU clock to PLL clock */
1585615f31feSGabriel Fernandez 	mmio_clrbits_32(chgclkreq_reg, A35_SS_CHGCLKREQ_ARM_CHGCLKREQ);
1586615f31feSGabriel Fernandez 
1587615f31feSGabriel Fernandez 	/* Wait for clock change acknowledge */
1588615f31feSGabriel Fernandez 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
1589615f31feSGabriel Fernandez 	while ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) != 0U) {
1590615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1591615f31feSGabriel Fernandez 			EARLY_ERROR("CA35SS switch to PLL1 failed @ 0x%lx: 0x%x\n",
1592615f31feSGabriel Fernandez 				    chgclkreq_reg, mmio_read_32(chgclkreq_reg));
1593615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1594615f31feSGabriel Fernandez 		}
1595615f31feSGabriel Fernandez 	}
1596615f31feSGabriel Fernandez 
1597615f31feSGabriel Fernandez 	return 0;
1598615f31feSGabriel Fernandez }
1599615f31feSGabriel Fernandez 
stm32mp2_a35_pll1_config(uint32_t fbdiv,uint32_t refdiv,uint32_t postdiv1,uint32_t postdiv2)1600615f31feSGabriel Fernandez static void stm32mp2_a35_pll1_config(uint32_t fbdiv, uint32_t refdiv, uint32_t postdiv1,
1601615f31feSGabriel Fernandez 				     uint32_t postdiv2)
1602615f31feSGabriel Fernandez {
1603615f31feSGabriel Fernandez 	uintptr_t a35_ss_address = A35SSC_BASE;
1604615f31feSGabriel Fernandez 	uintptr_t pll_freq1_reg = a35_ss_address + A35_SS_PLL_FREQ1;
1605615f31feSGabriel Fernandez 	uintptr_t pll_freq2_reg = a35_ss_address + A35_SS_PLL_FREQ2;
1606615f31feSGabriel Fernandez 
1607615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pll_freq1_reg, A35_SS_PLL_FREQ1_REFDIV_MASK,
1608615f31feSGabriel Fernandez 			   (refdiv << A35_SS_PLL_FREQ1_REFDIV_SHIFT) &
1609615f31feSGabriel Fernandez 			   A35_SS_PLL_FREQ1_REFDIV_MASK);
1610615f31feSGabriel Fernandez 
1611615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pll_freq1_reg, A35_SS_PLL_FREQ1_FBDIV_MASK,
1612615f31feSGabriel Fernandez 			   (fbdiv << A35_SS_PLL_FREQ1_FBDIV_SHIFT) &
1613615f31feSGabriel Fernandez 			   A35_SS_PLL_FREQ1_FBDIV_MASK);
1614615f31feSGabriel Fernandez 
1615615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pll_freq2_reg, A35_SS_PLL_FREQ2_POSTDIV1_MASK,
1616615f31feSGabriel Fernandez 			   (postdiv1 << A35_SS_PLL_FREQ2_POSTDIV1_SHIFT) &
1617615f31feSGabriel Fernandez 			   A35_SS_PLL_FREQ2_POSTDIV1_MASK);
1618615f31feSGabriel Fernandez 
1619615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pll_freq2_reg, A35_SS_PLL_FREQ2_POSTDIV2_MASK,
1620615f31feSGabriel Fernandez 			   (postdiv2 << A35_SS_PLL_FREQ2_POSTDIV2_SHIFT) &
1621615f31feSGabriel Fernandez 			   A35_SS_PLL_FREQ2_POSTDIV2_MASK);
1622615f31feSGabriel Fernandez }
1623615f31feSGabriel Fernandez 
clk_stm32_pll_config_output(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll,uint32_t * pllcfg,uint32_t fracv)1624615f31feSGabriel Fernandez static int clk_stm32_pll_config_output(struct stm32_clk_priv *priv,
1625615f31feSGabriel Fernandez 				       const struct stm32_clk_pll *pll,
1626615f31feSGabriel Fernandez 				       uint32_t *pllcfg,
1627615f31feSGabriel Fernandez 				       uint32_t fracv)
1628615f31feSGabriel Fernandez {
1629615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
1630615f31feSGabriel Fernandez 	uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
1631615f31feSGabriel Fernandez 	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
1632615f31feSGabriel Fernandez 	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
1633615f31feSGabriel Fernandez 	uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
1634615f31feSGabriel Fernandez 	uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
1635615f31feSGabriel Fernandez 	unsigned long refclk;
1636615f31feSGabriel Fernandez 
1637615f31feSGabriel Fernandez 	refclk = _clk_stm32_get_parent_rate(priv, pll->clk_id);
1638615f31feSGabriel Fernandez 
1639615f31feSGabriel Fernandez 	if (fracv == 0U) {
1640615f31feSGabriel Fernandez 		/* PLL in integer mode */
1641615f31feSGabriel Fernandez 
1642615f31feSGabriel Fernandez 		/*
1643615f31feSGabriel Fernandez 		 * No need to check max clock, as oscillator reference clocks
1644615f31feSGabriel Fernandez 		 * will always be less than 1.2GHz
1645615f31feSGabriel Fernandez 		 */
1646615f31feSGabriel Fernandez 		if (refclk < PLL_REFCLK_MIN) {
1647615f31feSGabriel Fernandez 			panic();
1648615f31feSGabriel Fernandez 		}
1649615f31feSGabriel Fernandez 
1650615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK);
1651615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
1652615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
1653615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
1654615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
1655615f31feSGabriel Fernandez 	} else {
1656615f31feSGabriel Fernandez 		/* PLL in frac mode */
1657615f31feSGabriel Fernandez 
1658615f31feSGabriel Fernandez 		/*
1659615f31feSGabriel Fernandez 		 * No need to check max clock, as oscillator reference clocks
1660615f31feSGabriel Fernandez 		 * will always be less than 1.2GHz
1661615f31feSGabriel Fernandez 		 */
1662615f31feSGabriel Fernandez 		if (refclk < PLL_FRAC_REFCLK_MIN) {
1663615f31feSGabriel Fernandez 			panic();
1664615f31feSGabriel Fernandez 		}
1665615f31feSGabriel Fernandez 
1666615f31feSGabriel Fernandez 		mmio_clrsetbits_32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK,
1667615f31feSGabriel Fernandez 				   fracv & RCC_PLLxCFGR3_FRACIN_MASK);
1668615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
1669615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
1670615f31feSGabriel Fernandez 	}
1671615f31feSGabriel Fernandez 
1672615f31feSGabriel Fernandez 	assert(pllcfg[REFDIV] != 0U);
1673615f31feSGabriel Fernandez 
1674615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr2, RCC_PLLxCFGR2_FBDIV_MASK,
1675615f31feSGabriel Fernandez 			   (pllcfg[FBDIV] << RCC_PLLxCFGR2_FBDIV_SHIFT) &
1676615f31feSGabriel Fernandez 			   RCC_PLLxCFGR2_FBDIV_MASK);
1677615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr2, RCC_PLLxCFGR2_FREFDIV_MASK,
1678615f31feSGabriel Fernandez 			   pllcfg[REFDIV] & RCC_PLLxCFGR2_FREFDIV_MASK);
1679615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr6, RCC_PLLxCFGR6_POSTDIV1_MASK,
1680615f31feSGabriel Fernandez 			   pllcfg[POSTDIV1] & RCC_PLLxCFGR6_POSTDIV1_MASK);
1681615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr7, RCC_PLLxCFGR7_POSTDIV2_MASK,
1682615f31feSGabriel Fernandez 			   pllcfg[POSTDIV2] & RCC_PLLxCFGR7_POSTDIV2_MASK);
1683615f31feSGabriel Fernandez 
1684615f31feSGabriel Fernandez 	if ((pllcfg[POSTDIV1] == 0U) || (pllcfg[POSTDIV2] == 0U)) {
1685615f31feSGabriel Fernandez 		/* Bypass mode */
1686615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
1687615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
1688615f31feSGabriel Fernandez 	} else {
1689615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
1690615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
1691615f31feSGabriel Fernandez 	}
1692615f31feSGabriel Fernandez 
1693615f31feSGabriel Fernandez 	return 0;
1694615f31feSGabriel Fernandez }
1695615f31feSGabriel Fernandez 
clk_stm32_pll_config_csg(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll,uint32_t * csg)1696615f31feSGabriel Fernandez static void clk_stm32_pll_config_csg(struct stm32_clk_priv *priv,
1697615f31feSGabriel Fernandez 				     const struct stm32_clk_pll *pll,
1698615f31feSGabriel Fernandez 				     uint32_t *csg)
1699615f31feSGabriel Fernandez {
1700615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
1701615f31feSGabriel Fernandez 	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
1702615f31feSGabriel Fernandez 	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
1703615f31feSGabriel Fernandez 	uintptr_t pllxcfgr5 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR5;
1704615f31feSGabriel Fernandez 
1705615f31feSGabriel Fernandez 
1706615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr5, RCC_PLLxCFGR5_DIVVAL_MASK,
1707615f31feSGabriel Fernandez 			   csg[DIVVAL] & RCC_PLLxCFGR5_DIVVAL_MASK);
1708615f31feSGabriel Fernandez 	mmio_clrsetbits_32(pllxcfgr5, RCC_PLLxCFGR5_SPREAD_MASK,
1709615f31feSGabriel Fernandez 			   (csg[SPREAD] << RCC_PLLxCFGR5_SPREAD_SHIFT) &
1710615f31feSGabriel Fernandez 			   RCC_PLLxCFGR5_SPREAD_MASK);
1711615f31feSGabriel Fernandez 
1712615f31feSGabriel Fernandez 	if (csg[DOWNSPREAD] != 0) {
1713615f31feSGabriel Fernandez 		mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
1714615f31feSGabriel Fernandez 	} else {
1715615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
1716615f31feSGabriel Fernandez 	}
1717615f31feSGabriel Fernandez 
1718615f31feSGabriel Fernandez 	mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
1719615f31feSGabriel Fernandez 
1720615f31feSGabriel Fernandez 	mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
1721615f31feSGabriel Fernandez 	udelay(1);
1722615f31feSGabriel Fernandez 
1723615f31feSGabriel Fernandez 	mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
1724615f31feSGabriel Fernandez 	mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
1725615f31feSGabriel Fernandez }
1726615f31feSGabriel Fernandez 
1727615f31feSGabriel Fernandez static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data);
1728615f31feSGabriel Fernandez 
clk_stm32_pll_get_pdata(int pll_idx)1729615f31feSGabriel Fernandez static inline struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx)
1730615f31feSGabriel Fernandez {
1731615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
1732615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
1733615f31feSGabriel Fernandez 
1734615f31feSGabriel Fernandez 	return  &pdata->pll[pll_idx];
1735615f31feSGabriel Fernandez }
1736615f31feSGabriel Fernandez 
_clk_stm32_pll1_init(struct stm32_clk_priv * priv,int pll_idx,struct stm32_pll_dt_cfg * pll_conf)1737615f31feSGabriel Fernandez static int _clk_stm32_pll1_init(struct stm32_clk_priv *priv, int pll_idx,
1738615f31feSGabriel Fernandez 				struct stm32_pll_dt_cfg *pll_conf)
1739615f31feSGabriel Fernandez {
1740615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx);
1741615f31feSGabriel Fernandez 	unsigned long refclk;
1742615f31feSGabriel Fernandez 	int ret = 0;
1743615f31feSGabriel Fernandez 
1744615f31feSGabriel Fernandez 	stm32mp2_a35_ss_on_hsi();
1745615f31feSGabriel Fernandez 
1746615f31feSGabriel Fernandez 	ret = stm32_clk_configure_mux(priv, pll_conf->src);
1747615f31feSGabriel Fernandez 	if (ret != 0) {
1748615f31feSGabriel Fernandez 		panic();
1749615f31feSGabriel Fernandez 	}
1750615f31feSGabriel Fernandez 
1751615f31feSGabriel Fernandez 	refclk = _clk_stm32_get_parent_rate(priv, pll->clk_id);
1752615f31feSGabriel Fernandez 
1753615f31feSGabriel Fernandez 	/*
1754615f31feSGabriel Fernandez 	 * No need to check max clock, as oscillator reference clocks will
1755615f31feSGabriel Fernandez 	 * always be less than 1.2 GHz
1756615f31feSGabriel Fernandez 	 */
1757615f31feSGabriel Fernandez 	if (refclk < PLL_REFCLK_MIN) {
1758615f31feSGabriel Fernandez 		EARLY_ERROR("%s: %d\n", __func__, __LINE__);
1759615f31feSGabriel Fernandez 		panic();
1760615f31feSGabriel Fernandez 	}
1761615f31feSGabriel Fernandez 
1762615f31feSGabriel Fernandez 	stm32mp2_a35_pll1_config(pll_conf->cfg[FBDIV], pll_conf->cfg[REFDIV],
1763615f31feSGabriel Fernandez 				 pll_conf->cfg[POSTDIV1], pll_conf->cfg[POSTDIV2]);
1764615f31feSGabriel Fernandez 
1765615f31feSGabriel Fernandez 	ret = stm32mp2_a35_pll1_start();
1766615f31feSGabriel Fernandez 	if (ret != 0) {
1767615f31feSGabriel Fernandez 		panic();
1768615f31feSGabriel Fernandez 	}
1769615f31feSGabriel Fernandez 
1770615f31feSGabriel Fernandez 	return 0;
1771615f31feSGabriel Fernandez }
1772615f31feSGabriel Fernandez 
clk_stm32_pll_wait_mux_ready(struct stm32_clk_priv * priv,const struct stm32_clk_pll * pll)1773615f31feSGabriel Fernandez static int clk_stm32_pll_wait_mux_ready(struct stm32_clk_priv *priv,
1774615f31feSGabriel Fernandez 					const struct stm32_clk_pll *pll)
1775615f31feSGabriel Fernandez {
1776615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
1777615f31feSGabriel Fernandez 	uint64_t timeout = timeout_init_us(CLKSRC_TIMEOUT);
1778615f31feSGabriel Fernandez 
1779615f31feSGabriel Fernandez 	while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_CKREFST) !=
1780615f31feSGabriel Fernandez 	       RCC_PLLxCFGR1_CKREFST) {
1781615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1782615f31feSGabriel Fernandez 			EARLY_ERROR("PLL%d ref clock not started\n", pll->clk_id - _CK_PLL1 + 1);
1783615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1784615f31feSGabriel Fernandez 		}
1785615f31feSGabriel Fernandez 	}
1786615f31feSGabriel Fernandez 
1787615f31feSGabriel Fernandez 	return 0;
1788615f31feSGabriel Fernandez }
1789615f31feSGabriel Fernandez 
_clk_stm32_pll_init(struct stm32_clk_priv * priv,int pll_idx,struct stm32_pll_dt_cfg * pll_conf)1790615f31feSGabriel Fernandez static int _clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx,
1791615f31feSGabriel Fernandez 			       struct stm32_pll_dt_cfg *pll_conf)
1792615f31feSGabriel Fernandez {
1793615f31feSGabriel Fernandez 	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx);
1794615f31feSGabriel Fernandez 	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
1795615f31feSGabriel Fernandez 	bool spread_spectrum = false;
1796615f31feSGabriel Fernandez 	int ret = 0;
1797615f31feSGabriel Fernandez 
1798615f31feSGabriel Fernandez 	_clk_stm32_pll_disable(priv, pll);
1799615f31feSGabriel Fernandez 
1800615f31feSGabriel Fernandez 	ret = stm32_clk_configure_mux(priv, pll_conf->src);
1801615f31feSGabriel Fernandez 	if (ret != 0) {
1802615f31feSGabriel Fernandez 		panic();
1803615f31feSGabriel Fernandez 	}
1804615f31feSGabriel Fernandez 
1805615f31feSGabriel Fernandez 	ret = clk_stm32_pll_wait_mux_ready(priv, pll);
1806615f31feSGabriel Fernandez 	if (ret != 0) {
1807615f31feSGabriel Fernandez 		panic();
1808615f31feSGabriel Fernandez 	}
1809615f31feSGabriel Fernandez 
1810615f31feSGabriel Fernandez 	ret = clk_stm32_pll_config_output(priv, pll, pll_conf->cfg, pll_conf->frac);
1811615f31feSGabriel Fernandez 	if (ret != 0) {
1812615f31feSGabriel Fernandez 		panic();
1813615f31feSGabriel Fernandez 	}
1814615f31feSGabriel Fernandez 
1815615f31feSGabriel Fernandez 	if (pll_conf->csg_enabled) {
1816615f31feSGabriel Fernandez 		clk_stm32_pll_config_csg(priv, pll, pll_conf->csg);
1817615f31feSGabriel Fernandez 		spread_spectrum = true;
1818615f31feSGabriel Fernandez 	}
1819615f31feSGabriel Fernandez 
1820615f31feSGabriel Fernandez 	_clk_stm32_pll_enable(priv, pll);
1821615f31feSGabriel Fernandez 
1822615f31feSGabriel Fernandez 	if (spread_spectrum) {
1823615f31feSGabriel Fernandez 		mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
1824615f31feSGabriel Fernandez 	}
1825615f31feSGabriel Fernandez 
1826615f31feSGabriel Fernandez 	return 0;
1827615f31feSGabriel Fernandez }
1828615f31feSGabriel Fernandez 
clk_stm32_pll_init(struct stm32_clk_priv * priv,int pll_idx)1829615f31feSGabriel Fernandez static int clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx)
1830615f31feSGabriel Fernandez {
1831615f31feSGabriel Fernandez 	struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(pll_idx);
1832615f31feSGabriel Fernandez 
1833615f31feSGabriel Fernandez 	if (pll_conf->enabled) {
1834615f31feSGabriel Fernandez 		if (pll_idx == _PLL1) {
1835615f31feSGabriel Fernandez 			return _clk_stm32_pll1_init(priv, pll_idx, pll_conf);
1836615f31feSGabriel Fernandez 		} else  {
1837615f31feSGabriel Fernandez 			return _clk_stm32_pll_init(priv, pll_idx, pll_conf);
1838615f31feSGabriel Fernandez 		}
1839615f31feSGabriel Fernandez 	}
1840615f31feSGabriel Fernandez 
1841615f31feSGabriel Fernandez 	return 0;
1842615f31feSGabriel Fernandez }
1843615f31feSGabriel Fernandez 
stm32mp2_clk_pll_configure(struct stm32_clk_priv * priv)1844615f31feSGabriel Fernandez static int stm32mp2_clk_pll_configure(struct stm32_clk_priv *priv)
1845615f31feSGabriel Fernandez {
1846615f31feSGabriel Fernandez 	enum pll_id i;
1847615f31feSGabriel Fernandez 	int err;
1848615f31feSGabriel Fernandez 
1849615f31feSGabriel Fernandez 	for (i = _PLL1; i < _PLL_NB; i++) {
1850088238adSNicolas Le Bayon #if STM32MP21
1851088238adSNicolas Le Bayon 		if (i == _PLL3) {
1852088238adSNicolas Le Bayon 			continue;
1853088238adSNicolas Le Bayon 		}
1854088238adSNicolas Le Bayon #endif
1855615f31feSGabriel Fernandez 		err = clk_stm32_pll_init(priv, i);
1856615f31feSGabriel Fernandez 		if (err) {
1857615f31feSGabriel Fernandez 			return err;
1858615f31feSGabriel Fernandez 		}
1859615f31feSGabriel Fernandez 	}
1860615f31feSGabriel Fernandez 
1861615f31feSGabriel Fernandez 	return 0;
1862615f31feSGabriel Fernandez }
1863615f31feSGabriel Fernandez 
wait_predivsr(uint16_t channel)1864615f31feSGabriel Fernandez static int wait_predivsr(uint16_t channel)
1865615f31feSGabriel Fernandez {
1866615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
1867615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1868615f31feSGabriel Fernandez 	uintptr_t previvsr;
1869615f31feSGabriel Fernandez 	uint32_t channel_bit;
1870615f31feSGabriel Fernandez 	uint64_t timeout;
1871615f31feSGabriel Fernandez 
1872615f31feSGabriel Fernandez 	if (channel < __WORD_BIT) {
1873615f31feSGabriel Fernandez 		previvsr = rcc_base + RCC_PREDIVSR1;
1874615f31feSGabriel Fernandez 		channel_bit = BIT(channel);
1875615f31feSGabriel Fernandez 	} else {
1876615f31feSGabriel Fernandez 		previvsr = rcc_base + RCC_PREDIVSR2;
1877615f31feSGabriel Fernandez 		channel_bit = BIT(channel - __WORD_BIT);
1878615f31feSGabriel Fernandez 	}
1879615f31feSGabriel Fernandez 
1880615f31feSGabriel Fernandez 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
1881615f31feSGabriel Fernandez 	while ((mmio_read_32(previvsr) & channel_bit) != 0U) {
1882615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1883615f31feSGabriel Fernandez 			EARLY_ERROR("Pre divider status: %x\n",
1884615f31feSGabriel Fernandez 			      mmio_read_32(previvsr));
1885615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1886615f31feSGabriel Fernandez 		}
1887615f31feSGabriel Fernandez 	}
1888615f31feSGabriel Fernandez 
1889615f31feSGabriel Fernandez 	return 0;
1890615f31feSGabriel Fernandez }
1891615f31feSGabriel Fernandez 
wait_findivsr(uint16_t channel)1892615f31feSGabriel Fernandez static int wait_findivsr(uint16_t channel)
1893615f31feSGabriel Fernandez {
1894615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
1895615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1896615f31feSGabriel Fernandez 	uintptr_t finvivsr;
1897615f31feSGabriel Fernandez 	uint32_t channel_bit;
1898615f31feSGabriel Fernandez 	uint64_t timeout;
1899615f31feSGabriel Fernandez 
1900615f31feSGabriel Fernandez 	if (channel < __WORD_BIT) {
1901615f31feSGabriel Fernandez 		finvivsr = rcc_base + RCC_FINDIVSR1;
1902615f31feSGabriel Fernandez 		channel_bit = BIT(channel);
1903615f31feSGabriel Fernandez 	} else {
1904615f31feSGabriel Fernandez 		finvivsr = rcc_base + RCC_FINDIVSR2;
1905615f31feSGabriel Fernandez 		channel_bit = BIT(channel - __WORD_BIT);
1906615f31feSGabriel Fernandez 	}
1907615f31feSGabriel Fernandez 
1908615f31feSGabriel Fernandez 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
1909615f31feSGabriel Fernandez 	while ((mmio_read_32(finvivsr) & channel_bit) != 0U) {
1910615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1911615f31feSGabriel Fernandez 			EARLY_ERROR("Final divider status: %x\n",
1912615f31feSGabriel Fernandez 			      mmio_read_32(finvivsr));
1913615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1914615f31feSGabriel Fernandez 		}
1915615f31feSGabriel Fernandez 	}
1916615f31feSGabriel Fernandez 
1917615f31feSGabriel Fernandez 	return 0;
1918615f31feSGabriel Fernandez }
1919615f31feSGabriel Fernandez 
wait_xbar_sts(uint16_t channel)1920615f31feSGabriel Fernandez static int wait_xbar_sts(uint16_t channel)
1921615f31feSGabriel Fernandez {
1922615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
1923615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1924615f31feSGabriel Fernandez 	uintptr_t xbar_cfgr = rcc_base + RCC_XBAR0CFGR + (0x4U * channel);
1925615f31feSGabriel Fernandez 	uint64_t timeout;
1926615f31feSGabriel Fernandez 
1927615f31feSGabriel Fernandez 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
1928615f31feSGabriel Fernandez 	while ((mmio_read_32(xbar_cfgr) & RCC_XBAR0CFGR_XBAR0STS) != 0U) {
1929615f31feSGabriel Fernandez 		if (timeout_elapsed(timeout)) {
1930615f31feSGabriel Fernandez 			EARLY_ERROR("XBAR%uCFGR: %x\n", channel,
1931615f31feSGabriel Fernandez 			      mmio_read_32(xbar_cfgr));
1932615f31feSGabriel Fernandez 			return -ETIMEDOUT;
1933615f31feSGabriel Fernandez 		}
1934615f31feSGabriel Fernandez 	}
1935615f31feSGabriel Fernandez 
1936615f31feSGabriel Fernandez 	return 0;
1937615f31feSGabriel Fernandez }
1938615f31feSGabriel Fernandez 
flexclkgen_config_channel(uint16_t channel,unsigned int clk_src,unsigned int prediv,unsigned int findiv)1939615f31feSGabriel Fernandez static void flexclkgen_config_channel(uint16_t channel, unsigned int clk_src,
1940615f31feSGabriel Fernandez 				      unsigned int prediv, unsigned int findiv)
1941615f31feSGabriel Fernandez {
1942615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
1943615f31feSGabriel Fernandez 	uintptr_t rcc_base = priv->base;
1944615f31feSGabriel Fernandez 
1945615f31feSGabriel Fernandez 	if (wait_predivsr(channel) != 0) {
1946615f31feSGabriel Fernandez 		panic();
1947615f31feSGabriel Fernandez 	}
1948615f31feSGabriel Fernandez 
1949615f31feSGabriel Fernandez 	mmio_clrsetbits_32(rcc_base + RCC_PREDIV0CFGR + (0x4U * channel),
1950615f31feSGabriel Fernandez 			   RCC_PREDIV0CFGR_PREDIV0_MASK,
1951615f31feSGabriel Fernandez 			   prediv);
1952615f31feSGabriel Fernandez 
1953615f31feSGabriel Fernandez 	if (wait_predivsr(channel) != 0) {
1954615f31feSGabriel Fernandez 		panic();
1955615f31feSGabriel Fernandez 	}
1956615f31feSGabriel Fernandez 
1957615f31feSGabriel Fernandez 	if (wait_findivsr(channel) != 0) {
1958615f31feSGabriel Fernandez 		panic();
1959615f31feSGabriel Fernandez 	}
1960615f31feSGabriel Fernandez 
1961615f31feSGabriel Fernandez 	mmio_clrsetbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
1962615f31feSGabriel Fernandez 			   RCC_FINDIV0CFGR_FINDIV0_MASK,
1963615f31feSGabriel Fernandez 			   findiv);
1964615f31feSGabriel Fernandez 
1965615f31feSGabriel Fernandez 	if (wait_findivsr(channel) != 0) {
1966615f31feSGabriel Fernandez 		panic();
1967615f31feSGabriel Fernandez 	}
1968615f31feSGabriel Fernandez 
1969615f31feSGabriel Fernandez 	if (wait_xbar_sts(channel) != 0) {
1970615f31feSGabriel Fernandez 		panic();
1971615f31feSGabriel Fernandez 	}
1972615f31feSGabriel Fernandez 
1973615f31feSGabriel Fernandez 	mmio_clrsetbits_32(rcc_base + RCC_XBAR0CFGR + (0x4U * channel),
1974615f31feSGabriel Fernandez 			   RCC_XBARxCFGR_XBARxSEL_MASK,
1975615f31feSGabriel Fernandez 			   clk_src);
1976615f31feSGabriel Fernandez 	mmio_setbits_32(rcc_base + RCC_XBAR0CFGR + (0x4U * channel),
1977615f31feSGabriel Fernandez 			RCC_XBARxCFGR_XBARxEN);
1978615f31feSGabriel Fernandez 
1979615f31feSGabriel Fernandez 	if (wait_xbar_sts(channel) != 0) {
1980615f31feSGabriel Fernandez 		panic();
1981615f31feSGabriel Fernandez 	}
1982615f31feSGabriel Fernandez }
1983615f31feSGabriel Fernandez 
stm32mp2_clk_flexgen_configure(struct stm32_clk_priv * priv)1984615f31feSGabriel Fernandez static int stm32mp2_clk_flexgen_configure(struct stm32_clk_priv *priv)
1985615f31feSGabriel Fernandez {
1986615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
1987615f31feSGabriel Fernandez 	uint32_t i;
1988615f31feSGabriel Fernandez 
1989615f31feSGabriel Fernandez 	for (i = 0U; i < pdata->nflexgen; i++) {
1990615f31feSGabriel Fernandez 		uint32_t val = pdata->flexgen[i];
1991615f31feSGabriel Fernandez 		uint32_t cmd, cmd_data;
1992615f31feSGabriel Fernandez 		unsigned int channel, clk_src, pdiv, fdiv;
1993615f31feSGabriel Fernandez 
1994615f31feSGabriel Fernandez 		cmd = (val & CMD_MASK) >> CMD_SHIFT;
1995615f31feSGabriel Fernandez 		cmd_data = val & ~CMD_MASK;
1996615f31feSGabriel Fernandez 
1997615f31feSGabriel Fernandez 		if (cmd != CMD_FLEXGEN) {
1998615f31feSGabriel Fernandez 			continue;
1999615f31feSGabriel Fernandez 		}
2000615f31feSGabriel Fernandez 
2001615f31feSGabriel Fernandez 		channel = (cmd_data & FLEX_ID_MASK) >> FLEX_ID_SHIFT;
2002615f31feSGabriel Fernandez 		clk_src = (cmd_data & FLEX_SEL_MASK) >> FLEX_SEL_SHIFT;
2003615f31feSGabriel Fernandez 		pdiv = (cmd_data & FLEX_PDIV_MASK) >> FLEX_PDIV_SHIFT;
2004615f31feSGabriel Fernandez 		fdiv = (cmd_data & FLEX_FDIV_MASK) >> FLEX_FDIV_SHIFT;
2005615f31feSGabriel Fernandez 
2006615f31feSGabriel Fernandez 		switch (channel) {
2007615f31feSGabriel Fernandez 		case 33U: /* STGEN */
2008615f31feSGabriel Fernandez 			break;
2009615f31feSGabriel Fernandez 
2010615f31feSGabriel Fernandez 		default:
2011615f31feSGabriel Fernandez 			flexclkgen_config_channel(channel, clk_src, pdiv, fdiv);
2012615f31feSGabriel Fernandez 			break;
2013615f31feSGabriel Fernandez 		}
2014615f31feSGabriel Fernandez 	}
2015615f31feSGabriel Fernandez 
2016615f31feSGabriel Fernandez 	return 0;
2017615f31feSGabriel Fernandez }
2018615f31feSGabriel Fernandez 
stm32_enable_oscillator_hse(struct stm32_clk_priv * priv)2019615f31feSGabriel Fernandez static void stm32_enable_oscillator_hse(struct stm32_clk_priv *priv)
2020615f31feSGabriel Fernandez {
2021615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
2022615f31feSGabriel Fernandez 	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE];
2023615f31feSGabriel Fernandez 	bool digbyp =  osci->digbyp;
2024615f31feSGabriel Fernandez 	bool bypass = osci->bypass;
2025615f31feSGabriel Fernandez 	bool css = osci->css;
2026615f31feSGabriel Fernandez 
2027615f31feSGabriel Fernandez 	if (_clk_stm32_get_rate(priv, _CK_HSE) == 0U) {
2028615f31feSGabriel Fernandez 		return;
2029615f31feSGabriel Fernandez 	}
2030615f31feSGabriel Fernandez 
2031615f31feSGabriel Fernandez 	clk_oscillator_set_bypass(priv, _CK_HSE, digbyp, bypass);
2032615f31feSGabriel Fernandez 
2033615f31feSGabriel Fernandez 	_clk_stm32_enable(priv, _CK_HSE);
2034615f31feSGabriel Fernandez 
2035615f31feSGabriel Fernandez 	clk_oscillator_set_css(priv, _CK_HSE, css);
2036615f31feSGabriel Fernandez }
2037615f31feSGabriel Fernandez 
stm32_enable_oscillator_lse(struct stm32_clk_priv * priv)2038615f31feSGabriel Fernandez static void stm32_enable_oscillator_lse(struct stm32_clk_priv *priv)
2039615f31feSGabriel Fernandez {
2040615f31feSGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, _CK_LSE);
2041615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
2042615f31feSGabriel Fernandez 	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE];
2043615f31feSGabriel Fernandez 	bool digbyp =  osci->digbyp;
2044615f31feSGabriel Fernandez 	bool bypass = osci->bypass;
2045615f31feSGabriel Fernandez 	uint8_t drive = osci->drive;
2046615f31feSGabriel Fernandez 
2047615f31feSGabriel Fernandez 	if (_clk_stm32_get_rate(priv, _CK_LSE) == 0U) {
2048615f31feSGabriel Fernandez 		return;
2049615f31feSGabriel Fernandez 	}
2050615f31feSGabriel Fernandez 
2051615f31feSGabriel Fernandez 	/* Do not reconfigure LSE if already enabled */
2052615f31feSGabriel Fernandez 	if (_clk_stm32_gate_is_enabled(priv, osc_data->gate_id)) {
2053615f31feSGabriel Fernandez 		return;
2054615f31feSGabriel Fernandez 	}
2055615f31feSGabriel Fernandez 
2056615f31feSGabriel Fernandez 	clk_oscillator_set_bypass(priv, _CK_LSE, digbyp, bypass);
2057615f31feSGabriel Fernandez 
2058615f31feSGabriel Fernandez 	clk_oscillator_set_drive(priv, _CK_LSE, drive);
2059615f31feSGabriel Fernandez 
2060615f31feSGabriel Fernandez 	_clk_stm32_gate_enable(priv, osc_data->gate_id);
2061615f31feSGabriel Fernandez }
2062615f31feSGabriel Fernandez 
stm32mp2_clk_switch_to_hsi(struct stm32_clk_priv * priv)2063615f31feSGabriel Fernandez static int stm32mp2_clk_switch_to_hsi(struct stm32_clk_priv *priv)
2064615f31feSGabriel Fernandez {
2065615f31feSGabriel Fernandez 	stm32mp2_a35_ss_on_hsi();
2066615f31feSGabriel Fernandez 	stm32mp2_clk_muxsel_on_hsi(priv);
2067615f31feSGabriel Fernandez 	stm32mp2_clk_xbar_on_hsi(priv);
2068615f31feSGabriel Fernandez 
2069615f31feSGabriel Fernandez 	return 0;
2070615f31feSGabriel Fernandez }
2071615f31feSGabriel Fernandez 
stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv * priv)2072615f31feSGabriel Fernandez static int stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv *priv)
2073615f31feSGabriel Fernandez {
2074615f31feSGabriel Fernandez 	int ret = 0;
2075615f31feSGabriel Fernandez 
2076615f31feSGabriel Fernandez 	if (_clk_stm32_get_rate(priv, _CK_LSE) != 0U) {
2077615f31feSGabriel Fernandez 		ret = clk_oscillator_wait_ready_on(priv, _CK_LSE);
2078615f31feSGabriel Fernandez 	}
2079615f31feSGabriel Fernandez 
2080615f31feSGabriel Fernandez 	return ret;
2081615f31feSGabriel Fernandez }
2082615f31feSGabriel Fernandez 
stm32_enable_oscillator_msi(struct stm32_clk_priv * priv)2083615f31feSGabriel Fernandez static void stm32_enable_oscillator_msi(struct stm32_clk_priv *priv)
2084615f31feSGabriel Fernandez {
2085088238adSNicolas Le Bayon #if !STM32MP21
2086615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
2087615f31feSGabriel Fernandez 	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_MSI];
2088615f31feSGabriel Fernandez 	int err;
2089615f31feSGabriel Fernandez 
2090615f31feSGabriel Fernandez 	err = clk_stm32_osc_msi_set_rate(priv, _CK_MSI, osci->freq, 0);
2091615f31feSGabriel Fernandez 	if (err != 0) {
2092615f31feSGabriel Fernandez 		EARLY_ERROR("Invalid rate %lu MHz for MSI ! (4 or 16 only)\n",
2093615f31feSGabriel Fernandez 			    osci->freq / 1000000U);
2094615f31feSGabriel Fernandez 		panic();
2095615f31feSGabriel Fernandez 	}
2096088238adSNicolas Le Bayon #endif /* !STM32MP21 */
2097615f31feSGabriel Fernandez 
2098615f31feSGabriel Fernandez 	_clk_stm32_enable(priv, _CK_MSI);
2099615f31feSGabriel Fernandez }
2100615f31feSGabriel Fernandez 
stm32_clk_oscillators_enable(struct stm32_clk_priv * priv)2101615f31feSGabriel Fernandez static void stm32_clk_oscillators_enable(struct stm32_clk_priv *priv)
2102615f31feSGabriel Fernandez {
2103615f31feSGabriel Fernandez 	stm32_enable_oscillator_hse(priv);
2104615f31feSGabriel Fernandez 	stm32_enable_oscillator_lse(priv);
2105615f31feSGabriel Fernandez 	stm32_enable_oscillator_msi(priv);
2106615f31feSGabriel Fernandez 	_clk_stm32_enable(priv, _CK_LSI);
2107615f31feSGabriel Fernandez }
2108615f31feSGabriel Fernandez 
stm32_clk_configure_div(struct stm32_clk_priv * priv,uint32_t data)2109615f31feSGabriel Fernandez static int stm32_clk_configure_div(struct stm32_clk_priv *priv, uint32_t data)
2110615f31feSGabriel Fernandez {
2111615f31feSGabriel Fernandez 	int div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT;
2112615f31feSGabriel Fernandez 	int div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT;
2113615f31feSGabriel Fernandez 
2114615f31feSGabriel Fernandez 	return clk_stm32_set_div(priv, div_id, div_n);
2115615f31feSGabriel Fernandez }
2116615f31feSGabriel Fernandez 
stm32_clk_configure_mux(struct stm32_clk_priv * priv,uint32_t data)2117615f31feSGabriel Fernandez static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data)
2118615f31feSGabriel Fernandez {
2119615f31feSGabriel Fernandez 	int mux_id = (data & MUX_ID_MASK) >> MUX_ID_SHIFT;
2120615f31feSGabriel Fernandez 	int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
2121615f31feSGabriel Fernandez 
2122615f31feSGabriel Fernandez 	return clk_mux_set_parent(priv, mux_id, sel);
2123615f31feSGabriel Fernandez }
2124615f31feSGabriel Fernandez 
stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv * priv,uint32_t data)2125615f31feSGabriel Fernandez static int stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv *priv, uint32_t data)
2126615f31feSGabriel Fernandez {
2127615f31feSGabriel Fernandez 	unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT;
2128615f31feSGabriel Fernandez 
2129615f31feSGabriel Fernandez 	return clk_get_index(priv, binding_id);
2130615f31feSGabriel Fernandez }
2131615f31feSGabriel Fernandez 
stm32_clk_configure_clk(struct stm32_clk_priv * priv,uint32_t data)2132615f31feSGabriel Fernandez static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data)
2133615f31feSGabriel Fernandez {
2134615f31feSGabriel Fernandez 	int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT;
2135615f31feSGabriel Fernandez 	bool enable = ((data & CLK_ON_MASK) >> CLK_ON_SHIFT) != 0U;
2136615f31feSGabriel Fernandez 	int clk_id = 0;
2137615f31feSGabriel Fernandez 	int ret = 0;
2138615f31feSGabriel Fernandez 
2139615f31feSGabriel Fernandez 	clk_id = stm32_clk_configure_clk_get_binding_id(priv, data);
2140615f31feSGabriel Fernandez 	if (clk_id < 0) {
2141615f31feSGabriel Fernandez 		return clk_id;
2142615f31feSGabriel Fernandez 	}
2143615f31feSGabriel Fernandez 
2144615f31feSGabriel Fernandez 	if (sel != CLK_NOMUX) {
2145615f31feSGabriel Fernandez 		ret = _clk_stm32_set_parent_by_index(priv, clk_id, sel);
2146615f31feSGabriel Fernandez 		if (ret != 0) {
2147615f31feSGabriel Fernandez 			return ret;
2148615f31feSGabriel Fernandez 		}
2149615f31feSGabriel Fernandez 	}
2150615f31feSGabriel Fernandez 
2151615f31feSGabriel Fernandez 	if (enable) {
2152615f31feSGabriel Fernandez 		clk_stm32_enable_call_ops(priv, clk_id);
2153615f31feSGabriel Fernandez 	} else {
2154615f31feSGabriel Fernandez 		clk_stm32_disable_call_ops(priv, clk_id);
2155615f31feSGabriel Fernandez 	}
2156615f31feSGabriel Fernandez 
2157615f31feSGabriel Fernandez 	return 0;
2158615f31feSGabriel Fernandez }
2159615f31feSGabriel Fernandez 
stm32_clk_configure(struct stm32_clk_priv * priv,uint32_t val)2160615f31feSGabriel Fernandez static int stm32_clk_configure(struct stm32_clk_priv *priv, uint32_t val)
2161615f31feSGabriel Fernandez {
2162615f31feSGabriel Fernandez 	uint32_t cmd = (val & CMD_MASK) >> CMD_SHIFT;
2163615f31feSGabriel Fernandez 	uint32_t cmd_data = val & ~CMD_MASK;
2164615f31feSGabriel Fernandez 	int ret = -1;
2165615f31feSGabriel Fernandez 
2166615f31feSGabriel Fernandez 	switch (cmd) {
2167615f31feSGabriel Fernandez 	case CMD_DIV:
2168615f31feSGabriel Fernandez 		ret = stm32_clk_configure_div(priv, cmd_data);
2169615f31feSGabriel Fernandez 		break;
2170615f31feSGabriel Fernandez 
2171615f31feSGabriel Fernandez 	case CMD_MUX:
2172615f31feSGabriel Fernandez 		ret = stm32_clk_configure_mux(priv, cmd_data);
2173615f31feSGabriel Fernandez 		break;
2174615f31feSGabriel Fernandez 
2175615f31feSGabriel Fernandez 	case CMD_CLK:
2176615f31feSGabriel Fernandez 		ret = stm32_clk_configure_clk(priv, cmd_data);
2177615f31feSGabriel Fernandez 		break;
2178615f31feSGabriel Fernandez 
2179615f31feSGabriel Fernandez 	default:
2180615f31feSGabriel Fernandez 		EARLY_ERROR("%s: cmd unknown ! : 0x%x\n", __func__, val);
2181615f31feSGabriel Fernandez 		break;
2182615f31feSGabriel Fernandez 	}
2183615f31feSGabriel Fernandez 
2184615f31feSGabriel Fernandez 	return ret;
2185615f31feSGabriel Fernandez }
2186615f31feSGabriel Fernandez 
stm32_clk_bus_configure(struct stm32_clk_priv * priv)2187615f31feSGabriel Fernandez static int stm32_clk_bus_configure(struct stm32_clk_priv *priv)
2188615f31feSGabriel Fernandez {
2189615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
2190615f31feSGabriel Fernandez 	uint32_t i;
2191615f31feSGabriel Fernandez 
2192615f31feSGabriel Fernandez 	for (i = 0; i < pdata->nbusclk; i++) {
2193615f31feSGabriel Fernandez 		int ret;
2194615f31feSGabriel Fernandez 
2195615f31feSGabriel Fernandez 		ret = stm32_clk_configure(priv, pdata->busclk[i]);
2196615f31feSGabriel Fernandez 		if (ret != 0) {
2197615f31feSGabriel Fernandez 			return ret;
2198615f31feSGabriel Fernandez 		}
2199615f31feSGabriel Fernandez 	}
2200615f31feSGabriel Fernandez 
2201615f31feSGabriel Fernandez 	return 0;
2202615f31feSGabriel Fernandez }
2203615f31feSGabriel Fernandez 
stm32_clk_kernel_configure(struct stm32_clk_priv * priv)2204615f31feSGabriel Fernandez static int stm32_clk_kernel_configure(struct stm32_clk_priv *priv)
2205615f31feSGabriel Fernandez {
2206615f31feSGabriel Fernandez 	struct stm32_clk_platdata *pdata = priv->pdata;
2207615f31feSGabriel Fernandez 	uint32_t i;
2208615f31feSGabriel Fernandez 
2209615f31feSGabriel Fernandez 	for (i = 0U; i < pdata->nkernelclk; i++) {
2210615f31feSGabriel Fernandez 		int ret;
2211615f31feSGabriel Fernandez 
2212615f31feSGabriel Fernandez 		ret = stm32_clk_configure(priv, pdata->kernelclk[i]);
2213615f31feSGabriel Fernandez 		if (ret != 0) {
2214615f31feSGabriel Fernandez 			return ret;
2215615f31feSGabriel Fernandez 		}
2216615f31feSGabriel Fernandez 	}
2217615f31feSGabriel Fernandez 
2218615f31feSGabriel Fernandez 	return 0;
2219615f31feSGabriel Fernandez }
2220615f31feSGabriel Fernandez 
stm32mp2_init_clock_tree(void)2221615f31feSGabriel Fernandez static int stm32mp2_init_clock_tree(void)
2222615f31feSGabriel Fernandez {
2223615f31feSGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
2224615f31feSGabriel Fernandez 	int ret;
2225615f31feSGabriel Fernandez 
2226615f31feSGabriel Fernandez 	/* Set timer with STGEN without changing its clock source */
2227615f31feSGabriel Fernandez 	stm32mp_stgen_restore_rate();
2228615f31feSGabriel Fernandez 	generic_delay_timer_init();
2229615f31feSGabriel Fernandez 
2230615f31feSGabriel Fernandez 	stm32_clk_oscillators_enable(priv);
2231615f31feSGabriel Fernandez 
2232615f31feSGabriel Fernandez 	/* Come back to HSI */
2233615f31feSGabriel Fernandez 	ret = stm32mp2_clk_switch_to_hsi(priv);
2234615f31feSGabriel Fernandez 	if (ret != 0) {
2235615f31feSGabriel Fernandez 		panic();
2236615f31feSGabriel Fernandez 	}
2237615f31feSGabriel Fernandez 
2238615f31feSGabriel Fernandez 	ret = stm32mp2_clk_pll_configure(priv);
2239615f31feSGabriel Fernandez 	if (ret != 0) {
2240615f31feSGabriel Fernandez 		panic();
2241615f31feSGabriel Fernandez 	}
2242615f31feSGabriel Fernandez 
2243615f31feSGabriel Fernandez 	/* Wait LSE ready before to use it */
2244615f31feSGabriel Fernandez 	ret = stm32_clk_oscillators_wait_lse_ready(priv);
2245615f31feSGabriel Fernandez 	if (ret != 0) {
2246615f31feSGabriel Fernandez 		panic();
2247615f31feSGabriel Fernandez 	}
2248615f31feSGabriel Fernandez 
2249615f31feSGabriel Fernandez 	ret = stm32mp2_clk_flexgen_configure(priv);
2250615f31feSGabriel Fernandez 	if (ret != 0) {
2251615f31feSGabriel Fernandez 		panic();
2252615f31feSGabriel Fernandez 	}
2253615f31feSGabriel Fernandez 
2254615f31feSGabriel Fernandez 	ret = stm32_clk_bus_configure(priv);
2255615f31feSGabriel Fernandez 	if (ret != 0) {
2256615f31feSGabriel Fernandez 		panic();
2257615f31feSGabriel Fernandez 	}
2258615f31feSGabriel Fernandez 
2259615f31feSGabriel Fernandez 	ret = stm32_clk_kernel_configure(priv);
2260615f31feSGabriel Fernandez 	if (ret != 0) {
2261615f31feSGabriel Fernandez 		panic();
2262615f31feSGabriel Fernandez 	}
2263615f31feSGabriel Fernandez 
2264615f31feSGabriel Fernandez 	return 0;
2265615f31feSGabriel Fernandez }
2266615f31feSGabriel Fernandez 
clk_stm32_parse_oscillator_fdt(void * fdt,int node,const char * name,struct stm32_osci_dt_cfg * osci)2267615f31feSGabriel Fernandez static int clk_stm32_parse_oscillator_fdt(void *fdt, int node, const char *name,
2268615f31feSGabriel Fernandez 					  struct stm32_osci_dt_cfg *osci)
2269615f31feSGabriel Fernandez {
2270615f31feSGabriel Fernandez 	int subnode = 0;
2271615f31feSGabriel Fernandez 
2272615f31feSGabriel Fernandez 	/* Default value oscillator not found, freq=0 */
2273615f31feSGabriel Fernandez 	osci->freq = 0;
2274615f31feSGabriel Fernandez 
2275615f31feSGabriel Fernandez 	fdt_for_each_subnode(subnode, fdt, node) {
2276615f31feSGabriel Fernandez 		const char *cchar = NULL;
2277615f31feSGabriel Fernandez 		const fdt32_t *cuint = NULL;
2278615f31feSGabriel Fernandez 		int ret = 0;
2279615f31feSGabriel Fernandez 
2280615f31feSGabriel Fernandez 		cchar = fdt_get_name(fdt, subnode, &ret);
2281615f31feSGabriel Fernandez 		if (cchar == NULL) {
2282615f31feSGabriel Fernandez 			return ret;
2283615f31feSGabriel Fernandez 		}
2284615f31feSGabriel Fernandez 
2285615f31feSGabriel Fernandez 		if (strncmp(cchar, name, (size_t)ret) ||
2286615f31feSGabriel Fernandez 		    fdt_get_status(subnode) == DT_DISABLED) {
2287615f31feSGabriel Fernandez 			continue;
2288615f31feSGabriel Fernandez 		}
2289615f31feSGabriel Fernandez 
2290615f31feSGabriel Fernandez 		cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret);
2291615f31feSGabriel Fernandez 		if (cuint == NULL) {
2292615f31feSGabriel Fernandez 			return ret;
2293615f31feSGabriel Fernandez 		}
2294615f31feSGabriel Fernandez 
2295615f31feSGabriel Fernandez 		osci->freq = fdt32_to_cpu(*cuint);
2296615f31feSGabriel Fernandez 
2297615f31feSGabriel Fernandez 		if (fdt_getprop(fdt, subnode, "st,bypass", NULL) != NULL) {
2298615f31feSGabriel Fernandez 			osci->bypass = true;
2299615f31feSGabriel Fernandez 		}
2300615f31feSGabriel Fernandez 
2301615f31feSGabriel Fernandez 		if (fdt_getprop(fdt, subnode, "st,digbypass", NULL) != NULL) {
2302615f31feSGabriel Fernandez 			osci->digbyp = true;
2303615f31feSGabriel Fernandez 		}
2304615f31feSGabriel Fernandez 
2305615f31feSGabriel Fernandez 		if (fdt_getprop(fdt, subnode, "st,css", NULL) != NULL) {
2306615f31feSGabriel Fernandez 			osci->css = true;
2307615f31feSGabriel Fernandez 		}
2308615f31feSGabriel Fernandez 
2309615f31feSGabriel Fernandez 		osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH);
2310615f31feSGabriel Fernandez 
2311615f31feSGabriel Fernandez 		return 0;
2312615f31feSGabriel Fernandez 	}
2313615f31feSGabriel Fernandez 
2314615f31feSGabriel Fernandez 	return 0;
2315615f31feSGabriel Fernandez }
2316615f31feSGabriel Fernandez 
stm32_clk_parse_fdt_all_oscillator(void * fdt,struct stm32_clk_platdata * pdata)2317615f31feSGabriel Fernandez static int stm32_clk_parse_fdt_all_oscillator(void *fdt, struct stm32_clk_platdata *pdata)
2318615f31feSGabriel Fernandez {
2319615f31feSGabriel Fernandez 	int fdt_err = 0;
2320615f31feSGabriel Fernandez 	uint32_t i = 0;
2321615f31feSGabriel Fernandez 	int node = 0;
2322615f31feSGabriel Fernandez 
2323615f31feSGabriel Fernandez 	node = fdt_path_offset(fdt, "/clocks");
2324615f31feSGabriel Fernandez 	if (node < 0) {
2325615f31feSGabriel Fernandez 		return -FDT_ERR_NOTFOUND;
2326615f31feSGabriel Fernandez 	}
2327615f31feSGabriel Fernandez 
2328615f31feSGabriel Fernandez 	for (i = 0; i < pdata->nosci; i++) {
2329615f31feSGabriel Fernandez 		const char *name = NULL;
2330615f31feSGabriel Fernandez 
2331615f31feSGabriel Fernandez 		name = clk_stm32_get_oscillator_name((enum stm32_osc)i);
2332615f31feSGabriel Fernandez 		if (name == NULL) {
2333615f31feSGabriel Fernandez 			continue;
2334615f31feSGabriel Fernandez 		}
2335615f31feSGabriel Fernandez 
2336615f31feSGabriel Fernandez 		fdt_err = clk_stm32_parse_oscillator_fdt(fdt, node, name, &pdata->osci[i]);
2337615f31feSGabriel Fernandez 		if (fdt_err < 0) {
2338615f31feSGabriel Fernandez 			panic();
2339615f31feSGabriel Fernandez 		}
2340615f31feSGabriel Fernandez 	}
2341615f31feSGabriel Fernandez 
2342615f31feSGabriel Fernandez 	return 0;
2343615f31feSGabriel Fernandez }
2344615f31feSGabriel Fernandez 
clk_stm32_parse_pll_fdt(void * fdt,int subnode,struct stm32_pll_dt_cfg * pll)2345615f31feSGabriel Fernandez static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll)
2346615f31feSGabriel Fernandez {
2347615f31feSGabriel Fernandez 	const fdt32_t *cuint = NULL;
2348615f31feSGabriel Fernandez 	int subnode_pll = 0;
2349615f31feSGabriel Fernandez 	uint32_t val = 0;
2350615f31feSGabriel Fernandez 	int err = 0;
2351615f31feSGabriel Fernandez 
2352615f31feSGabriel Fernandez 	cuint = fdt_getprop(fdt, subnode, "st,pll", NULL);
2353615f31feSGabriel Fernandez 	if (!cuint) {
2354615f31feSGabriel Fernandez 		return -FDT_ERR_NOTFOUND;
2355615f31feSGabriel Fernandez 	}
2356615f31feSGabriel Fernandez 
2357615f31feSGabriel Fernandez 	subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
2358615f31feSGabriel Fernandez 	if (subnode_pll < 0) {
2359615f31feSGabriel Fernandez 		return -FDT_ERR_NOTFOUND;
2360615f31feSGabriel Fernandez 	}
2361615f31feSGabriel Fernandez 
2362615f31feSGabriel Fernandez 	err = fdt_read_uint32_array(fdt, subnode_pll, "cfg", (int)PLLCFG_NB, pll->cfg);
2363615f31feSGabriel Fernandez 	if (err != 0) {
2364615f31feSGabriel Fernandez 		return err;
2365615f31feSGabriel Fernandez 	}
2366615f31feSGabriel Fernandez 
2367615f31feSGabriel Fernandez 	err = fdt_read_uint32_array(fdt, subnode_pll, "csg", (int)PLLCSG_NB, pll->csg);
2368615f31feSGabriel Fernandez 
2369615f31feSGabriel Fernandez 	pll->csg_enabled = (err == 0);
2370615f31feSGabriel Fernandez 
2371615f31feSGabriel Fernandez 	if (err == -FDT_ERR_NOTFOUND) {
2372615f31feSGabriel Fernandez 		err = 0;
2373615f31feSGabriel Fernandez 	}
2374615f31feSGabriel Fernandez 
2375615f31feSGabriel Fernandez 	if (err != 0) {
2376615f31feSGabriel Fernandez 		return err;
2377615f31feSGabriel Fernandez 	}
2378615f31feSGabriel Fernandez 
2379615f31feSGabriel Fernandez 	pll->enabled = true;
2380615f31feSGabriel Fernandez 
2381615f31feSGabriel Fernandez 	pll->frac = fdt_read_uint32_default(fdt, subnode_pll, "frac", 0);
2382615f31feSGabriel Fernandez 
2383615f31feSGabriel Fernandez 	pll->src = UINT32_MAX;
2384615f31feSGabriel Fernandez 
2385615f31feSGabriel Fernandez 	err = fdt_read_uint32(fdt, subnode_pll, "src", &val);
2386615f31feSGabriel Fernandez 	if  (err == 0) {
2387615f31feSGabriel Fernandez 		pll->src = val;
2388615f31feSGabriel Fernandez 	}
2389615f31feSGabriel Fernandez 
2390615f31feSGabriel Fernandez 	return 0;
2391615f31feSGabriel Fernandez }
2392615f31feSGabriel Fernandez 
2393615f31feSGabriel Fernandez #define RCC_PLL_NAME_SIZE 12
2394615f31feSGabriel Fernandez 
stm32_clk_parse_fdt_all_pll(void * fdt,int node,struct stm32_clk_platdata * pdata)2395615f31feSGabriel Fernandez static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata)
2396615f31feSGabriel Fernandez {
2397615f31feSGabriel Fernandez 	unsigned int i = 0;
2398615f31feSGabriel Fernandez 
2399615f31feSGabriel Fernandez 	for (i = _PLL1; i < pdata->npll; i++) {
2400615f31feSGabriel Fernandez 		struct stm32_pll_dt_cfg *pll = pdata->pll + i;
2401615f31feSGabriel Fernandez 		char name[RCC_PLL_NAME_SIZE];
2402615f31feSGabriel Fernandez 		int subnode = 0;
2403615f31feSGabriel Fernandez 		int err = 0;
2404615f31feSGabriel Fernandez 
2405088238adSNicolas Le Bayon #if STM32MP21
2406088238adSNicolas Le Bayon 		if (i == _PLL3) {
2407088238adSNicolas Le Bayon 			continue;
2408088238adSNicolas Le Bayon 		}
2409088238adSNicolas Le Bayon #endif
2410615f31feSGabriel Fernandez 		snprintf(name, sizeof(name), "st,pll-%u", i + 1);
2411615f31feSGabriel Fernandez 
2412615f31feSGabriel Fernandez 		subnode = fdt_subnode_offset(fdt, node, name);
2413615f31feSGabriel Fernandez 		if (!fdt_check_node(subnode)) {
2414615f31feSGabriel Fernandez 			continue;
2415615f31feSGabriel Fernandez 		}
2416615f31feSGabriel Fernandez 
2417615f31feSGabriel Fernandez 		err = clk_stm32_parse_pll_fdt(fdt, subnode, pll);
2418615f31feSGabriel Fernandez 		if (err != 0) {
2419615f31feSGabriel Fernandez 			panic();
2420615f31feSGabriel Fernandez 		}
2421615f31feSGabriel Fernandez 	}
2422615f31feSGabriel Fernandez 
2423615f31feSGabriel Fernandez 	return 0;
2424615f31feSGabriel Fernandez }
2425615f31feSGabriel Fernandez 
stm32_clk_parse_fdt(struct stm32_clk_platdata * pdata)2426615f31feSGabriel Fernandez static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata)
2427615f31feSGabriel Fernandez {
2428615f31feSGabriel Fernandez 	void *fdt = NULL;
2429615f31feSGabriel Fernandez 	int node;
2430615f31feSGabriel Fernandez 	int err;
2431615f31feSGabriel Fernandez 
2432615f31feSGabriel Fernandez 	if (fdt_get_address(&fdt) == 0) {
2433615f31feSGabriel Fernandez 		return -ENOENT;
2434615f31feSGabriel Fernandez 	}
2435615f31feSGabriel Fernandez 
2436615f31feSGabriel Fernandez 	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
2437615f31feSGabriel Fernandez 	if (node < 0) {
2438615f31feSGabriel Fernandez 		panic();
2439615f31feSGabriel Fernandez 	}
2440615f31feSGabriel Fernandez 
2441615f31feSGabriel Fernandez 	err = stm32_clk_parse_fdt_all_oscillator(fdt, pdata);
2442615f31feSGabriel Fernandez 	if (err != 0) {
2443615f31feSGabriel Fernandez 		return err;
2444615f31feSGabriel Fernandez 	}
2445615f31feSGabriel Fernandez 
2446615f31feSGabriel Fernandez 	err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata);
2447615f31feSGabriel Fernandez 	if (err != 0) {
2448615f31feSGabriel Fernandez 		return err;
2449615f31feSGabriel Fernandez 	}
2450615f31feSGabriel Fernandez 
2451615f31feSGabriel Fernandez 	err = stm32_clk_parse_fdt_by_name(fdt, node, "st,busclk", pdata->busclk, &pdata->nbusclk);
2452615f31feSGabriel Fernandez 	if (err != 0) {
2453615f31feSGabriel Fernandez 		return err;
2454615f31feSGabriel Fernandez 	}
2455615f31feSGabriel Fernandez 
2456615f31feSGabriel Fernandez 	err = stm32_clk_parse_fdt_by_name(fdt, node, "st,flexgen", pdata->flexgen,
2457615f31feSGabriel Fernandez 					  &pdata->nflexgen);
2458615f31feSGabriel Fernandez 	if (err != 0) {
2459615f31feSGabriel Fernandez 		return err;
2460615f31feSGabriel Fernandez 	}
2461615f31feSGabriel Fernandez 
2462615f31feSGabriel Fernandez 	err = stm32_clk_parse_fdt_by_name(fdt, node, "st,kerclk", pdata->kernelclk,
2463615f31feSGabriel Fernandez 					  &pdata->nkernelclk);
2464615f31feSGabriel Fernandez 	if (err != 0) {
2465615f31feSGabriel Fernandez 		return err;
2466615f31feSGabriel Fernandez 	}
2467615f31feSGabriel Fernandez 
2468615f31feSGabriel Fernandez 	return 0;
2469615f31feSGabriel Fernandez }
2470615f31feSGabriel Fernandez #endif /* IMAGE_BL2 */
2471615f31feSGabriel Fernandez 
2472088238adSNicolas Le Bayon static struct stm32_osci_dt_cfg mp2_osci[NB_OSCILLATOR];
2473615f31feSGabriel Fernandez 
2474088238adSNicolas Le Bayon static struct stm32_pll_dt_cfg mp2_pll[_PLL_NB];
2475615f31feSGabriel Fernandez 
2476615f31feSGabriel Fernandez #define DT_FLEXGEN_CLK_MAX	64
2477088238adSNicolas Le Bayon static uint32_t mp2_flexgen[DT_FLEXGEN_CLK_MAX];
2478615f31feSGabriel Fernandez 
2479088238adSNicolas Le Bayon #if STM32MP21
2480088238adSNicolas Le Bayon #define DT_BUS_CLK_MAX		7
2481088238adSNicolas Le Bayon #else /* STM32MP21 */
2482615f31feSGabriel Fernandez #define DT_BUS_CLK_MAX		6
2483088238adSNicolas Le Bayon #endif /* STM32MP21 */
2484088238adSNicolas Le Bayon static uint32_t mp2_busclk[DT_BUS_CLK_MAX];
2485615f31feSGabriel Fernandez 
2486615f31feSGabriel Fernandez #define DT_KERNEL_CLK_MAX	20
2487088238adSNicolas Le Bayon static uint32_t mp2_kernelclk[DT_KERNEL_CLK_MAX];
2488615f31feSGabriel Fernandez 
2489088238adSNicolas Le Bayon static struct stm32_clk_platdata stm32mp2_pdata = {
2490088238adSNicolas Le Bayon 	.osci = mp2_osci,
2491615f31feSGabriel Fernandez 	.nosci = NB_OSCILLATOR,
2492088238adSNicolas Le Bayon 	.pll = mp2_pll,
2493615f31feSGabriel Fernandez 	.npll = _PLL_NB,
2494088238adSNicolas Le Bayon 	.flexgen = mp2_flexgen,
2495615f31feSGabriel Fernandez 	.nflexgen = DT_FLEXGEN_CLK_MAX,
2496088238adSNicolas Le Bayon 	.busclk	= mp2_busclk,
2497615f31feSGabriel Fernandez 	.nbusclk = DT_BUS_CLK_MAX,
2498088238adSNicolas Le Bayon 	.kernelclk = mp2_kernelclk,
2499615f31feSGabriel Fernandez 	.nkernelclk = DT_KERNEL_CLK_MAX,
2500615f31feSGabriel Fernandez };
2501615f31feSGabriel Fernandez 
2502088238adSNicolas Le Bayon static uint8_t refcounts_mp2[CK_LAST];
2503615f31feSGabriel Fernandez 
2504088238adSNicolas Le Bayon static struct stm32_clk_priv stm32mp2_clock_data = {
2505615f31feSGabriel Fernandez 	.base		= RCC_BASE,
2506088238adSNicolas Le Bayon 	.num		= ARRAY_SIZE(stm32mp2_clk),
2507088238adSNicolas Le Bayon 	.clks		= stm32mp2_clk,
2508088238adSNicolas Le Bayon 	.parents	= parent_mp2,
2509088238adSNicolas Le Bayon 	.nb_parents	= ARRAY_SIZE(parent_mp2),
2510088238adSNicolas Le Bayon 	.gates		= gates_mp2,
2511088238adSNicolas Le Bayon 	.nb_gates	= ARRAY_SIZE(gates_mp2),
2512088238adSNicolas Le Bayon 	.div		= dividers_mp2,
2513088238adSNicolas Le Bayon 	.nb_div		= ARRAY_SIZE(dividers_mp2),
2514088238adSNicolas Le Bayon 	.osci_data	= stm32mp2_osc_data,
2515088238adSNicolas Le Bayon 	.nb_osci_data	= ARRAY_SIZE(stm32mp2_osc_data),
2516088238adSNicolas Le Bayon 	.gate_refcounts	= refcounts_mp2,
2517088238adSNicolas Le Bayon 	.pdata		= &stm32mp2_pdata,
2518088238adSNicolas Le Bayon 	.ops_array	= ops_array_mp2,
2519615f31feSGabriel Fernandez };
2520615f31feSGabriel Fernandez 
stm32mp2_clk_init(void)2521615f31feSGabriel Fernandez int stm32mp2_clk_init(void)
2522615f31feSGabriel Fernandez {
2523615f31feSGabriel Fernandez 	uintptr_t base = RCC_BASE;
2524615f31feSGabriel Fernandez 	int ret;
2525615f31feSGabriel Fernandez 
2526615f31feSGabriel Fernandez #ifdef IMAGE_BL2
2527088238adSNicolas Le Bayon 	ret = stm32_clk_parse_fdt(&stm32mp2_pdata);
2528615f31feSGabriel Fernandez 	if (ret != 0) {
2529615f31feSGabriel Fernandez 		return ret;
2530615f31feSGabriel Fernandez 	}
2531615f31feSGabriel Fernandez #endif
2532615f31feSGabriel Fernandez 
2533088238adSNicolas Le Bayon 	ret = clk_stm32_init(&stm32mp2_clock_data, base);
2534615f31feSGabriel Fernandez 	if (ret != 0) {
2535615f31feSGabriel Fernandez 		return ret;
2536615f31feSGabriel Fernandez 	}
2537615f31feSGabriel Fernandez 
2538615f31feSGabriel Fernandez #ifdef IMAGE_BL2
2539615f31feSGabriel Fernandez 	ret = stm32mp2_init_clock_tree();
2540615f31feSGabriel Fernandez 	if (ret != 0) {
2541615f31feSGabriel Fernandez 		return ret;
2542615f31feSGabriel Fernandez 	}
2543615f31feSGabriel Fernandez 
2544615f31feSGabriel Fernandez 	clk_stm32_enable_critical_clocks();
2545615f31feSGabriel Fernandez #endif
2546615f31feSGabriel Fernandez 
2547615f31feSGabriel Fernandez 	return 0;
2548615f31feSGabriel Fernandez }
2549615f31feSGabriel Fernandez 
stm32mp2_pll1_disable(void)2550615f31feSGabriel Fernandez int stm32mp2_pll1_disable(void)
2551615f31feSGabriel Fernandez {
2552615f31feSGabriel Fernandez #ifdef IMAGE_BL2
2553615f31feSGabriel Fernandez 	return -EPERM;
2554615f31feSGabriel Fernandez #else
2555615f31feSGabriel Fernandez 	uintptr_t a35_ss_address = A35SSC_BASE;
2556615f31feSGabriel Fernandez 	uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
2557615f31feSGabriel Fernandez 
2558615f31feSGabriel Fernandez 	stm32mp2_a35_ss_on_hsi();
2559615f31feSGabriel Fernandez 
2560615f31feSGabriel Fernandez 	mmio_clrbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_PD);
2561615f31feSGabriel Fernandez 
2562615f31feSGabriel Fernandez 	return 0;
2563615f31feSGabriel Fernandez #endif
2564615f31feSGabriel Fernandez }
2565