It turns out that checking just one write is not enough. Due to unexplained reasons scan procedure detected double the size. By making 16 dword writes and comparisons that never happens.
New procedure is also inverted. Instead of writing two different values to base address and some offset and then reading both and comparing values, simplify this by writing pattern at the base address and then search for this pattern at some offset. Signed-off-by: Jernej Skrabec <jernej.skra...@gmail.com> --- arch/arm/mach-sunxi/dram_sun50i_h616.c | 58 +++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 6f84e59e39cd..1e21f5dd451f 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -1360,38 +1360,92 @@ static void mctl_auto_detect_rank_width(const struct dram_para *para, panic("This DRAM setup is currently not supported.\n"); } +static void mctl_write_pattern(void) +{ + unsigned int i; + u32 *ptr, val; + + ptr = (u32 *)CFG_SYS_SDRAM_BASE; + for (i = 0; i < 16; ptr++, i++) { + if (i & 1) + val = ~(ulong)ptr; + else + val = (ulong)ptr; + writel(val, ptr); + } +} + +static bool mctl_check_pattern(ulong offset) +{ + unsigned int i; + u32 *ptr, val; + + ptr = (u32 *)CFG_SYS_SDRAM_BASE; + for (i = 0; i < 16; ptr++, i++) { + if (i & 1) + val = ~(ulong)ptr; + else + val = (ulong)ptr; + if (val != *(ptr + offset / 4)) + return false; + } + + return true; +} + static void mctl_auto_detect_dram_size(const struct dram_para *para, struct dram_config *config) { unsigned int shift, cols, rows; + u32 buffer[16]; /* max. config for columns, but not rows */ config->cols = 11; config->rows = 13; mctl_core_init(para, config); + /* + * Store content so it can be restored later. This is important + * if controller was already initialized and holds any data + * which is important for restoring system. + */ + memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer)); + + mctl_write_pattern(); + shift = config->bus_full_width + 1; /* detect column address bits */ for (cols = 8; cols < 11; cols++) { - if (mctl_mem_matches(1ULL << (cols + shift))) + if (mctl_check_pattern(1ULL << (cols + shift))) break; } debug("detected %u columns\n", cols); + /* restore data */ + memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer)); + /* reconfigure to make sure that all active rows are accessible */ config->cols = 8; config->rows = 17; mctl_core_init(para, config); + /* store data again as it might be moved */ + memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer)); + + mctl_write_pattern(); + /* detect row address bits */ shift = config->bus_full_width + 4 + config->cols; for (rows = 13; rows < 17; rows++) { - if (mctl_mem_matches(1ULL << (rows + shift))) + if (mctl_check_pattern(1ULL << (rows + shift))) break; } debug("detected %u rows\n", rows); + /* restore data again */ + memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer)); + config->cols = cols; config->rows = rows; } -- 2.48.1