RK3588 kernel-6.1 drivers/pci 总线架构分析
1. 分析范围
本文聚焦:
rk3588/kernel-6.1/drivers/pci
目标是解释:
- PCI/PCIe 在 Linux 设备模型中的总线角色
- Root Complex(RC)从 host bridge 注册到设备枚举、资源分配、驱动绑定的主链路
- RK3588 平台的 Rockchip PCIe Host 控制器实现(DesignWare 路线)
- 开发和排障时应关注的关键点
2. drivers/pci 的分层结构
从 drivers/pci/Makefile 可见,PCI 子系统分为几层:
- 总线核心层
pci-driver.c、probe.c、bus.c、setup-bus.c、setup-res.c- 负责总线对象、枚举、资源分配、驱动绑定。
- 配置与能力层
pcie/、msi/、ats.c、iov.c、quirks.c- 负责 PCIe 特性、MSI/MSI-X、SR-IOV、quirk 修复。
- 固件/平台接口层
of.c、pci-acpi.c、ecam.c- 对接 DT/ACPI/ECAM 配置空间访问。
- 控制器驱动层
controller/- 各 SoC 的 PCIe Host/EP 驱动,RK3588 重点在
controller/dwc/pcie-dw-rockchip.c。
可归纳为:PCI core 定义“总线规则”,平台 RC 驱动负责“硬件落地”。
3. PCI 总线对象与驱动模型
在 pci-driver.c 里:
struct bus_type pci_bus_type定义了 PCI 总线.match = pci_bus_match.probe = pci_device_probe.remove = pci_device_remove.dma_configure = pci_dma_configure
__pci_register_driver()把pci_driver挂到pci_bus_type。
这意味着 PCI 驱动与 I2C/SPI 一样,都走 Linux 统一 device model,只是匹配规则基于 vendor/device/class ID 表。
4. Host 到枚举到绑定的主调用链
4.1 Host bridge 启动
典型平台驱动最终调用:
pci_host_probe(bridge)(probe.c)
pci_host_probe() 关键步骤:
pci_scan_root_bus_bridge(bridge):扫描 root bus- 根据
PCI_PROBE_ONLY决定pci_bus_claim_resources()(沿用固件资源)- 或
pci_bus_size_bridges()+pci_bus_assign_resources()(内核重分配)
pci_bus_add_devices():把枚举到的设备正式 add/attach 到驱动模型
4.2 扫描细节
pci_scan_root_bus_bridge() 内部调用:
pci_register_host_bridge()pci_scan_child_bus()
pci_scan_child_bus() 再递归桥设备(pci_scan_bridge())形成整棵 PCI 拓扑树。
4.3 设备 attach
bus.c 中 pci_bus_add_devices() 会遍历 bus->devices:
- 调
pci_bus_add_device() - 最终
device_attach(&dev->dev)触发与pci_driver的匹配/绑定
这一步之后,网卡/存储/NVMe/Wi-Fi 等 PCI 设备驱动才会进入各自 probe()。
5. RK3588 的 PCIe Host 架构(DesignWare 路线)
RK3588 在该内核树主要走:
drivers/pci/controller/dwc/pcie-dw-rockchip.c
它是 Rockchip 对 Synopsys DWC PCIe RC 的平台封装层。
核心模式是:Rockchip 平台资源管理 + DWC 通用 host 框架 (pcie-designware-host.c)。
5.1 平台探测主线
rk_pcie_probe() / rk_pcie_really_probe() 主要流程:
- 初始化
struct rk_pcie与struct dw_pcie - 解析 DT 资源(DBI/APB、GPIO、时钟、reset、regulator、PHY)
- 硬件上电与 PHY/时钟/复位时序(
rk_pcie_hardware_io_config()) - RC 寄存器配置(
rk_pcie_host_config()) - 中断域与系统中断初始化(legacy INTx + sys IRQ)
dw_pcie_host_init()启动 DWC host 框架
5.2 链路训练与 Link 状态
在 dw_pcie_ops 中绑定:
.start_link = rk_pcie_establish_link.stop_link = rk_pcie_stop_link.link_up = rk_pcie_link_up
rk_pcie_establish_link() 管理:
- PERST 时序
- LTSSM 使能
- 轮询 link up
- 失败重试与异常恢复(含供电重置场景)
这是 RK3588 PCIe bring-up 成败的核心路径。
5.3 与 DWC 通用 host 的协作边界
pcie-designware-host.c 中 dw_pcie_host_init() 负责通用部分:
- 建立 host bridge
- MSI 域初始化
dw_pcie_setup_rc()(RC 基础配置)- iATU outbound/inbound 配置
- 最终
pci_host_probe()
也就是:
- Rockchip 文件解决“平台差异”(供电、PHY、复位、APB/DBI、中断)
- DWC host 解决“PCI 通用流程”(MSI、ATU、RC 初始化、枚举接入 PCI core)
6. 中断架构:INTx + MSI
RK3588 方案同时支持两类中断路径:
- Legacy INTx
irq_domain_add_linear(...)- 链式处理
rk_pcie_legacy_int_handler()
- MSI/MSI-X
- 由 DWC host 层完成 MSI domain 和向量管理
dw_pcie_msi_host_init()/dw_handle_msi_irq()
因此从驱动视角,终端设备通常优先使用 MSI/MSI-X,INTx 作为兼容路径。
7. 资源与地址转换(ATU)
DWC RC 通过 iATU 把 CPU 地址空间与 PCIe 地址空间映射起来:
dw_pcie_iatu_setup()配置 MEM/IO outbound 窗口- 配置空间访问通过 CFG0/CFG1 类型事务
没有 ATU 正确配置,即使 Link up 也会出现“枚举不到设备/访问配置空间失败”。
8. 与旧 Rockchip PCIe 主控实现的关系
controller/pcie-rockchip-host.c 仍在树内,主要服务较早代控制器(如 rk3399 传统 AXI PCIe 路线)。
它与 RK3588 的 pcie-dw-rockchip.c 并存,体现了 Rockchip 多代 IP 的兼容策略。
对 RK3588 项目,优先看 dw 路线;旧文件更多是历史平台参考和对比样本。
9. 调试建议(RK3588 PCIe)
- 先看 Link
- 重点检查
rk_pcie_establish_link()路径是否超时 - 关注 LTSSM 状态、PERST 时序、refclk、供电
- 重点检查
- 再看资源与枚举
dw_pcie_iatu_setup()是否成功pci_host_probe()后是否进入pci_bus_add_devices()
- 再看中断
- MSI domain 是否创建成功
- legacy IRQ domain 与链式处理是否注册
- 最后看具体设备驱动
- 设备是否已被
pci_bus_match()命中并进入目标驱动probe()
- 设备是否已被
10. 结论
RK3588 kernel-6.1 的 PCI 总线架构可以概括为:
- Linux PCI core:提供统一总线模型、枚举、资源分配与驱动绑定。
- DWC host 框架:提供 RC 初始化、MSI、ATU、配置访问等通用能力。
- Rockchip 平台层:处理 RK3588 专属电源/时钟/PHY/复位/链路训练与中断域管理。
一句话:RK3588 的 PCIe 是“PCI core + DesignWare host + Rockchip 平台 glue”的三层协同架构。
正在加载留言…