|
|
|
@ -404,12 +404,12 @@ static int ddrphy_training(void __iomem *phy_base) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* UMC */ |
|
|
|
|
static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency) |
|
|
|
|
static void umc_set_system_latency(void __iomem *dc_base, int phy_latency) |
|
|
|
|
{ |
|
|
|
|
u32 val; |
|
|
|
|
int latency; |
|
|
|
|
|
|
|
|
|
val = readl(umc_dc_base + UMC_RDATACTL_D0); |
|
|
|
|
val = readl(dc_base + UMC_RDATACTL_D0); |
|
|
|
|
latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT; |
|
|
|
|
latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >> |
|
|
|
|
UMC_RDATACTL_RAD2LTY_SHIFT; |
|
|
|
@ -427,18 +427,18 @@ static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency) |
|
|
|
|
val |= latency << UMC_RDATACTL_RADLTY_SHIFT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writel(val, umc_dc_base + UMC_RDATACTL_D0); |
|
|
|
|
writel(val, umc_dc_base + UMC_RDATACTL_D1); |
|
|
|
|
writel(val, dc_base + UMC_RDATACTL_D0); |
|
|
|
|
writel(val, dc_base + UMC_RDATACTL_D1); |
|
|
|
|
|
|
|
|
|
readl(umc_dc_base + UMC_RDATACTL_D1); /* relax */ |
|
|
|
|
readl(dc_base + UMC_RDATACTL_D1); /* relax */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* enable/disable auto refresh */ |
|
|
|
|
void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable) |
|
|
|
|
void umc_refresh_ctrl(void __iomem *dc_base, int enable) |
|
|
|
|
{ |
|
|
|
|
u32 tmp; |
|
|
|
|
|
|
|
|
|
tmp = readl(umc_dc_base + UMC_SPCSETB); |
|
|
|
|
tmp = readl(dc_base + UMC_SPCSETB); |
|
|
|
|
tmp &= ~UMC_SPCSETB_AREFMD_MASK; |
|
|
|
|
|
|
|
|
|
if (enable) |
|
|
|
@ -446,7 +446,7 @@ void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable) |
|
|
|
|
else |
|
|
|
|
tmp |= UMC_SPCSETB_AREFMD_REG; |
|
|
|
|
|
|
|
|
|
writel(tmp, umc_dc_base + UMC_SPCSETB); |
|
|
|
|
writel(tmp, dc_base + UMC_SPCSETB); |
|
|
|
|
udelay(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -458,7 +458,7 @@ static void umc_ud_init(void __iomem *umc_base, int ch) |
|
|
|
|
writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, |
|
|
|
|
static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, |
|
|
|
|
unsigned long size, int width, int ch) |
|
|
|
|
{ |
|
|
|
|
enum dram_size size_e; |
|
|
|
@ -480,14 +480,13 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writel(umc_cmdctla[freq], umc_dc_base + UMC_CMDCTLA); |
|
|
|
|
writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA); |
|
|
|
|
|
|
|
|
|
writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq], |
|
|
|
|
umc_dc_base + UMC_CMDCTLB); |
|
|
|
|
dc_base + UMC_CMDCTLB); |
|
|
|
|
|
|
|
|
|
writel(umc_spcctla[freq][size_e], |
|
|
|
|
umc_dc_base + UMC_SPCCTLA); |
|
|
|
|
writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB); |
|
|
|
|
writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA); |
|
|
|
|
writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB); |
|
|
|
|
|
|
|
|
|
val = 0x000e000e; |
|
|
|
|
latency = 12; |
|
|
|
@ -502,38 +501,38 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, |
|
|
|
|
val |= latency << UMC_RDATACTL_RADLTY_SHIFT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writel(val, umc_dc_base + UMC_RDATACTL_D0); |
|
|
|
|
writel(val, dc_base + UMC_RDATACTL_D0); |
|
|
|
|
if (width >= 32) |
|
|
|
|
writel(val, umc_dc_base + UMC_RDATACTL_D1); |
|
|
|
|
writel(val, dc_base + UMC_RDATACTL_D1); |
|
|
|
|
|
|
|
|
|
writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D0); |
|
|
|
|
writel(0x04060A02, dc_base + UMC_WDATACTL_D0); |
|
|
|
|
if (width >= 32) |
|
|
|
|
writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D1); |
|
|
|
|
writel(0x04000000, umc_dc_base + UMC_DATASET); |
|
|
|
|
writel(0x00400020, umc_dc_base + UMC_DCCGCTL); |
|
|
|
|
writel(0x00000084, umc_dc_base + UMC_FLOWCTLG); |
|
|
|
|
writel(0x00000000, umc_dc_base + UMC_ACSSETA); |
|
|
|
|
writel(0x04060A02, dc_base + UMC_WDATACTL_D1); |
|
|
|
|
writel(0x04000000, dc_base + UMC_DATASET); |
|
|
|
|
writel(0x00400020, dc_base + UMC_DCCGCTL); |
|
|
|
|
writel(0x00000084, dc_base + UMC_FLOWCTLG); |
|
|
|
|
writel(0x00000000, dc_base + UMC_ACSSETA); |
|
|
|
|
|
|
|
|
|
writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq], |
|
|
|
|
umc_dc_base + UMC_FLOWCTLA); |
|
|
|
|
dc_base + UMC_FLOWCTLA); |
|
|
|
|
|
|
|
|
|
writel(0x00004400, umc_dc_base + UMC_FLOWCTLC); |
|
|
|
|
writel(0x200A0A00, umc_dc_base + UMC_SPCSETB); |
|
|
|
|
writel(0x00000520, umc_dc_base + UMC_DFICUPDCTLA); |
|
|
|
|
writel(0x0000000D, umc_dc_base + UMC_RESPCTL); |
|
|
|
|
writel(0x00004400, dc_base + UMC_FLOWCTLC); |
|
|
|
|
writel(0x200A0A00, dc_base + UMC_SPCSETB); |
|
|
|
|
writel(0x00000520, dc_base + UMC_DFICUPDCTLA); |
|
|
|
|
writel(0x0000000D, dc_base + UMC_RESPCTL); |
|
|
|
|
|
|
|
|
|
if (ch != 2) { |
|
|
|
|
writel(0x00202000, umc_dc_base + UMC_FLOWCTLB); |
|
|
|
|
writel(0xFDBFFFFF, umc_dc_base + UMC_FLOWCTLOB0); |
|
|
|
|
writel(0xFFFFFFFF, umc_dc_base + UMC_FLOWCTLOB1); |
|
|
|
|
writel(0x00080700, umc_dc_base + UMC_BSICMAPSET); |
|
|
|
|
writel(0x00202000, dc_base + UMC_FLOWCTLB); |
|
|
|
|
writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0); |
|
|
|
|
writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1); |
|
|
|
|
writel(0x00080700, dc_base + UMC_BSICMAPSET); |
|
|
|
|
} else { |
|
|
|
|
writel(0x00200000, umc_dc_base + UMC_FLOWCTLB); |
|
|
|
|
writel(0x00000000, umc_dc_base + UMC_BSICMAPSET); |
|
|
|
|
writel(0x00200000, dc_base + UMC_FLOWCTLB); |
|
|
|
|
writel(0x00000000, dc_base + UMC_BSICMAPSET); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writel(0x00000000, umc_dc_base + UMC_ERRMASKA); |
|
|
|
|
writel(0x00000000, umc_dc_base + UMC_ERRMASKB); |
|
|
|
|
writel(0x00000000, dc_base + UMC_ERRMASKA); |
|
|
|
|
writel(0x00000000, dc_base + UMC_ERRMASKB); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -541,17 +540,17 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, |
|
|
|
|
static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, |
|
|
|
|
unsigned long size, unsigned int width, int ch) |
|
|
|
|
{ |
|
|
|
|
void __iomem *umc_dc_base = umc_ch_base + 0x00011000; |
|
|
|
|
void __iomem *dc_base = umc_ch_base + 0x00011000; |
|
|
|
|
void __iomem *phy_base = umc_ch_base + 0x00030000; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
writel(0x00000002, umc_dc_base + UMC_INITSET); |
|
|
|
|
while (readl(umc_dc_base + UMC_INITSTAT) & BIT(2)) |
|
|
|
|
writel(0x00000002, dc_base + UMC_INITSET); |
|
|
|
|
while (readl(dc_base + UMC_INITSTAT) & BIT(2)) |
|
|
|
|
cpu_relax(); |
|
|
|
|
|
|
|
|
|
/* deassert PHY reset signals */ |
|
|
|
|
writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST, |
|
|
|
|
umc_dc_base + UMC_DIOCTLA); |
|
|
|
|
dc_base + UMC_DIOCTLA); |
|
|
|
|
|
|
|
|
|
ddrphy_init(phy_base, freq, width, ch); |
|
|
|
|
|
|
|
|
@ -563,7 +562,7 @@ static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
ret = umc_dc_init(umc_dc_base, freq, size, width, ch); |
|
|
|
|
ret = umc_dc_init(dc_base, freq, size, width, ch); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
@ -576,15 +575,15 @@ static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, |
|
|
|
|
udelay(1); |
|
|
|
|
|
|
|
|
|
/* match the system latency between UMC and PHY */ |
|
|
|
|
umc_set_system_latency(umc_dc_base, |
|
|
|
|
umc_set_system_latency(dc_base, |
|
|
|
|
ddrphy_get_system_latency(phy_base, width)); |
|
|
|
|
|
|
|
|
|
udelay(1); |
|
|
|
|
|
|
|
|
|
/* stop auto refresh before clearing FIFO in PHY */ |
|
|
|
|
umc_refresh_ctrl(umc_dc_base, 0); |
|
|
|
|
umc_refresh_ctrl(dc_base, 0); |
|
|
|
|
ddrphy_fifo_reset(phy_base); |
|
|
|
|
umc_refresh_ctrl(umc_dc_base, 1); |
|
|
|
|
umc_refresh_ctrl(dc_base, 1); |
|
|
|
|
|
|
|
|
|
udelay(10); |
|
|
|
|
|
|
|
|
|