diff options
Diffstat (limited to 'arch/arm/mach-sunxi/dram_sun50i_h616.c')
-rw-r--r-- | arch/arm/mach-sunxi/dram_sun50i_h616.c | 383 |
1 files changed, 237 insertions, 146 deletions
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 1f9416d..7e580b6 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -31,7 +31,7 @@ enum { MBUS_QOS_HIGHEST }; -inline void mbus_configure_port(u8 port, +static void mbus_configure_port(u8 port, bool bwlimit, bool priority, u8 qos, @@ -92,7 +92,7 @@ static void mctl_set_master_priority(void) dmb(); } -static void mctl_sys_init(struct dram_para *para) +static void mctl_sys_init(u32 clk_rate) { struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; @@ -114,7 +114,7 @@ static void mctl_sys_init(struct dram_para *para) /* Set PLL5 rate to doubled DRAM clock rate */ writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN | - CCM_PLL5_CTRL_N(para->clk * 2 / 24), &ccm->pll5_cfg); + CCM_PLL5_CTRL_N(clk_rate * 2 / 24), &ccm->pll5_cfg); mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK); /* Configure DRAM mod clock */ @@ -141,15 +141,15 @@ static void mctl_sys_init(struct dram_para *para) writel(0x8000, &mctl_ctl->clken); } -static void mctl_set_addrmap(struct dram_para *para) +static void mctl_set_addrmap(const struct dram_config *config) { struct sunxi_mctl_ctl_reg * const mctl_ctl = (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - u8 cols = para->cols; - u8 rows = para->rows; - u8 ranks = para->ranks; + u8 cols = config->cols; + u8 rows = config->rows; + u8 ranks = config->ranks; - if (!para->bus_full_width) + if (!config->bus_full_width) cols -= 1; /* Ranks */ @@ -228,13 +228,20 @@ static void mctl_set_addrmap(struct dram_para *para) } static const u8 phy_init[] = { +#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19, 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06, 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08, 0x09, 0x05, 0x18 +#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3) + 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02, + 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07, + 0x17, 0x19, 0x1a +#endif }; -static void mctl_phy_configure_odt(struct dram_para *para) +static void mctl_phy_configure_odt(const struct dram_para *para) { unsigned int val; @@ -263,25 +270,37 @@ static void mctl_phy_configure_odt(struct dram_para *para) writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x34c); val = para->dx_odt & 0x1f; - writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x380); + if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x380); + else + writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x380); writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x384); val = (para->dx_odt >> 8) & 0x1f; - writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c0); + if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x3c0); + else + writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c0); writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c4); val = (para->dx_odt >> 16) & 0x1f; - writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x400); + if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x400); + else + writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x400); writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x404); val = (para->dx_odt >> 24) & 0x1f; - writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x440); + if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x440); + else + writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x440); writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x444); dmb(); } -static bool mctl_phy_write_leveling(struct dram_para *para) +static bool mctl_phy_write_leveling(const struct dram_config *config) { bool result = true; u32 val; @@ -292,7 +311,7 @@ static bool mctl_phy_write_leveling(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4); - if (para->bus_full_width) + if (config->bus_full_width) val = 0xf; else val = 3; @@ -316,12 +335,12 @@ static bool mctl_phy_write_leveling(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0); - if (para->ranks == 2) { + if (config->ranks == 2) { clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40); setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4); - if (para->bus_full_width) + if (config->bus_full_width) val = 0xf; else val = 3; @@ -336,7 +355,7 @@ static bool mctl_phy_write_leveling(struct dram_para *para) return result; } -static bool mctl_phy_read_calibration(struct dram_para *para) +static bool mctl_phy_read_calibration(const struct dram_config *config) { bool result = true; u32 val, tmp; @@ -345,7 +364,7 @@ static bool mctl_phy_read_calibration(struct dram_para *para) setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1); - if (para->bus_full_width) + if (config->bus_full_width) val = 0xf; else val = 3; @@ -361,7 +380,7 @@ static bool mctl_phy_read_calibration(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30); - if (para->ranks == 2) { + if (config->ranks == 2) { clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10); setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1); @@ -395,7 +414,7 @@ static bool mctl_phy_read_calibration(struct dram_para *para) return result; } -static bool mctl_phy_read_training(struct dram_para *para) +static bool mctl_phy_read_training(const struct dram_config *config) { u32 val1, val2, *ptr1, *ptr2; bool result = true; @@ -414,7 +433,7 @@ static bool mctl_phy_read_training(struct dram_para *para) if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3) result = false; - if (para->bus_full_width) { + if (config->bus_full_width) { mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc); if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3) result = false; @@ -437,7 +456,7 @@ static bool mctl_phy_read_training(struct dram_para *para) result = false; } - if (para->bus_full_width) { + if (config->bus_full_width) { ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98); ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50); for (i = 0; i < 9; i++) { @@ -459,7 +478,7 @@ static bool mctl_phy_read_training(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3); - if (para->ranks == 2) { + if (config->ranks == 2) { /* maybe last parameter should be 1? */ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2); @@ -470,7 +489,7 @@ static bool mctl_phy_read_training(struct dram_para *para) if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3) result = false; - if (para->bus_full_width) { + if (config->bus_full_width) { mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc); if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3) result = false; @@ -484,7 +503,7 @@ static bool mctl_phy_read_training(struct dram_para *para) return result; } -static bool mctl_phy_write_training(struct dram_para *para) +static bool mctl_phy_write_training(const struct dram_config *config) { u32 val1, val2, *ptr1, *ptr2; bool result = true; @@ -504,7 +523,7 @@ static bool mctl_phy_write_training(struct dram_para *para) if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc) result = false; - if (para->bus_full_width) { + if (config->bus_full_width) { mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3); if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc) result = false; @@ -527,7 +546,7 @@ static bool mctl_phy_write_training(struct dram_para *para) result = false; } - if (para->bus_full_width) { + if (config->bus_full_width) { ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38); ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0); for (i = 0; i < 9; i++) { @@ -548,7 +567,7 @@ static bool mctl_phy_write_training(struct dram_para *para) clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60); - if (para->ranks == 2) { + if (config->ranks == 2) { clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4); setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10); @@ -558,7 +577,7 @@ static bool mctl_phy_write_training(struct dram_para *para) if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc) result = false; - if (para->bus_full_width) { + if (config->bus_full_width) { mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3); if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc) result = false; @@ -572,7 +591,7 @@ static bool mctl_phy_write_training(struct dram_para *para) return result; } -static void mctl_phy_bit_delay_compensation(struct dram_para *para) +static void mctl_phy_bit_delay_compensation(const struct dram_para *para) { u32 *ptr, val; int i; @@ -773,7 +792,8 @@ static void mctl_phy_bit_delay_compensation(struct dram_para *para) } } -static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para) +static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para, + const struct dram_config *config) { u32 val, *ptr; int i; @@ -793,36 +813,53 @@ static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para) writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0); writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4); - /* following configuration is DDR3 specific */ - val = (para->tpr10 >> 7) & 0x1e; - if (para->tpr2 & 1) { - writel(val, SUNXI_DRAM_PHY0_BASE + 0x794); - if (para->ranks == 2) { - val = (para->tpr10 >> 11) & 0x1e; - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4); - } - if (para->tpr0 & BIT(31)) { - val = (para->tpr0 << 1) & 0x3e; - writel(val, SUNXI_DRAM_PHY0_BASE + 0x790); - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8); - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc); - } - } else { - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4); - if (para->ranks == 2) { - val = (para->tpr10 >> 11) & 0x1e; - writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c); + if (para->type == SUNXI_DRAM_TYPE_DDR3) { + val = (para->tpr10 >> 7) & 0x1e; + if (para->tpr2 & 1) { + writel(val, SUNXI_DRAM_PHY0_BASE + 0x794); + if (config->ranks == 2) { + val = (para->tpr10 >> 11) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4); + } + if (para->tpr0 & BIT(31)) { + val = (para->tpr0 << 1) & 0x3e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x790); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc); + } + } else { + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4); + if (config->ranks == 2) { + val = (para->tpr10 >> 11) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c); + } + if (para->tpr0 & BIT(31)) { + val = (para->tpr0 << 1) & 0x3e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8); + } } - if (para->tpr0 & BIT(31)) { - val = (para->tpr0 << 1) & 0x3e; - writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c); - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4); - writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8); + } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) { + val = (para->tpr10 >> 7) & 0x1e; + if (para->tpr2 & 1) { + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0); + if (config->ranks == 2) { + val = (para->tpr10 >> 11) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c); + } + } else { + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8); + if (config->ranks == 2) { + val = (para->tpr10 >> 11) & 0x1e; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8); + } } } } -static bool mctl_phy_init(struct dram_para *para) +static bool mctl_phy_init(const struct dram_para *para, + const struct dram_config *config) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -831,18 +868,29 @@ static bool mctl_phy_init(struct dram_para *para) u32 val, val2, *ptr, mr0, mr2; int i; - if (para->bus_full_width) + if (config->bus_full_width) val = 0xf; else val = 3; clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val); if (para->tpr2 & 0x100) { - val = 9; - val2 = 7; + if (para->type == SUNXI_DRAM_TYPE_DDR3) { + val = 9; + val2 = 7; + } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) { + // untested setup: use some values for now + val = 14; + val2 = 8; + } } else { - val = 13; - val2 = 9; + if (para->type == SUNXI_DRAM_TYPE_DDR3) { + val = 13; + val2 = 9; + } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) { + val = 14; + val2 = 8; + } } writel(val, SUNXI_DRAM_PHY0_BASE + 0x14); @@ -865,14 +913,22 @@ static bool mctl_phy_init(struct dram_para *para) writel(phy_init[i], &ptr[i]); if (para->tpr10 & TPR10_CA_BIT_DELAY) - mctl_phy_ca_bit_delay_compensation(para); + mctl_phy_ca_bit_delay_compensation(para, config); - writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc); - writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c); + if (para->type == SUNXI_DRAM_TYPE_DDR3) + val = 0x80; + else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + val = 0xc0; + writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc); + writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c); mctl_phy_configure_odt(para); - clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa); + if (para->type == SUNXI_DRAM_TYPE_DDR3) + val = 0x0a; + else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + val = 0x0b; + clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val); if (para->clk <= 672) writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20); @@ -922,21 +978,39 @@ static bool mctl_phy_init(struct dram_para *para) mr2 = 0x20; } - writel(mr0, &mctl_ctl->mrctrl1); - writel(0x80000030, &mctl_ctl->mrctrl0); - mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); - - writel(4, &mctl_ctl->mrctrl1); - writel(0x80001030, &mctl_ctl->mrctrl0); - mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); - - writel(mr2, &mctl_ctl->mrctrl1); - writel(0x80002030, &mctl_ctl->mrctrl0); - mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); - - writel(0, &mctl_ctl->mrctrl1); - writel(0x80003030, &mctl_ctl->mrctrl0); - mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + if (para->type == SUNXI_DRAM_TYPE_DDR3) { + writel(mr0, &mctl_ctl->mrctrl1); + writel(0x80000030, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(4, &mctl_ctl->mrctrl1); + writel(0x80001030, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(mr2, &mctl_ctl->mrctrl1); + writel(0x80002030, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(0, &mctl_ctl->mrctrl1); + writel(0x80003030, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) { + writel(mr0, &mctl_ctl->mrctrl1); + writel(0x800000f0, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(4, &mctl_ctl->mrctrl1); + writel(0x800000f0, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(mr2, &mctl_ctl->mrctrl1); + writel(0x800000f0, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + + writel(0x301, &mctl_ctl->mrctrl1); + writel(0x800000f0, &mctl_ctl->mrctrl0); + mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0); + } writel(0, SUNXI_DRAM_PHY0_BASE + 0x54); @@ -946,7 +1020,7 @@ static bool mctl_phy_init(struct dram_para *para) if (para->tpr10 & TPR10_WRITE_LEVELING) { for (i = 0; i < 5; i++) - if (mctl_phy_write_leveling(para)) + if (mctl_phy_write_leveling(config)) break; if (i == 5) { debug("write leveling failed!\n"); @@ -956,7 +1030,7 @@ static bool mctl_phy_init(struct dram_para *para) if (para->tpr10 & TPR10_READ_CALIBRATION) { for (i = 0; i < 5; i++) - if (mctl_phy_read_calibration(para)) + if (mctl_phy_read_calibration(config)) break; if (i == 5) { debug("read calibration failed!\n"); @@ -966,7 +1040,7 @@ static bool mctl_phy_init(struct dram_para *para) if (para->tpr10 & TPR10_READ_TRAINING) { for (i = 0; i < 5; i++) - if (mctl_phy_read_training(para)) + if (mctl_phy_read_training(config)) break; if (i == 5) { debug("read training failed!\n"); @@ -976,7 +1050,7 @@ static bool mctl_phy_init(struct dram_para *para) if (para->tpr10 & TPR10_WRITE_TRAINING) { for (i = 0; i < 5; i++) - if (mctl_phy_write_training(para)) + if (mctl_phy_write_training(config)) break; if (i == 5) { debug("write training failed!\n"); @@ -991,7 +1065,8 @@ static bool mctl_phy_init(struct dram_para *para) return true; } -static bool mctl_ctrl_init(struct dram_para *para) +static bool mctl_ctrl_init(const struct dram_para *para, + const struct dram_config *config) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -1010,27 +1085,34 @@ static bool mctl_ctrl_init(struct dram_para *para) setbits_le32(&mctl_com->unk_0x008, 0xff00); - reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks); - reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE; - if (para->bus_full_width) + reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(config->ranks); + if (para->type == SUNXI_DRAM_TYPE_DDR3) + reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE; + else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + reg_val |= MSTR_DEVICETYPE_LPDDR3; + if (config->bus_full_width) reg_val |= MSTR_BUSWIDTH_FULL; else reg_val |= MSTR_BUSWIDTH_HALF; writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr); - if (para->ranks == 2) + if (config->ranks == 2) writel(0x0303, &mctl_ctl->odtmap); else writel(0x0201, &mctl_ctl->odtmap); - writel(0x06000400, &mctl_ctl->odtcfg); - writel(0x06000400, &mctl_ctl->unk_0x2240); - writel(0x06000400, &mctl_ctl->unk_0x3240); - writel(0x06000400, &mctl_ctl->unk_0x4240); + if (para->type == SUNXI_DRAM_TYPE_DDR3) + reg_val = 0x06000400; + else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) + reg_val = 0x09020400; + writel(reg_val, &mctl_ctl->odtcfg); + writel(reg_val, &mctl_ctl->unk_0x2240); + writel(reg_val, &mctl_ctl->unk_0x3240); + writel(reg_val, &mctl_ctl->unk_0x4240); writel(BIT(31), &mctl_com->cr); - mctl_set_addrmap(para); + mctl_set_addrmap(config); mctl_set_timing_params(para); @@ -1056,7 +1138,7 @@ static bool mctl_ctrl_init(struct dram_para *para) /* this write seems to enable PHY MMIO region */ setbits_le32(&mctl_com->unk_0x500, BIT(24)); - if (!mctl_phy_init(para)) + if (!mctl_phy_init(para, config)) return false; writel(0, &mctl_ctl->swctl); @@ -1073,18 +1155,20 @@ static bool mctl_ctrl_init(struct dram_para *para) return true; } -static bool mctl_core_init(struct dram_para *para) +static bool mctl_core_init(const struct dram_para *para, + const struct dram_config *config) { - mctl_sys_init(para); + mctl_sys_init(para->clk); - return mctl_ctrl_init(para); + return mctl_ctrl_init(para, config); } -static void mctl_auto_detect_rank_width(struct dram_para *para) +static void mctl_auto_detect_rank_width(const struct dram_para *para, + struct dram_config *config) { /* this is minimum size that it's supported */ - para->cols = 8; - para->rows = 13; + config->cols = 8; + config->rows = 13; /* * Strategy here is to test most demanding combination first and least @@ -1095,94 +1179,101 @@ static void mctl_auto_detect_rank_width(struct dram_para *para) */ debug("testing 32-bit width, rank = 2\n"); - para->bus_full_width = 1; - para->ranks = 2; - if (mctl_core_init(para)) + config->bus_full_width = 1; + config->ranks = 2; + if (mctl_core_init(para, config)) return; debug("testing 32-bit width, rank = 1\n"); - para->bus_full_width = 1; - para->ranks = 1; - if (mctl_core_init(para)) + config->bus_full_width = 1; + config->ranks = 1; + if (mctl_core_init(para, config)) return; debug("testing 16-bit width, rank = 2\n"); - para->bus_full_width = 0; - para->ranks = 2; - if (mctl_core_init(para)) + config->bus_full_width = 0; + config->ranks = 2; + if (mctl_core_init(para, config)) return; debug("testing 16-bit width, rank = 1\n"); - para->bus_full_width = 0; - para->ranks = 1; - if (mctl_core_init(para)) + config->bus_full_width = 0; + config->ranks = 1; + if (mctl_core_init(para, config)) return; panic("This DRAM setup is currently not supported.\n"); } -static void mctl_auto_detect_dram_size(struct dram_para *para) +static void mctl_auto_detect_dram_size(const struct dram_para *para, + struct dram_config *config) { /* detect row address bits */ - para->cols = 8; - para->rows = 18; - mctl_core_init(para); + config->cols = 8; + config->rows = 18; + mctl_core_init(para, config); - for (para->rows = 13; para->rows < 18; para->rows++) { + for (config->rows = 13; config->rows < 18; config->rows++) { /* 8 banks, 8 bit per byte and 16/32 bit width */ - if (mctl_mem_matches((1 << (para->rows + para->cols + - 4 + para->bus_full_width)))) + if (mctl_mem_matches((1 << (config->rows + config->cols + + 4 + config->bus_full_width)))) break; } /* detect column address bits */ - para->cols = 11; - mctl_core_init(para); + config->cols = 11; + mctl_core_init(para, config); - for (para->cols = 8; para->cols < 11; para->cols++) { + for (config->cols = 8; config->cols < 11; config->cols++) { /* 8 bits per byte and 16/32 bit width */ - if (mctl_mem_matches(1 << (para->cols + 1 + - para->bus_full_width))) + if (mctl_mem_matches(1 << (config->cols + 1 + + config->bus_full_width))) break; } } -static unsigned long mctl_calc_size(struct dram_para *para) +static unsigned long mctl_calc_size(const struct dram_config *config) { - u8 width = para->bus_full_width ? 4 : 2; + u8 width = config->bus_full_width ? 4 : 2; /* 8 banks */ - return (1ULL << (para->cols + para->rows + 3)) * width * para->ranks; + return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks; } +static const struct dram_para para = { + .clk = CONFIG_DRAM_CLK, +#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333 + .type = SUNXI_DRAM_TYPE_DDR3, +#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3) + .type = SUNXI_DRAM_TYPE_LPDDR3, +#endif + .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, + .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, + .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI, + .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN, + .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0, + .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2, + .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, + .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, + .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12, +}; + unsigned long sunxi_dram_init(void) { struct sunxi_prcm_reg *const prcm = (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; - struct dram_para para = { - .clk = CONFIG_DRAM_CLK, - .type = SUNXI_DRAM_TYPE_DDR3, - .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT, - .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI, - .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI, - .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN, - .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0, - .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2, - .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10, - .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11, - .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12, - }; + struct dram_config config; unsigned long size; setbits_le32(&prcm->res_cal_ctrl, BIT(8)); clrbits_le32(&prcm->ohms240, 0x3f); - mctl_auto_detect_rank_width(¶); - mctl_auto_detect_dram_size(¶); + mctl_auto_detect_rank_width(¶, &config); + mctl_auto_detect_dram_size(¶, &config); - mctl_core_init(¶); + mctl_core_init(¶, &config); - size = mctl_calc_size(¶); + size = mctl_calc_size(&config); mctl_set_master_priority(); |