diff options
author | Emilio López <emilio@elopez.com.ar> | 2013-12-22 22:32:39 -0500 |
---|---|---|
committer | Emilio López <emilio@elopez.com.ar> | 2013-12-28 15:08:22 -0500 |
commit | 7551769a225f3e600d6455e63ae00d51df37ff59 (patch) | |
tree | e2682fcc3bd43d228022be9be528f5ac58ab5046 | |
parent | d584c1331d6421e2387eab10b11fa6f08b4a4b5f (diff) |
clk: sunxi: mod0 support
This commit implements support for the "module 0" type of clocks, as
used by MMC, IR, NAND, SATA and other components.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Acked-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/clock/sunxi.txt | 5 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 57 |
2 files changed, 61 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 80b2a39b17a2..46d8433b2a8c 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -35,10 +35,13 @@ Required properties: | |||
35 | "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 | 35 | "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 |
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 | 39 | ||
39 | Required properties for all clocks: | 40 | Required properties for all clocks: |
40 | - reg : shall be the control register address for the clock. | 41 | - reg : shall be the control register address for the clock. |
41 | - clocks : shall be the input parent clock(s) phandle for the clock | 42 | - clocks : shall be the input parent clock(s) phandle for the clock. For |
43 | multiplexed clocks, the list order must match the hardware | ||
44 | programming order. | ||
42 | - #clock-cells : from common clock binding; shall be set to 0 except for | 45 | - #clock-cells : from common clock binding; shall be set to 0 except for |
43 | "allwinner,*-gates-clk" where it shall be set to 1 | 46 | "allwinner,*-gates-clk" where it shall be set to 1 |
44 | 47 | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index e90df083a36d..75fbc48129be 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -295,6 +295,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, | |||
295 | 295 | ||
296 | 296 | ||
297 | /** | 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 | /** | ||
298 | * sunxi_factors_clk_setup() - Setup function for factor clocks | 339 | * sunxi_factors_clk_setup() - Setup function for factor clocks |
299 | */ | 340 | */ |
300 | 341 | ||
@@ -341,6 +382,14 @@ static struct clk_factors_config sun4i_apb1_config = { | |||
341 | .pwidth = 2, | 382 | .pwidth = 2, |
342 | }; | 383 | }; |
343 | 384 | ||
385 | /* user manual says "n" but it's really "p" */ | ||
386 | static struct clk_factors_config sun4i_mod0_config = { | ||
387 | .mshift = 0, | ||
388 | .mwidth = 4, | ||
389 | .pshift = 16, | ||
390 | .pwidth = 2, | ||
391 | }; | ||
392 | |||
344 | static const struct factors_data sun4i_pll1_data __initconst = { | 393 | static const struct factors_data sun4i_pll1_data __initconst = { |
345 | .enable = 31, | 394 | .enable = 31, |
346 | .table = &sun4i_pll1_config, | 395 | .table = &sun4i_pll1_config, |
@@ -364,6 +413,13 @@ static const struct factors_data sun4i_apb1_data __initconst = { | |||
364 | .getter = sun4i_get_apb1_factors, | 413 | .getter = sun4i_get_apb1_factors, |
365 | }; | 414 | }; |
366 | 415 | ||
416 | static const struct factors_data sun4i_mod0_data __initconst = { | ||
417 | .enable = 31, | ||
418 | .mux = 24, | ||
419 | .table = &sun4i_mod0_config, | ||
420 | .getter = sun4i_get_mod0_factors, | ||
421 | }; | ||
422 | |||
367 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, | 423 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, |
368 | const struct factors_data *data) | 424 | const struct factors_data *data) |
369 | { | 425 | { |
@@ -852,6 +908,7 @@ static const struct of_device_id clk_factors_match[] __initconst = { | |||
852 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, | 908 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, |
853 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, | 909 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, |
854 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, | 910 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, |
911 | {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, | ||
855 | {} | 912 | {} |
856 | }; | 913 | }; |
857 | 914 | ||