]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/clk/at91/sckc.c
1f0f1cd06387596dd7447647df19d28c08c76cbb
[linux.git] / drivers / clk / at91 / sckc.c
1 /*
2  * drivers/clk/at91/sckc.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/delay.h>
16 #include <linux/of.h>
17 #include <linux/of_address.h>
18 #include <linux/io.h>
19
20 #define SLOW_CLOCK_FREQ         32768
21 #define SLOWCK_SW_CYCLES        5
22 #define SLOWCK_SW_TIME_USEC     ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
23                                  SLOW_CLOCK_FREQ)
24
25 #define AT91_SCKC_CR                    0x00
26
27 struct clk_slow_bits {
28         u32 cr_rcen;
29         u32 cr_osc32en;
30         u32 cr_osc32byp;
31         u32 cr_oscsel;
32 };
33
34 struct clk_slow_osc {
35         struct clk_hw hw;
36         void __iomem *sckcr;
37         const struct clk_slow_bits *bits;
38         unsigned long startup_usec;
39 };
40
41 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
42
43 struct clk_sama5d4_slow_osc {
44         struct clk_hw hw;
45         void __iomem *sckcr;
46         const struct clk_slow_bits *bits;
47         unsigned long startup_usec;
48         bool prepared;
49 };
50
51 #define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
52
53 struct clk_slow_rc_osc {
54         struct clk_hw hw;
55         void __iomem *sckcr;
56         const struct clk_slow_bits *bits;
57         unsigned long frequency;
58         unsigned long accuracy;
59         unsigned long startup_usec;
60 };
61
62 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
63
64 struct clk_sam9x5_slow {
65         struct clk_hw hw;
66         void __iomem *sckcr;
67         const struct clk_slow_bits *bits;
68         u8 parent;
69 };
70
71 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
72
73 static int clk_slow_osc_prepare(struct clk_hw *hw)
74 {
75         struct clk_slow_osc *osc = to_clk_slow_osc(hw);
76         void __iomem *sckcr = osc->sckcr;
77         u32 tmp = readl(sckcr);
78
79         if (tmp & (osc->bits->cr_osc32byp | osc->bits->cr_osc32en))
80                 return 0;
81
82         writel(tmp | osc->bits->cr_osc32en, sckcr);
83
84         usleep_range(osc->startup_usec, osc->startup_usec + 1);
85
86         return 0;
87 }
88
89 static void clk_slow_osc_unprepare(struct clk_hw *hw)
90 {
91         struct clk_slow_osc *osc = to_clk_slow_osc(hw);
92         void __iomem *sckcr = osc->sckcr;
93         u32 tmp = readl(sckcr);
94
95         if (tmp & osc->bits->cr_osc32byp)
96                 return;
97
98         writel(tmp & ~osc->bits->cr_osc32en, sckcr);
99 }
100
101 static int clk_slow_osc_is_prepared(struct clk_hw *hw)
102 {
103         struct clk_slow_osc *osc = to_clk_slow_osc(hw);
104         void __iomem *sckcr = osc->sckcr;
105         u32 tmp = readl(sckcr);
106
107         if (tmp & osc->bits->cr_osc32byp)
108                 return 1;
109
110         return !!(tmp & osc->bits->cr_osc32en);
111 }
112
113 static const struct clk_ops slow_osc_ops = {
114         .prepare = clk_slow_osc_prepare,
115         .unprepare = clk_slow_osc_unprepare,
116         .is_prepared = clk_slow_osc_is_prepared,
117 };
118
119 static struct clk_hw * __init
120 at91_clk_register_slow_osc(void __iomem *sckcr,
121                            const char *name,
122                            const char *parent_name,
123                            unsigned long startup,
124                            bool bypass,
125                            const struct clk_slow_bits *bits)
126 {
127         struct clk_slow_osc *osc;
128         struct clk_hw *hw;
129         struct clk_init_data init;
130         int ret;
131
132         if (!sckcr || !name || !parent_name)
133                 return ERR_PTR(-EINVAL);
134
135         osc = kzalloc(sizeof(*osc), GFP_KERNEL);
136         if (!osc)
137                 return ERR_PTR(-ENOMEM);
138
139         init.name = name;
140         init.ops = &slow_osc_ops;
141         init.parent_names = &parent_name;
142         init.num_parents = 1;
143         init.flags = CLK_IGNORE_UNUSED;
144
145         osc->hw.init = &init;
146         osc->sckcr = sckcr;
147         osc->startup_usec = startup;
148         osc->bits = bits;
149
150         if (bypass)
151                 writel((readl(sckcr) & ~osc->bits->cr_osc32en) |
152                                         osc->bits->cr_osc32byp, sckcr);
153
154         hw = &osc->hw;
155         ret = clk_hw_register(NULL, &osc->hw);
156         if (ret) {
157                 kfree(osc);
158                 hw = ERR_PTR(ret);
159         }
160
161         return hw;
162 }
163
164 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
165                                                  unsigned long parent_rate)
166 {
167         struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
168
169         return osc->frequency;
170 }
171
172 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
173                                                      unsigned long parent_acc)
174 {
175         struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
176
177         return osc->accuracy;
178 }
179
180 static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
181 {
182         struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
183         void __iomem *sckcr = osc->sckcr;
184
185         writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
186
187         usleep_range(osc->startup_usec, osc->startup_usec + 1);
188
189         return 0;
190 }
191
192 static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
193 {
194         struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
195         void __iomem *sckcr = osc->sckcr;
196
197         writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr);
198 }
199
200 static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
201 {
202         struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
203
204         return !!(readl(osc->sckcr) & osc->bits->cr_rcen);
205 }
206
207 static const struct clk_ops slow_rc_osc_ops = {
208         .prepare = clk_slow_rc_osc_prepare,
209         .unprepare = clk_slow_rc_osc_unprepare,
210         .is_prepared = clk_slow_rc_osc_is_prepared,
211         .recalc_rate = clk_slow_rc_osc_recalc_rate,
212         .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
213 };
214
215 static struct clk_hw * __init
216 at91_clk_register_slow_rc_osc(void __iomem *sckcr,
217                               const char *name,
218                               unsigned long frequency,
219                               unsigned long accuracy,
220                               unsigned long startup,
221                               const struct clk_slow_bits *bits)
222 {
223         struct clk_slow_rc_osc *osc;
224         struct clk_hw *hw;
225         struct clk_init_data init;
226         int ret;
227
228         if (!sckcr || !name)
229                 return ERR_PTR(-EINVAL);
230
231         osc = kzalloc(sizeof(*osc), GFP_KERNEL);
232         if (!osc)
233                 return ERR_PTR(-ENOMEM);
234
235         init.name = name;
236         init.ops = &slow_rc_osc_ops;
237         init.parent_names = NULL;
238         init.num_parents = 0;
239         init.flags = CLK_IGNORE_UNUSED;
240
241         osc->hw.init = &init;
242         osc->sckcr = sckcr;
243         osc->bits = bits;
244         osc->frequency = frequency;
245         osc->accuracy = accuracy;
246         osc->startup_usec = startup;
247
248         hw = &osc->hw;
249         ret = clk_hw_register(NULL, &osc->hw);
250         if (ret) {
251                 kfree(osc);
252                 hw = ERR_PTR(ret);
253         }
254
255         return hw;
256 }
257
258 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
259 {
260         struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
261         void __iomem *sckcr = slowck->sckcr;
262         u32 tmp;
263
264         if (index > 1)
265                 return -EINVAL;
266
267         tmp = readl(sckcr);
268
269         if ((!index && !(tmp & slowck->bits->cr_oscsel)) ||
270             (index && (tmp & slowck->bits->cr_oscsel)))
271                 return 0;
272
273         if (index)
274                 tmp |= slowck->bits->cr_oscsel;
275         else
276                 tmp &= ~slowck->bits->cr_oscsel;
277
278         writel(tmp, sckcr);
279
280         usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
281
282         return 0;
283 }
284
285 static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
286 {
287         struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
288
289         return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel);
290 }
291
292 static const struct clk_ops sam9x5_slow_ops = {
293         .set_parent = clk_sam9x5_slow_set_parent,
294         .get_parent = clk_sam9x5_slow_get_parent,
295 };
296
297 static struct clk_hw * __init
298 at91_clk_register_sam9x5_slow(void __iomem *sckcr,
299                               const char *name,
300                               const char **parent_names,
301                               int num_parents,
302                               const struct clk_slow_bits *bits)
303 {
304         struct clk_sam9x5_slow *slowck;
305         struct clk_hw *hw;
306         struct clk_init_data init;
307         int ret;
308
309         if (!sckcr || !name || !parent_names || !num_parents)
310                 return ERR_PTR(-EINVAL);
311
312         slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
313         if (!slowck)
314                 return ERR_PTR(-ENOMEM);
315
316         init.name = name;
317         init.ops = &sam9x5_slow_ops;
318         init.parent_names = parent_names;
319         init.num_parents = num_parents;
320         init.flags = 0;
321
322         slowck->hw.init = &init;
323         slowck->sckcr = sckcr;
324         slowck->bits = bits;
325         slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel);
326
327         hw = &slowck->hw;
328         ret = clk_hw_register(NULL, &slowck->hw);
329         if (ret) {
330                 kfree(slowck);
331                 hw = ERR_PTR(ret);
332         }
333
334         return hw;
335 }
336
337 static void __init at91sam9x5_sckc_register(struct device_node *np,
338                                             unsigned int rc_osc_startup_us,
339                                             const struct clk_slow_bits *bits)
340 {
341         const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
342         void __iomem *regbase = of_iomap(np, 0);
343         struct device_node *child = NULL;
344         const char *xtal_name;
345         struct clk_hw *hw;
346         bool bypass;
347
348         if (!regbase)
349                 return;
350
351         hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768,
352                                            50000000, rc_osc_startup_us,
353                                            bits);
354         if (IS_ERR(hw))
355                 return;
356
357         xtal_name = of_clk_get_parent_name(np, 0);
358         if (!xtal_name) {
359                 /* DT backward compatibility */
360                 child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
361                 if (!child)
362                         return;
363
364                 xtal_name = of_clk_get_parent_name(child, 0);
365                 bypass = of_property_read_bool(child, "atmel,osc-bypass");
366
367                 child =  of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow");
368         } else {
369                 bypass = of_property_read_bool(np, "atmel,osc-bypass");
370         }
371
372         if (!xtal_name)
373                 return;
374
375         hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name,
376                                         1200000, bypass, bits);
377         if (IS_ERR(hw))
378                 return;
379
380         hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2,
381                                            bits);
382         if (IS_ERR(hw))
383                 return;
384
385         of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
386
387         /* DT backward compatibility */
388         if (child)
389                 of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw);
390 }
391
392 static const struct clk_slow_bits at91sam9x5_bits = {
393         .cr_rcen = BIT(0),
394         .cr_osc32en = BIT(1),
395         .cr_osc32byp = BIT(2),
396         .cr_oscsel = BIT(3),
397 };
398
399 static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
400 {
401         at91sam9x5_sckc_register(np, 75, &at91sam9x5_bits);
402 }
403 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
404                of_at91sam9x5_sckc_setup);
405
406 static void __init of_sama5d3_sckc_setup(struct device_node *np)
407 {
408         at91sam9x5_sckc_register(np, 500, &at91sam9x5_bits);
409 }
410 CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
411                of_sama5d3_sckc_setup);
412
413 static const struct clk_slow_bits at91sam9x60_bits = {
414         .cr_osc32en = BIT(1),
415         .cr_osc32byp = BIT(2),
416         .cr_oscsel = BIT(24),
417 };
418
419 static void __init of_sam9x60_sckc_setup(struct device_node *np)
420 {
421         void __iomem *regbase = of_iomap(np, 0);
422         struct clk_hw_onecell_data *clk_data;
423         struct clk_hw *slow_rc, *slow_osc;
424         const char *xtal_name;
425         const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
426         bool bypass;
427         int ret;
428
429         if (!regbase)
430                 return;
431
432         slow_rc = clk_hw_register_fixed_rate(NULL, parent_names[0], NULL, 0,
433                                              32768);
434         if (IS_ERR(slow_rc))
435                 return;
436
437         xtal_name = of_clk_get_parent_name(np, 0);
438         if (!xtal_name)
439                 goto unregister_slow_rc;
440
441         bypass = of_property_read_bool(np, "atmel,osc-bypass");
442         slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
443                                               xtal_name, 5000000, bypass,
444                                               &at91sam9x60_bits);
445         if (IS_ERR(slow_osc))
446                 goto unregister_slow_rc;
447
448         clk_data = kzalloc(sizeof(*clk_data) + (2 * sizeof(struct clk_hw *)),
449                            GFP_KERNEL);
450         if (!clk_data)
451                 goto unregister_slow_osc;
452
453         /* MD_SLCK and TD_SLCK. */
454         clk_data->num = 2;
455         clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck",
456                                                       parent_names[0],
457                                                       0, 32768);
458         if (IS_ERR(clk_data->hws[0]))
459                 goto clk_data_free;
460
461         clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
462                                                          parent_names, 2,
463                                                          &at91sam9x60_bits);
464         if (IS_ERR(clk_data->hws[1]))
465                 goto unregister_md_slck;
466
467         ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
468         if (WARN_ON(ret))
469                 goto unregister_td_slck;
470
471         return;
472
473 unregister_td_slck:
474         clk_hw_unregister(clk_data->hws[1]);
475 unregister_md_slck:
476         clk_hw_unregister(clk_data->hws[0]);
477 clk_data_free:
478         kfree(clk_data);
479 unregister_slow_osc:
480         clk_hw_unregister(slow_osc);
481 unregister_slow_rc:
482         clk_hw_unregister(slow_rc);
483 }
484 CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc",
485                of_sam9x60_sckc_setup);
486
487 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
488 {
489         struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
490
491         if (osc->prepared)
492                 return 0;
493
494         /*
495          * Assume that if it has already been selected (for example by the
496          * bootloader), enough time has aready passed.
497          */
498         if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) {
499                 osc->prepared = true;
500                 return 0;
501         }
502
503         usleep_range(osc->startup_usec, osc->startup_usec + 1);
504         osc->prepared = true;
505
506         return 0;
507 }
508
509 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw)
510 {
511         struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
512
513         return osc->prepared;
514 }
515
516 static const struct clk_ops sama5d4_slow_osc_ops = {
517         .prepare = clk_sama5d4_slow_osc_prepare,
518         .is_prepared = clk_sama5d4_slow_osc_is_prepared,
519 };
520
521 static const struct clk_slow_bits at91sama5d4_bits = {
522         .cr_oscsel = BIT(3),
523 };
524
525 static void __init of_sama5d4_sckc_setup(struct device_node *np)
526 {
527         void __iomem *regbase = of_iomap(np, 0);
528         struct clk_hw *hw;
529         struct clk_sama5d4_slow_osc *osc;
530         struct clk_init_data init;
531         const char *xtal_name;
532         const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
533         int ret;
534
535         if (!regbase)
536                 return;
537
538         hw = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
539                                                       NULL, 0, 32768,
540                                                       250000000);
541         if (IS_ERR(hw))
542                 return;
543
544         xtal_name = of_clk_get_parent_name(np, 0);
545
546         osc = kzalloc(sizeof(*osc), GFP_KERNEL);
547         if (!osc)
548                 return;
549
550         init.name = parent_names[1];
551         init.ops = &sama5d4_slow_osc_ops;
552         init.parent_names = &xtal_name;
553         init.num_parents = 1;
554         init.flags = CLK_IGNORE_UNUSED;
555
556         osc->hw.init = &init;
557         osc->sckcr = regbase;
558         osc->startup_usec = 1200000;
559         osc->bits = &at91sama5d4_bits;
560
561         hw = &osc->hw;
562         ret = clk_hw_register(NULL, &osc->hw);
563         if (ret) {
564                 kfree(osc);
565                 return;
566         }
567
568         hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2,
569                                            &at91sama5d4_bits);
570         if (IS_ERR(hw))
571                 return;
572
573         of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
574 }
575 CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
576                of_sama5d4_sckc_setup);