summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorJimmy Zhang <jimmzhang@nvidia.com>2011-06-08 17:59:50 -0700
committerSimon Glass <sjg@chromium.org>2011-08-29 10:39:23 -0700
commitd163e35c341f08091813cae034eb7daf4a583ee2 (patch)
tree175c94de78ffd4a771ad9e228af7c04576fcbb2d /arch/arm
parenta299c32c4b3f4fc7352c9c80a9a5dc7e4e6e5941 (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.c71
-rw-r--r--arch/arm/include/asm/arch-tegra2/tegra2.h1
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 */