Linux 3.14.25
[platform/adaptation/renesas_rcar/renesas_kernel.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         if (clk->div_mask == SH_CLK_DIV6_MSK) {
130                 int ret = sh_clk_div_set_rate(clk, clk->rate);
131                 if (ret < 0)
132                         return ret;
133         }
134
135         sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
136         return 0;
137 }
138
139 static void sh_clk_div_disable(struct clk *clk)
140 {
141         unsigned int val;
142
143         val = sh_clk_read(clk);
144         val |= CPG_CKSTP_BIT;
145
146         /*
147          * div6 clocks require the divisor field to be non-zero or the
148          * above CKSTP toggle silently fails. Ensure that the divisor
149          * array is reset to its initial state on disable.
150          */
151         if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
152                 val |= clk->div_mask;
153
154         sh_clk_write(val, clk);
155 }
156
157 static struct sh_clk_ops sh_clk_div_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 };
162
163 static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
164         .recalc         = sh_clk_div_recalc,
165         .set_rate       = sh_clk_div_set_rate,
166         .round_rate     = sh_clk_div_round_rate,
167         .enable         = sh_clk_div_enable,
168         .disable        = sh_clk_div_disable,
169 };
170
171 static int __init sh_clk_init_parent(struct clk *clk)
172 {
173         u32 val;
174
175         if (clk->parent)
176                 return 0;
177
178         if (!clk->parent_table || !clk->parent_num)
179                 return 0;
180
181         if (!clk->src_width) {
182                 pr_err("sh_clk_init_parent: cannot select parent clock\n");
183                 return -EINVAL;
184         }
185
186         val  = (sh_clk_read(clk) >> clk->src_shift);
187         val &= (1 << clk->src_width) - 1;
188
189         if (val >= clk->parent_num) {
190                 pr_err("sh_clk_init_parent: parent table size failed\n");
191                 return -EINVAL;
192         }
193
194         clk_reparent(clk, clk->parent_table[val]);
195         if (!clk->parent) {
196                 pr_err("sh_clk_init_parent: unable to set parent");
197                 return -EINVAL;
198         }
199
200         return 0;
201 }
202
203 static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
204                         struct clk_div_table *table, struct sh_clk_ops *ops)
205 {
206         struct clk *clkp;
207         void *freq_table;
208         int nr_divs = table->div_mult_table->nr_divisors;
209         int freq_table_size = sizeof(struct cpufreq_frequency_table);
210         int ret = 0;
211         int k;
212
213         freq_table_size *= (nr_divs + 1);
214         freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
215         if (!freq_table) {
216                 pr_err("%s: unable to alloc memory\n", __func__);
217                 return -ENOMEM;
218         }
219
220         for (k = 0; !ret && (k < nr); k++) {
221                 clkp = clks + k;
222
223                 clkp->ops = ops;
224                 clkp->priv = table;
225
226                 clkp->freq_table = freq_table + (k * freq_table_size);
227                 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
228
229                 ret = clk_register(clkp);
230                 if (ret == 0)
231                         ret = sh_clk_init_parent(clkp);
232         }
233
234         return ret;
235 }
236
237 /*
238  * div6 support
239  */
240 static int sh_clk_div6_divisors[64] = {
241         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
242         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
243         33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
244         49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
245 };
246
247 static struct clk_div_mult_table div6_div_mult_table = {
248         .divisors = sh_clk_div6_divisors,
249         .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
250 };
251
252 static struct clk_div_table sh_clk_div6_table = {
253         .div_mult_table = &div6_div_mult_table,
254 };
255
256 static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
257 {
258         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
259         u32 value;
260         int ret, i;
261
262         if (!clk->parent_table || !clk->parent_num)
263                 return -EINVAL;
264
265         /* Search the parent */
266         for (i = 0; i < clk->parent_num; i++)
267                 if (clk->parent_table[i] == parent)
268                         break;
269
270         if (i == clk->parent_num)
271                 return -ENODEV;
272
273         ret = clk_reparent(clk, parent);
274         if (ret < 0)
275                 return ret;
276
277         value = sh_clk_read(clk) &
278                 ~(((1 << clk->src_width) - 1) << clk->src_shift);
279
280         sh_clk_write(value | (i << clk->src_shift), clk);
281
282         /* Rebuild the frequency table */
283         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
284                              table, NULL);
285
286         return 0;
287 }
288
289 static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
290         .recalc         = sh_clk_div_recalc,
291         .round_rate     = sh_clk_div_round_rate,
292         .set_rate       = sh_clk_div_set_rate,
293         .enable         = sh_clk_div_enable,
294         .disable        = sh_clk_div_disable,
295         .set_parent     = sh_clk_div6_set_parent,
296 };
297
298 int __init sh_clk_div6_register(struct clk *clks, int nr)
299 {
300         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
301                                        &sh_clk_div_enable_clk_ops);
302 }
303
304 int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
305 {
306         return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
307                                        &sh_clk_div6_reparent_clk_ops);
308 }
309
310 /*
311  * div4 support
312  */
313 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
314 {
315         struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
316         u32 value;
317         int ret;
318
319         /* we really need a better way to determine parent index, but for
320          * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
321          * no CLK_ENABLE_ON_INIT means external clock...
322          */
323
324         if (parent->flags & CLK_ENABLE_ON_INIT)
325                 value = sh_clk_read(clk) & ~(1 << 7);
326         else
327                 value = sh_clk_read(clk) | (1 << 7);
328
329         ret = clk_reparent(clk, parent);
330         if (ret < 0)
331                 return ret;
332
333         sh_clk_write(value, clk);
334
335         /* Rebiuld the frequency table */
336         clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
337                              table, &clk->arch_flags);
338
339         return 0;
340 }
341
342 static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
343         .recalc         = sh_clk_div_recalc,
344         .set_rate       = sh_clk_div_set_rate,
345         .round_rate     = sh_clk_div_round_rate,
346         .enable         = sh_clk_div_enable,
347         .disable        = sh_clk_div_disable,
348         .set_parent     = sh_clk_div4_set_parent,
349 };
350
351 int __init sh_clk_div4_register(struct clk *clks, int nr,
352                                 struct clk_div4_table *table)
353 {
354         return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
355 }
356
357 int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
358                                 struct clk_div4_table *table)
359 {
360         return sh_clk_div_register_ops(clks, nr, table,
361                                        &sh_clk_div_enable_clk_ops);
362 }
363
364 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
365                                 struct clk_div4_table *table)
366 {
367         return sh_clk_div_register_ops(clks, nr, table,
368                                        &sh_clk_div4_reparent_clk_ops);
369 }
370
371 /* FSI-DIV */
372 static unsigned long fsidiv_recalc(struct clk *clk)
373 {
374         u32 value;
375
376         value = __raw_readl(clk->mapping->base);
377
378         value >>= 16;
379         if (value < 2)
380                 return clk->parent->rate;
381
382         return clk->parent->rate / value;
383 }
384
385 static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
386 {
387         return clk_rate_div_range_round(clk, 1, 0xffff, rate);
388 }
389
390 static void fsidiv_disable(struct clk *clk)
391 {
392         __raw_writel(0, clk->mapping->base);
393 }
394
395 static int fsidiv_enable(struct clk *clk)
396 {
397         u32 value;
398
399         value  = __raw_readl(clk->mapping->base) >> 16;
400         if (value < 2)
401                 return 0;
402
403         __raw_writel((value << 16) | 0x3, clk->mapping->base);
404
405         return 0;
406 }
407
408 static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
409 {
410         int idx;
411
412         idx = (clk->parent->rate / rate) & 0xffff;
413         if (idx < 2)
414                 __raw_writel(0, clk->mapping->base);
415         else
416                 __raw_writel(idx << 16, clk->mapping->base);
417
418         return 0;
419 }
420
421 static struct sh_clk_ops fsidiv_clk_ops = {
422         .recalc         = fsidiv_recalc,
423         .round_rate     = fsidiv_round_rate,
424         .set_rate       = fsidiv_set_rate,
425         .enable         = fsidiv_enable,
426         .disable        = fsidiv_disable,
427 };
428
429 int __init sh_clk_fsidiv_register(struct clk *clks, int nr)
430 {
431         struct clk_mapping *map;
432         int i;
433
434         for (i = 0; i < nr; i++) {
435
436                 map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL);
437                 if (!map) {
438                         pr_err("%s: unable to alloc memory\n", __func__);
439                         return -ENOMEM;
440                 }
441
442                 /* clks[i].enable_reg came from SH_CLK_FSIDIV() */
443                 map->phys               = (phys_addr_t)clks[i].enable_reg;
444                 map->len                = 8;
445
446                 clks[i].enable_reg      = 0; /* remove .enable_reg */
447                 clks[i].ops             = &fsidiv_clk_ops;
448                 clks[i].mapping         = map;
449
450                 clk_register(&clks[i]);
451         }
452
453         return 0;
454 }