Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux...
[linux/fpc-iii.git] / drivers / clk / at91 / clk-slow.c
blob61090b1146cfd93e1255eb40a4d690502f08c6f5
1 /*
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>
17 #include <linux/of.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/regmap.h>
21 #include "pmc.h"
22 #include "sckc.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) / \
27 SLOW_CLOCK_FREQ)
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)
35 struct clk_slow_osc {
36 struct clk_hw hw;
37 void __iomem *sckcr;
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 {
44 struct clk_hw hw;
45 void __iomem *sckcr;
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 {
54 struct clk_hw hw;
55 struct regmap *regmap;
58 #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
60 struct clk_sam9x5_slow {
61 struct clk_hw hw;
62 void __iomem *sckcr;
63 u8 parent;
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)
75 return 0;
77 writel(tmp | AT91_SCKC_OSC32EN, sckcr);
79 usleep_range(osc->startup_usec, osc->startup_usec + 1);
81 return 0;
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)
91 return;
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)
103 return 1;
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,
116 const char *name,
117 const char *parent_name,
118 unsigned long startup,
119 bool bypass)
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);
129 if (!osc)
130 return ERR_PTR(-ENOMEM);
132 init.name = name;
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;
139 osc->sckcr = sckcr;
140 osc->startup_usec = startup;
142 if (bypass)
143 writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
144 sckcr);
146 clk = clk_register(NULL, &osc->hw);
147 if (IS_ERR(clk))
148 kfree(osc);
150 return clk;
153 void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
154 void __iomem *sckcr)
156 struct clk *clk;
157 const char *parent_name;
158 const char *name = np->name;
159 u32 startup;
160 bool bypass;
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,
168 bypass);
169 if (IS_ERR(clk))
170 return;
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);
200 return 0;
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,
228 const char *name,
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;
237 if (!sckcr || !name)
238 return ERR_PTR(-EINVAL);
240 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
241 if (!osc)
242 return ERR_PTR(-ENOMEM);
244 init.name = name;
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;
251 osc->sckcr = sckcr;
252 osc->frequency = frequency;
253 osc->accuracy = accuracy;
254 osc->startup_usec = startup;
256 clk = clk_register(NULL, &osc->hw);
257 if (IS_ERR(clk))
258 kfree(osc);
260 return clk;
263 void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
264 void __iomem *sckcr)
266 struct clk *clk;
267 u32 frequency = 0;
268 u32 accuracy = 0;
269 u32 startup = 0;
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,
278 startup);
279 if (IS_ERR(clk))
280 return;
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;
289 u32 tmp;
291 if (index > 1)
292 return -EINVAL;
294 tmp = readl(sckcr);
296 if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
297 (index && (tmp & AT91_SCKC_OSCSEL)))
298 return 0;
300 if (index)
301 tmp |= AT91_SCKC_OSCSEL;
302 else
303 tmp &= ~AT91_SCKC_OSCSEL;
305 writel(tmp, sckcr);
307 usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
309 return 0;
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,
326 const char *name,
327 const char **parent_names,
328 int num_parents)
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);
338 if (!slowck)
339 return ERR_PTR(-ENOMEM);
341 init.name = name;
342 init.ops = &sam9x5_slow_ops;
343 init.parent_names = parent_names;
344 init.num_parents = num_parents;
345 init.flags = 0;
347 slowck->hw.init = &init;
348 slowck->sckcr = sckcr;
349 slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
351 clk = clk_register(NULL, &slowck->hw);
352 if (IS_ERR(clk))
353 kfree(slowck);
355 return clk;
358 void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
359 void __iomem *sckcr)
361 struct clk *clk;
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)
368 return;
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,
375 num_parents);
376 if (IS_ERR(clk))
377 return;
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);
385 unsigned int status;
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,
398 const char *name,
399 const char **parent_names,
400 int num_parents)
402 struct clk_sam9260_slow *slowck;
403 struct clk *clk = NULL;
404 struct clk_init_data init;
406 if (!name)
407 return ERR_PTR(-EINVAL);
409 if (!parent_names || !num_parents)
410 return ERR_PTR(-EINVAL);
412 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
413 if (!slowck)
414 return ERR_PTR(-ENOMEM);
416 init.name = name;
417 init.ops = &sam9260_slow_ops;
418 init.parent_names = parent_names;
419 init.num_parents = num_parents;
420 init.flags = 0;
422 slowck->hw.init = &init;
423 slowck->regmap = regmap;
425 clk = clk_register(NULL, &slowck->hw);
426 if (IS_ERR(clk))
427 kfree(slowck);
429 return clk;
432 static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
434 struct clk *clk;
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)
442 return;
444 of_clk_parent_fill(np, parent_names, num_parents);
445 regmap = syscon_node_to_regmap(of_get_parent(np));
446 if (IS_ERR(regmap))
447 return;
449 of_property_read_string(np, "clock-output-names", &name);
451 clk = at91_clk_register_sam9260_slow(regmap, name, parent_names,
452 num_parents);
453 if (IS_ERR(clk))
454 return;
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);