aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-01-19 21:05:29 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-27 14:48:52 -0500
commitbca9690b942654f668ffb5124b2bbd0ba0f007bb (patch)
treeb0e4a32c3175916fbe680dbad1687ac9c7185221
parent15a02c1f6dd7c2bb150c61d00ffb33f584ff2288 (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.c212
-rw-r--r--include/linux/clk-provider.h11
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
35static unsigned int _get_table_maxdiv(const struct clk_div_table *table) 35static 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
57static unsigned int _get_maxdiv(struct clk_divider *divider) 57static 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
68static unsigned int _get_table_div(const struct clk_div_table *table, 69static 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
79static unsigned int _get_div(struct clk_divider *divider, unsigned int val) 80static 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
101static unsigned int _get_val(struct clk_divider *divider, unsigned int div) 103static 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
112static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, 115unsigned 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}
132EXPORT_SYMBOL_GPL(divider_recalc_rate);
133
134static 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
149static bool _is_valid_div(struct clk_divider *divider, unsigned int div) 164static 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
194static int _div_round_up(struct clk_divider *divider, 210static 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
207static int _div_round_closest(struct clk_divider *divider, 224static 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