aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-09-27 12:33:33 -0400
committerTony Lindgren <tony@atomide.com>2012-10-18 19:22:26 -0400
commit1fe9be8248ae9a04a09fcec7fed486d31e7f0897 (patch)
treeaa65df4a2e59363d9274c20d9441ff817f22e7cf /arch
parentf7a9b8a147cc10c7181cf0ca7b2b06cebf950140 (diff)
ARM: OMAP: duplicate plat-omap/clock.c into mach-omap[12]/clock.c
Duplicate arch/arm/plat-omap/clock.c into arch/arm/mach-omap1/clock.c and arch/arm/mach-omap2/clock.c. This is to support people who are working on the ARM single image kernel and the OMAP common clock framework conversion. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Tony Lindgren <tony@atomide.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap1/clock.c499
-rw-r--r--arch/arm/mach-omap1/clock_data.c10
-rw-r--r--arch/arm/mach-omap2/clock.c517
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c2
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c2
-rw-r--r--arch/arm/mach-omap2/clock33xx_data.c2
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c2
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c2
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/clock.c544
10 files changed, 1010 insertions, 572 deletions
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index b15d4ee7efa2..f46206eb3a15 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -12,6 +12,7 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/export.h>
15#include <linux/list.h> 16#include <linux/list.h>
16#include <linux/errno.h> 17#include <linux/errno.h>
17#include <linux/err.h> 18#include <linux/err.h>
@@ -37,6 +38,10 @@
37__u32 arm_idlect1_mask; 38__u32 arm_idlect1_mask;
38struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; 39struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
39 40
41static LIST_HEAD(clocks);
42static DEFINE_MUTEX(clocks_mutex);
43static DEFINE_SPINLOCK(clockfw_lock);
44
40/* 45/*
41 * Omap1 specific clock functions 46 * Omap1 specific clock functions
42 */ 47 */
@@ -608,3 +613,497 @@ void omap1_clk_disable_unused(struct clk *clk)
608} 613}
609 614
610#endif 615#endif
616
617
618int clk_enable(struct clk *clk)
619{
620 unsigned long flags;
621 int ret;
622
623 if (clk == NULL || IS_ERR(clk))
624 return -EINVAL;
625
626 spin_lock_irqsave(&clockfw_lock, flags);
627 ret = omap1_clk_enable(clk);
628 spin_unlock_irqrestore(&clockfw_lock, flags);
629
630 return ret;
631}
632EXPORT_SYMBOL(clk_enable);
633
634void clk_disable(struct clk *clk)
635{
636 unsigned long flags;
637
638 if (clk == NULL || IS_ERR(clk))
639 return;
640
641 spin_lock_irqsave(&clockfw_lock, flags);
642 if (clk->usecount == 0) {
643 pr_err("Trying disable clock %s with 0 usecount\n",
644 clk->name);
645 WARN_ON(1);
646 goto out;
647 }
648
649 omap1_clk_disable(clk);
650
651out:
652 spin_unlock_irqrestore(&clockfw_lock, flags);
653}
654EXPORT_SYMBOL(clk_disable);
655
656unsigned long clk_get_rate(struct clk *clk)
657{
658 unsigned long flags;
659 unsigned long ret;
660
661 if (clk == NULL || IS_ERR(clk))
662 return 0;
663
664 spin_lock_irqsave(&clockfw_lock, flags);
665 ret = clk->rate;
666 spin_unlock_irqrestore(&clockfw_lock, flags);
667
668 return ret;
669}
670EXPORT_SYMBOL(clk_get_rate);
671
672/*
673 * Optional clock functions defined in include/linux/clk.h
674 */
675
676long clk_round_rate(struct clk *clk, unsigned long rate)
677{
678 unsigned long flags;
679 long ret;
680
681 if (clk == NULL || IS_ERR(clk))
682 return 0;
683
684 spin_lock_irqsave(&clockfw_lock, flags);
685 ret = omap1_clk_round_rate(clk, rate);
686 spin_unlock_irqrestore(&clockfw_lock, flags);
687
688 return ret;
689}
690EXPORT_SYMBOL(clk_round_rate);
691
692int clk_set_rate(struct clk *clk, unsigned long rate)
693{
694 unsigned long flags;
695 int ret = -EINVAL;
696
697 if (clk == NULL || IS_ERR(clk))
698 return ret;
699
700 spin_lock_irqsave(&clockfw_lock, flags);
701 ret = omap1_clk_set_rate(clk, rate);
702 if (ret == 0)
703 propagate_rate(clk);
704 spin_unlock_irqrestore(&clockfw_lock, flags);
705
706 return ret;
707}
708EXPORT_SYMBOL(clk_set_rate);
709
710int clk_set_parent(struct clk *clk, struct clk *parent)
711{
712 WARN_ONCE(1, "clk_set_parent() not implemented for OMAP1\n");
713
714 return -EINVAL;
715}
716EXPORT_SYMBOL(clk_set_parent);
717
718struct clk *clk_get_parent(struct clk *clk)
719{
720 return clk->parent;
721}
722EXPORT_SYMBOL(clk_get_parent);
723
724/*
725 * OMAP specific clock functions shared between omap1 and omap2
726 */
727
728int __initdata mpurate;
729
730/*
731 * By default we use the rate set by the bootloader.
732 * You can override this with mpurate= cmdline option.
733 */
734static int __init omap_clk_setup(char *str)
735{
736 get_option(&str, &mpurate);
737
738 if (!mpurate)
739 return 1;
740
741 if (mpurate < 1000)
742 mpurate *= 1000000;
743
744 return 1;
745}
746__setup("mpurate=", omap_clk_setup);
747
748/* Used for clocks that always have same value as the parent clock */
749unsigned long followparent_recalc(struct clk *clk)
750{
751 return clk->parent->rate;
752}
753
754/*
755 * Used for clocks that have the same value as the parent clock,
756 * divided by some factor
757 */
758unsigned long omap_fixed_divisor_recalc(struct clk *clk)
759{
760 WARN_ON(!clk->fixed_div);
761
762 return clk->parent->rate / clk->fixed_div;
763}
764
765void clk_reparent(struct clk *child, struct clk *parent)
766{
767 list_del_init(&child->sibling);
768 if (parent)
769 list_add(&child->sibling, &parent->children);
770 child->parent = parent;
771
772 /* now do the debugfs renaming to reattach the child
773 to the proper parent */
774}
775
776/* Propagate rate to children */
777void propagate_rate(struct clk *tclk)
778{
779 struct clk *clkp;
780
781 list_for_each_entry(clkp, &tclk->children, sibling) {
782 if (clkp->recalc)
783 clkp->rate = clkp->recalc(clkp);
784 propagate_rate(clkp);
785 }
786}
787
788static LIST_HEAD(root_clks);
789
790/**
791 * recalculate_root_clocks - recalculate and propagate all root clocks
792 *
793 * Recalculates all root clocks (clocks with no parent), which if the
794 * clock's .recalc is set correctly, should also propagate their rates.
795 * Called at init.
796 */
797void recalculate_root_clocks(void)
798{
799 struct clk *clkp;
800
801 list_for_each_entry(clkp, &root_clks, sibling) {
802 if (clkp->recalc)
803 clkp->rate = clkp->recalc(clkp);
804 propagate_rate(clkp);
805 }
806}
807
808/**
809 * clk_preinit - initialize any fields in the struct clk before clk init
810 * @clk: struct clk * to initialize
811 *
812 * Initialize any struct clk fields needed before normal clk initialization
813 * can run. No return value.
814 */
815void clk_preinit(struct clk *clk)
816{
817 INIT_LIST_HEAD(&clk->children);
818}
819
820int clk_register(struct clk *clk)
821{
822 if (clk == NULL || IS_ERR(clk))
823 return -EINVAL;
824
825 /*
826 * trap out already registered clocks
827 */
828 if (clk->node.next || clk->node.prev)
829 return 0;
830
831 mutex_lock(&clocks_mutex);
832 if (clk->parent)
833 list_add(&clk->sibling, &clk->parent->children);
834 else
835 list_add(&clk->sibling, &root_clks);
836
837 list_add(&clk->node, &clocks);
838 if (clk->init)
839 clk->init(clk);
840 mutex_unlock(&clocks_mutex);
841
842 return 0;
843}
844EXPORT_SYMBOL(clk_register);
845
846void clk_unregister(struct clk *clk)
847{
848 if (clk == NULL || IS_ERR(clk))
849 return;
850
851 mutex_lock(&clocks_mutex);
852 list_del(&clk->sibling);
853 list_del(&clk->node);
854 mutex_unlock(&clocks_mutex);
855}
856EXPORT_SYMBOL(clk_unregister);
857
858void clk_enable_init_clocks(void)
859{
860 struct clk *clkp;
861
862 list_for_each_entry(clkp, &clocks, node)
863 if (clkp->flags & ENABLE_ON_INIT)
864 clk_enable(clkp);
865}
866
867/**
868 * omap_clk_get_by_name - locate OMAP struct clk by its name
869 * @name: name of the struct clk to locate
870 *
871 * Locate an OMAP struct clk by its name. Assumes that struct clk
872 * names are unique. Returns NULL if not found or a pointer to the
873 * struct clk if found.
874 */
875struct clk *omap_clk_get_by_name(const char *name)
876{
877 struct clk *c;
878 struct clk *ret = NULL;
879
880 mutex_lock(&clocks_mutex);
881
882 list_for_each_entry(c, &clocks, node) {
883 if (!strcmp(c->name, name)) {
884 ret = c;
885 break;
886 }
887 }
888
889 mutex_unlock(&clocks_mutex);
890
891 return ret;
892}
893
894int omap_clk_enable_autoidle_all(void)
895{
896 struct clk *c;
897 unsigned long flags;
898
899 spin_lock_irqsave(&clockfw_lock, flags);
900
901 list_for_each_entry(c, &clocks, node)
902 if (c->ops->allow_idle)
903 c->ops->allow_idle(c);
904
905 spin_unlock_irqrestore(&clockfw_lock, flags);
906
907 return 0;
908}
909
910int omap_clk_disable_autoidle_all(void)
911{
912 struct clk *c;
913 unsigned long flags;
914
915 spin_lock_irqsave(&clockfw_lock, flags);
916
917 list_for_each_entry(c, &clocks, node)
918 if (c->ops->deny_idle)
919 c->ops->deny_idle(c);
920
921 spin_unlock_irqrestore(&clockfw_lock, flags);
922
923 return 0;
924}
925
926/*
927 * Low level helpers
928 */
929static int clkll_enable_null(struct clk *clk)
930{
931 return 0;
932}
933
934static void clkll_disable_null(struct clk *clk)
935{
936}
937
938const struct clkops clkops_null = {
939 .enable = clkll_enable_null,
940 .disable = clkll_disable_null,
941};
942
943/*
944 * Dummy clock
945 *
946 * Used for clock aliases that are needed on some OMAPs, but not others
947 */
948struct clk dummy_ck = {
949 .name = "dummy",
950 .ops = &clkops_null,
951};
952
953/*
954 *
955 */
956
957#ifdef CONFIG_OMAP_RESET_CLOCKS
958/*
959 * Disable any unused clocks left on by the bootloader
960 */
961static int __init clk_disable_unused(void)
962{
963 struct clk *ck;
964 unsigned long flags;
965
966 pr_info("clock: disabling unused clocks to save power\n");
967
968 spin_lock_irqsave(&clockfw_lock, flags);
969 list_for_each_entry(ck, &clocks, node) {
970 if (ck->ops == &clkops_null)
971 continue;
972
973 if (ck->usecount > 0 || !ck->enable_reg)
974 continue;
975
976 omap1_clk_disable_unused(ck);
977 }
978 spin_unlock_irqrestore(&clockfw_lock, flags);
979
980 return 0;
981}
982late_initcall(clk_disable_unused);
983late_initcall(omap_clk_enable_autoidle_all);
984#endif
985
986#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
987/*
988 * debugfs support to trace clock tree hierarchy and attributes
989 */
990
991#include <linux/debugfs.h>
992#include <linux/seq_file.h>
993
994static struct dentry *clk_debugfs_root;
995
996static int clk_dbg_show_summary(struct seq_file *s, void *unused)
997{
998 struct clk *c;
999 struct clk *pa;
1000
1001 mutex_lock(&clocks_mutex);
1002 seq_printf(s, "%-30s %-30s %-10s %s\n",
1003 "clock-name", "parent-name", "rate", "use-count");
1004
1005 list_for_each_entry(c, &clocks, node) {
1006 pa = c->parent;
1007 seq_printf(s, "%-30s %-30s %-10lu %d\n",
1008 c->name, pa ? pa->name : "none", c->rate,
1009 c->usecount);
1010 }
1011 mutex_unlock(&clocks_mutex);
1012
1013 return 0;
1014}
1015
1016static int clk_dbg_open(struct inode *inode, struct file *file)
1017{
1018 return single_open(file, clk_dbg_show_summary, inode->i_private);
1019}
1020
1021static const struct file_operations debug_clock_fops = {
1022 .open = clk_dbg_open,
1023 .read = seq_read,
1024 .llseek = seq_lseek,
1025 .release = single_release,
1026};
1027
1028static int clk_debugfs_register_one(struct clk *c)
1029{
1030 int err;
1031 struct dentry *d;
1032 struct clk *pa = c->parent;
1033
1034 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
1035 if (!d)
1036 return -ENOMEM;
1037 c->dent = d;
1038
1039 d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
1040 if (!d) {
1041 err = -ENOMEM;
1042 goto err_out;
1043 }
1044 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
1045 if (!d) {
1046 err = -ENOMEM;
1047 goto err_out;
1048 }
1049 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
1050 if (!d) {
1051 err = -ENOMEM;
1052 goto err_out;
1053 }
1054 return 0;
1055
1056err_out:
1057 debugfs_remove_recursive(c->dent);
1058 return err;
1059}
1060
1061static int clk_debugfs_register(struct clk *c)
1062{
1063 int err;
1064 struct clk *pa = c->parent;
1065
1066 if (pa && !pa->dent) {
1067 err = clk_debugfs_register(pa);
1068 if (err)
1069 return err;
1070 }
1071
1072 if (!c->dent) {
1073 err = clk_debugfs_register_one(c);
1074 if (err)
1075 return err;
1076 }
1077 return 0;
1078}
1079
1080static int __init clk_debugfs_init(void)
1081{
1082 struct clk *c;
1083 struct dentry *d;
1084 int err;
1085
1086 d = debugfs_create_dir("clock", NULL);
1087 if (!d)
1088 return -ENOMEM;
1089 clk_debugfs_root = d;
1090
1091 list_for_each_entry(c, &clocks, node) {
1092 err = clk_debugfs_register(c);
1093 if (err)
1094 goto err_out;
1095 }
1096
1097 d = debugfs_create_file("summary", S_IRUGO,
1098 d, NULL, &debug_clock_fops);
1099 if (!d)
1100 return -ENOMEM;
1101
1102 return 0;
1103err_out:
1104 debugfs_remove_recursive(clk_debugfs_root);
1105 return err;
1106}
1107late_initcall(clk_debugfs_init);
1108
1109#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index 4337586195af..28e58eb163f2 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -766,14 +766,6 @@ static struct omap_clk omap_clks[] = {
766 * init 766 * init
767 */ 767 */
768 768
769static struct clk_functions omap1_clk_functions = {
770 .clk_enable = omap1_clk_enable,
771 .clk_disable = omap1_clk_disable,
772 .clk_round_rate = omap1_clk_round_rate,
773 .clk_set_rate = omap1_clk_set_rate,
774 .clk_disable_unused = omap1_clk_disable_unused,
775};
776
777static void __init omap1_show_rates(void) 769static void __init omap1_show_rates(void)
778{ 770{
779 pr_notice("Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", 771 pr_notice("Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
@@ -804,8 +796,6 @@ int __init omap1_clk_init(void)
804 if (!cpu_is_omap15xx()) 796 if (!cpu_is_omap15xx())
805 omap_writew(0, SOFT_REQ_REG2); 797 omap_writew(0, SOFT_REQ_REG2);
806 798
807 clk_init(&omap1_clk_functions);
808
809 /* By default all idlect1 clocks are allowed to idle */ 799 /* By default all idlect1 clocks are allowed to idle */
810 arm_idlect1_mask = ~0; 800 arm_idlect1_mask = ~0;
811 801
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 961ac8f7e13d..33f5b5de86c3 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -15,6 +15,7 @@
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/export.h>
18#include <linux/list.h> 19#include <linux/list.h>
19#include <linux/errno.h> 20#include <linux/errno.h>
20#include <linux/err.h> 21#include <linux/err.h>
@@ -47,6 +48,10 @@ u16 cpu_mask;
47 */ 48 */
48static bool clkdm_control = true; 49static bool clkdm_control = true;
49 50
51static LIST_HEAD(clocks);
52static DEFINE_MUTEX(clocks_mutex);
53static DEFINE_SPINLOCK(clockfw_lock);
54
50/* 55/*
51 * OMAP2+ specific clock functions 56 * OMAP2+ specific clock functions
52 */ 57 */
@@ -512,12 +517,510 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
512 517
513/* Common data */ 518/* Common data */
514 519
515struct clk_functions omap2_clk_functions = { 520int clk_enable(struct clk *clk)
516 .clk_enable = omap2_clk_enable, 521{
517 .clk_disable = omap2_clk_disable, 522 unsigned long flags;
518 .clk_round_rate = omap2_clk_round_rate, 523 int ret;
519 .clk_set_rate = omap2_clk_set_rate, 524
520 .clk_set_parent = omap2_clk_set_parent, 525 if (clk == NULL || IS_ERR(clk))
521 .clk_disable_unused = omap2_clk_disable_unused, 526 return -EINVAL;
527
528 spin_lock_irqsave(&clockfw_lock, flags);
529 ret = omap2_clk_enable(clk);
530 spin_unlock_irqrestore(&clockfw_lock, flags);
531
532 return ret;
533}
534EXPORT_SYMBOL(clk_enable);
535
536void clk_disable(struct clk *clk)
537{
538 unsigned long flags;
539
540 if (clk == NULL || IS_ERR(clk))
541 return;
542
543 spin_lock_irqsave(&clockfw_lock, flags);
544 if (clk->usecount == 0) {
545 pr_err("Trying disable clock %s with 0 usecount\n",
546 clk->name);
547 WARN_ON(1);
548 goto out;
549 }
550
551 omap2_clk_disable(clk);
552
553out:
554 spin_unlock_irqrestore(&clockfw_lock, flags);
555}
556EXPORT_SYMBOL(clk_disable);
557
558unsigned long clk_get_rate(struct clk *clk)
559{
560 unsigned long flags;
561 unsigned long ret;
562
563 if (clk == NULL || IS_ERR(clk))
564 return 0;
565
566 spin_lock_irqsave(&clockfw_lock, flags);
567 ret = clk->rate;
568 spin_unlock_irqrestore(&clockfw_lock, flags);
569
570 return ret;
571}
572EXPORT_SYMBOL(clk_get_rate);
573
574/*
575 * Optional clock functions defined in include/linux/clk.h
576 */
577
578long clk_round_rate(struct clk *clk, unsigned long rate)
579{
580 unsigned long flags;
581 long ret;
582
583 if (clk == NULL || IS_ERR(clk))
584 return 0;
585
586 spin_lock_irqsave(&clockfw_lock, flags);
587 ret = omap2_clk_round_rate(clk, rate);
588 spin_unlock_irqrestore(&clockfw_lock, flags);
589
590 return ret;
591}
592EXPORT_SYMBOL(clk_round_rate);
593
594int clk_set_rate(struct clk *clk, unsigned long rate)
595{
596 unsigned long flags;
597 int ret = -EINVAL;
598
599 if (clk == NULL || IS_ERR(clk))
600 return ret;
601
602 spin_lock_irqsave(&clockfw_lock, flags);
603 ret = omap2_clk_set_rate(clk, rate);
604 if (ret == 0)
605 propagate_rate(clk);
606 spin_unlock_irqrestore(&clockfw_lock, flags);
607
608 return ret;
609}
610EXPORT_SYMBOL(clk_set_rate);
611
612int clk_set_parent(struct clk *clk, struct clk *parent)
613{
614 unsigned long flags;
615 int ret = -EINVAL;
616
617 if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
618 return ret;
619
620 spin_lock_irqsave(&clockfw_lock, flags);
621 if (clk->usecount == 0) {
622 ret = omap2_clk_set_parent(clk, parent);
623 if (ret == 0)
624 propagate_rate(clk);
625 } else {
626 ret = -EBUSY;
627 }
628 spin_unlock_irqrestore(&clockfw_lock, flags);
629
630 return ret;
631}
632EXPORT_SYMBOL(clk_set_parent);
633
634struct clk *clk_get_parent(struct clk *clk)
635{
636 return clk->parent;
637}
638EXPORT_SYMBOL(clk_get_parent);
639
640/*
641 * OMAP specific clock functions shared between omap1 and omap2
642 */
643
644int __initdata mpurate;
645
646/*
647 * By default we use the rate set by the bootloader.
648 * You can override this with mpurate= cmdline option.
649 */
650static int __init omap_clk_setup(char *str)
651{
652 get_option(&str, &mpurate);
653
654 if (!mpurate)
655 return 1;
656
657 if (mpurate < 1000)
658 mpurate *= 1000000;
659
660 return 1;
661}
662__setup("mpurate=", omap_clk_setup);
663
664/* Used for clocks that always have same value as the parent clock */
665unsigned long followparent_recalc(struct clk *clk)
666{
667 return clk->parent->rate;
668}
669
670/*
671 * Used for clocks that have the same value as the parent clock,
672 * divided by some factor
673 */
674unsigned long omap_fixed_divisor_recalc(struct clk *clk)
675{
676 WARN_ON(!clk->fixed_div);
677
678 return clk->parent->rate / clk->fixed_div;
679}
680
681void clk_reparent(struct clk *child, struct clk *parent)
682{
683 list_del_init(&child->sibling);
684 if (parent)
685 list_add(&child->sibling, &parent->children);
686 child->parent = parent;
687
688 /* now do the debugfs renaming to reattach the child
689 to the proper parent */
690}
691
692/* Propagate rate to children */
693void propagate_rate(struct clk *tclk)
694{
695 struct clk *clkp;
696
697 list_for_each_entry(clkp, &tclk->children, sibling) {
698 if (clkp->recalc)
699 clkp->rate = clkp->recalc(clkp);
700 propagate_rate(clkp);
701 }
702}
703
704static LIST_HEAD(root_clks);
705
706/**
707 * recalculate_root_clocks - recalculate and propagate all root clocks
708 *
709 * Recalculates all root clocks (clocks with no parent), which if the
710 * clock's .recalc is set correctly, should also propagate their rates.
711 * Called at init.
712 */
713void recalculate_root_clocks(void)
714{
715 struct clk *clkp;
716
717 list_for_each_entry(clkp, &root_clks, sibling) {
718 if (clkp->recalc)
719 clkp->rate = clkp->recalc(clkp);
720 propagate_rate(clkp);
721 }
722}
723
724/**
725 * clk_preinit - initialize any fields in the struct clk before clk init
726 * @clk: struct clk * to initialize
727 *
728 * Initialize any struct clk fields needed before normal clk initialization
729 * can run. No return value.
730 */
731void clk_preinit(struct clk *clk)
732{
733 INIT_LIST_HEAD(&clk->children);
734}
735
736int clk_register(struct clk *clk)
737{
738 if (clk == NULL || IS_ERR(clk))
739 return -EINVAL;
740
741 /*
742 * trap out already registered clocks
743 */
744 if (clk->node.next || clk->node.prev)
745 return 0;
746
747 mutex_lock(&clocks_mutex);
748 if (clk->parent)
749 list_add(&clk->sibling, &clk->parent->children);
750 else
751 list_add(&clk->sibling, &root_clks);
752
753 list_add(&clk->node, &clocks);
754 if (clk->init)
755 clk->init(clk);
756 mutex_unlock(&clocks_mutex);
757
758 return 0;
759}
760EXPORT_SYMBOL(clk_register);
761
762void clk_unregister(struct clk *clk)
763{
764 if (clk == NULL || IS_ERR(clk))
765 return;
766
767 mutex_lock(&clocks_mutex);
768 list_del(&clk->sibling);
769 list_del(&clk->node);
770 mutex_unlock(&clocks_mutex);
771}
772EXPORT_SYMBOL(clk_unregister);
773
774void clk_enable_init_clocks(void)
775{
776 struct clk *clkp;
777
778 list_for_each_entry(clkp, &clocks, node)
779 if (clkp->flags & ENABLE_ON_INIT)
780 clk_enable(clkp);
781}
782
783/**
784 * omap_clk_get_by_name - locate OMAP struct clk by its name
785 * @name: name of the struct clk to locate
786 *
787 * Locate an OMAP struct clk by its name. Assumes that struct clk
788 * names are unique. Returns NULL if not found or a pointer to the
789 * struct clk if found.
790 */
791struct clk *omap_clk_get_by_name(const char *name)
792{
793 struct clk *c;
794 struct clk *ret = NULL;
795
796 mutex_lock(&clocks_mutex);
797
798 list_for_each_entry(c, &clocks, node) {
799 if (!strcmp(c->name, name)) {
800 ret = c;
801 break;
802 }
803 }
804
805 mutex_unlock(&clocks_mutex);
806
807 return ret;
808}
809
810int omap_clk_enable_autoidle_all(void)
811{
812 struct clk *c;
813 unsigned long flags;
814
815 spin_lock_irqsave(&clockfw_lock, flags);
816
817 list_for_each_entry(c, &clocks, node)
818 if (c->ops->allow_idle)
819 c->ops->allow_idle(c);
820
821 spin_unlock_irqrestore(&clockfw_lock, flags);
822
823 return 0;
824}
825
826int omap_clk_disable_autoidle_all(void)
827{
828 struct clk *c;
829 unsigned long flags;
830
831 spin_lock_irqsave(&clockfw_lock, flags);
832
833 list_for_each_entry(c, &clocks, node)
834 if (c->ops->deny_idle)
835 c->ops->deny_idle(c);
836
837 spin_unlock_irqrestore(&clockfw_lock, flags);
838
839 return 0;
840}
841
842/*
843 * Low level helpers
844 */
845static int clkll_enable_null(struct clk *clk)
846{
847 return 0;
848}
849
850static void clkll_disable_null(struct clk *clk)
851{
852}
853
854const struct clkops clkops_null = {
855 .enable = clkll_enable_null,
856 .disable = clkll_disable_null,
857};
858
859/*
860 * Dummy clock
861 *
862 * Used for clock aliases that are needed on some OMAPs, but not others
863 */
864struct clk dummy_ck = {
865 .name = "dummy",
866 .ops = &clkops_null,
867};
868
869/*
870 *
871 */
872
873#ifdef CONFIG_OMAP_RESET_CLOCKS
874/*
875 * Disable any unused clocks left on by the bootloader
876 */
877static int __init clk_disable_unused(void)
878{
879 struct clk *ck;
880 unsigned long flags;
881
882 pr_info("clock: disabling unused clocks to save power\n");
883
884 spin_lock_irqsave(&clockfw_lock, flags);
885 list_for_each_entry(ck, &clocks, node) {
886 if (ck->ops == &clkops_null)
887 continue;
888
889 if (ck->usecount > 0 || !ck->enable_reg)
890 continue;
891
892 omap2_clk_disable_unused(ck);
893 }
894 spin_unlock_irqrestore(&clockfw_lock, flags);
895
896 return 0;
897}
898late_initcall(clk_disable_unused);
899late_initcall(omap_clk_enable_autoidle_all);
900#endif
901
902#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
903/*
904 * debugfs support to trace clock tree hierarchy and attributes
905 */
906
907#include <linux/debugfs.h>
908#include <linux/seq_file.h>
909
910static struct dentry *clk_debugfs_root;
911
912static int clk_dbg_show_summary(struct seq_file *s, void *unused)
913{
914 struct clk *c;
915 struct clk *pa;
916
917 mutex_lock(&clocks_mutex);
918 seq_printf(s, "%-30s %-30s %-10s %s\n",
919 "clock-name", "parent-name", "rate", "use-count");
920
921 list_for_each_entry(c, &clocks, node) {
922 pa = c->parent;
923 seq_printf(s, "%-30s %-30s %-10lu %d\n",
924 c->name, pa ? pa->name : "none", c->rate,
925 c->usecount);
926 }
927 mutex_unlock(&clocks_mutex);
928
929 return 0;
930}
931
932static int clk_dbg_open(struct inode *inode, struct file *file)
933{
934 return single_open(file, clk_dbg_show_summary, inode->i_private);
935}
936
937static const struct file_operations debug_clock_fops = {
938 .open = clk_dbg_open,
939 .read = seq_read,
940 .llseek = seq_lseek,
941 .release = single_release,
522}; 942};
523 943
944static int clk_debugfs_register_one(struct clk *c)
945{
946 int err;
947 struct dentry *d;
948 struct clk *pa = c->parent;
949
950 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
951 if (!d)
952 return -ENOMEM;
953 c->dent = d;
954
955 d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
956 if (!d) {
957 err = -ENOMEM;
958 goto err_out;
959 }
960 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
961 if (!d) {
962 err = -ENOMEM;
963 goto err_out;
964 }
965 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
966 if (!d) {
967 err = -ENOMEM;
968 goto err_out;
969 }
970 return 0;
971
972err_out:
973 debugfs_remove_recursive(c->dent);
974 return err;
975}
976
977static int clk_debugfs_register(struct clk *c)
978{
979 int err;
980 struct clk *pa = c->parent;
981
982 if (pa && !pa->dent) {
983 err = clk_debugfs_register(pa);
984 if (err)
985 return err;
986 }
987
988 if (!c->dent) {
989 err = clk_debugfs_register_one(c);
990 if (err)
991 return err;
992 }
993 return 0;
994}
995
996static int __init clk_debugfs_init(void)
997{
998 struct clk *c;
999 struct dentry *d;
1000 int err;
1001
1002 d = debugfs_create_dir("clock", NULL);
1003 if (!d)
1004 return -ENOMEM;
1005 clk_debugfs_root = d;
1006
1007 list_for_each_entry(c, &clocks, node) {
1008 err = clk_debugfs_register(c);
1009 if (err)
1010 goto err_out;
1011 }
1012
1013 d = debugfs_create_file("summary", S_IRUGO,
1014 d, NULL, &debug_clock_fops);
1015 if (!d)
1016 return -ENOMEM;
1017
1018 return 0;
1019err_out:
1020 debugfs_remove_recursive(clk_debugfs_root);
1021 return err;
1022}
1023late_initcall(clk_debugfs_init);
1024
1025#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
1026
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index c3cde1a2b6de..5be7405f2328 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1935,8 +1935,6 @@ int __init omap2420_clk_init(void)
1935 cpu_mask = RATE_IN_242X; 1935 cpu_mask = RATE_IN_242X;
1936 rate_table = omap2420_rate_table; 1936 rate_table = omap2420_rate_table;
1937 1937
1938 clk_init(&omap2_clk_functions);
1939
1940 for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks); 1938 for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
1941 c++) 1939 c++)
1942 clk_preinit(c->lk.clk); 1940 clk_preinit(c->lk.clk);
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 22404fe435e7..17f110de88ea 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -2034,8 +2034,6 @@ int __init omap2430_clk_init(void)
2034 cpu_mask = RATE_IN_243X; 2034 cpu_mask = RATE_IN_243X;
2035 rate_table = omap2430_rate_table; 2035 rate_table = omap2430_rate_table;
2036 2036
2037 clk_init(&omap2_clk_functions);
2038
2039 for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks); 2037 for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
2040 c++) 2038 c++)
2041 clk_preinit(c->lk.clk); 2039 clk_preinit(c->lk.clk);
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
index 114ab4b8e0e3..3491b1769d4e 100644
--- a/arch/arm/mach-omap2/clock33xx_data.c
+++ b/arch/arm/mach-omap2/clock33xx_data.c
@@ -1085,8 +1085,6 @@ int __init am33xx_clk_init(void)
1085 cpu_clkflg = CK_AM33XX; 1085 cpu_clkflg = CK_AM33XX;
1086 } 1086 }
1087 1087
1088 clk_init(&omap2_clk_functions);
1089
1090 for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) 1088 for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)
1091 clk_preinit(c->lk.clk); 1089 clk_preinit(c->lk.clk);
1092 1090
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 1f42c9d5ecf3..e75d0c8f8300 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3573,8 +3573,6 @@ int __init omap3xxx_clk_init(void)
3573 else 3573 else
3574 dpll4_dd = dpll4_dd_34xx; 3574 dpll4_dd = dpll4_dd_34xx;
3575 3575
3576 clk_init(&omap2_clk_functions);
3577
3578 for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); 3576 for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
3579 c++) 3577 c++)
3580 clk_preinit(c->lk.clk); 3578 clk_preinit(c->lk.clk);
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index d661d138f270..c2450a64736b 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3366,8 +3366,6 @@ int __init omap4xxx_clk_init(void)
3366 return 0; 3366 return 0;
3367 } 3367 }
3368 3368
3369 clk_init(&omap2_clk_functions);
3370
3371 /* 3369 /*
3372 * Must stay commented until all OMAP SoC drivers are 3370 * Must stay commented until all OMAP SoC drivers are
3373 * converted to runtime PM, or drivers may start crashing 3371 * converted to runtime PM, or drivers may start crashing
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9c81cf539218..4bd0ace20e98 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5# Common support 5# Common support
6obj-y := common.o sram.o clock.o dma.o fb.o counter_32k.o 6obj-y := common.o sram.o dma.o fb.o counter_32k.o
7obj-m := 7obj-m :=
8obj-n := 8obj-n :=
9obj- := 9obj- :=
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
deleted file mode 100644
index 9d7ac20ef8f9..000000000000
--- a/arch/arm/plat-omap/clock.c
+++ /dev/null
@@ -1,544 +0,0 @@
1/*
2 * linux/arch/arm/plat-omap/clock.c
3 *
4 * Copyright (C) 2004 - 2008 Nokia corporation
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6 *
7 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/list.h>
16#include <linux/errno.h>
17#include <linux/export.h>
18#include <linux/err.h>
19#include <linux/string.h>
20#include <linux/clk.h>
21#include <linux/mutex.h>
22#include <linux/cpufreq.h>
23#include <linux/io.h>
24
25#include <plat/clock.h>
26
27static LIST_HEAD(clocks);
28static DEFINE_MUTEX(clocks_mutex);
29static DEFINE_SPINLOCK(clockfw_lock);
30
31static struct clk_functions *arch_clock;
32
33/*
34 * Standard clock functions defined in include/linux/clk.h
35 */
36
37int clk_enable(struct clk *clk)
38{
39 unsigned long flags;
40 int ret;
41
42 if (clk == NULL || IS_ERR(clk))
43 return -EINVAL;
44
45 if (!arch_clock || !arch_clock->clk_enable)
46 return -EINVAL;
47
48 spin_lock_irqsave(&clockfw_lock, flags);
49 ret = arch_clock->clk_enable(clk);
50 spin_unlock_irqrestore(&clockfw_lock, flags);
51
52 return ret;
53}
54EXPORT_SYMBOL(clk_enable);
55
56void clk_disable(struct clk *clk)
57{
58 unsigned long flags;
59
60 if (clk == NULL || IS_ERR(clk))
61 return;
62
63 if (!arch_clock || !arch_clock->clk_disable)
64 return;
65
66 spin_lock_irqsave(&clockfw_lock, flags);
67 if (clk->usecount == 0) {
68 pr_err("Trying disable clock %s with 0 usecount\n",
69 clk->name);
70 WARN_ON(1);
71 goto out;
72 }
73
74 arch_clock->clk_disable(clk);
75
76out:
77 spin_unlock_irqrestore(&clockfw_lock, flags);
78}
79EXPORT_SYMBOL(clk_disable);
80
81unsigned long clk_get_rate(struct clk *clk)
82{
83 unsigned long flags;
84 unsigned long ret;
85
86 if (clk == NULL || IS_ERR(clk))
87 return 0;
88
89 spin_lock_irqsave(&clockfw_lock, flags);
90 ret = clk->rate;
91 spin_unlock_irqrestore(&clockfw_lock, flags);
92
93 return ret;
94}
95EXPORT_SYMBOL(clk_get_rate);
96
97/*
98 * Optional clock functions defined in include/linux/clk.h
99 */
100
101long clk_round_rate(struct clk *clk, unsigned long rate)
102{
103 unsigned long flags;
104 long ret;
105
106 if (clk == NULL || IS_ERR(clk))
107 return 0;
108
109 if (!arch_clock || !arch_clock->clk_round_rate)
110 return 0;
111
112 spin_lock_irqsave(&clockfw_lock, flags);
113 ret = arch_clock->clk_round_rate(clk, rate);
114 spin_unlock_irqrestore(&clockfw_lock, flags);
115
116 return ret;
117}
118EXPORT_SYMBOL(clk_round_rate);
119
120int clk_set_rate(struct clk *clk, unsigned long rate)
121{
122 unsigned long flags;
123 int ret = -EINVAL;
124
125 if (clk == NULL || IS_ERR(clk))
126 return ret;
127
128 if (!arch_clock || !arch_clock->clk_set_rate)
129 return ret;
130
131 spin_lock_irqsave(&clockfw_lock, flags);
132 ret = arch_clock->clk_set_rate(clk, rate);
133 if (ret == 0)
134 propagate_rate(clk);
135 spin_unlock_irqrestore(&clockfw_lock, flags);
136
137 return ret;
138}
139EXPORT_SYMBOL(clk_set_rate);
140
141int clk_set_parent(struct clk *clk, struct clk *parent)
142{
143 unsigned long flags;
144 int ret = -EINVAL;
145
146 if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
147 return ret;
148
149 if (!arch_clock || !arch_clock->clk_set_parent)
150 return ret;
151
152 spin_lock_irqsave(&clockfw_lock, flags);
153 if (clk->usecount == 0) {
154 ret = arch_clock->clk_set_parent(clk, parent);
155 if (ret == 0)
156 propagate_rate(clk);
157 } else
158 ret = -EBUSY;
159 spin_unlock_irqrestore(&clockfw_lock, flags);
160
161 return ret;
162}
163EXPORT_SYMBOL(clk_set_parent);
164
165struct clk *clk_get_parent(struct clk *clk)
166{
167 return clk->parent;
168}
169EXPORT_SYMBOL(clk_get_parent);
170
171/*
172 * OMAP specific clock functions shared between omap1 and omap2
173 */
174
175int __initdata mpurate;
176
177/*
178 * By default we use the rate set by the bootloader.
179 * You can override this with mpurate= cmdline option.
180 */
181static int __init omap_clk_setup(char *str)
182{
183 get_option(&str, &mpurate);
184
185 if (!mpurate)
186 return 1;
187
188 if (mpurate < 1000)
189 mpurate *= 1000000;
190
191 return 1;
192}
193__setup("mpurate=", omap_clk_setup);
194
195/* Used for clocks that always have same value as the parent clock */
196unsigned long followparent_recalc(struct clk *clk)
197{
198 return clk->parent->rate;
199}
200
201/*
202 * Used for clocks that have the same value as the parent clock,
203 * divided by some factor
204 */
205unsigned long omap_fixed_divisor_recalc(struct clk *clk)
206{
207 WARN_ON(!clk->fixed_div);
208
209 return clk->parent->rate / clk->fixed_div;
210}
211
212void clk_reparent(struct clk *child, struct clk *parent)
213{
214 list_del_init(&child->sibling);
215 if (parent)
216 list_add(&child->sibling, &parent->children);
217 child->parent = parent;
218
219 /* now do the debugfs renaming to reattach the child
220 to the proper parent */
221}
222
223/* Propagate rate to children */
224void propagate_rate(struct clk *tclk)
225{
226 struct clk *clkp;
227
228 list_for_each_entry(clkp, &tclk->children, sibling) {
229 if (clkp->recalc)
230 clkp->rate = clkp->recalc(clkp);
231 propagate_rate(clkp);
232 }
233}
234
235static LIST_HEAD(root_clks);
236
237/**
238 * recalculate_root_clocks - recalculate and propagate all root clocks
239 *
240 * Recalculates all root clocks (clocks with no parent), which if the
241 * clock's .recalc is set correctly, should also propagate their rates.
242 * Called at init.
243 */
244void recalculate_root_clocks(void)
245{
246 struct clk *clkp;
247
248 list_for_each_entry(clkp, &root_clks, sibling) {
249 if (clkp->recalc)
250 clkp->rate = clkp->recalc(clkp);
251 propagate_rate(clkp);
252 }
253}
254
255/**
256 * clk_preinit - initialize any fields in the struct clk before clk init
257 * @clk: struct clk * to initialize
258 *
259 * Initialize any struct clk fields needed before normal clk initialization
260 * can run. No return value.
261 */
262void clk_preinit(struct clk *clk)
263{
264 INIT_LIST_HEAD(&clk->children);
265}
266
267int clk_register(struct clk *clk)
268{
269 if (clk == NULL || IS_ERR(clk))
270 return -EINVAL;
271
272 /*
273 * trap out already registered clocks
274 */
275 if (clk->node.next || clk->node.prev)
276 return 0;
277
278 mutex_lock(&clocks_mutex);
279 if (clk->parent)
280 list_add(&clk->sibling, &clk->parent->children);
281 else
282 list_add(&clk->sibling, &root_clks);
283
284 list_add(&clk->node, &clocks);
285 if (clk->init)
286 clk->init(clk);
287 mutex_unlock(&clocks_mutex);
288
289 return 0;
290}
291EXPORT_SYMBOL(clk_register);
292
293void clk_unregister(struct clk *clk)
294{
295 if (clk == NULL || IS_ERR(clk))
296 return;
297
298 mutex_lock(&clocks_mutex);
299 list_del(&clk->sibling);
300 list_del(&clk->node);
301 mutex_unlock(&clocks_mutex);
302}
303EXPORT_SYMBOL(clk_unregister);
304
305void clk_enable_init_clocks(void)
306{
307 struct clk *clkp;
308
309 list_for_each_entry(clkp, &clocks, node) {
310 if (clkp->flags & ENABLE_ON_INIT)
311 clk_enable(clkp);
312 }
313}
314
315int omap_clk_enable_autoidle_all(void)
316{
317 struct clk *c;
318 unsigned long flags;
319
320 spin_lock_irqsave(&clockfw_lock, flags);
321
322 list_for_each_entry(c, &clocks, node)
323 if (c->ops->allow_idle)
324 c->ops->allow_idle(c);
325
326 spin_unlock_irqrestore(&clockfw_lock, flags);
327
328 return 0;
329}
330
331int omap_clk_disable_autoidle_all(void)
332{
333 struct clk *c;
334 unsigned long flags;
335
336 spin_lock_irqsave(&clockfw_lock, flags);
337
338 list_for_each_entry(c, &clocks, node)
339 if (c->ops->deny_idle)
340 c->ops->deny_idle(c);
341
342 spin_unlock_irqrestore(&clockfw_lock, flags);
343
344 return 0;
345}
346
347/*
348 * Low level helpers
349 */
350static int clkll_enable_null(struct clk *clk)
351{
352 return 0;
353}
354
355static void clkll_disable_null(struct clk *clk)
356{
357}
358
359const struct clkops clkops_null = {
360 .enable = clkll_enable_null,
361 .disable = clkll_disable_null,
362};
363
364/*
365 * Dummy clock
366 *
367 * Used for clock aliases that are needed on some OMAPs, but not others
368 */
369struct clk dummy_ck = {
370 .name = "dummy",
371 .ops = &clkops_null,
372};
373
374/*
375 *
376 */
377
378#ifdef CONFIG_OMAP_RESET_CLOCKS
379/*
380 * Disable any unused clocks left on by the bootloader
381 */
382static int __init clk_disable_unused(void)
383{
384 struct clk *ck;
385 unsigned long flags;
386
387 if (!arch_clock || !arch_clock->clk_disable_unused)
388 return 0;
389
390 pr_info("clock: disabling unused clocks to save power\n");
391
392 spin_lock_irqsave(&clockfw_lock, flags);
393 list_for_each_entry(ck, &clocks, node) {
394 if (ck->ops == &clkops_null)
395 continue;
396
397 if (ck->usecount > 0 || !ck->enable_reg)
398 continue;
399
400 arch_clock->clk_disable_unused(ck);
401 }
402 spin_unlock_irqrestore(&clockfw_lock, flags);
403
404 return 0;
405}
406late_initcall(clk_disable_unused);
407late_initcall(omap_clk_enable_autoidle_all);
408#endif
409
410int __init clk_init(struct clk_functions * custom_clocks)
411{
412 if (!custom_clocks) {
413 pr_err("No custom clock functions registered\n");
414 BUG();
415 }
416
417 arch_clock = custom_clocks;
418
419 return 0;
420}
421
422#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
423/*
424 * debugfs support to trace clock tree hierarchy and attributes
425 */
426
427#include <linux/debugfs.h>
428#include <linux/seq_file.h>
429
430static struct dentry *clk_debugfs_root;
431
432static int clk_dbg_show_summary(struct seq_file *s, void *unused)
433{
434 struct clk *c;
435 struct clk *pa;
436
437 mutex_lock(&clocks_mutex);
438 seq_printf(s, "%-30s %-30s %-10s %s\n",
439 "clock-name", "parent-name", "rate", "use-count");
440
441 list_for_each_entry(c, &clocks, node) {
442 pa = c->parent;
443 seq_printf(s, "%-30s %-30s %-10lu %d\n",
444 c->name, pa ? pa->name : "none", c->rate, c->usecount);
445 }
446 mutex_unlock(&clocks_mutex);
447
448 return 0;
449}
450
451static int clk_dbg_open(struct inode *inode, struct file *file)
452{
453 return single_open(file, clk_dbg_show_summary, inode->i_private);
454}
455
456static const struct file_operations debug_clock_fops = {
457 .open = clk_dbg_open,
458 .read = seq_read,
459 .llseek = seq_lseek,
460 .release = single_release,
461};
462
463static int clk_debugfs_register_one(struct clk *c)
464{
465 int err;
466 struct dentry *d;
467 struct clk *pa = c->parent;
468
469 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
470 if (!d)
471 return -ENOMEM;
472 c->dent = d;
473
474 d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
475 if (!d) {
476 err = -ENOMEM;
477 goto err_out;
478 }
479 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
480 if (!d) {
481 err = -ENOMEM;
482 goto err_out;
483 }
484 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
485 if (!d) {
486 err = -ENOMEM;
487 goto err_out;
488 }
489 return 0;
490
491err_out:
492 debugfs_remove_recursive(c->dent);
493 return err;
494}
495
496static int clk_debugfs_register(struct clk *c)
497{
498 int err;
499 struct clk *pa = c->parent;
500
501 if (pa && !pa->dent) {
502 err = clk_debugfs_register(pa);
503 if (err)
504 return err;
505 }
506
507 if (!c->dent) {
508 err = clk_debugfs_register_one(c);
509 if (err)
510 return err;
511 }
512 return 0;
513}
514
515static int __init clk_debugfs_init(void)
516{
517 struct clk *c;
518 struct dentry *d;
519 int err;
520
521 d = debugfs_create_dir("clock", NULL);
522 if (!d)
523 return -ENOMEM;
524 clk_debugfs_root = d;
525
526 list_for_each_entry(c, &clocks, node) {
527 err = clk_debugfs_register(c);
528 if (err)
529 goto err_out;
530 }
531
532 d = debugfs_create_file("summary", S_IRUGO,
533 d, NULL, &debug_clock_fops);
534 if (!d)
535 return -ENOMEM;
536
537 return 0;
538err_out:
539 debugfs_remove_recursive(clk_debugfs_root);
540 return err;
541}
542late_initcall(clk_debugfs_init);
543
544#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */