Blackfin arch: cache the values of vco/sclk/cclk as the overhead of doing so (~24 bytes) is worth avoiding the software mult/div routines

Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>

diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 102a9db..5a455b6 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -850,38 +850,55 @@
 
 subsys_initcall(topology_init);
 
+/* Get the voltage input multiplier */
+static u_long cached_vco_pll_ctl, cached_vco;
 static u_long get_vco(void)
 {
 	u_long msel;
-	u_long vco;
 
-	msel = (bfin_read_PLL_CTL() >> 9) & 0x3F;
+	u_long pll_ctl = bfin_read_PLL_CTL();
+	if (pll_ctl == cached_vco_pll_ctl)
+		return cached_vco;
+	else
+		cached_vco_pll_ctl = pll_ctl;
+
+	msel = (pll_ctl >> 9) & 0x3F;
 	if (0 == msel)
 		msel = 64;
 
-	vco = CONFIG_CLKIN_HZ;
-	vco >>= (1 & bfin_read_PLL_CTL());	/* DF bit */
-	vco = msel * vco;
-	return vco;
+	cached_vco = CONFIG_CLKIN_HZ;
+	cached_vco >>= (1 & pll_ctl);	/* DF bit */
+	cached_vco *= msel;
+	return cached_vco;
 }
 
 /* Get the Core clock */
+static u_long cached_cclk_pll_div, cached_cclk;
 u_long get_cclk(void)
 {
 	u_long csel, ssel;
+
 	if (bfin_read_PLL_STAT() & 0x1)
 		return CONFIG_CLKIN_HZ;
 
 	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_cclk_pll_div)
+		return cached_cclk;
+	else
+		cached_cclk_pll_div = ssel;
+
 	csel = ((ssel >> 4) & 0x03);
 	ssel &= 0xf;
 	if (ssel && ssel < (1 << csel))	/* SCLK > CCLK */
-		return get_vco() / ssel;
-	return get_vco() >> csel;
+		cached_cclk = get_vco() / ssel;
+	else
+		cached_cclk = get_vco() >> csel;
+	return cached_cclk;
 }
 EXPORT_SYMBOL(get_cclk);
 
 /* Get the System clock */
+static u_long cached_sclk_pll_div, cached_sclk;
 u_long get_sclk(void)
 {
 	u_long ssel;
@@ -889,13 +906,20 @@
 	if (bfin_read_PLL_STAT() & 0x1)
 		return CONFIG_CLKIN_HZ;
 
-	ssel = (bfin_read_PLL_DIV() & 0xf);
+	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_sclk_pll_div)
+		return cached_sclk;
+	else
+		cached_sclk_pll_div = ssel;
+
+	ssel &= 0xf;
 	if (0 == ssel) {
 		printk(KERN_WARNING "Invalid System Clock\n");
 		ssel = 1;
 	}
 
-	return get_vco() / ssel;
+	cached_sclk = get_vco() / ssel;
+	return cached_sclk;
 }
 EXPORT_SYMBOL(get_sclk);