diskOS installer: initial public beta
Flashes the diskOS custom UI onto the FiiO Snowsky Disc over Ingenic mask-ROM USB, building the image from your own stock firmware. Runs from source via install.sh.
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
From 08f128d82f8e86dac5ca277d4fe4cc3fd7fef204 Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 22:51:34 +1000
|
||||
Subject: [PATCH 1/8] baseline: burner_x2000 SPL that loads+executes on device
|
||||
(-fcommon + mask-ROM return shim)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/x2000/start.S | 23 +++++++++++++++++++++++
|
||||
config.mk | 2 +-
|
||||
tools/ingenic-tools/mmc_params | Bin 0 -> 14472 bytes
|
||||
3 files changed, 24 insertions(+), 1 deletion(-)
|
||||
create mode 100755 tools/ingenic-tools/mmc_params
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/x2000/start.S b/arch/mips/cpu/xburst2/x2000/start.S
|
||||
index caab455..2dcc1e2 100755
|
||||
--- a/arch/mips/cpu/xburst2/x2000/start.S
|
||||
+++ b/arch/mips/cpu/xburst2/x2000/start.S
|
||||
@@ -167,6 +167,29 @@ cache_alloc_a_line:
|
||||
li sp, 0x80001000
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_BURNER
|
||||
+ /*
|
||||
+ * DDR-only USB stage-1 (burner mode): board_init_f() brings up clocks and
|
||||
+ * SDRAM and then RETURNS (see arch/mips/cpu/xburst2/x2000/soc.c, the
|
||||
+ * CONFIG_BURNER branch). For usbboot to keep driving the USB session we
|
||||
+ * must hand control back to the mask ROM afterwards. Preserve the mask-ROM
|
||||
+ * return address (and sp) in a fixed TCSM scratch slot across the call --
|
||||
+ * board_init_f repoints/uses the stack internally, so a stack-relative save
|
||||
+ * is not reliable for the outer return. 0xb24017f0 lies in the param/pad
|
||||
+ * region below the code (offset 0x800) and is untouched by DDR init.
|
||||
+ */
|
||||
+ li t0, 0xb24017f0
|
||||
+ sw ra, 0(t0)
|
||||
+ sw sp, 4(t0)
|
||||
+ jal board_init_f
|
||||
+ nop
|
||||
+ li t0, 0xb24017f0
|
||||
+ lw ra, 0(t0)
|
||||
+ lw sp, 4(t0)
|
||||
+ jr ra
|
||||
+ nop
|
||||
+#else
|
||||
j board_init_f
|
||||
nop
|
||||
+#endif
|
||||
|
||||
diff --git a/config.mk b/config.mk
|
||||
index f71e145..d78be30 100755
|
||||
--- a/config.mk
|
||||
+++ b/config.mk
|
||||
@@ -195,7 +195,7 @@ endif
|
||||
ARFLAGS = $(error update your Makefile to use cmd_link_o_target and not AR)
|
||||
RELFLAGS= $(PLATFORM_RELFLAGS)
|
||||
DBGFLAGS= -g # -DDEBUG
|
||||
-OPTFLAGS= -Os #-fomit-frame-pointer
|
||||
+OPTFLAGS= -Os -fcommon #-fomit-frame-pointer (-fcommon: 2013 tree relies on tentative defs; GCC>=10 defaults -fno-common)
|
||||
|
||||
OBJCFLAGS += --gap-fill=0xff
|
||||
|
||||
diff --git a/tools/ingenic-tools/mmc_params b/tools/ingenic-tools/mmc_params
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..78adebd875be1ac2ec4d41c346622d76fea5e1c4
|
||||
GIT binary patch
|
||||
literal 14472
|
||||
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
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
From 8f93e72bd6b1c770269ce746d401cebb063e71dc Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 22:55:29 +1000
|
||||
Subject: [PATCH 2/8] =?UTF-8?q?ddr:=20add=20LPDDR3=20support=20(mr11=20fie?=
|
||||
=?UTF-8?q?ld,=20LPDDR3=20MR=20sequence,=20W63AH6NKB=20type-force)=20?=
|
||||
=?UTF-8?q?=E2=80=94=20ported=20from=20tobunto=20X2000?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 20 ++++++++++++++++++++
|
||||
arch/mips/cpu/xburst2/ddr_reg_data.h | 2 ++
|
||||
2 files changed, 22 insertions(+)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index 5257e3a..e08a5df 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -454,6 +454,21 @@ static void ddrc_dfi_init(enum ddr_type type, int bypass)
|
||||
ddr_writel(DDRC_LMR_MR(2), DDRC_LMR); //MR2
|
||||
ddr_writel(DDRC_LMR_MR(3), DDRC_LMR); //MR3
|
||||
ddr_writel(DDRC_DLMR_VALUE | DDRC_LMR_START | DDRC_LMR_CMD_ZQCL_CS0, DDRC_LMR); //ZQCL
|
||||
+#undef DDRC_LMR_MR
|
||||
+ break;
|
||||
+ case LPDDR3:
|
||||
+ /* LPDDR3 MR sequence - ported from tobunto/u-boot X2000 (matches the vendor
|
||||
+ * disc_spl.bin trace): MR63,10,1,2,3,11 each followed by mdelay(1); no ZQ. */
|
||||
+#define DDRC_LMR_MR(n) \
|
||||
+ DDRC_DLMR_VALUE | DDRC_LMR_START | DDRC_LMR_CMD_LMR | \
|
||||
+ ((DDR_MR##n##_VALUE & 0xff) << 24) | \
|
||||
+ (((DDR_MR##n##_VALUE >> 8) & 0xff) << (16))
|
||||
+ ddr_writel(DDRC_LMR_MR(63), DDRC_LMR); mdelay(1); //set MRS reset
|
||||
+ ddr_writel(DDRC_LMR_MR(10), DDRC_LMR); mdelay(1); //set IO calibration
|
||||
+ ddr_writel(DDRC_LMR_MR(1), DDRC_LMR); mdelay(1); //set MR1
|
||||
+ ddr_writel(DDRC_LMR_MR(2), DDRC_LMR); mdelay(1); //set MR2
|
||||
+ ddr_writel(DDRC_LMR_MR(3), DDRC_LMR); mdelay(1); //set MR3
|
||||
+ ddr_writel(DDRC_LMR_MR(11), DDRC_LMR); mdelay(1); //set MR11
|
||||
#undef DDRC_LMR_MR
|
||||
break;
|
||||
default:
|
||||
@@ -556,6 +571,11 @@ void sdram_init(void)
|
||||
soc_ddr_init();
|
||||
|
||||
type = get_ddr_type();
|
||||
+ /* Snowsky Disc = Winbond W63AH6NKB-BI LPDDR3. The controller CFG.TYPE field reads as
|
||||
+ * LPDDR2(5) for this part (the vendor SPL dispatches on the logical record type=3, not
|
||||
+ * CFG.TYPE), so force the LPDDR3 MR sequence here. Only ddrc_dfi_init consumes `type`
|
||||
+ * (the X2000 prev_ddr_init hook is a no-op). */
|
||||
+ type = LPDDR3;
|
||||
clk_set_rate(DDR, gd->arch.gi->ddrfreq);
|
||||
if(ddr_hook && ddr_hook->prev_ddr_init)
|
||||
ddr_hook->prev_ddr_init(type);
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_reg_data.h b/arch/mips/cpu/xburst2/ddr_reg_data.h
|
||||
index 4878267..b48575f 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_reg_data.h
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_reg_data.h
|
||||
@@ -27,6 +27,7 @@ struct ddr_registers
|
||||
uint32_t ddr_mr2;
|
||||
uint32_t ddr_mr3;
|
||||
uint32_t ddr_mr10;
|
||||
+ uint32_t ddr_mr11;
|
||||
uint32_t ddr_mr63;
|
||||
uint32_t ddr_chip0_size;
|
||||
uint32_t ddr_chip1_size;
|
||||
@@ -59,6 +60,7 @@ extern struct ddr_registers *g_ddr_param;
|
||||
#define DDR_MR2_VALUE g_ddr_param->ddr_mr2
|
||||
#define DDR_MR3_VALUE g_ddr_param->ddr_mr3
|
||||
#define DDR_MR10_VALUE g_ddr_param->ddr_mr10
|
||||
+#define DDR_MR11_VALUE g_ddr_param->ddr_mr11
|
||||
#define DDR_MR63_VALUE g_ddr_param->ddr_mr63
|
||||
#define DDR_CHIP_0_SIZE g_ddr_param->ddr_chip0_size
|
||||
#define DDR_CHIP_1_SIZE g_ddr_param->ddr_chip1_size
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
From 15c4698350fdd6ef22a15ce8daaab4b332f9762a Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 23:17:06 +1000
|
||||
Subject: [PATCH 3/8] ddr: instrument DDR bring-up with TCSM breadcrumbs +
|
||||
bounded polls (diagnostic build)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 45 +++++++++++++++++++++++------
|
||||
1 file changed, 36 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index e08a5df..91cf6a3 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -46,6 +46,23 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#define CONFIG_DWC_DEBUG 0
|
||||
+
|
||||
+/* ---- DDR bring-up diagnostics (breadcrumbs to TCSM pad @0xb24017c0, below the
|
||||
+ * start.S return-shim scratch at 0x17f0). usbboot uploads this region after the SPL
|
||||
+ * returns to the mask ROM, so ONE device cycle localises any DDR-init stall.
|
||||
+ * Layout: [0]=magic [1]=last stage reached [2]=first fail id [3]=status@fail [4]=fail count */
|
||||
+#define DDR_DIAG ((volatile unsigned int *)0xb24017c0)
|
||||
+#define DDR_DIAG_MAGIC 0xD1A6C0DEu
|
||||
+static inline void ddr_diag_init(void){ DDR_DIAG[0]=DDR_DIAG_MAGIC; DDR_DIAG[1]=0; DDR_DIAG[2]=0; DDR_DIAG[3]=0; DDR_DIAG[4]=0; __asm__ __volatile__("sync"); }
|
||||
+static inline void ddr_diag_stage(unsigned int s){ DDR_DIAG[1]=s; __asm__ __volatile__("sync"); }
|
||||
+static inline void ddr_diag_fail(unsigned int id, unsigned int status){ if(DDR_DIAG[2]==0){ DDR_DIAG[2]=id; DDR_DIAG[3]=status; } DDR_DIAG[4]++; __asm__ __volatile__("sync"); }
|
||||
+/* bounded busy-wait: wait for (cond); on ~1e6-iter timeout record (id,statusexpr) and stop waiting
|
||||
+ * (never spins forever, so the SPL always returns and the breadcrumb is readable). */
|
||||
+#define DDR_BOUND(cond, id, statusexpr) do { \
|
||||
+ unsigned int _bt = 1000000u; \
|
||||
+ while(!(cond)) { if(!--_bt){ ddr_diag_fail((id), (unsigned int)(statusexpr)); break; } } \
|
||||
+ } while(0)
|
||||
+
|
||||
#define ddr_hang() do{ \
|
||||
printf("%s %d\n",__FUNCTION__,__LINE__); \
|
||||
hang(); \
|
||||
@@ -250,7 +267,7 @@ static void ddrp_pll_init(void)
|
||||
ddr_writel(0, DDRP_INNOPHY_PLL_CTRL);
|
||||
#endif
|
||||
|
||||
- while(!(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & 1 << 3));
|
||||
+ DDR_BOUND(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & (1 << 3), 10 /*PLL_LOCK*/, ddr_readl(DDRP_INNOPHY_PLL_LOCK));
|
||||
}
|
||||
|
||||
static void ddrp_register_cfg(void)
|
||||
@@ -311,14 +328,15 @@ static void ddrp_hardware_calibration(void)
|
||||
unsigned int timeout = 1000000;
|
||||
/* ddr_writel(ddr_readl(DDRP_INNOPHY_TRAINING_CTRL) | 1, DDRP_INNOPHY_TRAINING_CTRL); */
|
||||
ddr_writel(1, DDRP_INNOPHY_TRAINING_CTRL);
|
||||
+ /* bounded (fixes the original timeout-- unsigned wrap); diagnostic, no hang() */
|
||||
do
|
||||
{
|
||||
val = ddr_readl(DDRP_INNOPHY_CALIB_DONE);
|
||||
- } while (((val & 0xf) != 0x3) && timeout--);
|
||||
+ } while (((val & 0xf) != 0x3) && --timeout);
|
||||
|
||||
- if(!timeout) {
|
||||
- printf("timeout:INNOPHY_CALIB_DONE %x\n", ddr_readl(DDRP_INNOPHY_CALIB_DONE));
|
||||
- hang();
|
||||
+ if(((val & 0xf) != 0x3)) {
|
||||
+ ddr_diag_fail(30 /*CALIB_DONE*/, val);
|
||||
+ ddr_writel(0, DDRP_INNOPHY_TRAINING_CTRL); /* clear training on failure (Codex) */
|
||||
}
|
||||
|
||||
ddr_writel(0, DDRP_INNOPHY_TRAINING_CTRL);
|
||||
@@ -424,7 +442,7 @@ static void ddrc_dfi_init(enum ddr_type type, int bypass)
|
||||
FUNC_ENTER();
|
||||
ddr_writel(DDRC_DWCFG_DFI_INIT_START, DDRC_DWCFG); // dfi_init_start high
|
||||
ddr_writel(0, DDRC_DWCFG); // set buswidth 16bit
|
||||
- while(!(ddr_readl(DDRC_DWSTATUS) & DDRC_DWSTATUS_DFI_INIT_COMP)); //polling dfi_init_complete
|
||||
+ DDR_BOUND(ddr_readl(DDRC_DWSTATUS) & DDRC_DWSTATUS_DFI_INIT_COMP, 20 /*DFI_INIT_COMP*/, ddr_readl(DDRC_DWSTATUS)); //polling dfi_init_complete
|
||||
|
||||
ddr_writel(0, DDRC_CTRL); //set dfi_reset_n high
|
||||
ddr_writel(DDRC_CFG_VALUE, DDRC_CFG);
|
||||
@@ -496,8 +514,7 @@ static void ddr_calibration(struct ddr_calib_value *dcv, int div)
|
||||
val = REG32(CPM_DDRCDR);
|
||||
val |= ((1 << 29) | (1 << 25));
|
||||
REG32(CPM_DDRCDR) = val;
|
||||
- while((REG32(CPM_DDRCDR) & (1 << 24)))
|
||||
- ;
|
||||
+ DDR_BOUND(!(REG32(CPM_DDRCDR) & (1 << 24)), 40 /*DDRCDR_BUSY*/, REG32(CPM_DDRCDR));
|
||||
/* // Set clock divider */
|
||||
val = REG32(CPM_DDRCDR);
|
||||
val &= ~(0xf);
|
||||
@@ -505,7 +522,7 @@ static void ddr_calibration(struct ddr_calib_value *dcv, int div)
|
||||
REG32(CPM_DDRCDR) = val;
|
||||
|
||||
// Polling PHY_FREQ_DONE
|
||||
- while(((ddr_readl(DDRC_DWSTATUS) & (1 << 3 | 1 << 1)) & 0xf) != 0xa);
|
||||
+ DDR_BOUND(((ddr_readl(DDRC_DWSTATUS) & (1 << 3 | 1 << 1)) & 0xf) == 0xa, 50 /*PHY_FREQ_DONE*/, ddr_readl(DDRC_DWSTATUS));
|
||||
ddrp_hardware_calibration();
|
||||
/* ddrp_software_calibration(); */
|
||||
|
||||
@@ -567,6 +584,8 @@ void sdram_init(void)
|
||||
int bypass = 0;
|
||||
|
||||
debug("sdram init start\n");
|
||||
+ ddr_diag_init(); /* breadcrumb record @0xb24017c0 */
|
||||
+ ddr_diag_stage(1); /* entered sdram_init */
|
||||
|
||||
soc_ddr_init();
|
||||
|
||||
@@ -582,26 +601,33 @@ void sdram_init(void)
|
||||
rate = clk_get_rate(DDR);
|
||||
debug("DDR clk rate %d\n", rate);
|
||||
|
||||
+ ddr_diag_stage(2);
|
||||
ddrc_reset_phy();
|
||||
|
||||
+ ddr_diag_stage(3);
|
||||
ddr_phy_init();
|
||||
dump_ddrp_register();
|
||||
|
||||
+ ddr_diag_stage(4);
|
||||
ddrc_dfi_init(type, bypass);
|
||||
|
||||
+ ddr_diag_stage(5);
|
||||
ddrc_prev_init();
|
||||
|
||||
/**
|
||||
* bypass = 1 or calibration = 0
|
||||
*/
|
||||
bypass = 0;
|
||||
+ ddr_diag_stage(6);
|
||||
ddrp_calibration(bypass);
|
||||
|
||||
+ ddr_diag_stage(7);
|
||||
ddrc_post_init();
|
||||
|
||||
if(ddr_hook && ddr_hook->post_ddr_init)
|
||||
ddr_hook->post_ddr_init(type);
|
||||
|
||||
+ ddr_diag_stage(8);
|
||||
get_dynamic_calib_value(rate);
|
||||
|
||||
if(DDRC_AUTOSR_EN_VALUE) {
|
||||
@@ -616,6 +642,7 @@ void sdram_init(void)
|
||||
|
||||
dump_ddrc_register();
|
||||
/* DDRC address remap configure*/
|
||||
+ ddr_diag_stage(9); /* 9 = sdram_init completed (success if no fail id recorded) */
|
||||
debug("sdram init finished\n");
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
From eb05eaef0f7dac0fb1f166f88d69e1b895eb2e1a Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 23:46:16 +1000
|
||||
Subject: [PATCH 4/8] ddr: bound clk.c DDR-clock polls + constrain
|
||||
dynamic-calib div; board_init_f breadcrumbs
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 1 +
|
||||
arch/mips/cpu/xburst2/x2000/clk.c | 6 +++---
|
||||
arch/mips/cpu/xburst2/x2000/soc.c | 22 +++++++++++++++++++++
|
||||
arch/mips/include/asm/arch-x2000/ddr_diag.h | 17 ++++++++++++++++
|
||||
4 files changed, 43 insertions(+), 3 deletions(-)
|
||||
create mode 100644 arch/mips/include/asm/arch-x2000/ddr_diag.h
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index 91cf6a3..c9b19f8 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -563,6 +563,7 @@ static void get_dynamic_calib_value(unsigned int rate)
|
||||
ddr_calibration(&dcv[cur_div], cur_div);
|
||||
break;
|
||||
}
|
||||
+ if(div > 0xf) { ddr_diag_fail(60 /*calib div overflow - bad DDR rate*/, (unsigned int)rate); break; }
|
||||
dcv[div].rate = drate;
|
||||
dcv[div].refcnt = get_refcnt_value(div);
|
||||
ddr_calibration(&dcv[div], div);
|
||||
diff --git a/arch/mips/cpu/xburst2/x2000/clk.c b/arch/mips/cpu/xburst2/x2000/clk.c
|
||||
index c700a03..30764b6 100755
|
||||
--- a/arch/mips/cpu/xburst2/x2000/clk.c
|
||||
+++ b/arch/mips/cpu/xburst2/x2000/clk.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/cpm.h>
|
||||
#include <asm/arch/clk.h>
|
||||
+#include <asm/arch/ddr_diag.h>
|
||||
#include <generated/clk_reg_values.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
@@ -68,7 +69,7 @@ void clk_prepare(void)
|
||||
/*set div max*/
|
||||
regval |= cgusetting[i].val;
|
||||
writel(regval, reg);
|
||||
- while (readl(reg) & (1 << cgusetting[i].busy));
|
||||
+ DDR_BOUND(!(readl(reg) & (1 << cgusetting[i].busy)), 4 /*cgu init busy*/, readl(reg));
|
||||
} else {
|
||||
regval &= ~(1 << cgusetting[i].ce);
|
||||
writel(regval, reg);
|
||||
@@ -244,8 +245,7 @@ void clk_set_rate(int clk_id, unsigned long rate)
|
||||
regval &= ~(3 << cgu->stop | 0xff);
|
||||
regval |= ((1 << cgu->ce) | cdr);
|
||||
writel(regval, reg);
|
||||
- while (readl(reg) & (1 << cgu->busy))
|
||||
- ;
|
||||
+ DDR_BOUND(!(readl(reg) & (1 << cgu->busy)), 5 /*DDR clk busy (clk_set_rate)*/, readl(reg));
|
||||
#ifdef DUMP_CGU_SELECT
|
||||
printf("%s(0x%x) :0x%x\n",clk_name[clk_id] ,reg, readl(reg));
|
||||
#endif
|
||||
diff --git a/arch/mips/cpu/xburst2/x2000/soc.c b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
index 54ff3b7..6b96c5b 100755
|
||||
--- a/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
+++ b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
@@ -67,11 +67,23 @@ extern void ddr_test_refresh(unsigned int start_addr, unsigned int end_addr);
|
||||
extern void flush_cache_all(void);
|
||||
|
||||
|
||||
+/* DIAG: breadcrumb record @0xb24017c0 (shared with ddr_innophy.c). Set 1 to early-return
|
||||
+ * before sdram_init to prove the mask-ROM return path works in isolation. */
|
||||
+#define DIAG_SKIP_SDRAM 0
|
||||
+#define BIF_CRUMB(s) do { *(volatile unsigned int*)0xb24017c4 = (s); __asm__ __volatile__("sync"); } while(0)
|
||||
+
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
/* Set global data pointer */
|
||||
gd = &gdata;
|
||||
|
||||
+ /* DIAG: mark that we reached board_init_f (magic + stage 0xF0) */
|
||||
+ *(volatile unsigned int*)0xb24017c0 = 0xD1A6C0DEu;
|
||||
+ *(volatile unsigned int*)0xb24017c8 = 0;
|
||||
+ *(volatile unsigned int*)0xb24017cc = 0;
|
||||
+ *(volatile unsigned int*)0xb24017d0 = 0;
|
||||
+ BIF_CRUMB(0xF0);
|
||||
+
|
||||
/* Setup global info */
|
||||
#ifndef CONFIG_BURNER
|
||||
gd->arch.gi = &ginfo;
|
||||
@@ -80,6 +92,7 @@ void board_init_f(ulong dummy)
|
||||
#endif
|
||||
|
||||
gpio_init();
|
||||
+ BIF_CRUMB(0xF1);
|
||||
|
||||
*(volatile unsigned int *)0xb0000020 = 0; //clk gate enable.
|
||||
*(volatile unsigned int *)0xb0000028 = 0; //clk gate enable.
|
||||
@@ -93,15 +106,24 @@ void board_init_f(ulong dummy)
|
||||
#endif
|
||||
debug("Timer init\n");
|
||||
timer_init();
|
||||
+ BIF_CRUMB(0xF2);
|
||||
|
||||
debug("CLK stop\n");
|
||||
// clk_prepare();
|
||||
|
||||
debug("PLL init\n");
|
||||
pll_init();
|
||||
+ BIF_CRUMB(0xF3);
|
||||
|
||||
debug("CLK init\n");
|
||||
clk_init();
|
||||
+ BIF_CRUMB(0xF4);
|
||||
+
|
||||
+#if DIAG_SKIP_SDRAM
|
||||
+ /* DIAG: return before DDR to test the mask-ROM return path in isolation. */
|
||||
+ BIF_CRUMB(0xFE);
|
||||
+ return;
|
||||
+#endif
|
||||
|
||||
debug("SDRAM init\n");
|
||||
sdram_init();
|
||||
diff --git a/arch/mips/include/asm/arch-x2000/ddr_diag.h b/arch/mips/include/asm/arch-x2000/ddr_diag.h
|
||||
new file mode 100644
|
||||
index 0000000..68654ec
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/arch-x2000/ddr_diag.h
|
||||
@@ -0,0 +1,17 @@
|
||||
+#ifndef _ASM_ARCH_DDR_DIAG_H
|
||||
+#define _ASM_ARCH_DDR_DIAG_H
|
||||
+/* Shared DDR bring-up breadcrumb record @0xb24017c0 (TCSM pad below the start.S return
|
||||
+ * shim scratch at 0x17f0). usbboot uploads it after the SPL returns to the mask ROM.
|
||||
+ * Layout: [0]=magic [1]=stage [2]=first fail id [3]=status@fail [4]=fail count */
|
||||
+#define DDR_DIAG ((volatile unsigned int *)0xb24017c0)
|
||||
+#define DDR_DIAG_MAGIC 0xD1A6C0DEu
|
||||
+#define ddr_diag_fail_raw(id, status) do { \
|
||||
+ if(DDR_DIAG[2]==0){ DDR_DIAG[2]=(unsigned int)(id); DDR_DIAG[3]=(unsigned int)(status); } \
|
||||
+ DDR_DIAG[4]++; __asm__ __volatile__("sync"); \
|
||||
+ } while(0)
|
||||
+/* bounded busy-wait: wait for (cond); on ~1e6-iter timeout record (id,statusexpr) and stop. */
|
||||
+#define DDR_BOUND(cond, id, statusexpr) do { \
|
||||
+ unsigned int _bt = 1000000u; \
|
||||
+ while(!(cond)) { if(!--_bt){ ddr_diag_fail_raw((id), (statusexpr)); break; } } \
|
||||
+ } while(0)
|
||||
+#endif
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From f51bc90392b4c0dc42456d876a37dc05926db445 Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 23:48:18 +1000
|
||||
Subject: [PATCH 5/8] ddr: disable verbose DEBUG/DWC_DEBUG printf dumps (slim
|
||||
SPL, no UART-wait in DDR path)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index c9b19f8..b394dad 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -21,7 +21,7 @@
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
-#define DEBUG
|
||||
+/* #define DEBUG */ /* off: shrink SPL + remove printf UART-waits from DDR path (breadcrumbs replace it) */
|
||||
/* #define DEBUG_READ_WRITE */
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
@@ -45,7 +45,7 @@
|
||||
#endif
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clk.h>
|
||||
-#define CONFIG_DWC_DEBUG 0
|
||||
+/* #define CONFIG_DWC_DEBUG 0 */ /* off: use the empty dump_ddr*_register() no-ops (shrinks SPL) */
|
||||
|
||||
/* ---- DDR bring-up diagnostics (breadcrumbs to TCSM pad @0xb24017c0, below the
|
||||
* start.S return-shim scratch at 0x17f0). usbboot uploads this region after the SPL
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From 26f15d13ea9b7e92eaf2326909b202799797f440 Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Mon, 24 Aug 2026 23:52:48 +1000
|
||||
Subject: [PATCH 6/8] ddr: fix PHY PLL divisors 20/5 -> 8/4 for W63AH6NKB
|
||||
LPDDR3 400MHz (calibration root cause)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 15 ++++++---------
|
||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index b394dad..4c7b921 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -247,25 +247,22 @@ static void ddrp_pll_init(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
+ /* PHY PLL divisors for W63AH6NKB LPDDR3 @400MHz: FBDIV=8, PDIV=4 (from tobunto X2000,
|
||||
+ * matches the vendor SPL). The tree's stock 20/5 sets the wrong PHY clock -> training
|
||||
+ * (CALIB_DONE) never converges. */
|
||||
val = ddr_readl(DDRP_INNOPHY_PLL_FBDIV);
|
||||
val &= ~(0xff);
|
||||
- val |= 0x14;
|
||||
+ val |= 0x8;
|
||||
ddr_writel(val, DDRP_INNOPHY_PLL_FBDIV);
|
||||
|
||||
val = ddr_readl(DDRP_INNOPHY_PLL_PDIV);
|
||||
val &= ~(0xff);
|
||||
- val |= 0x5;
|
||||
+ val |= 4;
|
||||
ddr_writel(val, DDRP_INNOPHY_PLL_PDIV);
|
||||
|
||||
- /* ddr_writel(0x14, DDRP_INNOPHY_PLL_FBDIV); */
|
||||
- /* ddr_writel(0x5, DDRP_INNOPHY_PLL_PDIV); */
|
||||
-#ifdef DEBUG_READ_WRITE
|
||||
+ /* toggle PLLPDEN via RMW (preserve other PLL_CTRL bits), as tobunto/vendor do */
|
||||
ddr_writel(ddr_readl(DDRP_INNOPHY_PLL_CTRL) | DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
|
||||
ddr_writel(ddr_readl(DDRP_INNOPHY_PLL_CTRL) & ~DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
|
||||
-#else
|
||||
- ddr_writel(DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
|
||||
- ddr_writel(0, DDRP_INNOPHY_PLL_CTRL);
|
||||
-#endif
|
||||
|
||||
DDR_BOUND(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & (1 << 3), 10 /*PLL_LOCK*/, ddr_readl(DDRP_INNOPHY_PLL_LOCK));
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
From e951f0e6e47ab7b0ffe4df2de1120685a11cd63a Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Tue, 25 Aug 2026 00:02:46 +1000
|
||||
Subject: [PATCH 7/8] spl: strip board_init_f test scaffolding (keep bounded
|
||||
polls + sdram diag as hardening)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/x2000/soc.c | 21 ---------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/x2000/soc.c b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
index 6b96c5b..ab9e437 100755
|
||||
--- a/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
+++ b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
@@ -67,23 +67,11 @@ extern void ddr_test_refresh(unsigned int start_addr, unsigned int end_addr);
|
||||
extern void flush_cache_all(void);
|
||||
|
||||
|
||||
-/* DIAG: breadcrumb record @0xb24017c0 (shared with ddr_innophy.c). Set 1 to early-return
|
||||
- * before sdram_init to prove the mask-ROM return path works in isolation. */
|
||||
-#define DIAG_SKIP_SDRAM 0
|
||||
-#define BIF_CRUMB(s) do { *(volatile unsigned int*)0xb24017c4 = (s); __asm__ __volatile__("sync"); } while(0)
|
||||
-
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
/* Set global data pointer */
|
||||
gd = &gdata;
|
||||
|
||||
- /* DIAG: mark that we reached board_init_f (magic + stage 0xF0) */
|
||||
- *(volatile unsigned int*)0xb24017c0 = 0xD1A6C0DEu;
|
||||
- *(volatile unsigned int*)0xb24017c8 = 0;
|
||||
- *(volatile unsigned int*)0xb24017cc = 0;
|
||||
- *(volatile unsigned int*)0xb24017d0 = 0;
|
||||
- BIF_CRUMB(0xF0);
|
||||
-
|
||||
/* Setup global info */
|
||||
#ifndef CONFIG_BURNER
|
||||
gd->arch.gi = &ginfo;
|
||||
@@ -92,7 +80,6 @@ void board_init_f(ulong dummy)
|
||||
#endif
|
||||
|
||||
gpio_init();
|
||||
- BIF_CRUMB(0xF1);
|
||||
|
||||
*(volatile unsigned int *)0xb0000020 = 0; //clk gate enable.
|
||||
*(volatile unsigned int *)0xb0000028 = 0; //clk gate enable.
|
||||
@@ -106,24 +93,16 @@ void board_init_f(ulong dummy)
|
||||
#endif
|
||||
debug("Timer init\n");
|
||||
timer_init();
|
||||
- BIF_CRUMB(0xF2);
|
||||
|
||||
debug("CLK stop\n");
|
||||
// clk_prepare();
|
||||
|
||||
debug("PLL init\n");
|
||||
pll_init();
|
||||
- BIF_CRUMB(0xF3);
|
||||
|
||||
debug("CLK init\n");
|
||||
clk_init();
|
||||
- BIF_CRUMB(0xF4);
|
||||
|
||||
-#if DIAG_SKIP_SDRAM
|
||||
- /* DIAG: return before DDR to test the mask-ROM return path in isolation. */
|
||||
- BIF_CRUMB(0xFE);
|
||||
- return;
|
||||
-#endif
|
||||
|
||||
debug("SDRAM init\n");
|
||||
sdram_init();
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
From 7caf048bae01c31460d4d675a52823e5b62ff091 Mon Sep 17 00:00:00 2001
|
||||
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
|
||||
Date: Tue, 25 Aug 2026 01:52:48 +1000
|
||||
Subject: [PATCH 8/8] spl: robust WDT disable (clear TCER.TCEN + TSSR) + drop
|
||||
dynamic-calib sweep (flash-failure root cause)
|
||||
|
||||
---
|
||||
arch/mips/cpu/xburst2/ddr_innophy.c | 8 +++++++-
|
||||
arch/mips/cpu/xburst2/x2000/soc.c | 8 +++++++-
|
||||
2 files changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
index 4c7b921..b78c02b 100755
|
||||
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
|
||||
@@ -626,7 +626,13 @@ void sdram_init(void)
|
||||
ddr_hook->post_ddr_init(type);
|
||||
|
||||
ddr_diag_stage(8);
|
||||
- get_dynamic_calib_value(rate);
|
||||
+ /* Dropped get_dynamic_calib_value(rate): the vendor SPL does NOT do this multi-rate
|
||||
+ * DVFS calibration sweep. Its result table is never consumed by the burner/writer path,
|
||||
+ * and the extra frequency transitions + retraining can leave a marginal final PHY
|
||||
+ * calibration that fails under the writer's sustained full-DRAM load (2026-08-25). The
|
||||
+ * single ddrp_calibration() above already calibrates at the final 400MHz. */
|
||||
+ /* get_dynamic_calib_value(rate); */
|
||||
+ (void)rate;
|
||||
|
||||
if(DDRC_AUTOSR_EN_VALUE) {
|
||||
/* ddr_writel(DDRC_AUTOSR_CNT_VALUE, DDRC_AUTOSR_CNT); */
|
||||
diff --git a/arch/mips/cpu/xburst2/x2000/soc.c b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
index ab9e437..6ea4b83 100755
|
||||
--- a/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
+++ b/arch/mips/cpu/xburst2/x2000/soc.c
|
||||
@@ -83,7 +83,13 @@ void board_init_f(ulong dummy)
|
||||
|
||||
*(volatile unsigned int *)0xb0000020 = 0; //clk gate enable.
|
||||
*(volatile unsigned int *)0xb0000028 = 0; //clk gate enable.
|
||||
- *(volatile unsigned int *)0xb000202c |= 1 << 16; // wdt disable.
|
||||
+ /* Disable the watchdog ROBUSTLY (match the vendor SPL + the tree's hw_watchdog_disable):
|
||||
+ * clear WDT_TCER.TCEN FIRST, then stop the WDT clock via TCU_TSSR (write-1, no RMW).
|
||||
+ * The old code stopped only the clock, leaving the counter armed - if the mask ROM
|
||||
+ * re-clocks it after we return, it fires and resets the device mid-flash (root cause of
|
||||
+ * the 2026-08-25 flash failure: device reset ~36min into the writer and again idle). */
|
||||
+ *(volatile unsigned int *)0xb0002004 &= ~(1u << 0); // WDT_TCER.TCEN = 0 (disable counter)
|
||||
+ *(volatile unsigned int *)0xb000202c = (1u << 16); // TCU_TSSR: stop WDT clock
|
||||
|
||||
/* Init uart first */
|
||||
enable_uart_clk();
|
||||
--
|
||||
2.43.0
|
||||
|
||||
Reference in New Issue
Block a user