clk: sunxi-ng: Support multiple variable pre-dividers
authorChen-Yu Tsai <wens@csie.org>
Fri, 19 May 2017 07:06:08 +0000 (15:06 +0800)
committerMaxime Ripard <maxime.ripard@free-electrons.com>
Wed, 7 Jun 2017 13:32:15 +0000 (15:32 +0200)
On the A83T, the AHB1 clock has a shared pre-divider on the two
PLL-PERIPH clock parents. To support such instances of shared
pre-dividers, this patch extends the mux clock type to support
multiple variable pre-dividers.

As the pre-dividers are only used to calculate the rate, but
do not participate in the factorization process, this is fairly
straightforward.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-r.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clk/sunxi-ng/ccu_mux.c
drivers/clk/sunxi-ng/ccu_mux.h

index f54114c..2bb4cab 100644 (file)
@@ -211,6 +211,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi", "pll-periph0" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -218,11 +221,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index df97e25..4d6078f 100644 (file)
@@ -195,6 +195,9 @@ static SUNXI_CCU_DIV_TABLE(axi_clk, "axi", "cpu",
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi", "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
@@ -203,11 +206,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index 5c6d37b..8a753ed 100644 (file)
@@ -169,6 +169,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi" , "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -176,11 +179,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index 8d38e65..10b38dc 100644 (file)
@@ -180,6 +180,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi" , "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -187,11 +190,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index 4cbc1b7..62e4f0d 100644 (file)
@@ -141,6 +141,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi" , "pll-periph0" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -148,11 +151,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index 119f47b..de02be7 100644 (file)
@@ -27,6 +27,9 @@
 
 static const char * const ar100_parents[] = { "osc32k", "osc24M",
                                             "pll-periph0", "iosc" };
+static const struct ccu_mux_var_prediv ar100_predivs[] = {
+       { .index = 2, .shift = 8, .width = 5 },
+};
 
 static struct ccu_div ar100_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
@@ -35,11 +38,8 @@ static struct ccu_div ar100_clk = {
                .shift  = 16,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 2,
-                       .shift  = 8,
-                       .width  = 5,
-               },
+               .var_predivs    = ar100_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ar100_predivs),
        },
 
        .common         = {
index 6297add..a34a78d 100644 (file)
@@ -132,6 +132,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
                                             "axi", "pll-periph0" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+       { .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -139,11 +142,8 @@ static struct ccu_div ahb1_clk = {
                .shift  = 12,
                .width  = 2,
 
-               .variable_prediv        = {
-                       .index  = 3,
-                       .shift  = 6,
-                       .width  = 2,
-               },
+               .var_predivs    = ahb1_predivs,
+               .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
        },
 
        .common         = {
index 748b172..cfe4538 100644 (file)
@@ -44,14 +44,18 @@ static u16 ccu_mux_get_prediv(struct ccu_common *common,
                                prediv = cm->fixed_predivs[i].div;
        }
 
-       if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
-               if (parent_index == cm->variable_prediv.index) {
-                       u8 div;
+       if (common->features & CCU_FEATURE_VARIABLE_PREDIV) {
+               int i;
 
-                       div = reg >> cm->variable_prediv.shift;
-                       div &= (1 << cm->variable_prediv.width) - 1;
-                       prediv = div + 1;
-               }
+               for (i = 0; i < cm->n_var_predivs; i++)
+                       if (parent_index == cm->var_predivs[i].index) {
+                               u8 div;
+
+                               div = reg >> cm->var_predivs[i].shift;
+                               div &= (1 << cm->var_predivs[i].width) - 1;
+                               prediv = div + 1;
+                       }
+       }
 
        return prediv;
 }
index dba12c7..f20c0bd 100644 (file)
@@ -10,6 +10,12 @@ struct ccu_mux_fixed_prediv {
        u16     div;
 };
 
+struct ccu_mux_var_prediv {
+       u8      index;
+       u8      shift;
+       u8      width;
+};
+
 struct ccu_mux_internal {
        u8              shift;
        u8              width;
@@ -18,11 +24,8 @@ struct ccu_mux_internal {
        const struct ccu_mux_fixed_prediv       *fixed_predivs;
        u8              n_predivs;
 
-       struct {
-               u8      index;
-               u8      shift;
-               u8      width;
-       } variable_prediv;
+       const struct ccu_mux_var_prediv         *var_predivs;
+       u8              n_var_predivs;
 };
 
 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table)   \