1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * drivers/clk/at91/sckc.c
5 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
8 #include <linux/clk-provider.h>
9 #include <linux/clkdev.h>
10 #include <linux/delay.h>
12 #include <linux/of_address.h>
15 #define SLOW_CLOCK_FREQ 32768
16 #define SLOWCK_SW_CYCLES 5
17 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
20 #define AT91_SCKC_CR 0x00
22 struct clk_slow_bits
{
32 const struct clk_slow_bits
*bits
;
33 unsigned long startup_usec
;
36 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
38 struct clk_sama5d4_slow_osc
{
41 const struct clk_slow_bits
*bits
;
42 unsigned long startup_usec
;
46 #define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
48 struct clk_slow_rc_osc
{
51 const struct clk_slow_bits
*bits
;
52 unsigned long frequency
;
53 unsigned long accuracy
;
54 unsigned long startup_usec
;
57 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
59 struct clk_sam9x5_slow
{
62 const struct clk_slow_bits
*bits
;
66 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
68 static int clk_slow_osc_prepare(struct clk_hw
*hw
)
70 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
71 void __iomem
*sckcr
= osc
->sckcr
;
72 u32 tmp
= readl(sckcr
);
74 if (tmp
& (osc
->bits
->cr_osc32byp
| osc
->bits
->cr_osc32en
))
77 writel(tmp
| osc
->bits
->cr_osc32en
, sckcr
);
79 if (system_state
< SYSTEM_RUNNING
)
80 udelay(osc
->startup_usec
);
82 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
87 static void clk_slow_osc_unprepare(struct clk_hw
*hw
)
89 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
90 void __iomem
*sckcr
= osc
->sckcr
;
91 u32 tmp
= readl(sckcr
);
93 if (tmp
& osc
->bits
->cr_osc32byp
)
96 writel(tmp
& ~osc
->bits
->cr_osc32en
, sckcr
);
99 static int clk_slow_osc_is_prepared(struct clk_hw
*hw
)
101 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
102 void __iomem
*sckcr
= osc
->sckcr
;
103 u32 tmp
= readl(sckcr
);
105 if (tmp
& osc
->bits
->cr_osc32byp
)
108 return !!(tmp
& osc
->bits
->cr_osc32en
);
111 static const struct clk_ops slow_osc_ops
= {
112 .prepare
= clk_slow_osc_prepare
,
113 .unprepare
= clk_slow_osc_unprepare
,
114 .is_prepared
= clk_slow_osc_is_prepared
,
117 static struct clk_hw
* __init
118 at91_clk_register_slow_osc(void __iomem
*sckcr
,
120 const struct clk_parent_data
*parent_data
,
121 unsigned long startup
,
123 const struct clk_slow_bits
*bits
)
125 struct clk_slow_osc
*osc
;
127 struct clk_init_data init
= {};
130 if (!sckcr
|| !name
|| !parent_data
)
131 return ERR_PTR(-EINVAL
);
133 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
135 return ERR_PTR(-ENOMEM
);
138 init
.ops
= &slow_osc_ops
;
139 init
.parent_data
= parent_data
;
140 init
.num_parents
= 1;
141 init
.flags
= CLK_IGNORE_UNUSED
;
143 osc
->hw
.init
= &init
;
145 osc
->startup_usec
= startup
;
149 writel((readl(sckcr
) & ~osc
->bits
->cr_osc32en
) |
150 osc
->bits
->cr_osc32byp
, sckcr
);
153 ret
= clk_hw_register(NULL
, &osc
->hw
);
162 static void at91_clk_unregister_slow_osc(struct clk_hw
*hw
)
164 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
166 clk_hw_unregister(hw
);
170 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw
*hw
,
171 unsigned long parent_rate
)
173 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
175 return osc
->frequency
;
178 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw
*hw
,
179 unsigned long parent_acc
)
181 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
183 return osc
->accuracy
;
186 static int clk_slow_rc_osc_prepare(struct clk_hw
*hw
)
188 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
189 void __iomem
*sckcr
= osc
->sckcr
;
191 writel(readl(sckcr
) | osc
->bits
->cr_rcen
, sckcr
);
193 if (system_state
< SYSTEM_RUNNING
)
194 udelay(osc
->startup_usec
);
196 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
201 static void clk_slow_rc_osc_unprepare(struct clk_hw
*hw
)
203 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
204 void __iomem
*sckcr
= osc
->sckcr
;
206 writel(readl(sckcr
) & ~osc
->bits
->cr_rcen
, sckcr
);
209 static int clk_slow_rc_osc_is_prepared(struct clk_hw
*hw
)
211 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
213 return !!(readl(osc
->sckcr
) & osc
->bits
->cr_rcen
);
216 static const struct clk_ops slow_rc_osc_ops
= {
217 .prepare
= clk_slow_rc_osc_prepare
,
218 .unprepare
= clk_slow_rc_osc_unprepare
,
219 .is_prepared
= clk_slow_rc_osc_is_prepared
,
220 .recalc_rate
= clk_slow_rc_osc_recalc_rate
,
221 .recalc_accuracy
= clk_slow_rc_osc_recalc_accuracy
,
224 static struct clk_hw
* __init
225 at91_clk_register_slow_rc_osc(void __iomem
*sckcr
,
227 unsigned long frequency
,
228 unsigned long accuracy
,
229 unsigned long startup
,
230 const struct clk_slow_bits
*bits
)
232 struct clk_slow_rc_osc
*osc
;
234 struct clk_init_data init
;
238 return ERR_PTR(-EINVAL
);
240 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
242 return ERR_PTR(-ENOMEM
);
245 init
.ops
= &slow_rc_osc_ops
;
246 init
.parent_names
= NULL
;
247 init
.num_parents
= 0;
248 init
.flags
= CLK_IGNORE_UNUSED
;
250 osc
->hw
.init
= &init
;
253 osc
->frequency
= frequency
;
254 osc
->accuracy
= accuracy
;
255 osc
->startup_usec
= startup
;
258 ret
= clk_hw_register(NULL
, &osc
->hw
);
267 static void at91_clk_unregister_slow_rc_osc(struct clk_hw
*hw
)
269 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
271 clk_hw_unregister(hw
);
275 static int clk_sam9x5_slow_set_parent(struct clk_hw
*hw
, u8 index
)
277 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
278 void __iomem
*sckcr
= slowck
->sckcr
;
286 if ((!index
&& !(tmp
& slowck
->bits
->cr_oscsel
)) ||
287 (index
&& (tmp
& slowck
->bits
->cr_oscsel
)))
291 tmp
|= slowck
->bits
->cr_oscsel
;
293 tmp
&= ~slowck
->bits
->cr_oscsel
;
297 if (system_state
< SYSTEM_RUNNING
)
298 udelay(SLOWCK_SW_TIME_USEC
);
300 usleep_range(SLOWCK_SW_TIME_USEC
, SLOWCK_SW_TIME_USEC
+ 1);
305 static u8
clk_sam9x5_slow_get_parent(struct clk_hw
*hw
)
307 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
309 return !!(readl(slowck
->sckcr
) & slowck
->bits
->cr_oscsel
);
312 static const struct clk_ops sam9x5_slow_ops
= {
313 .determine_rate
= clk_hw_determine_rate_no_reparent
,
314 .set_parent
= clk_sam9x5_slow_set_parent
,
315 .get_parent
= clk_sam9x5_slow_get_parent
,
318 static struct clk_hw
* __init
319 at91_clk_register_sam9x5_slow(void __iomem
*sckcr
,
321 const struct clk_hw
**parent_hws
,
323 const struct clk_slow_bits
*bits
)
325 struct clk_sam9x5_slow
*slowck
;
327 struct clk_init_data init
= {};
330 if (!sckcr
|| !name
|| !parent_hws
|| !num_parents
)
331 return ERR_PTR(-EINVAL
);
333 slowck
= kzalloc(sizeof(*slowck
), GFP_KERNEL
);
335 return ERR_PTR(-ENOMEM
);
338 init
.ops
= &sam9x5_slow_ops
;
339 init
.parent_hws
= parent_hws
;
340 init
.num_parents
= num_parents
;
343 slowck
->hw
.init
= &init
;
344 slowck
->sckcr
= sckcr
;
346 slowck
->parent
= !!(readl(sckcr
) & slowck
->bits
->cr_oscsel
);
349 ret
= clk_hw_register(NULL
, &slowck
->hw
);
358 static void at91_clk_unregister_sam9x5_slow(struct clk_hw
*hw
)
360 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
362 clk_hw_unregister(hw
);
366 static void __init
at91sam9x5_sckc_register(struct device_node
*np
,
367 unsigned int rc_osc_startup_us
,
368 const struct clk_slow_bits
*bits
)
370 void __iomem
*regbase
= of_iomap(np
, 0);
371 struct device_node
*child
= NULL
;
372 const char *xtal_name
;
373 struct clk_hw
*slow_rc
, *slow_osc
, *slowck
;
374 static struct clk_parent_data parent_data
= {
377 const struct clk_hw
*parent_hws
[2];
384 slow_rc
= at91_clk_register_slow_rc_osc(regbase
, "slow_rc_osc",
386 rc_osc_startup_us
, bits
);
390 xtal_name
= of_clk_get_parent_name(np
, 0);
392 /* DT backward compatibility */
393 child
= of_get_compatible_child(np
, "atmel,at91sam9x5-clk-slow-osc");
395 goto unregister_slow_rc
;
397 xtal_name
= of_clk_get_parent_name(child
, 0);
398 bypass
= of_property_read_bool(child
, "atmel,osc-bypass");
400 child
= of_get_compatible_child(np
, "atmel,at91sam9x5-clk-slow");
402 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
406 goto unregister_slow_rc
;
408 parent_data
.fw_name
= xtal_name
;
410 slow_osc
= at91_clk_register_slow_osc(regbase
, "slow_osc",
411 &parent_data
, 1200000, bypass
, bits
);
412 if (IS_ERR(slow_osc
))
413 goto unregister_slow_rc
;
415 parent_hws
[0] = slow_rc
;
416 parent_hws
[1] = slow_osc
;
417 slowck
= at91_clk_register_sam9x5_slow(regbase
, "slowck", parent_hws
,
420 goto unregister_slow_osc
;
422 /* DT backward compatibility */
424 ret
= of_clk_add_hw_provider(child
, of_clk_hw_simple_get
,
427 ret
= of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, slowck
);
430 goto unregister_slowck
;
435 at91_clk_unregister_sam9x5_slow(slowck
);
437 at91_clk_unregister_slow_osc(slow_osc
);
439 at91_clk_unregister_slow_rc_osc(slow_rc
);
442 static const struct clk_slow_bits at91sam9x5_bits
= {
444 .cr_osc32en
= BIT(1),
445 .cr_osc32byp
= BIT(2),
449 static void __init
of_at91sam9x5_sckc_setup(struct device_node
*np
)
451 at91sam9x5_sckc_register(np
, 75, &at91sam9x5_bits
);
453 CLK_OF_DECLARE(at91sam9x5_clk_sckc
, "atmel,at91sam9x5-sckc",
454 of_at91sam9x5_sckc_setup
);
456 static void __init
of_sama5d3_sckc_setup(struct device_node
*np
)
458 at91sam9x5_sckc_register(np
, 500, &at91sam9x5_bits
);
460 CLK_OF_DECLARE(sama5d3_clk_sckc
, "atmel,sama5d3-sckc",
461 of_sama5d3_sckc_setup
);
463 static const struct clk_slow_bits at91sam9x60_bits
= {
464 .cr_osc32en
= BIT(1),
465 .cr_osc32byp
= BIT(2),
466 .cr_oscsel
= BIT(24),
469 static void __init
of_sam9x60_sckc_setup(struct device_node
*np
)
471 void __iomem
*regbase
= of_iomap(np
, 0);
472 struct clk_hw_onecell_data
*clk_data
;
473 struct clk_hw
*slow_rc
, *slow_osc
;
474 const char *xtal_name
;
475 const struct clk_hw
*parent_hws
[2];
476 static struct clk_parent_data parent_data
= {
485 slow_rc
= clk_hw_register_fixed_rate_with_accuracy(NULL
, "slow_rc_osc",
491 xtal_name
= of_clk_get_parent_name(np
, 0);
493 goto unregister_slow_rc
;
495 parent_data
.fw_name
= xtal_name
;
496 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
497 slow_osc
= at91_clk_register_slow_osc(regbase
, "slow_osc",
498 &parent_data
, 5000000, bypass
,
500 if (IS_ERR(slow_osc
))
501 goto unregister_slow_rc
;
503 clk_data
= kzalloc(struct_size(clk_data
, hws
, 2), GFP_KERNEL
);
505 goto unregister_slow_osc
;
507 /* MD_SLCK and TD_SLCK. */
509 clk_data
->hws
[0] = clk_hw_register_fixed_rate_parent_hw(NULL
, "md_slck",
512 if (IS_ERR(clk_data
->hws
[0]))
515 parent_hws
[0] = slow_rc
;
516 parent_hws
[1] = slow_osc
;
517 clk_data
->hws
[1] = at91_clk_register_sam9x5_slow(regbase
, "td_slck",
520 if (IS_ERR(clk_data
->hws
[1]))
521 goto unregister_md_slck
;
523 ret
= of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, clk_data
);
525 goto unregister_td_slck
;
530 at91_clk_unregister_sam9x5_slow(clk_data
->hws
[1]);
532 clk_hw_unregister(clk_data
->hws
[0]);
536 at91_clk_unregister_slow_osc(slow_osc
);
538 clk_hw_unregister(slow_rc
);
540 CLK_OF_DECLARE(sam9x60_clk_sckc
, "microchip,sam9x60-sckc",
541 of_sam9x60_sckc_setup
);
543 static int clk_sama5d4_slow_osc_prepare(struct clk_hw
*hw
)
545 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
551 * Assume that if it has already been selected (for example by the
552 * bootloader), enough time has already passed.
554 if ((readl(osc
->sckcr
) & osc
->bits
->cr_oscsel
)) {
555 osc
->prepared
= true;
559 if (system_state
< SYSTEM_RUNNING
)
560 udelay(osc
->startup_usec
);
562 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
563 osc
->prepared
= true;
568 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw
*hw
)
570 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
572 return osc
->prepared
;
575 static const struct clk_ops sama5d4_slow_osc_ops
= {
576 .prepare
= clk_sama5d4_slow_osc_prepare
,
577 .is_prepared
= clk_sama5d4_slow_osc_is_prepared
,
580 static const struct clk_slow_bits at91sama5d4_bits
= {
584 static void __init
of_sama5d4_sckc_setup(struct device_node
*np
)
586 void __iomem
*regbase
= of_iomap(np
, 0);
587 struct clk_hw
*slow_rc
, *slowck
;
588 struct clk_sama5d4_slow_osc
*osc
;
589 struct clk_init_data init
= {};
590 const char *xtal_name
;
591 const struct clk_hw
*parent_hws
[2];
592 static struct clk_parent_data parent_data
= {
600 slow_rc
= clk_hw_register_fixed_rate_with_accuracy(NULL
,
607 xtal_name
= of_clk_get_parent_name(np
, 0);
609 goto unregister_slow_rc
;
610 parent_data
.fw_name
= xtal_name
;
612 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
614 goto unregister_slow_rc
;
616 init
.name
= "slow_osc";
617 init
.ops
= &sama5d4_slow_osc_ops
;
618 init
.parent_data
= &parent_data
;
619 init
.num_parents
= 1;
620 init
.flags
= CLK_IGNORE_UNUSED
;
622 osc
->hw
.init
= &init
;
623 osc
->sckcr
= regbase
;
624 osc
->startup_usec
= 1200000;
625 osc
->bits
= &at91sama5d4_bits
;
627 ret
= clk_hw_register(NULL
, &osc
->hw
);
629 goto free_slow_osc_data
;
631 parent_hws
[0] = slow_rc
;
632 parent_hws
[1] = &osc
->hw
;
633 slowck
= at91_clk_register_sam9x5_slow(regbase
, "slowck",
637 goto unregister_slow_osc
;
639 ret
= of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, slowck
);
641 goto unregister_slowck
;
646 at91_clk_unregister_sam9x5_slow(slowck
);
648 clk_hw_unregister(&osc
->hw
);
652 clk_hw_unregister(slow_rc
);
654 CLK_OF_DECLARE(sama5d4_clk_sckc
, "atmel,sama5d4-sckc",
655 of_sama5d4_sckc_setup
);