summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorLucas Stach <dev@lynxeye.de>2012-09-25 20:21:13 +0000
committerTom Rini <trini@ti.com>2012-10-15 11:54:07 -0700
commit65530a842eeaf7ad07e0613ac6f883f2f1f1e33f (patch)
tree01e704c3bbf59d1c5f7be1ba55ae8dcf656a5128 /arch/arm/cpu
parent3f44e44f33899821c4703c3bd5f9c117bb328e8b (diff)
downloadu-boot-imx-65530a842eeaf7ad07e0613ac6f883f2f1f1e33f.zip
u-boot-imx-65530a842eeaf7ad07e0613ac6f883f2f1f1e33f.tar.gz
u-boot-imx-65530a842eeaf7ad07e0613ac6f883f2f1f1e33f.tar.bz2
tegra20: add clock_set_pllout function
Common practice on Tegra 2 boards is to use the pllp_out4 FO to generate the ULPI reference clock. For this to work we have to override the default hardware generated output divider. This function adds a clean way to do so. Signed-off-by: Lucas Stach <dev@lynxeye.de> Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/tegra20-common/clock.c38
-rw-r--r--arch/arm/cpu/tegra20-common/warmboot_avp.c2
2 files changed, 39 insertions, 1 deletions
diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c
index a670b07..12987a6 100644
--- a/arch/arm/cpu/tegra20-common/clock.c
+++ b/arch/arm/cpu/tegra20-common/clock.c
@@ -396,6 +396,16 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
NONE(CRAM2),
};
+/* number of clock outputs of a PLL */
+static const u8 pll_num_clkouts[] = {
+ 1, /* PLLC */
+ 1, /* PLLM */
+ 4, /* PLLP */
+ 1, /* PLLA */
+ 0, /* PLLU */
+ 0, /* PLLD */
+};
+
/*
* Get the oscillator frequency, from the corresponding hardware configuration
* field.
@@ -604,6 +614,34 @@ unsigned long clock_get_periph_rate(enum periph_id periph_id,
(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
}
+int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate)
+{
+ struct clk_pll *pll = get_pll(clkid);
+ int data = 0, div = 0, offset = 0;
+
+ if (!clock_id_is_pll(clkid))
+ return -1;
+
+ if (pllout + 1 > pll_num_clkouts[clkid])
+ return -1;
+
+ div = clk_get_divider(8, pll_rate[clkid], rate);
+
+ if (div < 0)
+ return -1;
+
+ /* out2 and out4 are in the high part of the register */
+ if (pllout == PLL_OUT2 || pllout == PLL_OUT4)
+ offset = 16;
+
+ data = (div << PLL_OUT_RATIO_SHIFT) |
+ PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN;
+ clrsetbits_le32(&pll->pll_out[pllout >> 1],
+ PLL_OUT_RATIO_MASK << offset, data << offset);
+
+ return 0;
+}
+
/**
* Find the best available 7.1 format divisor given a parent clock rate and
* required child clock rate. This function assumes that a second-stage
diff --git a/arch/arm/cpu/tegra20-common/warmboot_avp.c b/arch/arm/cpu/tegra20-common/warmboot_avp.c
index bc6281d..bc46606 100644
--- a/arch/arm/cpu/tegra20-common/warmboot_avp.c
+++ b/arch/arm/cpu/tegra20-common/warmboot_avp.c
@@ -214,7 +214,7 @@ void wb_start(void)
reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
PLLM_OUT1_RATIO_VAL_8;
- writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
+ writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out[0]);
reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |