summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram.h1
-rw-r--r--arch/arm/mach-sunxi/dram_dw_helpers.c22
-rw-r--r--arch/arm/mach-sunxi/dram_helpers.c12
3 files changed, 34 insertions, 1 deletions
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 0eccb1e6c28..59e2e980bfa 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -45,5 +45,6 @@ unsigned long sunxi_dram_init(void);
void mctl_await_completion(u32 *reg, u32 mask, u32 val);
bool mctl_mem_matches(u32 offset);
bool mctl_mem_matches_base(u32 offset, ulong base);
+bool mctl_check_memory(phys_addr_t addr);
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
index 24767354935..d2af2d57fde 100644
--- a/arch/arm/mach-sunxi/dram_dw_helpers.c
+++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
@@ -143,8 +143,28 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
unsigned long mctl_calc_size(const struct dram_config *config)
{
+ unsigned long size;
u8 width = config->bus_full_width ? 4 : 2;
/* 8 banks */
- return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+ size = (1ULL << (config->cols + config->rows + 3)) * width *
+ config->ranks;
+
+ /*
+ * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
+ * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
+ * so test the last quarter for being able to store values.
+ */
+ if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
+ if (mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3 - 64)) {
+ size = (size / 4) * 3;
+ debug("capping memory at %ld MB\n", size >> 20);
+ } else {
+ printf("DRAM test failure at address 0x%lx\n",
+ CFG_SYS_SDRAM_BASE + size / 4 * 3 - 64);
+ return 0;
+ }
+ }
+
+ return size;
}
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index 83dbe4ca98f..376b7d14f86 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
}
#endif
+
+bool mctl_check_memory(phys_addr_t addr)
+{
+ uint32_t orig, val;
+
+ orig = readl(addr);
+ writel(~orig, addr);
+ val = readl(addr);
+ writel(orig, addr);
+
+ return ~orig == val;
+}