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/arm/mach-omap1 | |
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/arm/mach-omap1')
-rw-r--r-- | arch/arm/mach-omap1/clock.c | 499 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock_data.c | 10 |
2 files changed, 499 insertions, 10 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 | ||