RK3588 PCIe Not Detecting NVMe: A Step-by-Step Debug Checklist
NVMe missing from lsblk? Work through software, device tree, power/reset and signal integrity in the right order to find why the PCIe link isn't training.
An NVMe SSD that never shows up is one of the most common RK3588 bring-up problems, on custom carriers and on SBCs with the wrong DTB alike. Work through the layers in order: is the controller enabled → is the link up → is the device enumerated → is the driver bound.
Step 1: What does the kernel see?
lspci -nn # any device at all?
dmesg | grep -iE "pcie|nvme|phy"
ls /sys/bus/platform/drivers/rk-pcie/ 2>/dev/null # vendor kernel
ls /sys/bus/platform/drivers/rockchip-dw-pcie/ 2>/dev/null # mainline
- No PCIe messages at all: the controller node is disabled or the driver isn't built. Go to Step 2.
- Link training failure / "Link Fail" / timeout messages: the controller probed but no link. Go to Steps 3–5.
- Device in
lspcibut no/dev/nvme0n1: NVMe driver not loaded (CONFIG_BLK_DEV_NVME) or the device is a SATA M.2 SSD (see Step 6).
Step 2: Controller and PHY enabled in the device tree
RK3588 PCIe controllers (vendor and mainline dtsi):
| Node | Address | Type | PHY |
|---|---|---|---|
| pcie3x4 | fe150000 | PCIe 3.0 up to x4 | pcie30phy |
| pcie3x2 | fe160000 | PCIe 3.0 up to x2 | pcie30phy |
| pcie2x1l0 | fe170000 | PCIe 2.1 x1 | combphy1_ps |
| pcie2x1l1 | fe180000 | PCIe 2.1 x1 | combphy2_psu |
| pcie2x1l2 | fe190000 | PCIe 2.1 x1 | combphy0_ps |
Both the controller and its PHY must be status = "okay". Check the live tree:
cat /proc/device-tree/pcie@fe150000/status
dtc -I fs /proc/device-tree 2>/dev/null | grep -A20 "pcie@fe150000"
Note that RK3588S has no pcie3x4/pcie3x2. Only the 2.1 x1 controllers exist, and their combo PHYs are shared with SATA and USB 3, so the PHY must be configured for PCIe mode.
Step 3: Power and reset
&pcie3x4 {
reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; /* PERST#, match your schematic */
vpcie3v3-supply = <&vcc3v3_pcie30>;
status = "okay";
};
- Measure 3.3 V at the M.2 connector. If the regulator's enable GPIO is wrong, the SSD is simply unpowered.
- Scope PERST#: it must be held low while power and REFCLK stabilise, then released. A wrong GPIO or polarity leaves the device in reset.
- Some SSDs need a longer power-to-PERST delay; vendor kernels support properties to extend it.
Step 4: Lane configuration and bifurcation
The RK3588 PCIe 3.0 PHY can run as 1×4, 2×2 or 4×1 (x4 + x2 + two lanes shared via the x1 controllers). The PHY mode must match your board:
&pcie30phy {
/* vendor kernel example: select aggregation / bifurcation mode */
rockchip,pcie30-phymode = <PHY_MODE_PCIE_AGGREGATION>;
status = "okay";
};
Also check num-lanes / data-lanes on the controller match the lanes actually routed to your M.2 slot, and that any lane-reversal on the PCB is described.
Step 5: Signal integrity (force Gen2 / Gen1)
If the link trains at a lower speed but not at Gen3, you have a signal-integrity problem. Test by limiting speed:
&pcie3x4 {
max-link-speed = <2>; /* try 1 as well */
};
sudo lspci -vv | grep -E "LnkCap|LnkSta"
If Gen2 works reliably, review the layout: 85 Ω differential impedance, AC-coupling capacitors on TX (usually 220 nF), length matching within pairs, via count, connector quality, and the 100 MHz REFCLK path.
Step 6: Is it really an NVMe SSD?
M.2 B+M-keyed SATA SSDs fit in M-key NVMe slots but will never show up on PCIe. Check the label for "NVMe" or "PCIe". Conversely, a SATA SSD on a combo-PHY port needs that PHY in SATA mode and the sata node enabled.
Step 7: U-Boot vs Linux
If you boot from NVMe, U-Boot needs its own PCIe/NVMe support and DTS. Linux detecting the drive doesn't mean U-Boot does. Test in U-Boot with pci enum; nvme scan; nvme info.
Still stuck? Designing a custom RK3588 carrier with PCIe 3.0 x4 is exactly the kind of work where a review of your schematic and DTS saves a board spin. Talk to our engineering team.
¿Encontraste un error o quieres añadir algo? Sugerir una mejora.