]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/sh/clk/cpg.c
regulator: max8997: Convert max8997_safeout_ops to set_voltage_sel and list_voltage_table
[karo-tx-linux.git] / drivers / sh / clk / cpg.c
1 /*
2  * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
3  *
4  *  Copyright (C) 2010  Magnus Damm
5  *  Copyright (C) 2010 - 2012  Paul Mundt
6  *
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
9  * for more details.
10  */
11 #include <linux/clk.h>
12 #include <linux/compiler.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <linux/sh_clk.h>
16
17 #define CPG_CKSTP_BIT   BIT(8)
18
19 static unsigned int sh_clk_read(struct clk *clk)
20 {
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);
25
26         return ioread32(clk->mapped_reg);
27 }
28
29 static void sh_clk_write(int value, struct clk *clk)
30 {
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);
35         else
36                 iowrite32(value, clk->mapped_reg);
37 }
38
39 static int sh_clk_mstp_enable(struct clk *clk)
40 {
41         sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
42         return 0;
43 }
44
45 static void sh_clk_mstp_disable(struct clk *clk)
46 {
47         sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
48 }
49
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,
54 };
55
56 int __init sh_clk_mstp_register(struct clk *clks, int nr)
57 {
58         struct clk *clkp;
59         int ret = 0;
60         int k;
61
62         for (k = 0; !ret && (k < nr); k++) {
63                 clkp = clks + k;
64                 clkp->ops = &sh_clk_mstp_clk_ops;
65                 ret |= clk_register(clkp);
66         }
67
68         return ret;
69 }
70
71 /*
72  * Div/mult table lookup helpers
73  */
74 static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
75 {
76         return clk->priv;
77 }
78
79 static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
80 {
81         return clk_to_div_table(clk)->div_mult_table;
82 }
83
84 /*
85  * Common div ops
86  */
87 static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
88 {
89         return clk_rate_table_round(clk, clk->freq_table, rate);
90 }
91
92 static unsigned long sh_clk_div_recalc(struct clk *clk)
93 {
94         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
95         unsigned int idx;
96
97         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
98                              table, clk->arch_flags ? &clk->arch_flags : NULL);
99
100         idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
101
102         return clk->freq_table[idx].frequency;
103 }
104
105 static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
106 {
107         struct clk_div_table *dt = clk_to_div_table(clk);
108         unsigned long value;
109         int idx;
110
111         idx = clk_rate_table_find(clk, clk->freq_table, rate);
112         if (idx < 0)
113                 return idx;
114
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);
119
120         /* XXX: Should use a post-change notifier */
121         if (dt->kick)
122                 dt->kick(clk);
123
124         return 0;
125 }
126
127 static int sh_clk_div_enable(struct clk *clk)
128 {
129         sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
130         return 0;
131 }
132
133 static void sh_clk_div_disable(struct clk *clk)
134 {
135         unsigned int val;
136
137         val = sh_clk_read(clk);
138         val |= CPG_CKSTP_BIT;
139
140         /*
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.
144          */
145         if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
146                 val |= clk->div_mask;
147
148         sh_clk_write(val, clk);
149 }
150
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,
155 };
156
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,
163 };
164
165 static int __init sh_clk_init_parent(struct clk *clk)
166 {
167         u32 val;
168
169         if (clk->parent)
170                 return 0;
171
172         if (!clk->parent_table || !clk->parent_num)
173                 return 0;
174
175         if (!clk->src_width) {
176                 pr_err("sh_clk_init_parent: cannot select parent clock\n");
177                 return -EINVAL;
178         }
179
180         val  = (sh_clk_read(clk) >> clk->src_shift);
181         val &= (1 << clk->src_width) - 1;
182
183         if (val >= clk->parent_num) {
184                 pr_err("sh_clk_init_parent: parent table size failed\n");
185                 return -EINVAL;
186         }
187
188         clk_reparent(clk, clk->parent_table[val]);
189         if (!clk->parent) {
190                 pr_err("sh_clk_init_parent: unable to set parent");
191                 return -EINVAL;
192         }
193
194         return 0;
195 }
196
197 static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
198                         struct clk_div_table *table, struct sh_clk_ops *ops)
199 {
200         struct clk *clkp;
201         void *freq_table;
202         int nr_divs = table->div_mult_table->nr_divisors;
203         int freq_table_size = sizeof(struct cpufreq_frequency_table);
204         int ret = 0;
205         int k;
206
207         freq_table_size *= (nr_divs + 1);
208         freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
209         if (!freq_table) {
210                 pr_err("%s: unable to alloc memory\n", __func__);
211                 return -ENOMEM;
212         }
213
214         for (k = 0; !ret && (k < nr); k++) {
215                 clkp = clks + k;
216
217                 clkp->ops = ops;
218                 clkp->priv = table;
219
220                 clkp->freq_table = freq_table + (k * freq_table_size);
221                 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
222
223                 ret = clk_register(clkp);
224                 if (ret == 0)
225                         ret = sh_clk_init_parent(clkp);
226         }
227
228         return ret;
229 }
230
231 /*
232  * div6 support
233  */
234 static int sh_clk_div6_divisors[64] = {
235         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
236         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
237         33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
238         49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
239 };
240
241 static struct clk_div_mult_table div6_div_mult_table = {
242         .divisors = sh_clk_div6_divisors,
243         .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
244 };
245
246 static struct clk_div_table sh_clk_div6_table = {
247         .div_mult_table = &div6_div_mult_table,
248 };
249
250 static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
251 {
252         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
253         u32 value;
254         int ret, i;
255
256         if (!clk->parent_table || !clk->parent_num)
257                 return -EINVAL;
258
259         /* Search the parent */
260         for (i = 0; i < clk->parent_num; i++)
261                 if (clk->parent_table[i] == parent)
262                         break;
263
264         if (i == clk->parent_num)
265                 return -ENODEV;
266
267         ret = clk_reparent(clk, parent);
268         if (ret < 0)
269                 return ret;
270
271         value = sh_clk_read(clk) &
272                 ~(((1 << clk->src_width) - 1) << clk->src_shift);
273
274         sh_clk_write(value | (i << clk->src_shift), clk);
275
276         /* Rebuild the frequency table */
277         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
278                              table, NULL);
279
280         return 0;
281 }
282
283 static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
284         .recalc         = sh_clk_div_recalc,
285         .round_rate     = sh_clk_div_round_rate,
286         .set_rate       = sh_clk_div_set_rate,
287         .enable         = sh_clk_div_enable,
288         .disable        = sh_clk_div_disable,
289         .set_parent     = sh_clk_div6_set_parent,
290 };
291
292 int __init sh_clk_div6_register(struct clk *clks, int nr)
293 {
294         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
295                                        &sh_clk_div_enable_clk_ops);
296 }
297
298 int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
299 {
300         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
301                                        &sh_clk_div6_reparent_clk_ops);
302 }
303
304 /*
305  * div4 support
306  */
307 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
308 {
309         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
310         u32 value;
311         int ret;
312
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...
316          */
317
318         if (parent->flags & CLK_ENABLE_ON_INIT)
319                 value = sh_clk_read(clk) & ~(1 << 7);
320         else
321                 value = sh_clk_read(clk) | (1 << 7);
322
323         ret = clk_reparent(clk, parent);
324         if (ret < 0)
325                 return ret;
326
327         sh_clk_write(value, clk);
328
329         /* Rebiuld the frequency table */
330         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
331                              table, &clk->arch_flags);
332
333         return 0;
334 }
335
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,
343 };
344
345 int __init sh_clk_div4_register(struct clk *clks, int nr,
346                                 struct clk_div4_table *table)
347 {
348         return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
349 }
350
351 int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
352                                 struct clk_div4_table *table)
353 {
354         return sh_clk_div_register_ops(clks, nr, table,
355                                        &sh_clk_div_enable_clk_ops);
356 }
357
358 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
359                                 struct clk_div4_table *table)
360 {
361         return sh_clk_div_register_ops(clks, nr, table,
362                                        &sh_clk_div4_reparent_clk_ops);
363 }
364
365 /* FSI-DIV */
366 static unsigned long fsidiv_recalc(struct clk *clk)
367 {
368         u32 value;
369
370         value = __raw_readl(clk->mapping->base);
371
372         value >>= 16;
373         if (value < 2)
374                 return clk->parent->rate;
375
376         return clk->parent->rate / value;
377 }
378
379 static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
380 {
381         return clk_rate_div_range_round(clk, 1, 0xffff, rate);
382 }
383
384 static void fsidiv_disable(struct clk *clk)
385 {
386         __raw_writel(0, clk->mapping->base);
387 }
388
389 static int fsidiv_enable(struct clk *clk)
390 {
391         u32 value;
392
393         value  = __raw_readl(clk->mapping->base) >> 16;
394         if (value < 2)
395                 return 0;
396
397         __raw_writel((value << 16) | 0x3, clk->mapping->base);
398
399         return 0;
400 }
401
402 static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
403 {
404         int idx;
405
406         idx = (clk->parent->rate / rate) & 0xffff;
407         if (idx < 2)
408                 __raw_writel(0, clk->mapping->base);
409         else
410                 __raw_writel(idx << 16, clk->mapping->base);
411
412         return 0;
413 }
414
415 static struct sh_clk_ops fsidiv_clk_ops = {
416         .recalc         = fsidiv_recalc,
417         .round_rate     = fsidiv_round_rate,
418         .set_rate       = fsidiv_set_rate,
419         .enable         = fsidiv_enable,
420         .disable        = fsidiv_disable,
421 };
422
423 int __init sh_clk_fsidiv_register(struct clk *clks, int nr)
424 {
425         struct clk_mapping *map;
426         int i;
427
428         for (i = 0; i < nr; i++) {
429
430                 map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL);
431                 if (!map) {
432                         pr_err("%s: unable to alloc memory\n", __func__);
433                         return -ENOMEM;
434                 }
435
436                 /* clks[i].enable_reg came from SH_CLK_FSIDIV() */
437                 map->phys               = (phys_addr_t)clks[i].enable_reg;
438                 map->len                = 8;
439
440                 clks[i].enable_reg      = 0; /* remove .enable_reg */
441                 clks[i].ops             = &fsidiv_clk_ops;
442                 clks[i].mapping         = map;
443
444                 clk_register(&clks[i]);
445         }
446
447         return 0;
448 }