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 char *parent_name
,
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_name
)
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_names
= &parent_name
;
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 .set_parent
= clk_sam9x5_slow_set_parent
,
314 .get_parent
= clk_sam9x5_slow_get_parent
,
317 static struct clk_hw
* __init
318 at91_clk_register_sam9x5_slow(void __iomem
*sckcr
,
320 const char **parent_names
,
322 const struct clk_slow_bits
*bits
)
324 struct clk_sam9x5_slow
*slowck
;
326 struct clk_init_data init
;
329 if (!sckcr
|| !name
|| !parent_names
|| !num_parents
)
330 return ERR_PTR(-EINVAL
);
332 slowck
= kzalloc(sizeof(*slowck
), GFP_KERNEL
);
334 return ERR_PTR(-ENOMEM
);
337 init
.ops
= &sam9x5_slow_ops
;
338 init
.parent_names
= parent_names
;
339 init
.num_parents
= num_parents
;
342 slowck
->hw
.init
= &init
;
343 slowck
->sckcr
= sckcr
;
345 slowck
->parent
= !!(readl(sckcr
) & slowck
->bits
->cr_oscsel
);
348 ret
= clk_hw_register(NULL
, &slowck
->hw
);
357 static void at91_clk_unregister_sam9x5_slow(struct clk_hw
*hw
)
359 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
361 clk_hw_unregister(hw
);
365 static void __init
at91sam9x5_sckc_register(struct device_node
*np
,
366 unsigned int rc_osc_startup_us
,
367 const struct clk_slow_bits
*bits
)
369 const char *parent_names
[2] = { "slow_rc_osc", "slow_osc" };
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
;
380 slow_rc
= at91_clk_register_slow_rc_osc(regbase
, parent_names
[0],
382 rc_osc_startup_us
, bits
);
386 xtal_name
= of_clk_get_parent_name(np
, 0);
388 /* DT backward compatibility */
389 child
= of_get_compatible_child(np
, "atmel,at91sam9x5-clk-slow-osc");
391 goto unregister_slow_rc
;
393 xtal_name
= of_clk_get_parent_name(child
, 0);
394 bypass
= of_property_read_bool(child
, "atmel,osc-bypass");
396 child
= of_get_compatible_child(np
, "atmel,at91sam9x5-clk-slow");
398 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
402 goto unregister_slow_rc
;
404 slow_osc
= at91_clk_register_slow_osc(regbase
, parent_names
[1],
405 xtal_name
, 1200000, bypass
, bits
);
406 if (IS_ERR(slow_osc
))
407 goto unregister_slow_rc
;
409 slowck
= at91_clk_register_sam9x5_slow(regbase
, "slowck", parent_names
,
412 goto unregister_slow_osc
;
414 /* DT backward compatibility */
416 ret
= of_clk_add_hw_provider(child
, of_clk_hw_simple_get
,
419 ret
= of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, slowck
);
422 goto unregister_slowck
;
427 at91_clk_unregister_sam9x5_slow(slowck
);
429 at91_clk_unregister_slow_osc(slow_osc
);
431 at91_clk_unregister_slow_rc_osc(slow_rc
);
434 static const struct clk_slow_bits at91sam9x5_bits
= {
436 .cr_osc32en
= BIT(1),
437 .cr_osc32byp
= BIT(2),
441 static void __init
of_at91sam9x5_sckc_setup(struct device_node
*np
)
443 at91sam9x5_sckc_register(np
, 75, &at91sam9x5_bits
);
445 CLK_OF_DECLARE(at91sam9x5_clk_sckc
, "atmel,at91sam9x5-sckc",
446 of_at91sam9x5_sckc_setup
);
448 static void __init
of_sama5d3_sckc_setup(struct device_node
*np
)
450 at91sam9x5_sckc_register(np
, 500, &at91sam9x5_bits
);
452 CLK_OF_DECLARE(sama5d3_clk_sckc
, "atmel,sama5d3-sckc",
453 of_sama5d3_sckc_setup
);
455 static const struct clk_slow_bits at91sam9x60_bits
= {
456 .cr_osc32en
= BIT(1),
457 .cr_osc32byp
= BIT(2),
458 .cr_oscsel
= BIT(24),
461 static void __init
of_sam9x60_sckc_setup(struct device_node
*np
)
463 void __iomem
*regbase
= of_iomap(np
, 0);
464 struct clk_hw_onecell_data
*clk_data
;
465 struct clk_hw
*slow_rc
, *slow_osc
;
466 const char *xtal_name
;
467 const char *parent_names
[2] = { "slow_rc_osc", "slow_osc" };
474 slow_rc
= clk_hw_register_fixed_rate_with_accuracy(NULL
, parent_names
[0],
480 xtal_name
= of_clk_get_parent_name(np
, 0);
482 goto unregister_slow_rc
;
484 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
485 slow_osc
= at91_clk_register_slow_osc(regbase
, parent_names
[1],
486 xtal_name
, 5000000, bypass
,
488 if (IS_ERR(slow_osc
))
489 goto unregister_slow_rc
;
491 clk_data
= kzalloc(struct_size(clk_data
, hws
, 2), GFP_KERNEL
);
493 goto unregister_slow_osc
;
495 /* MD_SLCK and TD_SLCK. */
497 clk_data
->hws
[0] = clk_hw_register_fixed_rate(NULL
, "md_slck",
500 if (IS_ERR(clk_data
->hws
[0]))
503 clk_data
->hws
[1] = at91_clk_register_sam9x5_slow(regbase
, "td_slck",
506 if (IS_ERR(clk_data
->hws
[1]))
507 goto unregister_md_slck
;
509 ret
= of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, clk_data
);
511 goto unregister_td_slck
;
516 at91_clk_unregister_sam9x5_slow(clk_data
->hws
[1]);
518 clk_hw_unregister(clk_data
->hws
[0]);
522 at91_clk_unregister_slow_osc(slow_osc
);
524 clk_hw_unregister(slow_rc
);
526 CLK_OF_DECLARE(sam9x60_clk_sckc
, "microchip,sam9x60-sckc",
527 of_sam9x60_sckc_setup
);
529 static int clk_sama5d4_slow_osc_prepare(struct clk_hw
*hw
)
531 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
537 * Assume that if it has already been selected (for example by the
538 * bootloader), enough time has aready passed.
540 if ((readl(osc
->sckcr
) & osc
->bits
->cr_oscsel
)) {
541 osc
->prepared
= true;
545 if (system_state
< SYSTEM_RUNNING
)
546 udelay(osc
->startup_usec
);
548 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
549 osc
->prepared
= true;
554 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw
*hw
)
556 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
558 return osc
->prepared
;
561 static const struct clk_ops sama5d4_slow_osc_ops
= {
562 .prepare
= clk_sama5d4_slow_osc_prepare
,
563 .is_prepared
= clk_sama5d4_slow_osc_is_prepared
,
566 static const struct clk_slow_bits at91sama5d4_bits
= {
570 static void __init
of_sama5d4_sckc_setup(struct device_node
*np
)
572 void __iomem
*regbase
= of_iomap(np
, 0);
573 struct clk_hw
*slow_rc
, *slowck
;
574 struct clk_sama5d4_slow_osc
*osc
;
575 struct clk_init_data init
;
576 const char *xtal_name
;
577 const char *parent_names
[2] = { "slow_rc_osc", "slow_osc" };
583 slow_rc
= clk_hw_register_fixed_rate_with_accuracy(NULL
,
590 xtal_name
= of_clk_get_parent_name(np
, 0);
592 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
594 goto unregister_slow_rc
;
596 init
.name
= parent_names
[1];
597 init
.ops
= &sama5d4_slow_osc_ops
;
598 init
.parent_names
= &xtal_name
;
599 init
.num_parents
= 1;
600 init
.flags
= CLK_IGNORE_UNUSED
;
602 osc
->hw
.init
= &init
;
603 osc
->sckcr
= regbase
;
604 osc
->startup_usec
= 1200000;
605 osc
->bits
= &at91sama5d4_bits
;
607 ret
= clk_hw_register(NULL
, &osc
->hw
);
609 goto free_slow_osc_data
;
611 slowck
= at91_clk_register_sam9x5_slow(regbase
, "slowck",
615 goto unregister_slow_osc
;
617 ret
= of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, slowck
);
619 goto unregister_slowck
;
624 at91_clk_unregister_sam9x5_slow(slowck
);
626 clk_hw_unregister(&osc
->hw
);
630 clk_hw_unregister(slow_rc
);
632 CLK_OF_DECLARE(sama5d4_clk_sckc
, "atmel,sama5d4-sckc",
633 of_sama5d4_sckc_setup
);