diff options
Diffstat (limited to 'arch/arm/mach-omap2/clock.c')
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 517 |
1 files changed, 510 insertions, 7 deletions
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 | |||