diff options
| author | Stephen Boyd <sboyd@codeaurora.org> | 2015-01-19 21:05:29 -0500 |
|---|---|---|
| committer | Michael Turquette <mturquette@linaro.org> | 2015-01-27 14:48:52 -0500 |
| commit | bca9690b942654f668ffb5124b2bbd0ba0f007bb (patch) | |
| tree | b0e4a32c3175916fbe680dbad1687ac9c7185221 | |
| parent | 15a02c1f6dd7c2bb150c61d00ffb33f584ff2288 (diff) | |
clk: divider: Make generic for usage elsewhere
Some devices don't use mmio to interact with dividers. Split out the
logic from the register read/write parts so that we can reuse the
division logic elsewhere.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested-by: Kenneth Westfield <kwestfie@codeaurora.org>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
| -rw-r--r-- | drivers/clk/clk-divider.c | 212 | ||||
| -rw-r--r-- | include/linux/clk-provider.h | 11 |
2 files changed, 139 insertions, 84 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c2bb9f679ec6..db7f8bce7467 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) | 31 | #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) |
| 32 | 32 | ||
| 33 | #define div_mask(d) ((1 << ((d)->width)) - 1) | 33 | #define div_mask(width) ((1 << (width)) - 1) |
| 34 | 34 | ||
| 35 | static unsigned int _get_table_maxdiv(const struct clk_div_table *table) | 35 | static unsigned int _get_table_maxdiv(const struct clk_div_table *table) |
| 36 | { | 36 | { |
| @@ -54,15 +54,16 @@ static unsigned int _get_table_mindiv(const struct clk_div_table *table) | |||
| 54 | return mindiv; | 54 | return mindiv; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static unsigned int _get_maxdiv(struct clk_divider *divider) | 57 | static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, |
| 58 | unsigned long flags) | ||
| 58 | { | 59 | { |
| 59 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | 60 | if (flags & CLK_DIVIDER_ONE_BASED) |
| 60 | return div_mask(divider); | 61 | return div_mask(width); |
| 61 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | 62 | if (flags & CLK_DIVIDER_POWER_OF_TWO) |
| 62 | return 1 << div_mask(divider); | 63 | return 1 << div_mask(width); |
| 63 | if (divider->table) | 64 | if (table) |
| 64 | return _get_table_maxdiv(divider->table); | 65 | return _get_table_maxdiv(table); |
| 65 | return div_mask(divider) + 1; | 66 | return div_mask(width) + 1; |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | static unsigned int _get_table_div(const struct clk_div_table *table, | 69 | static unsigned int _get_table_div(const struct clk_div_table *table, |
| @@ -76,14 +77,15 @@ static unsigned int _get_table_div(const struct clk_div_table *table, | |||
| 76 | return 0; | 77 | return 0; |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | static unsigned int _get_div(struct clk_divider *divider, unsigned int val) | 80 | static unsigned int _get_div(const struct clk_div_table *table, |
| 81 | unsigned int val, unsigned long flags) | ||
| 80 | { | 82 | { |
| 81 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | 83 | if (flags & CLK_DIVIDER_ONE_BASED) |
| 82 | return val; | 84 | return val; |
| 83 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | 85 | if (flags & CLK_DIVIDER_POWER_OF_TWO) |
| 84 | return 1 << val; | 86 | return 1 << val; |
| 85 | if (divider->table) | 87 | if (table) |
| 86 | return _get_table_div(divider->table, val); | 88 | return _get_table_div(table, val); |
| 87 | return val + 1; | 89 | return val + 1; |
| 88 | } | 90 | } |
| 89 | 91 | ||
| @@ -98,29 +100,28 @@ static unsigned int _get_table_val(const struct clk_div_table *table, | |||
| 98 | return 0; | 100 | return 0; |
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | static unsigned int _get_val(struct clk_divider *divider, unsigned int div) | 103 | static unsigned int _get_val(const struct clk_div_table *table, |
| 104 | unsigned int div, unsigned long flags) | ||
| 102 | { | 105 | { |
| 103 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | 106 | if (flags & CLK_DIVIDER_ONE_BASED) |
| 104 | return div; | 107 | return div; |
| 105 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | 108 | if (flags & CLK_DIVIDER_POWER_OF_TWO) |
| 106 | return __ffs(div); | 109 | return __ffs(div); |
| 107 | if (divider->table) | 110 | if (table) |
| 108 | return _get_table_val(divider->table, div); | 111 | return _get_table_val(table, div); |
| 109 | return div - 1; | 112 | return div - 1; |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 112 | static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | 115 | unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, |
| 113 | unsigned long parent_rate) | 116 | unsigned int val, |
| 117 | const struct clk_div_table *table, | ||
| 118 | unsigned long flags) | ||
| 114 | { | 119 | { |
| 115 | struct clk_divider *divider = to_clk_divider(hw); | 120 | unsigned int div; |
| 116 | unsigned int div, val; | ||
| 117 | 121 | ||
| 118 | val = clk_readl(divider->reg) >> divider->shift; | 122 | div = _get_div(table, val, flags); |
| 119 | val &= div_mask(divider); | ||
| 120 | |||
| 121 | div = _get_div(divider, val); | ||
| 122 | if (!div) { | 123 | if (!div) { |
| 123 | WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), | 124 | WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO), |
| 124 | "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", | 125 | "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", |
| 125 | __clk_get_name(hw->clk)); | 126 | __clk_get_name(hw->clk)); |
| 126 | return parent_rate; | 127 | return parent_rate; |
| @@ -128,6 +129,20 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
| 128 | 129 | ||
| 129 | return DIV_ROUND_UP(parent_rate, div); | 130 | return DIV_ROUND_UP(parent_rate, div); |
| 130 | } | 131 | } |
| 132 | EXPORT_SYMBOL_GPL(divider_recalc_rate); | ||
| 133 | |||
| 134 | static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | ||
| 135 | unsigned long parent_rate) | ||
| 136 | { | ||
| 137 | struct clk_divider *divider = to_clk_divider(hw); | ||
| 138 | unsigned int val; | ||
| 139 | |||
| 140 | val = clk_readl(divider->reg) >> divider->shift; | ||
| 141 | val &= div_mask(divider->width); | ||
| 142 | |||
| 143 | return divider_recalc_rate(hw, parent_rate, val, divider->table, | ||
| 144 | divider->flags); | ||
| 145 | } | ||
| 131 | 146 | ||
| 132 | /* | 147 | /* |
| 133 | * The reverse of DIV_ROUND_UP: The maximum number which | 148 | * The reverse of DIV_ROUND_UP: The maximum number which |
| @@ -146,12 +161,13 @@ static bool _is_valid_table_div(const struct clk_div_table *table, | |||
| 146 | return false; | 161 | return false; |
| 147 | } | 162 | } |
| 148 | 163 | ||
| 149 | static bool _is_valid_div(struct clk_divider *divider, unsigned int div) | 164 | static bool _is_valid_div(const struct clk_div_table *table, unsigned int div, |
| 165 | unsigned long flags) | ||
| 150 | { | 166 | { |
| 151 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | 167 | if (flags & CLK_DIVIDER_POWER_OF_TWO) |
| 152 | return is_power_of_2(div); | 168 | return is_power_of_2(div); |
| 153 | if (divider->table) | 169 | if (table) |
| 154 | return _is_valid_table_div(divider->table, div); | 170 | return _is_valid_table_div(table, div); |
| 155 | return true; | 171 | return true; |
| 156 | } | 172 | } |
| 157 | 173 | ||
| @@ -191,71 +207,76 @@ static int _round_down_table(const struct clk_div_table *table, int div) | |||
| 191 | return down; | 207 | return down; |
| 192 | } | 208 | } |
| 193 | 209 | ||
| 194 | static int _div_round_up(struct clk_divider *divider, | 210 | static int _div_round_up(const struct clk_div_table *table, |
| 195 | unsigned long parent_rate, unsigned long rate) | 211 | unsigned long parent_rate, unsigned long rate, |
| 212 | unsigned long flags) | ||
| 196 | { | 213 | { |
| 197 | int div = DIV_ROUND_UP(parent_rate, rate); | 214 | int div = DIV_ROUND_UP(parent_rate, rate); |
| 198 | 215 | ||
| 199 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | 216 | if (flags & CLK_DIVIDER_POWER_OF_TWO) |
| 200 | div = __roundup_pow_of_two(div); | 217 | div = __roundup_pow_of_two(div); |
| 201 | if (divider->table) | 218 | if (table) |
| 202 | div = _round_up_table(divider->table, div); | 219 | div = _round_up_table(table, div); |
| 203 | 220 | ||
| 204 | return div; | 221 | return div; |
| 205 | } | 222 | } |
| 206 | 223 | ||
| 207 | static int _div_round_closest(struct clk_divider *divider, | 224 | static int _div_round_closest(const struct clk_div_table *table, |
| 208 | unsigned long parent_rate, unsigned long rate) | 225 | unsigned long parent_rate, unsigned long rate, |
| 226 | unsigned long flags) | ||
| 209 | { | 227 | { |
| 210 | int up, down, div; | 228 | int up, down, div; |
| 211 | 229 | ||
| 212 | up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate); | 230 | up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate); |
| 213 | 231 | ||
| 214 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) { | 232 | if (flags & CLK_DIVIDER_POWER_OF_TWO) { |
| 215 | up = __roundup_pow_of_two(div); | 233 | u |
