rk: freq limit resume when disable_limit
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-rk / clock.c
1 /* linux/arch/arm/mach-rk30/clock.c
2  *
3  * Copyright (C) 2012 ROCKCHIP, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
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 <linux/clk.h>
16 #include <linux/clkdev.h>
17 #include <linux/err.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/list.h>
21 #include <linux/module.h>
22 #include <linux/hardirq.h>
23 #include <linux/delay.h>
24 #include <mach/clock.h>
25 #include <mach/dvfs.h>
26 #include <linux/delay.h>
27
28 #define CLOCK_PRINTK_DBG(fmt, args...) pr_debug(fmt, ## args);
29 #define CLOCK_PRINTK_ERR(fmt, args...) pr_err(fmt, ## args);
30 #define CLOCK_PRINTK_LOG(fmt, args...) pr_debug(fmt, ## args);
31
32 /* Clock flags */
33 /* bit 0 is free */
34 #define RATE_FIXED              (1 << 1)        /* Fixed clock rate */
35 #define CONFIG_PARTICIPANT      (1 << 10)       /* Fundamental clock */
36
37 #define MHZ                     (1000*1000)
38 #define KHZ                     (1000)
39
40 static void __clk_recalc(struct clk *clk);
41 static void __propagate_rate(struct clk *tclk);
42 static void __clk_reparent(struct clk *child, struct clk *parent);
43
44 static LIST_HEAD(clocks);
45 static DEFINE_MUTEX(clocks_mutex);
46 static DEFINE_SPINLOCK(clockfw_lock);
47 static LIST_HEAD(root_clks);
48 static void clk_notify(struct clk *clk, unsigned long msg,
49                        unsigned long old_rate, unsigned long new_rate);
50
51 #define LOCK() do { WARN_ON(in_irq()); if (!irqs_disabled()) spin_lock_bh(&clockfw_lock); } while (0)
52 #define UNLOCK() do { if (!irqs_disabled()) spin_unlock_bh(&clockfw_lock); } while (0)
53 /**********************************************for clock data****************************************************/
54 struct list_head *get_rk_clocks_head(void)
55 {
56         return &clocks;
57 }
58
59 static struct clk *def_ops_clk=NULL;
60
61 void clk_register_default_ops_clk(struct clk *clk)
62 {
63         def_ops_clk=clk;
64 }
65
66 static struct clk *clk_default_get_parent(struct clk *clk)
67 {
68         if(def_ops_clk&&def_ops_clk->get_parent)
69                 return def_ops_clk->get_parent(clk);
70         else return NULL;
71
72
73
74 }
75 static int clk_default_set_parent(struct clk *clk, struct clk *parent)
76 {
77         if(def_ops_clk&&def_ops_clk->set_parent)
78                 return def_ops_clk->set_parent(clk,parent);
79         else
80                 return -EINVAL;
81 }
82
83 int __init clk_disable_unused(void)
84 {
85         struct clk *ck;
86         list_for_each_entry(ck, &clocks, node) {
87         if (ck->usecount > 0 || ck->mode == NULL || (ck->flags & IS_PD))
88                 continue;
89                 LOCK();
90                 clk_enable_nolock(ck);
91                 clk_disable_nolock(ck);
92                 UNLOCK();
93         }
94         return 0;
95 }
96 /**
97  * recalculate_root_clocks - recalculate and propagate all root clocks
98  *
99  * Recalculates all root clocks (clocks with no parent), which if the
100  * clock's .recalc is set correctly, should also propagate their rates.
101  * Called at init.
102  */
103 void clk_recalculate_root_clocks_nolock(void)
104 {
105         struct clk *clkp;
106
107         list_for_each_entry(clkp, &root_clks, sibling) {
108                 __clk_recalc(clkp);
109                 __propagate_rate(clkp);
110         }
111 }
112 /*
113 void clk_recalculate_root_clocks(void)
114 {
115         LOCK();
116         clk_recalculate_root_clocks_nolock();
117         UNLOCK();
118 }*/
119         
120 /**
121  * clk_preinit - initialize any fields in the struct clk before clk init
122  * @clk: struct clk * to initialize
123  *
124  * Initialize any struct clk fields needed before normal clk initialization
125  * can run.  No return value.
126  */
127 int clk_register(struct clk *clk)
128 {
129         if (clk == NULL || IS_ERR(clk))
130                 return -EINVAL;
131         //INIT_LIST_HEAD(&clk->sibling);
132         INIT_LIST_HEAD(&clk->children);
133
134         /*
135          * trap out already registered clocks
136          */
137         if (clk->node.next || clk->node.prev)
138                 return 0;
139
140         mutex_lock(&clocks_mutex);
141         if (clk->get_parent)
142                 clk->parent = clk->get_parent(clk);
143         else if (clk->parents)
144                 clk->parent =clk_default_get_parent(clk);
145         
146         if (clk->parent)
147                 list_add(&clk->sibling, &clk->parent->children);
148         else
149                 list_add(&clk->sibling, &root_clks);
150         list_add(&clk->node, &clocks);
151         mutex_unlock(&clocks_mutex);    
152         return 0;
153 }
154
155 /************************************************************/
156 static void __clk_recalc(struct clk *clk)
157 {
158         if (unlikely(clk->flags & RATE_FIXED))
159                 return;
160         if (clk->recalc)
161                 clk->rate = clk->recalc(clk);
162         else if (clk->parent)
163                 clk->rate = clk->parent->rate;
164 }
165 static void __clk_reparent(struct clk *child, struct clk *parent)
166 {
167         if (child->parent == parent)
168                 return;
169         //CLOCK_PRINTK_DBG("%s reparent to %s (was %s)\n", child->name, parent->name, ((child->parent) ? child->parent->name : "NULL"));
170
171         list_del_init(&child->sibling);
172         if (parent)
173                 list_add(&child->sibling, &parent->children);
174         child->parent = parent;
175 }
176
177 /* Propagate rate to children */
178 static void __propagate_rate(struct clk *tclk)
179 {
180         struct clk *clkp;
181         
182         //CLOCK_PRINTK_DBG("propagate_rate clk %s\n",clkp->name);
183         
184         list_for_each_entry(clkp, &tclk->children, sibling) {
185                 __clk_recalc(clkp);
186                 __propagate_rate(clkp);
187         }
188         //CLOCK_PRINTK_DBG("propagate_rate clk %s end\n",clkp->name);
189 }
190
191 int clk_enable_nolock(struct clk *clk)
192 {
193         int ret = 0;
194
195         if (clk->usecount == 0) {
196                 if (clk->parent) {
197                         ret = clk_enable_nolock(clk->parent);
198                         if (ret)
199                                 return ret;
200                 }
201
202                 if (clk->notifier_count)
203                         clk_notify(clk, CLK_PRE_ENABLE, clk->rate, clk->rate);
204                 if (clk->mode)
205                         ret = clk->mode(clk, 1);
206                 if (clk->notifier_count)
207                         clk_notify(clk, ret ? CLK_ABORT_ENABLE : CLK_POST_ENABLE, clk->rate, clk->rate);
208                 if (ret) {
209                         if (clk->parent)
210                                 clk_disable_nolock(clk->parent);
211                         return ret;
212                 }
213                 pr_debug("%s enabled\n", clk->name);
214         }
215         clk->usecount++;
216
217         return ret;
218 }
219  
220 void clk_disable_nolock(struct clk *clk)
221 {
222         if (clk->usecount == 0) {
223                 CLOCK_PRINTK_ERR(KERN_ERR "Trying disable clock %s with 0 usecount\n", clk->name);
224                 WARN_ON(1);
225                 return;
226         }
227         if (--clk->usecount == 0) {
228                 int ret = 0;
229                 if (clk->notifier_count)
230                         clk_notify(clk, CLK_PRE_DISABLE, clk->rate, clk->rate);
231                 if (clk->mode)
232                         ret = clk->mode(clk, 0);
233                 if (clk->notifier_count)
234                         clk_notify(clk, ret ? CLK_ABORT_DISABLE : CLK_POST_DISABLE, clk->rate, clk->rate);
235                 pr_debug("%s disabled\n", clk->name);
236                 if (ret == 0 && clk->parent)
237                         clk_disable_nolock(clk->parent);
238         }
239 }
240 /* Given a clock and a rate apply a clock specific rounding function */
241 long clk_round_rate_nolock(struct clk *clk, unsigned long rate)
242 {
243         if (clk->round_rate)
244                 return clk->round_rate(clk, rate);
245
246         if (clk->flags & RATE_FIXED)
247                 CLOCK_PRINTK_ERR("clock: clk_round_rate called on fixed-rate clock %s\n", clk->name);
248
249         return clk->rate;
250 }
251 int is_suport_round_rate(struct clk *clk)
252 {
253         return (clk->round_rate) ? 0:(-1);
254 }
255
256 int clk_set_rate_nolock(struct clk *clk, unsigned long rate)
257 {
258         int ret;
259         unsigned long old_rate;
260
261         if (rate == clk->rate)
262                 return 0;
263         if (clk->flags & CONFIG_PARTICIPANT)
264                 return -EINVAL;
265
266         if (!clk->set_rate)
267                 return -EINVAL;
268         
269         //CLOCK_PRINTK_LOG("**will set %s rate %lu\n", clk->name, rate);
270
271         old_rate = clk->rate;
272         if (clk->notifier_count)
273                 clk_notify(clk, CLK_PRE_RATE_CHANGE, old_rate, rate);
274
275         ret = clk->set_rate(clk, rate);
276
277         if (ret == 0) {
278                 __clk_recalc(clk);
279                 CLOCK_PRINTK_LOG("**set %s rate recalc=%lu\n",clk->name,clk->rate);
280                 __propagate_rate(clk);
281         }
282
283         clk->last_set_rate = rate;
284
285         if (clk->notifier_count)
286                 clk_notify(clk, ret ? CLK_ABORT_RATE_CHANGE : CLK_POST_RATE_CHANGE, old_rate, clk->rate);
287
288         return ret;
289 }
290  
291 int clk_set_parent_nolock(struct clk *clk, struct clk *parent)
292 {
293         int ret;
294         int enabled = clk->usecount > 0;
295         struct clk *old_parent = clk->parent;
296
297         if (clk->parent == parent)
298                 return 0;
299
300         /* if clk is already enabled, enable new parent first and disable old parent later. */
301         if (enabled)
302                 clk_enable_nolock(parent);
303
304         if (clk->set_parent)
305                 ret = clk->set_parent(clk, parent);
306         else
307                 ret = clk_default_set_parent(clk,parent);
308
309         if (ret == 0) {
310                 /* OK */
311                 
312                 //CLOCK_PRINTK_DBG("set_parent %s reparent\n",clk->name,parent->name);
313                 __clk_reparent(clk, parent);
314                 __clk_recalc(clk);
315                 __propagate_rate(clk);
316                 if (enabled)
317                         clk_disable_nolock(old_parent);
318         } else {
319                 //CLOCK_PRINTK_DBG("set_parent err\n",clk->name,parent->name);
320                 if (enabled)
321                         clk_disable_nolock(parent);
322         }
323
324         return ret;
325 }
326 /**********************************dvfs****************************************************/
327 int clk_set_rate_locked(struct clk * clk,unsigned long rate)
328 {
329         int ret;
330         //CLOCK_PRINTK_DBG("%s dvfs clk_set_locked\n",clk->name);
331         LOCK();
332     ret=clk_set_rate_nolock(clk, rate);;
333     UNLOCK();
334         return ret;
335         
336 }
337 void clk_register_dvfs(struct clk_node *dvfs_clk, struct clk *clk)
338 {
339     clk->dvfs_info = dvfs_clk;
340 }
341 int clk_set_enable_locked(struct clk * clk,int on)
342 {
343         int ret=0;
344         LOCK();
345         if(on)
346                 ret=clk_enable_nolock(clk);
347         else    
348                 clk_disable_nolock(clk);
349         UNLOCK();
350         return ret;
351 }
352 EXPORT_SYMBOL(clk_set_enable_locked);
353 /*-------------------------------------------------------------------------
354  * Optional clock functions defined in include/linux/clk.h
355  *-------------------------------------------------------------------------*/
356 #ifdef RK30_CLK_OFFBOARD_TEST
357 long rk30_clk_round_rate(struct clk *clk, unsigned long rate)
358 #else
359 long clk_round_rate(struct clk *clk, unsigned long rate)
360 #endif
361 {
362         long ret = 0;
363
364         if (clk == NULL || IS_ERR(clk))
365                 return ret;
366
367         LOCK();
368         ret = clk_round_rate_nolock(clk, rate);
369         UNLOCK();
370
371         return ret;
372 }
373
374 #ifdef RK30_CLK_OFFBOARD_TEST
375 EXPORT_SYMBOL(rk30_clk_round_rate);
376 #else
377 EXPORT_SYMBOL(clk_round_rate);
378 #endif
379
380 #ifdef RK30_CLK_OFFBOARD_TEST
381 unsigned long rk30_clk_get_rate(struct clk *clk)
382 #else
383 unsigned long clk_get_rate(struct clk *clk)
384 #endif
385 {
386         if (clk == NULL || IS_ERR(clk))
387                 return 0;
388
389         return clk->rate;
390 }
391 #ifdef RK30_CLK_OFFBOARD_TEST
392 EXPORT_SYMBOL(rk30_clk_get_rate);
393 #else
394 EXPORT_SYMBOL(clk_get_rate);
395 #endif
396
397
398 /* Set the clock rate for a clock source */
399 #ifdef RK30_CLK_OFFBOARD_TEST
400 int rk30_clk_set_rate(struct clk *clk, unsigned long rate)
401 #else
402 int clk_set_rate(struct clk *clk, unsigned long rate)
403 #endif
404 {
405         int ret = -EINVAL;
406         if (clk == NULL || IS_ERR(clk)){
407                 return ret;
408         }
409         if (rate == clk->rate)
410                 return 0;
411         if (dvfs_support_clk_set_rate(clk->dvfs_info)==true)
412                 return dvfs_vd_clk_set_rate(clk, rate);
413
414         LOCK();
415         ret = clk_set_rate_nolock(clk, rate);
416         UNLOCK();
417
418         return ret;
419 }
420 #ifdef RK30_CLK_OFFBOARD_TEST
421 EXPORT_SYMBOL(rk30_clk_set_rate);
422 #else
423 EXPORT_SYMBOL(clk_set_rate);
424 #endif
425
426
427 #ifdef RK30_CLK_OFFBOARD_TEST
428 int rk30_clk_set_parent(struct clk *clk, struct clk *parent)
429 #else
430 int clk_set_parent(struct clk *clk, struct clk *parent)
431 #endif
432 {
433         int ret = -EINVAL;
434
435         if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
436                 return ret;
437
438         if (clk->parents == NULL)
439                 return ret;
440
441         LOCK();
442         if (clk->usecount == 0)
443                 ret = clk_set_parent_nolock(clk, parent);
444         else
445                 ret = -EBUSY;
446         UNLOCK();
447
448         return ret;
449 }
450 int clk_set_parent_force(struct clk *clk, struct clk *parent)
451 {
452         int ret = -EINVAL;
453
454         if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
455                 return ret;
456
457         if (clk->parents == NULL)
458                 return ret;
459         LOCK();
460                 ret = clk_set_parent_nolock(clk, parent);       
461         UNLOCK();
462         return ret;
463 }
464
465 #ifdef RK30_CLK_OFFBOARD_TEST
466 EXPORT_SYMBOL(rk30_clk_set_parent);
467 #else
468 EXPORT_SYMBOL(clk_set_parent);
469 #endif
470
471 #ifdef RK30_CLK_OFFBOARD_TEST
472 struct clk *rk30_clk_get_parent(struct clk *clk)
473 #else
474 struct clk *clk_get_parent(struct clk *clk)
475 #endif
476 {
477         if (clk == NULL || IS_ERR(clk)) {
478                 return ERR_PTR(-EINVAL);
479         }
480         return clk->parent;
481 }
482
483 #ifdef RK30_CLK_OFFBOARD_TEST
484 EXPORT_SYMBOL(rk30_clk_get_parent);
485 #else
486 EXPORT_SYMBOL(clk_get_parent);
487 #endif
488
489 #ifdef RK30_CLK_OFFBOARD_TEST
490 void rk30_clk_disable(struct clk *clk)
491 #else
492 void clk_disable(struct clk *clk)
493 #endif
494 {
495         if (clk == NULL || IS_ERR(clk))
496                 return;
497         if (dvfs_support_clk_disable(clk->dvfs_info) == true) {
498                 dvfs_vd_clk_disable(clk, 0);
499                 return;
500         }
501
502         LOCK();
503         clk_disable_nolock(clk);
504         UNLOCK();
505 }
506 #ifdef RK30_CLK_OFFBOARD_TEST
507 EXPORT_SYMBOL(rk30_clk_disable);
508 #else
509 EXPORT_SYMBOL(clk_disable);
510 #endif
511
512 #ifdef RK30_CLK_OFFBOARD_TEST
513 int rk30_clk_enable(struct clk *clk)
514 #else
515 int  clk_enable(struct clk *clk)
516 #endif
517 {
518         int ret = 0;
519
520         if (clk == NULL || IS_ERR(clk))
521                 return -EINVAL;
522         if (dvfs_support_clk_disable(clk->dvfs_info)==true)
523                 return dvfs_vd_clk_disable(clk, 1);
524
525         LOCK();
526         ret = clk_enable_nolock(clk);
527         UNLOCK();
528
529         return ret;
530 }
531 #ifdef RK30_CLK_OFFBOARD_TEST
532 EXPORT_SYMBOL(rk30_clk_enable);
533 #else
534 EXPORT_SYMBOL(clk_enable);
535 #endif
536
537 /* Clk notifier implementation */
538
539 /**
540  * struct clk_notifier - associate a clk with a notifier
541  * @clk: struct clk * to associate the notifier with
542  * @notifier_head: a raw_notifier_head for this clk
543  * @node: linked list pointers
544  *
545  * A list of struct clk_notifier is maintained by the notifier code.
546  * An entry is created whenever code registers the first notifier on a
547  * particular @clk.  Future notifiers on that @clk are added to the
548  * @notifier_head.
549  */
550 struct clk_notifier {
551         struct clk                      *clk;
552         struct raw_notifier_head        notifier_head;
553         struct list_head                node;
554 };
555 static LIST_HEAD(clk_notifier_list);
556 /**
557  * _clk_free_notifier_chain - safely remove struct clk_notifier
558  * @cn: struct clk_notifier *
559  *
560  * Removes the struct clk_notifier @cn from the clk_notifier_list and
561  * frees it.
562  */
563 static void _clk_free_notifier_chain(struct clk_notifier *cn)
564 {
565         list_del(&cn->node);
566         kfree(cn);
567 }
568
569 /**
570  * clk_notify - call clk notifier chain
571  * @clk: struct clk * that is changing rate
572  * @msg: clk notifier type (i.e., CLK_POST_RATE_CHANGE; see mach/clock.h)
573  * @old_rate: old rate
574  * @new_rate: new rate
575  *
576  * Triggers a notifier call chain on the post-clk-rate-change notifier
577  * for clock 'clk'.  Passes a pointer to the struct clk and the
578  * previous and current rates to the notifier callback.  Intended to be
579  * called by internal clock code only.  No return value.
580  */
581 static void clk_notify(struct clk *clk, unsigned long msg,
582                        unsigned long old_rate, unsigned long new_rate)
583 {
584         struct clk_notifier *cn;
585         struct clk_notifier_data cnd;
586
587         cnd.clk = clk;
588         cnd.old_rate = old_rate;
589         cnd.new_rate = new_rate;
590
591         UNLOCK();
592         list_for_each_entry(cn, &clk_notifier_list, node) {
593                 if (cn->clk == clk) {
594                         pr_debug("%s msg %lu rate %lu -> %lu\n", clk->name, msg, old_rate, new_rate);
595                         raw_notifier_call_chain(&cn->notifier_head, msg, &cnd);
596                         break;
597                 }
598         }
599         LOCK();
600 }
601
602 /**
603  * clk_notifier_register - add a clock parameter change notifier
604  * @clk: struct clk * to watch
605  * @nb: struct notifier_block * with callback info
606  *
607  * Request notification for changes to the clock 'clk'.  This uses a
608  * blocking notifier.  Callback code must not call into the clock
609  * framework, as clocks_mutex is held.  Pre-notifier callbacks will be
610  * passed the previous and new rate of the clock.
611  *
612  * clk_notifier_register() must be called from process
613  * context.  Returns -EINVAL if called with null arguments, -ENOMEM
614  * upon allocation failure; otherwise, passes along the return value
615  * of blocking_notifier_chain_register().
616  */
617 int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
618 {
619         struct clk_notifier *cn = NULL, *cn_new = NULL;
620         int r;
621         struct clk *clkp;
622
623         if (!clk || IS_ERR(clk) || !nb)
624                 return -EINVAL;
625
626         mutex_lock(&clocks_mutex);
627
628         list_for_each_entry(cn, &clk_notifier_list, node)
629                 if (cn->clk == clk)
630                         break;
631
632         if (cn->clk != clk) {
633                 cn_new = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
634                 if (!cn_new) {
635                         r = -ENOMEM;
636                         goto cnr_out;
637                 };
638
639                 cn_new->clk = clk;
640                 RAW_INIT_NOTIFIER_HEAD(&cn_new->notifier_head);
641
642                 list_add(&cn_new->node, &clk_notifier_list);
643                 cn = cn_new;
644         }
645
646         r = raw_notifier_chain_register(&cn->notifier_head, nb);
647         if (!IS_ERR_VALUE(r)) {
648                 clkp = clk;
649                 do {
650                         clkp->notifier_count++;
651                 } while ((clkp = clkp->parent));
652         } else {
653                 if (cn_new)
654                         _clk_free_notifier_chain(cn);
655         }
656
657 cnr_out:
658         mutex_unlock(&clocks_mutex);
659
660         return r;
661 }
662 EXPORT_SYMBOL(clk_notifier_register);
663
664 /**
665  * clk_notifier_unregister - remove a clock change notifier
666  * @clk: struct clk *
667  * @nb: struct notifier_block * with callback info
668  *
669  * Request no further notification for changes to clock 'clk'.
670  * Returns -EINVAL if called with null arguments; otherwise, passes
671  * along the return value of blocking_notifier_chain_unregister().
672  */
673 int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
674 {
675         struct clk_notifier *cn = NULL;
676         struct clk *clkp;
677         int r = -EINVAL;
678
679         if (!clk || IS_ERR(clk) || !nb)
680                 return -EINVAL;
681
682         mutex_lock(&clocks_mutex);
683
684         list_for_each_entry(cn, &clk_notifier_list, node)
685                 if (cn->clk == clk)
686                         break;
687
688         if (cn->clk != clk) {
689                 r = -ENOENT;
690                 goto cnu_out;
691         };
692
693         r = raw_notifier_chain_unregister(&cn->notifier_head, nb);
694         if (!IS_ERR_VALUE(r)) {
695                 clkp = clk;
696                 do {
697                         clkp->notifier_count--;
698                 } while ((clkp = clkp->parent));
699         }
700
701         /*
702          * XXX ugh, layering violation.  There should be some
703          * support in the notifier code for this.
704          */
705         if (!cn->notifier_head.head)
706                 _clk_free_notifier_chain(cn);
707
708 cnu_out:
709         mutex_unlock(&clocks_mutex);
710
711         return r;
712 }
713 EXPORT_SYMBOL(clk_notifier_unregister);
714
715 #ifdef CONFIG_PROC_FS
716 static struct clk_dump_ops *dump_def_ops;
717
718 void clk_register_dump_ops(struct clk_dump_ops *ops)
719 {
720         dump_def_ops=ops;
721 }
722 #endif
723
724 #ifdef CONFIG_RK_CLOCK_PROC
725 static int proc_clk_show(struct seq_file *s, void *v)
726 {
727         struct clk* clk;
728         
729         if(!dump_def_ops)
730                 return 0;
731
732         if(dump_def_ops->dump_clk)
733         {
734                 mutex_lock(&clocks_mutex);
735                 list_for_each_entry(clk, &clocks, node) {
736                         if (!clk->parent)
737                         {
738                                 dump_def_ops->dump_clk(s, clk, 0,&clocks);
739                         }
740                 }
741                 mutex_unlock(&clocks_mutex);
742         }
743         if(dump_def_ops->dump_regs)
744                 dump_def_ops->dump_regs(s);
745         return 0;
746 }
747
748
749 static int proc_clk_open(struct inode *inode, struct file *file)
750 {
751         return single_open(file, proc_clk_show, NULL);
752 }
753
754 static const struct file_operations proc_clk_fops = {
755         .open           = proc_clk_open,
756         .read           = seq_read,
757         .llseek         = seq_lseek,
758         .release        = single_release,
759 };
760
761 static int __init clk_proc_init(void)
762 {
763         proc_create("clocks", S_IFREG | S_IRUSR | S_IRGRP, NULL, &proc_clk_fops);
764         return 0;
765
766 }
767 late_initcall(clk_proc_init);
768 #endif /* CONFIG_RK_CLOCK_PROC */
769
770 static int clk_panic(struct notifier_block *this, unsigned long ev, void *ptr)
771 {
772 #ifdef RK30_CRU_BASE
773 #define CRU_BASE RK30_CRU_BASE
774 #elif defined(RK2928_CRU_BASE)
775 #define CRU_BASE RK2928_CRU_BASE
776 #endif
777 #ifdef CRU_BASE
778         print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_ADDRESS, 16, 4, CRU_BASE, 0x150, false);
779 #endif
780         return NOTIFY_DONE;
781 }
782
783 static struct notifier_block clk_panic_block = {
784         .notifier_call = clk_panic,
785 };
786
787 static int __init clk_panic_init(void)
788 {
789         return atomic_notifier_chain_register(&panic_notifier_list, &clk_panic_block);
790 }
791 pure_initcall(clk_panic_init);