PCIe 驱动
本文档介绍 RK3588 PCIe 控制器在 Linux 6.1 内核中的驱动配置、设备树绑定、lspci 调试和常见 PCIe 设备识别。
适用范围: RK3588 Linux 6.1 Debian 12 / Ubuntu 22.04 系统,C-3588LQ V1.0 + SHIMETAPI-M5-R2A V1.0 底板。
1. 概念基础
1.1 PCIe 是什么
PCIe(Peripheral Component Interconnect Express)是点对点高速串行总线,电脑里的显卡、NVMe 固态硬盘都靠它和主控相连。RK3588 内置多路 PCIe 控制器:
| 控制器 | 规格 | 通道数 |
|---|---|---|
| PCIe 2/3 | PCIe 4.0 | 最多 4 lanes |
| PCIe 0/1 | PCIe 3.0 | 2 lanes |
PCIe 2/3 最高 16 GT/s,PCIe 0/1 最高 8 GT/s。GT/s 是每秒传输次数,衡量 PCIe 速度的基本单位;lane(通道)是 PCIe 最小的数据通路,多条 lane 并行可成倍提高带宽。
1.2 应用场景
- NVMe SSD(Key-M 插槽)
- PCIe WiFi 6/6E 模块(Key-E)
- 外置 2.5G / 10G 以太网
- 4G/5G PCIe 模块
- GPU 扩展(受带宽限制)
2. 准备工作
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3588LQ 核心板 + SHIMETAPI-M5-R2A 底板 | 1 | 内置 PCIe PHY |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| PCIe 设备(可选) | NVMe SSD / WiFi / 网卡 等 | 1 | 按 M.2 Key 选 |
2.2 引脚
底板上 M.2 Key-M(SSD)和 Key-E(WiFi)插槽已直接引出,无需额外接线。M.2 插槽按 Key 区分用途:Key-M 一般插 SSD,Key-E 插 WiFi 模块,购买设备时注意对上。
3. 软件准备
3.1 内核配置
除了 PCIe 控制器本身,记得把要用的设备驱动也配上:
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_ROCKCHIP=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
# 常见 PCIe 设备:
CONFIG_BLK_DEV_NVME=y
CONFIG_RTW88=y /* PCIe WiFi (Intel AX210) */
CONFIG_NET_DSA=y3.2 设备树
每个 PCIe 控制器在设备树里占一个节点,pcie0 属于 PCIe 3.0 那组,pcie2 是 PCIe 4.0 四通道那组:
/ {
pcie0: pcie@fe180000 {
compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
reg = <0x0 0xfe180000 0x0 0x10000>;
reg-names = "config";
#address-cells = <3>;
#size-cells = <2>;
ranges = <0x82000000 0x00 0xfa000000 0x00 0xfa000000 0x00 0x1000000
0xc3000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
phys = <&pcie0_phy>;
phy-names = "pcie-phy";
power-domains = <&power RK3588_PD_PIPE>;
clocks = <&cru PCLK_PCIE0>, <&cru CLK_PCIE_AUX0>;
clock-names = "pclk", "aux";
resets = <&cru SRST_PCIE0>;
reset-names = "pipe";
status = "okay";
};
pcie2: pcie@fe190000 {
/* PCIe 4.0,4 lanes */
compatible = "rockchip,rk3588-pcie", "snps,dw-pcie";
reg = <0x0 0xfe190000 0x0 0x10000>;
/* ... 类似 pcie0 ... */
status = "okay";
};
};RK3588 PCIe 控制器基地址:PCIe2@fe190000、PCIe3@fe1a0000(PCIe 4.0)。
4. 设备端 PCIe
以下命令都在板子上执行,重点看两件事:设备有没有被枚举到、链路速率协商到了多少。
4.1 当前拓扑
lspci实机输出:
0002:20:00.0 PCI bridge: Rockchip Electronics Co., Ltd RK3588 (rev 01)
0002:21:00.0 Ethernet controller: Motorcomm Microelectronics. YT6801 Gigabit Ethernet Controller (rev 03)
0004:40:00.0 PCI bridge: Rockchip Electronics Co., Ltd RK3588 (rev 01)
0004:41:00.0 Processing accelerators: Rockchip Electronics Co., Ltd Device 182a (rev 01)每行开头的 0002:21:00.0 是 BDF 地址(总线:设备:功能),可以理解为设备的门牌号,后面命令都用它指定设备。本机 PCIe 拓扑:
- 0002:20/21:Slot 0 上接 YT6801 千兆网卡(Motorcomm)
- 0004:40/41:Slot 1 上接 Rockchip 自家加速设备(
182a是 NPU / VPU 类)
4.2 链路速度与宽度
lspci -vv -s 0002:21.0实机输出节选:
LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1
LnkSta: Speed 2.5GT/s, Width x1LnkCap 是设备的能力上限,LnkSta 是当前实际协商结果,对比着看就知道链路有没有跑满:
YT6801 实际协商速度 2.5 GT/s × 1 lane(理论上可达 5 GT/s,受 PCIE 协商与硬件走线限制)。
lspci -vv -s 0004:41.0实机输出节选:
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L1
LnkSta: Speed 2.5GT/s, Width x1第二路 PCIe 协商 2.5 GT/s × 1 lane。
4.3 探测 NVMe 设备(如果有)
lspci -nn | grep -i nvme
# 例:01:00.0 Non-Volatile memory controller [0108]: Samsung Electronics NVMe SSD Controller [144d:a808]
# 块设备名
lsblk | grep nvme4.4 PCIe 拓扑
树状视图更直观:
lspci -tv输出示例:
-[0000:00]-
\-02.0-[0002]----00.0-[0002:21]----00.0 YT6801
\-04.0-[0004]----00.0-[0004:41]----00.0 RK3588 Device 182a5. 内核调试
5.1 PCIe AER 错误
AER(Advanced Error Reporting)是 PCIe 的高级错误报告机制,链路上的纠错和故障都会记下来:
# 检查 PCIe 高级错误报告(AER)
lspci -vv | grep -i "AER\|corrected\|uncorrected"
# dmesg 找 AER 报错
dmesg | grep -i aer5.2 电源管理 / ASPM
ASPM(Active State Power Management)是 PCIe 的链路省电机制,空闲时自动降低链路状态:
# 查看 ASPM 状态
find /sys/bus/pci -name power -type d | xargs -I{} sh -c 'echo {}; cat {}/control'
# 手动开启 / 关闭 ASPM
echo auto > /sys/bus/pci/devices/0002:21:00.0/power/control
echo on > /sys/bus/pci/devices/0002:21:00.0/power/control5.3 速度强制(debug)
怀疑高速率下不稳定时,可以强制降速来复现问题:
# 强制 PCIe 2.0(5 GT/s → 2.5 GT/s)用于测试
echo 2 > /sys/bus/pci/devices/0002:20:00.0/link_speed6. 用户态设备操作
6.1 NVMe SSD(如有)
拿到 /dev/nvme0n1 之后就是常规的分区、格式化、挂载流程:
# 分区
fdisk /dev/nvme0n1
mkfs.ext4 /dev/nvme0n1p1
mount /dev/nvme0n1p1 /mnt/nvme
# 性能测试
hdparm -t /dev/nvme0n1
dd if=/dev/zero of=/mnt/nvme/test bs=1M count=1024 conv=fdatasync6.2 YT6801 PCIe 网卡
# 确认驱动已加载(Motorcomm)
lsmod | grep -i yt6801
# 网卡设备
ip link show
# 输出:ethX(具体名以 udev 分配为准)
# 测速(如驱动支持)
iperf -c <iperf_server_IP>6.3 PCIe WiFi
# Intel AX210 / 类似 PCIe WiFi 模块(rtw88 驱动)
modprobe rtw88
ip link
# 应出现 wlanX
iw dev7. 设备树微调(PC 端)
如需禁用某路 PCIe 用于省电 / 排查:
&pcie0 {
status = "disabled"; /* 完全关闭 bus */
};如需限制最高速率:
&pcie2 {
num-lanes = <2>; /* 强制 2 lanes(原可能为自动协商) */
max-link-speed = <2>; /* PCIe Gen2 = 5 GT/s,1 = Gen1 = 2.5 GT/s */
};电脑端 重编译烧录:
./build.sh kernel
./mkfirmware.sh8. 代码解读
8.1 内核驱动注册
PCIe 控制器驱动同样是 platform driver,按 compatible 匹配设备树节点:
// drivers/pci/controller/dwc/pcie-dw-rockchip.c(简化)
static const struct of_device_id rk_pcie_of_match[] = {
{ .compatible = "rockchip,rk3588-pcie" },
{ /* sentinel */ }
};
static struct platform_driver rk_pcie_driver = {
.probe = rk_pcie_probe,
.remove = rk_pcie_remove,
.driver = {
.name = "rk-pcie",
.of_match_table = rk_pcie_of_match,
},
};8.2 PCIe 枚举调用链
开机时内核扫描并识别 PCIe 设备的全过程:
内核启动
→ pcie_bus_scan()
→ rk_pcie_init() /* Rockchip 控制器 probe */
→ of_pci_msi_init() /* MSI 中断初始化 */
→ pci_scan_single_device()
→ 读取 PCIe 配置空间
→ 识别 vendor/device ID
→ 加载匹配驱动9. 故障排除
9.1 设备不识别
dmesg | grep -i pcie
lspci设备树 status = "disabled" 或 PCIe PHY 未配置都可能导致不识别。
9.2 链路协商失败 / 速度低
lspci -vv -s <BDF> | grep -i LnkSta
dmesg | grep -i "link training\|speed\|width"排查:
- 硬件焊接 / FPC 接触
- PHY 供电及时钟
- DTS
max-link-speed/num-lanes
9.3 NVMe / WiFi 模块被探测但驱动未加载
lspci -k | grep -i nvme # 是否有内核中的驱动?如未加载,安装对应驱动模块或 modprobe。
