mmc: core: Reset HPI enabled state during re-init and in case of errors
[linux/fpc-iii.git] / drivers / clk / at91 / clk-main.c
blob7ac0facdb28b1b0e76f476da9e7faf54997bae33
1 /*
2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 */
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
14 #include <linux/delay.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/regmap.h>
18 #include "pmc.h"
20 #define SLOW_CLOCK_FREQ 32768
21 #define MAINF_DIV 16
22 #define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \
23 SLOW_CLOCK_FREQ)
24 #define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
25 #define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
27 #define MOR_KEY_MASK (0xff << 16)
29 struct clk_main_osc {
30 struct clk_hw hw;
31 struct regmap *regmap;
34 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
36 struct clk_main_rc_osc {
37 struct clk_hw hw;
38 struct regmap *regmap;
39 unsigned long frequency;
40 unsigned long accuracy;
43 #define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
45 struct clk_rm9200_main {
46 struct clk_hw hw;
47 struct regmap *regmap;
50 #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
52 struct clk_sam9x5_main {
53 struct clk_hw hw;
54 struct regmap *regmap;
55 u8 parent;
58 #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
60 static inline bool clk_main_osc_ready(struct regmap *regmap)
62 unsigned int status;
64 regmap_read(regmap, AT91_PMC_SR, &status);
66 return status & AT91_PMC_MOSCS;
69 static int clk_main_osc_prepare(struct clk_hw *hw)
71 struct clk_main_osc *osc = to_clk_main_osc(hw);
72 struct regmap *regmap = osc->regmap;
73 u32 tmp;
75 regmap_read(regmap, AT91_CKGR_MOR, &tmp);
76 tmp &= ~MOR_KEY_MASK;
78 if (tmp & AT91_PMC_OSCBYPASS)
79 return 0;
81 if (!(tmp & AT91_PMC_MOSCEN)) {
82 tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
83 regmap_write(regmap, AT91_CKGR_MOR, tmp);
86 while (!clk_main_osc_ready(regmap))
87 cpu_relax();
89 return 0;
92 static void clk_main_osc_unprepare(struct clk_hw *hw)
94 struct clk_main_osc *osc = to_clk_main_osc(hw);
95 struct regmap *regmap = osc->regmap;
96 u32 tmp;
98 regmap_read(regmap, AT91_CKGR_MOR, &tmp);
99 if (tmp & AT91_PMC_OSCBYPASS)
100 return;
102 if (!(tmp & AT91_PMC_MOSCEN))
103 return;
105 tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
106 regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
109 static int clk_main_osc_is_prepared(struct clk_hw *hw)
111 struct clk_main_osc *osc = to_clk_main_osc(hw);
112 struct regmap *regmap = osc->regmap;
113 u32 tmp, status;
115 regmap_read(regmap, AT91_CKGR_MOR, &tmp);
116 if (tmp & AT91_PMC_OSCBYPASS)
117 return 1;
119 regmap_read(regmap, AT91_PMC_SR, &status);
121 return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN);
124 static const struct clk_ops main_osc_ops = {
125 .prepare = clk_main_osc_prepare,
126 .unprepare = clk_main_osc_unprepare,
127 .is_prepared = clk_main_osc_is_prepared,
130 struct clk_hw * __init
131 at91_clk_register_main_osc(struct regmap *regmap,
132 const char *name,
133 const char *parent_name,
134 bool bypass)
136 struct clk_main_osc *osc;
137 struct clk_init_data init;
138 struct clk_hw *hw;
139 int ret;
141 if (!name || !parent_name)
142 return ERR_PTR(-EINVAL);
144 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
145 if (!osc)
146 return ERR_PTR(-ENOMEM);
148 init.name = name;
149 init.ops = &main_osc_ops;
150 init.parent_names = &parent_name;
151 init.num_parents = 1;
152 init.flags = CLK_IGNORE_UNUSED;
154 osc->hw.init = &init;
155 osc->regmap = regmap;
157 if (bypass)
158 regmap_update_bits(regmap,
159 AT91_CKGR_MOR, MOR_KEY_MASK |
160 AT91_PMC_MOSCEN,
161 AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
163 hw = &osc->hw;
164 ret = clk_hw_register(NULL, &osc->hw);
165 if (ret) {
166 kfree(osc);
167 hw = ERR_PTR(ret);
170 return hw;
173 static bool clk_main_rc_osc_ready(struct regmap *regmap)
175 unsigned int status;
177 regmap_read(regmap, AT91_PMC_SR, &status);
179 return status & AT91_PMC_MOSCRCS;
182 static int clk_main_rc_osc_prepare(struct clk_hw *hw)
184 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
185 struct regmap *regmap = osc->regmap;
186 unsigned int mor;
188 regmap_read(regmap, AT91_CKGR_MOR, &mor);
190 if (!(mor & AT91_PMC_MOSCRCEN))
191 regmap_update_bits(regmap, AT91_CKGR_MOR,
192 MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
193 AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
195 while (!clk_main_rc_osc_ready(regmap))
196 cpu_relax();
198 return 0;
201 static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
203 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
204 struct regmap *regmap = osc->regmap;
205 unsigned int mor;
207 regmap_read(regmap, AT91_CKGR_MOR, &mor);
209 if (!(mor & AT91_PMC_MOSCRCEN))
210 return;
212 regmap_update_bits(regmap, AT91_CKGR_MOR,
213 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
216 static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
218 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
219 struct regmap *regmap = osc->regmap;
220 unsigned int mor, status;
222 regmap_read(regmap, AT91_CKGR_MOR, &mor);
223 regmap_read(regmap, AT91_PMC_SR, &status);
225 return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
228 static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
229 unsigned long parent_rate)
231 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
233 return osc->frequency;
236 static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
237 unsigned long parent_acc)
239 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
241 return osc->accuracy;
244 static const struct clk_ops main_rc_osc_ops = {
245 .prepare = clk_main_rc_osc_prepare,
246 .unprepare = clk_main_rc_osc_unprepare,
247 .is_prepared = clk_main_rc_osc_is_prepared,
248 .recalc_rate = clk_main_rc_osc_recalc_rate,
249 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
252 struct clk_hw * __init
253 at91_clk_register_main_rc_osc(struct regmap *regmap,
254 const char *name,
255 u32 frequency, u32 accuracy)
257 struct clk_main_rc_osc *osc;
258 struct clk_init_data init;
259 struct clk_hw *hw;
260 int ret;
262 if (!name || !frequency)
263 return ERR_PTR(-EINVAL);
265 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
266 if (!osc)
267 return ERR_PTR(-ENOMEM);
269 init.name = name;
270 init.ops = &main_rc_osc_ops;
271 init.parent_names = NULL;
272 init.num_parents = 0;
273 init.flags = CLK_IGNORE_UNUSED;
275 osc->hw.init = &init;
276 osc->regmap = regmap;
277 osc->frequency = frequency;
278 osc->accuracy = accuracy;
280 hw = &osc->hw;
281 ret = clk_hw_register(NULL, hw);
282 if (ret) {
283 kfree(osc);
284 hw = ERR_PTR(ret);
287 return hw;
290 static int clk_main_probe_frequency(struct regmap *regmap)
292 unsigned long prep_time, timeout;
293 unsigned int mcfr;
295 timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
296 do {
297 prep_time = jiffies;
298 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
299 if (mcfr & AT91_PMC_MAINRDY)
300 return 0;
301 usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
302 } while (time_before(prep_time, timeout));
304 return -ETIMEDOUT;
307 static unsigned long clk_main_recalc_rate(struct regmap *regmap,
308 unsigned long parent_rate)
310 unsigned int mcfr;
312 if (parent_rate)
313 return parent_rate;
315 pr_warn("Main crystal frequency not set, using approximate value\n");
316 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
317 if (!(mcfr & AT91_PMC_MAINRDY))
318 return 0;
320 return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
323 static int clk_rm9200_main_prepare(struct clk_hw *hw)
325 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
327 return clk_main_probe_frequency(clkmain->regmap);
330 static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
332 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
333 unsigned int status;
335 regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
337 return status & AT91_PMC_MAINRDY ? 1 : 0;
340 static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
341 unsigned long parent_rate)
343 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
345 return clk_main_recalc_rate(clkmain->regmap, parent_rate);
348 static const struct clk_ops rm9200_main_ops = {
349 .prepare = clk_rm9200_main_prepare,
350 .is_prepared = clk_rm9200_main_is_prepared,
351 .recalc_rate = clk_rm9200_main_recalc_rate,
354 struct clk_hw * __init
355 at91_clk_register_rm9200_main(struct regmap *regmap,
356 const char *name,
357 const char *parent_name)
359 struct clk_rm9200_main *clkmain;
360 struct clk_init_data init;
361 struct clk_hw *hw;
362 int ret;
364 if (!name)
365 return ERR_PTR(-EINVAL);
367 if (!parent_name)
368 return ERR_PTR(-EINVAL);
370 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
371 if (!clkmain)
372 return ERR_PTR(-ENOMEM);
374 init.name = name;
375 init.ops = &rm9200_main_ops;
376 init.parent_names = &parent_name;
377 init.num_parents = 1;
378 init.flags = 0;
380 clkmain->hw.init = &init;
381 clkmain->regmap = regmap;
383 hw = &clkmain->hw;
384 ret = clk_hw_register(NULL, &clkmain->hw);
385 if (ret) {
386 kfree(clkmain);
387 hw = ERR_PTR(ret);
390 return hw;
393 static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
395 unsigned int status;
397 regmap_read(regmap, AT91_PMC_SR, &status);
399 return status & AT91_PMC_MOSCSELS ? 1 : 0;
402 static int clk_sam9x5_main_prepare(struct clk_hw *hw)
404 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
405 struct regmap *regmap = clkmain->regmap;
407 while (!clk_sam9x5_main_ready(regmap))
408 cpu_relax();
410 return clk_main_probe_frequency(regmap);
413 static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
415 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
417 return clk_sam9x5_main_ready(clkmain->regmap);
420 static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
421 unsigned long parent_rate)
423 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
425 return clk_main_recalc_rate(clkmain->regmap, parent_rate);
428 static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
430 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
431 struct regmap *regmap = clkmain->regmap;
432 unsigned int tmp;
434 if (index > 1)
435 return -EINVAL;
437 regmap_read(regmap, AT91_CKGR_MOR, &tmp);
438 tmp &= ~MOR_KEY_MASK;
440 if (index && !(tmp & AT91_PMC_MOSCSEL))
441 regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
442 else if (!index && (tmp & AT91_PMC_MOSCSEL))
443 regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
445 while (!clk_sam9x5_main_ready(regmap))
446 cpu_relax();
448 return 0;
451 static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
453 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
454 unsigned int status;
456 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
458 return status & AT91_PMC_MOSCEN ? 1 : 0;
461 static const struct clk_ops sam9x5_main_ops = {
462 .prepare = clk_sam9x5_main_prepare,
463 .is_prepared = clk_sam9x5_main_is_prepared,
464 .recalc_rate = clk_sam9x5_main_recalc_rate,
465 .set_parent = clk_sam9x5_main_set_parent,
466 .get_parent = clk_sam9x5_main_get_parent,
469 struct clk_hw * __init
470 at91_clk_register_sam9x5_main(struct regmap *regmap,
471 const char *name,
472 const char **parent_names,
473 int num_parents)
475 struct clk_sam9x5_main *clkmain;
476 struct clk_init_data init;
477 unsigned int status;
478 struct clk_hw *hw;
479 int ret;
481 if (!name)
482 return ERR_PTR(-EINVAL);
484 if (!parent_names || !num_parents)
485 return ERR_PTR(-EINVAL);
487 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
488 if (!clkmain)
489 return ERR_PTR(-ENOMEM);
491 init.name = name;
492 init.ops = &sam9x5_main_ops;
493 init.parent_names = parent_names;
494 init.num_parents = num_parents;
495 init.flags = CLK_SET_PARENT_GATE;
497 clkmain->hw.init = &init;
498 clkmain->regmap = regmap;
499 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
500 clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0;
502 hw = &clkmain->hw;
503 ret = clk_hw_register(NULL, &clkmain->hw);
504 if (ret) {
505 kfree(clkmain);
506 hw = ERR_PTR(ret);
509 return hw;