change source file mode to 0644 instead of 0755
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8825 / clock.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15 #ifdef CONFIG_NKERNEL
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/debugfs.h>
20 #include <linux/err.h>
21 #include <linux/platform_device.h>
22 #include <linux/clk.h>
23 #include <linux/clkdev.h>
24 #include <linux/cpufreq.h>
25
26 #include <mach/sci.h>
27 #include <mach/hardware.h>
28 #include <mach/regs_glb.h>
29 #include <mach/regs_ahb.h>
30 #else
31 #include <ubi_uboot.h>
32 #include <asm/arch/sc8810_reg_base.h>
33 #include <asm/arch/regs_glb.h>
34 #include <asm/arch/__regs_ahb.h>
35 #include <linux/compiler.h>
36
37 #define __ffs(x) (ffs(x) - 1)
38
39 #define DEFINE_SPINLOCK(...)
40 #define spin_lock_irqsave(...)
41 #define spin_unlock_irqrestore(...)
42 #endif
43
44 #include <asm/arch/clock.h>
45 #include <asm/arch/__clock_tree.h>
46
47 //#ifndef CONFIG_NKERNEL
48 #if 1
49 const u32 __clkinit0 __clkinit_begin = 0xeeeebbbb;
50 const u32 __clkinit2 __clkinit_end   = 0xddddeeee;
51 #else
52 const u32 __clkinit0 __clkinit_begin = &CLK_LK_clk_mpll;
53 const u32 __clkinit2 __clkinit_end   = &CLK_LK_clk_mpll;
54 #endif
55
56 #ifndef CONFIG_NKERNEL
57 //#define debug0 printf
58 #endif
59
60 DEFINE_SPINLOCK(clocks_lock);
61
62 int clk_enable(struct clk *clk)
63 {
64         unsigned long flags;
65         if (IS_ERR_OR_NULL(clk))
66                 return -EINVAL;
67
68         clk_enable(clk->parent);
69
70         spin_lock_irqsave(&clocks_lock, flags);
71         if ((clk->usage++) == 0 && clk->enable)
72                 (clk->enable) (clk, 1, &flags);
73         spin_unlock_irqrestore(&clocks_lock, flags);
74         debug0("clk %p, usage %d\n", clk, clk->usage);
75         return 0;
76 }
77
78 EXPORT_SYMBOL(clk_enable);
79
80 void clk_disable(struct clk *clk)
81 {
82         unsigned long flags;
83         if (IS_ERR_OR_NULL(clk))
84                 return;
85
86         spin_lock_irqsave(&clocks_lock, flags);
87         if ((--clk->usage) == 0 && clk->enable)
88                 (clk->enable) (clk, 0, &flags);
89         if (WARN(clk->usage < 0,
90                  "warning: clock (%s) usage (%d)\n", clk->regs->name, clk->usage)) {
91                 clk->usage = 0; /* force reset clock refcnt */
92                 spin_unlock_irqrestore(&clocks_lock, flags);
93                 return;
94         }
95         spin_unlock_irqrestore(&clocks_lock, flags);
96         debug0("clk %p, usage %d\n", clk, clk->usage);
97         clk_disable(clk->parent);
98 }
99
100 EXPORT_SYMBOL(clk_disable);
101
102 /**
103  * clk_force_disable - force disable clock output
104  * @clk: clock source
105  *
106  * Forcibly disable the clock output.
107  * NOTE: this *will* disable the clock output even if other consumer
108  * devices have it enabled. This should be used for situations when device
109  * suspend or damage will likely occur if the devices is not disabled.
110  */
111 void clk_force_disable(struct clk *clk)
112 {
113         if (IS_ERR_OR_NULL(clk))
114                 return;
115
116         debug("clk %p, usage %d\n", clk, clk->usage);
117         while (clk->usage > 0) {
118                 clk_disable(clk);
119         }
120 }
121
122 EXPORT_SYMBOL(clk_force_disable);
123
124 unsigned long clk_get_rate(struct clk *clk)
125 {
126         debug0("clk %p, rate %lu\n", clk, IS_ERR_OR_NULL(clk) ? -1 : clk->rate);
127         if (IS_ERR_OR_NULL(clk))
128                 return 0;
129
130 /*
131         if (clk->rate != 0)
132                 return clk->rate;
133 */
134
135         if (clk->ops != NULL && clk->ops->get_rate != NULL)
136                 return (clk->ops->get_rate) (clk);
137
138         if (clk->parent != NULL)
139                 return clk_get_rate(clk->parent);
140
141         return clk->rate;
142 }
143
144 EXPORT_SYMBOL(clk_get_rate);
145
146 long clk_round_rate(struct clk *clk, unsigned long rate)
147 {
148         if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
149                 return (clk->ops->round_rate) (clk, rate);
150
151         return rate;
152 }
153
154 EXPORT_SYMBOL(clk_round_rate);
155
156 int clk_set_rate(struct clk *clk, unsigned long rate)
157 {
158         int ret;
159         unsigned long flags;
160         debug0("clk %p, rate %lu\n", clk, rate);
161         if (IS_ERR_OR_NULL(clk) || rate == 0)
162                 return -EINVAL;
163
164         /* We do not default just do a clk->rate = rate as
165          * the clock may have been made this way by choice.
166          */
167
168         //WARN_ON(clk->ops == NULL);
169         //WARN_ON(clk->ops && clk->ops->set_rate == NULL);
170
171         if (clk->ops == NULL || clk->ops->set_rate == NULL)
172                 return -EINVAL;
173
174         spin_lock_irqsave(&clocks_lock, flags);
175         ret = (clk->ops->set_rate) (clk, rate);
176         spin_unlock_irqrestore(&clocks_lock, flags);
177         return ret;
178 }
179
180 EXPORT_SYMBOL(clk_set_rate);
181
182 struct clk *clk_get_parent(struct clk *clk)
183 {
184         return clk->parent;
185 }
186
187 EXPORT_SYMBOL(clk_get_parent);
188
189 int clk_set_parent(struct clk *clk, struct clk *parent)
190 {
191         int ret = -EACCES;
192         unsigned long flags;
193         struct clk *old_parent = clk_get_parent(clk);
194         debug0("clk %p, parent %p <<< %p\n", clk, parent, old_parent);
195         if (IS_ERR_OR_NULL(clk) || IS_ERR(parent))
196                 return -EINVAL;
197
198         spin_lock_irqsave(&clocks_lock, flags);
199         if (clk->ops && clk->ops->set_parent)
200                 ret = (clk->ops->set_parent) (clk, parent);
201         spin_unlock_irqrestore(&clocks_lock, flags);
202
203 #if defined(CONFIG_DEBUG_FS)
204         /* FIXME: call debugfs_rename() out of spin lock,
205          * maybe not match with the real parent-child relationship
206          * in some extreme scenes.
207          */
208         if (0 == ret && old_parent && old_parent->dent && clk->dent
209             && parent && parent->dent) {
210                 debug0("directory dentry move %s to %s\n",
211                        old_parent->regs->name, parent->regs->name);
212                 debugfs_rename(old_parent->dent, clk->dent,
213                                parent->dent, clk->regs->name);
214         }
215 #endif
216         return ret;
217 }
218
219 EXPORT_SYMBOL(clk_set_parent);
220
221 static int sci_clk_enable(struct clk *c, int enable, unsigned long *pflags)
222 {
223         debug("clk %p (%s) enb %08x, %s\n", c, c->regs->name,
224               c->regs->enb.reg, enable ? "enable" : "disable");
225
226         BUG_ON(!c->regs->enb.reg);
227         if (c->regs->enb.reg & 1)
228                 enable = !enable;
229
230         if (!c->regs->enb.mask) {       /* enable matrix clock */
231                 if (pflags)
232                         spin_unlock_irqrestore(&clocks_lock, *pflags);
233                 if (enable)
234                         clk_enable((struct clk *)c->regs->enb.reg);
235                 else
236                         clk_disable((struct clk *)c->regs->enb.reg);
237                 if (pflags)
238                         spin_lock_irqsave(&clocks_lock, *pflags);
239         } else {
240                 if (enable)
241                         sci_glb_set(c->regs->enb.reg & ~1, c->regs->enb.mask);
242                 else
243                         sci_glb_clr(c->regs->enb.reg & ~1, c->regs->enb.mask);
244         }
245         return 0;
246 }
247
248 static int sci_clk_is_enable(struct clk *c)
249 {
250         int enable;
251
252         debug0("clk %p (%s) enb %08x\n", c, c->regs->name, c->regs->enb.reg);
253
254         BUG_ON(!c->regs->enb.reg);
255         if (!c->regs->enb.mask) {       /* check matrix clock */
256                 enable = ! !sci_clk_is_enable((struct clk *)c->regs->enb.reg);
257         } else {
258                 enable =
259                     ! !sci_glb_read(c->regs->enb.reg & ~1, c->regs->enb.mask);
260         }
261
262         if (c->regs->enb.reg & 1)
263                 enable = !enable;
264         return enable;
265 }
266
267 static int sci_clk_set_rate(struct clk *c, unsigned long rate)
268 {
269         u32 div, div_shift;
270         debug("clk %p (%s) set rate %lu\n", c, c->regs->name, rate);
271         rate = clk_round_rate(c, rate);
272         div = clk_get_rate(c->parent) / rate - 1;       //FIXME:
273         div_shift = __ffs(c->regs->div.mask);
274         debug0("clk %p (%s) pll div reg %08x, val %08x mask %08x\n", c,
275                c->regs->name, c->regs->div.reg, div << div_shift,
276                c->regs->div.mask);
277         sci_glb_write(c->regs->div.reg, div << div_shift, c->regs->div.mask);
278
279         c->rate = 0;            /* FIXME: auto update all children after new rate if need */
280         return 0;
281 }
282
283 static unsigned long sci_clk_get_rate(struct clk *c)
284 {
285         u32 div = 0, div_shift;
286         unsigned long rate;
287         div_shift = __ffs(c->regs->div.mask);
288         debug0("clk %p (%s) div reg %08x, shift %u msk %08x\n", c,
289                c->regs->name, c->regs->div.reg, div_shift, c->regs->div.mask);
290         rate = clk_get_rate(c->parent);
291
292         if (c->regs->div.reg)
293                 div = sci_glb_read(c->regs->div.reg,
294                                    c->regs->div.mask) >> div_shift;
295         debug0("clk %p (%s) parent rate %lu, div %u\n", c, c->regs->name, rate,
296                div + 1);
297         c->rate = rate = rate / (div + 1);      //FIXME:
298         debug0("clk %p (%s) get real rate %lu\n", c, c->regs->name, rate);
299         return rate;
300 }
301
302 #define SHFT_PLL_REFIN                 ( 16 )
303 #define MASK_PLL_REFIN                 ( BIT(16)|BIT(17) )
304 static unsigned long sci_pll_get_refin_rate(struct clk *c)
305 {
306         int i;
307         const unsigned long refin[4] = { 2, 4, 4, 13 }; /* default refin 4M */
308         i = sci_glb_read(c->regs->div.reg, MASK_PLL_REFIN) >> SHFT_PLL_REFIN;
309         debug0("pll %p (%s) refin %d\n", c, c->regs->name, i);
310         return refin[i] * 1000000;
311 }
312
313 static unsigned long sci_pll_get_rate(struct clk *c)
314 {
315         u32 mn = 1, mn_shift;
316         unsigned long rate;
317         mn_shift = __ffs(c->regs->div.mask);
318         debug0("pll %p (%s) mn reg %08x, shift %u msk %08x\n", c, c->regs->name,
319                c->regs->div.reg, mn_shift, c->regs->div.mask);
320         rate = clk_get_rate(c->parent);
321         if (0 == c->regs->div.reg) ;
322         else if (c->regs->div.reg < MAX_DIV) {
323                 mn = c->regs->div.reg;
324                 if (mn)
325                         rate = rate / mn;
326         } else {
327                 rate = sci_pll_get_refin_rate(c);
328                 mn = sci_glb_read(c->regs->div.reg,
329                                   c->regs->div.mask) >> mn_shift;
330                 if (mn)
331                         rate = rate * mn;
332         }
333         c->rate = rate;
334         debug0("pll %p (%s) get real rate %lu\n", c, c->regs->name, rate);
335         return rate;
336 }
337
338 static unsigned long sci_clk_round_rate(struct clk *c, unsigned long rate)
339 {
340         debug0("clk %p (%s) round rate %lu\n", c, c->regs->name, rate);
341         return rate;
342 }
343
344 static int sci_clk_set_parent(struct clk *c, struct clk *parent)
345 {
346         int i;
347         debug0("clk %p (%s) parent %p (%s)\n", c, c->regs->name,
348                parent, parent ? parent->regs->name : 0);
349
350         for (i = 0; i < c->regs->nr_sources; i++) {
351                 if (c->regs->sources[i] == parent) {
352                         u32 sel_shift = __ffs(c->regs->sel.mask);
353                         debug0("pll sel reg %08x, val %08x, msk %08x\n",
354                                c->regs->sel.reg, i << sel_shift,
355                                c->regs->sel.mask);
356                         if (c->regs->sel.reg)
357                                 sci_glb_write(c->regs->sel.reg, i << sel_shift,
358                                               c->regs->sel.mask);
359                         c->parent = parent;
360                         if (c->ops)
361                                 c->rate = 0;    /* FIXME: auto update clock rate after new parent */
362                         return 0;
363                 }
364         }
365
366         WARN(1, "warning: clock (%s) not support parent (%s)\n",
367              c->regs->name, parent ? parent->regs->name : 0);
368         return -EINVAL;
369 }
370
371 static int sci_clk_get_parent(struct clk *c)
372 {
373         int i = 0;
374         u32 sel_shift = __ffs(c->regs->sel.mask);
375         debug0("pll sel reg %08x, val %08x, msk %08x\n",
376                c->regs->sel.reg, i << sel_shift, c->regs->sel.mask);
377         if (c->regs->sel.reg) {
378                 i = sci_glb_read(c->regs->sel.reg,
379                                  c->regs->sel.mask) >> sel_shift;
380         }
381         return i;
382 }
383
384 static struct clk_ops generic_clk_ops = {
385         .set_rate = sci_clk_set_rate,
386         .get_rate = sci_clk_get_rate,
387         .round_rate = sci_clk_round_rate,
388         .set_parent = sci_clk_set_parent,
389 };
390
391 static struct clk_ops generic_pll_ops = {
392         .set_rate = 0,
393         .get_rate = sci_pll_get_rate,
394         .round_rate = 0,
395         .set_parent = sci_clk_set_parent,
396 };
397
398 /* debugfs support to trace clock tree hierarchy and attributes */
399 #if defined(CONFIG_DEBUG_FS)
400 static struct dentry *clk_debugfs_root;
401 static int __init clk_debugfs_register(struct clk *c)
402 {
403         char name[NAME_MAX], *p = name;
404         p += sprintf(p, "%s", c->regs->name);
405
406         if (IS_ERR_OR_NULL((c->dent =
407                             debugfs_create_dir(name,
408                                                c->parent ? c->parent->dent :
409                                                clk_debugfs_root))))
410                 goto err_exit;
411         if (IS_ERR_OR_NULL(debugfs_create_u32
412                            ("usecount", S_IRUGO, c->dent, (u32 *) & c->usage)))
413                 goto err_exit;
414         if (IS_ERR_OR_NULL(debugfs_create_u32
415                            ("rate", S_IRUGO, c->dent, (u32 *) & c->rate)))
416                 goto err_exit;
417         return 0;
418 err_exit:
419         if (c->dent)
420                 debugfs_remove_recursive(c->dent);
421         return -ENOMEM;
422 }
423 #endif
424
425
426 static __init int __clk_is_dummy_pll(struct clk *c)
427 {
428         return (c->regs->enb.reg & 1) || strstr(c->regs->name, "pll");
429 }
430
431 int __init sci_clk_register(struct clk_lookup *cl)
432 {
433         struct clk *c = cl->clk;
434
435         if (c->ops == NULL) {
436                 c->ops = &generic_clk_ops;
437                 if (c->rate)    /* fixed OSC */
438                         c->ops = NULL;
439                 else if ((c->regs->div.reg >= 0 && c->regs->div.reg < MAX_DIV)
440                          || strstr(c->regs->name, "pll")) {
441                         c->ops = &generic_pll_ops;
442                 }
443         }
444
445         debug0
446             ("clk %p (%s) rate %lu ops %p enb %08x sel %08x div %08x nr_sources %u\n",
447              c, c->regs->name, c->rate, c->ops, c->regs->enb.reg,
448              c->regs->sel.reg, c->regs->div.reg, c->regs->nr_sources);
449
450         if (c->enable == NULL && c->regs->enb.reg) {
451                 c->enable = sci_clk_enable;
452                 /* FIXME: dummy update some pll clocks usage */
453                 if (sci_clk_is_enable(c) && __clk_is_dummy_pll(c)) {
454                         clk_enable(c);
455                 }
456         }
457
458         if (!c->rate) {         /* FIXME: dummy update clock parent and rate */
459                 clk_set_parent(c, c->regs->sources[sci_clk_get_parent(c)]);
460                 /* clk_set_rate(c, clk_get_rate(c)); */
461         }
462
463         clkdev_add(cl);
464
465 #if defined(CONFIG_DEBUG_FS)
466         clk_debugfs_register(c);
467 #endif
468         return 0;
469 }
470
471 static int __init sci_clock_dump(void)
472 {
473         struct clk_lookup *cl = (struct clk_lookup *)(&__clkinit_begin + 1);
474         while (cl < (struct clk_lookup *)&__clkinit_end) {
475                 struct clk *c = cl->clk;
476                 struct clk *p = clk_get_parent(c);
477                 printk
478                     ("@@@clock[%s] is %sactive, usage %d, rate %lu, parent[%s]\n",
479                      c->regs->name,
480                      (c->enable == NULL || sci_clk_is_enable(c)) ? "" : "in",
481                      c->usage, clk_get_rate(c), p ? p->regs->name : "none");
482                 cl++;
483         }
484         return 0;
485 }
486
487 static int __clk_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
488 {
489         struct cpufreq_freqs *freq = data;
490
491         printk("%s (%u) dump cpu freq (%u %u %u %u)\n",
492                __func__, (unsigned int)val,
493                freq->cpu, freq->old, freq->new, (unsigned int)freq->flags);
494
495         return 0;
496 }
497
498 static struct notifier_block __clk_cpufreq_notifier_block = {
499         .notifier_call = __clk_cpufreq_notifier
500 };
501
502 int __init sci_clock_init(void)
503 {
504 #if defined(CONFIG_DEBUG_FS)
505         clk_debugfs_root = debugfs_create_dir("clock", NULL);
506         if (IS_ERR_OR_NULL(clk_debugfs_root))
507                 return -ENOMEM;
508 #endif
509
510         /* register all clock sources */
511         {
512                 struct clk_lookup *cl =
513                     (struct clk_lookup *)(&__clkinit_begin + 1);
514                 debug0("%p (%x) -- %p -- %p (%x)\n",
515                        &__clkinit_begin, __clkinit_begin, cl, &__clkinit_end,
516                        __clkinit_end);
517                 while (cl < (struct clk_lookup *)&__clkinit_end) {
518                         sci_clk_register(cl);                   
519                         cl++;
520                 }
521         }
522 #if 0
523         /* keep track of cpu frequency transitions */
524         cpufreq_register_notifier(&__clk_cpufreq_notifier_block,
525                           CPUFREQ_TRANSITION_NOTIFIER);
526 #endif
527         return 0;
528 }
529
530 #ifndef CONFIG_NKERNEL
531 arch_initcall(sci_clock_init);
532 late_initcall_sync(sci_clock_dump);
533 #endif
534
535 MODULE_LICENSE("GPL v2");
536 MODULE_DESCRIPTION("Spreadtrum Clock Driver");
537 MODULE_AUTHOR("robot <zhulin.lian@spreadtrum.com>");