diff options
author | Paul Walmsley <paul@pwsan.com> | 2012-09-27 12:33:33 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-10-18 19:22:26 -0400 |
commit | 1fe9be8248ae9a04a09fcec7fed486d31e7f0897 (patch) | |
tree | aa65df4a2e59363d9274c20d9441ff817f22e7cf /arch | |
parent | f7a9b8a147cc10c7181cf0ca7b2b06cebf950140 (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.c | 499 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock_data.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 517 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock2420_data.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock2430_data.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock33xx_data.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3xxx_data.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx_data.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 544 |
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; |
38 | struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; | 39 | struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; |
39 | 40 | ||
41 | static LIST_HEAD(clocks); | ||
42 | static DEFINE_MUTEX(clocks_mutex); | ||
43 | static 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 | |||
618 | int 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 | } | ||
632 | EXPORT_SYMBOL(clk_enable); | ||
633 | |||
634 | void 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 | |||
651 | out: | ||
652 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
653 | } | ||
654 | EXPORT_SYMBOL(clk_disable); | ||
655 | |||
656 | unsigned 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 | } | ||
670 | EXPORT_SYMBOL(clk_get_rate); | ||
671 | |||
672 | /* | ||
673 | * Optional clock functions defined in include/linux/clk.h | ||
674 | */ | ||
675 | |||
676 | long 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 | } | ||
690 | EXPORT_SYMBOL(clk_round_rate); | ||
691 | |||
692 | int 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 | } | ||
708 | EXPORT_SYMBOL(clk_set_rate); | ||
709 | |||
710 | int 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 | } | ||
716 | EXPORT_SYMBOL(clk_set_parent); | ||
717 | |||
718 | struct clk *clk_get_parent(struct clk *clk) | ||
719 | { | ||
720 | return clk->parent; | ||
721 | } | ||
722 | EXPORT_SYMBOL(clk_get_parent); | ||
723 | |||
724 | /* | ||
725 | * OMAP specific clock functions shared between omap1 and omap2 | ||
726 | */ | ||
727 | |||
728 | int __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 | */ | ||
734 | static 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 */ | ||
749 | unsigned 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 | */ | ||
758 | unsigned 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 | |||
765 | void 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 */ | ||
777 | void 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 | |||
788 | static 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 | */ | ||
797 | void 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 | */ | ||
815 | void clk_preinit(struct clk *clk) | ||
816 | { | ||
817 | INIT_LIST_HEAD(&clk->children); | ||
818 | } | ||
819 | |||
820 | int 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 | } | ||
844 | EXPORT_SYMBOL(clk_register); | ||
845 | |||
846 | void 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 | } | ||
856 | EXPORT_SYMBOL(clk_unregister); | ||
857 | |||
858 | void 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 | */ | ||
875 | struct 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 | |||
894 | int 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 | |||
910 | int 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 | */ | ||
929 | static int clkll_enable_null(struct clk *clk) | ||
930 | { | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static void clkll_disable_null(struct clk *clk) | ||
935 | { | ||
936 | } | ||
937 | |||
938 | const 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 | */ | ||
948 | struct 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 | */ | ||
961 | static 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 | } | ||
982 | late_initcall(clk_disable_unused); | ||
983 | late_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 | |||
994 | static struct dentry *clk_debugfs_root; | ||
995 | |||
996 | static 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 | |||
1016 | static 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 | |||
1021 | static 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 | |||
1028 | static 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 | |||
1056 | err_out: | ||
1057 | debugfs_remove_recursive(c->dent); | ||
1058 | return err; | ||
1059 | } | ||
1060 | |||
1061 | static 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 | |||
1080 | static 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; | ||
1103 | err_out: | ||
1104 | debugfs_remove_recursive(clk_debugfs_root); | ||
1105 | return err; | ||
1106 | } | ||
1107 | late_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 | ||
769 | static 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 | |||
777 | static void __init omap1_show_rates(void) | 769 | static 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 | */ |
48 | static bool clkdm_control = true; | 49 | static bool clkdm_control = true; |
49 | 50 | ||
51 | static LIST_HEAD(clocks); | ||
52 | static DEFINE_MUTEX(clocks_mutex); | ||
53 | static 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 | ||
515 | struct clk_functions omap2_clk_functions = { | 520 | int 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 | } | ||
534 | EXPORT_SYMBOL(clk_enable); | ||
535 | |||
536 | void 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 | |||
553 | out: | ||
554 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
555 | } | ||
556 | EXPORT_SYMBOL(clk_disable); | ||
557 | |||
558 | unsigned 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 | } | ||
572 | EXPORT_SYMBOL(clk_get_rate); | ||
573 | |||
574 | /* | ||
575 | * Optional clock functions defined in include/linux/clk.h | ||
576 | */ | ||
577 | |||
578 | long 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 | } | ||
592 | EXPORT_SYMBOL(clk_round_rate); | ||
593 | |||
594 | int 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 | } | ||
610 | EXPORT_SYMBOL(clk_set_rate); | ||
611 | |||
612 | int 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 | } | ||
632 | EXPORT_SYMBOL(clk_set_parent); | ||
633 | |||
634 | struct clk *clk_get_parent(struct clk *clk) | ||
635 | { | ||
636 | return clk->parent; | ||
637 | } | ||
638 | EXPORT_SYMBOL(clk_get_parent); | ||
639 | |||
640 | /* | ||
641 | * OMAP specific clock functions shared between omap1 and omap2 | ||
642 | */ | ||
643 | |||
644 | int __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 | */ | ||
650 | static 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 */ | ||
665 | unsigned 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 | */ | ||
674 | unsigned 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 | |||
681 | void 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 */ | ||
693 | void 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 | |||
704 | static 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 | */ | ||
713 | void 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 | */ | ||
731 | void clk_preinit(struct clk *clk) | ||
732 | { | ||
733 | INIT_LIST_HEAD(&clk->children); | ||
734 | } | ||
735 | |||
736 | int 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 | } | ||
760 | EXPORT_SYMBOL(clk_register); | ||
761 | |||
762 | void 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 | } | ||
772 | EXPORT_SYMBOL(clk_unregister); | ||
773 | |||
774 | void 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 | */ | ||
791 | struct 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 | |||
810 | int 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 | |||
826 | int 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 | */ | ||
845 | static int clkll_enable_null(struct clk *clk) | ||
846 | { | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static void clkll_disable_null(struct clk *clk) | ||
851 | { | ||
852 | } | ||
853 | |||
854 | const 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 | */ | ||
864 | struct 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 | */ | ||
877 | static 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 | } | ||
898 | late_initcall(clk_disable_unused); | ||
899 | late_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 | |||
910 | static struct dentry *clk_debugfs_root; | ||
911 | |||
912 | static 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 | |||
932 | static 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 | |||
937 | static 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 | ||
944 | static 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 | |||
972 | err_out: | ||
973 | debugfs_remove_recursive(c->dent); | ||
974 | return err; | ||
975 | } | ||
976 | |||
977 | static 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 | |||
996 | static 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; | ||
1019 | err_out: | ||
1020 | debugfs_remove_recursive(clk_debugfs_root); | ||
1021 | return err; | ||
1022 | } | ||
1023 | late_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 |
6 | obj-y := common.o sram.o clock.o dma.o fb.o counter_32k.o | 6 | obj-y := common.o sram.o dma.o fb.o counter_32k.o |
7 | obj-m := | 7 | obj-m := |
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
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 | |||
27 | static LIST_HEAD(clocks); | ||
28 | static DEFINE_MUTEX(clocks_mutex); | ||
29 | static DEFINE_SPINLOCK(clockfw_lock); | ||
30 | |||
31 | static struct clk_functions *arch_clock; | ||
32 | |||
33 | /* | ||
34 | * Standard clock functions defined in include/linux/clk.h | ||
35 | */ | ||
36 | |||
37 | int 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 | } | ||
54 | EXPORT_SYMBOL(clk_enable); | ||
55 | |||
56 | void 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 | |||
76 | out: | ||
77 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
78 | } | ||
79 | EXPORT_SYMBOL(clk_disable); | ||
80 | |||
81 | unsigned 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 | } | ||
95 | EXPORT_SYMBOL(clk_get_rate); | ||
96 | |||
97 | /* | ||
98 | * Optional clock functions defined in include/linux/clk.h | ||
99 | */ | ||
100 | |||
101 | long 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 | } | ||
118 | EXPORT_SYMBOL(clk_round_rate); | ||
119 | |||
120 | int 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 | } | ||
139 | EXPORT_SYMBOL(clk_set_rate); | ||
140 | |||
141 | int 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 | } | ||
163 | EXPORT_SYMBOL(clk_set_parent); | ||
164 | |||
165 | struct clk *clk_get_parent(struct clk *clk) | ||
166 | { | ||
167 | return clk->parent; | ||
168 | } | ||
169 | EXPORT_SYMBOL(clk_get_parent); | ||
170 | |||
171 | /* | ||
172 | * OMAP specific clock functions shared between omap1 and omap2 | ||
173 | */ | ||
174 | |||
175 | int __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 | */ | ||
181 | static 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 */ | ||
196 | unsigned 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 | */ | ||
205 | unsigned 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 | |||
212 | void 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 */ | ||
224 | void 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 | |||
235 | static 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 | */ | ||
244 | void 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 | */ | ||
262 | void clk_preinit(struct clk *clk) | ||
263 | { | ||
264 | INIT_LIST_HEAD(&clk->children); | ||
265 | } | ||
266 | |||
267 | int 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 | } | ||
291 | EXPORT_SYMBOL(clk_register); | ||
292 | |||
293 | void 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 | } | ||
303 | EXPORT_SYMBOL(clk_unregister); | ||
304 | |||
305 | void 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 | |||
315 | int 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 | |||
331 | int 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 | */ | ||
350 | static int clkll_enable_null(struct clk *clk) | ||
351 | { | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static void clkll_disable_null(struct clk *clk) | ||
356 | { | ||
357 | } | ||
358 | |||
359 | const 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 | */ | ||
369 | struct 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 | */ | ||
382 | static 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 | } | ||
406 | late_initcall(clk_disable_unused); | ||
407 | late_initcall(omap_clk_enable_autoidle_all); | ||
408 | #endif | ||
409 | |||
410 | int __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 | |||
430 | static struct dentry *clk_debugfs_root; | ||
431 | |||
432 | static 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 | |||
451 | static 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 | |||
456 | static 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 | |||
463 | static 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 | |||
491 | err_out: | ||
492 | debugfs_remove_recursive(c->dent); | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | static 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 | |||
515 | static 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; | ||
538 | err_out: | ||
539 | debugfs_remove_recursive(clk_debugfs_root); | ||
540 | return err; | ||
541 | } | ||
542 | late_initcall(clk_debugfs_init); | ||
543 | |||
544 | #endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ | ||