xref: /rk3399_ARM-atf/drivers/nxp/clk/s32cc/s32cc_clk_drv.c (revision 3eb5640a7d9277eee80b5b31bb30230a374e0fb0)
1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <errno.h>
7 
8 #include <s32cc-clk-regs.h>
9 
10 #include <common/debug.h>
11 #include <drivers/clk.h>
12 #include <lib/mmio.h>
13 #include <s32cc-clk-modules.h>
14 #include <s32cc-clk-utils.h>
15 
16 #define MAX_STACK_DEPTH		(15U)
17 
18 struct s32cc_clk_drv {
19 	uintptr_t fxosc_base;
20 };
21 
22 static int update_stack_depth(unsigned int *depth)
23 {
24 	if (*depth == 0U) {
25 		return -ENOMEM;
26 	}
27 
28 	(*depth)--;
29 	return 0;
30 }
31 
32 static struct s32cc_clk_drv *get_drv(void)
33 {
34 	static struct s32cc_clk_drv driver = {
35 		.fxosc_base = FXOSC_BASE_ADDR,
36 	};
37 
38 	return &driver;
39 }
40 
41 static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth);
42 
43 static int enable_clk_module(const struct s32cc_clk_obj *module,
44 			     const struct s32cc_clk_drv *drv,
45 			     unsigned int *depth)
46 {
47 	const struct s32cc_clk *clk = s32cc_obj2clk(module);
48 	int ret;
49 
50 	ret = update_stack_depth(depth);
51 	if (ret != 0) {
52 		return ret;
53 	}
54 
55 	if (clk == NULL) {
56 		return -EINVAL;
57 	}
58 
59 	if (clk->module != NULL) {
60 		return enable_module(clk->module, depth);
61 	}
62 
63 	if (clk->pclock != NULL) {
64 		return enable_clk_module(&clk->pclock->desc, drv, depth);
65 	}
66 
67 	return -EINVAL;
68 }
69 
70 static void enable_fxosc(const struct s32cc_clk_drv *drv)
71 {
72 	uintptr_t fxosc_base = drv->fxosc_base;
73 	uint32_t ctrl;
74 
75 	ctrl = mmio_read_32(FXOSC_CTRL(fxosc_base));
76 	if ((ctrl & FXOSC_CTRL_OSCON) != U(0)) {
77 		return;
78 	}
79 
80 	ctrl = FXOSC_CTRL_COMP_EN;
81 	ctrl &= ~FXOSC_CTRL_OSC_BYP;
82 	ctrl |= FXOSC_CTRL_EOCV(0x1);
83 	ctrl |= FXOSC_CTRL_GM_SEL(0x7);
84 	mmio_write_32(FXOSC_CTRL(fxosc_base), ctrl);
85 
86 	/* Switch ON the crystal oscillator. */
87 	mmio_setbits_32(FXOSC_CTRL(fxosc_base), FXOSC_CTRL_OSCON);
88 
89 	/* Wait until the clock is stable. */
90 	while ((mmio_read_32(FXOSC_STAT(fxosc_base)) & FXOSC_STAT_OSC_STAT) == U(0)) {
91 	}
92 }
93 
94 static int enable_osc(const struct s32cc_clk_obj *module,
95 		      const struct s32cc_clk_drv *drv,
96 		      unsigned int *depth)
97 {
98 	const struct s32cc_osc *osc = s32cc_obj2osc(module);
99 	int ret = 0;
100 
101 	ret = update_stack_depth(depth);
102 	if (ret != 0) {
103 		return ret;
104 	}
105 
106 	switch (osc->source) {
107 	case S32CC_FXOSC:
108 		enable_fxosc(drv);
109 		break;
110 	/* FIRC and SIRC oscillators are enabled by default */
111 	case S32CC_FIRC:
112 		break;
113 	case S32CC_SIRC:
114 		break;
115 	default:
116 		ERROR("Invalid oscillator %d\n", osc->source);
117 		ret = -EINVAL;
118 		break;
119 	};
120 
121 	return ret;
122 }
123 
124 static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth)
125 {
126 	const struct s32cc_clk_drv *drv = get_drv();
127 	int ret = 0;
128 
129 	ret = update_stack_depth(depth);
130 	if (ret != 0) {
131 		return ret;
132 	}
133 
134 	if (drv == NULL) {
135 		return -EINVAL;
136 	}
137 
138 	switch (module->type) {
139 	case s32cc_osc_t:
140 		ret = enable_osc(module, drv, depth);
141 		break;
142 	case s32cc_clk_t:
143 		ret = enable_clk_module(module, drv, depth);
144 		break;
145 	case s32cc_clkmux_t:
146 		ret = -ENOTSUP;
147 		break;
148 	case s32cc_shared_clkmux_t:
149 		ret = -ENOTSUP;
150 		break;
151 	case s32cc_pll_t:
152 		ret = -ENOTSUP;
153 		break;
154 	case s32cc_pll_out_div_t:
155 	case s32cc_fixed_div_t:
156 		ret = -ENOTSUP;
157 		break;
158 	default:
159 		ret = -EINVAL;
160 		break;
161 	}
162 
163 	return ret;
164 }
165 
166 static int s32cc_clk_enable(unsigned long id)
167 {
168 	unsigned int depth = MAX_STACK_DEPTH;
169 	const struct s32cc_clk *clk;
170 
171 	clk = s32cc_get_arch_clk(id);
172 	if (clk == NULL) {
173 		return -EINVAL;
174 	}
175 
176 	return enable_module(&clk->desc, &depth);
177 }
178 
179 static void s32cc_clk_disable(unsigned long id)
180 {
181 }
182 
183 static bool s32cc_clk_is_enabled(unsigned long id)
184 {
185 	return false;
186 }
187 
188 static unsigned long s32cc_clk_get_rate(unsigned long id)
189 {
190 	return 0;
191 }
192 
193 static int set_module_rate(const struct s32cc_clk_obj *module,
194 			   unsigned long rate, unsigned long *orate,
195 			   unsigned int *depth);
196 
197 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate,
198 			unsigned long *orate, unsigned int *depth)
199 {
200 	struct s32cc_osc *osc = s32cc_obj2osc(module);
201 	int ret;
202 
203 	ret = update_stack_depth(depth);
204 	if (ret != 0) {
205 		return ret;
206 	}
207 
208 	if ((osc->freq != 0UL) && (rate != osc->freq)) {
209 		ERROR("Already initialized oscillator. freq = %lu\n",
210 		      osc->freq);
211 		return -EINVAL;
212 	}
213 
214 	osc->freq = rate;
215 	*orate = osc->freq;
216 
217 	return 0;
218 }
219 
220 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate,
221 			unsigned long *orate, unsigned int *depth)
222 {
223 	const struct s32cc_clk *clk = s32cc_obj2clk(module);
224 	int ret;
225 
226 	ret = update_stack_depth(depth);
227 	if (ret != 0) {
228 		return ret;
229 	}
230 
231 	if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) &&
232 	    ((rate < clk->min_freq) || (rate > clk->max_freq))) {
233 		ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n",
234 		      rate, clk->min_freq, clk->max_freq);
235 		return -EINVAL;
236 	}
237 
238 	if (clk->module != NULL) {
239 		return set_module_rate(clk->module, rate, orate, depth);
240 	}
241 
242 	if (clk->pclock != NULL) {
243 		return set_clk_freq(&clk->pclock->desc, rate, orate, depth);
244 	}
245 
246 	return -EINVAL;
247 }
248 
249 static int set_pll_freq(const struct s32cc_clk_obj *module, unsigned long rate,
250 			unsigned long *orate, unsigned int *depth)
251 {
252 	struct s32cc_pll *pll = s32cc_obj2pll(module);
253 	int ret;
254 
255 	ret = update_stack_depth(depth);
256 	if (ret != 0) {
257 		return ret;
258 	}
259 
260 	if ((pll->vco_freq != 0UL) && (pll->vco_freq != rate)) {
261 		ERROR("PLL frequency was already set\n");
262 		return -EINVAL;
263 	}
264 
265 	pll->vco_freq = rate;
266 	*orate = pll->vco_freq;
267 
268 	return 0;
269 }
270 
271 static int set_pll_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
272 			    unsigned long *orate, unsigned int *depth)
273 {
274 	struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
275 	const struct s32cc_pll *pll;
276 	unsigned long prate, dc;
277 	int ret;
278 
279 	ret = update_stack_depth(depth);
280 	if (ret != 0) {
281 		return ret;
282 	}
283 
284 	if (pdiv->parent == NULL) {
285 		ERROR("Failed to identify PLL divider's parent\n");
286 		return -EINVAL;
287 	}
288 
289 	pll = s32cc_obj2pll(pdiv->parent);
290 	if (pll == NULL) {
291 		ERROR("The parent of the PLL DIV is invalid\n");
292 		return -EINVAL;
293 	}
294 
295 	prate = pll->vco_freq;
296 
297 	/**
298 	 * The PLL is not initialized yet, so let's take a risk
299 	 * and accept the proposed rate.
300 	 */
301 	if (prate == 0UL) {
302 		pdiv->freq = rate;
303 		*orate = rate;
304 		return 0;
305 	}
306 
307 	/* Decline in case the rate cannot fit PLL's requirements. */
308 	dc = prate / rate;
309 	if ((prate / dc) != rate) {
310 		return -EINVAL;
311 	}
312 
313 	pdiv->freq = rate;
314 	*orate = pdiv->freq;
315 
316 	return 0;
317 }
318 
319 static int set_fixed_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
320 			      unsigned long *orate, unsigned int *depth)
321 {
322 	const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module);
323 	int ret;
324 
325 	ret = update_stack_depth(depth);
326 	if (ret != 0) {
327 		return ret;
328 	}
329 
330 	if (fdiv->parent == NULL) {
331 		ERROR("The divider doesn't have a valid parent\b");
332 		return -EINVAL;
333 	}
334 
335 	ret = set_module_rate(fdiv->parent, rate * fdiv->rate_div, orate, depth);
336 
337 	/* Update the output rate based on the parent's rate */
338 	*orate /= fdiv->rate_div;
339 
340 	return ret;
341 }
342 
343 static int set_module_rate(const struct s32cc_clk_obj *module,
344 			   unsigned long rate, unsigned long *orate,
345 			   unsigned int *depth)
346 {
347 	int ret = 0;
348 
349 	ret = update_stack_depth(depth);
350 	if (ret != 0) {
351 		return ret;
352 	}
353 
354 	switch (module->type) {
355 	case s32cc_clk_t:
356 		ret = set_clk_freq(module, rate, orate, depth);
357 		break;
358 	case s32cc_osc_t:
359 		ret = set_osc_freq(module, rate, orate, depth);
360 		break;
361 	case s32cc_pll_t:
362 		ret = set_pll_freq(module, rate, orate, depth);
363 		break;
364 	case s32cc_pll_out_div_t:
365 		ret = set_pll_div_freq(module, rate, orate, depth);
366 		break;
367 	case s32cc_fixed_div_t:
368 		ret = set_fixed_div_freq(module, rate, orate, depth);
369 		break;
370 	case s32cc_clkmux_t:
371 	case s32cc_shared_clkmux_t:
372 		ret = -ENOTSUP;
373 		break;
374 	default:
375 		ret = -EINVAL;
376 		break;
377 	}
378 
379 	return ret;
380 }
381 
382 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate,
383 			      unsigned long *orate)
384 {
385 	unsigned int depth = MAX_STACK_DEPTH;
386 	const struct s32cc_clk *clk;
387 	int ret;
388 
389 	clk = s32cc_get_arch_clk(id);
390 	if (clk == NULL) {
391 		return -EINVAL;
392 	}
393 
394 	ret = set_module_rate(&clk->desc, rate, orate, &depth);
395 	if (ret != 0) {
396 		ERROR("Failed to set frequency (%lu MHz) for clock %lu\n",
397 		      rate, id);
398 	}
399 
400 	return ret;
401 }
402 
403 static int s32cc_clk_get_parent(unsigned long id)
404 {
405 	return -ENOTSUP;
406 }
407 
408 static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id)
409 {
410 	const struct s32cc_clk *parent;
411 	const struct s32cc_clk *clk;
412 	bool valid_source = false;
413 	struct s32cc_clkmux *mux;
414 	uint8_t i;
415 
416 	clk = s32cc_get_arch_clk(id);
417 	if (clk == NULL) {
418 		return -EINVAL;
419 	}
420 
421 	parent = s32cc_get_arch_clk(parent_id);
422 	if (parent == NULL) {
423 		return -EINVAL;
424 	}
425 
426 	if (!is_s32cc_clk_mux(clk)) {
427 		ERROR("Clock %lu is not a mux\n", id);
428 		return -EINVAL;
429 	}
430 
431 	mux = s32cc_clk2mux(clk);
432 	if (mux == NULL) {
433 		ERROR("Failed to cast clock %lu to clock mux\n", id);
434 		return -EINVAL;
435 	}
436 
437 	for (i = 0; i < mux->nclks; i++) {
438 		if (mux->clkids[i] == parent_id) {
439 			valid_source = true;
440 			break;
441 		}
442 	}
443 
444 	if (!valid_source) {
445 		ERROR("Clock %lu is not a valid clock for mux %lu\n",
446 		      parent_id, id);
447 		return -EINVAL;
448 	}
449 
450 	mux->source_id = parent_id;
451 
452 	return 0;
453 }
454 
455 void s32cc_clk_register_drv(void)
456 {
457 	static const struct clk_ops s32cc_clk_ops = {
458 		.enable		= s32cc_clk_enable,
459 		.disable	= s32cc_clk_disable,
460 		.is_enabled	= s32cc_clk_is_enabled,
461 		.get_rate	= s32cc_clk_get_rate,
462 		.set_rate	= s32cc_clk_set_rate,
463 		.get_parent	= s32cc_clk_get_parent,
464 		.set_parent	= s32cc_clk_set_parent,
465 	};
466 
467 	clk_register(&s32cc_clk_ops);
468 }
469 
470