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