diff options
Diffstat (limited to 'arch/arm/mach-ux500/clock.c')
-rw-r--r-- | arch/arm/mach-ux500/clock.c | 79 |
1 files changed, 55 insertions, 24 deletions
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 32ce90840ee..e832664d1bd 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/clkdev.h> | 16 | #include <linux/clkdev.h> |
17 | #include <linux/cpufreq.h> | ||
17 | 18 | ||
18 | #include <plat/mtu.h> | 19 | #include <plat/mtu.h> |
19 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
@@ -635,16 +636,13 @@ static const struct file_operations set_rate_fops = { | |||
635 | static struct dentry *clk_debugfs_register_dir(struct clk *c, | 636 | static struct dentry *clk_debugfs_register_dir(struct clk *c, |
636 | struct dentry *p_dentry) | 637 | struct dentry *p_dentry) |
637 | { | 638 | { |
638 | struct dentry *d, *clk_d, *child, *child_tmp; | 639 | struct dentry *d, *clk_d; |
639 | char s[255]; | 640 | const char *p = c->name; |
640 | char *p = s; | ||
641 | 641 | ||
642 | if (c->name == NULL) | 642 | if (!p) |
643 | p += sprintf(p, "BUG"); | 643 | p = "BUG"; |
644 | else | ||
645 | p += sprintf(p, "%s", c->name); | ||
646 | 644 | ||
647 | clk_d = debugfs_create_dir(s, p_dentry); | 645 | clk_d = debugfs_create_dir(p, p_dentry); |
648 | if (!clk_d) | 646 | if (!clk_d) |
649 | return NULL; | 647 | return NULL; |
650 | 648 | ||
@@ -666,24 +664,10 @@ static struct dentry *clk_debugfs_register_dir(struct clk *c, | |||
666 | return clk_d; | 664 | return clk_d; |
667 | 665 | ||
668 | err_out: | 666 | err_out: |
669 | d = clk_d; | 667 | debugfs_remove_recursive(clk_d); |
670 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
671 | debugfs_remove(child); | ||
672 | debugfs_remove(clk_d); | ||
673 | return NULL; | 668 | return NULL; |
674 | } | 669 | } |
675 | 670 | ||
676 | static void clk_debugfs_remove_dir(struct dentry *cdentry) | ||
677 | { | ||
678 | struct dentry *d, *child, *child_tmp; | ||
679 | |||
680 | d = cdentry; | ||
681 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
682 | debugfs_remove(child); | ||
683 | debugfs_remove(cdentry); | ||
684 | return ; | ||
685 | } | ||
686 | |||
687 | static int clk_debugfs_register_one(struct clk *c) | 671 | static int clk_debugfs_register_one(struct clk *c) |
688 | { | 672 | { |
689 | struct clk *pa = c->parent_periph; | 673 | struct clk *pa = c->parent_periph; |
@@ -700,7 +684,7 @@ static int clk_debugfs_register_one(struct clk *c) | |||
700 | c->dent_bus = clk_debugfs_register_dir(c, | 684 | c->dent_bus = clk_debugfs_register_dir(c, |
701 | bpa->dent_bus ? bpa->dent_bus : bpa->dent); | 685 | bpa->dent_bus ? bpa->dent_bus : bpa->dent); |
702 | if ((!c->dent_bus) && (c->dent)) { | 686 | if ((!c->dent_bus) && (c->dent)) { |
703 | clk_debugfs_remove_dir(c->dent); | 687 | debugfs_remove_recursive(c->dent); |
704 | c->dent = NULL; | 688 | c->dent = NULL; |
705 | return -ENOMEM; | 689 | return -ENOMEM; |
706 | } | 690 | } |
@@ -759,6 +743,51 @@ err_out: | |||
759 | late_initcall(clk_debugfs_init); | 743 | late_initcall(clk_debugfs_init); |
760 | #endif /* defined(CONFIG_DEBUG_FS) */ | 744 | #endif /* defined(CONFIG_DEBUG_FS) */ |
761 | 745 | ||
746 | unsigned long clk_smp_twd_rate = 400000000; | ||
747 | |||
748 | unsigned long clk_smp_twd_get_rate(struct clk *clk) | ||
749 | { | ||
750 | return clk_smp_twd_rate; | ||
751 | } | ||
752 | |||
753 | static struct clk clk_smp_twd = { | ||
754 | .get_rate = clk_smp_twd_get_rate, | ||
755 | .name = "smp_twd", | ||
756 | }; | ||
757 | |||
758 | static struct clk_lookup clk_smp_twd_lookup = { | ||
759 | .dev_id = "smp_twd", | ||
760 | .clk = &clk_smp_twd, | ||
761 | }; | ||
762 | |||
763 | #ifdef CONFIG_CPU_FREQ | ||
764 | |||
765 | static int clk_twd_cpufreq_transition(struct notifier_block *nb, | ||
766 | unsigned long state, void *data) | ||
767 | { | ||
768 | struct cpufreq_freqs *f = data; | ||
769 | |||
770 | if (state == CPUFREQ_PRECHANGE) { | ||
771 | /* Save frequency in simple Hz */ | ||
772 | clk_smp_twd_rate = f->new * 1000; | ||
773 | } | ||
774 | |||
775 | return NOTIFY_OK; | ||
776 | } | ||
777 | |||
778 | static struct notifier_block clk_twd_cpufreq_nb = { | ||
779 | .notifier_call = clk_twd_cpufreq_transition, | ||
780 | }; | ||
781 | |||
782 | static int clk_init_smp_twd_cpufreq(void) | ||
783 | { | ||
784 | return cpufreq_register_notifier(&clk_twd_cpufreq_nb, | ||
785 | CPUFREQ_TRANSITION_NOTIFIER); | ||
786 | } | ||
787 | late_initcall(clk_init_smp_twd_cpufreq); | ||
788 | |||
789 | #endif | ||
790 | |||
762 | int __init clk_init(void) | 791 | int __init clk_init(void) |
763 | { | 792 | { |
764 | if (cpu_is_u8500ed()) { | 793 | if (cpu_is_u8500ed()) { |
@@ -779,6 +808,8 @@ int __init clk_init(void) | |||
779 | else | 808 | else |
780 | clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); | 809 | clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); |
781 | 810 | ||
811 | clkdev_add(&clk_smp_twd_lookup); | ||
812 | |||
782 | #ifdef CONFIG_DEBUG_FS | 813 | #ifdef CONFIG_DEBUG_FS |
783 | clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); | 814 | clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); |
784 | if (cpu_is_u8500ed()) | 815 | if (cpu_is_u8500ed()) |