xref: /rk3399_ARM-atf/drivers/st/clk/clk-stm32-core.c (revision 9be88e75c198b08c508d8e470964720a781294b3)
1*9be88e75SGabriel Fernandez /*
2*9be88e75SGabriel Fernandez  * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
3*9be88e75SGabriel Fernandez  *
4*9be88e75SGabriel Fernandez  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5*9be88e75SGabriel Fernandez  */
6*9be88e75SGabriel Fernandez 
7*9be88e75SGabriel Fernandez #include <assert.h>
8*9be88e75SGabriel Fernandez #include <errno.h>
9*9be88e75SGabriel Fernandez 
10*9be88e75SGabriel Fernandez #include "clk-stm32-core.h"
11*9be88e75SGabriel Fernandez #include <common/debug.h>
12*9be88e75SGabriel Fernandez #include <common/fdt_wrappers.h>
13*9be88e75SGabriel Fernandez #include <drivers/clk.h>
14*9be88e75SGabriel Fernandez #include <drivers/delay_timer.h>
15*9be88e75SGabriel Fernandez #include <drivers/st/stm32mp_clkfunc.h>
16*9be88e75SGabriel Fernandez #include <lib/mmio.h>
17*9be88e75SGabriel Fernandez #include <lib/spinlock.h>
18*9be88e75SGabriel Fernandez 
19*9be88e75SGabriel Fernandez static struct spinlock reg_lock;
20*9be88e75SGabriel Fernandez static struct spinlock refcount_lock;
21*9be88e75SGabriel Fernandez 
22*9be88e75SGabriel Fernandez static struct stm32_clk_priv *stm32_clock_data;
23*9be88e75SGabriel Fernandez 
24*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_mux_ops;
25*9be88e75SGabriel Fernandez 
26*9be88e75SGabriel Fernandez struct stm32_clk_priv *clk_stm32_get_priv(void)
27*9be88e75SGabriel Fernandez {
28*9be88e75SGabriel Fernandez 	return stm32_clock_data;
29*9be88e75SGabriel Fernandez }
30*9be88e75SGabriel Fernandez 
31*9be88e75SGabriel Fernandez static void stm32mp1_clk_lock(struct spinlock *lock)
32*9be88e75SGabriel Fernandez {
33*9be88e75SGabriel Fernandez 	if (stm32mp_lock_available()) {
34*9be88e75SGabriel Fernandez 		/* Assume interrupts are masked */
35*9be88e75SGabriel Fernandez 		spin_lock(lock);
36*9be88e75SGabriel Fernandez 	}
37*9be88e75SGabriel Fernandez }
38*9be88e75SGabriel Fernandez 
39*9be88e75SGabriel Fernandez static void stm32mp1_clk_unlock(struct spinlock *lock)
40*9be88e75SGabriel Fernandez {
41*9be88e75SGabriel Fernandez 	if (stm32mp_lock_available()) {
42*9be88e75SGabriel Fernandez 		spin_unlock(lock);
43*9be88e75SGabriel Fernandez 	}
44*9be88e75SGabriel Fernandez }
45*9be88e75SGabriel Fernandez 
46*9be88e75SGabriel Fernandez void stm32mp1_clk_rcc_regs_lock(void)
47*9be88e75SGabriel Fernandez {
48*9be88e75SGabriel Fernandez 	stm32mp1_clk_lock(&reg_lock);
49*9be88e75SGabriel Fernandez }
50*9be88e75SGabriel Fernandez 
51*9be88e75SGabriel Fernandez void stm32mp1_clk_rcc_regs_unlock(void)
52*9be88e75SGabriel Fernandez {
53*9be88e75SGabriel Fernandez 	stm32mp1_clk_unlock(&reg_lock);
54*9be88e75SGabriel Fernandez }
55*9be88e75SGabriel Fernandez 
56*9be88e75SGabriel Fernandez #define TIMEOUT_US_1S	U(1000000)
57*9be88e75SGabriel Fernandez #define OSCRDY_TIMEOUT	TIMEOUT_US_1S
58*9be88e75SGabriel Fernandez 
59*9be88e75SGabriel Fernandez struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id)
60*9be88e75SGabriel Fernandez {
61*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
62*9be88e75SGabriel Fernandez 	struct stm32_osc_cfg *osc_cfg = clk->clock_cfg;
63*9be88e75SGabriel Fernandez 	int osc_id = osc_cfg->osc_id;
64*9be88e75SGabriel Fernandez 
65*9be88e75SGabriel Fernandez 	return &priv->osci_data[osc_id];
66*9be88e75SGabriel Fernandez }
67*9be88e75SGabriel Fernandez 
68*9be88e75SGabriel Fernandez void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass)
69*9be88e75SGabriel Fernandez {
70*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
71*9be88e75SGabriel Fernandez 
72*9be88e75SGabriel Fernandez 	struct stm32_clk_bypass *bypass_data = osc_data->bypass;
73*9be88e75SGabriel Fernandez 	uintptr_t address;
74*9be88e75SGabriel Fernandez 
75*9be88e75SGabriel Fernandez 	if (bypass_data == NULL) {
76*9be88e75SGabriel Fernandez 		return;
77*9be88e75SGabriel Fernandez 	}
78*9be88e75SGabriel Fernandez 
79*9be88e75SGabriel Fernandez 	address = priv->base + bypass_data->offset;
80*9be88e75SGabriel Fernandez 
81*9be88e75SGabriel Fernandez 	if (digbyp) {
82*9be88e75SGabriel Fernandez 		mmio_setbits_32(address, BIT(bypass_data->bit_digbyp));
83*9be88e75SGabriel Fernandez 	}
84*9be88e75SGabriel Fernandez 
85*9be88e75SGabriel Fernandez 	if (bypass || digbyp) {
86*9be88e75SGabriel Fernandez 		mmio_setbits_32(address, BIT(bypass_data->bit_byp));
87*9be88e75SGabriel Fernandez 	}
88*9be88e75SGabriel Fernandez }
89*9be88e75SGabriel Fernandez 
90*9be88e75SGabriel Fernandez void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css)
91*9be88e75SGabriel Fernandez {
92*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
93*9be88e75SGabriel Fernandez 
94*9be88e75SGabriel Fernandez 	struct stm32_clk_css *css_data = osc_data->css;
95*9be88e75SGabriel Fernandez 	uintptr_t address;
96*9be88e75SGabriel Fernandez 
97*9be88e75SGabriel Fernandez 	if (css_data == NULL) {
98*9be88e75SGabriel Fernandez 		return;
99*9be88e75SGabriel Fernandez 	}
100*9be88e75SGabriel Fernandez 
101*9be88e75SGabriel Fernandez 	address = priv->base + css_data->offset;
102*9be88e75SGabriel Fernandez 
103*9be88e75SGabriel Fernandez 	if (css) {
104*9be88e75SGabriel Fernandez 		mmio_setbits_32(address, BIT(css_data->bit_css));
105*9be88e75SGabriel Fernandez 	}
106*9be88e75SGabriel Fernandez }
107*9be88e75SGabriel Fernandez 
108*9be88e75SGabriel Fernandez void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv)
109*9be88e75SGabriel Fernandez {
110*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
111*9be88e75SGabriel Fernandez 
112*9be88e75SGabriel Fernandez 	struct stm32_clk_drive *drive_data = osc_data->drive;
113*9be88e75SGabriel Fernandez 	uintptr_t address;
114*9be88e75SGabriel Fernandez 	uint32_t mask;
115*9be88e75SGabriel Fernandez 	uint32_t value;
116*9be88e75SGabriel Fernandez 
117*9be88e75SGabriel Fernandez 	if (drive_data == NULL) {
118*9be88e75SGabriel Fernandez 		return;
119*9be88e75SGabriel Fernandez 	}
120*9be88e75SGabriel Fernandez 
121*9be88e75SGabriel Fernandez 	address = priv->base + drive_data->offset;
122*9be88e75SGabriel Fernandez 
123*9be88e75SGabriel Fernandez 	mask = (BIT(drive_data->drv_width) - 1U) <<  drive_data->drv_shift;
124*9be88e75SGabriel Fernandez 
125*9be88e75SGabriel Fernandez 	/*
126*9be88e75SGabriel Fernandez 	 * Warning: not recommended to switch directly from "high drive"
127*9be88e75SGabriel Fernandez 	 * to "medium low drive", and vice-versa.
128*9be88e75SGabriel Fernandez 	 */
129*9be88e75SGabriel Fernandez 	value = (mmio_read_32(address) & mask) >> drive_data->drv_shift;
130*9be88e75SGabriel Fernandez 
131*9be88e75SGabriel Fernandez 	while (value != lsedrv) {
132*9be88e75SGabriel Fernandez 		if (value > lsedrv) {
133*9be88e75SGabriel Fernandez 			value--;
134*9be88e75SGabriel Fernandez 		} else {
135*9be88e75SGabriel Fernandez 			value++;
136*9be88e75SGabriel Fernandez 		}
137*9be88e75SGabriel Fernandez 
138*9be88e75SGabriel Fernandez 		mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift);
139*9be88e75SGabriel Fernandez 	}
140*9be88e75SGabriel Fernandez }
141*9be88e75SGabriel Fernandez 
142*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on)
143*9be88e75SGabriel Fernandez {
144*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
145*9be88e75SGabriel Fernandez 
146*9be88e75SGabriel Fernandez 	return _clk_stm32_gate_wait_ready(priv, osc_data->gate_id, ready_on);
147*9be88e75SGabriel Fernandez }
148*9be88e75SGabriel Fernandez 
149*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id)
150*9be88e75SGabriel Fernandez {
151*9be88e75SGabriel Fernandez 	return clk_oscillator_wait_ready(priv, id, true);
152*9be88e75SGabriel Fernandez }
153*9be88e75SGabriel Fernandez 
154*9be88e75SGabriel Fernandez int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id)
155*9be88e75SGabriel Fernandez {
156*9be88e75SGabriel Fernandez 	return clk_oscillator_wait_ready(priv, id, false);
157*9be88e75SGabriel Fernandez }
158*9be88e75SGabriel Fernandez 
159*9be88e75SGabriel Fernandez static int clk_gate_enable(struct stm32_clk_priv *priv, int id)
160*9be88e75SGabriel Fernandez {
161*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
162*9be88e75SGabriel Fernandez 	struct clk_gate_cfg *cfg = clk->clock_cfg;
163*9be88e75SGabriel Fernandez 
164*9be88e75SGabriel Fernandez 	mmio_setbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx));
165*9be88e75SGabriel Fernandez 
166*9be88e75SGabriel Fernandez 	return 0;
167*9be88e75SGabriel Fernandez }
168*9be88e75SGabriel Fernandez 
169*9be88e75SGabriel Fernandez static void clk_gate_disable(struct stm32_clk_priv *priv, int id)
170*9be88e75SGabriel Fernandez {
171*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
172*9be88e75SGabriel Fernandez 	struct clk_gate_cfg *cfg = clk->clock_cfg;
173*9be88e75SGabriel Fernandez 
174*9be88e75SGabriel Fernandez 	mmio_clrbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx));
175*9be88e75SGabriel Fernandez }
176*9be88e75SGabriel Fernandez 
177*9be88e75SGabriel Fernandez static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id)
178*9be88e75SGabriel Fernandez {
179*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
180*9be88e75SGabriel Fernandez 	struct clk_gate_cfg *cfg = clk->clock_cfg;
181*9be88e75SGabriel Fernandez 
182*9be88e75SGabriel Fernandez 	return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U);
183*9be88e75SGabriel Fernandez }
184*9be88e75SGabriel Fernandez 
185*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_gate_ops = {
186*9be88e75SGabriel Fernandez 	.enable		= clk_gate_enable,
187*9be88e75SGabriel Fernandez 	.disable	= clk_gate_disable,
188*9be88e75SGabriel Fernandez 	.is_enabled	= clk_gate_is_enabled,
189*9be88e75SGabriel Fernandez };
190*9be88e75SGabriel Fernandez 
191*9be88e75SGabriel Fernandez void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id)
192*9be88e75SGabriel Fernandez {
193*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate = &priv->gates[gate_id];
194*9be88e75SGabriel Fernandez 	uintptr_t addr = priv->base + gate->offset;
195*9be88e75SGabriel Fernandez 
196*9be88e75SGabriel Fernandez 	if (gate->set_clr != 0U) {
197*9be88e75SGabriel Fernandez 		mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx));
198*9be88e75SGabriel Fernandez 	} else {
199*9be88e75SGabriel Fernandez 		mmio_clrbits_32(addr, BIT(gate->bit_idx));
200*9be88e75SGabriel Fernandez 	}
201*9be88e75SGabriel Fernandez }
202*9be88e75SGabriel Fernandez 
203*9be88e75SGabriel Fernandez int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id)
204*9be88e75SGabriel Fernandez {
205*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate = &priv->gates[gate_id];
206*9be88e75SGabriel Fernandez 	uintptr_t addr = priv->base + gate->offset;
207*9be88e75SGabriel Fernandez 
208*9be88e75SGabriel Fernandez 	if (gate->set_clr != 0U) {
209*9be88e75SGabriel Fernandez 		mmio_write_32(addr, BIT(gate->bit_idx));
210*9be88e75SGabriel Fernandez 
211*9be88e75SGabriel Fernandez 	} else {
212*9be88e75SGabriel Fernandez 		mmio_setbits_32(addr, BIT(gate->bit_idx));
213*9be88e75SGabriel Fernandez 	}
214*9be88e75SGabriel Fernandez 
215*9be88e75SGabriel Fernandez 	return 0;
216*9be88e75SGabriel Fernandez }
217*9be88e75SGabriel Fernandez 
218*9be88e75SGabriel Fernandez const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id)
219*9be88e75SGabriel Fernandez {
220*9be88e75SGabriel Fernandez 	return priv->clks[id].name;
221*9be88e75SGabriel Fernandez }
222*9be88e75SGabriel Fernandez 
223*9be88e75SGabriel Fernandez const char *clk_stm32_get_name(struct stm32_clk_priv *priv,
224*9be88e75SGabriel Fernandez 			       unsigned long binding_id)
225*9be88e75SGabriel Fernandez {
226*9be88e75SGabriel Fernandez 	int id;
227*9be88e75SGabriel Fernandez 
228*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
229*9be88e75SGabriel Fernandez 	if (id == -EINVAL) {
230*9be88e75SGabriel Fernandez 		return NULL;
231*9be88e75SGabriel Fernandez 	}
232*9be88e75SGabriel Fernandez 
233*9be88e75SGabriel Fernandez 	return _clk_stm32_get_name(priv, id);
234*9be88e75SGabriel Fernandez }
235*9be88e75SGabriel Fernandez 
236*9be88e75SGabriel Fernandez const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id)
237*9be88e75SGabriel Fernandez {
238*9be88e75SGabriel Fernandez 	if ((unsigned int)id < priv->num) {
239*9be88e75SGabriel Fernandez 		return &priv->clks[id];
240*9be88e75SGabriel Fernandez 	}
241*9be88e75SGabriel Fernandez 
242*9be88e75SGabriel Fernandez 	return NULL;
243*9be88e75SGabriel Fernandez }
244*9be88e75SGabriel Fernandez 
245*9be88e75SGabriel Fernandez #define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U)
246*9be88e75SGabriel Fernandez 
247*9be88e75SGabriel Fernandez static unsigned int _get_table_div(const struct clk_div_table *table,
248*9be88e75SGabriel Fernandez 				   unsigned int val)
249*9be88e75SGabriel Fernandez {
250*9be88e75SGabriel Fernandez 	const struct clk_div_table *clkt;
251*9be88e75SGabriel Fernandez 
252*9be88e75SGabriel Fernandez 	for (clkt = table; clkt->div; clkt++) {
253*9be88e75SGabriel Fernandez 		if (clkt->val == val) {
254*9be88e75SGabriel Fernandez 			return clkt->div;
255*9be88e75SGabriel Fernandez 		}
256*9be88e75SGabriel Fernandez 	}
257*9be88e75SGabriel Fernandez 
258*9be88e75SGabriel Fernandez 	return 0;
259*9be88e75SGabriel Fernandez }
260*9be88e75SGabriel Fernandez 
261*9be88e75SGabriel Fernandez static unsigned int _get_div(const struct clk_div_table *table,
262*9be88e75SGabriel Fernandez 			     unsigned int val, unsigned long flags,
263*9be88e75SGabriel Fernandez 			     uint8_t width)
264*9be88e75SGabriel Fernandez {
265*9be88e75SGabriel Fernandez 	if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) {
266*9be88e75SGabriel Fernandez 		return val;
267*9be88e75SGabriel Fernandez 	}
268*9be88e75SGabriel Fernandez 
269*9be88e75SGabriel Fernandez 	if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) {
270*9be88e75SGabriel Fernandez 		return BIT(val);
271*9be88e75SGabriel Fernandez 	}
272*9be88e75SGabriel Fernandez 
273*9be88e75SGabriel Fernandez 	if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) {
274*9be88e75SGabriel Fernandez 		return (val != 0U) ? val : BIT(width);
275*9be88e75SGabriel Fernandez 	}
276*9be88e75SGabriel Fernandez 
277*9be88e75SGabriel Fernandez 	if (table != NULL) {
278*9be88e75SGabriel Fernandez 		return _get_table_div(table, val);
279*9be88e75SGabriel Fernandez 	}
280*9be88e75SGabriel Fernandez 
281*9be88e75SGabriel Fernandez 	return val + 1U;
282*9be88e75SGabriel Fernandez }
283*9be88e75SGabriel Fernandez 
284*9be88e75SGabriel Fernandez #define TIMEOUT_US_200MS	U(200000)
285*9be88e75SGabriel Fernandez #define CLKSRC_TIMEOUT		TIMEOUT_US_200MS
286*9be88e75SGabriel Fernandez 
287*9be88e75SGabriel Fernandez int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel)
288*9be88e75SGabriel Fernandez {
289*9be88e75SGabriel Fernandez 	const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK];
290*9be88e75SGabriel Fernandez 	const struct mux_cfg *mux = parents->mux;
291*9be88e75SGabriel Fernandez 	uintptr_t address = priv->base + mux->offset;
292*9be88e75SGabriel Fernandez 	uint32_t mask;
293*9be88e75SGabriel Fernandez 	uint64_t timeout;
294*9be88e75SGabriel Fernandez 
295*9be88e75SGabriel Fernandez 	mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
296*9be88e75SGabriel Fernandez 
297*9be88e75SGabriel Fernandez 	mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask);
298*9be88e75SGabriel Fernandez 
299*9be88e75SGabriel Fernandez 	if (mux->bitrdy == MUX_NO_BIT_RDY) {
300*9be88e75SGabriel Fernandez 		return 0;
301*9be88e75SGabriel Fernandez 	}
302*9be88e75SGabriel Fernandez 
303*9be88e75SGabriel Fernandez 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
304*9be88e75SGabriel Fernandez 
305*9be88e75SGabriel Fernandez 	mask = BIT(mux->bitrdy);
306*9be88e75SGabriel Fernandez 
307*9be88e75SGabriel Fernandez 	while ((mmio_read_32(address) & mask) == 0U) {
308*9be88e75SGabriel Fernandez 		if (timeout_elapsed(timeout)) {
309*9be88e75SGabriel Fernandez 			return -ETIMEDOUT;
310*9be88e75SGabriel Fernandez 		}
311*9be88e75SGabriel Fernandez 	}
312*9be88e75SGabriel Fernandez 
313*9be88e75SGabriel Fernandez 	return 0;
314*9be88e75SGabriel Fernandez }
315*9be88e75SGabriel Fernandez 
316*9be88e75SGabriel Fernandez int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp)
317*9be88e75SGabriel Fernandez {
318*9be88e75SGabriel Fernandez 	const struct parent_cfg *parents;
319*9be88e75SGabriel Fernandez 	uint16_t pid;
320*9be88e75SGabriel Fernandez 	uint8_t sel;
321*9be88e75SGabriel Fernandez 	int old_parent;
322*9be88e75SGabriel Fernandez 
323*9be88e75SGabriel Fernandez 	pid = priv->clks[clk].parent;
324*9be88e75SGabriel Fernandez 
325*9be88e75SGabriel Fernandez 	if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) {
326*9be88e75SGabriel Fernandez 		return -EINVAL;
327*9be88e75SGabriel Fernandez 	}
328*9be88e75SGabriel Fernandez 
329*9be88e75SGabriel Fernandez 	old_parent = _clk_stm32_get_parent(priv, clk);
330*9be88e75SGabriel Fernandez 	if (old_parent == clkp) {
331*9be88e75SGabriel Fernandez 		return 0;
332*9be88e75SGabriel Fernandez 	}
333*9be88e75SGabriel Fernandez 
334*9be88e75SGabriel Fernandez 	parents = &priv->parents[pid & MUX_PARENT_MASK];
335*9be88e75SGabriel Fernandez 
336*9be88e75SGabriel Fernandez 	for (sel = 0; sel <  parents->num_parents; sel++) {
337*9be88e75SGabriel Fernandez 		if (parents->id_parents[sel] == (uint16_t)clkp) {
338*9be88e75SGabriel Fernandez 			bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk);
339*9be88e75SGabriel Fernandez 			int err = 0;
340*9be88e75SGabriel Fernandez 
341*9be88e75SGabriel Fernandez 			/* Enable the parents (for glitch free mux) */
342*9be88e75SGabriel Fernandez 			_clk_stm32_enable(priv, clkp);
343*9be88e75SGabriel Fernandez 			_clk_stm32_enable(priv, old_parent);
344*9be88e75SGabriel Fernandez 
345*9be88e75SGabriel Fernandez 			err = clk_mux_set_parent(priv, pid, sel);
346*9be88e75SGabriel Fernandez 
347*9be88e75SGabriel Fernandez 			_clk_stm32_disable(priv, old_parent);
348*9be88e75SGabriel Fernandez 
349*9be88e75SGabriel Fernandez 			if (clk_was_enabled) {
350*9be88e75SGabriel Fernandez 				_clk_stm32_disable(priv, old_parent);
351*9be88e75SGabriel Fernandez 			} else {
352*9be88e75SGabriel Fernandez 				_clk_stm32_disable(priv, clkp);
353*9be88e75SGabriel Fernandez 			}
354*9be88e75SGabriel Fernandez 
355*9be88e75SGabriel Fernandez 			return err;
356*9be88e75SGabriel Fernandez 		}
357*9be88e75SGabriel Fernandez 	}
358*9be88e75SGabriel Fernandez 
359*9be88e75SGabriel Fernandez 	return -EINVAL;
360*9be88e75SGabriel Fernandez }
361*9be88e75SGabriel Fernandez 
362*9be88e75SGabriel Fernandez int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id)
363*9be88e75SGabriel Fernandez {
364*9be88e75SGabriel Fernandez 	const struct parent_cfg *parent;
365*9be88e75SGabriel Fernandez 	const struct mux_cfg *mux;
366*9be88e75SGabriel Fernandez 	uint32_t mask;
367*9be88e75SGabriel Fernandez 
368*9be88e75SGabriel Fernandez 	if (mux_id >= priv->nb_parents) {
369*9be88e75SGabriel Fernandez 		panic();
370*9be88e75SGabriel Fernandez 	}
371*9be88e75SGabriel Fernandez 
372*9be88e75SGabriel Fernandez 	parent = &priv->parents[mux_id];
373*9be88e75SGabriel Fernandez 	mux = parent->mux;
374*9be88e75SGabriel Fernandez 
375*9be88e75SGabriel Fernandez 	mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
376*9be88e75SGabriel Fernandez 
377*9be88e75SGabriel Fernandez 	return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift;
378*9be88e75SGabriel Fernandez }
379*9be88e75SGabriel Fernandez 
380*9be88e75SGabriel Fernandez int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel)
381*9be88e75SGabriel Fernandez {
382*9be88e75SGabriel Fernandez 	uint16_t pid;
383*9be88e75SGabriel Fernandez 
384*9be88e75SGabriel Fernandez 	pid = priv->clks[clk].parent;
385*9be88e75SGabriel Fernandez 
386*9be88e75SGabriel Fernandez 	if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) {
387*9be88e75SGabriel Fernandez 		return -EINVAL;
388*9be88e75SGabriel Fernandez 	}
389*9be88e75SGabriel Fernandez 
390*9be88e75SGabriel Fernandez 	return clk_mux_set_parent(priv, pid, sel);
391*9be88e75SGabriel Fernandez }
392*9be88e75SGabriel Fernandez 
393*9be88e75SGabriel Fernandez int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id)
394*9be88e75SGabriel Fernandez {
395*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, clk_id);
396*9be88e75SGabriel Fernandez 	const struct parent_cfg *parent;
397*9be88e75SGabriel Fernandez 	uint16_t mux_id;
398*9be88e75SGabriel Fernandez 	int sel;
399*9be88e75SGabriel Fernandez 
400*9be88e75SGabriel Fernandez 	mux_id = priv->clks[clk_id].parent;
401*9be88e75SGabriel Fernandez 	if (mux_id == CLK_IS_ROOT) {
402*9be88e75SGabriel Fernandez 		return CLK_IS_ROOT;
403*9be88e75SGabriel Fernandez 	}
404*9be88e75SGabriel Fernandez 
405*9be88e75SGabriel Fernandez 	if (mux_id < MUX_MAX_PARENTS) {
406*9be88e75SGabriel Fernandez 		return mux_id & MUX_PARENT_MASK;
407*9be88e75SGabriel Fernandez 	}
408*9be88e75SGabriel Fernandez 
409*9be88e75SGabriel Fernandez 	mux_id &= MUX_PARENT_MASK;
410*9be88e75SGabriel Fernandez 	parent = &priv->parents[mux_id];
411*9be88e75SGabriel Fernandez 
412*9be88e75SGabriel Fernandez 	if (clk->ops->get_parent != NULL) {
413*9be88e75SGabriel Fernandez 		sel = clk->ops->get_parent(priv, clk_id);
414*9be88e75SGabriel Fernandez 	} else {
415*9be88e75SGabriel Fernandez 		sel = clk_mux_get_parent(priv, mux_id);
416*9be88e75SGabriel Fernandez 	}
417*9be88e75SGabriel Fernandez 
418*9be88e75SGabriel Fernandez 	if (sel < parent->num_parents) {
419*9be88e75SGabriel Fernandez 		return parent->id_parents[sel];
420*9be88e75SGabriel Fernandez 	}
421*9be88e75SGabriel Fernandez 
422*9be88e75SGabriel Fernandez 	return -EINVAL;
423*9be88e75SGabriel Fernandez }
424*9be88e75SGabriel Fernandez 
425*9be88e75SGabriel Fernandez int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id)
426*9be88e75SGabriel Fernandez {
427*9be88e75SGabriel Fernandez 	uint16_t mux_id;
428*9be88e75SGabriel Fernandez 
429*9be88e75SGabriel Fernandez 	mux_id = priv->clks[clk_id].parent;
430*9be88e75SGabriel Fernandez 	if (mux_id == CLK_IS_ROOT) {
431*9be88e75SGabriel Fernandez 		return CLK_IS_ROOT;
432*9be88e75SGabriel Fernandez 	}
433*9be88e75SGabriel Fernandez 
434*9be88e75SGabriel Fernandez 	if (mux_id < MUX_MAX_PARENTS) {
435*9be88e75SGabriel Fernandez 		return mux_id & MUX_PARENT_MASK;
436*9be88e75SGabriel Fernandez 	}
437*9be88e75SGabriel Fernandez 
438*9be88e75SGabriel Fernandez 	mux_id &= MUX_PARENT_MASK;
439*9be88e75SGabriel Fernandez 
440*9be88e75SGabriel Fernandez 	return clk_mux_get_parent(priv, mux_id);
441*9be88e75SGabriel Fernandez }
442*9be88e75SGabriel Fernandez 
443*9be88e75SGabriel Fernandez int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx)
444*9be88e75SGabriel Fernandez {
445*9be88e75SGabriel Fernandez 	const struct parent_cfg *parent;
446*9be88e75SGabriel Fernandez 	uint16_t mux_id;
447*9be88e75SGabriel Fernandez 
448*9be88e75SGabriel Fernandez 	mux_id = priv->clks[clk_id].parent;
449*9be88e75SGabriel Fernandez 	if (mux_id == CLK_IS_ROOT) {
450*9be88e75SGabriel Fernandez 		return CLK_IS_ROOT;
451*9be88e75SGabriel Fernandez 	}
452*9be88e75SGabriel Fernandez 
453*9be88e75SGabriel Fernandez 	if (mux_id < MUX_MAX_PARENTS) {
454*9be88e75SGabriel Fernandez 		return mux_id & MUX_PARENT_MASK;
455*9be88e75SGabriel Fernandez 	}
456*9be88e75SGabriel Fernandez 
457*9be88e75SGabriel Fernandez 	mux_id &= MUX_PARENT_MASK;
458*9be88e75SGabriel Fernandez 	parent = &priv->parents[mux_id];
459*9be88e75SGabriel Fernandez 
460*9be88e75SGabriel Fernandez 	if (idx < parent->num_parents) {
461*9be88e75SGabriel Fernandez 		return parent->id_parents[idx];
462*9be88e75SGabriel Fernandez 	}
463*9be88e75SGabriel Fernandez 
464*9be88e75SGabriel Fernandez 	return -EINVAL;
465*9be88e75SGabriel Fernandez }
466*9be88e75SGabriel Fernandez 
467*9be88e75SGabriel Fernandez int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id)
468*9be88e75SGabriel Fernandez {
469*9be88e75SGabriel Fernandez 	unsigned int i;
470*9be88e75SGabriel Fernandez 
471*9be88e75SGabriel Fernandez 	for (i = 0U; i < priv->num; i++) {
472*9be88e75SGabriel Fernandez 		if (binding_id == priv->clks[i].binding) {
473*9be88e75SGabriel Fernandez 			return (int)i;
474*9be88e75SGabriel Fernandez 		}
475*9be88e75SGabriel Fernandez 	}
476*9be88e75SGabriel Fernandez 
477*9be88e75SGabriel Fernandez 	return -EINVAL;
478*9be88e75SGabriel Fernandez }
479*9be88e75SGabriel Fernandez 
480*9be88e75SGabriel Fernandez unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id)
481*9be88e75SGabriel Fernandez {
482*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
483*9be88e75SGabriel Fernandez 	int parent;
484*9be88e75SGabriel Fernandez 	unsigned long rate = 0UL;
485*9be88e75SGabriel Fernandez 
486*9be88e75SGabriel Fernandez 	if ((unsigned int)id >= priv->num) {
487*9be88e75SGabriel Fernandez 		return rate;
488*9be88e75SGabriel Fernandez 	}
489*9be88e75SGabriel Fernandez 
490*9be88e75SGabriel Fernandez 	parent = _clk_stm32_get_parent(priv, id);
491*9be88e75SGabriel Fernandez 
492*9be88e75SGabriel Fernandez 	if (clk->ops->recalc_rate != NULL) {
493*9be88e75SGabriel Fernandez 		unsigned long prate = 0UL;
494*9be88e75SGabriel Fernandez 
495*9be88e75SGabriel Fernandez 		if (parent != CLK_IS_ROOT) {
496*9be88e75SGabriel Fernandez 			prate = _clk_stm32_get_rate(priv, parent);
497*9be88e75SGabriel Fernandez 		}
498*9be88e75SGabriel Fernandez 
499*9be88e75SGabriel Fernandez 		rate = clk->ops->recalc_rate(priv, id, prate);
500*9be88e75SGabriel Fernandez 
501*9be88e75SGabriel Fernandez 		return rate;
502*9be88e75SGabriel Fernandez 	}
503*9be88e75SGabriel Fernandez 
504*9be88e75SGabriel Fernandez 	switch (parent) {
505*9be88e75SGabriel Fernandez 	case CLK_IS_ROOT:
506*9be88e75SGabriel Fernandez 		panic();
507*9be88e75SGabriel Fernandez 
508*9be88e75SGabriel Fernandez 	default:
509*9be88e75SGabriel Fernandez 		rate = _clk_stm32_get_rate(priv, parent);
510*9be88e75SGabriel Fernandez 		break;
511*9be88e75SGabriel Fernandez 	}
512*9be88e75SGabriel Fernandez 	return rate;
513*9be88e75SGabriel Fernandez 
514*9be88e75SGabriel Fernandez }
515*9be88e75SGabriel Fernandez 
516*9be88e75SGabriel Fernandez unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id)
517*9be88e75SGabriel Fernandez {
518*9be88e75SGabriel Fernandez 	int parent_id = _clk_stm32_get_parent(priv, id);
519*9be88e75SGabriel Fernandez 
520*9be88e75SGabriel Fernandez 	return _clk_stm32_get_rate(priv, parent_id);
521*9be88e75SGabriel Fernandez }
522*9be88e75SGabriel Fernandez 
523*9be88e75SGabriel Fernandez static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id)
524*9be88e75SGabriel Fernandez {
525*9be88e75SGabriel Fernandez 	return priv->clks[id].flags;
526*9be88e75SGabriel Fernandez }
527*9be88e75SGabriel Fernandez 
528*9be88e75SGabriel Fernandez bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag)
529*9be88e75SGabriel Fernandez {
530*9be88e75SGabriel Fernandez 	if (_stm32_clk_get_flags(priv, id) & flag) {
531*9be88e75SGabriel Fernandez 		return true;
532*9be88e75SGabriel Fernandez 	}
533*9be88e75SGabriel Fernandez 
534*9be88e75SGabriel Fernandez 	return false;
535*9be88e75SGabriel Fernandez }
536*9be88e75SGabriel Fernandez 
537*9be88e75SGabriel Fernandez int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id)
538*9be88e75SGabriel Fernandez {
539*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
540*9be88e75SGabriel Fernandez 
541*9be88e75SGabriel Fernandez 	if (clk->ops->enable != NULL) {
542*9be88e75SGabriel Fernandez 		clk->ops->enable(priv, id);
543*9be88e75SGabriel Fernandez 	}
544*9be88e75SGabriel Fernandez 
545*9be88e75SGabriel Fernandez 	return 0;
546*9be88e75SGabriel Fernandez }
547*9be88e75SGabriel Fernandez 
548*9be88e75SGabriel Fernandez static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id)
549*9be88e75SGabriel Fernandez {
550*9be88e75SGabriel Fernandez 	int parent;
551*9be88e75SGabriel Fernandez 	int ret = 0;
552*9be88e75SGabriel Fernandez 
553*9be88e75SGabriel Fernandez 	if (priv->gate_refcounts[id] == 0U) {
554*9be88e75SGabriel Fernandez 		parent = _clk_stm32_get_parent(priv, id);
555*9be88e75SGabriel Fernandez 		if (parent != CLK_IS_ROOT) {
556*9be88e75SGabriel Fernandez 			ret = _clk_stm32_enable_core(priv, parent);
557*9be88e75SGabriel Fernandez 			if (ret) {
558*9be88e75SGabriel Fernandez 				return ret;
559*9be88e75SGabriel Fernandez 			}
560*9be88e75SGabriel Fernandez 		}
561*9be88e75SGabriel Fernandez 		clk_stm32_enable_call_ops(priv, id);
562*9be88e75SGabriel Fernandez 	}
563*9be88e75SGabriel Fernandez 
564*9be88e75SGabriel Fernandez 	priv->gate_refcounts[id]++;
565*9be88e75SGabriel Fernandez 
566*9be88e75SGabriel Fernandez 	if (priv->gate_refcounts[id] == UINT_MAX) {
567*9be88e75SGabriel Fernandez 		ERROR("%s: %d max enable count !", __func__, id);
568*9be88e75SGabriel Fernandez 		panic();
569*9be88e75SGabriel Fernandez 	}
570*9be88e75SGabriel Fernandez 
571*9be88e75SGabriel Fernandez 	return 0;
572*9be88e75SGabriel Fernandez }
573*9be88e75SGabriel Fernandez 
574*9be88e75SGabriel Fernandez int _clk_stm32_enable(struct stm32_clk_priv *priv, int id)
575*9be88e75SGabriel Fernandez {
576*9be88e75SGabriel Fernandez 	int ret;
577*9be88e75SGabriel Fernandez 
578*9be88e75SGabriel Fernandez 	stm32mp1_clk_lock(&refcount_lock);
579*9be88e75SGabriel Fernandez 	ret = _clk_stm32_enable_core(priv, id);
580*9be88e75SGabriel Fernandez 	stm32mp1_clk_unlock(&refcount_lock);
581*9be88e75SGabriel Fernandez 
582*9be88e75SGabriel Fernandez 	return ret;
583*9be88e75SGabriel Fernandez }
584*9be88e75SGabriel Fernandez 
585*9be88e75SGabriel Fernandez void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id)
586*9be88e75SGabriel Fernandez {
587*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
588*9be88e75SGabriel Fernandez 
589*9be88e75SGabriel Fernandez 	if (clk->ops->disable != NULL) {
590*9be88e75SGabriel Fernandez 		clk->ops->disable(priv, id);
591*9be88e75SGabriel Fernandez 	}
592*9be88e75SGabriel Fernandez }
593*9be88e75SGabriel Fernandez 
594*9be88e75SGabriel Fernandez static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id)
595*9be88e75SGabriel Fernandez {
596*9be88e75SGabriel Fernandez 	int parent;
597*9be88e75SGabriel Fernandez 
598*9be88e75SGabriel Fernandez 	if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) {
599*9be88e75SGabriel Fernandez 		return;
600*9be88e75SGabriel Fernandez 	}
601*9be88e75SGabriel Fernandez 
602*9be88e75SGabriel Fernandez 	if (priv->gate_refcounts[id] == 0U) {
603*9be88e75SGabriel Fernandez 		/* case of clock ignore unused */
604*9be88e75SGabriel Fernandez 		if (_clk_stm32_is_enabled(priv, id)) {
605*9be88e75SGabriel Fernandez 			clk_stm32_disable_call_ops(priv, id);
606*9be88e75SGabriel Fernandez 			return;
607*9be88e75SGabriel Fernandez 		}
608*9be88e75SGabriel Fernandez 		VERBOSE("%s: %d already disabled !\n\n", __func__, id);
609*9be88e75SGabriel Fernandez 		return;
610*9be88e75SGabriel Fernandez 	}
611*9be88e75SGabriel Fernandez 
612*9be88e75SGabriel Fernandez 	if (--priv->gate_refcounts[id] > 0U) {
613*9be88e75SGabriel Fernandez 		return;
614*9be88e75SGabriel Fernandez 	}
615*9be88e75SGabriel Fernandez 
616*9be88e75SGabriel Fernandez 	clk_stm32_disable_call_ops(priv, id);
617*9be88e75SGabriel Fernandez 
618*9be88e75SGabriel Fernandez 	parent = _clk_stm32_get_parent(priv, id);
619*9be88e75SGabriel Fernandez 	if (parent != CLK_IS_ROOT) {
620*9be88e75SGabriel Fernandez 		_clk_stm32_disable_core(priv, parent);
621*9be88e75SGabriel Fernandez 	}
622*9be88e75SGabriel Fernandez }
623*9be88e75SGabriel Fernandez 
624*9be88e75SGabriel Fernandez void _clk_stm32_disable(struct stm32_clk_priv *priv, int id)
625*9be88e75SGabriel Fernandez {
626*9be88e75SGabriel Fernandez 	stm32mp1_clk_lock(&refcount_lock);
627*9be88e75SGabriel Fernandez 
628*9be88e75SGabriel Fernandez 	_clk_stm32_disable_core(priv, id);
629*9be88e75SGabriel Fernandez 
630*9be88e75SGabriel Fernandez 	stm32mp1_clk_unlock(&refcount_lock);
631*9be88e75SGabriel Fernandez }
632*9be88e75SGabriel Fernandez 
633*9be88e75SGabriel Fernandez bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id)
634*9be88e75SGabriel Fernandez {
635*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
636*9be88e75SGabriel Fernandez 
637*9be88e75SGabriel Fernandez 	if (clk->ops->is_enabled != NULL) {
638*9be88e75SGabriel Fernandez 		return clk->ops->is_enabled(priv, id);
639*9be88e75SGabriel Fernandez 	}
640*9be88e75SGabriel Fernandez 
641*9be88e75SGabriel Fernandez 	return priv->gate_refcounts[id];
642*9be88e75SGabriel Fernandez }
643*9be88e75SGabriel Fernandez 
644*9be88e75SGabriel Fernandez static int clk_stm32_enable(unsigned long binding_id)
645*9be88e75SGabriel Fernandez {
646*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
647*9be88e75SGabriel Fernandez 	int id;
648*9be88e75SGabriel Fernandez 
649*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
650*9be88e75SGabriel Fernandez 	if (id == -EINVAL) {
651*9be88e75SGabriel Fernandez 		return id;
652*9be88e75SGabriel Fernandez 	}
653*9be88e75SGabriel Fernandez 
654*9be88e75SGabriel Fernandez 	return _clk_stm32_enable(priv, id);
655*9be88e75SGabriel Fernandez }
656*9be88e75SGabriel Fernandez 
657*9be88e75SGabriel Fernandez static void clk_stm32_disable(unsigned long binding_id)
658*9be88e75SGabriel Fernandez {
659*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
660*9be88e75SGabriel Fernandez 	int id;
661*9be88e75SGabriel Fernandez 
662*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
663*9be88e75SGabriel Fernandez 	if (id != -EINVAL) {
664*9be88e75SGabriel Fernandez 		_clk_stm32_disable(priv, id);
665*9be88e75SGabriel Fernandez 	}
666*9be88e75SGabriel Fernandez }
667*9be88e75SGabriel Fernandez 
668*9be88e75SGabriel Fernandez static bool clk_stm32_is_enabled(unsigned long binding_id)
669*9be88e75SGabriel Fernandez {
670*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
671*9be88e75SGabriel Fernandez 	int id;
672*9be88e75SGabriel Fernandez 
673*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
674*9be88e75SGabriel Fernandez 	if (id == -EINVAL) {
675*9be88e75SGabriel Fernandez 		return false;
676*9be88e75SGabriel Fernandez 	}
677*9be88e75SGabriel Fernandez 
678*9be88e75SGabriel Fernandez 	return _clk_stm32_is_enabled(priv, id);
679*9be88e75SGabriel Fernandez }
680*9be88e75SGabriel Fernandez 
681*9be88e75SGabriel Fernandez static unsigned long clk_stm32_get_rate(unsigned long binding_id)
682*9be88e75SGabriel Fernandez {
683*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
684*9be88e75SGabriel Fernandez 	int id;
685*9be88e75SGabriel Fernandez 
686*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
687*9be88e75SGabriel Fernandez 	if (id == -EINVAL) {
688*9be88e75SGabriel Fernandez 		return 0UL;
689*9be88e75SGabriel Fernandez 	}
690*9be88e75SGabriel Fernandez 
691*9be88e75SGabriel Fernandez 	return _clk_stm32_get_rate(priv, id);
692*9be88e75SGabriel Fernandez }
693*9be88e75SGabriel Fernandez 
694*9be88e75SGabriel Fernandez static int clk_stm32_get_parent(unsigned long binding_id)
695*9be88e75SGabriel Fernandez {
696*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
697*9be88e75SGabriel Fernandez 	int id;
698*9be88e75SGabriel Fernandez 
699*9be88e75SGabriel Fernandez 	id = clk_get_index(priv, binding_id);
700*9be88e75SGabriel Fernandez 	if (id == -EINVAL) {
701*9be88e75SGabriel Fernandez 		return id;
702*9be88e75SGabriel Fernandez 	}
703*9be88e75SGabriel Fernandez 
704*9be88e75SGabriel Fernandez 	return _clk_stm32_get_parent(priv, id);
705*9be88e75SGabriel Fernandez }
706*9be88e75SGabriel Fernandez 
707*9be88e75SGabriel Fernandez static const struct clk_ops stm32mp_clk_ops = {
708*9be88e75SGabriel Fernandez 	.enable		= clk_stm32_enable,
709*9be88e75SGabriel Fernandez 	.disable	= clk_stm32_disable,
710*9be88e75SGabriel Fernandez 	.is_enabled	= clk_stm32_is_enabled,
711*9be88e75SGabriel Fernandez 	.get_rate	= clk_stm32_get_rate,
712*9be88e75SGabriel Fernandez 	.get_parent	= clk_stm32_get_parent,
713*9be88e75SGabriel Fernandez };
714*9be88e75SGabriel Fernandez 
715*9be88e75SGabriel Fernandez void clk_stm32_enable_critical_clocks(void)
716*9be88e75SGabriel Fernandez {
717*9be88e75SGabriel Fernandez 	struct stm32_clk_priv *priv = clk_stm32_get_priv();
718*9be88e75SGabriel Fernandez 	unsigned int i;
719*9be88e75SGabriel Fernandez 
720*9be88e75SGabriel Fernandez 	for (i = 0U; i < priv->num; i++) {
721*9be88e75SGabriel Fernandez 		if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) {
722*9be88e75SGabriel Fernandez 			_clk_stm32_enable(priv, i);
723*9be88e75SGabriel Fernandez 		}
724*9be88e75SGabriel Fernandez 	}
725*9be88e75SGabriel Fernandez }
726*9be88e75SGabriel Fernandez 
727*9be88e75SGabriel Fernandez static void stm32_clk_register(void)
728*9be88e75SGabriel Fernandez {
729*9be88e75SGabriel Fernandez 	clk_register(&stm32mp_clk_ops);
730*9be88e75SGabriel Fernandez }
731*9be88e75SGabriel Fernandez 
732*9be88e75SGabriel Fernandez uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id)
733*9be88e75SGabriel Fernandez {
734*9be88e75SGabriel Fernandez 	const struct div_cfg *divider = &priv->div[div_id];
735*9be88e75SGabriel Fernandez 	uint32_t val = 0;
736*9be88e75SGabriel Fernandez 
737*9be88e75SGabriel Fernandez 	val = mmio_read_32(priv->base + divider->offset) >> divider->shift;
738*9be88e75SGabriel Fernandez 	val &= clk_div_mask(divider->width);
739*9be88e75SGabriel Fernandez 
740*9be88e75SGabriel Fernandez 	return val;
741*9be88e75SGabriel Fernandez }
742*9be88e75SGabriel Fernandez 
743*9be88e75SGabriel Fernandez unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv,
744*9be88e75SGabriel Fernandez 					int div_id,
745*9be88e75SGabriel Fernandez 					unsigned long prate)
746*9be88e75SGabriel Fernandez {
747*9be88e75SGabriel Fernandez 	const struct div_cfg *divider = &priv->div[div_id];
748*9be88e75SGabriel Fernandez 	uint32_t val = clk_stm32_div_get_value(priv, div_id);
749*9be88e75SGabriel Fernandez 	unsigned int div = 0U;
750*9be88e75SGabriel Fernandez 
751*9be88e75SGabriel Fernandez 	div = _get_div(divider->table, val, divider->flags, divider->width);
752*9be88e75SGabriel Fernandez 	if (div == 0U) {
753*9be88e75SGabriel Fernandez 		return prate;
754*9be88e75SGabriel Fernandez 	}
755*9be88e75SGabriel Fernandez 
756*9be88e75SGabriel Fernandez 	return div_round_up((uint64_t)prate, div);
757*9be88e75SGabriel Fernandez }
758*9be88e75SGabriel Fernandez 
759*9be88e75SGabriel Fernandez unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id,
760*9be88e75SGabriel Fernandez 				       unsigned long prate)
761*9be88e75SGabriel Fernandez {
762*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
763*9be88e75SGabriel Fernandez 	struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg;
764*9be88e75SGabriel Fernandez 
765*9be88e75SGabriel Fernandez 	return _clk_stm32_divider_recalc(priv, div_cfg->id, prate);
766*9be88e75SGabriel Fernandez }
767*9be88e75SGabriel Fernandez 
768*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_divider_ops = {
769*9be88e75SGabriel Fernandez 	.recalc_rate	= clk_stm32_divider_recalc,
770*9be88e75SGabriel Fernandez };
771*9be88e75SGabriel Fernandez 
772*9be88e75SGabriel Fernandez int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value)
773*9be88e75SGabriel Fernandez {
774*9be88e75SGabriel Fernandez 	const struct div_cfg *divider;
775*9be88e75SGabriel Fernandez 	uintptr_t address;
776*9be88e75SGabriel Fernandez 	uint64_t timeout;
777*9be88e75SGabriel Fernandez 	uint32_t mask;
778*9be88e75SGabriel Fernandez 
779*9be88e75SGabriel Fernandez 	if (div_id >= priv->nb_div) {
780*9be88e75SGabriel Fernandez 		panic();
781*9be88e75SGabriel Fernandez 	}
782*9be88e75SGabriel Fernandez 
783*9be88e75SGabriel Fernandez 	divider = &priv->div[div_id];
784*9be88e75SGabriel Fernandez 	address = priv->base + divider->offset;
785*9be88e75SGabriel Fernandez 
786*9be88e75SGabriel Fernandez 	mask = MASK_WIDTH_SHIFT(divider->width, divider->shift);
787*9be88e75SGabriel Fernandez 	mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask);
788*9be88e75SGabriel Fernandez 
789*9be88e75SGabriel Fernandez 	if (divider->bitrdy == DIV_NO_BIT_RDY) {
790*9be88e75SGabriel Fernandez 		return 0;
791*9be88e75SGabriel Fernandez 	}
792*9be88e75SGabriel Fernandez 
793*9be88e75SGabriel Fernandez 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
794*9be88e75SGabriel Fernandez 	mask = BIT(divider->bitrdy);
795*9be88e75SGabriel Fernandez 
796*9be88e75SGabriel Fernandez 	while ((mmio_read_32(address) & mask) == 0U) {
797*9be88e75SGabriel Fernandez 		if (timeout_elapsed(timeout)) {
798*9be88e75SGabriel Fernandez 			return -ETIMEDOUT;
799*9be88e75SGabriel Fernandez 		}
800*9be88e75SGabriel Fernandez 	}
801*9be88e75SGabriel Fernandez 
802*9be88e75SGabriel Fernandez 	return 0;
803*9be88e75SGabriel Fernandez }
804*9be88e75SGabriel Fernandez 
805*9be88e75SGabriel Fernandez int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id,
806*9be88e75SGabriel Fernandez 			       bool ready_on)
807*9be88e75SGabriel Fernandez {
808*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate = &priv->gates[gate_id];
809*9be88e75SGabriel Fernandez 	uintptr_t address = priv->base + gate->offset;
810*9be88e75SGabriel Fernandez 	uint32_t mask_rdy = BIT(gate->bit_idx);
811*9be88e75SGabriel Fernandez 	uint64_t timeout;
812*9be88e75SGabriel Fernandez 	uint32_t mask_test;
813*9be88e75SGabriel Fernandez 
814*9be88e75SGabriel Fernandez 	if (ready_on) {
815*9be88e75SGabriel Fernandez 		mask_test = BIT(gate->bit_idx);
816*9be88e75SGabriel Fernandez 	} else {
817*9be88e75SGabriel Fernandez 		mask_test = 0U;
818*9be88e75SGabriel Fernandez 	}
819*9be88e75SGabriel Fernandez 
820*9be88e75SGabriel Fernandez 	timeout = timeout_init_us(OSCRDY_TIMEOUT);
821*9be88e75SGabriel Fernandez 
822*9be88e75SGabriel Fernandez 	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
823*9be88e75SGabriel Fernandez 		if (timeout_elapsed(timeout)) {
824*9be88e75SGabriel Fernandez 			break;
825*9be88e75SGabriel Fernandez 		}
826*9be88e75SGabriel Fernandez 	}
827*9be88e75SGabriel Fernandez 
828*9be88e75SGabriel Fernandez 	if ((mmio_read_32(address) & mask_rdy) != mask_test)
829*9be88e75SGabriel Fernandez 		return -ETIMEDOUT;
830*9be88e75SGabriel Fernandez 
831*9be88e75SGabriel Fernandez 	return 0;
832*9be88e75SGabriel Fernandez }
833*9be88e75SGabriel Fernandez 
834*9be88e75SGabriel Fernandez int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id)
835*9be88e75SGabriel Fernandez {
836*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
837*9be88e75SGabriel Fernandez 	struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
838*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate = &priv->gates[cfg->id];
839*9be88e75SGabriel Fernandez 	uintptr_t addr = priv->base + gate->offset;
840*9be88e75SGabriel Fernandez 
841*9be88e75SGabriel Fernandez 	if (gate->set_clr != 0U) {
842*9be88e75SGabriel Fernandez 		mmio_write_32(addr, BIT(gate->bit_idx));
843*9be88e75SGabriel Fernandez 
844*9be88e75SGabriel Fernandez 	} else {
845*9be88e75SGabriel Fernandez 		mmio_setbits_32(addr, BIT(gate->bit_idx));
846*9be88e75SGabriel Fernandez 	}
847*9be88e75SGabriel Fernandez 
848*9be88e75SGabriel Fernandez 	return 0;
849*9be88e75SGabriel Fernandez }
850*9be88e75SGabriel Fernandez 
851*9be88e75SGabriel Fernandez void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id)
852*9be88e75SGabriel Fernandez {
853*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
854*9be88e75SGabriel Fernandez 	struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
855*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate = &priv->gates[cfg->id];
856*9be88e75SGabriel Fernandez 	uintptr_t addr = priv->base + gate->offset;
857*9be88e75SGabriel Fernandez 
858*9be88e75SGabriel Fernandez 	if (gate->set_clr != 0U) {
859*9be88e75SGabriel Fernandez 		mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx));
860*9be88e75SGabriel Fernandez 	} else {
861*9be88e75SGabriel Fernandez 		mmio_clrbits_32(addr, BIT(gate->bit_idx));
862*9be88e75SGabriel Fernandez 	}
863*9be88e75SGabriel Fernandez }
864*9be88e75SGabriel Fernandez 
865*9be88e75SGabriel Fernandez bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id)
866*9be88e75SGabriel Fernandez {
867*9be88e75SGabriel Fernandez 	const struct gate_cfg *gate;
868*9be88e75SGabriel Fernandez 	uint32_t addr;
869*9be88e75SGabriel Fernandez 
870*9be88e75SGabriel Fernandez 	gate = &priv->gates[gate_id];
871*9be88e75SGabriel Fernandez 	addr = priv->base + gate->offset;
872*9be88e75SGabriel Fernandez 
873*9be88e75SGabriel Fernandez 	return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U);
874*9be88e75SGabriel Fernandez }
875*9be88e75SGabriel Fernandez 
876*9be88e75SGabriel Fernandez bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id)
877*9be88e75SGabriel Fernandez {
878*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
879*9be88e75SGabriel Fernandez 	struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
880*9be88e75SGabriel Fernandez 
881*9be88e75SGabriel Fernandez 	return _clk_stm32_gate_is_enabled(priv, cfg->id);
882*9be88e75SGabriel Fernandez }
883*9be88e75SGabriel Fernandez 
884*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_gate_ops = {
885*9be88e75SGabriel Fernandez 	.enable		= clk_stm32_gate_enable,
886*9be88e75SGabriel Fernandez 	.disable	= clk_stm32_gate_disable,
887*9be88e75SGabriel Fernandez 	.is_enabled	= clk_stm32_gate_is_enabled,
888*9be88e75SGabriel Fernandez };
889*9be88e75SGabriel Fernandez 
890*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_fixed_factor_ops = {
891*9be88e75SGabriel Fernandez 	.recalc_rate	= fixed_factor_recalc_rate,
892*9be88e75SGabriel Fernandez };
893*9be88e75SGabriel Fernandez 
894*9be88e75SGabriel Fernandez unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv,
895*9be88e75SGabriel Fernandez 				       int id, unsigned long prate)
896*9be88e75SGabriel Fernandez {
897*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
898*9be88e75SGabriel Fernandez 	const struct fixed_factor_cfg *cfg = clk->clock_cfg;
899*9be88e75SGabriel Fernandez 	unsigned long long rate;
900*9be88e75SGabriel Fernandez 
901*9be88e75SGabriel Fernandez 	rate = (unsigned long long)prate * cfg->mult;
902*9be88e75SGabriel Fernandez 
903*9be88e75SGabriel Fernandez 	if (cfg->div == 0U) {
904*9be88e75SGabriel Fernandez 		ERROR("division by zero\n");
905*9be88e75SGabriel Fernandez 		panic();
906*9be88e75SGabriel Fernandez 	}
907*9be88e75SGabriel Fernandez 
908*9be88e75SGabriel Fernandez 	return (unsigned long)(rate / cfg->div);
909*9be88e75SGabriel Fernandez };
910*9be88e75SGabriel Fernandez 
911*9be88e75SGabriel Fernandez #define APB_DIV_MASK	GENMASK(2, 0)
912*9be88e75SGabriel Fernandez #define TIM_PRE_MASK	BIT(0)
913*9be88e75SGabriel Fernandez 
914*9be88e75SGabriel Fernandez static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv,
915*9be88e75SGabriel Fernandez 				       int id, unsigned long prate)
916*9be88e75SGabriel Fernandez {
917*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
918*9be88e75SGabriel Fernandez 	const struct clk_timer_cfg *cfg = clk->clock_cfg;
919*9be88e75SGabriel Fernandez 	uint32_t prescaler, timpre;
920*9be88e75SGabriel Fernandez 	uintptr_t rcc_base = priv->base;
921*9be88e75SGabriel Fernandez 
922*9be88e75SGabriel Fernandez 	prescaler = mmio_read_32(rcc_base + cfg->apbdiv) &
923*9be88e75SGabriel Fernandez 		APB_DIV_MASK;
924*9be88e75SGabriel Fernandez 
925*9be88e75SGabriel Fernandez 	timpre = mmio_read_32(rcc_base + cfg->timpre) &
926*9be88e75SGabriel Fernandez 		TIM_PRE_MASK;
927*9be88e75SGabriel Fernandez 
928*9be88e75SGabriel Fernandez 	if (prescaler == 0U) {
929*9be88e75SGabriel Fernandez 		return prate;
930*9be88e75SGabriel Fernandez 	}
931*9be88e75SGabriel Fernandez 
932*9be88e75SGabriel Fernandez 	return prate * (timpre + 1U) * 2U;
933*9be88e75SGabriel Fernandez };
934*9be88e75SGabriel Fernandez 
935*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_timer_ops = {
936*9be88e75SGabriel Fernandez 	.recalc_rate	= timer_recalc_rate,
937*9be88e75SGabriel Fernandez };
938*9be88e75SGabriel Fernandez 
939*9be88e75SGabriel Fernandez static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id,
940*9be88e75SGabriel Fernandez 					   unsigned long prate)
941*9be88e75SGabriel Fernandez {
942*9be88e75SGabriel Fernandez 	const struct clk_stm32 *clk = _clk_get(priv, id);
943*9be88e75SGabriel Fernandez 	struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg;
944*9be88e75SGabriel Fernandez 
945*9be88e75SGabriel Fernandez 	return cfg->rate;
946*9be88e75SGabriel Fernandez }
947*9be88e75SGabriel Fernandez 
948*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_fixed_rate_ops = {
949*9be88e75SGabriel Fernandez 	.recalc_rate	= clk_fixed_rate_recalc,
950*9be88e75SGabriel Fernandez };
951*9be88e75SGabriel Fernandez 
952*9be88e75SGabriel Fernandez static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv,
953*9be88e75SGabriel Fernandez 					       int id, unsigned long prate)
954*9be88e75SGabriel Fernandez {
955*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
956*9be88e75SGabriel Fernandez 
957*9be88e75SGabriel Fernandez 	return osc_data->frequency;
958*9be88e75SGabriel Fernandez };
959*9be88e75SGabriel Fernandez 
960*9be88e75SGabriel Fernandez bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id)
961*9be88e75SGabriel Fernandez {
962*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
963*9be88e75SGabriel Fernandez 
964*9be88e75SGabriel Fernandez 	return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id);
965*9be88e75SGabriel Fernandez 
966*9be88e75SGabriel Fernandez }
967*9be88e75SGabriel Fernandez 
968*9be88e75SGabriel Fernandez int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id)
969*9be88e75SGabriel Fernandez {
970*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
971*9be88e75SGabriel Fernandez 
972*9be88e75SGabriel Fernandez 	_clk_stm32_gate_enable(priv, osc_data->gate_id);
973*9be88e75SGabriel Fernandez 
974*9be88e75SGabriel Fernandez 	if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) {
975*9be88e75SGabriel Fernandez 		ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__);
976*9be88e75SGabriel Fernandez 		panic();
977*9be88e75SGabriel Fernandez 	}
978*9be88e75SGabriel Fernandez 
979*9be88e75SGabriel Fernandez 	return 0;
980*9be88e75SGabriel Fernandez }
981*9be88e75SGabriel Fernandez 
982*9be88e75SGabriel Fernandez void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id)
983*9be88e75SGabriel Fernandez {
984*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
985*9be88e75SGabriel Fernandez 
986*9be88e75SGabriel Fernandez 	_clk_stm32_gate_disable(priv, osc_data->gate_id);
987*9be88e75SGabriel Fernandez 
988*9be88e75SGabriel Fernandez 	if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) {
989*9be88e75SGabriel Fernandez 		ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__);
990*9be88e75SGabriel Fernandez 		panic();
991*9be88e75SGabriel Fernandez 	}
992*9be88e75SGabriel Fernandez }
993*9be88e75SGabriel Fernandez 
994*9be88e75SGabriel Fernandez static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name)
995*9be88e75SGabriel Fernandez {
996*9be88e75SGabriel Fernandez 	void *fdt = NULL;
997*9be88e75SGabriel Fernandez 	int node = 0;
998*9be88e75SGabriel Fernandez 	int subnode = 0;
999*9be88e75SGabriel Fernandez 
1000*9be88e75SGabriel Fernandez 	if (fdt_get_address(&fdt) == 0) {
1001*9be88e75SGabriel Fernandez 		panic();
1002*9be88e75SGabriel Fernandez 	}
1003*9be88e75SGabriel Fernandez 
1004*9be88e75SGabriel Fernandez 	node = fdt_path_offset(fdt, "/clocks");
1005*9be88e75SGabriel Fernandez 	if (node < 0) {
1006*9be88e75SGabriel Fernandez 		return 0UL;
1007*9be88e75SGabriel Fernandez 	}
1008*9be88e75SGabriel Fernandez 
1009*9be88e75SGabriel Fernandez 	fdt_for_each_subnode(subnode, fdt, node) {
1010*9be88e75SGabriel Fernandez 		const char *cchar = NULL;
1011*9be88e75SGabriel Fernandez 		const fdt32_t *cuint = NULL;
1012*9be88e75SGabriel Fernandez 		int ret = 0;
1013*9be88e75SGabriel Fernandez 
1014*9be88e75SGabriel Fernandez 		cchar = fdt_get_name(fdt, subnode, &ret);
1015*9be88e75SGabriel Fernandez 		if (cchar == NULL) {
1016*9be88e75SGabriel Fernandez 			continue;
1017*9be88e75SGabriel Fernandez 		}
1018*9be88e75SGabriel Fernandez 
1019*9be88e75SGabriel Fernandez 		if (strncmp(cchar, name, (size_t)ret) ||
1020*9be88e75SGabriel Fernandez 		    fdt_get_status(subnode) == DT_DISABLED) {
1021*9be88e75SGabriel Fernandez 			continue;
1022*9be88e75SGabriel Fernandez 		}
1023*9be88e75SGabriel Fernandez 
1024*9be88e75SGabriel Fernandez 		cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret);
1025*9be88e75SGabriel Fernandez 		if (cuint == NULL) {
1026*9be88e75SGabriel Fernandez 			return 0UL;
1027*9be88e75SGabriel Fernandez 		}
1028*9be88e75SGabriel Fernandez 
1029*9be88e75SGabriel Fernandez 		return fdt32_to_cpu(*cuint);
1030*9be88e75SGabriel Fernandez 	}
1031*9be88e75SGabriel Fernandez 
1032*9be88e75SGabriel Fernandez 	return 0UL;
1033*9be88e75SGabriel Fernandez }
1034*9be88e75SGabriel Fernandez 
1035*9be88e75SGabriel Fernandez void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id)
1036*9be88e75SGabriel Fernandez {
1037*9be88e75SGabriel Fernandez 	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
1038*9be88e75SGabriel Fernandez 	const char *name = osc_data->name;
1039*9be88e75SGabriel Fernandez 
1040*9be88e75SGabriel Fernandez 	osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name);
1041*9be88e75SGabriel Fernandez }
1042*9be88e75SGabriel Fernandez 
1043*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_osc_ops = {
1044*9be88e75SGabriel Fernandez 	.recalc_rate	= clk_stm32_osc_recalc_rate,
1045*9be88e75SGabriel Fernandez 	.is_enabled	= clk_stm32_osc_gate_is_enabled,
1046*9be88e75SGabriel Fernandez 	.enable		= clk_stm32_osc_gate_enable,
1047*9be88e75SGabriel Fernandez 	.disable	= clk_stm32_osc_gate_disable,
1048*9be88e75SGabriel Fernandez 	.init		= clk_stm32_osc_init,
1049*9be88e75SGabriel Fernandez };
1050*9be88e75SGabriel Fernandez 
1051*9be88e75SGabriel Fernandez const struct stm32_clk_ops clk_stm32_osc_nogate_ops = {
1052*9be88e75SGabriel Fernandez 	.recalc_rate	= clk_stm32_osc_recalc_rate,
1053*9be88e75SGabriel Fernandez 	.init		= clk_stm32_osc_init,
1054*9be88e75SGabriel Fernandez };
1055*9be88e75SGabriel Fernandez 
1056*9be88e75SGabriel Fernandez int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb)
1057*9be88e75SGabriel Fernandez {
1058*9be88e75SGabriel Fernandez 	const fdt32_t *cell;
1059*9be88e75SGabriel Fernandez 	int len = 0;
1060*9be88e75SGabriel Fernandez 	uint32_t i;
1061*9be88e75SGabriel Fernandez 
1062*9be88e75SGabriel Fernandez 	cell = fdt_getprop(fdt, node, name, &len);
1063*9be88e75SGabriel Fernandez 	if (cell != NULL) {
1064*9be88e75SGabriel Fernandez 		for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
1065*9be88e75SGabriel Fernandez 			uint32_t val = fdt32_to_cpu(cell[i]);
1066*9be88e75SGabriel Fernandez 
1067*9be88e75SGabriel Fernandez 			tab[i] = val;
1068*9be88e75SGabriel Fernandez 		}
1069*9be88e75SGabriel Fernandez 	}
1070*9be88e75SGabriel Fernandez 
1071*9be88e75SGabriel Fernandez 	*nb = (uint32_t)len / sizeof(uint32_t);
1072*9be88e75SGabriel Fernandez 
1073*9be88e75SGabriel Fernandez 	return 0;
1074*9be88e75SGabriel Fernandez }
1075*9be88e75SGabriel Fernandez 
1076*9be88e75SGabriel Fernandez int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base)
1077*9be88e75SGabriel Fernandez {
1078*9be88e75SGabriel Fernandez 	unsigned int i;
1079*9be88e75SGabriel Fernandez 
1080*9be88e75SGabriel Fernandez 	stm32_clock_data = priv;
1081*9be88e75SGabriel Fernandez 
1082*9be88e75SGabriel Fernandez 	priv->base = base;
1083*9be88e75SGabriel Fernandez 
1084*9be88e75SGabriel Fernandez 	for (i = 0U; i < priv->num; i++) {
1085*9be88e75SGabriel Fernandez 		const struct clk_stm32 *clk = _clk_get(priv, i);
1086*9be88e75SGabriel Fernandez 
1087*9be88e75SGabriel Fernandez 		assert(clk->ops != NULL);
1088*9be88e75SGabriel Fernandez 
1089*9be88e75SGabriel Fernandez 		if (clk->ops->init != NULL) {
1090*9be88e75SGabriel Fernandez 			clk->ops->init(priv, i);
1091*9be88e75SGabriel Fernandez 		}
1092*9be88e75SGabriel Fernandez 	}
1093*9be88e75SGabriel Fernandez 
1094*9be88e75SGabriel Fernandez 	stm32_clk_register();
1095*9be88e75SGabriel Fernandez 
1096*9be88e75SGabriel Fernandez 	return 0;
1097*9be88e75SGabriel Fernandez }
1098