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