2 * drivers/clk/at91/clk-slow.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/clk/at91_pmc.h>
16 #include <linux/delay.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/regmap.h>
24 #define SLOW_CLOCK_FREQ 32768
25 #define SLOWCK_SW_CYCLES 5
26 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
29 #define AT91_SCKC_CR 0x00
30 #define AT91_SCKC_RCEN (1 << 0)
31 #define AT91_SCKC_OSC32EN (1 << 1)
32 #define AT91_SCKC_OSC32BYP (1 << 2)
33 #define AT91_SCKC_OSCSEL (1 << 3)
38 unsigned long startup_usec
;
41 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
43 struct clk_slow_rc_osc
{
46 unsigned long frequency
;
47 unsigned long accuracy
;
48 unsigned long startup_usec
;
51 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
53 struct clk_sam9260_slow
{
55 struct regmap
*regmap
;
58 #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
60 struct clk_sam9x5_slow
{
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
& AT91_SCKC_OSC32BYP
)
77 writel(tmp
| AT91_SCKC_OSC32EN
, sckcr
);
79 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
84 static void clk_slow_osc_unprepare(struct clk_hw
*hw
)
86 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
87 void __iomem
*sckcr
= osc
->sckcr
;
88 u32 tmp
= readl(sckcr
);
90 if (tmp
& AT91_SCKC_OSC32BYP
)
93 writel(tmp
& ~AT91_SCKC_OSC32EN
, sckcr
);
96 static int clk_slow_osc_is_prepared(struct clk_hw
*hw
)
98 struct clk_slow_osc
*osc
= to_clk_slow_osc(hw
);
99 void __iomem
*sckcr
= osc
->sckcr
;
100 u32 tmp
= readl(sckcr
);
102 if (tmp
& AT91_SCKC_OSC32BYP
)
105 return !!(tmp
& AT91_SCKC_OSC32EN
);
108 static const struct clk_ops slow_osc_ops
= {
109 .prepare
= clk_slow_osc_prepare
,
110 .unprepare
= clk_slow_osc_unprepare
,
111 .is_prepared
= clk_slow_osc_is_prepared
,
114 static struct clk
* __init
115 at91_clk_register_slow_osc(void __iomem
*sckcr
,
117 const char *parent_name
,
118 unsigned long startup
,
121 struct clk_slow_osc
*osc
;
122 struct clk
*clk
= NULL
;
123 struct clk_init_data init
;
125 if (!sckcr
|| !name
|| !parent_name
)
126 return ERR_PTR(-EINVAL
);
128 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
130 return ERR_PTR(-ENOMEM
);
133 init
.ops
= &slow_osc_ops
;
134 init
.parent_names
= &parent_name
;
135 init
.num_parents
= 1;
136 init
.flags
= CLK_IGNORE_UNUSED
;
138 osc
->hw
.init
= &init
;
140 osc
->startup_usec
= startup
;
143 writel((readl(sckcr
) & ~AT91_SCKC_OSC32EN
) | AT91_SCKC_OSC32BYP
,
146 clk
= clk_register(NULL
, &osc
->hw
);
153 void __init
of_at91sam9x5_clk_slow_osc_setup(struct device_node
*np
,
157 const char *parent_name
;
158 const char *name
= np
->name
;
162 parent_name
= of_clk_get_parent_name(np
, 0);
163 of_property_read_string(np
, "clock-output-names", &name
);
164 of_property_read_u32(np
, "atmel,startup-time-usec", &startup
);
165 bypass
= of_property_read_bool(np
, "atmel,osc-bypass");
167 clk
= at91_clk_register_slow_osc(sckcr
, name
, parent_name
, startup
,
172 of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
175 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw
*hw
,
176 unsigned long parent_rate
)
178 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
180 return osc
->frequency
;
183 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw
*hw
,
184 unsigned long parent_acc
)
186 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
188 return osc
->accuracy
;
191 static int clk_slow_rc_osc_prepare(struct clk_hw
*hw
)
193 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
194 void __iomem
*sckcr
= osc
->sckcr
;
196 writel(readl(sckcr
) | AT91_SCKC_RCEN
, sckcr
);
198 usleep_range(osc
->startup_usec
, osc
->startup_usec
+ 1);
203 static void clk_slow_rc_osc_unprepare(struct clk_hw
*hw
)
205 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
206 void __iomem
*sckcr
= osc
->sckcr
;
208 writel(readl(sckcr
) & ~AT91_SCKC_RCEN
, sckcr
);
211 static int clk_slow_rc_osc_is_prepared(struct clk_hw
*hw
)
213 struct clk_slow_rc_osc
*osc
= to_clk_slow_rc_osc(hw
);
215 return !!(readl(osc
->sckcr
) & AT91_SCKC_RCEN
);
218 static const struct clk_ops slow_rc_osc_ops
= {
219 .prepare
= clk_slow_rc_osc_prepare
,
220 .unprepare
= clk_slow_rc_osc_unprepare
,
221 .is_prepared
= clk_slow_rc_osc_is_prepared
,
222 .recalc_rate
= clk_slow_rc_osc_recalc_rate
,
223 .recalc_accuracy
= clk_slow_rc_osc_recalc_accuracy
,
226 static struct clk
* __init
227 at91_clk_register_slow_rc_osc(void __iomem
*sckcr
,
229 unsigned long frequency
,
230 unsigned long accuracy
,
231 unsigned long startup
)
233 struct clk_slow_rc_osc
*osc
;
234 struct clk
*clk
= NULL
;
235 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
;
252 osc
->frequency
= frequency
;
253 osc
->accuracy
= accuracy
;
254 osc
->startup_usec
= startup
;
256 clk
= clk_register(NULL
, &osc
->hw
);
263 void __init
of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node
*np
,
270 const char *name
= np
->name
;
272 of_property_read_string(np
, "clock-output-names", &name
);
273 of_property_read_u32(np
, "clock-frequency", &frequency
);
274 of_property_read_u32(np
, "clock-accuracy", &accuracy
);
275 of_property_read_u32(np
, "atmel,startup-time-usec", &startup
);
277 clk
= at91_clk_register_slow_rc_osc(sckcr
, name
, frequency
, accuracy
,
282 of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
285 static int clk_sam9x5_slow_set_parent(struct clk_hw
*hw
, u8 index
)
287 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
288 void __iomem
*sckcr
= slowck
->sckcr
;
296 if ((!index
&& !(tmp
& AT91_SCKC_OSCSEL
)) ||
297 (index
&& (tmp
& AT91_SCKC_OSCSEL
)))
301 tmp
|= AT91_SCKC_OSCSEL
;
303 tmp
&= ~AT91_SCKC_OSCSEL
;
307 usleep_range(SLOWCK_SW_TIME_USEC
, SLOWCK_SW_TIME_USEC
+ 1);
312 static u8
clk_sam9x5_slow_get_parent(struct clk_hw
*hw
)
314 struct clk_sam9x5_slow
*slowck
= to_clk_sam9x5_slow(hw
);
316 return !!(readl(slowck
->sckcr
) & AT91_SCKC_OSCSEL
);
319 static const struct clk_ops sam9x5_slow_ops
= {
320 .set_parent
= clk_sam9x5_slow_set_parent
,
321 .get_parent
= clk_sam9x5_slow_get_parent
,
324 static struct clk
* __init
325 at91_clk_register_sam9x5_slow(void __iomem
*sckcr
,
327 const char **parent_names
,
330 struct clk_sam9x5_slow
*slowck
;
331 struct clk
*clk
= NULL
;
332 struct clk_init_data init
;
334 if (!sckcr
|| !name
|| !parent_names
|| !num_parents
)
335 return ERR_PTR(-EINVAL
);
337 slowck
= kzalloc(sizeof(*slowck
), GFP_KERNEL
);
339 return ERR_PTR(-ENOMEM
);
342 init
.ops
= &sam9x5_slow_ops
;
343 init
.parent_names
= parent_names
;
344 init
.num_parents
= num_parents
;
347 slowck
->hw
.init
= &init
;
348 slowck
->sckcr
= sckcr
;
349 slowck
->parent
= !!(readl(sckcr
) & AT91_SCKC_OSCSEL
);
351 clk
= clk_register(NULL
, &slowck
->hw
);
358 void __init
of_at91sam9x5_clk_slow_setup(struct device_node
*np
,
362 const char *parent_names
[2];
363 unsigned int num_parents
;
364 const char *name
= np
->name
;
366 num_parents
= of_clk_get_parent_count(np
);
367 if (num_parents
== 0 || num_parents
> 2)
370 of_clk_parent_fill(np
, parent_names
, num_parents
);
372 of_property_read_string(np
, "clock-output-names", &name
);
374 clk
= at91_clk_register_sam9x5_slow(sckcr
, name
, parent_names
,
379 of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
382 static u8
clk_sam9260_slow_get_parent(struct clk_hw
*hw
)
384 struct clk_sam9260_slow
*slowck
= to_clk_sam9260_slow(hw
);
387 regmap_read(slowck
->regmap
, AT91_PMC_SR
, &status
);
389 return status
& AT91_PMC_OSCSEL
? 1 : 0;
392 static const struct clk_ops sam9260_slow_ops
= {
393 .get_parent
= clk_sam9260_slow_get_parent
,
396 static struct clk
* __init
397 at91_clk_register_sam9260_slow(struct regmap
*regmap
,
399 const char **parent_names
,
402 struct clk_sam9260_slow
*slowck
;
403 struct clk
*clk
= NULL
;
404 struct clk_init_data init
;
407 return ERR_PTR(-EINVAL
);
409 if (!parent_names
|| !num_parents
)
410 return ERR_PTR(-EINVAL
);
412 slowck
= kzalloc(sizeof(*slowck
), GFP_KERNEL
);
414 return ERR_PTR(-ENOMEM
);
417 init
.ops
= &sam9260_slow_ops
;
418 init
.parent_names
= parent_names
;
419 init
.num_parents
= num_parents
;
422 slowck
->hw
.init
= &init
;
423 slowck
->regmap
= regmap
;
425 clk
= clk_register(NULL
, &slowck
->hw
);
432 static void __init
of_at91sam9260_clk_slow_setup(struct device_node
*np
)
435 const char *parent_names
[2];
436 unsigned int num_parents
;
437 const char *name
= np
->name
;
438 struct regmap
*regmap
;
440 num_parents
= of_clk_get_parent_count(np
);
441 if (num_parents
!= 2)
444 of_clk_parent_fill(np
, parent_names
, num_parents
);
445 regmap
= syscon_node_to_regmap(of_get_parent(np
));
449 of_property_read_string(np
, "clock-output-names", &name
);
451 clk
= at91_clk_register_sam9260_slow(regmap
, name
, parent_names
,
456 of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
459 CLK_OF_DECLARE(at91sam9260_clk_slow
, "atmel,at91sam9260-clk-slow",
460 of_at91sam9260_clk_slow_setup
);