xref: /openbmc/linux/drivers/clk/at91/clk-main.c (revision fbb6b31a)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/clkdev.h>
8 #include <linux/clk/at91_pmc.h>
9 #include <linux/delay.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
12 
13 #include "pmc.h"
14 
15 #define SLOW_CLOCK_FREQ		32768
16 #define MAINF_DIV		16
17 #define MAINFRDY_TIMEOUT	(((MAINF_DIV + 1) * USEC_PER_SEC) / \
18 				 SLOW_CLOCK_FREQ)
19 #define MAINF_LOOP_MIN_WAIT	(USEC_PER_SEC / SLOW_CLOCK_FREQ)
20 #define MAINF_LOOP_MAX_WAIT	MAINFRDY_TIMEOUT
21 
22 #define MOR_KEY_MASK		(0xff << 16)
23 
24 #define clk_main_parent_select(s)	(((s) & \
25 					(AT91_PMC_MOSCEN | \
26 					AT91_PMC_OSCBYPASS)) ? 1 : 0)
27 
28 struct clk_main_osc {
29 	struct clk_hw hw;
30 	struct regmap *regmap;
31 	struct at91_clk_pms pms;
32 };
33 
34 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
35 
36 struct clk_main_rc_osc {
37 	struct clk_hw hw;
38 	struct regmap *regmap;
39 	unsigned long frequency;
40 	unsigned long accuracy;
41 	struct at91_clk_pms pms;
42 };
43 
44 #define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
45 
46 struct clk_rm9200_main {
47 	struct clk_hw hw;
48 	struct regmap *regmap;
49 };
50 
51 #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
52 
53 struct clk_sam9x5_main {
54 	struct clk_hw hw;
55 	struct regmap *regmap;
56 	struct at91_clk_pms pms;
57 	u8 parent;
58 };
59 
60 #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
61 
62 static inline bool clk_main_osc_ready(struct regmap *regmap)
63 {
64 	unsigned int status;
65 
66 	regmap_read(regmap, AT91_PMC_SR, &status);
67 
68 	return status & AT91_PMC_MOSCS;
69 }
70 
71 static int clk_main_osc_prepare(struct clk_hw *hw)
72 {
73 	struct clk_main_osc *osc = to_clk_main_osc(hw);
74 	struct regmap *regmap = osc->regmap;
75 	u32 tmp;
76 
77 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
78 	tmp &= ~MOR_KEY_MASK;
79 
80 	if (tmp & AT91_PMC_OSCBYPASS)
81 		return 0;
82 
83 	if (!(tmp & AT91_PMC_MOSCEN)) {
84 		tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
85 		regmap_write(regmap, AT91_CKGR_MOR, tmp);
86 	}
87 
88 	while (!clk_main_osc_ready(regmap))
89 		cpu_relax();
90 
91 	return 0;
92 }
93 
94 static void clk_main_osc_unprepare(struct clk_hw *hw)
95 {
96 	struct clk_main_osc *osc = to_clk_main_osc(hw);
97 	struct regmap *regmap = osc->regmap;
98 	u32 tmp;
99 
100 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
101 	if (tmp & AT91_PMC_OSCBYPASS)
102 		return;
103 
104 	if (!(tmp & AT91_PMC_MOSCEN))
105 		return;
106 
107 	tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
108 	regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
109 }
110 
111 static int clk_main_osc_is_prepared(struct clk_hw *hw)
112 {
113 	struct clk_main_osc *osc = to_clk_main_osc(hw);
114 	struct regmap *regmap = osc->regmap;
115 	u32 tmp, status;
116 
117 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
118 	if (tmp & AT91_PMC_OSCBYPASS)
119 		return 1;
120 
121 	regmap_read(regmap, AT91_PMC_SR, &status);
122 
123 	return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
124 }
125 
126 static int clk_main_osc_save_context(struct clk_hw *hw)
127 {
128 	struct clk_main_osc *osc = to_clk_main_osc(hw);
129 
130 	osc->pms.status = clk_main_osc_is_prepared(hw);
131 
132 	return 0;
133 }
134 
135 static void clk_main_osc_restore_context(struct clk_hw *hw)
136 {
137 	struct clk_main_osc *osc = to_clk_main_osc(hw);
138 
139 	if (osc->pms.status)
140 		clk_main_osc_prepare(hw);
141 }
142 
143 static const struct clk_ops main_osc_ops = {
144 	.prepare = clk_main_osc_prepare,
145 	.unprepare = clk_main_osc_unprepare,
146 	.is_prepared = clk_main_osc_is_prepared,
147 	.save_context = clk_main_osc_save_context,
148 	.restore_context = clk_main_osc_restore_context,
149 };
150 
151 struct clk_hw * __init
152 at91_clk_register_main_osc(struct regmap *regmap,
153 			   const char *name,
154 			   const char *parent_name,
155 			   bool bypass)
156 {
157 	struct clk_main_osc *osc;
158 	struct clk_init_data init;
159 	struct clk_hw *hw;
160 	int ret;
161 
162 	if (!name || !parent_name)
163 		return ERR_PTR(-EINVAL);
164 
165 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
166 	if (!osc)
167 		return ERR_PTR(-ENOMEM);
168 
169 	init.name = name;
170 	init.ops = &main_osc_ops;
171 	init.parent_names = &parent_name;
172 	init.num_parents = 1;
173 	init.flags = CLK_IGNORE_UNUSED;
174 
175 	osc->hw.init = &init;
176 	osc->regmap = regmap;
177 
178 	if (bypass)
179 		regmap_update_bits(regmap,
180 				   AT91_CKGR_MOR, MOR_KEY_MASK |
181 				   AT91_PMC_OSCBYPASS,
182 				   AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
183 
184 	hw = &osc->hw;
185 	ret = clk_hw_register(NULL, &osc->hw);
186 	if (ret) {
187 		kfree(osc);
188 		hw = ERR_PTR(ret);
189 	}
190 
191 	return hw;
192 }
193 
194 static bool clk_main_rc_osc_ready(struct regmap *regmap)
195 {
196 	unsigned int status;
197 
198 	regmap_read(regmap, AT91_PMC_SR, &status);
199 
200 	return !!(status & AT91_PMC_MOSCRCS);
201 }
202 
203 static int clk_main_rc_osc_prepare(struct clk_hw *hw)
204 {
205 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
206 	struct regmap *regmap = osc->regmap;
207 	unsigned int mor;
208 
209 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
210 
211 	if (!(mor & AT91_PMC_MOSCRCEN))
212 		regmap_update_bits(regmap, AT91_CKGR_MOR,
213 				   MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
214 				   AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
215 
216 	while (!clk_main_rc_osc_ready(regmap))
217 		cpu_relax();
218 
219 	return 0;
220 }
221 
222 static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
223 {
224 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
225 	struct regmap *regmap = osc->regmap;
226 	unsigned int mor;
227 
228 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
229 
230 	if (!(mor & AT91_PMC_MOSCRCEN))
231 		return;
232 
233 	regmap_update_bits(regmap, AT91_CKGR_MOR,
234 			   MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
235 }
236 
237 static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
238 {
239 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
240 	struct regmap *regmap = osc->regmap;
241 	unsigned int mor, status;
242 
243 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
244 	regmap_read(regmap, AT91_PMC_SR, &status);
245 
246 	return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
247 }
248 
249 static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
250 						 unsigned long parent_rate)
251 {
252 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
253 
254 	return osc->frequency;
255 }
256 
257 static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
258 						     unsigned long parent_acc)
259 {
260 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
261 
262 	return osc->accuracy;
263 }
264 
265 static int clk_main_rc_osc_save_context(struct clk_hw *hw)
266 {
267 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
268 
269 	osc->pms.status = clk_main_rc_osc_is_prepared(hw);
270 
271 	return 0;
272 }
273 
274 static void clk_main_rc_osc_restore_context(struct clk_hw *hw)
275 {
276 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
277 
278 	if (osc->pms.status)
279 		clk_main_rc_osc_prepare(hw);
280 }
281 
282 static const struct clk_ops main_rc_osc_ops = {
283 	.prepare = clk_main_rc_osc_prepare,
284 	.unprepare = clk_main_rc_osc_unprepare,
285 	.is_prepared = clk_main_rc_osc_is_prepared,
286 	.recalc_rate = clk_main_rc_osc_recalc_rate,
287 	.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
288 	.save_context = clk_main_rc_osc_save_context,
289 	.restore_context = clk_main_rc_osc_restore_context,
290 };
291 
292 struct clk_hw * __init
293 at91_clk_register_main_rc_osc(struct regmap *regmap,
294 			      const char *name,
295 			      u32 frequency, u32 accuracy)
296 {
297 	struct clk_main_rc_osc *osc;
298 	struct clk_init_data init;
299 	struct clk_hw *hw;
300 	int ret;
301 
302 	if (!name || !frequency)
303 		return ERR_PTR(-EINVAL);
304 
305 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
306 	if (!osc)
307 		return ERR_PTR(-ENOMEM);
308 
309 	init.name = name;
310 	init.ops = &main_rc_osc_ops;
311 	init.parent_names = NULL;
312 	init.num_parents = 0;
313 	init.flags = CLK_IGNORE_UNUSED;
314 
315 	osc->hw.init = &init;
316 	osc->regmap = regmap;
317 	osc->frequency = frequency;
318 	osc->accuracy = accuracy;
319 
320 	hw = &osc->hw;
321 	ret = clk_hw_register(NULL, hw);
322 	if (ret) {
323 		kfree(osc);
324 		hw = ERR_PTR(ret);
325 	}
326 
327 	return hw;
328 }
329 
330 static int clk_main_probe_frequency(struct regmap *regmap)
331 {
332 	unsigned long prep_time, timeout;
333 	unsigned int mcfr;
334 
335 	timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
336 	do {
337 		prep_time = jiffies;
338 		regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
339 		if (mcfr & AT91_PMC_MAINRDY)
340 			return 0;
341 		if (system_state < SYSTEM_RUNNING)
342 			udelay(MAINF_LOOP_MIN_WAIT);
343 		else
344 			usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
345 	} while (time_before(prep_time, timeout));
346 
347 	return -ETIMEDOUT;
348 }
349 
350 static unsigned long clk_main_recalc_rate(struct regmap *regmap,
351 					  unsigned long parent_rate)
352 {
353 	unsigned int mcfr;
354 
355 	if (parent_rate)
356 		return parent_rate;
357 
358 	pr_warn("Main crystal frequency not set, using approximate value\n");
359 	regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
360 	if (!(mcfr & AT91_PMC_MAINRDY))
361 		return 0;
362 
363 	return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
364 }
365 
366 static int clk_rm9200_main_prepare(struct clk_hw *hw)
367 {
368 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
369 
370 	return clk_main_probe_frequency(clkmain->regmap);
371 }
372 
373 static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
374 {
375 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
376 	unsigned int status;
377 
378 	regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
379 
380 	return !!(status & AT91_PMC_MAINRDY);
381 }
382 
383 static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
384 						 unsigned long parent_rate)
385 {
386 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
387 
388 	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
389 }
390 
391 static const struct clk_ops rm9200_main_ops = {
392 	.prepare = clk_rm9200_main_prepare,
393 	.is_prepared = clk_rm9200_main_is_prepared,
394 	.recalc_rate = clk_rm9200_main_recalc_rate,
395 };
396 
397 struct clk_hw * __init
398 at91_clk_register_rm9200_main(struct regmap *regmap,
399 			      const char *name,
400 			      const char *parent_name)
401 {
402 	struct clk_rm9200_main *clkmain;
403 	struct clk_init_data init;
404 	struct clk_hw *hw;
405 	int ret;
406 
407 	if (!name)
408 		return ERR_PTR(-EINVAL);
409 
410 	if (!parent_name)
411 		return ERR_PTR(-EINVAL);
412 
413 	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
414 	if (!clkmain)
415 		return ERR_PTR(-ENOMEM);
416 
417 	init.name = name;
418 	init.ops = &rm9200_main_ops;
419 	init.parent_names = &parent_name;
420 	init.num_parents = 1;
421 	init.flags = 0;
422 
423 	clkmain->hw.init = &init;
424 	clkmain->regmap = regmap;
425 
426 	hw = &clkmain->hw;
427 	ret = clk_hw_register(NULL, &clkmain->hw);
428 	if (ret) {
429 		kfree(clkmain);
430 		hw = ERR_PTR(ret);
431 	}
432 
433 	return hw;
434 }
435 
436 static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
437 {
438 	unsigned int status;
439 
440 	regmap_read(regmap, AT91_PMC_SR, &status);
441 
442 	return !!(status & AT91_PMC_MOSCSELS);
443 }
444 
445 static int clk_sam9x5_main_prepare(struct clk_hw *hw)
446 {
447 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
448 	struct regmap *regmap = clkmain->regmap;
449 
450 	while (!clk_sam9x5_main_ready(regmap))
451 		cpu_relax();
452 
453 	return clk_main_probe_frequency(regmap);
454 }
455 
456 static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
457 {
458 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
459 
460 	return clk_sam9x5_main_ready(clkmain->regmap);
461 }
462 
463 static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
464 						 unsigned long parent_rate)
465 {
466 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
467 
468 	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
469 }
470 
471 static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
472 {
473 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
474 	struct regmap *regmap = clkmain->regmap;
475 	unsigned int tmp;
476 
477 	if (index > 1)
478 		return -EINVAL;
479 
480 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
481 
482 	if (index && !(tmp & AT91_PMC_MOSCSEL))
483 		tmp = AT91_PMC_MOSCSEL;
484 	else if (!index && (tmp & AT91_PMC_MOSCSEL))
485 		tmp = 0;
486 	else
487 		return 0;
488 
489 	regmap_update_bits(regmap, AT91_CKGR_MOR,
490 			   AT91_PMC_MOSCSEL | MOR_KEY_MASK,
491 			   tmp | AT91_PMC_KEY);
492 
493 	while (!clk_sam9x5_main_ready(regmap))
494 		cpu_relax();
495 
496 	return 0;
497 }
498 
499 static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
500 {
501 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
502 	unsigned int status;
503 
504 	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
505 
506 	return clk_main_parent_select(status);
507 }
508 
509 static int clk_sam9x5_main_save_context(struct clk_hw *hw)
510 {
511 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
512 
513 	clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw);
514 	clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw);
515 
516 	return 0;
517 }
518 
519 static void clk_sam9x5_main_restore_context(struct clk_hw *hw)
520 {
521 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
522 	int ret;
523 
524 	ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent);
525 	if (ret)
526 		return;
527 
528 	if (clkmain->pms.status)
529 		clk_sam9x5_main_prepare(hw);
530 }
531 
532 static const struct clk_ops sam9x5_main_ops = {
533 	.prepare = clk_sam9x5_main_prepare,
534 	.is_prepared = clk_sam9x5_main_is_prepared,
535 	.recalc_rate = clk_sam9x5_main_recalc_rate,
536 	.set_parent = clk_sam9x5_main_set_parent,
537 	.get_parent = clk_sam9x5_main_get_parent,
538 	.save_context = clk_sam9x5_main_save_context,
539 	.restore_context = clk_sam9x5_main_restore_context,
540 };
541 
542 struct clk_hw * __init
543 at91_clk_register_sam9x5_main(struct regmap *regmap,
544 			      const char *name,
545 			      const char **parent_names,
546 			      int num_parents)
547 {
548 	struct clk_sam9x5_main *clkmain;
549 	struct clk_init_data init;
550 	unsigned int status;
551 	struct clk_hw *hw;
552 	int ret;
553 
554 	if (!name)
555 		return ERR_PTR(-EINVAL);
556 
557 	if (!parent_names || !num_parents)
558 		return ERR_PTR(-EINVAL);
559 
560 	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
561 	if (!clkmain)
562 		return ERR_PTR(-ENOMEM);
563 
564 	init.name = name;
565 	init.ops = &sam9x5_main_ops;
566 	init.parent_names = parent_names;
567 	init.num_parents = num_parents;
568 	init.flags = CLK_SET_PARENT_GATE;
569 
570 	clkmain->hw.init = &init;
571 	clkmain->regmap = regmap;
572 	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
573 	clkmain->parent = clk_main_parent_select(status);
574 
575 	hw = &clkmain->hw;
576 	ret = clk_hw_register(NULL, &clkmain->hw);
577 	if (ret) {
578 		kfree(clkmain);
579 		hw = ERR_PTR(ret);
580 	}
581 
582 	return hw;
583 }
584