aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/setup.c')
-rw-r--r--arch/blackfin/kernel/setup.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 102a9db98559..5a455b6bb542 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
851subsys_initcall(topology_init); 851subsys_initcall(topology_init);
852 852
853/* Get the voltage input multiplier */
854static u_long cached_vco_pll_ctl, cached_vco;
853static u_long get_vco(void) 855static 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 */
876static u_long cached_cclk_pll_div, cached_cclk;
869u_long get_cclk(void) 877u_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}
882EXPORT_SYMBOL(get_cclk); 898EXPORT_SYMBOL(get_cclk);
883 899
884/* Get the System clock */ 900/* Get the System clock */
901static u_long cached_sclk_pll_div, cached_sclk;
885u_long get_sclk(void) 902u_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}
900EXPORT_SYMBOL(get_sclk); 924EXPORT_SYMBOL(get_sclk);
901 925