diff options
-rw-r--r-- | arch/blackfin/kernel/setup.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 102a9db9855..5a455b6bb54 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -850,38 +850,55 @@ static int __init topology_init(void) | |||
850 | 850 | ||
851 | subsys_initcall(topology_init); | 851 | subsys_initcall(topology_init); |
852 | 852 | ||
853 | /* Get the voltage input multiplier */ | ||
854 | static u_long cached_vco_pll_ctl, cached_vco; | ||
853 | static u_long get_vco(void) | 855 | static u_long get_vco(void) |
854 | { | 856 | { |
855 | u_long msel; | 857 | u_long msel; |
856 | u_long vco; | ||
857 | 858 | ||
858 | msel = (bfin_read_PLL_CTL() >> 9) & 0x3F; | 859 | u_long pll_ctl = bfin_read_PLL_CTL(); |
860 | if (pll_ctl == cached_vco_pll_ctl) | ||
861 | return cached_vco; | ||
862 | else | ||
863 | cached_vco_pll_ctl = pll_ctl; | ||
864 | |||
865 | msel = (pll_ctl >> 9) & 0x3F; | ||
859 | if (0 == msel) | 866 | if (0 == msel) |
860 | msel = 64; | 867 | msel = 64; |
861 | 868 | ||
862 | vco = CONFIG_CLKIN_HZ; | 869 | cached_vco = CONFIG_CLKIN_HZ; |
863 | vco >>= (1 & bfin_read_PLL_CTL()); /* DF bit */ | 870 | cached_vco >>= (1 & pll_ctl); /* DF bit */ |
864 | vco = msel * vco; | 871 | cached_vco *= msel; |
865 | return vco; | 872 | return cached_vco; |
866 | } | 873 | } |
867 | 874 | ||
868 | /* Get the Core clock */ | 875 | /* Get the Core clock */ |
876 | static u_long cached_cclk_pll_div, cached_cclk; | ||
869 | u_long get_cclk(void) | 877 | u_long get_cclk(void) |
870 | { | 878 | { |
871 | u_long csel, ssel; | 879 | u_long csel, ssel; |
880 | |||
872 | if (bfin_read_PLL_STAT() & 0x1) | 881 | if (bfin_read_PLL_STAT() & 0x1) |
873 | return CONFIG_CLKIN_HZ; | 882 | return CONFIG_CLKIN_HZ; |
874 | 883 | ||
875 | ssel = bfin_read_PLL_DIV(); | 884 | ssel = bfin_read_PLL_DIV(); |
885 | if (ssel == cached_cclk_pll_div) | ||
886 | return cached_cclk; | ||
887 | else | ||
888 | cached_cclk_pll_div = ssel; | ||
889 | |||
876 | csel = ((ssel >> 4) & 0x03); | 890 | csel = ((ssel >> 4) & 0x03); |
877 | ssel &= 0xf; | 891 | ssel &= 0xf; |
878 | if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ | 892 | if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ |
879 | return get_vco() / ssel; | 893 | cached_cclk = get_vco() / ssel; |
880 | return get_vco() >> csel; | 894 | else |
895 | cached_cclk = get_vco() >> csel; | ||
896 | return cached_cclk; | ||
881 | } | 897 | } |
882 | EXPORT_SYMBOL(get_cclk); | 898 | EXPORT_SYMBOL(get_cclk); |
883 | 899 | ||
884 | /* Get the System clock */ | 900 | /* Get the System clock */ |
901 | static u_long cached_sclk_pll_div, cached_sclk; | ||
885 | u_long get_sclk(void) | 902 | u_long get_sclk(void) |
886 | { | 903 | { |
887 | u_long ssel; | 904 | u_long ssel; |
@@ -889,13 +906,20 @@ u_long get_sclk(void) | |||
889 | if (bfin_read_PLL_STAT() & 0x1) | 906 | if (bfin_read_PLL_STAT() & 0x1) |
890 | return CONFIG_CLKIN_HZ; | 907 | return CONFIG_CLKIN_HZ; |
891 | 908 | ||
892 | ssel = (bfin_read_PLL_DIV() & 0xf); | 909 | ssel = bfin_read_PLL_DIV(); |
910 | if (ssel == cached_sclk_pll_div) | ||
911 | return cached_sclk; | ||
912 | else | ||
913 | cached_sclk_pll_div = ssel; | ||
914 | |||
915 | ssel &= 0xf; | ||
893 | if (0 == ssel) { | 916 | if (0 == ssel) { |
894 | printk(KERN_WARNING "Invalid System Clock\n"); | 917 | printk(KERN_WARNING "Invalid System Clock\n"); |
895 | ssel = 1; | 918 | ssel = 1; |
896 | } | 919 | } |
897 | 920 | ||
898 | return get_vco() / ssel; | 921 | cached_sclk = get_vco() / ssel; |
922 | return cached_sclk; | ||
899 | } | 923 | } |
900 | EXPORT_SYMBOL(get_sclk); | 924 | EXPORT_SYMBOL(get_sclk); |
901 | 925 | ||