tegra124: Allow setting PLLM (clock for SDRAM).

The new clock_sdram(...) initialized PLLM by given configuration (which needs to
be explicitly determined, usually from BCT or SDRAM parameters).

BUG=none
TEST=emerge-nyan chromeos-coreoot-nyan
     # With other patches, the new function starts PLLM in correct clock.

Change-Id: I606d0506c734d312db9e1b72a910700ca766f2d3
Reviewed-on: https://chromium-review.googlesource.com/183621
Tested-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Commit-Queue: Hung-Te Lin <hungte@chromium.org>
This commit is contained in:
Hung-Te Lin 2014-01-23 18:28:09 +08:00 committed by chrome-internal-fetch
commit a534e5b7c6
3 changed files with 73 additions and 1 deletions

View file

@ -352,10 +352,20 @@ check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644);
#define PLL_BASE_DIVM_MASK (0x1f << PLL_BASE_DIVM_SHIFT)
/* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */
#define PLLCMX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT)
#define PLLCX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT)
#define PLLM_BASE_DIVP_MASK (0x1U << PLL_BASE_DIVP_SHIFT)
#define PLLCMX_BASE_DIVN_MASK (0xffU << PLL_BASE_DIVN_SHIFT)
#define PLLCMX_BASE_DIVM_MASK (0xffU << PLL_BASE_DIVM_SHIFT)
/* PLLM specific registers */
#define PLLM_MISC1_SETUP_SHIFT 0
#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT 28
#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT 29
#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT 30
#define PLLM_MISC2_KCP_SHIFT 1
#define PLLM_MISC2_KVCO_SHIFT 0
#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0)
/* Generic, indiscriminate divisor mask. May catch some innocent bystander bits
* on the side that we don't particularly care about. */
#define PLL_BASE_DIV_MASK (0xffffff)
@ -414,6 +424,8 @@ check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644);
#define CLK_SOURCE_SHIFT 29
#define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT)
#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16)
#define CLK_UART_DIV_OVERRIDE (1 << 24)
/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */

View file

@ -327,6 +327,63 @@ void clock_external_output(int clk_id)
}
}
/* Start PLLM for SDRAM. */
void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source,
u32 same_freq)
{
u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) |
(ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) |
(ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) |
(ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)),
misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) |
(kcp << PLLM_MISC2_KCP_SHIFT)),
base;
if (same_freq)
emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
else
emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
/*
* Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and
* PLLM_BASE.ENABLE must be in DISABLE state (both are the default
* values after coldboot reset).
*/
writel(misc1, &clk_rst->pllm_misc1);
writel(misc2, &clk_rst->pllm_misc2);
/* PLLM.BASE needs BYPASS=0, different from general init_pll */
base = readl(&clk_rst->pllm_base);
base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK |
PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS);
base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) |
(p << PLL_BASE_DIVP_SHIFT));
writel(base, &clk_rst->pllm_base);
setbits_le32(&clk_rst->pllm_base, PLL_BASE_ENABLE);
/* stable_time is required, before we can start to check lock. */
udelay(stable_time);
while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) {
udelay(1);
}
/*
* After PLLM reports being locked, we have to delay 10us before
* enabling PLLM_OUT.
*/
udelay(10);
/* Put OUT1 out of reset state (start to output). */
setbits_le32(&clk_rst->pllm_out, PLLM_OUT1_RSTN_RESET_DISABLE);
/* Enable and start MEM(MC) and EMC. */
clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0);
writel(emc_source, &clk_rst->clk_src_emc);
udelay(IO_STABILIZATION_DELAY);
}
void clock_cpu0_config_and_reset(void *entry)
{
void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100;

View file

@ -247,6 +247,9 @@ enum clock_source { /* Careful: Not true for all sources, always check TRM! */
int clock_get_osc_khz(void);
void clock_early_uart(void);
void clock_external_output(int clk_id);
void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source,
u32 same_freq);
void clock_cpu0_config_and_reset(void * entry);
void clock_halt_avp(void);
void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x);