2 * drivers/clk/at91/sckc.c
4 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
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.
13 #include <linux/clk-provider.h>
14 #include <linux/clkdev.h>
15 #include <linux/delay.h>
17 #include <linux/of_address.h>
20 #define SLOW_CLOCK_FREQ 32768
21 #define SLOWCK_SW_CYCLES 5
22 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
25 #define AT91_SCKC_CR 0x00
26 #define AT91_SCKC_RCEN (1 << 0)
27 #define AT91_SCKC_OSC32EN (1 << 1)
28 #define AT91_SCKC_OSC32BYP (1 << 2)
29 #define AT91_SCKC_OSCSEL (1 << 3)
34 unsigned long startup_usec
;
37 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
39 struct clk_sama5d4_slow_osc
{
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 unsigned long frequency
;
52 unsigned long accuracy
;
53 unsigned long startup_usec
;
56 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
58 struct clk_sam9x5_slow
{
64 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
66 static int clk_slow_osc_prepare(struct clk_hw
*hw
)
68 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
69 void __iomem
*sckcr
= osc
->sckcr
;
70 u32 tmp
= readl(sckcr
);
72 if (tmp
& (AT91_SCKC_OSC32BYP
| AT91_SCKC_OSC32EN
))
75 writel(tmp
| AT91_SCKC_OSC32EN
, sckcr
);
77 if (system_state
< SYSTEM_RUNNING
)
78 udelay(osc
->startup_usec
);
80 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
85 static void clk_slow_osc_unprepare(struct clk_hw
*hw
)
87 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
88 void __iomem
*sckcr
= osc
->sckcr
;
89 u32 tmp
= readl(sckcr
);
91 if (tmp
& AT91_SCKC_OSC32BYP
)
94 writel(tmp
& ~AT91_SCKC_OSC32EN
, sckcr
);
97 static int clk_slow_osc_is_prepared(struct clk_hw
*hw
)
99 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
100 void __iomem
*sckcr
= osc
->sckcr
;
101 u32 tmp
= readl(sckcr
);
103 if (tmp
& AT91_SCKC_OSC32BYP
)
106 return !!(tmp
& AT91_SCKC_OSC32EN
);
109 static const struct clk_ops slow_osc_ops
= {
110 .prepare
= clk_slow_osc_prepare
,
111 .unprepare
= clk_slow_osc_unprepare
,
112 .is_prepared
= clk_slow_osc_is_prepared
,
115 static struct clk_hw
* __init
116 at91_clk_register_slow_osc(void __iomem
*sckcr
,
118 const char *parent_name
,
119 unsigned long startup
,
122 struct clk_slow_osc
*osc
;
124 struct clk_init_data init
;
127 if (!sckcr
|| !name
|| !parent_name
)
128 return ERR_PTR(-EINVAL
);
130 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
132 return ERR_PTR(-ENOMEM
);
135 init
.ops
= &slow_osc_ops
;
136 init
.parent_names
= &parent_name
;
137 init
.num_parents
= 1;
138 init
.flags
= CLK_IGNORE_UNUSED
;
140 osc
->hw
.init
= &init
;
142 osc
->startup_usec
= startup
;
145 writel((readl(sckcr
) & ~AT91_SCKC_OSC32EN
) | AT91_SCKC_OSC32BYP
,
149 ret
= clk_hw_register(NULL
, &osc
->hw
);
159 of_at91sam9x5_clk_slow_osc_setup(struct device_node
*np
, void __iomem
*sckcr
)
162 const char *parent_name
;
163 const char *name
= np
->name
;
167 parent_name
= of_clk_get_parent_name(np
, 0);
168 of_property_read_string(np
, "clock-output-names", &name
);
169 of_property_read_u32(np
, "atmel,startup-time-usec", &startup
);
170 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
172 hw
= at91_clk_register_slow_osc(sckcr
, name
, parent_name
, startup
,
177 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
180 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw
*hw
,
181 unsigned long parent_rate
)
183 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
185 return osc
->frequency
;
188 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw
*hw
,
189 unsigned long parent_acc
)
191 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
193 return osc
->accuracy
;
196 static int clk_slow_rc_osc_prepare(struct clk_hw
*hw
)
198 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
199 void __iomem
*sckcr
= osc
->sckcr
;
201 writel(readl(sckcr
) | AT91_SCKC_RCEN
, sckcr
);
203 if (system_state
< SYSTEM_RUNNING
)
204 udelay(osc
->startup_usec
);
206 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
211 static void clk_slow_rc_osc_unprepare(struct clk_hw
*hw
)
213 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
214 void __iomem
*sckcr
= osc
->sckcr
;
216 writel(readl(sckcr
) & ~AT91_SCKC_RCEN
, sckcr
);
219 static int clk_slow_rc_osc_is_prepared(struct clk_hw
*hw
)
221 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
223 return !!(readl(osc
->sckcr
) & AT91_SCKC_RCEN
);
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
,
234 static struct clk_hw
* __init
235 at91_clk_register_slow_rc_osc(void __iomem
*sckcr
,
237 unsigned long frequency
,
238 unsigned long accuracy
,
239 unsigned long startup
)
241 struct clk_slow_rc_osc
*osc
;
243 struct clk_init_data init
;
247 return ERR_PTR(-EINVAL
);
249 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
251 return ERR_PTR(-ENOMEM
);
254 init
.ops
= &slow_rc_osc_ops
;
255 init
.parent_names
= NULL
;
256 init
.num_parents
= 0;
257 init
.flags
= CLK_IGNORE_UNUSED
;
259 osc
->hw
.init
= &init
;
261 osc
->frequency
= frequency
;
262 osc
->accuracy
= accuracy
;
263 osc
->startup_usec
= startup
;
266 ret
= clk_hw_register(NULL
, &osc
->hw
);
276 of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node
*np
, void __iomem
*sckcr
)
282 const char *name
= np
->name
;
284 of_property_read_string(np
, "clock-output-names", &name
);
285 of_property_read_u32(np
, "clock-frequency", &frequency
);
286 of_property_read_u32(np
, "clock-accuracy", &accuracy
);
287 of_property_read_u32(np
, "atmel,startup-time-usec", &startup
);
289 hw
= at91_clk_register_slow_rc_osc(sckcr
, name
, frequency
, accuracy
,
294 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
297 static int clk_sam9x5_slow_set_parent(struct clk_hw
*hw
, u8 index
)
299 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
300 void __iomem
*sckcr
= slowck
->sckcr
;
308 if ((!index
&& !(tmp
& AT91_SCKC_OSCSEL
)) ||
309 (index
&& (tmp
& AT91_SCKC_OSCSEL
)))
313 tmp
|= AT91_SCKC_OSCSEL
;
315 tmp
&= ~AT91_SCKC_OSCSEL
;
319 if (system_state
< SYSTEM_RUNNING
)
320 udelay(SLOWCK_SW_TIME_USEC
);
322 usleep_range(SLOWCK_SW_TIME_USEC
, SLOWCK_SW_TIME_USEC
+ 1);
327 static u8
clk_sam9x5_slow_get_parent(struct clk_hw
*hw
)
329 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
331 return !!(readl(slowck
->sckcr
) & AT91_SCKC_OSCSEL
);
334 static const struct clk_ops sam9x5_slow_ops
= {
335 .set_parent
= clk_sam9x5_slow_set_parent
,
336 .get_parent
= clk_sam9x5_slow_get_parent
,
339 static struct clk_hw
* __init
340 at91_clk_register_sam9x5_slow(void __iomem
*sckcr
,
342 const char **parent_names
,
345 struct clk_sam9x5_slow
*slowck
;
347 struct clk_init_data init
;
350 if (!sckcr
|| !name
|| !parent_names
|| !num_parents
)
351 return ERR_PTR(-EINVAL
);
353 slowck
= kzalloc(sizeof(*slowck
), GFP_KERNEL
);
355 return ERR_PTR(-ENOMEM
);
358 init
.ops
= &sam9x5_slow_ops
;
359 init
.parent_names
= parent_names
;
360 init
.num_parents
= num_parents
;
363 slowck
->hw
.init
= &init
;
364 slowck
->sckcr
= sckcr
;
365 slowck
->parent
= !!(readl(sckcr
) & AT91_SCKC_OSCSEL
);
368 ret
= clk_hw_register(NULL
, &slowck
->hw
);
378 of_at91sam9x5_clk_slow_setup(struct device_node
*np
, void __iomem
*sckcr
)
381 const char *parent_names
[2];
382 unsigned int num_parents
;
383 const char *name
= np
->name
;
385 num_parents
= of_clk_get_parent_count(np
);
386 if (num_parents
== 0 || num_parents
> 2)
389 of_clk_parent_fill(np
, parent_names
, num_parents
);
391 of_property_read_string(np
, "clock-output-names", &name
);
393 hw
= at91_clk_register_sam9x5_slow(sckcr
, name
, parent_names
,
398 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
401 static const struct of_device_id sckc_clk_ids
[] __initconst
= {
404 .compatible
= "atmel,at91sam9x5-clk-slow-osc",
405 .data
= of_at91sam9x5_clk_slow_osc_setup
,
408 .compatible
= "atmel,at91sam9x5-clk-slow-rc-osc",
409 .data
= of_at91sam9x5_clk_slow_rc_osc_setup
,
412 .compatible
= "atmel,at91sam9x5-clk-slow",
413 .data
= of_at91sam9x5_clk_slow_setup
,
418 static void __init
of_at91sam9x5_sckc_setup(struct device_node
*np
)
420 struct device_node
*childnp
;
421 void (*clk_setup
)(struct device_node
*, void __iomem
*);
422 const struct of_device_id
*clk_id
;
423 void __iomem
*regbase
= of_iomap(np
, 0);
428 for_each_child_of_node(np
, childnp
) {
429 clk_id
= of_match_node(sckc_clk_ids
, childnp
);
432 clk_setup
= clk_id
->data
;
433 clk_setup(childnp
, regbase
);
436 CLK_OF_DECLARE(at91sam9x5_clk_sckc
, "atmel,at91sam9x5-sckc",
437 of_at91sam9x5_sckc_setup
);
439 static int clk_sama5d4_slow_osc_prepare(struct clk_hw
*hw
)
441 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
447 * Assume that if it has already been selected (for example by the
448 * bootloader), enough time has aready passed.
450 if ((readl(osc
->sckcr
) & AT91_SCKC_OSCSEL
)) {
451 osc
->prepared
= true;
455 if (system_state
< SYSTEM_RUNNING
)
456 udelay(osc
->startup_usec
);
458 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
459 osc
->prepared
= true;
464 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw
*hw
)
466 struct clk_sama5d4_slow_osc
*osc
= to_clk_sama5d4_slow_osc(hw
);
468 return osc
->prepared
;
471 static const struct clk_ops sama5d4_slow_osc_ops
= {
472 .prepare
= clk_sama5d4_slow_osc_prepare
,
473 .is_prepared
= clk_sama5d4_slow_osc_is_prepared
,
476 static void __init
of_sama5d4_sckc_setup(struct device_node
*np
)
478 void __iomem
*regbase
= of_iomap(np
, 0);
480 struct clk_sama5d4_slow_osc
*osc
;
481 struct clk_init_data init
;
482 const char *xtal_name
;
483 const char *parent_names
[2] = { "slow_rc_osc", "slow_osc" };
490 hw
= clk_hw_register_fixed_rate_with_accuracy(NULL
, parent_names
[0],
496 xtal_name
= of_clk_get_parent_name(np
, 0);
498 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
500 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
504 init
.name
= parent_names
[1];
505 init
.ops
= &sama5d4_slow_osc_ops
;
506 init
.parent_names
= &xtal_name
;
507 init
.num_parents
= 1;
508 init
.flags
= CLK_IGNORE_UNUSED
;
510 osc
->hw
.init
= &init
;
511 osc
->sckcr
= regbase
;
512 osc
->startup_usec
= 1200000;
515 writel((readl(regbase
) | AT91_SCKC_OSC32BYP
), regbase
);
518 ret
= clk_hw_register(NULL
, &osc
->hw
);
524 hw
= at91_clk_register_sam9x5_slow(regbase
, "slowck", parent_names
, 2);
528 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
530 CLK_OF_DECLARE(sama5d4_clk_sckc
, "atmel,sama5d4-sckc",
531 of_sama5d4_sckc_setup
);