====== DDR Frequency Switching on PineTab2 / RK3566 (LPDDR4) ====== This page documents how to change the **DDR frequency** on the **Pine64 PineTab2 v2.0** (Rockchip **RK3566**, **8 GB LPDDR4** as 2x 4 GB) by swapping the rkbin TPL DDR-init blob, and records the **production-stable 1332 MT/s** operation observed on **ohm** (mfritsche's PineTab2 v2.0). Sibling page: [[megabitchip:ddr_frequency_switching|DDR frequency switching on RK3588 (LPDDR5)]] — same methodology framework, RK3588-/LPDDR5-specific blobs and offsets. Read both if you are working across the family. **Flashing a bad DDR blob bricks boot.** Recovery requires either booting from an SD card with a known-good ''idbloader.img'' (PineTab2 boots SD before eMMC) or putting the tablet into **MASKROM** mode and reflashing over USB from a host machine. A dedicated MASKROM-recovery page does not yet exist on this wiki — **TODO**: create ''megabitchip:maskrom_recovery'' (both the RK3588 and RK3566/PineTab2 mechanisms differ — PineTab2 has a dedicated **MASKROM hardware switch**, unlike the PinePhone and earlier Pine64 devices which rely on shorting a flash pin). ===== 1. Stock and observed frequencies ===== ==== Stock ==== The danctnix ''uboot-pinetab2'' package (version **2026.04-4** at time of writing) ships with ''rk3566_ddr_1056MHz_v1.23.bin'': ^ Blob ^ DPLL ^ Data Rate ^ BW/ch ^ Status ^ | ''rk3566_ddr_1056MHz_v1.23.bin'' | 528 MHz | **1056 MT/s** | ~4.2 GB/s | danctnix default | ==== Verified upgrade ==== ^ Blob ^ DPLL ^ Data Rate ^ BW/ch ^ Status ^ | ''rk3568_ddr_1332MHz_v1.23.bin'' | 666 MHz | **1332 MT/s** | ~5.3 GB/s | **VERIFIED stable on ohm** | **+26 % memory bandwidth** vs. stock, currently running on ohm. Validation: 50+ minutes of ''memtester 4G 1'' with all 10+ completed patterns clean (Stuck Address, Random Value, Compare XOR/SUB/MUL/DIV/OR/AND, Sequential Increment, Solid Bits, partial Block Sequential), no EDAC / MCE / kernel panic in dmesg. ==== Hardware ceiling ==== **1332 MT/s is the documented ceiling for this silicon.** Both ''rk3568_ddr_1560MHz_v1.23.bin'' and ''rk3568_ddr_1560MHz_D4_LP4_4x_eyescan_v1.23.bin'' were tested with structurally-validated SPL packaging (see §4) and **do not train** on RK3566 — ohm fails to boot, no recovery without MASKROM. Do not waste a session on 1560. ===== 2. Available rkbin v1.23 blobs for RK3566 ===== From ''~/src/rkbin/bin/rk35/'' on ohm (and on a clone of [[https://github.com/rockchip-linux/rkbin|rockchip-linux/rkbin]]): ^ Blob ^ Rate ^ Notes ^ | ''rk3566_ddr_528MHz_ultra_v1.10.bin'' | 528 MT/s | very low | | ''rk3566_ddr_780MHz_ultra_v1.10.bin'' | 780 MT/s | low | | ''rk3566_ddr_920MHz_ultra_v1.10.bin'' | 920 MT/s | older | | ''rk3566_ddr_920MHz_v1.23.bin'' | 920 MT/s | v1.23 conservative | | ''rk3566_ddr_1056MHz_ultra_v1.20.bin'' | 1056 MT/s | alt | | **''rk3566_ddr_1056MHz_v1.23.bin''** | **1056 MT/s** | **danctnix default** | | ''rk3568_ddr_920MHz_v1.23.bin'' | 920 MT/s | RK3568 cross-blob, works on RK3566 | | ''rk3568_ddr_1056MHz_v1.23.bin'' | 1056 MT/s | RK3568 cross-blob | | **''rk3568_ddr_1332MHz_v1.23.bin''** | **1332 MT/s** | **VERIFIED on PineTab2 — recommended** | | ''rk3568_ddr_1560MHz_v1.23.bin'' | 1560 MT/s | does NOT train on RK3566 silicon | | ''rk3568_ddr_1560MHz_D4_LP4_4x_eyescan_v1.23.bin'' | 1560 MT/s | does NOT train (eyescan variant tried) | The ''rk3568_'' blobs work on RK3566 because the two SoCs share their DDR controller IP; the rkbin RK3568 toolchain happens to ship the higher frequency points the RK3566 line does not. ===== 3. Build recipe (mkimage -T rksd) ===== The danctnix ''idbloader.img'' is a Rockchip RKSD container with two parts: the **DDR init blob** (TPL, 4 KB scrambled header + payload) and the **SPL** (U-Boot SPL stage). To switch frequency, repack the same SPL with a different DDR blob. DDR=~/src/rkbin/bin/rk35/rk3568_ddr_1332MHz_v1.23.bin # or 1056/920/780/528 etc. SPL=~/ohm-recovery/uboot-spl-correct.bin # extracted from danctnix # idbloader.img with skip=61440 mkimage -n rk3568 -T rksd -d $DDR:$SPL \ ~/ohm-recovery/idbloader-1332-FIXED.img The ''-n rk3568'' name argument is correct even on RK3566 — the rkbin TPL key matches the RK3568 line. The output is bit-for-bit consumable by the BootROM the same way the danctnix ''idbloader.img'' is. ===== 4. Critical SPL-extraction gotcha ===== **The ''dd skip='' for extracting the SPL from danctnix ''idbloader.img'' must be exactly 61440 (= sector 120 × 512), NOT 63488.** Sector 120 is recorded in the **RKNS header at byte 0xd0** of the danctnix ''idbloader.img''. Naively assuming a 4-sector pad-up of the DDR region (which would land at 63488) silently truncates the SPL by **2 KB**, and the resulting ''idbloader.img'' bricks on flash — **looking exactly like a DDR-training failure** at the device. ==== Validation procedure ==== To prove that a freshly-extracted SPL + your packaging recipe are **structurally sound** before risking a frequency change, build a 1056 variant **with the same SPL+recipe** and confirm: md5sum ~/ohm-recovery/idbloader-1056-FIXED.img # must equal: ceb4d3fdfb7252e0815d24694e9043b4 (the danctnix golden) If the md5 matches, the SPL extraction and ''mkimage'' recipe are correct, and **only the DDR portion** can fail at the device. If the md5 does not match, the SPL is wrong — fix the extraction first; do not flash. This is the procedure that retroactively explained ohm's 1560 MT/s bricking as a genuine DDR-training failure (and not an SPL truncation), because the parallel 1056-FIXED build matched the danctnix golden md5 byte-for-byte. ===== 5. Flash procedure (eMMC, danctnix layout) ===== Two raw offsets in the pre-GPT region (GPT starts at sector 65536): ^ Component ^ eMMC sector ^ Byte offset ^ | ''idbloader.img'' | 64 | 32 KB | | ''u-boot.itb'' | 16384 | 8 MB | ==== Path A — boot-from-SD (safest) ==== - Write the new ''idbloader--FIXED.img'' to a danctnix-bootable SD card's sector 64. - Insert SD into PineTab2, power on. The PineTab2 BootROM tries SD before eMMC, so a bad DDR blob on SD **cannot** brick the device — just remove the SD and the eMMC keeps booting. - If SD boots successfully, you have validated the blob on this physical hardware. Now mirror to eMMC (Path B). ==== Path B — direct eMMC write from a running ohm ==== sudo dd if=~/ohm-recovery/idbloader-1332-FIXED.img \ of=/dev/mmcblk0 bs=512 seek=64 count=420 conv=fsync sudo cp ~/ohm-recovery/idbloader-1332-FIXED.img /boot/idbloader.img sudo sync sudo reboot The ''/boot/idbloader.img'' copy keeps initramfs-rebuild / kernel-package hooks consistent with the on-disk raw region. **Failure mode for Path B = MASKROM + meitner.** Do not skip Path A on the first build of a frequency you have not previously verified. ===== 6. Recovery procedures ===== ==== 6.1 SD-boot recovery (preferred) ==== From a danctnix-bootable SD on ohm: sudo dd if=/path/to/idbloader-1056-FIXED.img \ of=/dev/mmcblk0 bs=512 seek=64 count=420 conv=fsync sudo cp /path/to/idbloader-1056-FIXED.img /boot/idbloader.img sudo sync sudo reboot Remove the SD before reboot completes so the device boots from the freshly-rewritten eMMC. ==== 6.2 MASKROM + rkdeveloptool from meitner (flaky) ==== - Trigger MASKROM via the **dedicated MASKROM hardware switch** on the PineTab2. //(This is the one significant divergence from PinePhone / earlier Pine64 devices, which rely on shorting a flash pin or holding a button — note this clearly when documenting recovery for future readers.)// - On meitner, build [[https://github.com/rockchip-linux/rkdeveloptool|rockchip-linux/rkdeveloptool]] **from master**. The prebuilt ''rkdeveloptool 1.32'' has trouble with NEWIDB v1.23 blobs — the ''wl'' step succeeds maybe half the time. Be prepared to retry. - Push the loader and write the idbloader: # On meitner, with PineTab2 in MASKROM connected over USB-C: rkdeveloptool db MiniLoaderAll.bin # wait ~15-20 s for USB-MSC to come up rkdeveloptool wl 64 idbloader.img rkdeveloptool rd 0 ''MiniLoaderAll.bin'' is the Pine64-supplied loader from [[https://pine64.org/documentation/PineTab2/files/MiniLoaderAll.bin.zip|pine64.org]]. ===== 7. Runtime DVFS ===== **Mainline kernel does NOT have a DMC devfreq driver wired for the PineTab2 DT.** Whatever frequency the TPL programs at boot is the steady-state frequency. There is **no runtime scaling** and **no runtime safety net** that would drop to a lower step if the chosen frequency becomes unstable. Treat the boot blob as the only frequency the system will ever see. ===== 8. Safety notes ===== * **Always run the §4 md5 validation.** A mis-extracted SPL fails identically to a mis-trained DDR — you will misdiagnose for hours otherwise. * **Always do Path A (SD boot) before Path B (direct eMMC)** for any frequency you have not previously verified on the specific physical device. * **1332 is the ceiling.** Do not retry 1560 expecting a different result on PineTab2 silicon. * **No DMC devfreq on mainline = boot frequency is forever.** No kernel-side fallback if a marginal blob is silently flaky under thermal stress months later. * **Thermals matter.** 1332 MT/s raises per-channel bandwidth ~26 % over the 1056 MT/s default; sustained-load temps should be checked before declaring stable in a hot ambient. ===== See also ===== * [[megabitchip:start|MegabitChip running index]] * [[megabitchip:ddr_frequency_switching|DDR frequency switching on RK3588 (LPDDR5)]] — sibling page, same framework, different SoC family * [[https://github.com/rockchip-linux/rkbin|rockchip-linux/rkbin]] — upstream Rockchip blob repo * [[https://github.com/rockchip-linux/rkdeveloptool|rockchip-linux/rkdeveloptool]] — MASKROM USB tool (build from master, 1.32 prebuilt is flaky on NEWIDB v1.23) * [[https://pine64.org/documentation/PineTab2/files/MiniLoaderAll.bin.zip|MiniLoaderAll.bin]] — Pine64-supplied MASKROM loader for PineTab2 * **TODO:** ''megabitchip:maskrom_recovery'' (not yet created) — full MASKROM recovery procedure for both RK3588 and RK3566/PineTab2 (note the PineTab2-unique hardware MASKROM switch)