xref: /optee_os/core/drivers/clk/clk-stm32mp15.c (revision 6b651796a4a0014f32f3061c86454fef73a62b37)
1*6b651796SEtienne Carriere // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0+)
2*6b651796SEtienne Carriere /*
3*6b651796SEtienne Carriere  * Copyright (C) 2018-2019, STMicroelectronics
4*6b651796SEtienne Carriere  */
5*6b651796SEtienne Carriere 
6*6b651796SEtienne Carriere #include <assert.h>
7*6b651796SEtienne Carriere #include <config.h>
8*6b651796SEtienne Carriere #include <drivers/stm32mp1_rcc.h>
9*6b651796SEtienne Carriere #include <drivers/clk.h>
10*6b651796SEtienne Carriere #include <drivers/clk_dt.h>
11*6b651796SEtienne Carriere #include <dt-bindings/clock/stm32mp1-clks.h>
12*6b651796SEtienne Carriere #include <initcall.h>
13*6b651796SEtienne Carriere #include <io.h>
14*6b651796SEtienne Carriere #include <keep.h>
15*6b651796SEtienne Carriere #include <kernel/dt.h>
16*6b651796SEtienne Carriere #include <kernel/boot.h>
17*6b651796SEtienne Carriere #include <kernel/panic.h>
18*6b651796SEtienne Carriere #include <kernel/spinlock.h>
19*6b651796SEtienne Carriere #include <libfdt.h>
20*6b651796SEtienne Carriere #include <platform_config.h>
21*6b651796SEtienne Carriere #include <stdio.h>
22*6b651796SEtienne Carriere #include <stm32_util.h>
23*6b651796SEtienne Carriere #include <trace.h>
24*6b651796SEtienne Carriere #include <util.h>
25*6b651796SEtienne Carriere 
26*6b651796SEtienne Carriere /* Identifiers for root oscillators */
27*6b651796SEtienne Carriere enum stm32mp_osc_id {
28*6b651796SEtienne Carriere 	_HSI = 0,
29*6b651796SEtienne Carriere 	_HSE,
30*6b651796SEtienne Carriere 	_CSI,
31*6b651796SEtienne Carriere 	_LSI,
32*6b651796SEtienne Carriere 	_LSE,
33*6b651796SEtienne Carriere 	_I2S_CKIN,
34*6b651796SEtienne Carriere 	_USB_PHY_48,
35*6b651796SEtienne Carriere 	NB_OSC,
36*6b651796SEtienne Carriere 	_UNKNOWN_OSC_ID = 0xffU
37*6b651796SEtienne Carriere };
38*6b651796SEtienne Carriere 
39*6b651796SEtienne Carriere /* Identifiers for parent clocks */
40*6b651796SEtienne Carriere enum stm32mp1_parent_id {
41*6b651796SEtienne Carriere /*
42*6b651796SEtienne Carriere  * Oscillators are valid IDs for parent clock and are already
43*6b651796SEtienne Carriere  * defined in enum stm32mp_osc_id, ending at NB_OSC - 1.
44*6b651796SEtienne Carriere  * This enum defines IDs are the other possible clock parents.
45*6b651796SEtienne Carriere  */
46*6b651796SEtienne Carriere 	_HSI_KER = NB_OSC,
47*6b651796SEtienne Carriere 	_HSE_KER,
48*6b651796SEtienne Carriere 	_HSE_KER_DIV2,
49*6b651796SEtienne Carriere 	_CSI_KER,
50*6b651796SEtienne Carriere 	_PLL1_P,
51*6b651796SEtienne Carriere 	_PLL1_Q,
52*6b651796SEtienne Carriere 	_PLL1_R,
53*6b651796SEtienne Carriere 	_PLL2_P,
54*6b651796SEtienne Carriere 	_PLL2_Q,
55*6b651796SEtienne Carriere 	_PLL2_R,
56*6b651796SEtienne Carriere 	_PLL3_P,
57*6b651796SEtienne Carriere 	_PLL3_Q,
58*6b651796SEtienne Carriere 	_PLL3_R,
59*6b651796SEtienne Carriere 	_PLL4_P,
60*6b651796SEtienne Carriere 	_PLL4_Q,
61*6b651796SEtienne Carriere 	_PLL4_R,
62*6b651796SEtienne Carriere 	_ACLK,
63*6b651796SEtienne Carriere 	_PCLK1,
64*6b651796SEtienne Carriere 	_PCLK2,
65*6b651796SEtienne Carriere 	_PCLK3,
66*6b651796SEtienne Carriere 	_PCLK4,
67*6b651796SEtienne Carriere 	_PCLK5,
68*6b651796SEtienne Carriere 	_HCLK5,
69*6b651796SEtienne Carriere 	_HCLK6,
70*6b651796SEtienne Carriere 	_HCLK2,
71*6b651796SEtienne Carriere 	_CK_PER,
72*6b651796SEtienne Carriere 	_CK_MPU,
73*6b651796SEtienne Carriere 	_CK_MCU,
74*6b651796SEtienne Carriere 	_PARENT_NB,
75*6b651796SEtienne Carriere 	_UNKNOWN_ID = 0xff,
76*6b651796SEtienne Carriere };
77*6b651796SEtienne Carriere 
78*6b651796SEtienne Carriere /*
79*6b651796SEtienne Carriere  * Identifiers for parent clock selectors.
80*6b651796SEtienne Carriere  * This enum lists only the parent clocks we are interested in.
81*6b651796SEtienne Carriere  */
82*6b651796SEtienne Carriere enum stm32mp1_parent_sel {
83*6b651796SEtienne Carriere 	_STGEN_SEL,
84*6b651796SEtienne Carriere 	_I2C46_SEL,
85*6b651796SEtienne Carriere 	_SPI6_SEL,
86*6b651796SEtienne Carriere 	_USART1_SEL,
87*6b651796SEtienne Carriere 	_RNG1_SEL,
88*6b651796SEtienne Carriere 	_UART6_SEL,
89*6b651796SEtienne Carriere 	_UART24_SEL,
90*6b651796SEtienne Carriere 	_UART35_SEL,
91*6b651796SEtienne Carriere 	_UART78_SEL,
92*6b651796SEtienne Carriere 	_AXISS_SEL,
93*6b651796SEtienne Carriere 	_MCUSS_SEL,
94*6b651796SEtienne Carriere 	_USBPHY_SEL,
95*6b651796SEtienne Carriere 	_USBO_SEL,
96*6b651796SEtienne Carriere 	_RTC_SEL,
97*6b651796SEtienne Carriere 	_PARENT_SEL_NB,
98*6b651796SEtienne Carriere 	_UNKNOWN_SEL = 0xff,
99*6b651796SEtienne Carriere };
100*6b651796SEtienne Carriere 
101*6b651796SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = {
102*6b651796SEtienne Carriere 	[_HSE] = CK_HSE,
103*6b651796SEtienne Carriere 	[_HSI] = CK_HSI,
104*6b651796SEtienne Carriere 	[_CSI] = CK_CSI,
105*6b651796SEtienne Carriere 	[_LSE] = CK_LSE,
106*6b651796SEtienne Carriere 	[_LSI] = CK_LSI,
107*6b651796SEtienne Carriere 	[_I2S_CKIN] = _UNKNOWN_ID,
108*6b651796SEtienne Carriere 	[_USB_PHY_48] = _UNKNOWN_ID,
109*6b651796SEtienne Carriere 	[_HSI_KER] = CK_HSI,
110*6b651796SEtienne Carriere 	[_HSE_KER] = CK_HSE,
111*6b651796SEtienne Carriere 	[_HSE_KER_DIV2] = CK_HSE_DIV2,
112*6b651796SEtienne Carriere 	[_CSI_KER] = CK_CSI,
113*6b651796SEtienne Carriere 	[_PLL1_P] = PLL1_P,
114*6b651796SEtienne Carriere 	[_PLL1_Q] = PLL1_Q,
115*6b651796SEtienne Carriere 	[_PLL1_R] = PLL1_R,
116*6b651796SEtienne Carriere 	[_PLL2_P] = PLL2_P,
117*6b651796SEtienne Carriere 	[_PLL2_Q] = PLL2_Q,
118*6b651796SEtienne Carriere 	[_PLL2_R] = PLL2_R,
119*6b651796SEtienne Carriere 	[_PLL3_P] = PLL3_P,
120*6b651796SEtienne Carriere 	[_PLL3_Q] = PLL3_Q,
121*6b651796SEtienne Carriere 	[_PLL3_R] = PLL3_R,
122*6b651796SEtienne Carriere 	[_PLL4_P] = PLL4_P,
123*6b651796SEtienne Carriere 	[_PLL4_Q] = PLL4_Q,
124*6b651796SEtienne Carriere 	[_PLL4_R] = PLL4_R,
125*6b651796SEtienne Carriere 	[_ACLK] = CK_AXI,
126*6b651796SEtienne Carriere 	[_PCLK1] = CK_AXI,
127*6b651796SEtienne Carriere 	[_PCLK2] = CK_AXI,
128*6b651796SEtienne Carriere 	[_PCLK3] = CK_AXI,
129*6b651796SEtienne Carriere 	[_PCLK4] = CK_AXI,
130*6b651796SEtienne Carriere 	[_PCLK5] = CK_AXI,
131*6b651796SEtienne Carriere 	[_HCLK5] = CK_AXI,
132*6b651796SEtienne Carriere 	[_HCLK6] = CK_AXI,
133*6b651796SEtienne Carriere 	[_HCLK2] = CK_AXI,
134*6b651796SEtienne Carriere 	[_CK_PER] = CK_PER,
135*6b651796SEtienne Carriere 	[_CK_MPU] = CK_MPU,
136*6b651796SEtienne Carriere 	[_CK_MCU] = CK_MCU,
137*6b651796SEtienne Carriere };
138*6b651796SEtienne Carriere 
139*6b651796SEtienne Carriere static enum stm32mp1_parent_id clock_id2parent_id(unsigned long id)
140*6b651796SEtienne Carriere {
141*6b651796SEtienne Carriere 	size_t n = 0;
142*6b651796SEtienne Carriere 
143*6b651796SEtienne Carriere 	COMPILE_TIME_ASSERT(STM32MP1_LAST_CLK < _UNKNOWN_ID);
144*6b651796SEtienne Carriere 
145*6b651796SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(parent_id_clock_id); n++)
146*6b651796SEtienne Carriere 		if (parent_id_clock_id[n] == id)
147*6b651796SEtienne Carriere 			return (enum stm32mp1_parent_id)n;
148*6b651796SEtienne Carriere 
149*6b651796SEtienne Carriere 	return _UNKNOWN_ID;
150*6b651796SEtienne Carriere }
151*6b651796SEtienne Carriere 
152*6b651796SEtienne Carriere /* Identifiers for PLLs and their configuration resources */
153*6b651796SEtienne Carriere enum stm32mp1_pll_id {
154*6b651796SEtienne Carriere 	_PLL1,
155*6b651796SEtienne Carriere 	_PLL2,
156*6b651796SEtienne Carriere 	_PLL3,
157*6b651796SEtienne Carriere 	_PLL4,
158*6b651796SEtienne Carriere 	_PLL_NB
159*6b651796SEtienne Carriere };
160*6b651796SEtienne Carriere 
161*6b651796SEtienne Carriere enum stm32mp1_div_id {
162*6b651796SEtienne Carriere 	_DIV_P,
163*6b651796SEtienne Carriere 	_DIV_Q,
164*6b651796SEtienne Carriere 	_DIV_R,
165*6b651796SEtienne Carriere 	_DIV_NB,
166*6b651796SEtienne Carriere };
167*6b651796SEtienne Carriere 
168*6b651796SEtienne Carriere enum stm32mp1_plltype {
169*6b651796SEtienne Carriere 	PLL_800,
170*6b651796SEtienne Carriere 	PLL_1600,
171*6b651796SEtienne Carriere 	PLL_TYPE_NB
172*6b651796SEtienne Carriere };
173*6b651796SEtienne Carriere 
174*6b651796SEtienne Carriere /*
175*6b651796SEtienne Carriere  * Clock generic gates clocks which state is controlled by a single RCC bit
176*6b651796SEtienne Carriere  *
177*6b651796SEtienne Carriere  * @offset: RCC register byte offset from RCC base where clock is controlled
178*6b651796SEtienne Carriere  * @bit: Bit position in the RCC 32bit register
179*6b651796SEtienne Carriere  * @clock_id: Identifier used for the clock in the clock driver API
180*6b651796SEtienne Carriere  * @set_clr: Non-null if and only-if RCC register is a CLEAR/SET register
181*6b651796SEtienne Carriere  *	(CLEAR register is at offset RCC_MP_ENCLRR_OFFSET from SET register)
182*6b651796SEtienne Carriere  * @secure: One of N_S or SEC, defined below
183*6b651796SEtienne Carriere  * @sel: _UNKNOWN_ID (fixed parent) or reference to parent clock selector
184*6b651796SEtienne Carriere  *	(8bit storage of ID from enum stm32mp1_parent_sel)
185*6b651796SEtienne Carriere  * @fixed: _UNKNOWN_ID (selectable paranet) or reference to parent clock
186*6b651796SEtienne Carriere  *	(8bit storage of ID from enum stm32mp1_parent_id)
187*6b651796SEtienne Carriere  */
188*6b651796SEtienne Carriere struct stm32mp1_clk_gate {
189*6b651796SEtienne Carriere 	uint16_t offset;
190*6b651796SEtienne Carriere 	uint8_t bit;
191*6b651796SEtienne Carriere 	uint8_t clock_id;
192*6b651796SEtienne Carriere 	uint8_t set_clr;
193*6b651796SEtienne Carriere 	uint8_t secure;
194*6b651796SEtienne Carriere 	uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
195*6b651796SEtienne Carriere 	uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
196*6b651796SEtienne Carriere };
197*6b651796SEtienne Carriere 
198*6b651796SEtienne Carriere /* Parent clock selection: select register info, parent clocks references */
199*6b651796SEtienne Carriere struct stm32mp1_clk_sel {
200*6b651796SEtienne Carriere 	uint16_t offset;
201*6b651796SEtienne Carriere 	uint8_t src;
202*6b651796SEtienne Carriere 	uint8_t msk;
203*6b651796SEtienne Carriere 	uint8_t nb_parent;
204*6b651796SEtienne Carriere 	const uint8_t *parent;
205*6b651796SEtienne Carriere };
206*6b651796SEtienne Carriere 
207*6b651796SEtienne Carriere #define REFCLK_SIZE 4
208*6b651796SEtienne Carriere /* PLL control: type, control register offsets, up-to-4 selectable parent */
209*6b651796SEtienne Carriere struct stm32mp1_clk_pll {
210*6b651796SEtienne Carriere 	enum stm32mp1_plltype plltype;
211*6b651796SEtienne Carriere 	uint16_t rckxselr;
212*6b651796SEtienne Carriere 	uint16_t pllxcfgr1;
213*6b651796SEtienne Carriere 	uint16_t pllxcfgr2;
214*6b651796SEtienne Carriere 	uint16_t pllxfracr;
215*6b651796SEtienne Carriere 	uint16_t pllxcr;
216*6b651796SEtienne Carriere 	uint16_t pllxcsgr;
217*6b651796SEtienne Carriere 	enum stm32mp_osc_id refclk[REFCLK_SIZE];
218*6b651796SEtienne Carriere };
219*6b651796SEtienne Carriere 
220*6b651796SEtienne Carriere #define N_S	0	/* Non-secure can access RCC interface */
221*6b651796SEtienne Carriere #define SEC	1	/* RCC[TZEN] protects RCC interface */
222*6b651796SEtienne Carriere 
223*6b651796SEtienne Carriere /* Clocks with selectable source and not set/clr register access */
224*6b651796SEtienne Carriere #define _CLK_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel)	\
225*6b651796SEtienne Carriere 	{							\
226*6b651796SEtienne Carriere 		.offset = (_offset),				\
227*6b651796SEtienne Carriere 		.bit = (_bit),					\
228*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
229*6b651796SEtienne Carriere 		.set_clr = 0,					\
230*6b651796SEtienne Carriere 		.secure = (_sec),				\
231*6b651796SEtienne Carriere 		.sel = (_parent_sel),				\
232*6b651796SEtienne Carriere 		.fixed = _UNKNOWN_ID,				\
233*6b651796SEtienne Carriere 	}
234*6b651796SEtienne Carriere 
235*6b651796SEtienne Carriere /* Clocks with fixed source and not set/clr register access */
236*6b651796SEtienne Carriere #define _CLK_FIXED(_sec, _offset, _bit, _clock_id, _parent)		\
237*6b651796SEtienne Carriere 	{							\
238*6b651796SEtienne Carriere 		.offset = (_offset),				\
239*6b651796SEtienne Carriere 		.bit = (_bit),					\
240*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
241*6b651796SEtienne Carriere 		.set_clr = 0,					\
242*6b651796SEtienne Carriere 		.secure = (_sec),				\
243*6b651796SEtienne Carriere 		.sel = _UNKNOWN_SEL,				\
244*6b651796SEtienne Carriere 		.fixed = (_parent),				\
245*6b651796SEtienne Carriere 	}
246*6b651796SEtienne Carriere 
247*6b651796SEtienne Carriere /* Clocks with selectable source and set/clr register access */
248*6b651796SEtienne Carriere #define _CLK_SC_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel)	\
249*6b651796SEtienne Carriere 	{							\
250*6b651796SEtienne Carriere 		.offset = (_offset),				\
251*6b651796SEtienne Carriere 		.bit = (_bit),					\
252*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
253*6b651796SEtienne Carriere 		.set_clr = 1,					\
254*6b651796SEtienne Carriere 		.secure = (_sec),				\
255*6b651796SEtienne Carriere 		.sel = (_parent_sel),				\
256*6b651796SEtienne Carriere 		.fixed = _UNKNOWN_ID,				\
257*6b651796SEtienne Carriere 	}
258*6b651796SEtienne Carriere 
259*6b651796SEtienne Carriere /* Clocks with fixed source and set/clr register access */
260*6b651796SEtienne Carriere #define _CLK_SC_FIXED(_sec, _offset, _bit, _clock_id, _parent)	\
261*6b651796SEtienne Carriere 	{							\
262*6b651796SEtienne Carriere 		.offset = (_offset),				\
263*6b651796SEtienne Carriere 		.bit = (_bit),					\
264*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
265*6b651796SEtienne Carriere 		.set_clr = 1,					\
266*6b651796SEtienne Carriere 		.secure = (_sec),				\
267*6b651796SEtienne Carriere 		.sel = _UNKNOWN_SEL,				\
268*6b651796SEtienne Carriere 		.fixed = (_parent),				\
269*6b651796SEtienne Carriere 	}
270*6b651796SEtienne Carriere 
271*6b651796SEtienne Carriere /*
272*6b651796SEtienne Carriere  * Clocks with selectable source and set/clr register access
273*6b651796SEtienne Carriere  * and enable bit position defined by a label (argument _bit)
274*6b651796SEtienne Carriere  */
275*6b651796SEtienne Carriere #define _CLK_SC2_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel)	\
276*6b651796SEtienne Carriere 	{							\
277*6b651796SEtienne Carriere 		.offset = (_offset),				\
278*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
279*6b651796SEtienne Carriere 		.bit = _offset ## _ ## _bit ## _POS,		\
280*6b651796SEtienne Carriere 		.set_clr = 1,					\
281*6b651796SEtienne Carriere 		.secure = (_sec),				\
282*6b651796SEtienne Carriere 		.sel = (_parent_sel),				\
283*6b651796SEtienne Carriere 		.fixed = _UNKNOWN_ID,				\
284*6b651796SEtienne Carriere 	}
285*6b651796SEtienne Carriere #define _CLK_SC2_FIXED(_sec, _offset, _bit, _clock_id, _parent)	\
286*6b651796SEtienne Carriere 	{							\
287*6b651796SEtienne Carriere 		.offset = (_offset),				\
288*6b651796SEtienne Carriere 		.clock_id = (_clock_id),			\
289*6b651796SEtienne Carriere 		.bit = _offset ## _ ## _bit ## _POS,		\
290*6b651796SEtienne Carriere 		.set_clr = 1,					\
291*6b651796SEtienne Carriere 		.secure = (_sec),				\
292*6b651796SEtienne Carriere 		.sel = _UNKNOWN_SEL,				\
293*6b651796SEtienne Carriere 		.fixed = (_parent),				\
294*6b651796SEtienne Carriere 	}
295*6b651796SEtienne Carriere 
296*6b651796SEtienne Carriere #define _CLK_PARENT(idx, _offset, _src, _mask, _parent)		\
297*6b651796SEtienne Carriere 	[(idx)] = {						\
298*6b651796SEtienne Carriere 		.offset = (_offset),				\
299*6b651796SEtienne Carriere 		.src = (_src),					\
300*6b651796SEtienne Carriere 		.msk = (_mask),					\
301*6b651796SEtienne Carriere 		.parent = (_parent),				\
302*6b651796SEtienne Carriere 		.nb_parent = ARRAY_SIZE(_parent)		\
303*6b651796SEtienne Carriere 	}
304*6b651796SEtienne Carriere 
305*6b651796SEtienne Carriere #define _CLK_PLL(_idx, _type, _off1, _off2, _off3, _off4,	\
306*6b651796SEtienne Carriere 		 _off5, _off6, _p1, _p2, _p3, _p4)		\
307*6b651796SEtienne Carriere 	[(_idx)] = {						\
308*6b651796SEtienne Carriere 		.plltype = (_type),				\
309*6b651796SEtienne Carriere 		.rckxselr = (_off1),				\
310*6b651796SEtienne Carriere 		.pllxcfgr1 = (_off2),				\
311*6b651796SEtienne Carriere 		.pllxcfgr2 = (_off3),				\
312*6b651796SEtienne Carriere 		.pllxfracr = (_off4),				\
313*6b651796SEtienne Carriere 		.pllxcr = (_off5),				\
314*6b651796SEtienne Carriere 		.pllxcsgr = (_off6),				\
315*6b651796SEtienne Carriere 		.refclk[0] = (_p1),				\
316*6b651796SEtienne Carriere 		.refclk[1] = (_p2),				\
317*6b651796SEtienne Carriere 		.refclk[2] = (_p3),				\
318*6b651796SEtienne Carriere 		.refclk[3] = (_p4),				\
319*6b651796SEtienne Carriere 	}
320*6b651796SEtienne Carriere 
321*6b651796SEtienne Carriere #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
322*6b651796SEtienne Carriere 
323*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
324*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK),
325*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
326*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK),
327*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
328*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
329*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
330*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
331*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
332*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK),
333*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
334*6b651796SEtienne Carriere 	_CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
335*6b651796SEtienne Carriere 
336*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, SPI6EN, SPI6_K, _SPI6_SEL),
337*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C4EN, I2C4_K, _I2C46_SEL),
338*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C6EN, I2C6_K, _I2C46_SEL),
339*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, USART1EN, USART1_K, _USART1_SEL),
340*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, RTCAPBEN, RTCAPB, _PCLK5),
341*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC1EN, TZC1, _PCLK5),
342*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC2EN, TZC2, _PCLK5),
343*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZPCEN, TZPC, _PCLK5),
344*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, IWDG1APBEN, IWDG1, _PCLK5),
345*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5),
346*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL),
347*6b651796SEtienne Carriere 
348*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _HCLK5),
349*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _HCLK5),
350*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _HCLK5),
351*6b651796SEtienne Carriere 	_CLK_SC2_SELEC(SEC, RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL),
352*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _PCLK5),
353*6b651796SEtienne Carriere 
354*6b651796SEtienne Carriere 	_CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _HCLK6),
355*6b651796SEtienne Carriere 
356*6b651796SEtienne Carriere 	_CLK_SELEC(SEC, RCC_BDCR, RCC_BDCR_RTCCKEN_POS, RTC, _RTC_SEL),
357*6b651796SEtienne Carriere 
358*6b651796SEtienne Carriere 	/* Non-secure clocks */
359*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_GPIOS
360*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_ID),
361*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_ID),
362*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_ID),
363*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_ID),
364*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_ID),
365*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_ID),
366*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_ID),
367*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_ID),
368*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_ID),
369*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_ID),
370*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_ID),
371*6b651796SEtienne Carriere #endif
372*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
373*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS
374*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
375*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
376*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
377*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
378*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
379*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
380*6b651796SEtienne Carriere #endif
381*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
382*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS
383*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
384*6b651796SEtienne Carriere #endif
385*6b651796SEtienne Carriere 	_CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
386*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
387*6b651796SEtienne Carriere 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
388*6b651796SEtienne Carriere 
389*6b651796SEtienne Carriere 	_CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
390*6b651796SEtienne Carriere };
391*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(stm32mp1_clk_gate);
392*6b651796SEtienne Carriere 
393*6b651796SEtienne Carriere const uint8_t stm32mp1_clk_on[] = {
394*6b651796SEtienne Carriere 	CK_HSE, CK_CSI, CK_LSI, CK_LSE, CK_HSI, CK_HSE_DIV2,
395*6b651796SEtienne Carriere 	PLL1_P, PLL1_Q, PLL1_R, PLL2_P, PLL2_Q, PLL2_R, PLL3_P, PLL3_Q, PLL3_R,
396*6b651796SEtienne Carriere 	CK_AXI, CK_MPU, CK_MCU,
397*6b651796SEtienne Carriere };
398*6b651796SEtienne Carriere 
399*6b651796SEtienne Carriere /* Parents for secure aware clocks in the xxxSELR value ordering */
400*6b651796SEtienne Carriere static const uint8_t stgen_parents[] = {
401*6b651796SEtienne Carriere 	_HSI_KER, _HSE_KER
402*6b651796SEtienne Carriere };
403*6b651796SEtienne Carriere 
404*6b651796SEtienne Carriere static const uint8_t i2c46_parents[] = {
405*6b651796SEtienne Carriere 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
406*6b651796SEtienne Carriere };
407*6b651796SEtienne Carriere 
408*6b651796SEtienne Carriere static const uint8_t spi6_parents[] = {
409*6b651796SEtienne Carriere 	_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
410*6b651796SEtienne Carriere };
411*6b651796SEtienne Carriere 
412*6b651796SEtienne Carriere static const uint8_t usart1_parents[] = {
413*6b651796SEtienne Carriere 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
414*6b651796SEtienne Carriere };
415*6b651796SEtienne Carriere 
416*6b651796SEtienne Carriere static const uint8_t rng1_parents[] = {
417*6b651796SEtienne Carriere 	_CSI, _PLL4_R, _LSE, _LSI
418*6b651796SEtienne Carriere };
419*6b651796SEtienne Carriere 
420*6b651796SEtienne Carriere /* Parents for (some) non-secure clocks */
421*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS
422*6b651796SEtienne Carriere static const uint8_t uart6_parents[] = {
423*6b651796SEtienne Carriere 	_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
424*6b651796SEtienne Carriere };
425*6b651796SEtienne Carriere 
426*6b651796SEtienne Carriere static const uint8_t uart234578_parents[] = {
427*6b651796SEtienne Carriere 	_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
428*6b651796SEtienne Carriere };
429*6b651796SEtienne Carriere #endif
430*6b651796SEtienne Carriere 
431*6b651796SEtienne Carriere static const uint8_t axiss_parents[] = {
432*6b651796SEtienne Carriere 	_HSI, _HSE, _PLL2_P
433*6b651796SEtienne Carriere };
434*6b651796SEtienne Carriere 
435*6b651796SEtienne Carriere static const uint8_t mcuss_parents[] = {
436*6b651796SEtienne Carriere 	_HSI, _HSE, _CSI, _PLL3_P
437*6b651796SEtienne Carriere };
438*6b651796SEtienne Carriere 
439*6b651796SEtienne Carriere static const uint8_t rtc_parents[] = {
440*6b651796SEtienne Carriere 	_UNKNOWN_ID, _LSE, _LSI, _HSE
441*6b651796SEtienne Carriere };
442*6b651796SEtienne Carriere 
443*6b651796SEtienne Carriere static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
444*6b651796SEtienne Carriere 	/* Secure aware clocks */
445*6b651796SEtienne Carriere 	_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
446*6b651796SEtienne Carriere 	_CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents),
447*6b651796SEtienne Carriere 	_CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents),
448*6b651796SEtienne Carriere 	_CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents),
449*6b651796SEtienne Carriere 	_CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents),
450*6b651796SEtienne Carriere 	_CLK_PARENT(_RTC_SEL, RCC_BDCR, 0, 0x3, rtc_parents),
451*6b651796SEtienne Carriere 	/* Always non-secure clocks (maybe used in some way in secure world) */
452*6b651796SEtienne Carriere #ifdef CFG_WITH_NSEC_UARTS
453*6b651796SEtienne Carriere 	_CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents),
454*6b651796SEtienne Carriere 	_CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents),
455*6b651796SEtienne Carriere 	_CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents),
456*6b651796SEtienne Carriere 	_CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents),
457*6b651796SEtienne Carriere #endif
458*6b651796SEtienne Carriere 	_CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents),
459*6b651796SEtienne Carriere 	_CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents),
460*6b651796SEtienne Carriere };
461*6b651796SEtienne Carriere 
462*6b651796SEtienne Carriere /* PLLNCFGR2 register divider by output */
463*6b651796SEtienne Carriere static const uint8_t pllncfgr2[_DIV_NB] = {
464*6b651796SEtienne Carriere 	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
465*6b651796SEtienne Carriere 	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
466*6b651796SEtienne Carriere 	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
467*6b651796SEtienne Carriere };
468*6b651796SEtienne Carriere 
469*6b651796SEtienne Carriere static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
470*6b651796SEtienne Carriere 	_CLK_PLL(_PLL1, PLL_1600,
471*6b651796SEtienne Carriere 		 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
472*6b651796SEtienne Carriere 		 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
473*6b651796SEtienne Carriere 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
474*6b651796SEtienne Carriere 	_CLK_PLL(_PLL2, PLL_1600,
475*6b651796SEtienne Carriere 		 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
476*6b651796SEtienne Carriere 		 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
477*6b651796SEtienne Carriere 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
478*6b651796SEtienne Carriere 	_CLK_PLL(_PLL3, PLL_800,
479*6b651796SEtienne Carriere 		 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
480*6b651796SEtienne Carriere 		 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
481*6b651796SEtienne Carriere 		 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
482*6b651796SEtienne Carriere 	_CLK_PLL(_PLL4, PLL_800,
483*6b651796SEtienne Carriere 		 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
484*6b651796SEtienne Carriere 		 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
485*6b651796SEtienne Carriere 		 _HSI, _HSE, _CSI, _I2S_CKIN),
486*6b651796SEtienne Carriere };
487*6b651796SEtienne Carriere 
488*6b651796SEtienne Carriere /* Prescaler table lookups for clock computation */
489*6b651796SEtienne Carriere /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
490*6b651796SEtienne Carriere static const uint8_t stm32mp1_mcu_div[16] = {
491*6b651796SEtienne Carriere 	0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
492*6b651796SEtienne Carriere };
493*6b651796SEtienne Carriere 
494*6b651796SEtienne Carriere /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
495*6b651796SEtienne Carriere #define stm32mp1_mpu_div	stm32mp1_mpu_apbx_div
496*6b651796SEtienne Carriere #define stm32mp1_apbx_div	stm32mp1_mpu_apbx_div
497*6b651796SEtienne Carriere static const uint8_t stm32mp1_mpu_apbx_div[8] = {
498*6b651796SEtienne Carriere 	0, 1, 2, 3, 4, 4, 4, 4
499*6b651796SEtienne Carriere };
500*6b651796SEtienne Carriere 
501*6b651796SEtienne Carriere /* div = /1 /2 /3 /4 */
502*6b651796SEtienne Carriere static const uint8_t stm32mp1_axi_div[8] = {
503*6b651796SEtienne Carriere 	1, 2, 3, 4, 4, 4, 4, 4
504*6b651796SEtienne Carriere };
505*6b651796SEtienne Carriere 
506*6b651796SEtienne Carriere static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = {
507*6b651796SEtienne Carriere 	[_HSI] = "HSI",
508*6b651796SEtienne Carriere 	[_HSE] = "HSE",
509*6b651796SEtienne Carriere 	[_CSI] = "CSI",
510*6b651796SEtienne Carriere 	[_LSI] = "LSI",
511*6b651796SEtienne Carriere 	[_LSE] = "LSE",
512*6b651796SEtienne Carriere 	[_I2S_CKIN] = "I2S_CKIN",
513*6b651796SEtienne Carriere 	[_HSI_KER] = "HSI_KER",
514*6b651796SEtienne Carriere 	[_HSE_KER] = "HSE_KER",
515*6b651796SEtienne Carriere 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
516*6b651796SEtienne Carriere 	[_CSI_KER] = "CSI_KER",
517*6b651796SEtienne Carriere 	[_PLL1_P] = "PLL1_P",
518*6b651796SEtienne Carriere 	[_PLL1_Q] = "PLL1_Q",
519*6b651796SEtienne Carriere 	[_PLL1_R] = "PLL1_R",
520*6b651796SEtienne Carriere 	[_PLL2_P] = "PLL2_P",
521*6b651796SEtienne Carriere 	[_PLL2_Q] = "PLL2_Q",
522*6b651796SEtienne Carriere 	[_PLL2_R] = "PLL2_R",
523*6b651796SEtienne Carriere 	[_PLL3_P] = "PLL3_P",
524*6b651796SEtienne Carriere 	[_PLL3_Q] = "PLL3_Q",
525*6b651796SEtienne Carriere 	[_PLL3_R] = "PLL3_R",
526*6b651796SEtienne Carriere 	[_PLL4_P] = "PLL4_P",
527*6b651796SEtienne Carriere 	[_PLL4_Q] = "PLL4_Q",
528*6b651796SEtienne Carriere 	[_PLL4_R] = "PLL4_R",
529*6b651796SEtienne Carriere 	[_ACLK] = "ACLK",
530*6b651796SEtienne Carriere 	[_PCLK1] = "PCLK1",
531*6b651796SEtienne Carriere 	[_PCLK2] = "PCLK2",
532*6b651796SEtienne Carriere 	[_PCLK3] = "PCLK3",
533*6b651796SEtienne Carriere 	[_PCLK4] = "PCLK4",
534*6b651796SEtienne Carriere 	[_PCLK5] = "PCLK5",
535*6b651796SEtienne Carriere 	[_HCLK5] = "HCLK5",
536*6b651796SEtienne Carriere 	[_HCLK6] = "HCLK6",
537*6b651796SEtienne Carriere 	[_HCLK2] = "HCLK2",
538*6b651796SEtienne Carriere 	[_CK_PER] = "CK_PER",
539*6b651796SEtienne Carriere 	[_CK_MPU] = "CK_MPU",
540*6b651796SEtienne Carriere 	[_CK_MCU] = "CK_MCU",
541*6b651796SEtienne Carriere 	[_USB_PHY_48] = "USB_PHY_48",
542*6b651796SEtienne Carriere };
543*6b651796SEtienne Carriere 
544*6b651796SEtienne Carriere /*
545*6b651796SEtienne Carriere  * Oscillator frequency in Hz. This array shall be initialized
546*6b651796SEtienne Carriere  * according to platform.
547*6b651796SEtienne Carriere  */
548*6b651796SEtienne Carriere static unsigned long stm32mp1_osc[NB_OSC];
549*6b651796SEtienne Carriere 
550*6b651796SEtienne Carriere static unsigned long osc_frequency(enum stm32mp_osc_id idx)
551*6b651796SEtienne Carriere {
552*6b651796SEtienne Carriere 	if (idx >= ARRAY_SIZE(stm32mp1_osc)) {
553*6b651796SEtienne Carriere 		DMSG("clk id %d not found", idx);
554*6b651796SEtienne Carriere 		return 0;
555*6b651796SEtienne Carriere 	}
556*6b651796SEtienne Carriere 
557*6b651796SEtienne Carriere 	return stm32mp1_osc[idx];
558*6b651796SEtienne Carriere }
559*6b651796SEtienne Carriere 
560*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
561*6b651796SEtienne Carriere {
562*6b651796SEtienne Carriere 	return &stm32mp1_clk_gate[idx];
563*6b651796SEtienne Carriere }
564*6b651796SEtienne Carriere 
565*6b651796SEtienne Carriere static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
566*6b651796SEtienne Carriere {
567*6b651796SEtienne Carriere 	return &stm32mp1_clk_sel[idx];
568*6b651796SEtienne Carriere }
569*6b651796SEtienne Carriere 
570*6b651796SEtienne Carriere static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
571*6b651796SEtienne Carriere {
572*6b651796SEtienne Carriere 	return &stm32mp1_clk_pll[idx];
573*6b651796SEtienne Carriere }
574*6b651796SEtienne Carriere 
575*6b651796SEtienne Carriere static int stm32mp1_clk_get_gated_id(unsigned long id)
576*6b651796SEtienne Carriere {
577*6b651796SEtienne Carriere 	unsigned int i = 0;
578*6b651796SEtienne Carriere 
579*6b651796SEtienne Carriere 	for (i = 0; i < NB_GATES; i++)
580*6b651796SEtienne Carriere 		if (gate_ref(i)->clock_id == id)
581*6b651796SEtienne Carriere 			return i;
582*6b651796SEtienne Carriere 
583*6b651796SEtienne Carriere 	DMSG("clk id %lu not found", id);
584*6b651796SEtienne Carriere 	return -1;
585*6b651796SEtienne Carriere }
586*6b651796SEtienne Carriere 
587*6b651796SEtienne Carriere static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
588*6b651796SEtienne Carriere {
589*6b651796SEtienne Carriere 	return (enum stm32mp1_parent_sel)gate_ref(i)->sel;
590*6b651796SEtienne Carriere }
591*6b651796SEtienne Carriere 
592*6b651796SEtienne Carriere static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
593*6b651796SEtienne Carriere {
594*6b651796SEtienne Carriere 	return (enum stm32mp1_parent_id)gate_ref(i)->fixed;
595*6b651796SEtienne Carriere }
596*6b651796SEtienne Carriere 
597*6b651796SEtienne Carriere static int stm32mp1_clk_get_parent(unsigned long id)
598*6b651796SEtienne Carriere {
599*6b651796SEtienne Carriere 	const struct stm32mp1_clk_sel *sel = NULL;
600*6b651796SEtienne Carriere 	enum stm32mp1_parent_id parent_id = 0;
601*6b651796SEtienne Carriere 	uint32_t p_sel = 0;
602*6b651796SEtienne Carriere 	int i = 0;
603*6b651796SEtienne Carriere 	enum stm32mp1_parent_id p = _UNKNOWN_ID;
604*6b651796SEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
605*6b651796SEtienne Carriere 	vaddr_t rcc_base = stm32_rcc_base();
606*6b651796SEtienne Carriere 
607*6b651796SEtienne Carriere 	parent_id = clock_id2parent_id(id);
608*6b651796SEtienne Carriere 	if (parent_id != _UNKNOWN_ID)
609*6b651796SEtienne Carriere 		return (int)parent_id;
610*6b651796SEtienne Carriere 
611*6b651796SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
612*6b651796SEtienne Carriere 	if (i < 0)
613*6b651796SEtienne Carriere 		panic();
614*6b651796SEtienne Carriere 
615*6b651796SEtienne Carriere 	p = stm32mp1_clk_get_fixed_parent(i);
616*6b651796SEtienne Carriere 	if (p < _PARENT_NB)
617*6b651796SEtienne Carriere 		return (int)p;
618*6b651796SEtienne Carriere 
619*6b651796SEtienne Carriere 	s = stm32mp1_clk_get_sel(i);
620*6b651796SEtienne Carriere 	if (s == _UNKNOWN_SEL)
621*6b651796SEtienne Carriere 		return -1;
622*6b651796SEtienne Carriere 	if (s >= _PARENT_SEL_NB)
623*6b651796SEtienne Carriere 		panic();
624*6b651796SEtienne Carriere 
625*6b651796SEtienne Carriere 	sel = clk_sel_ref(s);
626*6b651796SEtienne Carriere 	p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & sel->msk;
627*6b651796SEtienne Carriere 	if (p_sel < sel->nb_parent)
628*6b651796SEtienne Carriere 		return (int)sel->parent[p_sel];
629*6b651796SEtienne Carriere 
630*6b651796SEtienne Carriere 	DMSG("No parent selected for clk %lu", id);
631*6b651796SEtienne Carriere 	return -1;
632*6b651796SEtienne Carriere }
633*6b651796SEtienne Carriere 
634*6b651796SEtienne Carriere static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
635*6b651796SEtienne Carriere {
636*6b651796SEtienne Carriere 	uint32_t selr = io_read32(stm32_rcc_base() + pll->rckxselr);
637*6b651796SEtienne Carriere 	uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
638*6b651796SEtienne Carriere 
639*6b651796SEtienne Carriere 	return osc_frequency(pll->refclk[src]);
640*6b651796SEtienne Carriere }
641*6b651796SEtienne Carriere 
642*6b651796SEtienne Carriere /*
643*6b651796SEtienne Carriere  * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
644*6b651796SEtienne Carriere  * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
645*6b651796SEtienne Carriere  * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
646*6b651796SEtienne Carriere  * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
647*6b651796SEtienne Carriere  */
648*6b651796SEtienne Carriere static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
649*6b651796SEtienne Carriere {
650*6b651796SEtienne Carriere 	unsigned long refclk = 0;
651*6b651796SEtienne Carriere 	unsigned long fvco = 0;
652*6b651796SEtienne Carriere 	uint32_t cfgr1 = 0;
653*6b651796SEtienne Carriere 	uint32_t fracr = 0;
654*6b651796SEtienne Carriere 	uint32_t divm = 0;
655*6b651796SEtienne Carriere 	uint32_t divn = 0;
656*6b651796SEtienne Carriere 
657*6b651796SEtienne Carriere 	cfgr1 = io_read32(stm32_rcc_base() + pll->pllxcfgr1);
658*6b651796SEtienne Carriere 	fracr = io_read32(stm32_rcc_base() + pll->pllxfracr);
659*6b651796SEtienne Carriere 
660*6b651796SEtienne Carriere 	divm = (cfgr1 & RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT;
661*6b651796SEtienne Carriere 	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
662*6b651796SEtienne Carriere 
663*6b651796SEtienne Carriere 	refclk = stm32mp1_pll_get_fref(pll);
664*6b651796SEtienne Carriere 
665*6b651796SEtienne Carriere 	/*
666*6b651796SEtienne Carriere 	 * With FRACV :
667*6b651796SEtienne Carriere 	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
668*6b651796SEtienne Carriere 	 * Without FRACV
669*6b651796SEtienne Carriere 	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
670*6b651796SEtienne Carriere 	 */
671*6b651796SEtienne Carriere 	if (fracr & RCC_PLLNFRACR_FRACLE) {
672*6b651796SEtienne Carriere 		unsigned long long numerator = 0;
673*6b651796SEtienne Carriere 		unsigned long long denominator = 0;
674*6b651796SEtienne Carriere 		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
675*6b651796SEtienne Carriere 				 RCC_PLLNFRACR_FRACV_SHIFT;
676*6b651796SEtienne Carriere 
677*6b651796SEtienne Carriere 		numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
678*6b651796SEtienne Carriere 		numerator = refclk * numerator;
679*6b651796SEtienne Carriere 		denominator = ((unsigned long long)divm + 1U) << 13;
680*6b651796SEtienne Carriere 		fvco = (unsigned long)(numerator / denominator);
681*6b651796SEtienne Carriere 	} else {
682*6b651796SEtienne Carriere 		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
683*6b651796SEtienne Carriere 	}
684*6b651796SEtienne Carriere 
685*6b651796SEtienne Carriere 	return fvco;
686*6b651796SEtienne Carriere }
687*6b651796SEtienne Carriere 
688*6b651796SEtienne Carriere static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
689*6b651796SEtienne Carriere 					    enum stm32mp1_div_id div_id)
690*6b651796SEtienne Carriere {
691*6b651796SEtienne Carriere 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
692*6b651796SEtienne Carriere 	unsigned long dfout = 0;
693*6b651796SEtienne Carriere 	uint32_t cfgr2 = 0;
694*6b651796SEtienne Carriere 	uint32_t divy = 0;
695*6b651796SEtienne Carriere 
696*6b651796SEtienne Carriere 	if (div_id >= _DIV_NB)
697*6b651796SEtienne Carriere 		return 0;
698*6b651796SEtienne Carriere 
699*6b651796SEtienne Carriere 	cfgr2 = io_read32(stm32_rcc_base() + pll->pllxcfgr2);
700*6b651796SEtienne Carriere 	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
701*6b651796SEtienne Carriere 
702*6b651796SEtienne Carriere 	dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
703*6b651796SEtienne Carriere 
704*6b651796SEtienne Carriere 	return dfout;
705*6b651796SEtienne Carriere }
706*6b651796SEtienne Carriere 
707*6b651796SEtienne Carriere static unsigned long get_clock_rate(int p)
708*6b651796SEtienne Carriere {
709*6b651796SEtienne Carriere 	uint32_t reg = 0;
710*6b651796SEtienne Carriere 	unsigned long clock = 0;
711*6b651796SEtienne Carriere 	vaddr_t rcc_base = stm32_rcc_base();
712*6b651796SEtienne Carriere 
713*6b651796SEtienne Carriere 	switch (p) {
714*6b651796SEtienne Carriere 	case _CK_MPU:
715*6b651796SEtienne Carriere 	/* MPU sub system */
716*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_MPCKSELR);
717*6b651796SEtienne Carriere 		switch (reg & RCC_SELR_SRC_MASK) {
718*6b651796SEtienne Carriere 		case RCC_MPCKSELR_HSI:
719*6b651796SEtienne Carriere 			clock = osc_frequency(_HSI);
720*6b651796SEtienne Carriere 			break;
721*6b651796SEtienne Carriere 		case RCC_MPCKSELR_HSE:
722*6b651796SEtienne Carriere 			clock = osc_frequency(_HSE);
723*6b651796SEtienne Carriere 			break;
724*6b651796SEtienne Carriere 		case RCC_MPCKSELR_PLL:
725*6b651796SEtienne Carriere 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
726*6b651796SEtienne Carriere 			break;
727*6b651796SEtienne Carriere 		case RCC_MPCKSELR_PLL_MPUDIV:
728*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_MPCKDIVR);
729*6b651796SEtienne Carriere 			if (reg & RCC_MPUDIV_MASK)
730*6b651796SEtienne Carriere 				clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P) >>
731*6b651796SEtienne Carriere 					stm32mp1_mpu_div[reg & RCC_MPUDIV_MASK];
732*6b651796SEtienne Carriere 			else
733*6b651796SEtienne Carriere 				clock = 0;
734*6b651796SEtienne Carriere 			break;
735*6b651796SEtienne Carriere 		default:
736*6b651796SEtienne Carriere 			break;
737*6b651796SEtienne Carriere 		}
738*6b651796SEtienne Carriere 		break;
739*6b651796SEtienne Carriere 	/* AXI sub system */
740*6b651796SEtienne Carriere 	case _ACLK:
741*6b651796SEtienne Carriere 	case _HCLK2:
742*6b651796SEtienne Carriere 	case _HCLK5:
743*6b651796SEtienne Carriere 	case _HCLK6:
744*6b651796SEtienne Carriere 	case _PCLK4:
745*6b651796SEtienne Carriere 	case _PCLK5:
746*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_ASSCKSELR);
747*6b651796SEtienne Carriere 		switch (reg & RCC_SELR_SRC_MASK) {
748*6b651796SEtienne Carriere 		case RCC_ASSCKSELR_HSI:
749*6b651796SEtienne Carriere 			clock = osc_frequency(_HSI);
750*6b651796SEtienne Carriere 			break;
751*6b651796SEtienne Carriere 		case RCC_ASSCKSELR_HSE:
752*6b651796SEtienne Carriere 			clock = osc_frequency(_HSE);
753*6b651796SEtienne Carriere 			break;
754*6b651796SEtienne Carriere 		case RCC_ASSCKSELR_PLL:
755*6b651796SEtienne Carriere 			clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
756*6b651796SEtienne Carriere 			break;
757*6b651796SEtienne Carriere 		default:
758*6b651796SEtienne Carriere 			break;
759*6b651796SEtienne Carriere 		}
760*6b651796SEtienne Carriere 
761*6b651796SEtienne Carriere 		/* System clock divider */
762*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_AXIDIVR);
763*6b651796SEtienne Carriere 		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
764*6b651796SEtienne Carriere 
765*6b651796SEtienne Carriere 		switch (p) {
766*6b651796SEtienne Carriere 		case _PCLK4:
767*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_APB4DIVR);
768*6b651796SEtienne Carriere 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
769*6b651796SEtienne Carriere 			break;
770*6b651796SEtienne Carriere 		case _PCLK5:
771*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_APB5DIVR);
772*6b651796SEtienne Carriere 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
773*6b651796SEtienne Carriere 			break;
774*6b651796SEtienne Carriere 		default:
775*6b651796SEtienne Carriere 			break;
776*6b651796SEtienne Carriere 		}
777*6b651796SEtienne Carriere 		break;
778*6b651796SEtienne Carriere 	/* MCU sub system */
779*6b651796SEtienne Carriere 	case _CK_MCU:
780*6b651796SEtienne Carriere 	case _PCLK1:
781*6b651796SEtienne Carriere 	case _PCLK2:
782*6b651796SEtienne Carriere 	case _PCLK3:
783*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_MSSCKSELR);
784*6b651796SEtienne Carriere 		switch (reg & RCC_SELR_SRC_MASK) {
785*6b651796SEtienne Carriere 		case RCC_MSSCKSELR_HSI:
786*6b651796SEtienne Carriere 			clock = osc_frequency(_HSI);
787*6b651796SEtienne Carriere 			break;
788*6b651796SEtienne Carriere 		case RCC_MSSCKSELR_HSE:
789*6b651796SEtienne Carriere 			clock = osc_frequency(_HSE);
790*6b651796SEtienne Carriere 			break;
791*6b651796SEtienne Carriere 		case RCC_MSSCKSELR_CSI:
792*6b651796SEtienne Carriere 			clock = osc_frequency(_CSI);
793*6b651796SEtienne Carriere 			break;
794*6b651796SEtienne Carriere 		case RCC_MSSCKSELR_PLL:
795*6b651796SEtienne Carriere 			clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
796*6b651796SEtienne Carriere 			break;
797*6b651796SEtienne Carriere 		default:
798*6b651796SEtienne Carriere 			break;
799*6b651796SEtienne Carriere 		}
800*6b651796SEtienne Carriere 
801*6b651796SEtienne Carriere 		/* MCU clock divider */
802*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_MCUDIVR);
803*6b651796SEtienne Carriere 		clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
804*6b651796SEtienne Carriere 
805*6b651796SEtienne Carriere 		switch (p) {
806*6b651796SEtienne Carriere 		case _PCLK1:
807*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_APB1DIVR);
808*6b651796SEtienne Carriere 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
809*6b651796SEtienne Carriere 			break;
810*6b651796SEtienne Carriere 		case _PCLK2:
811*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_APB2DIVR);
812*6b651796SEtienne Carriere 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
813*6b651796SEtienne Carriere 			break;
814*6b651796SEtienne Carriere 		case _PCLK3:
815*6b651796SEtienne Carriere 			reg = io_read32(rcc_base + RCC_APB3DIVR);
816*6b651796SEtienne Carriere 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
817*6b651796SEtienne Carriere 			break;
818*6b651796SEtienne Carriere 		case _CK_MCU:
819*6b651796SEtienne Carriere 		default:
820*6b651796SEtienne Carriere 			break;
821*6b651796SEtienne Carriere 		}
822*6b651796SEtienne Carriere 		break;
823*6b651796SEtienne Carriere 	case _CK_PER:
824*6b651796SEtienne Carriere 		reg = io_read32(rcc_base + RCC_CPERCKSELR);
825*6b651796SEtienne Carriere 		switch (reg & RCC_SELR_SRC_MASK) {
826*6b651796SEtienne Carriere 		case RCC_CPERCKSELR_HSI:
827*6b651796SEtienne Carriere 			clock = osc_frequency(_HSI);
828*6b651796SEtienne Carriere 			break;
829*6b651796SEtienne Carriere 		case RCC_CPERCKSELR_HSE:
830*6b651796SEtienne Carriere 			clock = osc_frequency(_HSE);
831*6b651796SEtienne Carriere 			break;
832*6b651796SEtienne Carriere 		case RCC_CPERCKSELR_CSI:
833*6b651796SEtienne Carriere 			clock = osc_frequency(_CSI);
834*6b651796SEtienne Carriere 			break;
835*6b651796SEtienne Carriere 		default:
836*6b651796SEtienne Carriere 			break;
837*6b651796SEtienne Carriere 		}
838*6b651796SEtienne Carriere 		break;
839*6b651796SEtienne Carriere 	case _HSI:
840*6b651796SEtienne Carriere 	case _HSI_KER:
841*6b651796SEtienne Carriere 		clock = osc_frequency(_HSI);
842*6b651796SEtienne Carriere 		break;
843*6b651796SEtienne Carriere 	case _CSI:
844*6b651796SEtienne Carriere 	case _CSI_KER:
845*6b651796SEtienne Carriere 		clock = osc_frequency(_CSI);
846*6b651796SEtienne Carriere 		break;
847*6b651796SEtienne Carriere 	case _HSE:
848*6b651796SEtienne Carriere 	case _HSE_KER:
849*6b651796SEtienne Carriere 		clock = osc_frequency(_HSE);
850*6b651796SEtienne Carriere 		break;
851*6b651796SEtienne Carriere 	case _HSE_KER_DIV2:
852*6b651796SEtienne Carriere 		clock = osc_frequency(_HSE) >> 1;
853*6b651796SEtienne Carriere 		break;
854*6b651796SEtienne Carriere 	case _LSI:
855*6b651796SEtienne Carriere 		clock = osc_frequency(_LSI);
856*6b651796SEtienne Carriere 		break;
857*6b651796SEtienne Carriere 	case _LSE:
858*6b651796SEtienne Carriere 		clock = osc_frequency(_LSE);
859*6b651796SEtienne Carriere 		break;
860*6b651796SEtienne Carriere 	/* PLL */
861*6b651796SEtienne Carriere 	case _PLL1_P:
862*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
863*6b651796SEtienne Carriere 		break;
864*6b651796SEtienne Carriere 	case _PLL1_Q:
865*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
866*6b651796SEtienne Carriere 		break;
867*6b651796SEtienne Carriere 	case _PLL1_R:
868*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
869*6b651796SEtienne Carriere 		break;
870*6b651796SEtienne Carriere 	case _PLL2_P:
871*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
872*6b651796SEtienne Carriere 		break;
873*6b651796SEtienne Carriere 	case _PLL2_Q:
874*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
875*6b651796SEtienne Carriere 		break;
876*6b651796SEtienne Carriere 	case _PLL2_R:
877*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
878*6b651796SEtienne Carriere 		break;
879*6b651796SEtienne Carriere 	case _PLL3_P:
880*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
881*6b651796SEtienne Carriere 		break;
882*6b651796SEtienne Carriere 	case _PLL3_Q:
883*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
884*6b651796SEtienne Carriere 		break;
885*6b651796SEtienne Carriere 	case _PLL3_R:
886*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
887*6b651796SEtienne Carriere 		break;
888*6b651796SEtienne Carriere 	case _PLL4_P:
889*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
890*6b651796SEtienne Carriere 		break;
891*6b651796SEtienne Carriere 	case _PLL4_Q:
892*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
893*6b651796SEtienne Carriere 		break;
894*6b651796SEtienne Carriere 	case _PLL4_R:
895*6b651796SEtienne Carriere 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
896*6b651796SEtienne Carriere 		break;
897*6b651796SEtienne Carriere 	/* Other */
898*6b651796SEtienne Carriere 	case _USB_PHY_48:
899*6b651796SEtienne Carriere 		clock = osc_frequency(_USB_PHY_48);
900*6b651796SEtienne Carriere 		break;
901*6b651796SEtienne Carriere 	default:
902*6b651796SEtienne Carriere 		break;
903*6b651796SEtienne Carriere 	}
904*6b651796SEtienne Carriere 
905*6b651796SEtienne Carriere 	return clock;
906*6b651796SEtienne Carriere }
907*6b651796SEtienne Carriere 
908*6b651796SEtienne Carriere static void __clk_enable(const struct stm32mp1_clk_gate *gate)
909*6b651796SEtienne Carriere {
910*6b651796SEtienne Carriere 	vaddr_t base = stm32_rcc_base();
911*6b651796SEtienne Carriere 	uint32_t bit = BIT(gate->bit);
912*6b651796SEtienne Carriere 
913*6b651796SEtienne Carriere 	if (gate->set_clr)
914*6b651796SEtienne Carriere 		io_write32(base + gate->offset, bit);
915*6b651796SEtienne Carriere 	else
916*6b651796SEtienne Carriere 		io_setbits32_stm32shregs(base + gate->offset, bit);
917*6b651796SEtienne Carriere 
918*6b651796SEtienne Carriere 	FMSG("Clock %u has been enabled", gate->clock_id);
919*6b651796SEtienne Carriere }
920*6b651796SEtienne Carriere 
921*6b651796SEtienne Carriere static void __clk_disable(const struct stm32mp1_clk_gate *gate)
922*6b651796SEtienne Carriere {
923*6b651796SEtienne Carriere 	vaddr_t base = stm32_rcc_base();
924*6b651796SEtienne Carriere 	uint32_t bit = BIT(gate->bit);
925*6b651796SEtienne Carriere 
926*6b651796SEtienne Carriere 	if (gate->set_clr)
927*6b651796SEtienne Carriere 		io_write32(base + gate->offset + RCC_MP_ENCLRR_OFFSET, bit);
928*6b651796SEtienne Carriere 	else
929*6b651796SEtienne Carriere 		io_clrbits32_stm32shregs(base + gate->offset, bit);
930*6b651796SEtienne Carriere 
931*6b651796SEtienne Carriere 	FMSG("Clock %u has been disabled", gate->clock_id);
932*6b651796SEtienne Carriere }
933*6b651796SEtienne Carriere 
934*6b651796SEtienne Carriere static long get_timer_rate(long parent_rate, unsigned int apb_bus)
935*6b651796SEtienne Carriere {
936*6b651796SEtienne Carriere 	uint32_t timgxpre = 0;
937*6b651796SEtienne Carriere 	uint32_t apbxdiv = 0;
938*6b651796SEtienne Carriere 	vaddr_t rcc_base = stm32_rcc_base();
939*6b651796SEtienne Carriere 
940*6b651796SEtienne Carriere 	switch (apb_bus) {
941*6b651796SEtienne Carriere 	case 1:
942*6b651796SEtienne Carriere 		apbxdiv = io_read32(rcc_base + RCC_APB1DIVR) &
943*6b651796SEtienne Carriere 			  RCC_APBXDIV_MASK;
944*6b651796SEtienne Carriere 		timgxpre = io_read32(rcc_base + RCC_TIMG1PRER) &
945*6b651796SEtienne Carriere 			   RCC_TIMGXPRER_TIMGXPRE;
946*6b651796SEtienne Carriere 		break;
947*6b651796SEtienne Carriere 	case 2:
948*6b651796SEtienne Carriere 		apbxdiv = io_read32(rcc_base + RCC_APB2DIVR) &
949*6b651796SEtienne Carriere 			  RCC_APBXDIV_MASK;
950*6b651796SEtienne Carriere 		timgxpre = io_read32(rcc_base + RCC_TIMG2PRER) &
951*6b651796SEtienne Carriere 			   RCC_TIMGXPRER_TIMGXPRE;
952*6b651796SEtienne Carriere 		break;
953*6b651796SEtienne Carriere 	default:
954*6b651796SEtienne Carriere 		panic();
955*6b651796SEtienne Carriere 		break;
956*6b651796SEtienne Carriere 	}
957*6b651796SEtienne Carriere 
958*6b651796SEtienne Carriere 	if (apbxdiv == 0)
959*6b651796SEtienne Carriere 		return parent_rate;
960*6b651796SEtienne Carriere 
961*6b651796SEtienne Carriere 	return parent_rate * (timgxpre + 1) * 2;
962*6b651796SEtienne Carriere }
963*6b651796SEtienne Carriere 
964*6b651796SEtienne Carriere static unsigned long _stm32_clock_get_rate(unsigned long id)
965*6b651796SEtienne Carriere {
966*6b651796SEtienne Carriere 	int p = 0;
967*6b651796SEtienne Carriere 	unsigned long rate = 0;
968*6b651796SEtienne Carriere 
969*6b651796SEtienne Carriere 	p = stm32mp1_clk_get_parent(id);
970*6b651796SEtienne Carriere 	if (p < 0)
971*6b651796SEtienne Carriere 		return 0;
972*6b651796SEtienne Carriere 
973*6b651796SEtienne Carriere 	rate = get_clock_rate(p);
974*6b651796SEtienne Carriere 
975*6b651796SEtienne Carriere 	if ((id >= TIM2_K) && (id <= TIM14_K))
976*6b651796SEtienne Carriere 		rate = get_timer_rate(rate, 1);
977*6b651796SEtienne Carriere 
978*6b651796SEtienne Carriere 	if ((id >= TIM1_K) && (id <= TIM17_K))
979*6b651796SEtienne Carriere 		rate = get_timer_rate(rate, 2);
980*6b651796SEtienne Carriere 
981*6b651796SEtienne Carriere 	return rate;
982*6b651796SEtienne Carriere }
983*6b651796SEtienne Carriere 
984*6b651796SEtienne Carriere /*
985*6b651796SEtienne Carriere  * Get the parent ID of the target parent clock, or -1 if no parent found.
986*6b651796SEtienne Carriere  */
987*6b651796SEtienne Carriere static int get_parent_id_parent(unsigned int parent_id)
988*6b651796SEtienne Carriere {
989*6b651796SEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
990*6b651796SEtienne Carriere 	enum stm32mp1_pll_id pll_id = _PLL_NB;
991*6b651796SEtienne Carriere 	uint32_t p_sel = 0;
992*6b651796SEtienne Carriere 
993*6b651796SEtienne Carriere 	switch (parent_id) {
994*6b651796SEtienne Carriere 	case _ACLK:
995*6b651796SEtienne Carriere 	case _PCLK4:
996*6b651796SEtienne Carriere 	case _PCLK5:
997*6b651796SEtienne Carriere 		s = _AXISS_SEL;
998*6b651796SEtienne Carriere 		break;
999*6b651796SEtienne Carriere 	case _PLL1_P:
1000*6b651796SEtienne Carriere 	case _PLL1_Q:
1001*6b651796SEtienne Carriere 	case _PLL1_R:
1002*6b651796SEtienne Carriere 		pll_id = _PLL1;
1003*6b651796SEtienne Carriere 		break;
1004*6b651796SEtienne Carriere 	case _PLL2_P:
1005*6b651796SEtienne Carriere 	case _PLL2_Q:
1006*6b651796SEtienne Carriere 	case _PLL2_R:
1007*6b651796SEtienne Carriere 		pll_id = _PLL2;
1008*6b651796SEtienne Carriere 		break;
1009*6b651796SEtienne Carriere 	case _PLL3_P:
1010*6b651796SEtienne Carriere 	case _PLL3_Q:
1011*6b651796SEtienne Carriere 	case _PLL3_R:
1012*6b651796SEtienne Carriere 		pll_id = _PLL3;
1013*6b651796SEtienne Carriere 		break;
1014*6b651796SEtienne Carriere 	case _PLL4_P:
1015*6b651796SEtienne Carriere 	case _PLL4_Q:
1016*6b651796SEtienne Carriere 	case _PLL4_R:
1017*6b651796SEtienne Carriere 		pll_id = _PLL4;
1018*6b651796SEtienne Carriere 		break;
1019*6b651796SEtienne Carriere 	case _PCLK1:
1020*6b651796SEtienne Carriere 	case _PCLK2:
1021*6b651796SEtienne Carriere 	case _HCLK2:
1022*6b651796SEtienne Carriere 	case _HCLK6:
1023*6b651796SEtienne Carriere 	case _CK_PER:
1024*6b651796SEtienne Carriere 	case _CK_MPU:
1025*6b651796SEtienne Carriere 	case _CK_MCU:
1026*6b651796SEtienne Carriere 	case _USB_PHY_48:
1027*6b651796SEtienne Carriere 		/* We do not expected to access these */
1028*6b651796SEtienne Carriere 		panic();
1029*6b651796SEtienne Carriere 		break;
1030*6b651796SEtienne Carriere 	default:
1031*6b651796SEtienne Carriere 		/* Other parents have no parent */
1032*6b651796SEtienne Carriere 		return -1;
1033*6b651796SEtienne Carriere 	}
1034*6b651796SEtienne Carriere 
1035*6b651796SEtienne Carriere 	if (s != _UNKNOWN_SEL) {
1036*6b651796SEtienne Carriere 		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
1037*6b651796SEtienne Carriere 		vaddr_t rcc_base = stm32_rcc_base();
1038*6b651796SEtienne Carriere 
1039*6b651796SEtienne Carriere 		p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) &
1040*6b651796SEtienne Carriere 			sel->msk;
1041*6b651796SEtienne Carriere 
1042*6b651796SEtienne Carriere 		if (p_sel < sel->nb_parent)
1043*6b651796SEtienne Carriere 			return sel->parent[p_sel];
1044*6b651796SEtienne Carriere 	} else {
1045*6b651796SEtienne Carriere 		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1046*6b651796SEtienne Carriere 
1047*6b651796SEtienne Carriere 		p_sel = io_read32(stm32_rcc_base() + pll->rckxselr) &
1048*6b651796SEtienne Carriere 			RCC_SELR_REFCLK_SRC_MASK;
1049*6b651796SEtienne Carriere 
1050*6b651796SEtienne Carriere 		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID)
1051*6b651796SEtienne Carriere 			return pll->refclk[p_sel];
1052*6b651796SEtienne Carriere 	}
1053*6b651796SEtienne Carriere 
1054*6b651796SEtienne Carriere 	FMSG("No parent found for %s", stm32mp1_clk_parent_name[parent_id]);
1055*6b651796SEtienne Carriere 	return -1;
1056*6b651796SEtienne Carriere }
1057*6b651796SEtienne Carriere 
1058*6b651796SEtienne Carriere /* We are only interested in knowing if PLL3 shall be secure or not */
1059*6b651796SEtienne Carriere static void secure_parent_clocks(unsigned long parent_id)
1060*6b651796SEtienne Carriere {
1061*6b651796SEtienne Carriere 	int grandparent_id = 0;
1062*6b651796SEtienne Carriere 
1063*6b651796SEtienne Carriere 	switch (parent_id) {
1064*6b651796SEtienne Carriere 	case _ACLK:
1065*6b651796SEtienne Carriere 	case _HCLK2:
1066*6b651796SEtienne Carriere 	case _HCLK5:
1067*6b651796SEtienne Carriere 	case _HCLK6:
1068*6b651796SEtienne Carriere 	case _PCLK4:
1069*6b651796SEtienne Carriere 	case _PCLK5:
1070*6b651796SEtienne Carriere 		/* Intermediate clock mux or clock, go deeper in clock tree */
1071*6b651796SEtienne Carriere 		break;
1072*6b651796SEtienne Carriere 	case _HSI:
1073*6b651796SEtienne Carriere 	case _HSI_KER:
1074*6b651796SEtienne Carriere 	case _LSI:
1075*6b651796SEtienne Carriere 	case _CSI:
1076*6b651796SEtienne Carriere 	case _CSI_KER:
1077*6b651796SEtienne Carriere 	case _HSE:
1078*6b651796SEtienne Carriere 	case _HSE_KER:
1079*6b651796SEtienne Carriere 	case _HSE_KER_DIV2:
1080*6b651796SEtienne Carriere 	case _LSE:
1081*6b651796SEtienne Carriere 	case _PLL1_P:
1082*6b651796SEtienne Carriere 	case _PLL1_Q:
1083*6b651796SEtienne Carriere 	case _PLL1_R:
1084*6b651796SEtienne Carriere 	case _PLL2_P:
1085*6b651796SEtienne Carriere 	case _PLL2_Q:
1086*6b651796SEtienne Carriere 	case _PLL2_R:
1087*6b651796SEtienne Carriere 		/* Always secure clocks, no need to go further */
1088*6b651796SEtienne Carriere 		return;
1089*6b651796SEtienne Carriere 	case _PLL3_P:
1090*6b651796SEtienne Carriere 	case _PLL3_Q:
1091*6b651796SEtienne Carriere 	case _PLL3_R:
1092*6b651796SEtienne Carriere 		/* PLL3 is a shared resource, registered and don't go further */
1093*6b651796SEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
1094*6b651796SEtienne Carriere 		return;
1095*6b651796SEtienne Carriere 	default:
1096*6b651796SEtienne Carriere 		DMSG("Cannot lookup parent clock %s",
1097*6b651796SEtienne Carriere 		     stm32mp1_clk_parent_name[parent_id]);
1098*6b651796SEtienne Carriere 		panic();
1099*6b651796SEtienne Carriere 	}
1100*6b651796SEtienne Carriere 
1101*6b651796SEtienne Carriere 	grandparent_id = get_parent_id_parent(parent_id);
1102*6b651796SEtienne Carriere 	if (grandparent_id >= 0)
1103*6b651796SEtienne Carriere 		secure_parent_clocks(grandparent_id);
1104*6b651796SEtienne Carriere }
1105*6b651796SEtienne Carriere 
1106*6b651796SEtienne Carriere void stm32mp_register_clock_parents_secure(unsigned long clock_id)
1107*6b651796SEtienne Carriere {
1108*6b651796SEtienne Carriere 	int parent_id = stm32mp1_clk_get_parent(clock_id);
1109*6b651796SEtienne Carriere 
1110*6b651796SEtienne Carriere 	if (parent_id < 0) {
1111*6b651796SEtienne Carriere 		DMSG("No parent for clock %lu", clock_id);
1112*6b651796SEtienne Carriere 		return;
1113*6b651796SEtienne Carriere 	}
1114*6b651796SEtienne Carriere 
1115*6b651796SEtienne Carriere 	secure_parent_clocks(parent_id);
1116*6b651796SEtienne Carriere }
1117*6b651796SEtienne Carriere 
1118*6b651796SEtienne Carriere #ifdef CFG_EMBED_DTB
1119*6b651796SEtienne Carriere static const char *stm32mp_osc_node_label[NB_OSC] = {
1120*6b651796SEtienne Carriere 	[_LSI] = "clk-lsi",
1121*6b651796SEtienne Carriere 	[_LSE] = "clk-lse",
1122*6b651796SEtienne Carriere 	[_HSI] = "clk-hsi",
1123*6b651796SEtienne Carriere 	[_HSE] = "clk-hse",
1124*6b651796SEtienne Carriere 	[_CSI] = "clk-csi",
1125*6b651796SEtienne Carriere 	[_I2S_CKIN] = "i2s_ckin",
1126*6b651796SEtienne Carriere 	[_USB_PHY_48] = "ck_usbo_48m"
1127*6b651796SEtienne Carriere };
1128*6b651796SEtienne Carriere 
1129*6b651796SEtienne Carriere static unsigned int clk_freq_prop(const void *fdt, int node)
1130*6b651796SEtienne Carriere {
1131*6b651796SEtienne Carriere 	const fdt32_t *cuint = NULL;
1132*6b651796SEtienne Carriere 	int ret = 0;
1133*6b651796SEtienne Carriere 
1134*6b651796SEtienne Carriere 	/* Disabled clocks report null rate */
1135*6b651796SEtienne Carriere 	if (_fdt_get_status(fdt, node) == DT_STATUS_DISABLED)
1136*6b651796SEtienne Carriere 		return 0;
1137*6b651796SEtienne Carriere 
1138*6b651796SEtienne Carriere 	cuint = fdt_getprop(fdt, node, "clock-frequency", &ret);
1139*6b651796SEtienne Carriere 	if (!cuint)
1140*6b651796SEtienne Carriere 		panic();
1141*6b651796SEtienne Carriere 
1142*6b651796SEtienne Carriere 	return fdt32_to_cpu(*cuint);
1143*6b651796SEtienne Carriere }
1144*6b651796SEtienne Carriere 
1145*6b651796SEtienne Carriere static void get_osc_freq_from_dt(const void *fdt)
1146*6b651796SEtienne Carriere {
1147*6b651796SEtienne Carriere 	enum stm32mp_osc_id idx = _UNKNOWN_OSC_ID;
1148*6b651796SEtienne Carriere 	int clk_node = fdt_path_offset(fdt, "/clocks");
1149*6b651796SEtienne Carriere 
1150*6b651796SEtienne Carriere 	if (clk_node < 0)
1151*6b651796SEtienne Carriere 		panic();
1152*6b651796SEtienne Carriere 
1153*6b651796SEtienne Carriere 	COMPILE_TIME_ASSERT((int)_HSI == 0);
1154*6b651796SEtienne Carriere 	for (idx = _HSI; idx < NB_OSC; idx++) {
1155*6b651796SEtienne Carriere 		const char *name = stm32mp_osc_node_label[idx];
1156*6b651796SEtienne Carriere 		int subnode = 0;
1157*6b651796SEtienne Carriere 
1158*6b651796SEtienne Carriere 		fdt_for_each_subnode(subnode, fdt, clk_node) {
1159*6b651796SEtienne Carriere 			const char *cchar = NULL;
1160*6b651796SEtienne Carriere 			int ret = 0;
1161*6b651796SEtienne Carriere 
1162*6b651796SEtienne Carriere 			cchar = fdt_get_name(fdt, subnode, &ret);
1163*6b651796SEtienne Carriere 			if (!cchar)
1164*6b651796SEtienne Carriere 				panic();
1165*6b651796SEtienne Carriere 
1166*6b651796SEtienne Carriere 			if (strncmp(cchar, name, (size_t)ret) == 0) {
1167*6b651796SEtienne Carriere 				stm32mp1_osc[idx] = clk_freq_prop(fdt, subnode);
1168*6b651796SEtienne Carriere 
1169*6b651796SEtienne Carriere 				DMSG("Osc %s: %lu Hz", name, stm32mp1_osc[idx]);
1170*6b651796SEtienne Carriere 				break;
1171*6b651796SEtienne Carriere 			}
1172*6b651796SEtienne Carriere 		}
1173*6b651796SEtienne Carriere 
1174*6b651796SEtienne Carriere 		if (!stm32mp1_osc[idx])
1175*6b651796SEtienne Carriere 			DMSG("Osc %s: no frequency info", name);
1176*6b651796SEtienne Carriere 	}
1177*6b651796SEtienne Carriere }
1178*6b651796SEtienne Carriere #endif /*CFG_EMBED_DTB*/
1179*6b651796SEtienne Carriere 
1180*6b651796SEtienne Carriere static void enable_static_secure_clocks(void)
1181*6b651796SEtienne Carriere {
1182*6b651796SEtienne Carriere 	unsigned int idx = 0;
1183*6b651796SEtienne Carriere 	const unsigned long secure_enable[] = {
1184*6b651796SEtienne Carriere 		DDRC1, DDRC1LP, DDRC2, DDRC2LP, DDRPHYC, DDRPHYCLP, DDRCAPB,
1185*6b651796SEtienne Carriere 		AXIDCG, DDRPHYCAPB, DDRPHYCAPBLP, TZPC, TZC1, TZC2, STGEN_K,
1186*6b651796SEtienne Carriere 		BSEC,
1187*6b651796SEtienne Carriere 	};
1188*6b651796SEtienne Carriere 
1189*6b651796SEtienne Carriere 	for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++) {
1190*6b651796SEtienne Carriere 		stm32_clock_enable(secure_enable[idx]);
1191*6b651796SEtienne Carriere 		stm32mp_register_clock_parents_secure(secure_enable[idx]);
1192*6b651796SEtienne Carriere 	}
1193*6b651796SEtienne Carriere 
1194*6b651796SEtienne Carriere 	if (CFG_TEE_CORE_NB_CORE > 1)
1195*6b651796SEtienne Carriere 		stm32_clock_enable(RTCAPB);
1196*6b651796SEtienne Carriere }
1197*6b651796SEtienne Carriere 
1198*6b651796SEtienne Carriere static void __maybe_unused enable_rcc_tzen(void)
1199*6b651796SEtienne Carriere {
1200*6b651796SEtienne Carriere 	io_setbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN);
1201*6b651796SEtienne Carriere }
1202*6b651796SEtienne Carriere 
1203*6b651796SEtienne Carriere static void __maybe_unused disable_rcc_tzen(void)
1204*6b651796SEtienne Carriere {
1205*6b651796SEtienne Carriere 	IMSG("RCC is non-secure");
1206*6b651796SEtienne Carriere 	io_clrbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN);
1207*6b651796SEtienne Carriere }
1208*6b651796SEtienne Carriere 
1209*6b651796SEtienne Carriere #ifdef CFG_EMBED_DTB
1210*6b651796SEtienne Carriere static TEE_Result stm32mp1_clk_fdt_init(const void *fdt, int node)
1211*6b651796SEtienne Carriere {
1212*6b651796SEtienne Carriere 	unsigned int i = 0;
1213*6b651796SEtienne Carriere 	int len = 0;
1214*6b651796SEtienne Carriere 	int ignored = 0;
1215*6b651796SEtienne Carriere 
1216*6b651796SEtienne Carriere 	get_osc_freq_from_dt(fdt);
1217*6b651796SEtienne Carriere 
1218*6b651796SEtienne Carriere 	/*
1219*6b651796SEtienne Carriere 	 * OP-TEE core is not in charge of configuring clock parenthood.
1220*6b651796SEtienne Carriere 	 * This is expected from an earlier boot stage. Modifying the clock
1221*6b651796SEtienne Carriere 	 * tree parenthood here may jeopardize already configured clocks.
1222*6b651796SEtienne Carriere 	 * The sequence below ignores such DT directives with a friendly
1223*6b651796SEtienne Carriere 	 * debug trace.
1224*6b651796SEtienne Carriere 	 */
1225*6b651796SEtienne Carriere 	if (fdt_getprop(fdt, node, "st,clksrc", &len)) {
1226*6b651796SEtienne Carriere 		DMSG("Ignore source clocks configuration from DT");
1227*6b651796SEtienne Carriere 		ignored++;
1228*6b651796SEtienne Carriere 	}
1229*6b651796SEtienne Carriere 	if (fdt_getprop(fdt, node, "st,clkdiv", &len)) {
1230*6b651796SEtienne Carriere 		DMSG("Ignore clock divisors configuration from DT");
1231*6b651796SEtienne Carriere 		ignored++;
1232*6b651796SEtienne Carriere 	}
1233*6b651796SEtienne Carriere 	if (fdt_getprop(fdt, node, "st,pkcs", &len)) {
1234*6b651796SEtienne Carriere 		DMSG("Ignore peripheral clocks tree configuration from DT");
1235*6b651796SEtienne Carriere 		ignored++;
1236*6b651796SEtienne Carriere 	}
1237*6b651796SEtienne Carriere 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1238*6b651796SEtienne Carriere 		char name[] = "st,pll@X";
1239*6b651796SEtienne Carriere 
1240*6b651796SEtienne Carriere 		snprintf(name, sizeof(name), "st,pll@%d", i);
1241*6b651796SEtienne Carriere 		node = fdt_subnode_offset(fdt, node, name);
1242*6b651796SEtienne Carriere 		if (node < 0)
1243*6b651796SEtienne Carriere 			continue;
1244*6b651796SEtienne Carriere 
1245*6b651796SEtienne Carriere 		if (fdt_getprop(fdt, node, "cfg", &len) ||
1246*6b651796SEtienne Carriere 		    fdt_getprop(fdt, node, "frac", &len)) {
1247*6b651796SEtienne Carriere 			DMSG("Ignore PLL%u configurations from DT", i);
1248*6b651796SEtienne Carriere 			ignored++;
1249*6b651796SEtienne Carriere 		}
1250*6b651796SEtienne Carriere 	}
1251*6b651796SEtienne Carriere 
1252*6b651796SEtienne Carriere 	if (ignored != 0)
1253*6b651796SEtienne Carriere 		IMSG("DT clock tree configurations were ignored");
1254*6b651796SEtienne Carriere 
1255*6b651796SEtienne Carriere 	return TEE_SUCCESS;
1256*6b651796SEtienne Carriere }
1257*6b651796SEtienne Carriere #endif /*CFG_EMBED_DTB*/
1258*6b651796SEtienne Carriere 
1259*6b651796SEtienne Carriere /*
1260*6b651796SEtienne Carriere  * Conversion between clk references and clock gates and clock on internals
1261*6b651796SEtienne Carriere  *
1262*6b651796SEtienne Carriere  * stm32mp1_clk first cells follow stm32mp1_clk_gate[] ordering.
1263*6b651796SEtienne Carriere  * stm32mp1_clk last cells follow stm32mp1_clk_on[] ordering.
1264*6b651796SEtienne Carriere  */
1265*6b651796SEtienne Carriere static struct clk stm32mp1_clk[ARRAY_SIZE(stm32mp1_clk_gate) +
1266*6b651796SEtienne Carriere 			       ARRAY_SIZE(stm32mp1_clk_on)];
1267*6b651796SEtienne Carriere 
1268*6b651796SEtienne Carriere #define CLK_ON_INDEX_OFFSET	((int)ARRAY_SIZE(stm32mp1_clk_gate))
1269*6b651796SEtienne Carriere 
1270*6b651796SEtienne Carriere static bool clk_is_gate(struct clk *clk)
1271*6b651796SEtienne Carriere {
1272*6b651796SEtienne Carriere 	int clk_index = clk - stm32mp1_clk;
1273*6b651796SEtienne Carriere 
1274*6b651796SEtienne Carriere 	assert(clk_index >= 0 && clk_index < (int)ARRAY_SIZE(stm32mp1_clk));
1275*6b651796SEtienne Carriere 	return clk_index < CLK_ON_INDEX_OFFSET;
1276*6b651796SEtienne Carriere }
1277*6b651796SEtienne Carriere 
1278*6b651796SEtienne Carriere static unsigned long clk_to_clock_id(struct clk *clk)
1279*6b651796SEtienne Carriere {
1280*6b651796SEtienne Carriere 	int gate_index = clk - stm32mp1_clk;
1281*6b651796SEtienne Carriere 	int on_index = gate_index - CLK_ON_INDEX_OFFSET;
1282*6b651796SEtienne Carriere 
1283*6b651796SEtienne Carriere 	if (clk_is_gate(clk))
1284*6b651796SEtienne Carriere 		return stm32mp1_clk_gate[gate_index].clock_id;
1285*6b651796SEtienne Carriere 
1286*6b651796SEtienne Carriere 	return stm32mp1_clk_on[on_index];
1287*6b651796SEtienne Carriere }
1288*6b651796SEtienne Carriere 
1289*6b651796SEtienne Carriere static const struct stm32mp1_clk_gate *clk_to_gate_ref(struct clk *clk)
1290*6b651796SEtienne Carriere {
1291*6b651796SEtienne Carriere 	int gate_index = clk - stm32mp1_clk;
1292*6b651796SEtienne Carriere 
1293*6b651796SEtienne Carriere 	assert(clk_is_gate(clk));
1294*6b651796SEtienne Carriere 
1295*6b651796SEtienne Carriere 	return stm32mp1_clk_gate + gate_index;
1296*6b651796SEtienne Carriere }
1297*6b651796SEtienne Carriere 
1298*6b651796SEtienne Carriere static int clock_id_to_gate_index(unsigned long clock_id)
1299*6b651796SEtienne Carriere {
1300*6b651796SEtienne Carriere 	size_t n = 0;
1301*6b651796SEtienne Carriere 
1302*6b651796SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_gate); n++)
1303*6b651796SEtienne Carriere 		if (stm32mp1_clk_gate[n].clock_id == clock_id)
1304*6b651796SEtienne Carriere 			return n;
1305*6b651796SEtienne Carriere 
1306*6b651796SEtienne Carriere 	return -1;
1307*6b651796SEtienne Carriere }
1308*6b651796SEtienne Carriere 
1309*6b651796SEtienne Carriere static int clock_id_to_always_on_index(unsigned long clock_id)
1310*6b651796SEtienne Carriere {
1311*6b651796SEtienne Carriere 	size_t n = 0;
1312*6b651796SEtienne Carriere 
1313*6b651796SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_on); n++)
1314*6b651796SEtienne Carriere 		if (stm32mp1_clk_on[n] == clock_id)
1315*6b651796SEtienne Carriere 			return n;
1316*6b651796SEtienne Carriere 
1317*6b651796SEtienne Carriere 	return -1;
1318*6b651796SEtienne Carriere }
1319*6b651796SEtienne Carriere 
1320*6b651796SEtienne Carriere static struct clk *clock_id_to_clk(unsigned long clock_id)
1321*6b651796SEtienne Carriere {
1322*6b651796SEtienne Carriere 	int gate_index = clock_id_to_gate_index(clock_id);
1323*6b651796SEtienne Carriere 	int on_index = clock_id_to_always_on_index(clock_id);
1324*6b651796SEtienne Carriere 
1325*6b651796SEtienne Carriere 	if (gate_index >= 0)
1326*6b651796SEtienne Carriere 		return stm32mp1_clk + gate_index;
1327*6b651796SEtienne Carriere 
1328*6b651796SEtienne Carriere 	if (on_index >= 0)
1329*6b651796SEtienne Carriere 		return stm32mp1_clk + CLK_ON_INDEX_OFFSET + on_index;
1330*6b651796SEtienne Carriere 
1331*6b651796SEtienne Carriere 	return NULL;
1332*6b651796SEtienne Carriere }
1333*6b651796SEtienne Carriere 
1334*6b651796SEtienne Carriere #if CFG_TEE_CORE_LOG_LEVEL >= TRACE_DEBUG
1335*6b651796SEtienne Carriere struct clk_name {
1336*6b651796SEtienne Carriere 	unsigned int clock_id;
1337*6b651796SEtienne Carriere 	const char *name;
1338*6b651796SEtienne Carriere };
1339*6b651796SEtienne Carriere 
1340*6b651796SEtienne Carriere #define CLOCK_NAME(_binding, _name) \
1341*6b651796SEtienne Carriere 	{ .clock_id = (_binding), .name = (_name) }
1342*6b651796SEtienne Carriere 
1343*6b651796SEtienne Carriere /* Store names only for some clocks */
1344*6b651796SEtienne Carriere const struct clk_name exposed_clk_name[] = {
1345*6b651796SEtienne Carriere 	/* Clocks used by platform drivers not yet probed from DT */
1346*6b651796SEtienne Carriere 	CLOCK_NAME(CK_DBG, "dbg"),
1347*6b651796SEtienne Carriere 	CLOCK_NAME(CK_MCU, "mcu"),
1348*6b651796SEtienne Carriere 	CLOCK_NAME(RTCAPB, "rtcapb"),
1349*6b651796SEtienne Carriere 	CLOCK_NAME(BKPSRAM, "bkpsram"),
1350*6b651796SEtienne Carriere 	CLOCK_NAME(RTC, "rtc"),
1351*6b651796SEtienne Carriere 	CLOCK_NAME(CRYP1, "crpy1"),
1352*6b651796SEtienne Carriere 	CLOCK_NAME(SYSCFG, "syscfg"),
1353*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOA, "gpioa"),
1354*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOB, "gpiob"),
1355*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOC, "gpioc"),
1356*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOD, "gpiod"),
1357*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOE, "gpioe"),
1358*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOF, "gpiof"),
1359*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOG, "gpiog"),
1360*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOH, "gpioh"),
1361*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOI, "gpioi"),
1362*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOJ, "gpioj"),
1363*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOK, "gpiok"),
1364*6b651796SEtienne Carriere 	CLOCK_NAME(GPIOZ, "gpioz"),
1365*6b651796SEtienne Carriere 	/* Clock exposed by SCMI. SCMI clock fmro DT bindings to come... */
1366*6b651796SEtienne Carriere 	CLOCK_NAME(CK_HSE, "hse"),
1367*6b651796SEtienne Carriere 	CLOCK_NAME(CK_HSI, "hsi"),
1368*6b651796SEtienne Carriere 	CLOCK_NAME(CK_CSI, "csi"),
1369*6b651796SEtienne Carriere 	CLOCK_NAME(CK_LSE, "lse"),
1370*6b651796SEtienne Carriere 	CLOCK_NAME(CK_LSI, "lsi"),
1371*6b651796SEtienne Carriere 	CLOCK_NAME(PLL2_Q, "pll2q"),
1372*6b651796SEtienne Carriere 	CLOCK_NAME(PLL2_R, "pll2r"),
1373*6b651796SEtienne Carriere 	CLOCK_NAME(PLL3_Q, "pll3q"),
1374*6b651796SEtienne Carriere 	CLOCK_NAME(PLL3_R, "pll3r"),
1375*6b651796SEtienne Carriere 	CLOCK_NAME(CRYP1, "cryp1"),
1376*6b651796SEtienne Carriere 	CLOCK_NAME(HASH1, "hash1"),
1377*6b651796SEtienne Carriere 	CLOCK_NAME(I2C4_K, "i2c4"),
1378*6b651796SEtienne Carriere 	CLOCK_NAME(I2C6_K, "i2c6"),
1379*6b651796SEtienne Carriere 	CLOCK_NAME(IWDG1, "iwdg"),
1380*6b651796SEtienne Carriere 	CLOCK_NAME(RNG1_K, "rng1"),
1381*6b651796SEtienne Carriere 	CLOCK_NAME(SPI6_K, "spi6"),
1382*6b651796SEtienne Carriere 	CLOCK_NAME(USART1_K, "usart1"),
1383*6b651796SEtienne Carriere 	CLOCK_NAME(CK_MCU, "mcu"),
1384*6b651796SEtienne Carriere };
1385*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(exposed_clk_name);
1386*6b651796SEtienne Carriere 
1387*6b651796SEtienne Carriere static const char *clk_op_get_name(struct clk *clk)
1388*6b651796SEtienne Carriere {
1389*6b651796SEtienne Carriere 	unsigned long clock_id = clk_to_clock_id(clk);
1390*6b651796SEtienne Carriere 	size_t n = 0;
1391*6b651796SEtienne Carriere 
1392*6b651796SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(exposed_clk_name); n++)
1393*6b651796SEtienne Carriere 		if (exposed_clk_name[n].clock_id == clock_id)
1394*6b651796SEtienne Carriere 			return exposed_clk_name[n].name;
1395*6b651796SEtienne Carriere 
1396*6b651796SEtienne Carriere 	return NULL;
1397*6b651796SEtienne Carriere }
1398*6b651796SEtienne Carriere #else
1399*6b651796SEtienne Carriere static const char *clk_op_get_name(struct clk *clk __unused)
1400*6b651796SEtienne Carriere {
1401*6b651796SEtienne Carriere 	return NULL;
1402*6b651796SEtienne Carriere }
1403*6b651796SEtienne Carriere #endif /*CFG_TEE_CORE_LOG_LEVEL*/
1404*6b651796SEtienne Carriere 
1405*6b651796SEtienne Carriere static unsigned long clk_op_compute_rate(struct clk *clk,
1406*6b651796SEtienne Carriere 					 unsigned long parent_rate __unused)
1407*6b651796SEtienne Carriere {
1408*6b651796SEtienne Carriere 	return _stm32_clock_get_rate(clk_to_clock_id(clk));
1409*6b651796SEtienne Carriere }
1410*6b651796SEtienne Carriere 
1411*6b651796SEtienne Carriere static TEE_Result clk_op_enable(struct clk *clk)
1412*6b651796SEtienne Carriere {
1413*6b651796SEtienne Carriere 	if (clk_is_gate(clk))
1414*6b651796SEtienne Carriere 		__clk_enable(clk_to_gate_ref(clk));
1415*6b651796SEtienne Carriere 
1416*6b651796SEtienne Carriere 	return TEE_SUCCESS;
1417*6b651796SEtienne Carriere }
1418*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(clk_op_enable);
1419*6b651796SEtienne Carriere 
1420*6b651796SEtienne Carriere static void clk_op_disable(struct clk *clk)
1421*6b651796SEtienne Carriere {
1422*6b651796SEtienne Carriere 	if (clk_is_gate(clk))
1423*6b651796SEtienne Carriere 		__clk_disable(clk_to_gate_ref(clk));
1424*6b651796SEtienne Carriere }
1425*6b651796SEtienne Carriere DECLARE_KEEP_PAGER(clk_op_disable);
1426*6b651796SEtienne Carriere 
1427*6b651796SEtienne Carriere /* This variable is weak to break its dependency chain when linked as unpaged */
1428*6b651796SEtienne Carriere const struct clk_ops stm32mp1_clk_ops
1429*6b651796SEtienne Carriere __weak __rodata_unpaged("stm32mp1_clk_ops") = {
1430*6b651796SEtienne Carriere 	.enable = clk_op_enable,
1431*6b651796SEtienne Carriere 	.disable = clk_op_disable,
1432*6b651796SEtienne Carriere 	.get_rate = clk_op_compute_rate,
1433*6b651796SEtienne Carriere };
1434*6b651796SEtienne Carriere 
1435*6b651796SEtienne Carriere static TEE_Result register_stm32mp1_clocks(void)
1436*6b651796SEtienne Carriere {
1437*6b651796SEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1438*6b651796SEtienne Carriere 	size_t n = 0;
1439*6b651796SEtienne Carriere 
1440*6b651796SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(stm32mp1_clk); n++) {
1441*6b651796SEtienne Carriere 		stm32mp1_clk[n].ops = &stm32mp1_clk_ops;
1442*6b651796SEtienne Carriere 		stm32mp1_clk[n].name = clk_op_get_name(stm32mp1_clk + n);
1443*6b651796SEtienne Carriere 		refcount_set(&stm32mp1_clk[n].enabled_count, 0);
1444*6b651796SEtienne Carriere 
1445*6b651796SEtienne Carriere 		res = clk_register(stm32mp1_clk + n);
1446*6b651796SEtienne Carriere 		if (res)
1447*6b651796SEtienne Carriere 			return res;
1448*6b651796SEtienne Carriere 	}
1449*6b651796SEtienne Carriere 
1450*6b651796SEtienne Carriere 	return TEE_SUCCESS;
1451*6b651796SEtienne Carriere }
1452*6b651796SEtienne Carriere 
1453*6b651796SEtienne Carriere /* Route platform legacy clock functions to clk driver functions */
1454*6b651796SEtienne Carriere bool stm32_clock_is_enabled(unsigned long clock_id)
1455*6b651796SEtienne Carriere {
1456*6b651796SEtienne Carriere 	struct clk *clk = clock_id_to_clk(clock_id);
1457*6b651796SEtienne Carriere 
1458*6b651796SEtienne Carriere 	assert(clk);
1459*6b651796SEtienne Carriere 	return clk_is_enabled(clk);
1460*6b651796SEtienne Carriere }
1461*6b651796SEtienne Carriere 
1462*6b651796SEtienne Carriere void stm32_clock_enable(unsigned long clock_id)
1463*6b651796SEtienne Carriere {
1464*6b651796SEtienne Carriere 	struct clk *clk = clock_id_to_clk(clock_id);
1465*6b651796SEtienne Carriere 	TEE_Result __maybe_unused res = TEE_ERROR_GENERIC;
1466*6b651796SEtienne Carriere 
1467*6b651796SEtienne Carriere 	assert(clk);
1468*6b651796SEtienne Carriere 	res = clk_enable(clk);
1469*6b651796SEtienne Carriere 	assert(!res);
1470*6b651796SEtienne Carriere }
1471*6b651796SEtienne Carriere 
1472*6b651796SEtienne Carriere void stm32_clock_disable(unsigned long clock_id)
1473*6b651796SEtienne Carriere {
1474*6b651796SEtienne Carriere 	struct clk *clk = clock_id_to_clk(clock_id);
1475*6b651796SEtienne Carriere 
1476*6b651796SEtienne Carriere 	assert(clk);
1477*6b651796SEtienne Carriere 	clk_disable(clk);
1478*6b651796SEtienne Carriere }
1479*6b651796SEtienne Carriere 
1480*6b651796SEtienne Carriere unsigned long stm32_clock_get_rate(unsigned long clock_id)
1481*6b651796SEtienne Carriere {
1482*6b651796SEtienne Carriere 	struct clk *clk = clock_id_to_clk(clock_id);
1483*6b651796SEtienne Carriere 
1484*6b651796SEtienne Carriere 	assert(clk);
1485*6b651796SEtienne Carriere 	return clk_get_rate(clk);
1486*6b651796SEtienne Carriere }
1487*6b651796SEtienne Carriere 
1488*6b651796SEtienne Carriere #ifdef CFG_DRIVERS_CLK_DT
1489*6b651796SEtienne Carriere static struct clk *stm32mp1_clk_dt_get_clk(struct dt_driver_phandle_args *pargs,
1490*6b651796SEtienne Carriere 					   void *data __unused, TEE_Result *res)
1491*6b651796SEtienne Carriere {
1492*6b651796SEtienne Carriere 	unsigned long clock_id = pargs->args[0];
1493*6b651796SEtienne Carriere 	struct clk *clk = NULL;
1494*6b651796SEtienne Carriere 
1495*6b651796SEtienne Carriere 	*res = TEE_ERROR_BAD_PARAMETERS;
1496*6b651796SEtienne Carriere 
1497*6b651796SEtienne Carriere 	if (pargs->args_count != 1)
1498*6b651796SEtienne Carriere 		return NULL;
1499*6b651796SEtienne Carriere 
1500*6b651796SEtienne Carriere 	clk = clock_id_to_clk(clock_id);
1501*6b651796SEtienne Carriere 	if (!clk)
1502*6b651796SEtienne Carriere 		return NULL;
1503*6b651796SEtienne Carriere 
1504*6b651796SEtienne Carriere 	*res = TEE_SUCCESS;
1505*6b651796SEtienne Carriere 	return clk;
1506*6b651796SEtienne Carriere }
1507*6b651796SEtienne Carriere 
1508*6b651796SEtienne Carriere /* Non-null reference for compat data */
1509*6b651796SEtienne Carriere static const uint8_t non_secure_rcc;
1510*6b651796SEtienne Carriere 
1511*6b651796SEtienne Carriere static TEE_Result stm32mp1_clock_provider_probe(const void *fdt, int offs,
1512*6b651796SEtienne Carriere 						const void *compat_data)
1513*6b651796SEtienne Carriere {
1514*6b651796SEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
1515*6b651796SEtienne Carriere 
1516*6b651796SEtienne Carriere 	if (compat_data == &non_secure_rcc)
1517*6b651796SEtienne Carriere 		disable_rcc_tzen();
1518*6b651796SEtienne Carriere 	else
1519*6b651796SEtienne Carriere 		enable_rcc_tzen();
1520*6b651796SEtienne Carriere 
1521*6b651796SEtienne Carriere 	res = stm32mp1_clk_fdt_init(fdt, offs);
1522*6b651796SEtienne Carriere 	if (res) {
1523*6b651796SEtienne Carriere 		EMSG("Failed to initialize clocks from DT: %#"PRIx32, res);
1524*6b651796SEtienne Carriere 		panic();
1525*6b651796SEtienne Carriere 	}
1526*6b651796SEtienne Carriere 
1527*6b651796SEtienne Carriere 	res = register_stm32mp1_clocks();
1528*6b651796SEtienne Carriere 	if (res) {
1529*6b651796SEtienne Carriere 		EMSG("Failed to register clocks: %#"PRIx32, res);
1530*6b651796SEtienne Carriere 		panic();
1531*6b651796SEtienne Carriere 	}
1532*6b651796SEtienne Carriere 
1533*6b651796SEtienne Carriere 	res = clk_dt_register_clk_provider(fdt, offs, stm32mp1_clk_dt_get_clk,
1534*6b651796SEtienne Carriere 					   NULL);
1535*6b651796SEtienne Carriere 	if (res) {
1536*6b651796SEtienne Carriere 		EMSG("Failed to register clock provider: %#"PRIx32, res);
1537*6b651796SEtienne Carriere 		panic();
1538*6b651796SEtienne Carriere 	}
1539*6b651796SEtienne Carriere 
1540*6b651796SEtienne Carriere 	enable_static_secure_clocks();
1541*6b651796SEtienne Carriere 
1542*6b651796SEtienne Carriere 	return TEE_SUCCESS;
1543*6b651796SEtienne Carriere }
1544*6b651796SEtienne Carriere 
1545*6b651796SEtienne Carriere static const struct dt_device_match stm32mp1_clock_match_table[] = {
1546*6b651796SEtienne Carriere 	{  .compatible = "st,stm32mp1-rcc", .compat_data = &non_secure_rcc, },
1547*6b651796SEtienne Carriere 	{  .compatible = "st,stm32mp1-rcc-secure", },
1548*6b651796SEtienne Carriere 	{ }
1549*6b651796SEtienne Carriere };
1550*6b651796SEtienne Carriere 
1551*6b651796SEtienne Carriere DEFINE_DT_DRIVER(stm32mp1_clock_dt_driver) = {
1552*6b651796SEtienne Carriere 	.name = "stm32mp1_clock",
1553*6b651796SEtienne Carriere 	.type = DT_DRIVER_CLK,
1554*6b651796SEtienne Carriere 	.match_table = stm32mp1_clock_match_table,
1555*6b651796SEtienne Carriere 	.probe = stm32mp1_clock_provider_probe,
1556*6b651796SEtienne Carriere };
1557*6b651796SEtienne Carriere #else /*CFG_DRIVERS_CLK_DT*/
1558*6b651796SEtienne Carriere static TEE_Result stm32mp1_clk_early_init(void)
1559*6b651796SEtienne Carriere {
1560*6b651796SEtienne Carriere 	TEE_Result __maybe_unused res = TEE_ERROR_GENERIC;
1561*6b651796SEtienne Carriere 
1562*6b651796SEtienne Carriere 	res = register_stm32mp1_clocks();
1563*6b651796SEtienne Carriere 	if (res) {
1564*6b651796SEtienne Carriere 		EMSG("Failed to register clocks: %#"PRIx32, res);
1565*6b651796SEtienne Carriere 		panic();
1566*6b651796SEtienne Carriere 	}
1567*6b651796SEtienne Carriere 
1568*6b651796SEtienne Carriere 	enable_static_secure_clocks();
1569*6b651796SEtienne Carriere 
1570*6b651796SEtienne Carriere 	return TEE_SUCCESS;
1571*6b651796SEtienne Carriere }
1572*6b651796SEtienne Carriere 
1573*6b651796SEtienne Carriere service_init(stm32mp1_clk_early_init);
1574*6b651796SEtienne Carriere #endif /*CFG_DRIVERS_CLK_DT*/
1575