diff options
Diffstat (limited to 'arch/arm/cpu/armv7/sunxi/dram_sun6i.c')
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/dram_sun6i.c | 77 |
1 files changed, 28 insertions, 49 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c index 699173cf69..5dbbf6186f 100644 --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c @@ -17,9 +17,7 @@ #include <asm/arch/dram.h> #include <asm/arch/prcm.h> -/* DRAM clk & zq defaults, maybe turn these into Kconfig options ? */ -#define DRAM_CLK_DEFAULT 312000000 -#define DRAM_ZQ_DEFAULT 0x78 +#define DRAM_CLK (CONFIG_DRAM_CLK * 1000000) struct dram_sun6i_para { u8 bus_width; @@ -29,31 +27,18 @@ struct dram_sun6i_para { u16 page_size; }; -/* - * Wait up to 1s for value to be set in given part of reg. - */ -static void await_completion(u32 *reg, u32 mask, u32 val) -{ - unsigned long tmo = timer_get_us() + 1000000; - - while ((readl(reg) & mask) != val) { - if (timer_get_us() > tmo) - panic("Timeout initialising DRAM\n"); - } -} - static void mctl_sys_init(void) { struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; const int dram_clk_div = 2; - clock_set_pll5(DRAM_CLK_DEFAULT * dram_clk_div); + clock_set_pll5(DRAM_CLK * dram_clk_div, false); clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK, CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST | CCM_DRAMCLK_CFG_UPD); - await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); + mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); writel(MDFS_CLK_DEFAULT, &ccm->mdfs_clk_cfg); @@ -109,8 +94,8 @@ static bool mctl_rank_detect(u32 *gsr0, int rank) const u32 done = MCTL_DX_GSR0_RANK0_TRAIN_DONE << rank; const u32 err = MCTL_DX_GSR0_RANK0_TRAIN_ERR << rank; - await_completion(gsr0, done, done); - await_completion(gsr0 + 0x10, done, done); + mctl_await_completion(gsr0, done, done); + mctl_await_completion(gsr0 + 0x10, done, done); return !(readl(gsr0) & err) && !(readl(gsr0 + 0x10) & err); } @@ -131,7 +116,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para) } writel(MCTL_MCMD_NOP, &mctl_ctl->mcmd); - await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0); + mctl_await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0); /* PHY initialization */ writel(MCTL_PGCR, &mctl_phy->pgcr); @@ -168,14 +153,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para) writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx2gcr); writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx3gcr); - await_completion(&mctl_phy->pgsr, 0x03, 0x03); + mctl_await_completion(&mctl_phy->pgsr, 0x03, 0x03); - writel(DRAM_ZQ_DEFAULT, &mctl_phy->zq0cr1); + writel(CONFIG_DRAM_ZQ, &mctl_phy->zq0cr1); setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS); writel(MCTL_PIR_STEP1, &mctl_phy->pir); udelay(10); - await_completion(&mctl_phy->pgsr, 0x1f, 0x1f); + mctl_await_completion(&mctl_phy->pgsr, 0x1f, 0x1f); /* rank detect */ if (!mctl_rank_detect(&mctl_phy->dx0gsr0, 1)) { @@ -206,19 +191,19 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para) setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS); writel(MCTL_PIR_STEP2, &mctl_phy->pir); udelay(10); - await_completion(&mctl_phy->pgsr, 0x11, 0x11); + mctl_await_completion(&mctl_phy->pgsr, 0x11, 0x11); if (readl(&mctl_phy->pgsr) & MCTL_PGSR_TRAIN_ERR_MASK) panic("Training error initialising DRAM\n"); /* Move to configure state */ writel(MCTL_SCTL_CONFIG, &mctl_ctl->sctl); - await_completion(&mctl_ctl->sstat, 0x07, 0x01); + mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x01); /* Set number of clks per micro-second */ - writel(DRAM_CLK_DEFAULT / 1000000, &mctl_ctl->togcnt1u); + writel(DRAM_CLK / 1000000, &mctl_ctl->togcnt1u); /* Set number of clks per 100 nano-seconds */ - writel(DRAM_CLK_DEFAULT / 10000000, &mctl_ctl->togcnt100n); + writel(DRAM_CLK / 10000000, &mctl_ctl->togcnt100n); /* Set memory timing registers */ writel(MCTL_TREFI, &mctl_ctl->trefi); writel(MCTL_TMRD, &mctl_ctl->tmrd); @@ -272,7 +257,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para) /* Move to access state */ writel(MCTL_SCTL_ACCESS, &mctl_ctl->sctl); - await_completion(&mctl_ctl->sstat, 0x07, 0x03); + mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x03); } static void mctl_com_init(struct dram_sun6i_para *para) @@ -341,20 +326,6 @@ static void mctl_port_cfg(void) writel(0x00000307, &mctl_com->mbagcr[5]); } -static bool mctl_mem_matches(u32 offset) -{ - const int match_count = 64; - int i, matches = 0; - - for (i = 0; i < match_count; i++) { - if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) == - readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4)) - matches++; - } - - return matches == match_count; -} - unsigned long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = @@ -371,18 +342,26 @@ unsigned long sunxi_dram_init(void) .rows = 16, }; + /* A31s only has one channel */ + if (sunxi_get_ss_bonding_id() == SUNXI_SS_BOND_ID_A31S) + para.chan = 1; + mctl_sys_init(); mctl_dll_init(0, ¶); - mctl_dll_init(1, ¶); + setbits_le32(&mctl_com->ccr, MCTL_CCR_CH0_CLK_EN); + + if (para.chan == 2) { + mctl_dll_init(1, ¶); + setbits_le32(&mctl_com->ccr, MCTL_CCR_CH1_CLK_EN); + } - setbits_le32(&mctl_com->ccr, - MCTL_CCR_MASTER_CLK_EN | - MCTL_CCR_CH0_CLK_EN | - MCTL_CCR_CH1_CLK_EN); + setbits_le32(&mctl_com->ccr, MCTL_CCR_MASTER_CLK_EN); mctl_channel_init(0, ¶); - mctl_channel_init(1, ¶); + if (para.chan == 2) + mctl_channel_init(1, ¶); + mctl_com_init(¶); mctl_port_cfg(); |