1 /*
2  * clocks.c - figure out sclk/cclk/vco and such
3  *
4  * Copyright (c) 2005-2008 Analog Devices Inc.
5  *
6  * Licensed under the GPL-2 or later.
7  */
8 
9 #include <common.h>
10 #include <asm/blackfin.h>
11 
12 /* Get the voltage input multiplier */
13 static u_long cached_vco_pll_ctl, cached_vco;
get_vco(void)14 u_long get_vco(void)
15 {
16 	u_long msel;
17 
18 	u_long pll_ctl = bfin_read_PLL_CTL();
19 	if (pll_ctl == cached_vco_pll_ctl)
20 		return cached_vco;
21 	else
22 		cached_vco_pll_ctl = pll_ctl;
23 
24 	msel = (pll_ctl >> 9) & 0x3F;
25 	if (0 == msel)
26 		msel = 64;
27 
28 	cached_vco = CONFIG_CLKIN_HZ;
29 	cached_vco >>= (1 & pll_ctl);	/* DF bit */
30 	cached_vco *= msel;
31 	return cached_vco;
32 }
33 
34 /* Get the Core clock */
35 static u_long cached_cclk_pll_div, cached_cclk;
get_cclk(void)36 u_long get_cclk(void)
37 {
38 	u_long csel, ssel;
39 
40 	if (bfin_read_PLL_STAT() & 0x1)
41 		return CONFIG_CLKIN_HZ;
42 
43 	ssel = bfin_read_PLL_DIV();
44 	if (ssel == cached_cclk_pll_div)
45 		return cached_cclk;
46 	else
47 		cached_cclk_pll_div = ssel;
48 
49 	csel = ((ssel >> 4) & 0x03);
50 	ssel &= 0xf;
51 	if (ssel && ssel < (1 << csel))	/* SCLK > CCLK */
52 		cached_cclk = get_vco() / ssel;
53 	else
54 		cached_cclk = get_vco() >> csel;
55 	return cached_cclk;
56 }
57 
58 /* Get the System clock */
59 static u_long cached_sclk_pll_div, cached_sclk;
get_sclk(void)60 u_long get_sclk(void)
61 {
62 	u_long ssel;
63 
64 	if (bfin_read_PLL_STAT() & 0x1)
65 		return CONFIG_CLKIN_HZ;
66 
67 	ssel = bfin_read_PLL_DIV();
68 	if (ssel == cached_sclk_pll_div)
69 		return cached_sclk;
70 	else
71 		cached_sclk_pll_div = ssel;
72 
73 	ssel &= 0xf;
74 
75 	cached_sclk = get_vco() / ssel;
76 	return cached_sclk;
77 }
78