From 17db971b66b1770cdc5e997e54b856a68d3aa77a Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Fri, 25 Sep 2026 11:15:49 +0200 Subject: [PATCH] rk27xx: leave the SDRAM mode and timings as the boot left them Firmware builds reprogram the SDRAM controller twice. system_init() sets burst 8, T_RP = T_RCD = 1 and the refresh, with CAS 3 since a6538abd16 - CAS 2 on HM60X/HM801. And set_sdram_timing(), on every CPU frequency change, rewrites the mode: CAS 2 whenever the AHB runs at 100 MHz or below, which is every clock this code sets. On a generic rk2705 the firmware hangs in system_init() on those writes; with them skipped it boots. Doing the same writes from IRAM, so that nothing touches the SDRAM while the controller reprograms the chip, hangs the same way: it is the settings themselves. The board's SDRAM is an Elpida EDS1216AATA-75 (16 MB), a 133 MHz part at CAS 3 whose minimum clock period at CAS 2 is 10 ns - exactly the 100 MHz it runs at here, with no margin, next to minimal T_RP/T_RCD. On a Samsung YP-CP3 the firmware boots but corrupts memory at random once the clock first changes: data aborts on valid addresses in unrelated code, undefined instruction exceptions on valid instructions, glitches in the boot logo, crashes on USB plug and unplug. A memory test over 15 MB passes with the boot's setup (CAS 3, burst 1, T_RP = T_RCD = 2) and with system_init()'s values alike - it never changes the clock - and skipping only the system_init() writes is not enough, as set_sdram_timing() still selects CAS 2. With both removed the YP-CP3 runs, passes a USB mass storage stress test and survives USB unplug. The boot ROM's and the bootloaders' setup works on every rk27xx target seen, and nothing before Rockbox changes it (the NAND bootloader's stage 1 and rk27load's s1 only probe the organisation). The gain claimed for the tweak was a slight improvement in memory throughput. So remove it for every rk27xx target, the HM60X/HM801 CAS 2 included, and have set_sdram_timing() adjust only the refresh to the bus clock. Co-Authored-By: Claude Opus 5.5 Change-Id: Icd063367783b0ae6eb80bad67d908269c07e704f --- firmware/target/arm/rk27xx/system-rk27xx.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/firmware/target/arm/rk27xx/system-rk27xx.c b/firmware/target/arm/rk27xx/system-rk27xx.c index 6cbc3aa9ae..729b0c25a6 100644 --- a/firmware/target/arm/rk27xx/system-rk27xx.c +++ b/firmware/target/arm/rk27xx/system-rk27xx.c @@ -116,19 +116,6 @@ void system_init(void) WDTCON &= ~(1<<3); #ifndef BOOTLOADER - /* SDRAM tweaks. Note this assumes 100MHz AHB+SDRAM clock. */ - -#if !(defined(HM60X) || defined(HM801)) - MCSDR_MODE = (3<<4)|3; /* CAS=3, burst=8(2^3) -- Safe but slower */ -#else - MCSDR_MODE = (2<<4)|3; /* CAS=2, burst=8(2^3) -- Ideal but causes startup issues on (some?) IHIFI devices */ -#endif - - MCSDR_T_REF = (125*100) >> 3; /* 125/8 = 15.625 autorefresh interval */ - MCSDR_T_RFC = (64*100) / 1000; /* autorefresh period */ - MCSDR_T_RP = 1; /* precharge period */ - MCSDR_T_RCD = 1; /* active to RD/WR delay */ - /* turn off clock for unused modules - not the NAND controller's: the * FTL uses it, and a register access with its HCLK gated aborts */ SCU_CLKCFG |= CLKCFG_WDT | /* WDT pclk */ @@ -245,12 +232,8 @@ void commit_discard_dcache_range (const void *base, unsigned int size) #if !defined(BOOTLOADER) && defined(HAVE_ADJUSTABLE_CPU_FREQ) static inline void set_sdram_timing(int ahb_freq) { -#if 1 - if (ahb_freq > 100000000) - MCSDR_MODE = (3<<4)|3; /* CAS=3, burst=8(2^3) */ - else - MCSDR_MODE = (2<<4)|3; /* CAS=2, burst=8(2^3) */ -#endif + /* refresh only: the mode register - CAS latency - stays as the boot set + * it (see system_init()) */ MCSDR_T_REF = (125*ahb_freq/1000000) >> 3; MCSDR_T_RFC = (64*ahb_freq/1000000)/1000; }