aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1
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/arm/mach-omap1
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/arm/mach-omap1')
-rw-r--r--arch/arm/mach-omap1/clock.c499
-rw-r--r--arch/arm/mach-omap1/clock_data.c10
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;
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