diff options
author | Mike Frysinger <vapier@gentoo.org> | 2008-10-24 22:48:47 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-02-02 12:24:42 -0500 |
commit | 40599239e7875b39e2a5c12e6545992041c72c52 (patch) | |
tree | 1cb9d7601f914acbf80c467ec7710abc61756258 | |
parent | 6957a6209b02f6b69607fc47425f13731cc477f1 (diff) |
Blackfin: cache core/system clock values
Calculating the clocks requires a bit of calls to gcc math functions, so
cache the values after the first run since they'll most likely never
change once U-Boot is up and running.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | include/asm-blackfin/blackfin_local.h | 2 | ||||
-rw-r--r-- | lib_blackfin/Makefile | 1 | ||||
-rw-r--r-- | lib_blackfin/board.c | 44 | ||||
-rw-r--r-- | lib_blackfin/clocks.c | 77 |
4 files changed, 80 insertions, 44 deletions
diff --git a/include/asm-blackfin/blackfin_local.h b/include/asm-blackfin/blackfin_local.h index c9ee91a439..90259ba7d4 100644 --- a/include/asm-blackfin/blackfin_local.h +++ b/include/asm-blackfin/blackfin_local.h @@ -52,6 +52,8 @@ # include <linux/types.h> +extern u_long get_vco(void); +extern u_long get_cclk(void); extern u_long get_sclk(void); # define bfin_revid() (*pCHIPID >> 28) diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index 93f7d4f102..46ef7f3316 100644 --- a/lib_blackfin/Makefile +++ b/lib_blackfin/Makefile @@ -39,6 +39,7 @@ SOBJS-y += memset.o COBJS-y += board.o COBJS-y += boot.o COBJS-y += cache.o +COBJS-y += clocks.o COBJS-y += muldi3.o COBJS-$(CONFIG_POST) += post.o tests.o COBJS-y += string.o diff --git a/lib_blackfin/board.c b/lib_blackfin/board.c index 01b71d4481..4aa859593e 100644 --- a/lib_blackfin/board.c +++ b/lib_blackfin/board.c @@ -44,50 +44,6 @@ static inline void serial_early_puts(const char *s) #endif } -/* Get the input voltage */ -static u_long get_vco(void) -{ - u_long msel; - u_long vco; - - msel = (*pPLL_CTL >> 9) & 0x3F; - if (0 == msel) - msel = 64; - - vco = CONFIG_CLKIN_HZ; - vco >>= (1 & *pPLL_CTL); /* DF bit */ - vco = msel * vco; - return vco; -} - -/* Get the Core clock */ -u_long get_cclk(void) -{ - u_long csel, ssel; - if (*pPLL_STAT & 0x1) - return CONFIG_CLKIN_HZ; - - ssel = *pPLL_DIV; - csel = ((ssel >> 4) & 0x03); - ssel &= 0xf; - if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ - return get_vco() / ssel; - return get_vco() >> csel; -} - -/* Get the System clock */ -u_long get_sclk(void) -{ - u_long ssel; - - if (*pPLL_STAT & 0x1) - return CONFIG_CLKIN_HZ; - - ssel = (*pPLL_DIV & 0xf); - - return get_vco() / ssel; -} - static void *mem_malloc_start, *mem_malloc_end, *mem_malloc_brk; static void mem_malloc_init(void) diff --git a/lib_blackfin/clocks.c b/lib_blackfin/clocks.c new file mode 100644 index 0000000000..0be395bb30 --- /dev/null +++ b/lib_blackfin/clocks.c @@ -0,0 +1,77 @@ +/* + * clocks.c - figure out sclk/cclk/vco and such + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <asm/blackfin.h> + +/* Get the voltage input multiplier */ +static u_long cached_vco_pll_ctl, cached_vco; +u_long get_vco(void) +{ + u_long msel; + + 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; + + 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 */ + cached_cclk = get_vco() / ssel; + else + cached_cclk = get_vco() >> csel; + return cached_cclk; +} + +/* Get the System clock */ +static u_long cached_sclk_pll_div, cached_sclk; +u_long get_sclk(void) +{ + u_long ssel; + + if (bfin_read_PLL_STAT() & 0x1) + return CONFIG_CLKIN_HZ; + + ssel = bfin_read_PLL_DIV(); + if (ssel == cached_sclk_pll_div) + return cached_sclk; + else + cached_sclk_pll_div = ssel; + + ssel &= 0xf; + + cached_sclk = get_vco() / ssel; + return cached_sclk; +} |