xref: /openbmc/linux/drivers/clk/at91/clk-slow.c (revision 1bdf0232)
1 /*
2  * drivers/clk/at91/clk-slow.c
3  *
4  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  */
12 
13 #include <linux/clk-provider.h>
14 #include <linux/clkdev.h>
15 #include <linux/slab.h>
16 #include <linux/clk/at91_pmc.h>
17 #include <linux/delay.h>
18 #include <linux/of.h>
19 #include <linux/of_address.h>
20 #include <linux/of_irq.h>
21 #include <linux/io.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/mfd/syscon.h>
25 #include <linux/regmap.h>
26 #include <linux/sched.h>
27 #include <linux/wait.h>
28 
29 #include "pmc.h"
30 #include "sckc.h"
31 
32 #define SLOW_CLOCK_FREQ		32768
33 #define SLOWCK_SW_CYCLES	5
34 #define SLOWCK_SW_TIME_USEC	((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
35 				 SLOW_CLOCK_FREQ)
36 
37 #define	AT91_SCKC_CR			0x00
38 #define		AT91_SCKC_RCEN		(1 << 0)
39 #define		AT91_SCKC_OSC32EN	(1 << 1)
40 #define		AT91_SCKC_OSC32BYP	(1 << 2)
41 #define		AT91_SCKC_OSCSEL	(1 << 3)
42 
43 struct clk_slow_osc {
44 	struct clk_hw hw;
45 	void __iomem *sckcr;
46 	unsigned long startup_usec;
47 };
48 
49 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
50 
51 struct clk_slow_rc_osc {
52 	struct clk_hw hw;
53 	void __iomem *sckcr;
54 	unsigned long frequency;
55 	unsigned long accuracy;
56 	unsigned long startup_usec;
57 };
58 
59 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
60 
61 struct clk_sam9260_slow {
62 	struct clk_hw hw;
63 	struct regmap *regmap;
64 };
65 
66 #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
67 
68 struct clk_sam9x5_slow {
69 	struct clk_hw hw;
70 	void __iomem *sckcr;
71 	u8 parent;
72 };
73 
74 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
75 
76 static int clk_slow_osc_prepare(struct clk_hw *hw)
77 {
78 	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
79 	void __iomem *sckcr = osc->sckcr;
80 	u32 tmp = readl(sckcr);
81 
82 	if (tmp & AT91_SCKC_OSC32BYP)
83 		return 0;
84 
85 	writel(tmp | AT91_SCKC_OSC32EN, sckcr);
86 
87 	usleep_range(osc->startup_usec, osc->startup_usec + 1);
88 
89 	return 0;
90 }
91 
92 static void clk_slow_osc_unprepare(struct clk_hw *hw)
93 {
94 	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
95 	void __iomem *sckcr = osc->sckcr;
96 	u32 tmp = readl(sckcr);
97 
98 	if (tmp & AT91_SCKC_OSC32BYP)
99 		return;
100 
101 	writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
102 }
103 
104 static int clk_slow_osc_is_prepared(struct clk_hw *hw)
105 {
106 	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
107 	void __iomem *sckcr = osc->sckcr;
108 	u32 tmp = readl(sckcr);
109 
110 	if (tmp & AT91_SCKC_OSC32BYP)
111 		return 1;
112 
113 	return !!(tmp & AT91_SCKC_OSC32EN);
114 }
115 
116 static const struct clk_ops slow_osc_ops = {
117 	.prepare = clk_slow_osc_prepare,
118 	.unprepare = clk_slow_osc_unprepare,
119 	.is_prepared = clk_slow_osc_is_prepared,
120 };
121 
122 static struct clk * __init
123 at91_clk_register_slow_osc(void __iomem *sckcr,
124 			   const char *name,
125 			   const char *parent_name,
126 			   unsigned long startup,
127 			   bool bypass)
128 {
129 	struct clk_slow_osc *osc;
130 	struct clk *clk = NULL;
131 	struct clk_init_data init;
132 
133 	if (!sckcr || !name || !parent_name)
134 		return ERR_PTR(-EINVAL);
135 
136 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
137 	if (!osc)
138 		return ERR_PTR(-ENOMEM);
139 
140 	init.name = name;
141 	init.ops = &slow_osc_ops;
142 	init.parent_names = &parent_name;
143 	init.num_parents = 1;
144 	init.flags = CLK_IGNORE_UNUSED;
145 
146 	osc->hw.init = &init;
147 	osc->sckcr = sckcr;
148 	osc->startup_usec = startup;
149 
150 	if (bypass)
151 		writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
152 		       sckcr);
153 
154 	clk = clk_register(NULL, &osc->hw);
155 	if (IS_ERR(clk))
156 		kfree(osc);
157 
158 	return clk;
159 }
160 
161 void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
162 					     void __iomem *sckcr)
163 {
164 	struct clk *clk;
165 	const char *parent_name;
166 	const char *name = np->name;
167 	u32 startup;
168 	bool bypass;
169 
170 	parent_name = of_clk_get_parent_name(np, 0);
171 	of_property_read_string(np, "clock-output-names", &name);
172 	of_property_read_u32(np, "atmel,startup-time-usec", &startup);
173 	bypass = of_property_read_bool(np, "atmel,osc-bypass");
174 
175 	clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
176 					 bypass);
177 	if (IS_ERR(clk))
178 		return;
179 
180 	of_clk_add_provider(np, of_clk_src_simple_get, clk);
181 }
182 
183 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
184 						 unsigned long parent_rate)
185 {
186 	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
187 
188 	return osc->frequency;
189 }
190 
191 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
192 						     unsigned long parent_acc)
193 {
194 	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
195 
196 	return osc->accuracy;
197 }
198 
199 static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
200 {
201 	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
202 	void __iomem *sckcr = osc->sckcr;
203 
204 	writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
205 
206 	usleep_range(osc->startup_usec, osc->startup_usec + 1);
207 
208 	return 0;
209 }
210 
211 static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
212 {
213 	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
214 	void __iomem *sckcr = osc->sckcr;
215 
216 	writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
217 }
218 
219 static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
220 {
221 	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
222 
223 	return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
224 }
225 
226 static const struct clk_ops slow_rc_osc_ops = {
227 	.prepare = clk_slow_rc_osc_prepare,
228 	.unprepare = clk_slow_rc_osc_unprepare,
229 	.is_prepared = clk_slow_rc_osc_is_prepared,
230 	.recalc_rate = clk_slow_rc_osc_recalc_rate,
231 	.recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
232 };
233 
234 static struct clk * __init
235 at91_clk_register_slow_rc_osc(void __iomem *sckcr,
236 			      const char *name,
237 			      unsigned long frequency,
238 			      unsigned long accuracy,
239 			      unsigned long startup)
240 {
241 	struct clk_slow_rc_osc *osc;
242 	struct clk *clk = NULL;
243 	struct clk_init_data init;
244 
245 	if (!sckcr || !name)
246 		return ERR_PTR(-EINVAL);
247 
248 	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
249 	if (!osc)
250 		return ERR_PTR(-ENOMEM);
251 
252 	init.name = name;
253 	init.ops = &slow_rc_osc_ops;
254 	init.parent_names = NULL;
255 	init.num_parents = 0;
256 	init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
257 
258 	osc->hw.init = &init;
259 	osc->sckcr = sckcr;
260 	osc->frequency = frequency;
261 	osc->accuracy = accuracy;
262 	osc->startup_usec = startup;
263 
264 	clk = clk_register(NULL, &osc->hw);
265 	if (IS_ERR(clk))
266 		kfree(osc);
267 
268 	return clk;
269 }
270 
271 void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
272 						void __iomem *sckcr)
273 {
274 	struct clk *clk;
275 	u32 frequency = 0;
276 	u32 accuracy = 0;
277 	u32 startup = 0;
278 	const char *name = np->name;
279 
280 	of_property_read_string(np, "clock-output-names", &name);
281 	of_property_read_u32(np, "clock-frequency", &frequency);
282 	of_property_read_u32(np, "clock-accuracy", &accuracy);
283 	of_property_read_u32(np, "atmel,startup-time-usec", &startup);
284 
285 	clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
286 					    startup);
287 	if (IS_ERR(clk))
288 		return;
289 
290 	of_clk_add_provider(np, of_clk_src_simple_get, clk);
291 }
292 
293 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
294 {
295 	struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
296 	void __iomem *sckcr = slowck->sckcr;
297 	u32 tmp;
298 
299 	if (index > 1)
300 		return -EINVAL;
301 
302 	tmp = readl(sckcr);
303 
304 	if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
305 	    (index && (tmp & AT91_SCKC_OSCSEL)))
306 		return 0;
307 
308 	if (index)
309 		tmp |= AT91_SCKC_OSCSEL;
310 	else
311 		tmp &= ~AT91_SCKC_OSCSEL;
312 
313 	writel(tmp, sckcr);
314 
315 	usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
316 
317 	return 0;
318 }
319 
320 static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
321 {
322 	struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
323 
324 	return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
325 }
326 
327 static const struct clk_ops sam9x5_slow_ops = {
328 	.set_parent = clk_sam9x5_slow_set_parent,
329 	.get_parent = clk_sam9x5_slow_get_parent,
330 };
331 
332 static struct clk * __init
333 at91_clk_register_sam9x5_slow(void __iomem *sckcr,
334 			      const char *name,
335 			      const char **parent_names,
336 			      int num_parents)
337 {
338 	struct clk_sam9x5_slow *slowck;
339 	struct clk *clk = NULL;
340 	struct clk_init_data init;
341 
342 	if (!sckcr || !name || !parent_names || !num_parents)
343 		return ERR_PTR(-EINVAL);
344 
345 	slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
346 	if (!slowck)
347 		return ERR_PTR(-ENOMEM);
348 
349 	init.name = name;
350 	init.ops = &sam9x5_slow_ops;
351 	init.parent_names = parent_names;
352 	init.num_parents = num_parents;
353 	init.flags = 0;
354 
355 	slowck->hw.init = &init;
356 	slowck->sckcr = sckcr;
357 	slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
358 
359 	clk = clk_register(NULL, &slowck->hw);
360 	if (IS_ERR(clk))
361 		kfree(slowck);
362 
363 	return clk;
364 }
365 
366 void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
367 					 void __iomem *sckcr)
368 {
369 	struct clk *clk;
370 	const char *parent_names[2];
371 	int num_parents;
372 	const char *name = np->name;
373 
374 	num_parents = of_clk_get_parent_count(np);
375 	if (num_parents <= 0 || num_parents > 2)
376 		return;
377 
378 	of_clk_parent_fill(np, parent_names, num_parents);
379 
380 	of_property_read_string(np, "clock-output-names", &name);
381 
382 	clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
383 					    num_parents);
384 	if (IS_ERR(clk))
385 		return;
386 
387 	of_clk_add_provider(np, of_clk_src_simple_get, clk);
388 }
389 
390 static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
391 {
392 	struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
393 	unsigned int status;
394 
395 	regmap_read(slowck->regmap, AT91_PMC_SR, &status);
396 
397 	return status & AT91_PMC_OSCSEL ? 1 : 0;
398 }
399 
400 static const struct clk_ops sam9260_slow_ops = {
401 	.get_parent = clk_sam9260_slow_get_parent,
402 };
403 
404 static struct clk * __init
405 at91_clk_register_sam9260_slow(struct regmap *regmap,
406 			       const char *name,
407 			       const char **parent_names,
408 			       int num_parents)
409 {
410 	struct clk_sam9260_slow *slowck;
411 	struct clk *clk = NULL;
412 	struct clk_init_data init;
413 
414 	if (!name)
415 		return ERR_PTR(-EINVAL);
416 
417 	if (!parent_names || !num_parents)
418 		return ERR_PTR(-EINVAL);
419 
420 	slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
421 	if (!slowck)
422 		return ERR_PTR(-ENOMEM);
423 
424 	init.name = name;
425 	init.ops = &sam9260_slow_ops;
426 	init.parent_names = parent_names;
427 	init.num_parents = num_parents;
428 	init.flags = 0;
429 
430 	slowck->hw.init = &init;
431 	slowck->regmap = regmap;
432 
433 	clk = clk_register(NULL, &slowck->hw);
434 	if (IS_ERR(clk))
435 		kfree(slowck);
436 
437 	return clk;
438 }
439 
440 static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
441 {
442 	struct clk *clk;
443 	const char *parent_names[2];
444 	int num_parents;
445 	const char *name = np->name;
446 	struct regmap *regmap;
447 
448 	num_parents = of_clk_get_parent_count(np);
449 	if (num_parents != 2)
450 		return;
451 
452 	of_clk_parent_fill(np, parent_names, num_parents);
453 	regmap = syscon_node_to_regmap(of_get_parent(np));
454 	if (IS_ERR(regmap))
455 		return;
456 
457 	of_property_read_string(np, "clock-output-names", &name);
458 
459 	clk = at91_clk_register_sam9260_slow(regmap, name, parent_names,
460 					     num_parents);
461 	if (IS_ERR(clk))
462 		return;
463 
464 	of_clk_add_provider(np, of_clk_src_simple_get, clk);
465 }
466 
467 CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
468 	       of_at91sam9260_clk_slow_setup);
469