exynos5420: add a peripheral clock select --> PLL decoder

This adds a helper function to translate between peripheral clock
select fields in clock source registers and PLLs. Some of this was
already done to handle a few special cases, this generalizes the
earlier work so that follow-up patches can do further clean-up.

Unfortunately, the PLLs represented by clock select fields in
various modules are not uniformly ordered. So for now we focus on
peripheral clock sources only.

Signed-off-by: David Hendricks <dhendrix@chromium.org>

Change-Id: Id58a3e488650d09e6a35c22d5394fcbf0ee9ddff
Reviewed-on: https://gerrit.chromium.org/gerrit/65283
Commit-Queue: David Hendricks <dhendrix@chromium.org>
Tested-by: David Hendricks <dhendrix@chromium.org>
Reviewed-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/4462
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
David Hendricks
2013-08-08 19:03:03 -07:00
committed by Patrick Georgi
parent 5f6ffbab1b
commit efd4b9e936
2 changed files with 52 additions and 19 deletions

View File

@ -25,6 +25,7 @@
enum periph_id; enum periph_id;
/* This master list of PLLs is ordered arbitrarily. */
#define APLL 0 #define APLL 0
#define MPLL 1 #define MPLL 1
#define EPLL 2 #define EPLL 2
@ -35,16 +36,7 @@ enum periph_id;
#define SPLL 7 #define SPLL 7
#define CPLL 8 #define CPLL 8
#define DPLL 9 #define DPLL 9
#define IPLL 10
enum pll_src_bit {
EXYNOS_SRC_CPLL = 1,
EXYNOS_SRC_DPLL = 2,
EXYNOS_SRC_MPLL = 3,
EXYNOS_SRC_SPLL = 4,
EXYNOS_SRC_IPLL = 5,
EXYNOS_SRC_EPLL = 6,
EXYNOS_SRC_RPLL = 7,
};
/* * /* *
* This structure is to store the src bit, div bit and prediv bit * This structure is to store the src bit, div bit and prediv bit

View File

@ -151,6 +151,50 @@ unsigned long get_pll_clk(int pllreg)
return fout; return fout;
} }
enum peripheral_clock_select {
PERIPH_SRC_CPLL = 1,
PERIPH_SRC_DPLL = 2,
PERIPH_SRC_MPLL = 3,
PERIPH_SRC_SPLL = 4,
PERIPH_SRC_IPLL = 5,
PERIPH_SRC_EPLL = 6,
PERIPH_SRC_RPLL = 7,
};
static int clock_select_to_pll(enum peripheral_clock_select sel)
{
int pll;
switch (sel) {
case PERIPH_SRC_CPLL:
pll = CPLL;
break;
case PERIPH_SRC_DPLL:
pll = DPLL;
break;
case PERIPH_SRC_MPLL:
pll = MPLL;
break;
case PERIPH_SRC_SPLL:
pll = SPLL;
break;
case PERIPH_SRC_IPLL:
pll = IPLL;
break;
case PERIPH_SRC_EPLL:
pll = EPLL;
break;
case PERIPH_SRC_RPLL:
pll = RPLL;
break;
default:
pll = -1;
break;
}
return pll;
}
unsigned long clock_get_periph_rate(enum periph_id peripheral) unsigned long clock_get_periph_rate(enum periph_id peripheral)
{ {
struct clk_bit_info *bit_info = &clk_bit_info[peripheral]; struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
@ -206,17 +250,14 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral)
src = (src >> bit_info->src_bit) & 0xf; src = (src >> bit_info->src_bit) & 0xf;
switch (src) { src = clock_select_to_pll(src);
case EXYNOS_SRC_MPLL: if (src < 0) {
sclk = get_pll_clk(MPLL); printk(BIOS_DEBUG, "%s: cannot determine source PLL", __func__);
break; return -1;
case EXYNOS_SRC_EPLL:
sclk = get_pll_clk(EPLL);
break;
default:
return 0;
} }
sclk = get_pll_clk(src);
/* Ratio clock division for this peripheral */ /* Ratio clock division for this peripheral */
sub_div = (div >> bit_info->div_bit) & 0xf; sub_div = (div >> bit_info->div_bit) & 0xf;
sub_clk = sclk / (sub_div + 1); sub_clk = sclk / (sub_div + 1);