RK3588 kernel-6.1 PCI 核心层:probe / bus / setup-* / pci-driver
1. 文档范围
- 源码树:
rk3588/kernel-6.1/drivers/pci/ - 重点文件:
probe.c、bus.c、setup-bus.c、setup-res.c、pci-driver.c - 不包含:具体 SoC Host 控制器驱动(如
controller/dwc/pcie-dw-rockchip*.c),该类驱动负责 注册pci_host_bridge;本文描述其 调用的通用核心路径 - 相关固件入口(非「五文件」之内):
pci-acpi.c(ACPIMCFG/_CRS等构造 host bridge 与窗口)
2. 核心层实现的总线语义
PCI 在 Linux 内核中由三层拼图组成:
| 层次 | 含义 | 主要由哪些文件承担 |
|---|---|---|
| 拓扑 + 配置空间 | Bus/Dev/Fn 枚举,读配置头,得到 pci_bus / pci_dev |
probe.c |
| 资源(BAR / 桥窗口) | 在 iomem_resource / ioport_resource 上开窗,写 BAR/桥寄存器 |
bus.c、setup-bus.c、setup-res.c |
| 设备模型 + 功能驱动 | 每个 pci_dev 对应 device,pci_driver match + probe |
pci-driver.c |
3. probe.c:枚举与 device 注册
职责:PCI 检测与 setup——根总线链表、扫描子总线、解析单功能设备、桥、pci_device_add。
pci_root_buses:根总线全局链表。pci_create_root_bus→pci_register_host_bridge:由 host 端 提供pci_ops(配置读写)、sysdata、窗口resources。- 扫描:
pci_scan_child_bus、pci_scan_slot、pci_scan_bridge等,读 Vendor/Device、建立子 bus。 pci_setup_device:解析 Class、BAR 初值、能力链表、中断路由信息 等,填充pci_dev。pci_device_add:pci_configure_device、fixup、capabilities;链入bus->devices;device_add(&dev->dev)—— 触发driver core去 matchpci_driver并调用probe。
主机一站式入口(多数 platform/ACPI host 驱动 最终会走到类似路径):
1 | int pci_host_probe(struct pci_host_bridge *bridge) |
4. pci-driver.c:总线类型与驱动绑定
职责:不把设备扫出来,而是 注册/匹配 PCI 功能驱动。
__pci_register_driver:drv->driver.bus = &pci_bus_type,driver_register。pci_bus_match:按struct pci_device_id(及 动态 ID)匹配pci_dev。probe/remove、电源管理、AER 恢复 等与struct pci_driver钩连。
1 | int __pci_register_driver(struct pci_driver *drv, struct module *owner, |
5. bus.c:pci_bus 级资源窗口与申请
职责:维护 总线/桥上可用的 IO/MEM 窗口(struct resource 树),并提供 从父总线窗口里划一段给子设备 的 pci_bus_alloc_resource。
pci_add_resource(_offset):host bridge 把 CPU 物理区间 登记到windows(配合 offset 做 CPU ↔ bus 地址 映射)。pci_bus_add_resource/pci_bus_resource_n:在pci_bus上挂 MMIO/IO 窗(含桥 固定槽位 + 动态链表)。pci_bus_alloc_resource:allocate_resource在 匹配的父窗口 内满足 对齐、类型、prefetch 等约束。
与 setup-bus.c / setup-res.c 的关系:bus.c 提供「池子」;setup-* 决定「每个设备/桥拿哪一块」并写配置空间。
6. setup-bus.c:整棵 PCI 树的资源分配
职责:多遍、排序地处理 桥窗口与下游 BAR,典型入口:
pci_bus_size_bridges/pci_bus_assign_resources:先缩/放桥窗,再分配未决资源。pci_assign_unassigned_root_bus_resources、pci_assign_unassigned_bus_resources:处理IORESOURCE_UNSET、rescan 等场景。
与 probe.c 的衔接:非 PCI_PROBE_ONLY 时 pci_host_probe 在扫描后调用 size/assign,再 pci_bus_add_devices。
7. setup-res.c:单个 pci_dev 的 BAR 落地
职责:把 struct resource 的选择结果 写回 PCI 配置空间,并 向内核资源树 claim。
pci_assign_resource:为指定 BAR 槽位 分配/确定区间。pci_std_update_resource/pci_update_resource:算 总线侧地址,pci_write_config_*写 BAR0…/ROM,处理 64 位 BAR 临时关 MEM decode 等。pci_claim_resource:request_resource挂到 iomem/ioport。pci_enable_resources:PCI_COMMANDIO/MEM 解码使能。
8. 与 pci-acpi.c 的分工
| 组件 | 角色 |
|---|---|
| 五文件(本文) | 与固件无关的 PCI 枚举、资源、驱动模型 核心 |
pci-acpi.c |
在 ACPI 系统上,由 MCFG、_CRS、_PRT 等 构造/扩展 pci_host_bridge、IO/MEM 窗口、中断链接,再 调用通用 pci_host_probe 类路径 |
RK3588 若走 ACPI PCIe,pci-acpi.c 常常是 「把固件描述变成 host bridge」;RK SDK 常见 DT + 专有 host 驱动 则更多在 of_pci + controller/*.c,最终同样落到 pci_host_probe。
9. RK3588 典型逻辑顺序(示意)
- Host 驱动(如 DWC Rockchip)分配并配置
pci_host_bridge(ops、窗口、DT/ACPI 数据)。 pci_host_probe:扫描 →pci_bus_size_bridges/pci_bus_assign_resources(非 probe-only)→pci_bus_add_devices。- 各
pci_devdevice_add→ 已注册的pci_drivermatch → probe(网卡、NVMe 等)。
10. 小结
probe.c:拓扑 + 配置空间 → 内核对象 +devicebus.c:总线级resource池与分配 primitivesetup-bus.c:全树桥与 BAR 策略(多遍)setup-res.c:单设备 BAR 写配置 + claimpci-driver.c:pci_bus_type与pci_driver生命周期
深入 RK 具体 RC 硬件,请结合 drivers/pci/controller/dwc/pcie-dw-rockchip*.c 与本 drivers/pci 目录的 pci_host_common / probe 调用点 对照阅读。
同目录已有 rk3588-kernel-6.1-pci总线架构分析.md、DMA 专题 时可一并索引。
正在加载留言…