1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
6 #include <linux/clk-provider.h>
7 #include <linux/clkdev.h>
8 #include <linux/clk/at91_pmc.h>
9 #include <linux/delay.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
15 #define SLOW_CLOCK_FREQ 32768
17 #define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \
19 #define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
20 #define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
22 #define MOR_KEY_MASK (0xff << 16)
24 #define clk_main_parent_select(s) (((s) & \
26 AT91_PMC_OSCBYPASS)) ? 1 : 0)
30 struct regmap
*regmap
;
33 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
35 struct clk_main_rc_osc
{
37 struct regmap
*regmap
;
38 unsigned long frequency
;
39 unsigned long accuracy
;
42 #define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
44 struct clk_rm9200_main
{
46 struct regmap
*regmap
;
49 #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
51 struct clk_sam9x5_main
{
53 struct regmap
*regmap
;
57 #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
59 static inline bool clk_main_osc_ready(struct regmap
*regmap
)
63 regmap_read(regmap
, AT91_PMC_SR
, &status
);
65 return status
& AT91_PMC_MOSCS
;
68 static int clk_main_osc_prepare(struct clk_hw
*hw
)
70 struct clk_main_osc
*osc
= to_clk_main_osc(hw
);
71 struct regmap
*regmap
= osc
->regmap
;
74 regmap_read(regmap
, AT91_CKGR_MOR
, &tmp
);
77 if (tmp
& AT91_PMC_OSCBYPASS
)
80 if (!(tmp
& AT91_PMC_MOSCEN
)) {
81 tmp
|= AT91_PMC_MOSCEN
| AT91_PMC_KEY
;
82 regmap_write(regmap
, AT91_CKGR_MOR
, tmp
);
85 while (!clk_main_osc_ready(regmap
))
91 static void clk_main_osc_unprepare(struct clk_hw
*hw
)
93 struct clk_main_osc
*osc
= to_clk_main_osc(hw
);
94 struct regmap
*regmap
= osc
->regmap
;
97 regmap_read(regmap
, AT91_CKGR_MOR
, &tmp
);
98 if (tmp
& AT91_PMC_OSCBYPASS
)
101 if (!(tmp
& AT91_PMC_MOSCEN
))
104 tmp
&= ~(AT91_PMC_KEY
| AT91_PMC_MOSCEN
);
105 regmap_write(regmap
, AT91_CKGR_MOR
, tmp
| AT91_PMC_KEY
);
108 static int clk_main_osc_is_prepared(struct clk_hw
*hw
)
110 struct clk_main_osc
*osc
= to_clk_main_osc(hw
);
111 struct regmap
*regmap
= osc
->regmap
;
114 regmap_read(regmap
, AT91_CKGR_MOR
, &tmp
);
115 if (tmp
& AT91_PMC_OSCBYPASS
)
118 regmap_read(regmap
, AT91_PMC_SR
, &status
);
120 return (status
& AT91_PMC_MOSCS
) && clk_main_parent_select(tmp
);
123 static const struct clk_ops main_osc_ops
= {
124 .prepare
= clk_main_osc_prepare
,
125 .unprepare
= clk_main_osc_unprepare
,
126 .is_prepared
= clk_main_osc_is_prepared
,
129 struct clk_hw
* __init
130 at91_clk_register_main_osc(struct regmap
*regmap
,
132 const char *parent_name
,
135 struct clk_main_osc
*osc
;
136 struct clk_init_data init
;
140 if (!name
|| !parent_name
)
141 return ERR_PTR(-EINVAL
);
143 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
145 return ERR_PTR(-ENOMEM
);
148 init
.ops
= &main_osc_ops
;
149 init
.parent_names
= &parent_name
;
150 init
.num_parents
= 1;
151 init
.flags
= CLK_IGNORE_UNUSED
;
153 osc
->hw
.init
= &init
;
154 osc
->regmap
= regmap
;
157 regmap_update_bits(regmap
,
158 AT91_CKGR_MOR
, MOR_KEY_MASK
|
160 AT91_PMC_OSCBYPASS
| AT91_PMC_KEY
);
163 ret
= clk_hw_register(NULL
, &osc
->hw
);
172 static bool clk_main_rc_osc_ready(struct regmap
*regmap
)
176 regmap_read(regmap
, AT91_PMC_SR
, &status
);
178 return !!(status
& AT91_PMC_MOSCRCS
);
181 static int clk_main_rc_osc_prepare(struct clk_hw
*hw
)
183 struct clk_main_rc_osc
*osc
= to_clk_main_rc_osc(hw
);
184 struct regmap
*regmap
= osc
->regmap
;
187 regmap_read(regmap
, AT91_CKGR_MOR
, &mor
);
189 if (!(mor
& AT91_PMC_MOSCRCEN
))
190 regmap_update_bits(regmap
, AT91_CKGR_MOR
,
191 MOR_KEY_MASK
| AT91_PMC_MOSCRCEN
,
192 AT91_PMC_MOSCRCEN
| AT91_PMC_KEY
);
194 while (!clk_main_rc_osc_ready(regmap
))
200 static void clk_main_rc_osc_unprepare(struct clk_hw
*hw
)
202 struct clk_main_rc_osc
*osc
= to_clk_main_rc_osc(hw
);
203 struct regmap
*regmap
= osc
->regmap
;
206 regmap_read(regmap
, AT91_CKGR_MOR
, &mor
);
208 if (!(mor
& AT91_PMC_MOSCRCEN
))
211 regmap_update_bits(regmap
, AT91_CKGR_MOR
,
212 MOR_KEY_MASK
| AT91_PMC_MOSCRCEN
, AT91_PMC_KEY
);
215 static int clk_main_rc_osc_is_prepared(struct clk_hw
*hw
)
217 struct clk_main_rc_osc
*osc
= to_clk_main_rc_osc(hw
);
218 struct regmap
*regmap
= osc
->regmap
;
219 unsigned int mor
, status
;
221 regmap_read(regmap
, AT91_CKGR_MOR
, &mor
);
222 regmap_read(regmap
, AT91_PMC_SR
, &status
);
224 return (mor
& AT91_PMC_MOSCRCEN
) && (status
& AT91_PMC_MOSCRCS
);
227 static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw
*hw
,
228 unsigned long parent_rate
)
230 struct clk_main_rc_osc
*osc
= to_clk_main_rc_osc(hw
);
232 return osc
->frequency
;
235 static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw
*hw
,
236 unsigned long parent_acc
)
238 struct clk_main_rc_osc
*osc
= to_clk_main_rc_osc(hw
);
240 return osc
->accuracy
;
243 static const struct clk_ops main_rc_osc_ops
= {
244 .prepare
= clk_main_rc_osc_prepare
,
245 .unprepare
= clk_main_rc_osc_unprepare
,
246 .is_prepared
= clk_main_rc_osc_is_prepared
,
247 .recalc_rate
= clk_main_rc_osc_recalc_rate
,
248 .recalc_accuracy
= clk_main_rc_osc_recalc_accuracy
,
251 struct clk_hw
* __init
252 at91_clk_register_main_rc_osc(struct regmap
*regmap
,
254 u32 frequency
, u32 accuracy
)
256 struct clk_main_rc_osc
*osc
;
257 struct clk_init_data init
;
261 if (!name
|| !frequency
)
262 return ERR_PTR(-EINVAL
);
264 osc
= kzalloc(sizeof(*osc
), GFP_KERNEL
);
266 return ERR_PTR(-ENOMEM
);
269 init
.ops
= &main_rc_osc_ops
;
270 init
.parent_names
= NULL
;
271 init
.num_parents
= 0;
272 init
.flags
= CLK_IGNORE_UNUSED
;
274 osc
->hw
.init
= &init
;
275 osc
->regmap
= regmap
;
276 osc
->frequency
= frequency
;
277 osc
->accuracy
= accuracy
;
280 ret
= clk_hw_register(NULL
, hw
);
289 static int clk_main_probe_frequency(struct regmap
*regmap
)
291 unsigned long prep_time
, timeout
;
294 timeout
= jiffies
+ usecs_to_jiffies(MAINFRDY_TIMEOUT
);
297 regmap_read(regmap
, AT91_CKGR_MCFR
, &mcfr
);
298 if (mcfr
& AT91_PMC_MAINRDY
)
300 if (system_state
< SYSTEM_RUNNING
)
301 udelay(MAINF_LOOP_MIN_WAIT
);
303 usleep_range(MAINF_LOOP_MIN_WAIT
, MAINF_LOOP_MAX_WAIT
);
304 } while (time_before(prep_time
, timeout
));
309 static unsigned long clk_main_recalc_rate(struct regmap
*regmap
,
310 unsigned long parent_rate
)
317 pr_warn("Main crystal frequency not set, using approximate value\n");
318 regmap_read(regmap
, AT91_CKGR_MCFR
, &mcfr
);
319 if (!(mcfr
& AT91_PMC_MAINRDY
))
322 return ((mcfr
& AT91_PMC_MAINF
) * SLOW_CLOCK_FREQ
) / MAINF_DIV
;
325 static int clk_rm9200_main_prepare(struct clk_hw
*hw
)
327 struct clk_rm9200_main
*clkmain
= to_clk_rm9200_main(hw
);
329 return clk_main_probe_frequency(clkmain
->regmap
);
332 static int clk_rm9200_main_is_prepared(struct clk_hw
*hw
)
334 struct clk_rm9200_main
*clkmain
= to_clk_rm9200_main(hw
);
337 regmap_read(clkmain
->regmap
, AT91_CKGR_MCFR
, &status
);
339 return !!(status
& AT91_PMC_MAINRDY
);
342 static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw
*hw
,
343 unsigned long parent_rate
)
345 struct clk_rm9200_main
*clkmain
= to_clk_rm9200_main(hw
);
347 return clk_main_recalc_rate(clkmain
->regmap
, parent_rate
);
350 static const struct clk_ops rm9200_main_ops
= {
351 .prepare
= clk_rm9200_main_prepare
,
352 .is_prepared
= clk_rm9200_main_is_prepared
,
353 .recalc_rate
= clk_rm9200_main_recalc_rate
,
356 struct clk_hw
* __init
357 at91_clk_register_rm9200_main(struct regmap
*regmap
,
359 const char *parent_name
)
361 struct clk_rm9200_main
*clkmain
;
362 struct clk_init_data init
;
367 return ERR_PTR(-EINVAL
);
370 return ERR_PTR(-EINVAL
);
372 clkmain
= kzalloc(sizeof(*clkmain
), GFP_KERNEL
);
374 return ERR_PTR(-ENOMEM
);
377 init
.ops
= &rm9200_main_ops
;
378 init
.parent_names
= &parent_name
;
379 init
.num_parents
= 1;
382 clkmain
->hw
.init
= &init
;
383 clkmain
->regmap
= regmap
;
386 ret
= clk_hw_register(NULL
, &clkmain
->hw
);
395 static inline bool clk_sam9x5_main_ready(struct regmap
*regmap
)
399 regmap_read(regmap
, AT91_PMC_SR
, &status
);
401 return !!(status
& AT91_PMC_MOSCSELS
);
404 static int clk_sam9x5_main_prepare(struct clk_hw
*hw
)
406 struct clk_sam9x5_main
*clkmain
= to_clk_sam9x5_main(hw
);
407 struct regmap
*regmap
= clkmain
->regmap
;
409 while (!clk_sam9x5_main_ready(regmap
))
412 return clk_main_probe_frequency(regmap
);
415 static int clk_sam9x5_main_is_prepared(struct clk_hw
*hw
)
417 struct clk_sam9x5_main
*clkmain
= to_clk_sam9x5_main(hw
);
419 return clk_sam9x5_main_ready(clkmain
->regmap
);
422 static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw
*hw
,
423 unsigned long parent_rate
)
425 struct clk_sam9x5_main
*clkmain
= to_clk_sam9x5_main(hw
);
427 return clk_main_recalc_rate(clkmain
->regmap
, parent_rate
);
430 static int clk_sam9x5_main_set_parent(struct clk_hw
*hw
, u8 index
)
432 struct clk_sam9x5_main
*clkmain
= to_clk_sam9x5_main(hw
);
433 struct regmap
*regmap
= clkmain
->regmap
;
439 regmap_read(regmap
, AT91_CKGR_MOR
, &tmp
);
441 if (index
&& !(tmp
& AT91_PMC_MOSCSEL
))
442 tmp
= AT91_PMC_MOSCSEL
;
443 else if (!index
&& (tmp
& AT91_PMC_MOSCSEL
))
448 regmap_update_bits(regmap
, AT91_CKGR_MOR
,
449 AT91_PMC_MOSCSEL
| MOR_KEY_MASK
,
452 while (!clk_sam9x5_main_ready(regmap
))
458 static u8
clk_sam9x5_main_get_parent(struct clk_hw
*hw
)
460 struct clk_sam9x5_main
*clkmain
= to_clk_sam9x5_main(hw
);
463 regmap_read(clkmain
->regmap
, AT91_CKGR_MOR
, &status
);
465 return clk_main_parent_select(status
);
468 static const struct clk_ops sam9x5_main_ops
= {
469 .prepare
= clk_sam9x5_main_prepare
,
470 .is_prepared
= clk_sam9x5_main_is_prepared
,
471 .recalc_rate
= clk_sam9x5_main_recalc_rate
,
472 .set_parent
= clk_sam9x5_main_set_parent
,
473 .get_parent
= clk_sam9x5_main_get_parent
,
476 struct clk_hw
* __init
477 at91_clk_register_sam9x5_main(struct regmap
*regmap
,
479 const char **parent_names
,
482 struct clk_sam9x5_main
*clkmain
;
483 struct clk_init_data init
;
489 return ERR_PTR(-EINVAL
);
491 if (!parent_names
|| !num_parents
)
492 return ERR_PTR(-EINVAL
);
494 clkmain
= kzalloc(sizeof(*clkmain
), GFP_KERNEL
);
496 return ERR_PTR(-ENOMEM
);
499 init
.ops
= &sam9x5_main_ops
;
500 init
.parent_names
= parent_names
;
501 init
.num_parents
= num_parents
;
502 init
.flags
= CLK_SET_PARENT_GATE
;
504 clkmain
->hw
.init
= &init
;
505 clkmain
->regmap
= regmap
;
506 regmap_read(clkmain
->regmap
, AT91_CKGR_MOR
, &status
);
507 clkmain
->parent
= clk_main_parent_select(status
);
510 ret
= clk_hw_register(NULL
, &clkmain
->hw
);