diff options
Diffstat (limited to 'arch/sh/kernel/cpu/clock-cpg.c')
-rw-r--r-- | arch/sh/kernel/cpu/clock-cpg.c | 104 |
1 files changed, 99 insertions, 5 deletions
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 6dfe2cced3fc..eed5eaff96ba 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -149,7 +149,8 @@ int __init sh_clk_div6_register(struct clk *clks, int nr) | |||
149 | 149 | ||
150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | 150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) |
151 | { | 151 | { |
152 | struct clk_div_mult_table *table = clk->priv; | 152 | struct clk_div4_table *d4t = clk->priv; |
153 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
153 | unsigned int idx; | 154 | unsigned int idx; |
154 | 155 | ||
155 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 156 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
@@ -160,17 +161,90 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) | |||
160 | return clk->freq_table[idx].frequency; | 161 | return clk->freq_table[idx].frequency; |
161 | } | 162 | } |
162 | 163 | ||
164 | static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | ||
165 | { | ||
166 | struct clk_div4_table *d4t = clk->priv; | ||
167 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
168 | u32 value; | ||
169 | int ret; | ||
170 | |||
171 | if (!strcmp("pll_clk", parent->name)) | ||
172 | value = __raw_readl(clk->enable_reg) & ~(1 << 7); | ||
173 | else | ||
174 | value = __raw_readl(clk->enable_reg) | (1 << 7); | ||
175 | |||
176 | ret = clk_reparent(clk, parent); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | __raw_writel(value, clk->enable_reg); | ||
181 | |||
182 | /* Rebiuld the frequency table */ | ||
183 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
184 | table, &clk->arch_flags); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) | ||
190 | { | ||
191 | struct clk_div4_table *d4t = clk->priv; | ||
192 | unsigned long value; | ||
193 | int idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
194 | if (idx < 0) | ||
195 | return idx; | ||
196 | |||
197 | value = __raw_readl(clk->enable_reg); | ||
198 | value &= ~(0xf << clk->enable_bit); | ||
199 | value |= (idx << clk->enable_bit); | ||
200 | __raw_writel(value, clk->enable_reg); | ||
201 | |||
202 | if (d4t->kick) | ||
203 | d4t->kick(clk); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int sh_clk_div4_enable(struct clk *clk) | ||
209 | { | ||
210 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static void sh_clk_div4_disable(struct clk *clk) | ||
215 | { | ||
216 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); | ||
217 | } | ||
218 | |||
163 | static struct clk_ops sh_clk_div4_clk_ops = { | 219 | static struct clk_ops sh_clk_div4_clk_ops = { |
164 | .recalc = sh_clk_div4_recalc, | 220 | .recalc = sh_clk_div4_recalc, |
221 | .set_rate = sh_clk_div4_set_rate, | ||
165 | .round_rate = sh_clk_div_round_rate, | 222 | .round_rate = sh_clk_div_round_rate, |
166 | }; | 223 | }; |
167 | 224 | ||
168 | int __init sh_clk_div4_register(struct clk *clks, int nr, | 225 | static struct clk_ops sh_clk_div4_enable_clk_ops = { |
169 | struct clk_div_mult_table *table) | 226 | .recalc = sh_clk_div4_recalc, |
227 | .set_rate = sh_clk_div4_set_rate, | ||
228 | .round_rate = sh_clk_div_round_rate, | ||
229 | .enable = sh_clk_div4_enable, | ||
230 | .disable = sh_clk_div4_disable, | ||
231 | }; | ||
232 | |||
233 | static struct clk_ops sh_clk_div4_reparent_clk_ops = { | ||
234 | .recalc = sh_clk_div4_recalc, | ||
235 | .set_rate = sh_clk_div4_set_rate, | ||
236 | .round_rate = sh_clk_div_round_rate, | ||
237 | .enable = sh_clk_div4_enable, | ||
238 | .disable = sh_clk_div4_disable, | ||
239 | .set_parent = sh_clk_div4_set_parent, | ||
240 | }; | ||
241 | |||
242 | static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, | ||
243 | struct clk_div4_table *table, struct clk_ops *ops) | ||
170 | { | 244 | { |
171 | struct clk *clkp; | 245 | struct clk *clkp; |
172 | void *freq_table; | 246 | void *freq_table; |
173 | int nr_divs = table->nr_divisors; | 247 | int nr_divs = table->div_mult_table->nr_divisors; |
174 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | 248 | int freq_table_size = sizeof(struct cpufreq_frequency_table); |
175 | int ret = 0; | 249 | int ret = 0; |
176 | int k; | 250 | int k; |
@@ -185,7 +259,7 @@ int __init sh_clk_div4_register(struct clk *clks, int nr, | |||
185 | for (k = 0; !ret && (k < nr); k++) { | 259 | for (k = 0; !ret && (k < nr); k++) { |
186 | clkp = clks + k; | 260 | clkp = clks + k; |
187 | 261 | ||
188 | clkp->ops = &sh_clk_div4_clk_ops; | 262 | clkp->ops = ops; |
189 | clkp->id = -1; | 263 | clkp->id = -1; |
190 | clkp->priv = table; | 264 | clkp->priv = table; |
191 | 265 | ||
@@ -198,6 +272,26 @@ int __init sh_clk_div4_register(struct clk *clks, int nr, | |||
198 | return ret; | 272 | return ret; |
199 | } | 273 | } |
200 | 274 | ||
275 | int __init sh_clk_div4_register(struct clk *clks, int nr, | ||
276 | struct clk_div4_table *table) | ||
277 | { | ||
278 | return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); | ||
279 | } | ||
280 | |||
281 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, | ||
282 | struct clk_div4_table *table) | ||
283 | { | ||
284 | return sh_clk_div4_register_ops(clks, nr, table, | ||
285 | &sh_clk_div4_enable_clk_ops); | ||
286 | } | ||
287 | |||
288 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | ||
289 | struct clk_div4_table *table) | ||
290 | { | ||
291 | return sh_clk_div4_register_ops(clks, nr, table, | ||
292 | &sh_clk_div4_reparent_clk_ops); | ||
293 | } | ||
294 | |||
201 | #ifdef CONFIG_SH_CLK_CPG_LEGACY | 295 | #ifdef CONFIG_SH_CLK_CPG_LEGACY |
202 | static struct clk master_clk = { | 296 | static struct clk master_clk = { |
203 | .name = "master_clk", | 297 | .name = "master_clk", |