diff options
author | Mike Turquette <mturquette@linaro.org> | 2013-12-29 16:37:56 -0500 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2013-12-29 16:37:56 -0500 |
commit | 6b71e0d9d6bfd24d2426a4ea7edf3c01d872903f (patch) | |
tree | e6304ae02ad41ab2620776a7b54cdf61b1e31546 /drivers | |
parent | ea72dc2cf9552631e43327ce593bdbb0b9fdf058 (diff) | |
parent | 6f86341726cbec1921e925fd54a10c5b58e6f9f1 (diff) |
Merge tag 'sunxi-clk-3.14-for-mike' of https://bitbucket.org/emiliolopez/linux into clk-next-sunxi
Allwinner sunXi SoCs clock changes
This contains the clk driver parts of the "[PATCH v3 00/13] clk: sunxi:
add PLL5 and PLL6 support" series. It adds support for PLL4/5/6 and
mod0 clocks on most sunxi platforms. Additionally, it contains "[PATCH
1/4] clk: sunxi: Allwinner A20 output clock support" (v2) from Chen-Yu
Tsai, which adds support for output clocks present on A20.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/sunxi/clk-factors.c | 63 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-factors.h | 16 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 435 |
3 files changed, 437 insertions, 77 deletions
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index f05207a27e5f..9e232644f07e 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -30,14 +30,6 @@ | |||
30 | * parent - fixed parent. No clk_set_parent support | 30 | * parent - fixed parent. No clk_set_parent support |
31 | */ | 31 | */ |
32 | 32 | ||
33 | struct clk_factors { | ||
34 | struct clk_hw hw; | ||
35 | void __iomem *reg; | ||
36 | struct clk_factors_config *config; | ||
37 | void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); | ||
38 | spinlock_t *lock; | ||
39 | }; | ||
40 | |||
41 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) | 33 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) |
42 | 34 | ||
43 | #define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) | 35 | #define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) |
@@ -120,61 +112,8 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | |||
120 | return 0; | 112 | return 0; |
121 | } | 113 | } |
122 | 114 | ||
123 | static const struct clk_ops clk_factors_ops = { | 115 | const struct clk_ops clk_factors_ops = { |
124 | .recalc_rate = clk_factors_recalc_rate, | 116 | .recalc_rate = clk_factors_recalc_rate, |
125 | .round_rate = clk_factors_round_rate, | 117 | .round_rate = clk_factors_round_rate, |
126 | .set_rate = clk_factors_set_rate, | 118 | .set_rate = clk_factors_set_rate, |
127 | }; | 119 | }; |
128 | |||
129 | /** | ||
130 | * clk_register_factors - register a factors clock with | ||
131 | * the clock framework | ||
132 | * @dev: device registering this clock | ||
133 | * @name: name of this clock | ||
134 | * @parent_name: name of clock's parent | ||
135 | * @flags: framework-specific flags | ||
136 | * @reg: register address to adjust factors | ||
137 | * @config: shift and width of factors n, k, m and p | ||
138 | * @get_factors: function to calculate the factors for a given frequency | ||
139 | * @lock: shared register lock for this clock | ||
140 | */ | ||
141 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
142 | const char *parent_name, | ||
143 | unsigned long flags, void __iomem *reg, | ||
144 | struct clk_factors_config *config, | ||
145 | void (*get_factors)(u32 *rate, u32 parent, | ||
146 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
147 | spinlock_t *lock) | ||
148 | { | ||
149 | struct clk_factors *factors; | ||
150 | struct clk *clk; | ||
151 | struct clk_init_data init; | ||
152 | |||
153 | /* allocate the factors */ | ||
154 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | ||
155 | if (!factors) { | ||
156 | pr_err("%s: could not allocate factors clk\n", __func__); | ||
157 | return ERR_PTR(-ENOMEM); | ||
158 | } | ||
159 | |||
160 | init.name = name; | ||
161 | init.ops = &clk_factors_ops; | ||
162 | init.flags = flags; | ||
163 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
164 | init.num_parents = (parent_name ? 1 : 0); | ||
165 | |||
166 | /* struct clk_factors assignments */ | ||
167 | factors->reg = reg; | ||
168 | factors->config = config; | ||
169 | factors->lock = lock; | ||
170 | factors->hw.init = &init; | ||
171 | factors->get_factors = get_factors; | ||
172 | |||
173 | /* register the clock */ | ||
174 | clk = clk_register(dev, &factors->hw); | ||
175 | |||
176 | if (IS_ERR(clk)) | ||
177 | kfree(factors); | ||
178 | |||
179 | return clk; | ||
180 | } | ||
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index f49851cc4380..02e1a43ebac7 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -17,11 +17,13 @@ struct clk_factors_config { | |||
17 | u8 pwidth; | 17 | u8 pwidth; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | struct clk *clk_register_factors(struct device *dev, const char *name, | 20 | struct clk_factors { |
21 | const char *parent_name, | 21 | struct clk_hw hw; |
22 | unsigned long flags, void __iomem *reg, | 22 | void __iomem *reg; |
23 | struct clk_factors_config *config, | 23 | struct clk_factors_config *config; |
24 | void (*get_factors) (u32 *rate, u32 parent_rate, | 24 | void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); |
25 | u8 *n, u8 *k, u8 *m, u8 *p), | 25 | spinlock_t *lock; |
26 | spinlock_t *lock); | 26 | }; |
27 | |||
28 | extern const struct clk_ops clk_factors_ops; | ||
27 | #endif | 29 | #endif |
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 98fec4e4baa7..659e4ea31893 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -23,6 +23,9 @@ | |||
23 | 23 | ||
24 | static DEFINE_SPINLOCK(clk_lock); | 24 | static DEFINE_SPINLOCK(clk_lock); |
25 | 25 | ||
26 | /* Maximum number of parents our clocks have */ | ||
27 | #define SUNXI_MAX_PARENTS 5 | ||
28 | |||
26 | /** | 29 | /** |
27 | * sun4i_osc_clk_setup() - Setup function for gatable oscillator | 30 | * sun4i_osc_clk_setup() - Setup function for gatable oscillator |
28 | */ | 31 | */ |
@@ -215,6 +218,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, | |||
215 | } | 218 | } |
216 | 219 | ||
217 | /** | 220 | /** |
221 | * sun4i_get_pll5_factors() - calculates n, k factors for PLL5 | ||
222 | * PLL5 rate is calculated as follows | ||
223 | * rate = parent_rate * n * (k + 1) | ||
224 | * parent_rate is always 24Mhz | ||
225 | */ | ||
226 | |||
227 | static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, | ||
228 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
229 | { | ||
230 | u8 div; | ||
231 | |||
232 | /* Normalize value to a parent_rate multiple (24M) */ | ||
233 | div = *freq / parent_rate; | ||
234 | *freq = parent_rate * div; | ||
235 | |||
236 | /* we were called to round the frequency, we can now return */ | ||
237 | if (n == NULL) | ||
238 | return; | ||
239 | |||
240 | if (div < 31) | ||
241 | *k = 0; | ||
242 | else if (div / 2 < 31) | ||
243 | *k = 1; | ||
244 | else if (div / 3 < 31) | ||
245 | *k = 2; | ||
246 | else | ||
247 | *k = 3; | ||
248 | |||
249 | *n = DIV_ROUND_UP(div, (*k+1)); | ||
250 | } | ||
251 | |||
252 | |||
253 | |||
254 | /** | ||
218 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 | 255 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 |
219 | * APB1 rate is calculated as follows | 256 | * APB1 rate is calculated as follows |
220 | * rate = (parent_rate >> p) / (m + 1); | 257 | * rate = (parent_rate >> p) / (m + 1); |
@@ -258,10 +295,96 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, | |||
258 | 295 | ||
259 | 296 | ||
260 | /** | 297 | /** |
298 | * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks | ||
299 | * MMC rate is calculated as follows | ||
300 | * rate = (parent_rate >> p) / (m + 1); | ||
301 | */ | ||
302 | |||
303 | static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate, | ||
304 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
305 | { | ||
306 | u8 div, calcm, calcp; | ||
307 | |||
308 | /* These clocks can only divide, so we will never be able to achieve | ||
309 | * frequencies higher than the parent frequency */ | ||
310 | if (*freq > parent_rate) | ||
311 | *freq = parent_rate; | ||
312 | |||
313 | div = parent_rate / *freq; | ||
314 | |||
315 | if (div < 16) | ||
316 | calcp = 0; | ||
317 | else if (div / 2 < 16) | ||
318 | calcp = 1; | ||
319 | else if (div / 4 < 16) | ||
320 | calcp = 2; | ||
321 | else | ||
322 | calcp = 3; | ||
323 | |||
324 | calcm = DIV_ROUND_UP(div, 1 << calcp); | ||
325 | |||
326 | *freq = (parent_rate >> calcp) / calcm; | ||
327 | |||
328 | /* we were called to round the frequency, we can now return */ | ||
329 | if (n == NULL) | ||
330 | return; | ||
331 | |||
332 | *m = calcm - 1; | ||
333 | *p = calcp; | ||
334 | } | ||
335 | |||
336 | |||
337 | |||
338 | /** | ||
339 | * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B | ||
340 | * CLK_OUT rate is calculated as follows | ||
341 | * rate = (parent_rate >> p) / (m + 1); | ||
342 | */ | ||
343 | |||
344 | static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | ||
345 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
346 | { | ||
347 | u8 div, calcm, calcp; | ||
348 | |||
349 | /* These clocks can only divide, so we will never be able to achieve | ||
350 | * frequencies higher than the parent frequency */ | ||
351 | if (*freq > parent_rate) | ||
352 | *freq = parent_rate; | ||
353 | |||
354 | div = parent_rate / *freq; | ||
355 | |||
356 | if (div < 32) | ||
357 | calcp = 0; | ||
358 | else if (div / 2 < 32) | ||
359 | calcp = 1; | ||
360 | else if (div / 4 < 32) | ||
361 | calcp = 2; | ||
362 | else | ||
363 | calcp = 3; | ||
364 | |||
365 | calcm = DIV_ROUND_UP(div, 1 << calcp); | ||
366 | |||
367 | *freq = (parent_rate >> calcp) / calcm; | ||
368 | |||
369 | /* we were called to round the frequency, we can now return */ | ||
370 | if (n == NULL) | ||
371 | return; | ||
372 | |||
373 | *m = calcm - 1; | ||
374 | *p = calcp; | ||
375 | } | ||
376 | |||
377 | |||
378 | |||
379 | /** | ||
261 | * sunxi_factors_clk_setup() - Setup function for factor clocks | 380 | * sunxi_factors_clk_setup() - Setup function for factor clocks |
262 | */ | 381 | */ |
263 | 382 | ||
383 | #define SUNXI_FACTORS_MUX_MASK 0x3 | ||
384 | |||
264 | struct factors_data { | 385 | struct factors_data { |
386 | int enable; | ||
387 | int mux; | ||
265 | struct clk_factors_config *table; | 388 | struct clk_factors_config *table; |
266 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | 389 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); |
267 | }; | 390 | }; |
@@ -286,6 +409,13 @@ static struct clk_factors_config sun6i_a31_pll1_config = { | |||
286 | .mwidth = 2, | 409 | .mwidth = 2, |
287 | }; | 410 | }; |
288 | 411 | ||
412 | static struct clk_factors_config sun4i_pll5_config = { | ||
413 | .nshift = 8, | ||
414 | .nwidth = 5, | ||
415 | .kshift = 4, | ||
416 | .kwidth = 2, | ||
417 | }; | ||
418 | |||
289 | static struct clk_factors_config sun4i_apb1_config = { | 419 | static struct clk_factors_config sun4i_apb1_config = { |
290 | .mshift = 0, | 420 | .mshift = 0, |
291 | .mwidth = 5, | 421 | .mwidth = 5, |
@@ -293,40 +423,143 @@ static struct clk_factors_config sun4i_apb1_config = { | |||
293 | .pwidth = 2, | 423 | .pwidth = 2, |
294 | }; | 424 | }; |
295 | 425 | ||
426 | /* user manual says "n" but it's really "p" */ | ||
427 | static struct clk_factors_config sun4i_mod0_config = { | ||
428 | .mshift = 0, | ||
429 | .mwidth = 4, | ||
430 | .pshift = 16, | ||
431 | .pwidth = 2, | ||
432 | }; | ||
433 | |||
434 | /* user manual says "n" but it's really "p" */ | ||
435 | static struct clk_factors_config sun7i_a20_out_config = { | ||
436 | .mshift = 8, | ||
437 | .mwidth = 5, | ||
438 | .pshift = 20, | ||
439 | .pwidth = 2, | ||
440 | }; | ||
441 | |||
296 | static const struct factors_data sun4i_pll1_data __initconst = { | 442 | static const struct factors_data sun4i_pll1_data __initconst = { |
443 | .enable = 31, | ||
297 | .table = &sun4i_pll1_config, | 444 | .table = &sun4i_pll1_config, |
298 | .getter = sun4i_get_pll1_factors, | 445 | .getter = sun4i_get_pll1_factors, |
299 | }; | 446 | }; |
300 | 447 | ||
301 | static const struct factors_data sun6i_a31_pll1_data __initconst = { | 448 | static const struct factors_data sun6i_a31_pll1_data __initconst = { |
449 | .enable = 31, | ||
302 | .table = &sun6i_a31_pll1_config, | 450 | .table = &sun6i_a31_pll1_config, |
303 | .getter = sun6i_a31_get_pll1_factors, | 451 | .getter = sun6i_a31_get_pll1_factors, |
304 | }; | 452 | }; |
305 | 453 | ||
454 | static const struct factors_data sun4i_pll5_data __initconst = { | ||
455 | .enable = 31, | ||
456 | .table = &sun4i_pll5_config, | ||
457 | .getter = sun4i_get_pll5_factors, | ||
458 | }; | ||
459 | |||
306 | static const struct factors_data sun4i_apb1_data __initconst = { | 460 | static const struct factors_data sun4i_apb1_data __initconst = { |
307 | .table = &sun4i_apb1_config, | 461 | .table = &sun4i_apb1_config, |
308 | .getter = sun4i_get_apb1_factors, | 462 | .getter = sun4i_get_apb1_factors, |
309 | }; | 463 | }; |
310 | 464 | ||
311 | static void __init sunxi_factors_clk_setup(struct device_node *node, | 465 | static const struct factors_data sun4i_mod0_data __initconst = { |
312 | struct factors_data *data) | 466 | .enable = 31, |
467 | .mux = 24, | ||
468 | .table = &sun4i_mod0_config, | ||
469 | .getter = sun4i_get_mod0_factors, | ||
470 | }; | ||
471 | |||
472 | static const struct factors_data sun7i_a20_out_data __initconst = { | ||
473 | .enable = 31, | ||
474 | .mux = 24, | ||
475 | .table = &sun7i_a20_out_config, | ||
476 | .getter = sun7i_a20_get_out_factors, | ||
477 | }; | ||
478 | |||
479 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, | ||
480 | const struct factors_data *data) | ||
313 | { | 481 | { |
314 | struct clk *clk; | 482 | struct clk *clk; |
483 | struct clk_factors *factors; | ||
484 | struct clk_gate *gate = NULL; | ||
485 | struct clk_mux *mux = NULL; | ||
486 | struct clk_hw *gate_hw = NULL; | ||
487 | struct clk_hw *mux_hw = NULL; | ||
315 | const char *clk_name = node->name; | 488 | const char *clk_name = node->name; |
316 | const char *parent; | 489 | const char *parents[SUNXI_MAX_PARENTS]; |
317 | void *reg; | 490 | void *reg; |
491 | int i = 0; | ||
318 | 492 | ||
319 | reg = of_iomap(node, 0); | 493 | reg = of_iomap(node, 0); |
320 | 494 | ||
321 | parent = of_clk_get_parent_name(node, 0); | 495 | /* if we have a mux, we will have >1 parents */ |
496 | while (i < SUNXI_MAX_PARENTS && | ||
497 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
498 | i++; | ||
322 | 499 | ||
323 | clk = clk_register_factors(NULL, clk_name, parent, 0, reg, | 500 | /* Nodes should be providing the name via clock-output-names |
324 | data->table, data->getter, &clk_lock); | 501 | * but originally our dts didn't, and so we used node->name. |
502 | * The new, better nodes look like clk@deadbeef, so we pull the | ||
503 | * name just in this case */ | ||
504 | if (!strcmp("clk", clk_name)) { | ||
505 | of_property_read_string_index(node, "clock-output-names", | ||
506 | 0, &clk_name); | ||
507 | } | ||
508 | |||
509 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | ||
510 | if (!factors) | ||
511 | return NULL; | ||
512 | |||
513 | /* Add a gate if this factor clock can be gated */ | ||
514 | if (data->enable) { | ||
515 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
516 | if (!gate) { | ||
517 | kfree(factors); | ||
518 | return NULL; | ||
519 | } | ||
520 | |||
521 | /* set up gate properties */ | ||
522 | gate->reg = reg; | ||
523 | gate->bit_idx = data->enable; | ||
524 | gate->lock = &clk_lock; | ||
525 | gate_hw = &gate->hw; | ||
526 | } | ||
527 | |||
528 | /* Add a mux if this factor clock can be muxed */ | ||
529 | if (data->mux) { | ||
530 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
531 | if (!mux) { | ||
532 | kfree(factors); | ||
533 | kfree(gate); | ||
534 | return NULL; | ||
535 | } | ||
536 | |||
537 | /* set up gate properties */ | ||
538 | mux->reg = reg; | ||
539 | mux->shift = data->mux; | ||
540 | mux->mask = SUNXI_FACTORS_MUX_MASK; | ||
541 | mux->lock = &clk_lock; | ||
542 | mux_hw = &mux->hw; | ||
543 | } | ||
544 | |||
545 | /* set up factors properties */ | ||
546 | factors->reg = reg; | ||
547 | factors->config = data->table; | ||
548 | factors->get_factors = data->getter; | ||
549 | factors->lock = &clk_lock; | ||
550 | |||
551 | clk = clk_register_composite(NULL, clk_name, | ||
552 | parents, i, | ||
553 | mux_hw, &clk_mux_ops, | ||
554 | &factors->hw, &clk_factors_ops, | ||
555 | gate_hw, &clk_gate_ops, 0); | ||
325 | 556 | ||
326 | if (!IS_ERR(clk)) { | 557 | if (!IS_ERR(clk)) { |
327 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 558 | of_clk_add_provider(node, of_clk_src_simple_get, clk); |
328 | clk_register_clkdev(clk, clk_name, NULL); | 559 | clk_register_clkdev(clk, clk_name, NULL); |
329 | } | 560 | } |
561 | |||
562 | return clk; | ||
330 | } | 563 | } |
331 | 564 | ||
332 | 565 | ||
@@ -358,13 +591,14 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, | |||
358 | { | 591 | { |
359 | struct clk *clk; | 592 | struct clk *clk; |
360 | const char *clk_name = node->name; | 593 | const char *clk_name = node->name; |
361 | const char *parents[5]; | 594 | const char *parents[SUNXI_MAX_PARENTS]; |
362 | void *reg; | 595 | void *reg; |
363 | int i = 0; | 596 | int i = 0; |
364 | 597 | ||
365 | reg = of_iomap(node, 0); | 598 | reg = of_iomap(node, 0); |
366 | 599 | ||
367 | while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | 600 | while (i < SUNXI_MAX_PARENTS && |
601 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
368 | i++; | 602 | i++; |
369 | 603 | ||
370 | clk = clk_register_mux(NULL, clk_name, parents, i, | 604 | clk = clk_register_mux(NULL, clk_name, parents, i, |
@@ -561,11 +795,186 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, | |||
561 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | 795 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
562 | } | 796 | } |
563 | 797 | ||
798 | |||
799 | |||
800 | /** | ||
801 | * sunxi_divs_clk_setup() helper data | ||
802 | */ | ||
803 | |||
804 | #define SUNXI_DIVS_MAX_QTY 2 | ||
805 | #define SUNXI_DIVISOR_WIDTH 2 | ||
806 | |||
807 | struct divs_data { | ||
808 | const struct factors_data *factors; /* data for the factor clock */ | ||
809 | struct { | ||
810 | u8 fixed; /* is it a fixed divisor? if not... */ | ||
811 | struct clk_div_table *table; /* is it a table based divisor? */ | ||
812 | u8 shift; /* otherwise it's a normal divisor with this shift */ | ||
813 | u8 pow; /* is it power-of-two based? */ | ||
814 | u8 gate; /* is it independently gateable? */ | ||
815 | } div[SUNXI_DIVS_MAX_QTY]; | ||
816 | }; | ||
817 | |||
818 | static struct clk_div_table pll6_sata_tbl[] = { | ||
819 | { .val = 0, .div = 6, }, | ||
820 | { .val = 1, .div = 12, }, | ||
821 | { .val = 2, .div = 18, }, | ||
822 | { .val = 3, .div = 24, }, | ||
823 | { } /* sentinel */ | ||
824 | }; | ||
825 | |||
826 | static const struct divs_data pll5_divs_data __initconst = { | ||
827 | .factors = &sun4i_pll5_data, | ||
828 | .div = { | ||
829 | { .shift = 0, .pow = 0, }, /* M, DDR */ | ||
830 | { .shift = 16, .pow = 1, }, /* P, other */ | ||
831 | } | ||
832 | }; | ||
833 | |||
834 | static const struct divs_data pll6_divs_data __initconst = { | ||
835 | .factors = &sun4i_pll5_data, | ||
836 | .div = { | ||
837 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ | ||
838 | { .fixed = 2 }, /* P, other */ | ||
839 | } | ||
840 | }; | ||
841 | |||
842 | /** | ||
843 | * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks | ||
844 | * | ||
845 | * These clocks look something like this | ||
846 | * ________________________ | ||
847 | * | ___divisor 1---|----> to consumer | ||
848 | * parent >--| pll___/___divisor 2---|----> to consumer | ||
849 | * | \_______________|____> to consumer | ||
850 | * |________________________| | ||
851 | */ | ||
852 | |||
853 | static void __init sunxi_divs_clk_setup(struct device_node *node, | ||
854 | struct divs_data *data) | ||
855 | { | ||
856 | struct clk_onecell_data *clk_data; | ||
857 | const char *parent = node->name; | ||
858 | const char *clk_name; | ||
859 | struct clk **clks, *pclk; | ||
860 | struct clk_hw *gate_hw, *rate_hw; | ||
861 | const struct clk_ops *rate_ops; | ||
862 | struct clk_gate *gate = NULL; | ||
863 | struct clk_fixed_factor *fix_factor; | ||
864 | struct clk_divider *divider; | ||
865 | void *reg; | ||
866 | int i = 0; | ||
867 | int flags, clkflags; | ||
868 | |||
869 | /* Set up factor clock that we will be dividing */ | ||
870 | pclk = sunxi_factors_clk_setup(node, data->factors); | ||
871 | |||
872 | reg = of_iomap(node, 0); | ||
873 | |||
874 | clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); | ||
875 | if (!clk_data) | ||
876 | return; | ||
877 | |||
878 | clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL); | ||
879 | if (!clks) | ||
880 | goto free_clkdata; | ||
881 | |||
882 | clk_data->clks = clks; | ||
883 | |||
884 | /* It's not a good idea to have automatic reparenting changing | ||
885 | * our RAM clock! */ | ||
886 | clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT; | ||
887 | |||
888 | for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) { | ||
889 | if (of_property_read_string_index(node, "clock-output-names", | ||
890 | i, &clk_name) != 0) | ||
891 | break; | ||
892 | |||
893 | gate_hw = NULL; | ||
894 | rate_hw = NULL; | ||
895 | rate_ops = NULL; | ||
896 | |||
897 | /* If this leaf clock can be gated, create a gate */ | ||
898 | if (data->div[i].gate) { | ||
899 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
900 | if (!gate) | ||
901 | goto free_clks; | ||
902 | |||
903 | gate->reg = reg; | ||
904 | gate->bit_idx = data->div[i].gate; | ||
905 | gate->lock = &clk_lock; | ||
906 | |||
907 | gate_hw = &gate->hw; | ||
908 | } | ||
909 | |||
910 | /* Leaves can be fixed or configurable divisors */ | ||
911 | if (data->div[i].fixed) { | ||
912 | fix_factor = kzalloc(sizeof(*fix_factor), GFP_KERNEL); | ||
913 | if (!fix_factor) | ||
914 | goto free_gate; | ||
915 | |||
916 | fix_factor->mult = 1; | ||
917 | fix_factor->div = data->div[i].fixed; | ||
918 | |||
919 | rate_hw = &fix_factor->hw; | ||
920 | rate_ops = &clk_fixed_factor_ops; | ||
921 | } else { | ||
922 | divider = kzalloc(sizeof(*divider), GFP_KERNEL); | ||
923 | if (!divider) | ||
924 | goto free_gate; | ||
925 | |||
926 | flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0; | ||
927 | |||
928 | divider->reg = reg; | ||
929 | divider->shift = data->div[i].shift; | ||
930 | divider->width = SUNXI_DIVISOR_WIDTH; | ||
931 | divider->flags = flags; | ||
932 | divider->lock = &clk_lock; | ||
933 | divider->table = data->div[i].table; | ||
934 | |||
935 | rate_hw = ÷r->hw; | ||
936 | rate_ops = &clk_divider_ops; | ||
937 | } | ||
938 | |||
939 | /* Wrap the (potential) gate and the divisor on a composite | ||
940 | * clock to unify them */ | ||
941 | clks[i] = clk_register_composite(NULL, clk_name, &parent, 1, | ||
942 | NULL, NULL, | ||
943 | rate_hw, rate_ops, | ||
944 | gate_hw, &clk_gate_ops, | ||
945 | clkflags); | ||
946 | |||
947 | WARN_ON(IS_ERR(clk_data->clks[i])); | ||
948 | clk_register_clkdev(clks[i], clk_name, NULL); | ||
949 | } | ||
950 | |||
951 | /* The last clock available on the getter is the parent */ | ||
952 | clks[i++] = pclk; | ||
953 | |||
954 | /* Adjust to the real max */ | ||
955 | clk_data->clk_num = i; | ||
956 | |||
957 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||
958 | |||
959 | return; | ||
960 | |||
961 | free_gate: | ||
962 | kfree(gate); | ||
963 | free_clks: | ||
964 | kfree(clks); | ||
965 | free_clkdata: | ||
966 | kfree(clk_data); | ||
967 | } | ||
968 | |||
969 | |||
970 | |||
564 | /* Matches for factors clocks */ | 971 | /* Matches for factors clocks */ |
565 | static const struct of_device_id clk_factors_match[] __initconst = { | 972 | static const struct of_device_id clk_factors_match[] __initconst = { |
566 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, | 973 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, |
567 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, | 974 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, |
568 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, | 975 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, |
976 | {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, | ||
977 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, | ||
569 | {} | 978 | {} |
570 | }; | 979 | }; |
571 | 980 | ||
@@ -578,6 +987,13 @@ static const struct of_device_id clk_div_match[] __initconst = { | |||
578 | {} | 987 | {} |
579 | }; | 988 | }; |
580 | 989 | ||
990 | /* Matches for divided outputs */ | ||
991 | static const struct of_device_id clk_divs_match[] __initconst = { | ||
992 | {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,}, | ||
993 | {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,}, | ||
994 | {} | ||
995 | }; | ||
996 | |||
581 | /* Matches for mux clocks */ | 997 | /* Matches for mux clocks */ |
582 | static const struct of_device_id clk_mux_match[] __initconst = { | 998 | static const struct of_device_id clk_mux_match[] __initconst = { |
583 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, | 999 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, |
@@ -655,6 +1071,9 @@ static void __init sunxi_init_clocks(void) | |||
655 | /* Register divider clocks */ | 1071 | /* Register divider clocks */ |
656 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); | 1072 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); |
657 | 1073 | ||
1074 | /* Register divided output clocks */ | ||
1075 | of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup); | ||
1076 | |||
658 | /* Register mux clocks */ | 1077 | /* Register mux clocks */ |
659 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); | 1078 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); |
660 | 1079 | ||