Allwinner: u-boot: Fix H6 DRAM size detection

This commit is contained in:
Jernej Skrabec 2025-03-15 19:55:50 +01:00
parent cd5ee5f728
commit 8314eaef94
2 changed files with 132 additions and 46 deletions

View File

@ -1,46 +0,0 @@
From: Gunjan Gupta <viraniac@gmail.com>
Subject: [PATCH 1/1] sunxi: dram: Fix incorrect ram size detection for some H6
boards
Date: Sun, 1 Oct 2023 21:43:32 +0530
On some H6 boards like Orange Pi 3 LTS, some times U-Boot fails to detect
ram size correctly. Instead of 2GB thats available, it detects 4GB of ram
and then SPL just hangs there making board not to boot further.
On debugging, I found that the rows value were being determined correctly,
but columns were sometimes off by one value. I found that adding some
delay after the mctl_core_init call along with making use of dsb in the
start of the mctl_mem_matches solves the issue.
Signed-off-by: Gunjan Gupta <viraniac@gmail.com>
---
arch/arm/mach-sunxi/dram_helpers.c | 1 +
arch/arm/mach-sunxi/dram_sun50i_h6.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index cdf2750f1c..5758c58e07 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -41,6 +41,7 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val)
val_base = readl(base);
val_offset = readl(base + offset);
+ dsb();
/* Try to write different values to RAM at two addresses */
writel(0, base);
writel(0xaa55aa55, base + offset);
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index bff2e42513..a031a845f5 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -621,6 +621,8 @@ static void mctl_auto_detect_dram_size(struct dram_para *para)
para->cols = 11;
mctl_core_init(para);
+ udelay(50);
+
for (para->cols = 8; para->cols < 11; para->cols++) {
/* 8 bits per byte and 16/32 bit width */
if (mctl_mem_matches(1 << (para->cols + 1 +

View File

@ -0,0 +1,132 @@
From dacaffdf195c924b33c6ad0a7f93de18dfed92b4 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sat, 15 Mar 2025 19:52:31 +0100
Subject: [PATCH] sunxi: h6: Fix DRAM size detection
This is based on submitted patches for newer SoCs. It needs to be
properly reworked once they are merged.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
arch/arm/mach-sunxi/dram_sun50i_h6.c | 97 ++++++++++++++++++++++------
1 file changed, 79 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index e7862bd06ea3..f5ee64cfead4 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -601,32 +601,93 @@ static void mctl_auto_detect_rank_width(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(struct dram_para *para)
{
- /* TODO: non-(LP)DDR3 */
+ unsigned int shift, cols, rows;
+ u32 buffer[16];
- /* detect row address bits */
- para->cols = 8;
- para->rows = 18;
- mctl_core_init(para);
-
- for (para->rows = 13; para->rows < 18; para->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))))
- break;
- }
-
- /* detect column address bits */
+ /* max. config for columns, but not rows */
para->cols = 11;
+ para->rows = 13;
mctl_core_init(para);
- for (para->cols = 8; para->cols < 11; para->cols++) {
- /* 8 bits per byte and 16/32 bit width */
- if (mctl_mem_matches(1 << (para->cols + 1 +
- para->bus_full_width)))
+ /*
+ * 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 = para->bus_full_width + 1;
+
+ /* detect column address bits */
+ for (cols = 8; cols < 11; cols++) {
+ 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 */
+ para->cols = 8;
+ para->rows = 17;
+ mctl_core_init(para);
+
+ /* 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 = para->bus_full_width + 4 + para->cols;
+ for (rows = 13; rows < 17; rows++) {
+ 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));
+
+ para->cols = cols;
+ para->rows = rows;
}
unsigned long mctl_calc_size(struct dram_para *para)
--
2.48.1