Mention branches and keyring.
[releases.git] / 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         if (clk->status_reg) {
43                 unsigned int (*read)(const void __iomem *addr);
44                 int i;
45                 void __iomem *mapped_status = (phys_addr_t)clk->status_reg -
46                         (phys_addr_t)clk->enable_reg + clk->mapped_reg;
47
48                 if (clk->flags & CLK_ENABLE_REG_8BIT)
49                         read = ioread8;
50                 else if (clk->flags & CLK_ENABLE_REG_16BIT)
51                         read = ioread16;
52                 else
53                         read = ioread32;
54
55                 for (i = 1000;
56                      (read(mapped_status) & (1 << clk->enable_bit)) && i;
57                      i--)
58                         cpu_relax();
59                 if (!i) {
60                         pr_err("cpg: failed to enable %p[%d]\n",
61                                clk->enable_reg, clk->enable_bit);
62                         return -ETIMEDOUT;
63                 }
64         }
65         return 0;
66 }
67
68 static void sh_clk_mstp_disable(struct clk *clk)
69 {
70         sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
71 }
72
73 static struct sh_clk_ops sh_clk_mstp_clk_ops = {
74         .enable         = sh_clk_mstp_enable,
75         .disable        = sh_clk_mstp_disable,
76         .recalc         = followparent_recalc,
77 };
78
79 int __init sh_clk_mstp_register(struct clk *clks, int nr)
80 {
81         struct clk *clkp;
82         int ret = 0;
83         int k;
84
85         for (k = 0; !ret && (k < nr); k++) {
86                 clkp = clks + k;
87                 clkp->ops = &sh_clk_mstp_clk_ops;
88                 ret |= clk_register(clkp);
89         }
90
91         return ret;
92 }
93
94 /*
95  * Div/mult table lookup helpers
96  */
97 static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
98 {
99         return clk->priv;
100 }
101
102 static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
103 {
104         return clk_to_div_table(clk)->div_mult_table;
105 }
106
107 /*
108  * Common div ops
109  */
110 static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
111 {
112         return clk_rate_table_round(clk, clk->freq_table, rate);
113 }
114
115 static unsigned long sh_clk_div_recalc(struct clk *clk)
116 {
117         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
118         unsigned int idx;
119
120         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
121                              table, clk->arch_flags ? &clk->arch_flags : NULL);
122
123         idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
124
125         return clk->freq_table[idx].frequency;
126 }
127
128 static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
129 {
130         struct clk_div_table *dt = clk_to_div_table(clk);
131         unsigned long value;
132         int idx;
133
134         idx = clk_rate_table_find(clk, clk->freq_table, rate);
135         if (idx < 0)
136                 return idx;
137
138         value = sh_clk_read(clk);
139         value &= ~(clk->div_mask << clk->enable_bit);
140         value |= (idx << clk->enable_bit);
141         sh_clk_write(value, clk);
142
143         /* XXX: Should use a post-change notifier */
144         if (dt->kick)
145                 dt->kick(clk);
146
147         return 0;
148 }
149
150 static int sh_clk_div_enable(struct clk *clk)
151 {
152         if (clk->div_mask == SH_CLK_DIV6_MSK) {
153                 int ret = sh_clk_div_set_rate(clk, clk->rate);
154                 if (ret < 0)
155                         return ret;
156         }
157
158         sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
159         return 0;
160 }
161
162 static void sh_clk_div_disable(struct clk *clk)
163 {
164         unsigned int val;
165
166         val = sh_clk_read(clk);
167         val |= CPG_CKSTP_BIT;
168
169         /*
170          * div6 clocks require the divisor field to be non-zero or the
171          * above CKSTP toggle silently fails. Ensure that the divisor
172          * array is reset to its initial state on disable.
173          */
174         if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
175                 val |= clk->div_mask;
176
177         sh_clk_write(val, clk);
178 }
179
180 static struct sh_clk_ops sh_clk_div_clk_ops = {
181         .recalc         = sh_clk_div_recalc,
182         .set_rate       = sh_clk_div_set_rate,
183         .round_rate     = sh_clk_div_round_rate,
184 };
185
186 static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
187         .recalc         = sh_clk_div_recalc,
188         .set_rate       = sh_clk_div_set_rate,
189         .round_rate     = sh_clk_div_round_rate,
190         .enable         = sh_clk_div_enable,
191         .disable        = sh_clk_div_disable,
192 };
193
194 static int __init sh_clk_init_parent(struct clk *clk)
195 {
196         u32 val;
197
198         if (clk->parent)
199                 return 0;
200
201         if (!clk->parent_table || !clk->parent_num)
202                 return 0;
203
204         if (!clk->src_width) {
205                 pr_err("sh_clk_init_parent: cannot select parent clock\n");
206                 return -EINVAL;
207         }
208
209         val  = (sh_clk_read(clk) >> clk->src_shift);
210         val &= (1 << clk->src_width) - 1;
211
212         if (val >= clk->parent_num) {
213                 pr_err("sh_clk_init_parent: parent table size failed\n");
214                 return -EINVAL;
215         }
216
217         clk_reparent(clk, clk->parent_table[val]);
218         if (!clk->parent) {
219                 pr_err("sh_clk_init_parent: unable to set parent");
220                 return -EINVAL;
221         }
222
223         return 0;
224 }
225
226 static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
227                         struct clk_div_table *table, struct sh_clk_ops *ops)
228 {
229         struct clk *clkp;
230         void *freq_table;
231         int nr_divs = table->div_mult_table->nr_divisors;
232         int freq_table_size = sizeof(struct cpufreq_frequency_table);
233         int ret = 0;
234         int k;
235
236         freq_table_size *= (nr_divs + 1);
237         freq_table = kcalloc(nr, freq_table_size, GFP_KERNEL);
238         if (!freq_table) {
239                 pr_err("%s: unable to alloc memory\n", __func__);
240                 return -ENOMEM;
241         }
242
243         for (k = 0; !ret && (k < nr); k++) {
244                 clkp = clks + k;
245
246                 clkp->ops = ops;
247                 clkp->priv = table;
248
249                 clkp->freq_table = freq_table + (k * freq_table_size);
250                 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
251
252                 ret = clk_register(clkp);
253                 if (ret == 0)
254                         ret = sh_clk_init_parent(clkp);
255         }
256
257         return ret;
258 }
259
260 /*
261  * div6 support
262  */
263 static int sh_clk_div6_divisors[64] = {
264         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
265         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
266         33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
267         49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
268 };
269
270 static struct clk_div_mult_table div6_div_mult_table = {
271         .divisors = sh_clk_div6_divisors,
272         .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
273 };
274
275 static struct clk_div_table sh_clk_div6_table = {
276         .div_mult_table = &div6_div_mult_table,
277 };
278
279 static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
280 {
281         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
282         u32 value;
283         int ret, i;
284
285         if (!clk->parent_table || !clk->parent_num)
286                 return -EINVAL;
287
288         /* Search the parent */
289         for (i = 0; i < clk->parent_num; i++)
290                 if (clk->parent_table[i] == parent)
291                         break;
292
293         if (i == clk->parent_num)
294                 return -ENODEV;
295
296         ret = clk_reparent(clk, parent);
297         if (ret < 0)
298                 return ret;
299
300         value = sh_clk_read(clk) &
301                 ~(((1 << clk->src_width) - 1) << clk->src_shift);
302
303         sh_clk_write(value | (i << clk->src_shift), clk);
304
305         /* Rebuild the frequency table */
306         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
307                              table, NULL);
308
309         return 0;
310 }
311
312 static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
313         .recalc         = sh_clk_div_recalc,
314         .round_rate     = sh_clk_div_round_rate,
315         .set_rate       = sh_clk_div_set_rate,
316         .enable         = sh_clk_div_enable,
317         .disable        = sh_clk_div_disable,
318         .set_parent     = sh_clk_div6_set_parent,
319 };
320
321 int __init sh_clk_div6_register(struct clk *clks, int nr)
322 {
323         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
324                                        &sh_clk_div_enable_clk_ops);
325 }
326
327 int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
328 {
329         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
330                                        &sh_clk_div6_reparent_clk_ops);
331 }
332
333 /*
334  * div4 support
335  */
336 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
337 {
338         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
339         u32 value;
340         int ret;
341
342         /* we really need a better way to determine parent index, but for
343          * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
344          * no CLK_ENABLE_ON_INIT means external clock...
345          */
346
347         if (parent->flags & CLK_ENABLE_ON_INIT)
348                 value = sh_clk_read(clk) & ~(1 << 7);
349         else
350                 value = sh_clk_read(clk) | (1 << 7);
351
352         ret = clk_reparent(clk, parent);
353         if (ret < 0)
354                 return ret;
355
356         sh_clk_write(value, clk);
357
358         /* Rebiuld the frequency table */
359         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
360                              table, &clk->arch_flags);
361
362         return 0;
363 }
364
365 static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
366         .recalc         = sh_clk_div_recalc,
367         .set_rate       = sh_clk_div_set_rate,
368         .round_rate     = sh_clk_div_round_rate,
369         .enable         = sh_clk_div_enable,
370         .disable        = sh_clk_div_disable,
371         .set_parent     = sh_clk_div4_set_parent,
372 };
373
374 int __init sh_clk_div4_register(struct clk *clks, int nr,
375                                 struct clk_div4_table *table)
376 {
377         return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
378 }
379
380 int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
381                                 struct clk_div4_table *table)
382 {
383         return sh_clk_div_register_ops(clks, nr, table,
384                                        &sh_clk_div_enable_clk_ops);
385 }
386
387 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
388                                 struct clk_div4_table *table)
389 {
390         return sh_clk_div_register_ops(clks, nr, table,
391                                        &sh_clk_div4_reparent_clk_ops);
392 }
393
394 /* FSI-DIV */
395 static unsigned long fsidiv_recalc(struct clk *clk)
396 {
397         u32 value;
398
399         value = __raw_readl(clk->mapping->base);
400
401         value >>= 16;
402         if (value < 2)
403                 return clk->parent->rate;
404
405         return clk->parent->rate / value;
406 }
407
408 static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
409 {
410         return clk_rate_div_range_round(clk, 1, 0xffff, rate);
411 }
412
413 static void fsidiv_disable(struct clk *clk)
414 {
415         __raw_writel(0, clk->mapping->base);
416 }
417
418 static int fsidiv_enable(struct clk *clk)
419 {
420         u32 value;
421
422         value  = __raw_readl(clk->mapping->base) >> 16;
423         if (value < 2)
424                 return 0;
425
426         __raw_writel((value << 16) | 0x3, clk->mapping->base);
427
428         return 0;
429 }
430
431 static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
432 {
433         int idx;
434
435         idx = (clk->parent->rate / rate) & 0xffff;
436         if (idx < 2)
437                 __raw_writel(0, clk->mapping->base);
438         else
439                 __raw_writel(idx << 16, clk->mapping->base);
440
441         return 0;
442 }
443
444 static struct sh_clk_ops fsidiv_clk_ops = {
445         .recalc         = fsidiv_recalc,
446         .round_rate     = fsidiv_round_rate,
447         .set_rate       = fsidiv_set_rate,
448         .enable         = fsidiv_enable,
449         .disable        = fsidiv_disable,
450 };
451
452 int __init sh_clk_fsidiv_register(struct clk *clks, int nr)
453 {
454         struct clk_mapping *map;
455         int i;
456
457         for (i = 0; i < nr; i++) {
458
459                 map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL);
460                 if (!map) {
461                         pr_err("%s: unable to alloc memory\n", __func__);
462                         return -ENOMEM;
463                 }
464
465                 /* clks[i].enable_reg came from SH_CLK_FSIDIV() */
466                 map->phys               = (phys_addr_t)clks[i].enable_reg;
467                 map->len                = 8;
468
469                 clks[i].enable_reg      = 0; /* remove .enable_reg */
470                 clks[i].ops             = &fsidiv_clk_ops;
471                 clks[i].mapping         = map;
472
473                 clk_register(&clks[i]);
474         }
475
476         return 0;
477 }