Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: sunxi-ng: Support multiple variable pre-dividers

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>

authored by

Chen-Yu Tsai and committed by
Maxime Ripard
13e0dde8 11ad470c

+54 -47
+5 -5
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
··· 211 211 212 212 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 213 213 "axi", "pll-periph0" }; 214 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 215 + { .index = 3, .shift = 6, .width = 2 }, 216 + }; 214 217 static struct ccu_div ahb1_clk = { 215 218 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 216 219 ··· 221 218 .shift = 12, 222 219 .width = 2, 223 220 224 - .variable_prediv = { 225 - .index = 3, 226 - .shift = 6, 227 - .width = 2, 228 - }, 221 + .var_predivs = ahb1_predivs, 222 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 229 223 }, 230 224 231 225 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
··· 195 195 196 196 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 197 197 "axi", "pll-periph" }; 198 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 199 + { .index = 3, .shift = 6, .width = 2 }, 200 + }; 198 201 199 202 static struct ccu_div ahb1_clk = { 200 203 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), ··· 206 203 .shift = 12, 207 204 .width = 2, 208 205 209 - .variable_prediv = { 210 - .index = 3, 211 - .shift = 6, 212 - .width = 2, 213 - }, 206 + .var_predivs = ahb1_predivs, 207 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 214 208 }, 215 209 216 210 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
··· 169 169 170 170 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 171 171 "axi" , "pll-periph" }; 172 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 173 + { .index = 3, .shift = 6, .width = 2 }, 174 + }; 172 175 static struct ccu_div ahb1_clk = { 173 176 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 174 177 ··· 179 176 .shift = 12, 180 177 .width = 2, 181 178 182 - .variable_prediv = { 183 - .index = 3, 184 - .shift = 6, 185 - .width = 2, 186 - }, 179 + .var_predivs = ahb1_predivs, 180 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 187 181 }, 188 182 189 183 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
··· 180 180 181 181 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 182 182 "axi" , "pll-periph" }; 183 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 184 + { .index = 3, .shift = 6, .width = 2 }, 185 + }; 183 186 static struct ccu_div ahb1_clk = { 184 187 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 185 188 ··· 190 187 .shift = 12, 191 188 .width = 2, 192 189 193 - .variable_prediv = { 194 - .index = 3, 195 - .shift = 6, 196 - .width = 2, 197 - }, 190 + .var_predivs = ahb1_predivs, 191 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 198 192 }, 199 193 200 194 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
··· 141 141 142 142 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 143 143 "axi" , "pll-periph0" }; 144 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 145 + { .index = 3, .shift = 6, .width = 2 }, 146 + }; 144 147 static struct ccu_div ahb1_clk = { 145 148 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 146 149 ··· 151 148 .shift = 12, 152 149 .width = 2, 153 150 154 - .variable_prediv = { 155 - .index = 3, 156 - .shift = 6, 157 - .width = 2, 158 - }, 151 + .var_predivs = ahb1_predivs, 152 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 159 153 }, 160 154 161 155 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-r.c
··· 27 27 28 28 static const char * const ar100_parents[] = { "osc32k", "osc24M", 29 29 "pll-periph0", "iosc" }; 30 + static const struct ccu_mux_var_prediv ar100_predivs[] = { 31 + { .index = 2, .shift = 8, .width = 5 }, 32 + }; 30 33 31 34 static struct ccu_div ar100_clk = { 32 35 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), ··· 38 35 .shift = 16, 39 36 .width = 2, 40 37 41 - .variable_prediv = { 42 - .index = 2, 43 - .shift = 8, 44 - .width = 5, 45 - }, 38 + .var_predivs = ar100_predivs, 39 + .n_var_predivs = ARRAY_SIZE(ar100_predivs), 46 40 }, 47 41 48 42 .common = {
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
··· 132 132 133 133 static const char * const ahb1_parents[] = { "osc32k", "osc24M", 134 134 "axi", "pll-periph0" }; 135 + static const struct ccu_mux_var_prediv ahb1_predivs[] = { 136 + { .index = 3, .shift = 6, .width = 2 }, 137 + }; 135 138 static struct ccu_div ahb1_clk = { 136 139 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 137 140 ··· 142 139 .shift = 12, 143 140 .width = 2, 144 141 145 - .variable_prediv = { 146 - .index = 3, 147 - .shift = 6, 148 - .width = 2, 149 - }, 142 + .var_predivs = ahb1_predivs, 143 + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), 150 144 }, 151 145 152 146 .common = {
+11 -7
drivers/clk/sunxi-ng/ccu_mux.c
··· 44 44 prediv = cm->fixed_predivs[i].div; 45 45 } 46 46 47 - if (common->features & CCU_FEATURE_VARIABLE_PREDIV) 48 - if (parent_index == cm->variable_prediv.index) { 49 - u8 div; 47 + if (common->features & CCU_FEATURE_VARIABLE_PREDIV) { 48 + int i; 50 49 51 - div = reg >> cm->variable_prediv.shift; 52 - div &= (1 << cm->variable_prediv.width) - 1; 53 - prediv = div + 1; 54 - } 50 + for (i = 0; i < cm->n_var_predivs; i++) 51 + if (parent_index == cm->var_predivs[i].index) { 52 + u8 div; 53 + 54 + div = reg >> cm->var_predivs[i].shift; 55 + div &= (1 << cm->var_predivs[i].width) - 1; 56 + prediv = div + 1; 57 + } 58 + } 55 59 56 60 return prediv; 57 61 }
+8 -5
drivers/clk/sunxi-ng/ccu_mux.h
··· 10 10 u16 div; 11 11 }; 12 12 13 + struct ccu_mux_var_prediv { 14 + u8 index; 15 + u8 shift; 16 + u8 width; 17 + }; 18 + 13 19 struct ccu_mux_internal { 14 20 u8 shift; 15 21 u8 width; ··· 24 18 const struct ccu_mux_fixed_prediv *fixed_predivs; 25 19 u8 n_predivs; 26 20 27 - struct { 28 - u8 index; 29 - u8 shift; 30 - u8 width; 31 - } variable_prediv; 21 + const struct ccu_mux_var_prediv *var_predivs; 22 + u8 n_var_predivs; 32 23 }; 33 24 34 25 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table) \