aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2014-11-12 13:08:31 -0500
committerMaxime Ripard <maxime.ripard@free-electrons.com>2014-11-23 11:02:56 -0500
commit95e94c1fadcd1959857db45c2e11810a893badd0 (patch)
tree2c62bbbe6df23b6b1ab8bb5660d06dc3384a58fd /drivers
parent13d52f61065dcdbea13aae2f0aea6af43a3abf65 (diff)
clk: sunxi: Implement A31 PLL6 as a divs clock for 2x output
Some clock modules on the A31 use PLL6x2 as one of their inputs. This patch changes the PLL6 implementation for A31 to a divs clock, i.e. clock with multiple outputs that have different dividers. The first output will be the normal PLL6 output, and the second will be PLL6x2. This patch fixes the PLL6 N factor in the clock driver, and removes any /2 dividers in the PLL6 factors clock part. The N factor counts from 1 to 32, mapping to values 0 to 31, as shown in the A31 manual. Signed-off-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d46949372762..570202582dcf 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -245,9 +245,9 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
245} 245}
246 246
247/** 247/**
248 * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 248 * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2
249 * PLL6 rate is calculated as follows 249 * PLL6x2 rate is calculated as follows
250 * rate = parent_rate * n * (k + 1) / 2 250 * rate = parent_rate * (n + 1) * (k + 1)
251 * parent_rate is always 24Mhz 251 * parent_rate is always 24Mhz
252 */ 252 */
253 253
@@ -256,13 +256,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
256{ 256{
257 u8 div; 257 u8 div;
258 258
259 /* 259 /* Normalize value to a parent_rate multiple (24M) */
260 * We always have 24MHz / 2, so we can just say that our
261 * parent clock is 12MHz.
262 */
263 parent_rate = parent_rate / 2;
264
265 /* Normalize value to a parent_rate multiple (24M / 2) */
266 div = *freq / parent_rate; 260 div = *freq / parent_rate;
267 *freq = parent_rate * div; 261 *freq = parent_rate * div;
268 262
@@ -274,7 +268,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
274 if (*k > 3) 268 if (*k > 3)
275 *k = 3; 269 *k = 3;
276 270
277 *n = DIV_ROUND_UP(div, (*k+1)); 271 *n = DIV_ROUND_UP(div, (*k+1)) - 1;
278} 272}
279 273
280/** 274/**
@@ -445,6 +439,7 @@ static struct clk_factors_config sun6i_a31_pll6_config = {
445 .nwidth = 5, 439 .nwidth = 5,
446 .kshift = 4, 440 .kshift = 4,
447 .kwidth = 2, 441 .kwidth = 2,
442 .n_start = 1,
448}; 443};
449 444
450static struct clk_factors_config sun4i_apb1_config = { 445static struct clk_factors_config sun4i_apb1_config = {
@@ -504,6 +499,7 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = {
504 .enable = 31, 499 .enable = 31,
505 .table = &sun6i_a31_pll6_config, 500 .table = &sun6i_a31_pll6_config,
506 .getter = sun6i_a31_get_pll6_factors, 501 .getter = sun6i_a31_get_pll6_factors,
502 .name = "pll6x2",
507}; 503};
508 504
509static const struct factors_data sun4i_apb1_data __initconst = { 505static const struct factors_data sun4i_apb1_data __initconst = {
@@ -942,6 +938,14 @@ static const struct divs_data pll6_divs_data __initconst = {
942 } 938 }
943}; 939};
944 940
941static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
942 .factors = &sun6i_a31_pll6_data,
943 .ndivs = 1,
944 .div = {
945 { .fixed = 2 }, /* normal output */
946 }
947};
948
945/** 949/**
946 * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks 950 * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
947 * 951 *
@@ -1082,7 +1086,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
1082 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, 1086 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
1083 {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, 1087 {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
1084 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, 1088 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
1085 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
1086 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, 1089 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1087 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1090 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
1088 {} 1091 {}
@@ -1101,6 +1104,7 @@ static const struct of_device_id clk_div_match[] __initconst = {
1101static const struct of_device_id clk_divs_match[] __initconst = { 1104static const struct of_device_id clk_divs_match[] __initconst = {
1102 {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, 1105 {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
1103 {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, 1106 {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
1107 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,},
1104 {} 1108 {}
1105}; 1109};
1106 1110