2 * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
4 * Copyright (C) 2010 Magnus Damm
5 * Copyright (C) 2010 - 2012 Paul Mundt
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
11 #include <linux/clk.h>
12 #include <linux/compiler.h>
13 #include <linux/slab.h>
15 #include <linux/sh_clk.h>
17 #define CPG_CKSTP_BIT BIT(8)
19 static unsigned int sh_clk_read(struct clk *clk)
21 if (clk->flags & CLK_ENABLE_REG_8BIT)
22 return ioread8(clk->mapped_reg);
23 else if (clk->flags & CLK_ENABLE_REG_16BIT)
24 return ioread16(clk->mapped_reg);
26 return ioread32(clk->mapped_reg);
29 static void sh_clk_write(int value, struct clk *clk)
31 if (clk->flags & CLK_ENABLE_REG_8BIT)
32 iowrite8(value, clk->mapped_reg);
33 else if (clk->flags & CLK_ENABLE_REG_16BIT)
34 iowrite16(value, clk->mapped_reg);
36 iowrite32(value, clk->mapped_reg);
39 static int sh_clk_mstp_enable(struct clk *clk)
41 sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
45 static void sh_clk_mstp_disable(struct clk *clk)
47 sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
50 static struct sh_clk_ops sh_clk_mstp_clk_ops = {
51 .enable = sh_clk_mstp_enable,
52 .disable = sh_clk_mstp_disable,
53 .recalc = followparent_recalc,
56 int __init sh_clk_mstp_register(struct clk *clks, int nr)
62 for (k = 0; !ret && (k < nr); k++) {
64 clkp->ops = &sh_clk_mstp_clk_ops;
65 ret |= clk_register(clkp);
72 * Div/mult table lookup helpers
74 static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
79 static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
81 return clk_to_div_table(clk)->div_mult_table;
87 static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
89 return clk_rate_table_round(clk, clk->freq_table, rate);
92 static unsigned long sh_clk_div_recalc(struct clk *clk)
94 struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
97 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
98 table, clk->arch_flags ? &clk->arch_flags : NULL);
100 idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
102 return clk->freq_table[idx].frequency;
105 static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
107 struct clk_div_table *dt = clk_to_div_table(clk);
111 idx = clk_rate_table_find(clk, clk->freq_table, rate);
115 value = sh_clk_read(clk);
116 value &= ~(clk->div_mask << clk->enable_bit);
117 value |= (idx << clk->enable_bit);
118 sh_clk_write(value, clk);
120 /* XXX: Should use a post-change notifier */
127 static int sh_clk_div_enable(struct clk *clk)
129 sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
133 static void sh_clk_div_disable(struct clk *clk)
137 val = sh_clk_read(clk);
138 val |= CPG_CKSTP_BIT;
141 * div6 clocks require the divisor field to be non-zero or the
142 * above CKSTP toggle silently fails. Ensure that the divisor
143 * array is reset to its initial state on disable.
145 if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
146 val |= clk->div_mask;
148 sh_clk_write(val, clk);
151 static struct sh_clk_ops sh_clk_div_clk_ops = {
152 .recalc = sh_clk_div_recalc,
153 .set_rate = sh_clk_div_set_rate,
154 .round_rate = sh_clk_div_round_rate,
157 static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
158 .recalc = sh_clk_div_recalc,
159 .set_rate = sh_clk_div_set_rate,
160 .round_rate = sh_clk_div_round_rate,
161 .enable = sh_clk_div_enable,
162 .disable = sh_clk_div_disable,
168 static int sh_clk_div6_divisors[64] = {
169 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
170 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
171 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
172 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
175 static struct clk_div_mult_table div6_div_mult_table = {
176 .divisors = sh_clk_div6_divisors,
177 .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
180 static struct clk_div_table sh_clk_div6_table = {
181 .div_mult_table = &div6_div_mult_table,
184 static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
186 struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
190 if (!clk->parent_table || !clk->parent_num)
193 /* Search the parent */
194 for (i = 0; i < clk->parent_num; i++)
195 if (clk->parent_table[i] == parent)
198 if (i == clk->parent_num)
201 ret = clk_reparent(clk, parent);
205 value = sh_clk_read(clk) &
206 ~(((1 << clk->src_width) - 1) << clk->src_shift);
208 sh_clk_write(value | (i << clk->src_shift), clk);
210 /* Rebuild the frequency table */
211 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
217 static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
218 .recalc = sh_clk_div_recalc,
219 .round_rate = sh_clk_div_round_rate,
220 .set_rate = sh_clk_div_set_rate,
221 .enable = sh_clk_div_enable,
222 .disable = sh_clk_div_disable,
223 .set_parent = sh_clk_div6_set_parent,
226 static int __init sh_clk_init_parent(struct clk *clk)
233 if (!clk->parent_table || !clk->parent_num)
236 if (!clk->src_width) {
237 pr_err("sh_clk_init_parent: cannot select parent clock\n");
241 val = (sh_clk_read(clk) >> clk->src_shift);
242 val &= (1 << clk->src_width) - 1;
244 if (val >= clk->parent_num) {
245 pr_err("sh_clk_init_parent: parent table size failed\n");
249 clk_reparent(clk, clk->parent_table[val]);
251 pr_err("sh_clk_init_parent: unable to set parent");
258 static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
259 struct sh_clk_ops *ops)
263 struct clk_div_table *table = &sh_clk_div6_table;
264 int nr_divs = table->div_mult_table->nr_divisors;
265 int freq_table_size = sizeof(struct cpufreq_frequency_table);
269 freq_table_size *= (nr_divs + 1);
270 freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
272 pr_err("sh_clk_div6_register: unable to alloc memory\n");
276 for (k = 0; !ret && (k < nr); k++) {
281 clkp->freq_table = freq_table + (k * freq_table_size);
282 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
283 ret = clk_register(clkp);
287 ret = sh_clk_init_parent(clkp);
293 int __init sh_clk_div6_register(struct clk *clks, int nr)
295 return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops);
298 int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
300 return sh_clk_div6_register_ops(clks, nr,
301 &sh_clk_div6_reparent_clk_ops);
307 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
309 struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
313 /* we really need a better way to determine parent index, but for
314 * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
315 * no CLK_ENABLE_ON_INIT means external clock...
318 if (parent->flags & CLK_ENABLE_ON_INIT)
319 value = sh_clk_read(clk) & ~(1 << 7);
321 value = sh_clk_read(clk) | (1 << 7);
323 ret = clk_reparent(clk, parent);
327 sh_clk_write(value, clk);
329 /* Rebiuld the frequency table */
330 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
331 table, &clk->arch_flags);
336 static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
337 .recalc = sh_clk_div_recalc,
338 .set_rate = sh_clk_div_set_rate,
339 .round_rate = sh_clk_div_round_rate,
340 .enable = sh_clk_div_enable,
341 .disable = sh_clk_div_disable,
342 .set_parent = sh_clk_div4_set_parent,
345 static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
346 struct clk_div4_table *table, struct sh_clk_ops *ops)
350 int nr_divs = table->div_mult_table->nr_divisors;
351 int freq_table_size = sizeof(struct cpufreq_frequency_table);
355 freq_table_size *= (nr_divs + 1);
356 freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
358 pr_err("sh_clk_div4_register: unable to alloc memory\n");
362 for (k = 0; !ret && (k < nr); k++) {
368 clkp->freq_table = freq_table + (k * freq_table_size);
369 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
371 ret = clk_register(clkp);
377 int __init sh_clk_div4_register(struct clk *clks, int nr,
378 struct clk_div4_table *table)
380 return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
383 int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
384 struct clk_div4_table *table)
386 return sh_clk_div4_register_ops(clks, nr, table,
387 &sh_clk_div_enable_clk_ops);
390 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
391 struct clk_div4_table *table)
393 return sh_clk_div4_register_ops(clks, nr, table,
394 &sh_clk_div4_reparent_clk_ops);