xref: /linux/drivers/clk/at91/clk-main.c (revision b5105e37)
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 
clk_main_osc_ready(struct regmap * regmap)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 
clk_main_osc_prepare(struct clk_hw * hw)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 
clk_main_osc_unprepare(struct clk_hw * hw)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 
clk_main_osc_is_prepared(struct clk_hw * hw)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 
clk_main_osc_save_context(struct clk_hw * hw)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 
clk_main_osc_restore_context(struct clk_hw * hw)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
at91_clk_register_main_osc(struct regmap * regmap,const char * name,const char * parent_name,struct clk_parent_data * parent_data,bool bypass)152 at91_clk_register_main_osc(struct regmap *regmap,
153 			   const char *name,
154 			   const char *parent_name,
155 			   struct clk_parent_data *parent_data,
156 			   bool bypass)
157 {
158 	struct clk_main_osc *osc;
159 	struct clk_init_data init = {};
160 	struct clk_hw *hw;
161 	int ret;
162 
163 	if (!name || !(parent_name || parent_data))
164 		return ERR_PTR(-EINVAL);
165 
166 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
167 	if (!osc)
168 		return ERR_PTR(-ENOMEM);
169 
170 	init.name = name;
171 	init.ops = &main_osc_ops;
172 	if (parent_data)
173 		init.parent_data = (const struct clk_parent_data *)parent_data;
174 	else
175 		init.parent_names = &parent_name;
176 	init.num_parents = 1;
177 	init.flags = CLK_IGNORE_UNUSED;
178 
179 	osc->hw.init = &init;
180 	osc->regmap = regmap;
181 
182 	if (bypass)
183 		regmap_update_bits(regmap,
184 				   AT91_CKGR_MOR, MOR_KEY_MASK |
185 				   AT91_PMC_OSCBYPASS,
186 				   AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
187 
188 	hw = &osc->hw;
189 	ret = clk_hw_register(NULL, &osc->hw);
190 	if (ret) {
191 		kfree(osc);
192 		hw = ERR_PTR(ret);
193 	}
194 
195 	return hw;
196 }
197 
clk_main_rc_osc_ready(struct regmap * regmap)198 static bool clk_main_rc_osc_ready(struct regmap *regmap)
199 {
200 	unsigned int status;
201 
202 	regmap_read(regmap, AT91_PMC_SR, &status);
203 
204 	return !!(status & AT91_PMC_MOSCRCS);
205 }
206 
clk_main_rc_osc_prepare(struct clk_hw * hw)207 static int clk_main_rc_osc_prepare(struct clk_hw *hw)
208 {
209 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
210 	struct regmap *regmap = osc->regmap;
211 	unsigned int mor;
212 
213 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
214 
215 	if (!(mor & AT91_PMC_MOSCRCEN))
216 		regmap_update_bits(regmap, AT91_CKGR_MOR,
217 				   MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
218 				   AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
219 
220 	while (!clk_main_rc_osc_ready(regmap))
221 		cpu_relax();
222 
223 	return 0;
224 }
225 
clk_main_rc_osc_unprepare(struct clk_hw * hw)226 static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
227 {
228 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
229 	struct regmap *regmap = osc->regmap;
230 	unsigned int mor;
231 
232 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
233 
234 	if (!(mor & AT91_PMC_MOSCRCEN))
235 		return;
236 
237 	regmap_update_bits(regmap, AT91_CKGR_MOR,
238 			   MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
239 }
240 
clk_main_rc_osc_is_prepared(struct clk_hw * hw)241 static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
242 {
243 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
244 	struct regmap *regmap = osc->regmap;
245 	unsigned int mor, status;
246 
247 	regmap_read(regmap, AT91_CKGR_MOR, &mor);
248 	regmap_read(regmap, AT91_PMC_SR, &status);
249 
250 	return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
251 }
252 
clk_main_rc_osc_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)253 static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
254 						 unsigned long parent_rate)
255 {
256 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
257 
258 	return osc->frequency;
259 }
260 
clk_main_rc_osc_recalc_accuracy(struct clk_hw * hw,unsigned long parent_acc)261 static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
262 						     unsigned long parent_acc)
263 {
264 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
265 
266 	return osc->accuracy;
267 }
268 
clk_main_rc_osc_save_context(struct clk_hw * hw)269 static int clk_main_rc_osc_save_context(struct clk_hw *hw)
270 {
271 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
272 
273 	osc->pms.status = clk_main_rc_osc_is_prepared(hw);
274 
275 	return 0;
276 }
277 
clk_main_rc_osc_restore_context(struct clk_hw * hw)278 static void clk_main_rc_osc_restore_context(struct clk_hw *hw)
279 {
280 	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
281 
282 	if (osc->pms.status)
283 		clk_main_rc_osc_prepare(hw);
284 }
285 
286 static const struct clk_ops main_rc_osc_ops = {
287 	.prepare = clk_main_rc_osc_prepare,
288 	.unprepare = clk_main_rc_osc_unprepare,
289 	.is_prepared = clk_main_rc_osc_is_prepared,
290 	.recalc_rate = clk_main_rc_osc_recalc_rate,
291 	.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
292 	.save_context = clk_main_rc_osc_save_context,
293 	.restore_context = clk_main_rc_osc_restore_context,
294 };
295 
296 struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap * regmap,const char * name,u32 frequency,u32 accuracy)297 at91_clk_register_main_rc_osc(struct regmap *regmap,
298 			      const char *name,
299 			      u32 frequency, u32 accuracy)
300 {
301 	struct clk_main_rc_osc *osc;
302 	struct clk_init_data init;
303 	struct clk_hw *hw;
304 	int ret;
305 
306 	if (!name || !frequency)
307 		return ERR_PTR(-EINVAL);
308 
309 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
310 	if (!osc)
311 		return ERR_PTR(-ENOMEM);
312 
313 	init.name = name;
314 	init.ops = &main_rc_osc_ops;
315 	init.parent_names = NULL;
316 	init.num_parents = 0;
317 	init.flags = CLK_IGNORE_UNUSED;
318 
319 	osc->hw.init = &init;
320 	osc->regmap = regmap;
321 	osc->frequency = frequency;
322 	osc->accuracy = accuracy;
323 
324 	hw = &osc->hw;
325 	ret = clk_hw_register(NULL, hw);
326 	if (ret) {
327 		kfree(osc);
328 		hw = ERR_PTR(ret);
329 	}
330 
331 	return hw;
332 }
333 
clk_main_probe_frequency(struct regmap * regmap)334 static int clk_main_probe_frequency(struct regmap *regmap)
335 {
336 	unsigned long prep_time, timeout;
337 	unsigned int mcfr;
338 
339 	timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
340 	do {
341 		prep_time = jiffies;
342 		regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
343 		if (mcfr & AT91_PMC_MAINRDY)
344 			return 0;
345 		if (system_state < SYSTEM_RUNNING)
346 			udelay(MAINF_LOOP_MIN_WAIT);
347 		else
348 			usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
349 	} while (time_before(prep_time, timeout));
350 
351 	return -ETIMEDOUT;
352 }
353 
clk_main_recalc_rate(struct regmap * regmap,unsigned long parent_rate)354 static unsigned long clk_main_recalc_rate(struct regmap *regmap,
355 					  unsigned long parent_rate)
356 {
357 	unsigned int mcfr;
358 
359 	if (parent_rate)
360 		return parent_rate;
361 
362 	pr_warn("Main crystal frequency not set, using approximate value\n");
363 	regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
364 	if (!(mcfr & AT91_PMC_MAINRDY))
365 		return 0;
366 
367 	return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
368 }
369 
clk_rm9200_main_prepare(struct clk_hw * hw)370 static int clk_rm9200_main_prepare(struct clk_hw *hw)
371 {
372 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
373 
374 	return clk_main_probe_frequency(clkmain->regmap);
375 }
376 
clk_rm9200_main_is_prepared(struct clk_hw * hw)377 static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
378 {
379 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
380 	unsigned int status;
381 
382 	regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
383 
384 	return !!(status & AT91_PMC_MAINRDY);
385 }
386 
clk_rm9200_main_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)387 static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
388 						 unsigned long parent_rate)
389 {
390 	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
391 
392 	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
393 }
394 
395 static const struct clk_ops rm9200_main_ops = {
396 	.prepare = clk_rm9200_main_prepare,
397 	.is_prepared = clk_rm9200_main_is_prepared,
398 	.recalc_rate = clk_rm9200_main_recalc_rate,
399 };
400 
401 struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap * regmap,const char * name,const char * parent_name,struct clk_hw * parent_hw)402 at91_clk_register_rm9200_main(struct regmap *regmap,
403 			      const char *name,
404 			      const char *parent_name,
405 			      struct clk_hw *parent_hw)
406 {
407 	struct clk_rm9200_main *clkmain;
408 	struct clk_init_data init = {};
409 	struct clk_hw *hw;
410 	int ret;
411 
412 	if (!name)
413 		return ERR_PTR(-EINVAL);
414 
415 	if (!(parent_name || parent_hw))
416 		return ERR_PTR(-EINVAL);
417 
418 	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
419 	if (!clkmain)
420 		return ERR_PTR(-ENOMEM);
421 
422 	init.name = name;
423 	init.ops = &rm9200_main_ops;
424 	if (parent_hw)
425 		init.parent_hws = (const struct clk_hw **)&parent_hw;
426 	else
427 		init.parent_names = &parent_name;
428 	init.num_parents = 1;
429 	init.flags = 0;
430 
431 	clkmain->hw.init = &init;
432 	clkmain->regmap = regmap;
433 
434 	hw = &clkmain->hw;
435 	ret = clk_hw_register(NULL, &clkmain->hw);
436 	if (ret) {
437 		kfree(clkmain);
438 		hw = ERR_PTR(ret);
439 	}
440 
441 	return hw;
442 }
443 
clk_sam9x5_main_ready(struct regmap * regmap)444 static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
445 {
446 	unsigned int status;
447 
448 	regmap_read(regmap, AT91_PMC_SR, &status);
449 
450 	return !!(status & AT91_PMC_MOSCSELS);
451 }
452 
clk_sam9x5_main_prepare(struct clk_hw * hw)453 static int clk_sam9x5_main_prepare(struct clk_hw *hw)
454 {
455 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
456 	struct regmap *regmap = clkmain->regmap;
457 
458 	while (!clk_sam9x5_main_ready(regmap))
459 		cpu_relax();
460 
461 	return clk_main_probe_frequency(regmap);
462 }
463 
clk_sam9x5_main_is_prepared(struct clk_hw * hw)464 static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
465 {
466 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
467 
468 	return clk_sam9x5_main_ready(clkmain->regmap);
469 }
470 
clk_sam9x5_main_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)471 static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
472 						 unsigned long parent_rate)
473 {
474 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
475 
476 	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
477 }
478 
clk_sam9x5_main_set_parent(struct clk_hw * hw,u8 index)479 static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
480 {
481 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
482 	struct regmap *regmap = clkmain->regmap;
483 	unsigned int tmp;
484 
485 	if (index > 1)
486 		return -EINVAL;
487 
488 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
489 
490 	if (index && !(tmp & AT91_PMC_MOSCSEL))
491 		tmp = AT91_PMC_MOSCSEL;
492 	else if (!index && (tmp & AT91_PMC_MOSCSEL))
493 		tmp = 0;
494 	else
495 		return 0;
496 
497 	regmap_update_bits(regmap, AT91_CKGR_MOR,
498 			   AT91_PMC_MOSCSEL | MOR_KEY_MASK,
499 			   tmp | AT91_PMC_KEY);
500 
501 	while (!clk_sam9x5_main_ready(regmap))
502 		cpu_relax();
503 
504 	return 0;
505 }
506 
clk_sam9x5_main_get_parent(struct clk_hw * hw)507 static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
508 {
509 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
510 	unsigned int status;
511 
512 	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
513 
514 	return clk_main_parent_select(status);
515 }
516 
clk_sam9x5_main_save_context(struct clk_hw * hw)517 static int clk_sam9x5_main_save_context(struct clk_hw *hw)
518 {
519 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
520 
521 	clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw);
522 	clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw);
523 
524 	return 0;
525 }
526 
clk_sam9x5_main_restore_context(struct clk_hw * hw)527 static void clk_sam9x5_main_restore_context(struct clk_hw *hw)
528 {
529 	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
530 	int ret;
531 
532 	ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent);
533 	if (ret)
534 		return;
535 
536 	if (clkmain->pms.status)
537 		clk_sam9x5_main_prepare(hw);
538 }
539 
540 static const struct clk_ops sam9x5_main_ops = {
541 	.prepare = clk_sam9x5_main_prepare,
542 	.is_prepared = clk_sam9x5_main_is_prepared,
543 	.recalc_rate = clk_sam9x5_main_recalc_rate,
544 	.determine_rate = clk_hw_determine_rate_no_reparent,
545 	.set_parent = clk_sam9x5_main_set_parent,
546 	.get_parent = clk_sam9x5_main_get_parent,
547 	.save_context = clk_sam9x5_main_save_context,
548 	.restore_context = clk_sam9x5_main_restore_context,
549 };
550 
551 struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap * regmap,const char * name,const char ** parent_names,struct clk_hw ** parent_hws,int num_parents)552 at91_clk_register_sam9x5_main(struct regmap *regmap,
553 			      const char *name,
554 			      const char **parent_names,
555 			      struct clk_hw **parent_hws,
556 			      int num_parents)
557 {
558 	struct clk_sam9x5_main *clkmain;
559 	struct clk_init_data init = {};
560 	unsigned int status;
561 	struct clk_hw *hw;
562 	int ret;
563 
564 	if (!name)
565 		return ERR_PTR(-EINVAL);
566 
567 	if (!(parent_hws || parent_names) || !num_parents)
568 		return ERR_PTR(-EINVAL);
569 
570 	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
571 	if (!clkmain)
572 		return ERR_PTR(-ENOMEM);
573 
574 	init.name = name;
575 	init.ops = &sam9x5_main_ops;
576 	if (parent_hws)
577 		init.parent_hws = (const struct clk_hw **)parent_hws;
578 	else
579 		init.parent_names = parent_names;
580 	init.num_parents = num_parents;
581 	init.flags = CLK_SET_PARENT_GATE;
582 
583 	clkmain->hw.init = &init;
584 	clkmain->regmap = regmap;
585 	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
586 	clkmain->parent = clk_main_parent_select(status);
587 
588 	hw = &clkmain->hw;
589 	ret = clk_hw_register(NULL, &clkmain->hw);
590 	if (ret) {
591 		kfree(clkmain);
592 		hw = ERR_PTR(ret);
593 	}
594 
595 	return hw;
596 }
597