rk: clock: fix compile error when build without PROC_FS support
[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         if (clk->notifier_count)
284                 clk_notify(clk, ret ? CLK_ABORT_RATE_CHANGE : CLK_POST_RATE_CHANGE, old_rate, clk->rate);
285
286         return ret;
287 }
288  
289 int clk_set_parent_nolock(struct clk *clk, struct clk *parent)
290 {
291         int ret;
292         int enabled = clk->usecount > 0;
293         struct clk *old_parent = clk->parent;
294
295         if (clk->parent == parent)
296                 return 0;
297
298         /* if clk is already enabled, enable new parent first and disable old parent later. */
299         if (enabled)
300                 clk_enable_nolock(parent);
301
302         if (clk->set_parent)
303                 ret = clk->set_parent(clk, parent);
304         else
305                 ret = clk_default_set_parent(clk,parent);
306
307         if (ret == 0) {
308                 /* OK */
309                 
310                 //CLOCK_PRINTK_DBG("set_parent %s reparent\n",clk->name,parent->name);
311                 __clk_reparent(clk, parent);
312                 __clk_recalc(clk);
313                 __propagate_rate(clk);
314                 if (enabled)
315                         clk_disable_nolock(old_parent);
316         } else {
317                 //CLOCK_PRINTK_DBG("set_parent err\n",clk->name,parent->name);
318                 if (enabled)
319                         clk_disable_nolock(parent);
320         }
321
322         return ret;
323 }
324 /**********************************dvfs****************************************************/
325 int clk_set_rate_locked(struct clk * clk,unsigned long rate)
326 {
327         int ret;
328         //CLOCK_PRINTK_DBG("%s dvfs clk_set_locked\n",clk->name);
329         LOCK();
330     ret=clk_set_rate_nolock(clk, rate);;
331     UNLOCK();
332         return ret;
333         
334 }
335 void clk_register_dvfs(struct clk_node *dvfs_clk, struct clk *clk)
336 {
337     clk->dvfs_info = dvfs_clk;
338 }
339 int clk_set_enable_locked(struct clk * clk,int on)
340 {
341         int ret=0;
342         LOCK();
343         if(on)
344                 ret=clk_enable_nolock(clk);
345         else    
346                 clk_disable_nolock(clk);
347         UNLOCK();
348         return ret;
349 }
350 EXPORT_SYMBOL(clk_set_enable_locked);
351 /*-------------------------------------------------------------------------
352  * Optional clock functions defined in include/linux/clk.h
353  *-------------------------------------------------------------------------*/
354 #ifdef RK30_CLK_OFFBOARD_TEST
355 long rk30_clk_round_rate(struct clk *clk, unsigned long rate)
356 #else
357 long clk_round_rate(struct clk *clk, unsigned long rate)
358 #endif
359 {
360         long ret = 0;
361
362         if (clk == NULL || IS_ERR(clk))
363                 return ret;
364
365         LOCK();
366         ret = clk_round_rate_nolock(clk, rate);
367         UNLOCK();
368
369         return ret;
370 }
371
372 #ifdef RK30_CLK_OFFBOARD_TEST
373 EXPORT_SYMBOL(rk30_clk_round_rate);
374 #else
375 EXPORT_SYMBOL(clk_round_rate);
376 #endif
377
378 #ifdef RK30_CLK_OFFBOARD_TEST
379 unsigned long rk30_clk_get_rate(struct clk *clk)
380 #else
381 unsigned long clk_get_rate(struct clk *clk)
382 #endif
383 {
384         if (clk == NULL || IS_ERR(clk))
385                 return 0;
386
387         return clk->rate;
388 }
389 #ifdef RK30_CLK_OFFBOARD_TEST
390 EXPORT_SYMBOL(rk30_clk_get_rate);
391 #else
392 EXPORT_SYMBOL(clk_get_rate);
393 #endif
394
395
396 /* Set the clock rate for a clock source */
397 #ifdef RK30_CLK_OFFBOARD_TEST
398 int rk30_clk_set_rate(struct clk *clk, unsigned long rate)
399 #else
400 int clk_set_rate(struct clk *clk, unsigned long rate)
401 #endif
402 {
403         int ret = -EINVAL;
404         if (clk == NULL || IS_ERR(clk)){
405                 return ret;
406         }
407         if (rate == clk->rate)
408                 return 0;
409         if (dvfs_support_clk_set_rate(clk->dvfs_info)==true)
410                 return dvfs_vd_clk_set_rate(clk, rate);
411
412         LOCK();
413         ret = clk_set_rate_nolock(clk, rate);
414         UNLOCK();
415
416         return ret;
417 }
418 #ifdef RK30_CLK_OFFBOARD_TEST
419 EXPORT_SYMBOL(rk30_clk_set_rate);
420 #else
421 EXPORT_SYMBOL(clk_set_rate);
422 #endif
423
424
425 #ifdef RK30_CLK_OFFBOARD_TEST
426 int rk30_clk_set_parent(struct clk *clk, struct clk *parent)
427 #else
428 int clk_set_parent(struct clk *clk, struct clk *parent)
429 #endif
430 {
431         int ret = -EINVAL;
432
433         if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
434                 return ret;
435
436         if (clk->parents == NULL)
437                 return ret;
438
439         LOCK();
440         if (clk->usecount == 0)
441                 ret = clk_set_parent_nolock(clk, parent);
442         else
443                 ret = -EBUSY;
444         UNLOCK();
445
446         return ret;
447 }
448 int clk_set_parent_force(struct clk *clk, struct clk *parent)
449 {
450         int ret = -EINVAL;
451
452         if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
453                 return ret;
454
455         if (clk->parents == NULL)
456                 return ret;
457         LOCK();
458                 ret = clk_set_parent_nolock(clk, parent);       
459         UNLOCK();
460         return ret;
461 }
462
463 #ifdef RK30_CLK_OFFBOARD_TEST
464 EXPORT_SYMBOL(rk30_clk_set_parent);
465 #else
466 EXPORT_SYMBOL(clk_set_parent);
467 #endif
468
469 #ifdef RK30_CLK_OFFBOARD_TEST
470 struct clk *rk30_clk_get_parent(struct clk *clk)
471 #else
472 struct clk *clk_get_parent(struct clk *clk)
473 #endif
474 {
475         if (clk == NULL || IS_ERR(clk)) {
476                 return ERR_PTR(-EINVAL);
477         }
478         return clk->parent;
479 }
480
481 #ifdef RK30_CLK_OFFBOARD_TEST
482 EXPORT_SYMBOL(rk30_clk_get_parent);
483 #else
484 EXPORT_SYMBOL(clk_get_parent);
485 #endif
486
487 #ifdef RK30_CLK_OFFBOARD_TEST
488 void rk30_clk_disable(struct clk *clk)
489 #else
490 void clk_disable(struct clk *clk)
491 #endif
492 {
493         if (clk == NULL || IS_ERR(clk))
494                 return;
495         if (dvfs_support_clk_disable(clk->dvfs_info) == true) {
496                 dvfs_vd_clk_disable(clk, 0);
497                 return;
498         }
499
500         LOCK();
501         clk_disable_nolock(clk);
502         UNLOCK();
503 }
504 #ifdef RK30_CLK_OFFBOARD_TEST
505 EXPORT_SYMBOL(rk30_clk_disable);
506 #else
507 EXPORT_SYMBOL(clk_disable);
508 #endif
509
510 #ifdef RK30_CLK_OFFBOARD_TEST
511 int rk30_clk_enable(struct clk *clk)
512 #else
513 int  clk_enable(struct clk *clk)
514 #endif
515 {
516         int ret = 0;
517
518         if (clk == NULL || IS_ERR(clk))
519                 return -EINVAL;
520         if (dvfs_support_clk_disable(clk->dvfs_info)==true)
521                 return dvfs_vd_clk_disable(clk, 1);
522
523         LOCK();
524         ret = clk_enable_nolock(clk);
525         UNLOCK();
526
527         return ret;
528 }
529 #ifdef RK30_CLK_OFFBOARD_TEST
530 EXPORT_SYMBOL(rk30_clk_enable);
531 #else
532 EXPORT_SYMBOL(clk_enable);
533 #endif
534
535 /* Clk notifier implementation */
536
537 /**
538  * struct clk_notifier - associate a clk with a notifier
539  * @clk: struct clk * to associate the notifier with
540  * @notifier_head: a raw_notifier_head for this clk
541  * @node: linked list pointers
542  *
543  * A list of struct clk_notifier is maintained by the notifier code.
544  * An entry is created whenever code registers the first notifier on a
545  * particular @clk.  Future notifiers on that @clk are added to the
546  * @notifier_head.
547  */
548 struct clk_notifier {
549         struct clk                      *clk;
550         struct raw_notifier_head        notifier_head;
551         struct list_head                node;
552 };
553 static LIST_HEAD(clk_notifier_list);
554 /**
555  * _clk_free_notifier_chain - safely remove struct clk_notifier
556  * @cn: struct clk_notifier *
557  *
558  * Removes the struct clk_notifier @cn from the clk_notifier_list and
559  * frees it.
560  */
561 static void _clk_free_notifier_chain(struct clk_notifier *cn)
562 {
563         list_del(&cn->node);
564         kfree(cn);
565 }
566
567 /**
568  * clk_notify - call clk notifier chain
569  * @clk: struct clk * that is changing rate
570  * @msg: clk notifier type (i.e., CLK_POST_RATE_CHANGE; see mach/clock.h)
571  * @old_rate: old rate
572  * @new_rate: new rate
573  *
574  * Triggers a notifier call chain on the post-clk-rate-change notifier
575  * for clock 'clk'.  Passes a pointer to the struct clk and the
576  * previous and current rates to the notifier callback.  Intended to be
577  * called by internal clock code only.  No return value.
578  */
579 static void clk_notify(struct clk *clk, unsigned long msg,
580                        unsigned long old_rate, unsigned long new_rate)
581 {
582         struct clk_notifier *cn;
583         struct clk_notifier_data cnd;
584
585         cnd.clk = clk;
586         cnd.old_rate = old_rate;
587         cnd.new_rate = new_rate;
588
589         UNLOCK();
590         list_for_each_entry(cn, &clk_notifier_list, node) {
591                 if (cn->clk == clk) {
592                         pr_debug("%s msg %lu rate %lu -> %lu\n", clk->name, msg, old_rate, new_rate);
593                         raw_notifier_call_chain(&cn->notifier_head, msg, &cnd);
594                         break;
595                 }
596         }
597         LOCK();
598 }
599
600 /**
601  * clk_notifier_register - add a clock parameter change notifier
602  * @clk: struct clk * to watch
603  * @nb: struct notifier_block * with callback info
604  *
605  * Request notification for changes to the clock 'clk'.  This uses a
606  * blocking notifier.  Callback code must not call into the clock
607  * framework, as clocks_mutex is held.  Pre-notifier callbacks will be
608  * passed the previous and new rate of the clock.
609  *
610  * clk_notifier_register() must be called from process
611  * context.  Returns -EINVAL if called with null arguments, -ENOMEM
612  * upon allocation failure; otherwise, passes along the return value
613  * of blocking_notifier_chain_register().
614  */
615 int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
616 {
617         struct clk_notifier *cn = NULL, *cn_new = NULL;
618         int r;
619         struct clk *clkp;
620
621         if (!clk || IS_ERR(clk) || !nb)
622                 return -EINVAL;
623
624         mutex_lock(&clocks_mutex);
625
626         list_for_each_entry(cn, &clk_notifier_list, node)
627                 if (cn->clk == clk)
628                         break;
629
630         if (cn->clk != clk) {
631                 cn_new = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
632                 if (!cn_new) {
633                         r = -ENOMEM;
634                         goto cnr_out;
635                 };
636
637                 cn_new->clk = clk;
638                 RAW_INIT_NOTIFIER_HEAD(&cn_new->notifier_head);
639
640                 list_add(&cn_new->node, &clk_notifier_list);
641                 cn = cn_new;
642         }
643
644         r = raw_notifier_chain_register(&cn->notifier_head, nb);
645         if (!IS_ERR_VALUE(r)) {
646                 clkp = clk;
647                 do {
648                         clkp->notifier_count++;
649                 } while ((clkp = clkp->parent));
650         } else {
651                 if (cn_new)
652                         _clk_free_notifier_chain(cn);
653         }
654
655 cnr_out:
656         mutex_unlock(&clocks_mutex);
657
658         return r;
659 }
660 EXPORT_SYMBOL(clk_notifier_register);
661
662 /**
663  * clk_notifier_unregister - remove a clock change notifier
664  * @clk: struct clk *
665  * @nb: struct notifier_block * with callback info
666  *
667  * Request no further notification for changes to clock 'clk'.
668  * Returns -EINVAL if called with null arguments; otherwise, passes
669  * along the return value of blocking_notifier_chain_unregister().
670  */
671 int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
672 {
673         struct clk_notifier *cn = NULL;
674         struct clk *clkp;
675         int r = -EINVAL;
676
677         if (!clk || IS_ERR(clk) || !nb)
678                 return -EINVAL;
679
680         mutex_lock(&clocks_mutex);
681
682         list_for_each_entry(cn, &clk_notifier_list, node)
683                 if (cn->clk == clk)
684                         break;
685
686         if (cn->clk != clk) {
687                 r = -ENOENT;
688                 goto cnu_out;
689         };
690
691         r = raw_notifier_chain_unregister(&cn->notifier_head, nb);
692         if (!IS_ERR_VALUE(r)) {
693                 clkp = clk;
694                 do {
695                         clkp->notifier_count--;
696                 } while ((clkp = clkp->parent));
697         }
698
699         /*
700          * XXX ugh, layering violation.  There should be some
701          * support in the notifier code for this.
702          */
703         if (!cn->notifier_head.head)
704                 _clk_free_notifier_chain(cn);
705
706 cnu_out:
707         mutex_unlock(&clocks_mutex);
708
709         return r;
710 }
711 EXPORT_SYMBOL(clk_notifier_unregister);
712
713 #ifdef CONFIG_PROC_FS
714 static struct clk_dump_ops *dump_def_ops;
715
716 void clk_register_dump_ops(struct clk_dump_ops *ops)
717 {
718         dump_def_ops=ops;
719 }
720 #endif
721
722 #ifdef CONFIG_RK_CLOCK_PROC
723 static int proc_clk_show(struct seq_file *s, void *v)
724 {
725         struct clk* clk;
726         
727         if(!dump_def_ops)
728                 return 0;
729
730         if(dump_def_ops->dump_clk)
731         {
732                 mutex_lock(&clocks_mutex);
733                 list_for_each_entry(clk, &clocks, node) {
734                         if (!clk->parent)
735                         {
736                                 dump_def_ops->dump_clk(s, clk, 0,&clocks);
737                         }
738                 }
739                 mutex_unlock(&clocks_mutex);
740         }
741         if(dump_def_ops->dump_regs)
742                 dump_def_ops->dump_regs(s);
743         return 0;
744 }
745
746
747 static int proc_clk_open(struct inode *inode, struct file *file)
748 {
749         return single_open(file, proc_clk_show, NULL);
750 }
751
752 static const struct file_operations proc_clk_fops = {
753         .open           = proc_clk_open,
754         .read           = seq_read,
755         .llseek         = seq_lseek,
756         .release        = single_release,
757 };
758
759 static int __init clk_proc_init(void)
760 {
761         proc_create("clocks", S_IFREG | S_IRUSR | S_IRGRP, NULL, &proc_clk_fops);
762         return 0;
763
764 }
765 late_initcall(clk_proc_init);
766 #endif /* CONFIG_RK_CLOCK_PROC */
767