This page documents how to change the DDR frequency on RK3588 platforms (as shipped by the rkbin DDR init blob) and records the observed LPDDR5-6400 / 3200 MHz operation on ampere (CoolPi CM5 GenBook, 32 GB LPDDR5).
Source material: the public
DDR_FREQUENCY_TABLE.md
in the rk3588-ddr-analysis repo. Reverse-engineered DFS entry point
is tracked in the memory note project_rk3588_ddr_dfs_entry.md.
<WRAP round important>
Flashing a bad DDR blob bricks boot. Recovery requires putting the
board into maskrom mode and reflashing over USB. Always keep a known-good
blob image handy before experimenting. A dedicated MASKROM recovery page does
not yet exist on this wiki — TODO: create megabitchip:maskrom_recovery.
</WRAP>
| Version | LP4 Freq | LP5 Freq | LP5 Data Rate | LP5 BW/ch | Status |
|---|---|---|---|---|---|
| v1.09 | 2112 MHz | 2736 MHz | 5472 MT/s | 10.9 GB/s | Oldest available |
| v1.10–v1.14 | 2112 MHz | 2736 MHz | 5472 MT/s | 10.9 GB/s | Iterative fixes |
| v1.15 | 2112 MHz | 2736 MHz | 5472 MT/s | 10.9 GB/s | Last 2736 blob |
| v1.16 | 2112 MHz | 2400 MHz | 4800 MT/s | 9.6 GB/s | 2736 dropped |
| v1.17–v1.19 | 2112 MHz | 2400 MHz | 4800 MT/s | 9.6 GB/s | Current |
| v1.19 (cons.) | 1848 MHz | 2112 MHz | 4224 MT/s | 8.4 GB/s | Conservative |
| LP5 Freq | Data Rate | BW/ch | Source | Stability |
|---|---|---|---|---|
| 2112 MHz | 4224 MT/s | 8.4 GB/s | Official conservative | Rock solid |
| 2400 MHz | 4800 MT/s | 9.6 GB/s | Official default | Stable |
| 2736 MHz | 5472 MT/s | 10.9 GB/s | Old official (v1.15) | Dropped by Rockchip |
| 3200 MHz | 6400 MT/s | 12.8 GB/s | Community (hbiyik rkddr) | Works with SK Hynix rated modules |
The simplest approach: pick a pre-built blob and use it verbatim.
Drop the chosen rk3588_ddr_*.bin into rkbin/bin/rk35/ and rebuild
idbloader.img. No byte-level editing needed.
https://github.com/hbiyik/rkddr — a TUI that edits DDR blob parameters (frequency, ODT, drive strength) directly on the board and writes the modified blob back into the IDB (eMMC / SPI flash). This is the documented path to the 3200 MHz community setting.
Shipped in rkbin/tools/. Official configurator for frequency, channel
config, ODT, drive strength. Operates on a blob file before flashing.
The code is identical across all frequency variants — only timing parameter bytes differ.
LP5 timing word, 32-bit little-endian:
| LP5 Frequency | Timing Value | Blob Offset |
|---|---|---|
| 2112 MHz | 0x00216840 | 0x11BF4 (v1.19) |
| 2400 MHz | 0x00216960 | 0x11BF4 (v1.19) |
| 2736 MHz | 0x00210AB0 | 0x10F64 (v1.15) |
LP4 timing word:
| LP4 Frequency | Timing Value | Blob Offset |
|---|---|---|
| 1848 MHz | 0x00210738 | 0x11B8C (v1.19) |
| 2112 MHz | 0x00210840 | 0x11B8C (v1.19) |
Six bytes in the data section — get them wrong and the board does not complete DDR training.
The TPL blob trains six frequency steps (main + five alternatives) and
writes the pre-trained results to PMU GRF OS registers for the Linux
side to consume. Runtime DDR frequency transitions (DVFS) are dispatched
through the vector at blob+0x34 → FUN_10978, invoked by the M0
coprocessor under BL31 on a DVFS event.
Caveat on ampere: the current mainline kernel on ampere has no DMC
devfreq driver wired, so FUN_10978 is dormant at runtime —
whatever frequency the blob sets at boot is the steady-state frequency.
Backlink: memory note project_rk3588_ddr_dfs_entry.md.
Setup: ampere (CoolPi CM5 GenBook, RK3588, 32 GB LPDDR5, SK Hynix
module). The blob was reconfigured via the community rkddr TUI to
LPDDR5-6400 (3200 MHz clock, 6400 MT/s, ~12.8 GB/s per channel).
Ampere runs at this setting stably in daily use.
Why it works: LPDDR5-6400 is the JEDEC ceiling for LPDDR5 (LPDDR5X
extends beyond but is not populated on RK3588). Ampere's DRAM is SK Hynix
LPDDR5, rated for the 6400 MT/s grade per JEDEC. The combination of
(a) rated modules and (b) community-tuned timings from rkddr is the
documented path to this clock.
Pending capture on the next bench-on session — not verification (the 3200 MHz operation is already established), just useful data points to preserve alongside this entry:
sudo dmidecode -t memory (or decode the SPD/JEDEC ID from DT if dmidecode is sparse on this platform).dmesg | grep -iE “ddr|dram|lpddr” at boot.cat /sys/bus/platform/drivers/rockchip-dmc/dmc/devfreq/dmc/available_frequencies (likely ENOENT since DMC devfreq is not wired on mainline — worth confirming).…/devfreq/dmc/cur_freq readback.stressapptest runtime hours logged at 3200 MHz.idbloader.img. Keep the previous working idbloader.img on a USB stick.megabitchip:maskrom_recovery (not yet created) — recovery procedure when a bad blob blocks boot