aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2013-12-24 08:26:17 -0500
committerEmilio López <emilio@elopez.com.ar>2013-12-28 15:14:21 -0500
commit6f86341726cbec1921e925fd54a10c5b58e6f9f1 (patch)
treeec7de73187cf68dd890e8e62dcab535e4434e052
parent76192dc8873f724361c1bf8a90b37abc7dfed7ad (diff)
clk: sunxi: Allwinner A20 output clock support
This patch adds support for the external clock outputs on the Allwinner A20 SoC. The clock outputs are similar to "module 0" type clocks, with different offsets and widths for clock factors. Signed-off-by: Chen-Yu Tsai <wens@csie.org> Acked-by: Emilio López <emilio@elopez.com.ar>
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt1
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c57
2 files changed, 58 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 46d8433b2a8c..c2cb7621ad2d 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -36,6 +36,7 @@ Required properties:
36 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 36 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
37 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 37 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
38 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks 38 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
39 "allwinner,sun7i-a20-out-clk" - for the external output clocks
39 40
40Required properties for all clocks: 41Required properties for all clocks:
41- reg : shall be the control register address for the clock. 42- reg : shall be the control register address for the clock.
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 124113e33f06..659e4ea31893 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -336,6 +336,47 @@ static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
336 336
337 337
338/** 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
344static 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/**
339 * sunxi_factors_clk_setup() - Setup function for factor clocks 380 * sunxi_factors_clk_setup() - Setup function for factor clocks
340 */ 381 */
341 382
@@ -390,6 +431,14 @@ static struct clk_factors_config sun4i_mod0_config = {
390 .pwidth = 2, 431 .pwidth = 2,
391}; 432};
392 433
434/* user manual says "n" but it's really "p" */
435static struct clk_factors_config sun7i_a20_out_config = {
436 .mshift = 8,
437 .mwidth = 5,
438 .pshift = 20,
439 .pwidth = 2,
440};
441
393static const struct factors_data sun4i_pll1_data __initconst = { 442static const struct factors_data sun4i_pll1_data __initconst = {
394 .enable = 31, 443 .enable = 31,
395 .table = &sun4i_pll1_config, 444 .table = &sun4i_pll1_config,
@@ -420,6 +469,13 @@ static const struct factors_data sun4i_mod0_data __initconst = {
420 .getter = sun4i_get_mod0_factors, 469 .getter = sun4i_get_mod0_factors,
421}; 470};
422 471
472static 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
423static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 479static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
424 const struct factors_data *data) 480 const struct factors_data *data)
425{ 481{
@@ -918,6 +974,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
918 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, 974 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
919 {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, 975 {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
920 {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, 976 {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
977 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
921 {} 978 {}
922}; 979};
923 980