clk: sunxi: Add muxable ahb factors clock for sun5i and sun7i
authorChen-Yu Tsai <wens@csie.org>
Thu, 19 Mar 2015 17:19:03 +0000 (01:19 +0800)
committerMaxime Ripard <maxime.ripard@free-electrons.com>
Sat, 21 Mar 2015 10:48:40 +0000 (11:48 +0100)
The AHB clock on sun5i and sun7i are muxable divider clocks.
Use a factors clock to support them.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Documentation/devicetree/bindings/clock/sunxi.txt
drivers/clk/sunxi/clk-sunxi.c

index 3f1dcd8..4fa11af 100644 (file)
@@ -20,6 +20,7 @@ Required properties:
        "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
        "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
        "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
+       "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
        "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
        "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
        "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
index b6f28ac..ae7b1c4 100644 (file)
@@ -482,6 +482,45 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
 }
 
 /**
+ * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB
+ * AHB rate is calculated as follows
+ * rate = parent_rate >> p
+ */
+
+static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate,
+                                      u8 *n, u8 *k, u8 *m, u8 *p)
+{
+       u32 div;
+
+       /* divide only */
+       if (parent_rate < *freq)
+               *freq = parent_rate;
+
+       /*
+        * user manual says valid speed is 8k ~ 276M, but tests show it
+        * can work at speeds up to 300M, just after reparenting to pll6
+        */
+       if (*freq < 8000)
+               *freq = 8000;
+       if (*freq > 300000000)
+               *freq = 300000000;
+
+       div = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
+
+       /* p = 0 ~ 3 */
+       if (div > 3)
+               div = 3;
+
+       *freq = parent_rate >> div;
+
+       /* we were called to round the frequency, we can now return */
+       if (p == NULL)
+               return;
+
+       *p = div;
+}
+
+/**
  * sun4i_get_apb1_factors() - calculates m, p factors for APB1
  * APB1 rate is calculated as follows
  * rate = (parent_rate >> p) / (m + 1);
@@ -616,6 +655,11 @@ static struct clk_factors_config sun6i_a31_pll6_config = {
        .n_start = 1,
 };
 
+static struct clk_factors_config sun5i_a13_ahb_config = {
+       .pshift = 4,
+       .pwidth = 2,
+};
+
 static struct clk_factors_config sun4i_apb1_config = {
        .mshift = 0,
        .mwidth = 5,
@@ -676,6 +720,13 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = {
        .name = "pll6x2",
 };
 
+static const struct factors_data sun5i_a13_ahb_data __initconst = {
+       .mux = 6,
+       .muxmask = BIT(1) | BIT(0),
+       .table = &sun5i_a13_ahb_config,
+       .getter = sun5i_a13_get_ahb_factors,
+};
+
 static const struct factors_data sun4i_apb1_data __initconst = {
        .mux = 24,
        .muxmask = BIT(1) | BIT(0),
@@ -1184,6 +1235,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
        {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
        {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
        {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
+       {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,},
        {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
        {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
        {}