Mainline Linux 7.1/7.2 on uConsole + Radxa CM5 — new panel working, sources published

Mainline Linux 7.1/7.2 on uConsole + Radxa CM5 — new panel working, sources published

Short version: mainline kernel, no BSP tree, on a uConsole with a Radxa CM5 — including the new December-2025 LCD (TXW500170B0-BL) that the existing drivers render as garbage. Display, GPU-accelerated Wayland, internal keyboard/trackball, NVMe, ethernet, charging, clean poweroff. Everything needed to reproduce it is here:

GitHub - tdeval/uconsole-radxa-cm5-mainline: WIP support for the Radxa CM5 module on the ClockWork µConsole with its post 2025 panel · GitHub

I know a few people have got 7.1 booting recently, but as far as I can tell nobody’s published the sources — and having watched the threads where people are stuck, that seemed like the gap worth filling. Device tree, panel driver, kernel config fragment, build script, and a long troubleshooting doc are all in the repo.


Why mainline works now

RK3588s DSI support landed upstream in pieces during 2025 — the Samsung MIPI D/C-PHY driver around 6.15, then the DSI2 controller and its DT nodes in 6.16. By 7.1 the whole chain is present and stable, and rk3588s-radxa-cm5.dtsi is upstream too. So the only things missing for a uConsole are a panel driver and a board device tree.

What works

LCD — TXW500170B0-BL (new) :white_check_mark:
LCD — TXW500170B0 (original) :warning: auto-detected, code path there, untested — please report
GPU — Mali-G610, panthor + Mesa panfrost :white_check_mark: glmark2 2270 fullscreen at native res
Wayland — sway, labwc :white_check_mark:
Internal keyboard + trackball :white_check_mark:
Ethernet, eMMC, microSD, USB :white_check_mark:
NVMe (HackerGadgets board) :white_check_mark: Gen2 x1, Samsung SM981
Battery charging :white_check_mark:
Poweroff / reboot :white_check_mark: (with the included shutdown hook)
HDMI :white_check_mark: under Wayland, hotplug included — :warning: console needs it connected at boot
Backlight brightness :warning: on/off only — dimming needs an OCP8178 driver port
Orange charge LED :cross_mark: dark (charging itself is fine)
WiFi USB dongle (RTW88 configs included); CM5 has no onboard radio
Audio :cross_mark: not attempted

One workaround is required: the first DSI enable at boot wedges the controller and you get a grey screen. A one-shot systemd service that blanks/unblanks fb0 at boot fixes it completely. Details below — I think it’s a genuine mainline dw-mipi-dsi2 bug, not board-specific. It looks like this:

[ 1.406] panel-cwu50 fde30000.dsi.0: GPIO probe: new panel (final check at prepare)
[ 1.580] dw-mipi-dsi2 fde30000.dsi: command interface is busy
[ 1.580] dw-mipi-dsi2 fde30000.dsi: failed to write command header
         ...~4 seconds of that, once per init command...
[ 5.728] panel-cwu50 fde30000.dsi.0: failed to exit sleep mode (-110)
[15.100] panel-cwu50 fde30000.dsi.0: panel: TXW500170B0-BL (new)   ← after the kick, fine

Tested on: uConsole (2026), Radxa CM5, HackerGadgets adapter + NVMe board, Arch Linux ARM, Mesa 26.1.4, panthor 1.8.0.

Dual display works properly under Wayland — each output at its own native resolution with its own transform, and HDMI hotplug is picked up mid-session:

DSI-1      720x1280   transform=90       → logical 1280x720
HDMI-A-1   1280x1024  transform=normal

The boot console is a different story: fbcon drives a single framebuffer cloned to both outputs and its rotation is global, so one of the two is always crooked, and it won’t re-probe a monitor plugged in after boot. Cosmetic — it’s only the boot console.

Also works on 7.2. I’ve since built and booted 7.2.0 from a clean linux-7.2.y checkout — same driver, same DTS, same Kconfig/Makefile one-liners, no changes at all, and the panel is detected identically. That portability is the whole argument for being on mainline rather than a vendor tree.


