diff options
author | Jimmy Zhang <jimmzhang@nvidia.com> | 2011-06-08 17:59:50 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-29 10:39:23 -0700 |
commit | d163e35c341f08091813cae034eb7daf4a583ee2 (patch) | |
tree | 175c94de78ffd4a771ad9e228af7c04576fcbb2d /arch/arm | |
parent | a299c32c4b3f4fc7352c9c80a9a5dc7e4e6e5941 (diff) |
Init Pllx based on sku id and OSC freq
This fix sets up cpu clock appropriately according to its sku id and the
external oscillator frequency. Previously, the cpu clock is set to 1.0GHz
with assumed oscillator frequency of 12MHz. On a 26MHz based Kaen board,
current code will cause cpu over clocked. With this fix, the cpu clock
will be set to 1.0GHz and 1.2GHz respectively for t20 and t25 with all
different oscillator frequencies.
BUG=none
TEST=unit test done on t20 and t25. cpu clocks were set as expected.
Change-Id: Ic886854d31602442763a835c46918505fd8d6705
Reviewed-on: http://gerrit.chromium.org/gerrit/2361
Tested-by: Jimmy Zhang <jimmzhang@nvidia.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/cpu/armv7/tegra2/ap20.c | 71 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-tegra2/tegra2.h | 1 |
2 files changed, 62 insertions, 10 deletions
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c index 74cd583d146..4fec9f8dd11 100644 --- a/arch/arm/cpu/armv7/tegra2/ap20.c +++ b/arch/arm/cpu/armv7/tegra2/ap20.c @@ -31,6 +31,34 @@ #include <asm/arch/pinmux.h> #include <asm/arch/scu.h> #include <common.h> +#include "../../../../../board/nvidia/common/board.h" + +struct clk_pll_table { + u16 n; + u16 m; + u8 p; + u8 cpcon; +}; + +/* + * Timing tables for each SOC for all four oscillator options. + */ +static struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_COUNT] + [CLOCK_OSC_FREQ_COUNT] = { + /* T20: 1 GHz */ + {{ 1000, 13, 0, 12}, /* OSC 13M */ + { 625, 12, 0, 8}, /* OSC 19.2M */ + { 1000, 12, 0, 12}, /* OSC 12M */ + { 1000, 26, 0, 12}, /* OSC 26M */ + }, + + /* T25: 1.2 GHz */ + {{ 923, 10, 0, 12}, + { 750, 12, 0, 8}, + { 600, 6, 0, 12}, + { 600, 13, 0, 12}, + }, +}; /* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */ static int ap20_cpu_is_cortexa9(void) @@ -39,7 +67,7 @@ static int ap20_cpu_is_cortexa9(void) return id == (PG_UP_TAG_0_PID_CPU & 0xff); } -void init_pllx(void) +static int pllx_set_rate(u32 divn, u32 divm, u32 divp, u32 cpcon) { struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU]; @@ -47,22 +75,45 @@ void init_pllx(void) /* If PLLX is already enabled, just return */ if (bf_readl(PLL_ENABLE, &pll->pll_base)) - return; + return 0; - /* Set PLLX_MISC */ - reg = bf_pack(PLL_CPCON, 1); - writel(reg, &pll->pll_misc); - - /* Use 12MHz clock here */ - reg = bf_pack(PLL_BYPASS, 1) | bf_pack(PLL_DIVM, 12); - reg |= bf_pack(PLL_DIVN, 1000); + /* Set BYPASS, m, n and p to PLLX_BASE */ + reg = bf_pack(PLL_BYPASS, 1) | bf_pack(PLL_DIVM, divm); + reg |= bf_pack(PLL_DIVN, divn) | bf_pack(PLL_DIVP, divp); writel(reg, &pll->pll_base); + /* Set cpcon to PLLX_MISC */ + reg = bf_pack(PLL_CPCON, cpcon); + writel(reg, &pll->pll_misc); + + /* Enable PLLX */ + reg = readl(&pll->pll_base); reg |= bf_pack(PLL_ENABLE, 1); - writel(reg, &pll->pll_base); + /* Disable BYPASS */ reg &= ~bf_mask(PLL_BYPASS); writel(reg, &pll->pll_base); + + return 0; +} + +static void init_pllx(void) +{ + int chip_type; + enum clock_osc_freq osc; + struct clk_pll_table *sel; + + /* get chip type. If unknown, assign to T20 */ + chip_type = tegra_get_chip_type(); + if (chip_type == TEGRA_SOC_UNKNOWN) + chip_type = TEGRA_SOC_T20; + + /* get osc freq */ + osc = clock_get_osc_freq(); + + /* set pllx */ + sel = &tegra_pll_x_table[chip_type][osc]; + pllx_set_rate(sel->n, sel->m, sel->p, sel->cpcon); } static void enable_cpu_clock(int enable) diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h index 77ecb99c948..dfefa3ce49a 100644 --- a/arch/arm/include/asm/arch-tegra2/tegra2.h +++ b/arch/arm/include/asm/arch-tegra2/tegra2.h @@ -76,5 +76,6 @@ struct timerus { #define TEGRA_SOC_UNKNOWN (-1) #define TEGRA_SOC_T20 (0) #define TEGRA_SOC_T25 (1) +#define TEGRA_SOC_COUNT (2) #endif /* TEGRA2_H */ |