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