The five things that cost me the most time

Full write-up in docs/troubleshooting.md — these are the highlights.

1. Don’t put earlycon on the cmdline. It touches UART4’s registers before its clock is ungated and hard-hangs the boot: no output anywhere, static LED, nothing. Cost me a day of thinking the kernel was broken. console=ttyS4,1500000 on its own is fine.

2. root=UUID= doesn’t work without an initramfs. A bare kernel can’t resolve filesystem UUIDs — only /dev/..., PARTUUID=, PARTLABEL=. The vendor entries get away with it because they ship an initramfs.

3. “The kernel doesn’t boot” was the kernel booting fine. Mainline renames the NIC (end0) with a different MAC, so the DHCP server hands out a different IP. It was up, sshd was listening, I was knocking on the old address. If the status LED heartbeats and the ethernet link blinks, it’s alive — go look at your router’s lease table.

4. Reboot/poweroff hung until I disabled the PCIe SMMU. device_shutdown() freezes on arm-smmu-v3 fc900000.iommu: shutdown (MMU600 wired-IRQ erratum territory). &mmu600_pcie { status = "disabled"; } fixes it, and PCIe/NVMe works perfectly without it. Found via netconsole + initcall_debug, which prints each device’s name right before calling its shutdown callback — the last name in the stream is your culprit.

5. Panel revision detection is inverted from intuition. The reset GPIO is GPIO_ACTIVE_LOW, the new panel pulls RESX physically low, and gpiod_get_value() returns the logical level — so the new panel reads 1. I “fixed” this the wrong way round and spent a build cycle on a grey screen. Also: the RDID confirmation from the RPi driver doesn’t port — you get 93 00 00 on the Rockchip DSI2 read path, not 0x39.

Bonus, because it saved the whole project: you can read a failed boot’s log from your fallback kernel. journalctl --list-boots, then journalctl -b -1 -k. And if it won’t boot at all, pull the card and journalctl --root=/mnt -b -1 -k from another machine. No serial cable needed for most of this.


Serial console, if you do want one

The SoC’s default debug UART (uart2) routes to Mini-PCIe on this chassis and never reaches the GPIO header. UART4 with the m2 pinmux does:

uConsole pin Signal Adapter
23 UART4 TX RX
19 UART4 RX TX
25 GND GND

1,500,000 baud, not 115200 — PL2303x and CH340 adapters can’t do it. CP2102N, FT232H or CH343P.


Deploying safely

Please install this alongside your working kernel as a second extlinux.conf entry and leave the old one intact. That’s how the whole thing was developed: BSP image as fallback, mainline as a second entry, iterating over SSH. If it doesn’t boot, put the card in another machine and change one line back.

Also worth knowing: there are three artifacts — Image, the DTB, and modules — and deploying a stale one fails silently. I lost an evening to “PCIe isn’t working” when I’d rebuilt the config but not redeployed the DTB. tr -d '\0' < /sys/firmware/devicetree/base/pcie@fe190000/status tells you what the kernel is actually running.



Credits

The panel init sequences are @ak-rexs work from the ClockworkPi RPi tree — both the or@ak-rexginal and the new-panel variants, plus the GPIO-based revision detection. Without that driver none of this would exist; my part is the port to the mainline panel API, the device tree, and the integration@dev-null2019 The @dev-null2019 Radxa CM5 overlays were how I worked out the hardw@dev-null2019re mapping, and randomlinuxuser’s Arch image was the fallback system throughout.


Questions welcome. If you have the original (pre-2025) panel I’d particularly like to know whether auto-detection picks it up correctly — dmesg | grep cwu50 will say which sequence it chose.

8 Likes

This is a very hardcore technical post, worthy of a thumbs up.:+1:

1 Like

That’s huge, thank you very much! :folded_hands::folded_hands::folded_hands::rocket:

1 Like