aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap1/clock.c')
-rw-r--r--arch/arm/mach-omap1/clock.c508
1 files changed, 502 insertions, 6 deletions
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 638f4070fc70..931f3f6d396b 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>
@@ -21,14 +22,11 @@
21 22
22#include <asm/mach-types.h> 23#include <asm/mach-types.h>
23 24
24#include <plat/cpu.h>
25#include <plat/usb.h>
26#include <plat/clock.h>
27#include <plat/sram.h>
28#include <plat/clkdev_omap.h>
29
30#include <mach/hardware.h> 25#include <mach/hardware.h>
31 26
27#include "../plat-omap/sram.h"
28
29#include "soc.h"
32#include "iomap.h" 30#include "iomap.h"
33#include "clock.h" 31#include "clock.h"
34#include "opp.h" 32#include "opp.h"
@@ -36,6 +34,10 @@
36__u32 arm_idlect1_mask; 34__u32 arm_idlect1_mask;
37struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p; 35struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
38 36
37static LIST_HEAD(clocks);
38static DEFINE_MUTEX(clocks_mutex);
39static DEFINE_SPINLOCK(clockfw_lock);
40
39/* 41/*
40 * Omap1 specific clock functions 42 * Omap1 specific clock functions
41 */ 43 */
@@ -607,3 +609,497 @@ void omap1_clk_disable_unused(struct clk *clk)
607} 609}
608 610
609#endif 611#endif
612
613
614int clk_enable(struct clk *clk)
615{
616 unsigned long flags;
617 int ret;
618
619 if (clk == NULL || IS_ERR(clk))
620 return -EINVAL;
621
622 spin_lock_irqsave(&clockfw_lock, flags);
623 ret = omap1_clk_enable(clk);
624 spin_unlock_irqrestore(&clockfw_lock, flags);
625
626 return ret;
627}
628EXPORT_SYMBOL(clk_enable);
629
630void clk_disable(struct clk *clk)
631{
632 unsigned long flags;
633
634 if (clk == NULL || IS_ERR(clk))
635 return;
636
637 spin_lock_irqsave(&clockfw_lock, flags);
638 if (clk->usecount == 0) {
639 pr_err("Trying disable clock %s with 0 usecount\n",
640 clk->name);
641 WARN_ON(1);
642 goto out;
643 }
644
645 omap1_clk_disable(clk);
646
647out:
648 spin_unlock_irqrestore(&clockfw_lock, flags);
649}
650EXPORT_SYMBOL(clk_disable);
651
652unsigned long clk_get_rate(struct clk *clk)
653{
654 unsigned long flags;
655 unsigned long ret;
656
657 if (clk == NULL || IS_ERR(clk))
658 return 0;
659
660 spin_lock_irqsave(&clockfw_lock, flags);
661 ret = clk->rate;
662 spin_unlock_irqrestore(&clockfw_lock, flags);
663
664 return ret;
665}
666EXPORT_SYMBOL(clk_get_rate);
667
668/*
669 * Optional clock functions defined in include/linux/clk.h
670 */
671
672long clk_round_rate(struct clk *clk, unsigned long rate)
673{
674 unsigned long flags;
675 long ret;
676
677 if (clk == NULL || IS_ERR(clk))
678 return 0;
679
680 spin_lock_irqsave(&clockfw_lock, flags);
681 ret = omap1_clk_round_rate(clk, rate);
682 spin_unlock_irqrestore(&clockfw_lock, flags);
683
684 return ret;
685}
686EXPORT_SYMBOL(clk_round_rate);
687
688int clk_set_rate(struct clk *clk, unsigned long rate)
689{
690 unsigned long flags;
691 int ret = -EINVAL;
692
693 if (clk == NULL || IS_ERR(clk))
694 return ret;
695
696 spin_lock_irqsave(&clockfw_lock, flags);
697 ret = omap1_clk_set_rate(clk, rate);
698 if (ret == 0)
699 propagate_rate(clk);
700 spin_unlock_irqrestore(&clockfw_lock, flags);
701
702 return ret;
703}
704EXPORT_SYMBOL(clk_set_rate);
705
706int clk_set_parent(struct clk *clk, struct clk *parent)
707{
708 WARN_ONCE(1, "clk_set_parent() not implemented for OMAP1\n");
709
710 return -EINVAL;
711}
712EXPORT_SYMBOL(clk_set_parent);
713
714struct clk *clk_get_parent(struct clk *clk)
715{
716 return clk->parent;
717}
718EXPORT_SYMBOL(clk_get_parent);
719
720/*
721 * OMAP specific clock functions shared between omap1 and omap2
722 */
723
724int __initdata mpurate;
725
726/*
727 * By default we use the rate set by the bootloader.
728 * You can override this with mpurate= cmdline option.
729 */
730static int __init omap_clk_setup(char *str)
731{
732 get_option(&str, &mpurate);
733
734 if (!mpurate)
735 return 1;
736
737 if (mpurate < 1000)
738 mpurate *= 1000000;
739
740 return 1;
741}
742__setup("mpurate=", omap_clk_setup);
743
744/* Used for clocks that always have same value as the parent clock */
745unsigned long followparent_recalc(struct clk *clk)
746{
747 return clk->parent->rate;
748}
749
750/*
751 * Used for clocks that have the same value as the parent clock,
752 * divided by some factor
753 */
754unsigned long omap_fixed_divisor_recalc(struct clk *clk)
755{
756 WARN_ON(!clk->fixed_div);
757
758 return clk->parent->rate / clk->fixed_div;
759}
760
761void clk_reparent(struct clk *child, struct clk *parent)
762{
763 list_del_init(&child->sibling);
764 if (parent)
765 list_add(&child->sibling, &parent->children);
766 child->parent = parent;
767
768 /* now do the debugfs renaming to reattach the child
769 to the proper parent */
770}
771
772/* Propagate rate to children */
773void propagate_rate(struct clk *tclk)
774{
775 struct clk *clkp;
776
777 list_for_each_entry(clkp, &tclk->children, sibling) {
778 if (clkp->recalc)
779 clkp->rate = clkp->recalc(clkp);
780 propagate_rate(clkp);
781 }
782}
783
784static LIST_HEAD(root_clks);
785
786/**
787 * recalculate_root_clocks - recalculate and propagate all root clocks
788 *
789 * Recalculates all root clocks (clocks with no parent), which if the
790 * clock's .recalc is set correctly, should also propagate their rates.
791 * Called at init.
792 */
793void recalculate_root_clocks(void)
794{
795 struct clk *clkp;
796
797 list_for_each_entry(clkp, &root_clks, sibling) {
798 if (clkp->recalc)
799 clkp->rate = clkp->recalc(clkp);
800 propagate_rate(clkp);
801 }
802}
803
804/**
805 * clk_preinit - initialize any fields in the struct clk before clk init
806 * @clk: struct clk * to initialize
807 *
808 * Initialize any struct clk fields needed before normal clk initialization
809 * can run. No return value.
810 */
811void clk_preinit(struct clk *clk)
812{
813 INIT_LIST_HEAD(&clk->children);
814}
815
816int clk_register(struct clk *clk)
817{
818 if (clk == NULL || IS_ERR(clk))
819 return -EINVAL;
820
821 /*
822 * trap out already registered clocks
823 */
824 if (clk->node.next || clk->node.prev)
825 return 0;
826
827 mutex_lock(&clocks_mutex);
828 if (clk->parent)
829 list_add(&clk->sibling, &clk->parent->children);
830 else
831 list_add(&clk->sibling, &root_clks);
832
833 list_add(&clk->node, &clocks);
834 if (clk->init)
835 clk->init(clk);
836 mutex_unlock(&clocks_mutex);
837
838 return 0;
839}
840EXPORT_SYMBOL(clk_register);
841
842void clk_unregister(struct clk *clk)
843{
844 if (clk == NULL || IS_ERR(clk))
845 return;
846
847 mutex_lock(&clocks_mutex);
848 list_del(&clk->sibling);
849 list_del(&clk->node);
850 mutex_unlock(&clocks_mutex);
851}
852EXPORT_SYMBOL(clk_unregister);
853
854void clk_enable_init_clocks(void)
855{
856 struct clk *clkp;
857
858 list_for_each_entry(clkp, &clocks, node)
859 if (clkp->flags & ENABLE_ON_INIT)
860 clk_enable(clkp);
861}
862
863/**
864 * omap_clk_get_by_name - locate OMAP struct clk by its name
865 * @name: name of the struct clk to locate
866 *
867 * Locate an OMAP struct clk by its name. Assumes that struct clk
868 * names are unique. Returns NULL if not found or a pointer to the
869 * struct clk if found.
870 */
871struct clk *omap_clk_get_by_name(const char *name)
872{
873 struct clk *c;
874 struct clk *ret = NULL;
875
876 mutex_lock(&clocks_mutex);
877
878 list_for_each_entry(c, &clocks, node) {
879 if (!strcmp(c->name, name)) {
880 ret = c;
881 break;
882 }
883 }
884
885 mutex_unlock(&clocks_mutex);
886
887 return ret;
888}
889
890int omap_clk_enable_autoidle_all(void)
891{
892 struct clk *c;
893 unsigned long flags;
894
895 spin_lock_irqsave(&clockfw_lock, flags);
896
897 list_for_each_entry(c, &clocks, node)
898 if (c->ops->allow_idle)
899 c->ops->allow_idle(c);
900
901 spin_unlock_irqrestore(&clockfw_lock, flags);
902
903 return 0;
904}
905
906int omap_clk_disable_autoidle_all(void)
907{
908 struct clk *c;
909 unsigned long flags;
910
911 spin_lock_irqsave(&clockfw_lock, flags);
912
913 list_for_each_entry(c, &clocks, node)
914 if (c->ops->deny_idle)
915 c->ops->deny_idle(c);
916
917 spin_unlock_irqrestore(&clockfw_lock, flags);
918
919 return 0;
920}
921
922/*
923 * Low level helpers
924 */
925static int clkll_enable_null(struct clk *clk)
926{
927 return 0;
928}
929
930static void clkll_disable_null(struct clk *clk)
931{
932}
933
934const struct clkops clkops_null = {
935 .enable = clkll_enable_null,
936 .disable = clkll_disable_null,
937};
938
939/*
940 * Dummy clock
941 *
942 * Used for clock aliases that are needed on some OMAPs, but not others
943 */
944struct clk dummy_ck = {
945 .name = "dummy",
946 .ops = &clkops_null,
947};
948
949/*
950 *
951 */
952
953#ifdef CONFIG_OMAP_RESET_CLOCKS
954/*
955 * Disable any unused clocks left on by the bootloader
956 */
957static int __init clk_disable_unused(void)
958{
959 struct clk *ck;
960 unsigned long flags;
961
962 pr_info("clock: disabling unused clocks to save power\n");
963
964 spin_lock_irqsave(&clockfw_lock, flags);
965 list_for_each_entry(ck, &clocks, node) {
966 if (ck->ops == &clkops_null)
967 continue;
968
969 if (ck->usecount > 0 || !ck->enable_reg)
970 continue;
971
972 omap1_clk_disable_unused(ck);
973 }
974 spin_unlock_irqrestore(&clockfw_lock, flags);
975
976 return 0;
977}
978late_initcall(clk_disable_unused);
979late_initcall(omap_clk_enable_autoidle_all);
980#endif
981
982#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
983/*
984 * debugfs support to trace clock tree hierarchy and attributes
985 */
986
987#include <linux/debugfs.h>
988#include <linux/seq_file.h>
989
990static struct dentry *clk_debugfs_root;
991
992static int clk_dbg_show_summary(struct seq_file *s, void *unused)
993{
994 struct clk *c;
995 struct clk *pa;
996
997 mutex_lock(&clocks_mutex);
998 seq_printf(s, "%-30s %-30s %-10s %s\n",
999 "clock-name", "parent-name", "rate", "use-count");
1000
1001 list_for_each_entry(c, &clocks, node) {
1002 pa = c->parent;
1003 seq_printf(s, "%-30s %-30s %-10lu %d\n",
1004 c->name, pa ? pa->name : "none", c->rate,
1005 c->usecount);
1006 }
1007 mutex_unlock(&clocks_mutex);
1008
1009 return 0;
1010}
1011
1012static int clk_dbg_open(struct inode *inode, struct file *file)
1013{
1014 return single_open(file, clk_dbg_show_summary, inode->i_private);
1015}
1016
1017static const struct file_operations debug_clock_fops = {
1018 .open = clk_dbg_open,
1019 .read = seq_read,
1020 .llseek = seq_lseek,
1021 .release = single_release,
1022};
1023
1024static int clk_debugfs_register_one(struct clk *c)
1025{
1026 int err;
1027 struct dentry *d;
1028 struct clk *pa = c->parent;
1029
1030 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
1031 if (!d)
1032 return -ENOMEM;
1033 c->dent = d;
1034
1035 d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
1036 if (!d) {
1037 err = -ENOMEM;
1038 goto err_out;
1039 }
1040 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
1041 if (!d) {
1042 err = -ENOMEM;
1043 goto err_out;
1044 }
1045 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
1046 if (!d) {
1047 err = -ENOMEM;
1048 goto err_out;
1049 }
1050 return 0;
1051
1052err_out:
1053 debugfs_remove_recursive(c->dent);
1054 return err;
1055}
1056
1057static int clk_debugfs_register(struct clk *c)
1058{
1059 int err;
1060 struct clk *pa = c->parent;
1061
1062 if (pa && !pa->dent) {
1063 err = clk_debugfs_register(pa);
1064 if (err)
1065 return err;
1066 }
1067
1068 if (!c->dent) {
1069 err = clk_debugfs_register_one(c);
1070 if (err)
1071 return err;
1072 }
1073 return 0;
1074}
1075
1076static int __init clk_debugfs_init(void)
1077{
1078 struct clk *c;
1079 struct dentry *d;
1080 int err;
1081
1082 d = debugfs_create_dir("clock", NULL);
1083 if (!d)
1084 return -ENOMEM;
1085 clk_debugfs_root = d;
1086
1087 list_for_each_entry(c, &clocks, node) {
1088 err = clk_debugfs_register(c);
1089 if (err)
1090 goto err_out;
1091 }
1092
1093 d = debugfs_create_file("summary", S_IRUGO,
1094 d, NULL, &debug_clock_fops);
1095 if (!d)
1096 return -ENOMEM;
1097
1098 return 0;
1099err_out:
1100 debugfs_remove_recursive(clk_debugfs_root);
1101 return err;
1102}
1103late_initcall(clk_debugfs_init);
1104
1105#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */