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:
parent
89cbd15c95
commit
a534e5b7c6
3 changed files with 73 additions and 1 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue