首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

RK3588 kernel-6.1 — drivers/pci/hotplug 目录详细分析

RK3588 kernel-6.1drivers/pci/hotplug 目录详细分析

1. 文档范围

项目 说明
源码路径 rk3588/kernel-6.1/drivers/pci/hotplug
关联路径 include/linux/pci_hotplug.hdrivers/pci/pcie/(端口 HP 服务)、drivers/pci/probe.c 等枚举核心
目标 说明 PCI 带电插拔(Hotplug) 的软件分层、各后端驱动职责、与 PCIe 原生端口的关系,以及在 RK3588 / DT 场景下的取舍

2. 子系统在 PCI 栈中的位置

flowchart TB
  subgraph userspace [用户空间]
    sysfs["/sys/bus/pci/slots/..."]
    udev[udev / 策略]
  end
  subgraph hotplug_core [hotplug 通用核心]
    pci_hp["pci_hotplug_core.c\nhotplug_slot / pci_slot"]
  end
  subgraph backends [后端驱动 · 选一或多]
    pciehp["pciehp · PCIe Native Slot"]
    acpiphp["acpiphp · ACPI PCI"]
    shpchp["shpchp · SHPC"]
    gpio["gpio_php · DT GPIO"]
    other["cpqphp / ibmphp / cpci / …"]
  end
  subgraph pcie_port [PCIe 端口层]
    portdrv["pcie_port_bus_type\nPCIE_PORT_SERVICE_HP"]
  end
  subgraph pci_core [PCI 核心]
    scan["pci_scan_slot\npci_bus_add_devices"]
    remove["拔除路径 · remove/rescan"]
  end
  sysfs --> pci_hp
  pci_hp --> backends
  pciehp --> portdrv
  pciehp --> scan
  pciehp --> remove
  acpiphp --> pci_hp
  acpiphp --> scan
  gpio --> portdrv
  gpio --> pci_hp

要点

  • 框架层只认识 struct hotplug_slot + hotplug_slot_ops,不关心下面是 PCIe Slot 寄存器还是 ACPI。
  • PCIe 原生热插pciehp)必须建立在 CONFIG_PCIEPORTBUS 已为端口创建 HP 服务(pcie_device 的前提下(见 drivers/pci/pcie)。
  • 枚举/注销最终仍调用 PCI 核心的 pci_scan_*pci_stop_and_remove_bus_device_* 一类接口(具体由各后端在 enable/disable 路径里组合)。

3. 通用核心:pci_hotplug_core.c

3.1 数据结构(include/linux/pci_hotplug.h

struct hotplug_slot_ops — 各后端必须实现的回调(按需可为 NULL):

回调 典型用途
enable_slot / disable_slot 用户写 sysfs power 时上电/断电并触发扫描或拔除
get_power_status 读电源状态
set_attention_status / get_attention_status Attention 指示灯
get_latch_status MRL(Manual Retention Latch) 机械锁闩状态
get_adapter_status 槽内是否有卡(在 sysfs 中文件名为 adapter
hardware_test 可选硬件自检
reset_slot 可选:槽位或次级总线复位(避免与普通 secondary bus reset 副作用冲突时使用)

struct hotplug_slot

  • ops:上表回调表。
  • pci_slot:与 pci_create_slot() 建立的 struct pci_slot 绑定;pci_slot->hotplug 指回本结构。
  • owner / mod_name:模块所有权,sysfs 操作里 try_module_get 防止卸载竞态。

3.2 注册与生命周期 API

API 作用
pci_hp_register(slot, bus, devnr, name) __pci_hp_initialize + pci_hp_add 一步完成:分配 pci_slot、关联 hotplug、创建 sysfs、发 KOBJ_ADD uevent
pci_hp_initialize / pci_hp_add 两步:先只做 pci_create_slot,再 fs_add_slot + 加入全局链表
pci_hp_del 从链表摘除并 fs_remove_slot(撤 sysfs)
pci_hp_destroy pci_destroy_slot,断开 pci_slot->hotplug
pci_hp_deregister pci_hp_del + pci_hp_destroy

内核全局pci_hotplug_slot_list + pci_hp_mutex;按 hotplug_slot_name()(即 pci_slot_name)查找槽位。

3.3 对用户空间的 sysfs 接口(/sys/bus/pci/slots/<name>/

根据 hotplug_slot_ops 中非空成员 选择性创建

文件名 条件 读写
power 存在 enable_slot / disable_slot / get_power_status 读状态;写 0disable_slot1enable_slot
attention 存在 set_*get_attention_status 读写 Attention LED
latch 存在 get_latch_status 只读
adapter 存在 get_adapter_status 只读(适配器是否在槽)
test 存在 hardware_test 写触发测试

另外会为模块创建 符号链接pci_hp_create_module_link)。

3.4 模块初始化

device_initcall(pci_hotplug_init):若编译 CONFIG_HOTPLUG_PCI_CPCI,会调用 cpci_hotplug_init

模块参数debug(bool),打开后 pci_hotplug 内核日志更啰嗦。


4. ACPI 公共代码:acpi_pcihp.c

编入 pci_hotplug.o 的条件:CONFIG_ACPI(见 hotplug/Makefile)。

主要职责

  • acpi_get_hp_hw_control_from_firmware(pdev):对桥设备查找 ACPI 节点并评估 _OSHP,尝试 从固件取得 OS 对热插硬件的控制权(失败时的语义由各调用方处理)。
  • 配合 acpi_pci_root、host bridge 句柄遍历 PCI 设备 ACPI companion。

与原生驱动的分工:在 CONFIG_ACPIpci_hotplug.h 提供 pciehp_is_native / shpchp_is_nativehotplug_is_native(bridge) 表示二者其一为原生则视为原生路径占优,用于避免 ACPI 与原生 HPC 重复接管冲突。


5. Makefile 编译拓扑与链接顺序

文件:drivers/pci/hotplug/Makefile

5.1 核心与条件编译

1
CONFIG_HOTPLUG_PCI          → pci_hotplug.o ← pci_hotplug_core.o [+ cpci* ] [+ acpi_pcihp.o ]

5.2 按特性追加的对象(节选)

CONFIG 变量 组成
HOTPLUG_PCI_COMPAQ cpqphp.o cpqphp_core/ctrl/sysfs/pci [+ nvram]
HOTPLUG_PCI_IBM ibmphp.o ibmphp_core/ebda/pci/res/hpc
HOTPLUG_PCI_PCIE pciehp.o pciehp_core / ctrl / pci / hpc
HOTPLUG_PCI_SHPC shpchp.o shpchp_core/ctrl/pci/sysfs/hpc
HOTPLUG_PCI_POWERNV pnv-php.o pnv_php.o
HOTPLUG_PCI_RPA rpaphp.o rpaphp_core/pci/slot
HOTPLUG_PCI_RPA_DLPAR rpadlpar_io.o rpadlpar_core/sysfs
HOTPLUG_PCI_ACPI acpiphp.o acpiphp_core / glue
HOTPLUG_PCI_S390 s390_pci_hpc.o 单文件
HOTPLUG_PCI_GPIO gpio_php.o 单文件
HOTPLUG_PCI_ACPI_IBM acpiphp_ibm.o 必须在 acpiphp 之后链接(扩展 ACPI)
HOTPLUG_PCI_CPCI_ZT5550 cpcihp_zt5550.o
HOTPLUG_PCI_CPCI_GENERIC cpcihp_generic.o

注释要求CONFIG_HOTPLUG_PCI_PCIE(及同类原生驱动)在 CONFIG_HOTPLUG_PCI_ACPI 之前列出,使 原生 HPC 优先绑定,无原生时再退回 ACPI 通用实现


6. Kconfig 关联

6.1 drivers/pci/hotplug/Kconfig

  • 顶层 HOTPLUG_PCI:依赖 PCI && SYSFS
  • 各子选项:HOTPLUG_PCI_ACPISHPCCPCI、PowerNV、RPA、GPIO、s390、Compaq、IBM 等(详见源码)。
  • HOTPLUG_PCI_PCIE 不在本文件中定义,而在 drivers/pci/pcie/Kconfig(依赖 HOTPLUG_PCI && PCIEPORTBUS)。

6.2 PCIe 原生热插依赖链(摘要)

1
2
PCIEPORTBUS → 端口总线与 HP/AER/PME 等服务
HOTPLUG_PCI_PCIE → pciehp 驱动(绑定 PCIE_PORT_SERVICE_HP)

7. PCIe 原生热插:pciehp_*(重点)

7.1 模块划分

文件 职责
pciehp.h struct controller:关联 struct pcie_devicectrl->pcie->port 即端口 pci_dev)、缓存 Slot Capabilities / Slot ControlCommand Completed 同步(ctrl_lockwait_queuecmd_busy)、电源故障标志、poll_threadhotplug_slotreset_lock(复位期间屏蔽 Presence/DLLLA 抖动)等
pciehp_core.c 装配 hotplug_slot_ops(enable/disable/reset/attention/adapter…)、pci_hp_initialize / pci_hp_destroy、模块参数
pciehp_hpc.c 硬件层:读 PCI_EXP_SLTSTA / PCI_EXP_SLTCTL、处理 Presence Detect Changed、Button Press、Attention Button、Power Fault、Command Completedrequest_threaded_irq 上半部 pciehp_isr + 线程 pciehp_ist;或 pciehp_poll 内核线程
pciehp_ctrl.c 策略/状态机:与用户可见操作、延迟上电(Attention Button 约 5 秒)、工作队列协作
pciehp_pci.c pciehp_configure_device():对桥下 pci_lock_rescan_removepci_get_slot 判重 → pci_scan_slotpci_bus_add_devices;拔除侧对称调用 PCI 核心移除接口(在同模块其它路径)

7.2 模块参数

  • pciehp_poll_mode:无可靠 MSI/中断时使用 轮询
  • pciehp_poll_time:轮询周期(秒)。

7.3 与 PCIe 规范的衔接(实现层面)

  • Slot Control 写入:规范要求两次写入间隔或依赖 Command Completed;驱动用 pcie_poll_cmd / IRQ 路径清 PCI_EXP_SLTSTA_CC,避免违规访问。
  • In-band Presence Disable:部分 OEM(如 DMI 表中的 Dell)对 NVMe 槽启用 in-band presence disabled 行为;pciehp_hpc.cinband_presence_disabled_dmi_table 等变通,避免错误探测。

7.4 与 drivers/pci/pcie 的绑定

pciehp.h #include "../pcie/portdrv.h":驱动作为 pcie_port_service_driver 注册 HP 服务,probe 时拿到 struct pcie_device * 与端口 IRQ

结论:没有 PCIEPORTBUS 或未创建 HP 服务时,pciehp 不会绑定,即便硬件有物理槽位。


8. ACPI PCI 热插:acpiphp_*

文件 职责
acpiphp_core.c ACPI slot/桥 数据结构、与 pci_hotplug 核心对接的具体逻辑
acpiphp_glue.c ACPI CA 粘合acpi_device notify、bridge_listacpiphp_init_context / acpi_set_hp_context、dock fixup、acpiphp_sanitize_bus、热插事件 hotplug_event
acpiphp.h 内部结构与声明
acpiphp_ibm.c(可选) IBM ACPI 扩展

acpiphp_glue.c 文件头说明了 pci_dev 引用计数规则(桥扫描 pci_get_slot、子ordinate bus、卸载时释放),排查泄漏时可对照。


9. 其它后端一览

模块 适用硬件/场景
shpchp_* Standard Hot-Plug Controller(SHPC),常见于传统 PCI/PCI-X 桥片暴露的标准寄存器集
cpqphp_* Compaq 专有控制器,BIOS/NVRAM(可选 cpqphp_nvram
ibmphp_* IBM 专有,EBDA 等查找控制器
cpci_hotplug_* + cpcihp_* CompactPCI,PICMG 2.1 ENUM
pnv_php.c IBM POWERNV
rpaphp_* / rpadlpar_* pSeries RPADLPAR I/O 动态分区
s390_pci_hpc.c IBM Z PCI function standby/注销
gpio_php.c 设备树 GPIO:GPIO 表示连接状态;与 pcie_port 注册配合,走 gpio_hotplug_slot 封装 pci_hp_*

10. 典型调用链(插入,pciehp

  1. 硬件产生 Presence Detect Changed 或用户 power1
  2. pciehp_ist / pciehp_poll 解析 Slot Statuspciehp_ctrl 状态机允许后调用 enable 路径。
  3. pciehp_configure_devicepci_scan_slot 发现新 pci_devpci_bus_add_devices 触发 pci_driver probe
  4. udev 根据 pci_slot / MODALIAS 加载设备驱动。

拔除路径对称:disable_slot → 停止设备 → 从总线移除 → 必要时关电。


11. 调试与排障建议

现象 可查项
/sys/bus/pci/slots/ 条目 CONFIG_HOTPLUG_PCI、是否 pci_hp_add 成功、是否有任一后端 probe
有槽无 pciehp CONFIG_PCIEPORTBUSCONFIG_HOTPLUG_PCI_PCIElspci -vv 看端口是否有 Slot Cap;内核 pcie_ports= / ACPI _OSC 是否禁止原生
中断不工作 pciehp_poll_mode=1 验证;检查端口 MSI 分配
ACPI 与原生冲突 hotplug_is_nativedmesgacpiphp / pciehp 注册顺序

12. RK3588(Device Tree)场景

事实 说明
通常无 ACPI PCI hotplug acpiphp / acpi_pcihp 多数配置下不参与
原生 PCIe 槽 若 SoC/固件为下游端口声明标准 PCIe Slot,且开启 PCIEPORTBUS + HOTPLUG_PCI_PCIEpciehp 可工作
板级 GPIO M.2 卡检测脚可通过 HOTPLUG_PCI_GPIO + DTS 描述接入 gpio_php
裁剪 嵌入式产品若固定单板无带电插拔,可在 defconfig 中关闭 Compaq/IBM/SHPC/RPA/s390 等以减小体积

13. 目录源码索引(约 50 文件)

核心pci_hotplug_core.cacpi_pcihp.c(条件)、cpci_hotplug_core.ccpci_hotplug_pci.c(条件)。

PCIepciehp_core.cpciehp_ctrl.cpciehp_hpc.cpciehp_pci.cpciehp.h

ACPIacpiphp_core.cacpiphp_glue.cacpiphp.hacpiphp_ibm.c

SHPCshpchp_core.cshpchp_ctrl.cshpchp_pci.cshpchp_sysfs.cshpchp_hpc.cshpchp.h

其它cpqphp_*ibmphp_*gpio_php.cgpiophp.hpnv_php.crpaphp_*rpadlpar_*s390_pci_hpc.ccpcihp_*MakefileKconfigTODO


14. 参考与修订

日期 说明
2026-05-08 初版:pci_hotplug 框架、pciehp/ACPI/其它后端、Makefile/Kconfig、RK3588 注意事项

规范细节请以 PCI Express Base Specification(Slot Capability/Control、Command Completed)及 include/linux/pci_hotplug.h 为准。

RK3588 kernel-6.1 — drivers/pci/pcie 端口与子系统模块说明

RK3588 kernel-6.1drivers/pci/pcie 端口与子系统模块说明

1. 分析范围与源码路径

  • 目录rk3588/kernel-6.1/drivers/pci/pcie
  • 关联头文件:同目录 portdrv.h;PCI 公共接口见 include/linux/pci*.hpci_regs.h 等。

本文说明该目录在 PCI Express 端口(Root Port / Switch Port 等) 侧实现的子系统:端口服务设备模型、AER、链路电源(ASPM)、PME、DPC、PTM、EDR、RCEC 等,并与 drivers/pci 总线核心(见同目录下《pci总线架构分析》)区分职责边界。


2. 与 PCI 核心层的关系

层次 典型对象 职责
PCI 总线核心 struct pci_devpci_bus_typepci_driver 枚举端点/桥、资源、设备驱动绑定
本目录(pcie) pcie_port_bus_typestruct pcie_devicepcie_port_service_driver 端口上的 PCIe 能力 拆成独立 服务(PME、AER、HP、DPC…),各自 probe/中断/电源管理

要点:普通网卡、NVMe 等绑定 pci_driver;根端口上的 AER/PME/DPC 等由 pcie_port_bus_type 上的服务驱动处理,二者并行存在。


3. Makefile 与编译单元

文件:drivers/pci/pcie/Makefile

CONFIG 生成对象 说明
CONFIG_PCIEPORTBUS pcieportdrv.oportdrv_core.o + portdrv_pci.o + rcec.o PCIe 端口总线核心
CONFIG_PCIEASPM aspm.o ASPM(L0s/L1 等)
CONFIG_PCIEASPM_EXT aspm_ext.o ASPM 扩展 API(本树含 Rockchip 面向 Wi‑Fi 等的寄存器路径)
CONFIG_PCIEAER aer.oerr.o AER 服务 + 错误恢复核心
CONFIG_PCIEAER_INJECT aer_inject.o 软件注入 AER(调试)
CONFIG_PCIE_PME pme.o 原生 PME
CONFIG_PCIE_DPC dpc.o Downstream Port Containment
CONFIG_PCIE_PTM ptm.o Precision Time Measurement
CONFIG_PCIE_EDR edr.o Error Disconnect Recover(ACPI + DPC)

4. Kconfig 依赖要点

文件:drivers/pci/pcie/Kconfig

  • PCIEPORTBUS:总开关;启用后才可选原生热插拔、AER、PME、DPC 等端口服务。
  • PCIEAER:依赖 PCIEPORTBUS,并 select RAS
  • PCIE_DPC:依赖 PCIEPORTBUS + PCIEAER
  • PCIE_EDR:依赖 PCIE_DPC + ACPI(固件 _DSM 协作)。
  • PCIEASPM:可选默认策略(BIOS / powersave / performance 等);运行时策略见帮助中的 pcie_aspm.parameters.policy 说明。

5. 端口总线核心文件

5.1 portdrv.h

  • 服务类型位PCIE_PORT_SERVICE_PMEAERHPDPCBWNOTIF 等。
  • struct pcie_device:挂在端口上的 逻辑服务设备(含 irqport 指针、service 掩码、priv_data)。
  • struct pcie_port_service_driver:服务端驱动的 probe/remove、PM、slot_reset 等。
  • 声明:pcie_port_service_register/unregisterpcie_port_device_register/remove、suspend/resume 等。

5.2 portdrv_core.c

  • 根据端口能力与 mask 计算各服务所需的 Interrupt Message Number,汇总 MSI/MSI-X 向量数量。
  • 创建 pcie_device、绑定 IRQ、向 pcie_port_bus_type 注册设备。
  • 与各 pcie_port_service_driver(AER、PME、DPC 等模块注册)对接。

5.3 portdrv_pci.c

  • 模块入口pcie_ports= 等内核参数:pcie_ports_disabledpcie_ports_nativepcie_ports_dpc_native 等。
  • ACPI _OSC 协商平台是否允许 OS 原生接管 PCIe 端口能力(及例外场景)。

5.4 rcec.c

  • Root Complex Event Collector(RCEC):遍历/关联 RCiEP 等与 RCEC 上报路径相关的拓扑,服务于根复合体侧错误收集模型。

6. AER 与错误恢复

文件 职责
aer.c 根端口 AER 服务驱动:中断或消息路径上收集 Root Error Status、调度工作队列、与 RAS/CPER 日志衔接。
err.c 错误恢复流程:在 PCIe 错误上报后,沿 pci_error_handlers 调用链执行 error_detectedmmio_enabledslot_resetresume 等,并合并各驱动返回的 pci_ers_result_t
aer_inject.c 软件注入多种 AER 场景;用户态可配合 aer-inject 工具(Kconfig 中给出的仓库链接)。

调试时日志前缀常见:AER:、与 err.c 合并结果相关的 pci 驱动回调日志。


7. ASPM 与扩展

文件 职责
aspm.c 链路 L0s/L1、时钟电源管理等;模块参数前缀 pcie_aspm.;可对已知缺陷硬件关闭 ASPM。
aspm_ext.c CONFIG_PCIEASPM_EXT:导出扩展控制接口。RK3588 厂商树中注释标明面向 Wi‑Fi 等场景,包含 Rockchip 侧 PCIe RAS/能力寄存器访问封装;与主线合并时需逐项 diff。

8. PME、DPC、PTM、EDR

文件 职责
pme.c 原生 PME:端口 PME 中断与 pm_runtime 协同;可选 pcie_pme_nomsi,缓解部分平台上 MSI 与系统睡眠唤醒的交互问题。
dpc.c DPC:下游端口检测到严重错误时的 遏制,限制故障扩散;常与 AER 日志一起分析。
ptm.c PTM:查找链路伙伴是否支持 PTM、辅助 PTM 上下文初始化(时间同步相关)。
edr.c EDR:通过 ACPI _DSM 启停/定位 DPC,与固件组成 混合 DPC 模型(PCI Firmware Spec 相关章节)。

日志前缀常见:PME:DPC:EDR:


9. 与 drivers/pci/hotplug 的关系

  • 原生 PCIe 热插拔依赖 PCIEPORTBUS,具体 HOTPLUG_PCI_PCIE 实现在 drivers/pci/hotplug/(如 pciehp),通过端口能力与本目录注册的端口设备模型衔接。
  • 排障时需同时看:端口是否暴露 HP 能力_OSC/内核参数是否禁用原生端口hotplug 驱动是否加载

10. 维护与合并建议

  1. 合并上游 Linux 时重点比对:portdrv_pci.c_OSC / pcie_ports)、edr.c_DSM 编号与语义)、aspm_ext.c(厂商扩展与主线冲突)。
  2. 寄存器位域与错误类型以 PCIe 规范pci_regs.h 为准;本文仅做代码导航。
  3. 平台为 DT(无 ACPI) 时,EDR 等与 ACPI 强相关的路径通常不参与。

11. 文档修订

日期 说明
2026-05-08 初版:路径、Makefile/Kconfig、各 .c 职责与 hotplug 关联

RK3588 kernel-6.1 — drivers/pci 设备枚举与配置空间探测流程

RK3588 kernel-6.1drivers/pci 设备枚举与配置空间探测流程

1. 文档目的与源码范围

项目 说明
基准路径 rk3588/kernel-6.1/drivers/pci/
核心文件 probe.c(扫描与 pci_dev 创建)、access.cpci_bus_read_config_*bus->ops->read
易混淆文件 search.c(仅在内核已枚举设备链表中查找,不做硬件探测

本文回答:内核如何判定某个 (bus, devfn) 上是否存在 PCI 设备、“扫描”对应的软件操作是什么,以及与硬件侧 Configuration Read 的关系。


2. 结论摘要(协议视角)

  • Linux PCI 核心 不会 单独发送一条高层“扫描命令”再由设备回报;枚举的本质是对 配置空间(Configuration Space)的读(及后续对桥的写)
  • 判断设备是否存在的第一道检查:对 PCI_VENDOR_ID(配置空间偏移 0) 做一次 dword,同时得到 Vendor ID(低 16 位)Device ID(高 16 位)
  • 空槽或无响应时,读结果常为 0xFFFFFFFF(或错误完成、PCI_POSSIBLE_ERROR 等);内核据此认为 无有效设备
  • CPU 侧调用 pci_bus_read_config_*;具体如何变成链路上的 PCIe Configuration TLP(Type 0 / Type 1)由 Host 控制器 / ECAM / SoC 路由 完成(如 RK3588 上 DesignWare PCIe RC 驱动注册的 bus->ops)。

3. search.cprobe.c 的职责划分

3.1 search.c — 仅搜索已注册设备

实现 pci_find_buspci_get_slotpci_get_devicepci_dev_present 等。

  • 依赖 pci_bus_sem 与全局 / 总线上的 pci_dev 链表
  • 不进行 pci_bus_read_config_*,因此 不参与发现新设备

3.2 probe.c — 枚举与探测

  • pci_scan_child_bus:在一条 PCI 总线下扫描设备。
  • pci_scan_slotpci_scan_single_devicepci_scan_device:对给定 (bus, devfn) 做存在性判断并 pci_device_add

4. 判定设备是否存在:pci_bus_read_dev_vendor_id

入口:pci_scan_device() 调用 pci_bus_read_dev_vendor_id(bus, devfn, &l, timeout);其中 timeout 用于 CRS(Completion Retry Status) 重试场景。

逻辑要点(pci_bus_generic_read_dev_vendor_id):

  1. pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l)
  2. 若返回值表现为 错误响应全 0、或部分板级异常的 0x0000ffff / 0xffff0000,则视为 无设备
  3. Vendor ID 为 PCI‑SIG 保留值表示 CRS,则循环 msleep + 重读,直到超时或得到合法 VID。

对应源码位置:probe.cpci_bus_generic_read_dev_vendor_idpci_scan_device


5. 扫描调用链

1
2
3
4
5
6
7
8
9
10
pci_scan_child_bus(bus)
└─ … 对每个 devfn / slot …
pci_scan_slot(bus, devfn) # 从 function 0 起,必要时遍历多功能
└─ pci_scan_single_device(bus, devfn + fn)
├─ pci_get_slot() 若已在内核链表中则直接返回
└─ pci_scan_device()
├─ pci_bus_read_dev_vendor_id() # 关键:VID/DID 读
├─ pci_alloc_dev()
└─ pci_setup_device() # 继续读 Class、Header、BAR、Cap…
└─ pci_device_add()

5.1 pci_scan_slot 与多功能

  • fn = 0 开始 pci_scan_single_device
  • 若 function 0 不存在且非虚拟机隔离等多函数场景,通常 不再扫描更高 function
  • 多功能设备通过 next_fn() / ARI 扩展后续 function 号

5.2 PCIe「仅 Device 0」优化

对典型 PCIe Downstream Port 下联链路,规范上通常为 单设备、logical Device 0。内核 only_one_child() 为真时 只扫描 devfn == 0,避免对 devfn 1..31 的无谓配置访问(除非 PCI_SCAN_ALL_PCIE_DEVS 等特殊拓扑)。


6. 配置访问如何落到硬件:access.c

pci_bus_read_config_dword(bus, devfn, pos, value)(及 byte/word 变体)在持 pci_lock(或可配置的 lockless 路径)后调用:

1
bus->ops->read(bus, devfn, pos, len, &data)

即:每条枚举用的配置读最终由 pci_bus 注册的 pci_ops 实现(ECAM MMIO、Rockchip/DesignWare 封装等均在此处对接)。

文件:drivers/pci/access.c(宏 PCI_OP_READ)。


7. 发现桥之后的扫描

pci_setup_device() 根据 Header Type 识别 PCI‑PCI / PCIe 桥Root Port 后,会继续:

  • 读写 总线号、窗口寄存器 等;
  • 创建 子总线 pci_bus
  • *递归 pci_scan_child_bus*。

此后对新一级 bus 上的设备再次重复 VID 读 → pci_setup_device


8. RK3588 侧提示

  • RK3588 常见为 DT + DesignWare PCIe Host,配置访问经 pci_ops 映射到 控制器 MMIO(含 ECAM 区间)
  • lspci 看不到设备:除链路训练、时钟、复位管脚外,可从 首次 VID 读是否返回 0xFFFFFFFF 推断配置事务是否到达对端(结合 earlycon/pci=earlydump 等内核调试手段,若启用)。

9. 与其它文档的关系

文档 内容
rk3588-kernel-6.1-pci总线架构分析.md Host probe、pci_scan_root_bus_bridge 整体流程
rk3588-kernel-6.1-pci核心层-probe-bus-setup-driver分析.md probe/bus/setup/driver 分层

本文聚焦 「是否存在设备」的配置读判据与 pci_scan_* 调用链


10. 修订记录

日期 说明
2026-05-08 初版:VID 探测、pci_scan_*search.c 区分、bus->ops

PCI 与 PCIe 区别详解

PCI 与 PCIe 区别详解

本文从规范演进、物理拓扑、事务模型、配置空间、中断与电源管理、Linux 内核视角等方面对比 经典 PCI(含 PCI-X)PCI Express(PCIe)。不涉及某一芯片厂的寄存器级细节;规范细节请以 PCI Local Bus SpecificationPCI Express Base Specification 为准。


1. 概述与命名

术语 常见所指
PCI Peripheral Component Interconnect,传统 并行 局部总线(33/66 MHz,32/64 bit)。
PCI-X PCI 并行总线的扩展,更高时钟与拆分事务;物理上与 PCI 槽位/信号形态相近,仍属「并行 PCI 家族」。
PCIe / PCI Express PCI-SIG 定义的 串行、点对点、分组交换 继任架构;与 PCI 在电气与链路层不兼容,通过 互连。

口语中「PCI 插槽」在现今 PC/嵌入式上 多数是 PCIe;真正的 并行 PCI 在新平台上已罕见。


2. 物理层与电气特性

2.1 并行 PCI / PCI-X

  • 多根并行数据线 + 地址线 + 控制线,公共参考时钟。
  • 共享介质:同一时刻总线上通常只有一个事务主导设备。
  • 频率上限信号skew、反射、负载 制约,难以持续推高(典型 33 MHz / 66 MHz,PCI-X 可到更高 MHz 但仍是并行瓶颈)。
  • 连接器:较长插槽、大量引脚(经典 PCI 金手指)。

2.2 PCIe

  • 差分对串行链路:每条 Lane 为一对发送 + 一对接收(TX+/TX−、RX+/RX−)。
  • 链路宽度×1、×2、×4、×8、×16(多 Lane 绑定同链路)。
  • 编码:Gen1/2 常用 8b/10b;更高代数常用 128b/130b,提高有效带宽。
  • 嵌入式时钟 recovery,利于提高速率与 PCB 走线
  • 连接器:较短的金手指(PCIe)、M.2、U.2 等也是 PCIe 电气封装的一种形态。

2.3 带宽直觉(量级)

PCIe 单 Lane 每代比特率大致翻番(规范表格可查);实际吞吐量还受 编码开销、协议头、链路开销 影响。并行 PCI 的总带宽 远低于 当代 PCIe ×4 以上链路。


3. 拓扑结构

3.1 PCI:共享总线段(multi-drop)

1
2
3
CPU — Host Bridge —+—— Dev A
+—— Dev B
+—— PCI-PCI Bridge —— 下游总线段 …
  • 同一 PCI bus segment 上多个设备 电气并联
  • 仲裁:谁占用总线由仲裁逻辑决定。
  • 桥(Bridge) 分隔 不同 PCI bus number,扩展拓扑。

3.2 PCIe:交换/fabric(点对点)

1
2
CPU — Root Complex — Root Port —[Link]— Endpoint
— Switch Upstream — Switch Downstream Port —[Link]— Endpoint
  • 链路两端点对点:无「同一电气总线上挂十几个设备」的形态。
  • Switch 提供 多下游端口,内部用 包交换 转发。
  • Bus/Device/Function(BDF) 仍用于 软件编号,但 物理连接链路 + 路由,不是一根并行线。

4. 事务与协议模型(概念对比)

4.1 PCI:基于周期的总线事务

  • 典型阶段:仲裁 → 地址 →(可选)数据多次传送 → 结束
  • Memory Read/Write、IO Read/Write、Configuration Read/Write 等在 并行信号时序 上体现。
  • 中断:传统 INTx 边带信号线(INTA#…),多个设备可线与共享。

4.2 PCIe:分层封包(Packet)

典型分层概念(与 OS 驱动日常工作远近不一):

层级(概念) 作用(简述)
物理层 Lane、电气、编码、链路训练(LTSSM)。
数据链路层 DLLP、ACK/NAK、重传、credits,链路可靠传输。
事务层 TLP(Transaction Layer Packet):Memory、IO、Configuration、Message 等;相当于 把 PCI 事务语义打成包在链路上传

要点:软件仍读写 MMIO/配置空间,仿佛「仍是 PCI」;底层已由 TLP + Credit 替代并行周期。


5. 配置空间

5.1 共同点(兼容内核枚举)

  • 256 字节标准配置头(Type 0 设备 / Type 1 桥)布局 一脉相承:Vendor ID、Device ID、Command、Status、BAR、Capability Pointer 等。
  • OS 枚举第一步仍是 读 Vendor/Device(Linux 见 pci_scan_device / pci_bus_read_dev_vendor_id)。

5.2 PCIe 扩展差异

特性 经典 PCI PCIe
扩展配置空间 有限或依赖具体主机实现 常见 4 KB/function(ECAM 映射)。
PCIe Capability 链路能力/状态(速度、宽度、ASPM 位等)。
扩展能力 较少 MSI/MSI-XAERSR-IOVACSPASID 等更丰富。

6. BAR、内存/IO 与 DMA(软件观感)

6.1 相似之处

  • 设备通过 BAR 请求 Memory 或 I/O 空间;操作系统分配 CPU 可见物理地址(或 No-MMIO 特殊情况)。
  • DMA:仍需关心 地址宽度、一致性、IOMMU;语义上仍是「设备 ↔ 内存」。

6.2 PCIe 侧额外关注点

  • Payload Size(MPS/MRR)Read Completion Boundary 等影响大包拆分与性能。
  • ACS/P2PATS(地址翻译服务) 等多见于服务器 GPU/NVMe 组网场景。
  • PCIe-to-PCI 桥 会带来 地址窗口与 prefetch 行为差异(驱动偶尔需 quirk)。

6.3 BAR 是什么、谁在「控制」这块空间

BAR(Base Address Register) 位于配置空间 Header(Type 0 设备一般为 BAR0–BAR5),用来声明设备需要主机映射的 MemoryI/O 窗口的大小与属性。

角色 做什么
硬件(设备) 提供 类型位(Memory / IO、32/64-bit、prefetch 等)与 位数编码(通过 sizing 暴露长度);上电或复位后 BAR 未必已是最终 CPU 物理地址。
固件/操作系统 在枚举阶段 探测长度计算对齐、把 总线可路由地址 写回 BAR;必要时配置上游 桥的 Memory/IO 窗口,令访问能落到正确下游。
驱动 通常依赖 pci_enable_device() 之后 pci_resource_start() / ioremap() 使用 BAR;一般 不应随意改写已由内核分配好的 BAR(除非平台文档明确要求且整套资源一致更新)。

要点:「BAR 空间」本质是一段主机地址空间与配置空间里 BAR 字段的对应关系控制权在枚举与资源分配流程(BIOS/UEFI + Linux pci_bus/pci_dev 资源树),设备只声明需求。

6.4 BAR 探测(Sizing)与大小编码

枚举时常用流程(规范语义,具体实现在 drivers/pci/probe.c 等与 pci_bus_read_dev_vendor_id 之后的 BAR 编程路径):

  1. 向 BAR 写入全 1(或规范允许的试探写)
  2. 读回:低位中为 1 的位表示 可修改(参与译码);结合 类型位 解码 最小对齐 / 空间大小(IO 与 Memory、32/64-bit BAR 规则略有差异)。
  3. 64-bit Memory BAR 占用 相邻两个 BAR 寄存器(低 dword + 高 dword);探测时需 成对处理。
  4. 写入真实基址 后再启用 PCI_COMMAND_MEMORY / PCI_COMMAND_IO(命令寄存器),设备才开始对该窗口译码。

这与 并行 PCI 与 PCIe 在配置头层面是一致的;差别主要体现在 CPU 侧如何访问配置空间(IO 端口间接索引 vs ECAM/MMIO),而不是 BAR 位域定义本身。

6.5 分配、对齐与「空间从哪来」

  • 对齐:BAR 大小天然等于 最小对齐边界(例如 64 KB 窗口须对齐到 64 KB);内核分配时需满足 pci_probe_bar / pci_assign_resource 等路径中的对齐约束。
  • 地址池:来自 主机桥 / Root Complex 声明的 PCIe Memory / IO 范围(设备树 rangespci-host-generic 资源或 ACPI);桥设备(Type 1) 还有 Base/Limit 寄存器把上游大窗口 裁剪 给下游总线。
  • Prefetchable vs Non-prefetchable Memory:影响处理器缓存策略与桥合并窗口行为;显卡大块 framebuffer 常为 prefetchable,MMIO 控制寄存器 常为 non-prefetchable。
  • I/O BAR:在 x86 上仍有意义;许多 ARM/RISC SoCpci=noio 或对 IO 范围声明为空, effectively 只使用 MEM BAR

6.6 Linux 中与 BAR 相关的常用接口(观感)

接口 / 概念 含义
pci_enable_device() 分配 IRQ、映射资源(含 BAR)并使能设备命令位中的 MEM/IO(配合电源状态)。
pci_resource_start(len/flags) 得到某 BAR 在 CPU 物理地址域 的起始与长度、IORESOURCE_MEM/IORESOURCE_IO 等标志。
devm_pci_remap_cfg_resource()(控制器侧) RC 驱动映射 ECAM/配置窗口,与 设备 BAR 是不同概念:前者访问 配置空间,后者是 设备寄存器/内存窗口
pci_release_regions() / request_region 独占或协调与其它驱动的资源冲突(视场景)。

Endpoint(EP)侧若在 Linux 里扮演 pci_epc,则由 pci_epc_ops.set_bar 等把 SoC 本地物理地址 写进 EP 硬件 BAR 译码(与 RC 枚举「主机分配总线地址」方向相反但语义对应)。

6.7 PCI / PCIe 在 BAR 上的结论句

  • 配置头布局与 BAR sizing 规则:PCI 与 PCIe 同一套软件模型
  • 物理实现:PCIe 通过 Memory Read/Write TLP 访问映射后的地址;并行 PCI 用 总线周期。对驱动而言,BAR 仍是 MMIO/PIO 入口
  • 复杂拓扑:经过 Switch / 桥 时,BAR 背后可达性依赖 各级窗口与路由;调试「读 BAR 挂死」常需同时查 链路、桥窗口、对齐与 COMMAND 位

7. 中断

方式 PCI PCIe
INTx 必选硬件线(分时共享) 常以 Message 模拟(Virtual Wire Message),减少专用引脚
MSI / MSI-X 后期可选 极为普遍;MSI-X 适合高队列设备(网卡、NVMe)

Linux 中 pci_alloc_irq_vectors 一类 API 主要面向 MSI-X;纯 legacy PCI 设备仍可能只用 INTx


8. 错误处理与可靠性(简要)

  • PCI:parity/error 线与状态位为主,系统级错误模型相对简单。
  • PCIeAER(Advanced Error Reporting)ECRC链路误码检测与恢复、根端口 错误上报 等更完备;Linux drivers/pci/pcie/aer.c 等与 RAS 挂钩。

9. 电源管理

  • PCI:PME、D 状态等已有基础。
  • PCIe:除传统 PCI PM 外,强调 链路级 ASPM(L0s/L1/L1.1/L1.2…);与 ACPI _PRT/OSCI 协同更常见。

内核 drivers/pci/pcie/aspm.c 即 OS 侧策略控制示例。


10. 热插拔与外形规格

  • 并行 PCI:热插依赖机箱 控制器 + 专有驱动(厂商方案多)。
  • PCIe:规范层面定义 Slot Capabilities / Slot Status,配合 pciehp 等做 原生热插(视平台固件与布线)。

外形:PCI 长槽 vs PCIe 各类长度(×16 显卡槽、×1 开口槽)、M.2 Key M(NVMe)等均为 PCIe 链路封装变化。


11. PCI-X 是什么(避免混淆)

  • 仍是并行 PCI 电气家族的增强:更高性能、拆分事务等。
  • 不是 PCIe:勿把 「PCI-X」读成「PCIe ×」。
  • 新系统设计几乎不再采用并行 PCI-X。

12. Linux 内核视角(与 RK3588 文档衔接)

  • 统一子系统drivers/pcipci_bus_typestruct pci_devpci_driver 同时服务 PCI 与 PCIe
  • 枚举配置空间访问(ECAM 或 SoC 自定义窗口);PCIe 设备同样挂在 pci 总线上
  • PCIe 特有逻辑:集中在 drivers/pci/pcie/(ASPM、AER、端口服务、pciehp 等)。
  • 判定pci_is_pcie(pdev)、读 PCIe Capability;Rockchip 等平台主机控制器多为 PCIe Root Complex,枚举路径仍走 pci_host_probe

13. 互连与兼容桥

  • PCIe-to-PCI(或 PCI-X)桥:允许 旧并行设备出现在 PCIe 拓扑下游,配置仍是 PCI 模型。
  • Root Complex Integrated Endpoint:片上 「逻辑 PCIe 设备」无独立插槽。

14. 对照总表

维度 PCI(并行) PCIe
介质 并行共享总线 串行点对点链路
拓扑扩展 Bridge 分段 Root Port / Switch / Endpoint
时钟 公共总线时钟 链路嵌入式时钟
典型带宽扩展 升频/位宽受限 加 Lane + 代数
配置空间 256B 头为主 256B 兼容 + 扩展 + PCIe Cap
传输抽象 总线周期 TLP + 链路层可靠传输
中断 INTx 线为主 Message / MSI-X 为主流
电源 PCI PM PCI PM + ASPM
物理连接器 经典 PCI 长槽 PCIe / M.2 等

15. 延伸阅读(本仓库 linuxDoc/pci

文档 关联
rk3588-kernel-6.1-pci总线架构分析.md Linux PCI 枚举与 RK Host
rk3588-kernel-6.1-drivers-pci-pcie端口与子系统模块说明.md PCIe 端口服务(AER/ASPM 等)

16. 修订记录

日期 说明
2026-05-08 初版:PCI/PCI-X/PCIe 多维对比与内核衔接
2026-05-08 §6 增补 BAR 空间控制:角色分工、sizing、分配对齐、桥窗口、Linux 接口与 RC/EP 对照

RK3588 kernel-6.1 drivers/pci 总线架构分析

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 子系统分为几层:

  1. 总线核心层
    • pci-driver.cprobe.cbus.csetup-bus.csetup-res.c
    • 负责总线对象、枚举、资源分配、驱动绑定。
  2. 配置与能力层
    • pcie/msi/ats.ciov.cquirks.c
    • 负责 PCIe 特性、MSI/MSI-X、SR-IOV、quirk 修复。
  3. 固件/平台接口层
    • of.cpci-acpi.cecam.c
    • 对接 DT/ACPI/ECAM 配置空间访问。
  4. 控制器驱动层
    • 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() 关键步骤:

  1. pci_scan_root_bus_bridge(bridge):扫描 root bus
  2. 根据 PCI_PROBE_ONLY 决定
    • pci_bus_claim_resources()(沿用固件资源)
    • pci_bus_size_bridges() + pci_bus_assign_resources()(内核重分配)
  3. 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.cpci_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() 主要流程:

  1. 初始化 struct rk_pciestruct dw_pcie
  2. 解析 DT 资源(DBI/APB、GPIO、时钟、reset、regulator、PHY)
  3. 硬件上电与 PHY/时钟/复位时序(rk_pcie_hardware_io_config()
  4. RC 寄存器配置(rk_pcie_host_config()
  5. 中断域与系统中断初始化(legacy INTx + sys IRQ)
  6. dw_pcie_host_init() 启动 DWC host 框架

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.cdw_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 方案同时支持两类中断路径:

  1. Legacy INTx
    • irq_domain_add_linear(...)
    • 链式处理 rk_pcie_legacy_int_handler()
  2. 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)

  1. 先看 Link
    • 重点检查 rk_pcie_establish_link() 路径是否超时
    • 关注 LTSSM 状态、PERST 时序、refclk、供电
  2. 再看资源与枚举
    • dw_pcie_iatu_setup() 是否成功
    • pci_host_probe() 后是否进入 pci_bus_add_devices()
  3. 再看中断
    • MSI domain 是否创建成功
    • legacy IRQ domain 与链式处理是否注册
  4. 最后看具体设备驱动
    • 设备是否已被 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”的三层协同架构。

RK3588 kernel-6.1 PCI 核心层:probe / bus / setup-* / pci-driver

RK3588 kernel-6.1 PCI 核心层:probe / bus / setup-* / pci-driver

1. 文档范围

  • 源码树:rk3588/kernel-6.1/drivers/pci/
  • 重点文件:probe.cbus.csetup-bus.csetup-res.cpci-driver.c
  • 不包含:具体 SoC Host 控制器驱动(如 controller/dwc/pcie-dw-rockchip*.c),该类驱动负责 注册 pci_host_bridge;本文描述其 调用的通用核心路径
  • 相关固件入口(非「五文件」之内):pci-acpi.c(ACPI MCFG/_CRS 等构造 host bridge 与窗口)

2. 核心层实现的总线语义

PCI 在 Linux 内核中由三层拼图组成:

层次 含义 主要由哪些文件承担
拓扑 + 配置空间 Bus/Dev/Fn 枚举,读配置头,得到 pci_bus / pci_dev probe.c
资源(BAR / 桥窗口) iomem_resource / ioport_resource 上开窗,写 BAR/桥寄存器 bus.csetup-bus.csetup-res.c
设备模型 + 功能驱动 每个 pci_dev 对应 devicepci_driver match + probe pci-driver.c

3. probe.c:枚举与 device 注册

职责:PCI 检测与 setup——根总线链表、扫描子总线、解析单功能设备、桥、pci_device_add

  • pci_root_buses:根总线全局链表。
  • pci_create_root_buspci_register_host_bridge:由 host 端 提供 pci_ops(配置读写)sysdata窗口 resources
  • 扫描pci_scan_child_buspci_scan_slotpci_scan_bridge 等,读 Vendor/Device、建立子 bus
  • pci_setup_device:解析 Class、BAR 初值、能力链表、中断路由信息 等,填充 pci_dev
  • pci_device_addpci_configure_device、fixup、capabilities;链入 bus->devicesdevice_add(&dev->dev) —— 触发 driver corematch pci_driver 并调用 probe

主机一站式入口(多数 platform/ACPI host 驱动 最终会走到类似路径):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int pci_host_probe(struct pci_host_bridge *bridge)
{
ret = pci_scan_root_bus_bridge(bridge);
bus = bridge->bus;
if (pci_has_flag(PCI_PROBE_ONLY)) {
pci_bus_claim_resources(bus);
} else {
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child);
}
pci_bus_add_devices(bus);
return 0;
}

4. pci-driver.c:总线类型与驱动绑定

职责不把设备扫出来,而是 注册/匹配 PCI 功能驱动

  • __pci_register_driverdrv->driver.bus = &pci_bus_typedriver_register
  • pci_bus_match:按 struct pci_device_id(及 动态 ID)匹配 pci_dev
  • probe / remove、电源管理、AER 恢复 等与 struct pci_driver 钩连。
1
2
3
4
5
6
7
8
int __pci_register_driver(struct pci_driver *drv, struct module *owner,
const char *mod_name)
{
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
// ...
return driver_register(&drv->driver);
}

5. bus.cpci_bus资源窗口与申请

职责:维护 总线/桥上可用的 IO/MEM 窗口struct resource),并提供 从父总线窗口里划一段给子设备pci_bus_alloc_resource

  • pci_add_resource(_offset):host bridge 把 CPU 物理区间 登记到 windows(配合 offsetCPU ↔ bus 地址 映射)。
  • pci_bus_add_resource / pci_bus_resource_n:在 pci_bus 上挂 MMIO/IO 窗(含桥 固定槽位 + 动态链表)。
  • pci_bus_alloc_resourceallocate_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_resourcespci_assign_unassigned_bus_resources:处理 IORESOURCE_UNSET、rescan 等场景。

probe.c 的衔接:非 PCI_PROBE_ONLYpci_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_resourcerequest_resource 挂到 iomem/ioport
  • pci_enable_resourcesPCI_COMMAND IO/MEM 解码使能。

8. 与 pci-acpi.c 的分工

组件 角色
五文件(本文) 与固件无关的 PCI 枚举、资源、驱动模型 核心
pci-acpi.c ACPI 系统上,由 MCFG_CRS_PRT构造/扩展 pci_host_bridgeIO/MEM 窗口、中断链接,再 调用通用 pci_host_probe 类路径

RK3588 若走 ACPI PCIepci-acpi.c 常常是 「把固件描述变成 host bridge」RK SDK 常见 DT + 专有 host 驱动 则更多在 of_pci + controller/*.c,最终同样落到 pci_host_probe


9. RK3588 典型逻辑顺序(示意)

  1. Host 驱动(如 DWC Rockchip)分配并配置 pci_host_bridgeops、窗口、DT/ACPI 数据)。
  2. pci_host_probe扫描pci_bus_size_bridges / pci_bus_assign_resources(非 probe-only)→ pci_bus_add_devices
  3. pci_dev device_add已注册的 pci_driver match → probe(网卡、NVMe 等)。

10. 小结

  • probe.c拓扑 + 配置空间 → 内核对象 + device
  • bus.c总线级 resource 池与分配 primitive
  • setup-bus.c全树桥与 BAR 策略(多遍)
  • setup-res.c单设备 BAR 写配置 + claim
  • pci-driver.cpci_bus_typepci_driver 生命周期

深入 RK 具体 RC 硬件,请结合 drivers/pci/controller/dwc/pcie-dw-rockchip*.c 与本 drivers/pci 目录的 pci_host_common / probe 调用点 对照阅读。

同目录已有 rk3588-kernel-6.1-pci总线架构分析.mdDMA 专题 时可一并索引。

Linux 6.1 PCI/PCIe 驱动文档索引

Linux 6.1 PCI/PCIe 驱动文档索引

源码基准:rk3588/kernel-6.1/drivers/pci/。文档以 PCI Core 为主线,并单独说明 RK3588 DesignWare Host/Endpoint 平台实现。

系统化分析

文档 主题
源码目录构建配置与模块索引.md 目录地图、Makefile/Kconfig、通用与平台代码边界
01-HostBridge枚举与设备生命周期.md Host Bridge、BDF 探测、桥递归、绑定、移除和并发
02-BAR桥窗口与地址资源分配.md BAR sizing、桥窗口、CPU/PCI 地址和 DWC iATU
03-INTx-MSI与MSIX中断路径.md INTx 路由、MSI/MSI-X、IRQ domain 和 RK3588
04-设备使能电源管理与复位恢复.md Command、D0-D3、状态保存、FLR/总线复位和 AER 恢复
05-SRIOV-ATS-PASID与IOMMU虚拟化.md PF/VF、VF BAR、ATS/PRI/PASID 与隔离边界
06-PCI-Endpoint框架与ConfigFS.md EPC/EPF、BAR、地址映射、中断、ConfigFS
07-RK3588-DesignWare-PCIe控制器.md Rockchip glue、DWC Host、链路、iATU、IRQ 和 PM
08-Sysfs-Proc与用户态控制接口.md config/resource、remove/rescan/reset、bind 和 Slot
09-PCIe能力-AER-ASPM-DPC与高级特性.md Port Bus、AER、DPC、ASPM、DOE、P2PDMA、VPD、quirks
10-RK3588配置-DTS与故障排查.md defconfig、DTS、PHY/时序和分层故障树
11-OF-ACPI-ECAM与配置空间后端.md DT ranges/IRQ/IOMMU、ACPI MCFG/_OSC、ECAM 与 DWC 配置访问

已有专题

文档 主题
pci总线架构分析.md PCI Core、枚举和 RK3588 Host 总览
drivers-pci-枚举与配置空间探测流程.md VID/DID 配置读和pci_scan_*调用链
pci核心层-probe-bus-setup-driver分析.md probe/bus/setup/driver 分层
drivers-pci-pcie端口与子系统模块说明.md PCIe Port、AER、ASPM、DPC、PME
drivers-pci-hotplug目录详细分析.md Hotplug Core、pciehp、ACPI、GPIO
驱动DMA编程与PCIe设备DMA传输分析.md 功能驱动 DMA 编程
rockchip-pcie-rockchip-rc-ep-dma分析.md Rockchip RC/EP 与 DMA
rockchip-pcie-ep应用层数据传输接口.md 厂商 EP 字符设备与应用接口
PCI与PCIe区别详解.md PCI、PCI-X、PCIe 协议与 Linux 视角

建议阅读路线

Host/RC 开发:目录索引 → 01 → 02 → 03 → 11 → 07 → 10。

Endpoint 开发:目录索引 → 06 → 07 → Rockchip EP/DMA 专题。

设备直通/虚拟化:01 → 02 → 05,并结合linuxDoc/drivers/vfio/和 IOMMU 文档。

RK3588 kernel-6.1 — Rockchip PCIe EP 模式应用层数据传输接口

RK3588 kernel-6.1 — Rockchip PCIe EP 模式应用层数据传输接口

1. 文档目的

说明在 PCIe Endpoint(EP) 场景下,用户态应用可通过哪些内核暴露的接口与 Root Complex(RC) 或片上逻辑交换数据;并区分 pcie-rockchip-ep.c(老式 AXI EP)与 pcie-dw-ep-rockchip.c(DesignWare EP,RK3568/RK3588 常用)。

源码基准rk3588/kernel-6.1/
用户态头文件include/uapi/linux/rk-pcie-ep.hinclude/uapi/linux/rk-pcie-dma.h


2. 两条 EP 驱动路径对照

项目 pcie-rockchip-ep.c dwc/pcie-dw-ep-rockchip.c
典型 compatible rockchip,rk3399-pcie-ep rockchip,rk3588-pcie-ep
内核框架 pci_epc + pci_epf_* DWC dw_pcie + Rockchip 封装
专用 /dev 字符设备 /dev/pcie_ep
片上 UDMA (pcie-dev) 本文件不注册 rockchip_pcie_init_dma_trx() 后可出现 /dev/pcie-dev

结论:需要「打开设备 + mmap/ioctl」的典型应用接口,在 RK3588 上应看 DWC EP 驱动,而不是仅 pcie-rockchip-ep.c


3. pcie-rockchip-ep.c — 应用层无法直接拿到 /dev

  • 控制器驱动只实现 struct pci_epc_ops(写头、BAR、OB 映射、MSI/Legacy IRQ 等),不向用户空间注册 misc 设备
  • 配置与功能绑定走 pci_epf 子系统(常见配合 configfs/sys/kernel/config/pci_ep/)或内核内的 EP function 驱动。
  • 数据面:通常由 RC 侧映射 EP 的 BARMMIO/DMA;EP 侧若在用户态访问同一块内存,需 自写内核模块导出 mmap,或通过 已存在的 EP function 驱动暴露接口。

4. DesignWare EP:/dev/pcie_ep

驱动drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c
节点miscdevicename = "pcie_ep"/dev/pcie_ep

4.1 使用顺序(概要)

  1. open("/dev/pcie_ep")
  2. ioctl(PCIE_EP_SET_MMAP_RESOURCE, &res) — 选择下一次 mmap 映射的资源(见 enum pcie_ep_mmap_resourcerk-pcie-ep.h
  3. mmap(...) — 将选中资源的 物理窗口映射到进程虚拟地址
  4. 视需要 ioctl(PCIE_DMA_CACHE_INVALIDE / PCIE_DMA_CACHE_FLUSH) 维护 CPU 与 DMA/RC 访问的缓存一致性

4.2 mmap 资源类型(节选)

pcie_ep_mmap_resource 含义
PCIE_EP_MMAP_RESOURCE_DBI DBI(调试/寄存器访问,慎用)
PCIE_EP_MMAP_RESOURCE_BAR0/1/2/5 Inbound BAR 在 EP SoC 侧对应的 DRAM 物理区:应用可对映射区 读写,与 RC 通过 PCIe 访问同一 BAR 的数据通路一致
PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER 与连续缓冲相关 ioctl 配合

映射属性BAR2 常用 writecombine;其它多为 noncached(见驱动 pcie_ep_mmap)。

4.3 pcie-dw-ep-rockchip.c 中已处理的 IOCTL(与头文件对照)

实现见 pcie_ep_ioctl();包含但不限于:

IOCTL(rk-pcie-ep.h 作用
PCIE_DMA_CACHE_INVALIDE dma_sync_single_for_cpu
PCIE_DMA_CACHE_FLUSH dma_sync_single_for_device
PCIE_DMA_IRQ_MASK_ALL 写 DWC PCIe DMA 中断 mask
PCIE_EP_RAISE_MSI 触发 MSI(测试/通知 RC)
PCIE_EP_SET_MMAP_RESOURCE 设置 cur_mmap_res
PCIE_EP_RAISE_IRQ_USER 用户 IRQ 索引,配合对象协议
PCIE_EP_POLL_IRQ_USER 轮询虚拟 ID / 状态

头文件中另有 PCIE_EP_GET_FUNC_DRV_VERSIONPCIE_EP_DMA_XFER_BLOCK连续缓冲 alloc/freePCIE_EP_SET_MMAP_RESOURCE_CONTINUOUS_BUFFER 等 —— 是否在你们内核的 pcie-dw-ep-rockchip.c 全部分支实现,请以该文件 switch(cmd) 为准;部分场景可能由 drivers/misc/rockchip/pcie-rkep.c 等模块补充。

4.4 BAR0 对象信息(协议层)

struct pcie_ep_obj_infork-pcie-ep.h):约定可放在 BAR0 的结构体(magic PCIE_EP_OBJ_INFO_MAGIC),含 mode/submodemsi_datairq/dma 状态字等,供 RC 与 EP 应用做握手;与 PCIE_EP_RAISE_IRQ_USER / PCIE_EP_POLL_IRQ_USER 同属一套对象协议。


5. 片上 PCIe UDMA:/dev/pcie-dev

驱动drivers/pci/controller/rockchip-pcie-dma.c
节点miscdevicename = "pcie-dev"

  • 依赖 CONFIG_ROCKCHIP_PCIE_DMA_OBJ,且 rk_pcie_dma_obj_probe()EP probe(如 rockchip_pcie_init_dma_trx)或 RC probe 路径上成功执行。
  • 接口include/uapi/linux/rk-pcie-dma.hmmap(local_mem)PCIE_DMA_START、读写缓冲索引、PCIE_DMA_WAIT_TRANSFER_COMPLETE 等。
  • 语义:在 本地 DRAM 地址PCI 总线地址 之间用 控制器内置 UDMA 搬运数据;需 对端配合映射/缓冲区约定,多用于 双芯片 DMA 演示或专用传输,不是标准 PCI Endpoint 类驱动的通用模型。

6. 应用选型建议

场景 推荐接口
EP SoC 用户态直接读写「与 RC 共享的 BAR backed 内存」 /dev/pcie_epPCIE_EP_SET_MMAP_RESOURCE + mmap + 按需 PCIE_DMA_CACHE_*
使用 Rockchip UDMA 固定缓冲协议与 RC 高速搬运 /dev/pcie-dev + rk-pcie-dma.h
pcie-rockchip-ep.c + 无厂商扩展 无现成 /dev:RC 映 BAR + EP 侧内核 pci_epf 或自定义驱动

7. 相关文档

文档
rk3588-kernel-6.1-rockchip-pcie-rockchip-rc-ep-dma分析.md

8. 修订记录

日期 说明
2026-05-08 初版:pcie_ep / pcie-devrk-pcie-ep.h 要点、与 pcie-rockchip-ep.c 区别

RK3588 kernel-6.1 — Rockchip pcie-rockchip* RC/EP 与 rockchip-pcie-dma 分析

RK3588 kernel-6.1 — Rockchip pcie-rockchip* RC/EP 与 rockchip-pcie-dma 分析

1. 文档范围与源码路径

文件 路径
公共层 drivers/pci/controller/pcie-rockchip.c
Root Complex(主机) drivers/pci/controller/pcie-rockchip-host.c
Endpoint(端点) drivers/pci/controller/pcie-rockchip-ep.c
PCIe UDMA / 用户态接口 drivers/pci/controller/rockchip-pcie-dma.c
DMA 结构与 probe 声明 drivers/pci/controller/rockchip-pcie-dma.h
寄存器与 struct rockchip_pcie drivers/pci/controller/pcie-rockchip.h
用户态 ioctl include/uapi/linux/rk-pcie-dma.h

说明:本组驱动源于 RK3399 时代 AXI PCIe Host 实现。RK3588 单板量产 RC 模式更常见绑定 drivers/pci/controller/dwc/pcie-dw-rockchip.c(DesignWare);本文所述 rockchip,rk3399-pcie / rockchip,rk3399-pcie-ep 与 DWC 树并存于源码树,实际启用与否以 defconfig 与 DTS compatible 为准。


2. 总体架构:四文件分工

1
2
3
4
5
6
7
8
9
pcie-rockchip.c          # DT 解析、时钟/复位/PHY、端口初始化(RC 或 EP 模式寄存器)

├──────────────────────────────────────┐
▼ ▼
pcie-rockchip-host.c pcie-rockchip-ep.c
pci_host_bridge + ECAM pci_epc + pci_epf 框架
可选接驳 rockchip-pcie-dma 本文件内不注册 rk_pcie_dma_obj_probe

└─► rockchip-pcie-dma.c(misc + ioctl + UDMA 描述符队列)

3. pcie-rockchip.c — RC/EP 共用层

3.1 rockchip_pcie_parse_dt()

  • RCplatform_get_resource_byname(..., "axi-base")devm_pci_remap_cfg_resourcerockchip->reg_base(下游配置 ECAM 等)。
  • EP"mem-base"rockchip->mem_res(供 pci_epc 分配 BAR 窗口的物理内存描述)。
  • 共用:apb-base、按 lane 的 pcie-phy-n(或 deprecated pcie-phy)、core/mgmt/mgmt-sticky/pipe/pm/pclk/aclk reset、多路时钟、num-lanesmax-link-speed
  • RC 专有:可选 ep GPIOGPIOD_OUT_LOW)。

3.2 rockchip_pcie_init_port()

关键寄存器 PCIE_CLIENT_CONFIG(定义见 pcie-rockchip.h):

组合 含义
PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC Root Complex:开启访问类型配置、LINK_TRAIN 等与 RC 流程配套
PCIE_CLIENT_CONF_DISABLE | PCIE_CLIENT_MODE_EP Endpoint:先保持 EP 所需禁用项

序列:断言各级 reset → PHY init → core reset → 选 Gen1/Gen2 → 写 PCIE_CLIENT_CONFIG → PHY power_on → 等待 PLL lock → 按 TRM 顺序 deassert mgmt_sticky/core/mgmt/pipe


4. RC 模式:pcie-rockchip-host.c

4.1 绑定与 PCI 核心对接

  • rockchip->is_rc = truecompatiblerockchip,rk3399-pcie
  • devm_pci_alloc_host_bridge + pci_host_probe(bridge) 完成枚举。

4.2 配置空间访问

  • RC 自身 Type0apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offsetrockchip_pcie_rd/wr_own_conf)。
  • 下游设备reg_base + PCIE_ECAM_OFFSET(bus, devfn, where),访问前 rockchip_pcie_cfg_configuration_accesses() 选择 AXI_WRAPPER_TYPE0_CFG / TYPE1_CFG
  • rockchip_pcie_valid_device():根桥下只允许 PCI_SLOT(devfn)==0,限制直连端口扫描宽度。

4.3 ATU 与 DMA workaround

  • rockchip_pcie_cfg_atu():编程 outbound MEM/IO、message region;若 dma_trx_enabled 为真,对 OB region 1 额外 rockchip_pcie_prog_ob_atu(..., mem_reserve_start, 0)(注释 Workaround for PCIe DMA transfer)。
  • dma_trx_enabled == 1rockchip_pcie_wait_l2() 直接返回 0(不强制进 L2,注释 Don’t enter L2 when no ep connected)。

4.4 内置 UDMA(RK3399 风格 APB 寄存器)

  • rk_pcie_config_dma_rk3399():在 dma_table->descs 填入 local/bus 地址 64 位buf_size、bit24 等(与 rockchip-pcie-dma.c 生成的表一致)。
  • rk_pcie_start_dma_rk3399():写 PCIE_APB_CORE_UDMA_BASE + 0x14*chn + {0x04,0x08,0x00}(描述符 PA 低/高、启动控制 BIT(0)|(dir<<1))。
  • 中断PCIE_CLIENT_INT_UDMArockchip_pcie_handle_dma_interrupt() 清除 PCIE_UDMA_INT_REG,更新 dma_trx_obj
  • probedma_trx_enabled != 0rk_pcie_dma_obj_probe(dev),并赋值 start_dma_func / config_dma_func

4.5 dma_trx_enabled 注意点

  • DTS 中可出现 rockchip,dma_trx_enabled(例如 rk3399pro-evb-v14-linux.dts)。
  • 当前仓库 rockchip_pcie_parse_host_dt() 未见对该属性的 of_property_read_*dma_trx_enabled 默认为 0;若需启用 DMA,须确认 厂商补丁是否在别处赋值,否则会跳过 rk_pcie_dma_obj_probe

5. EP 模式:pcie-rockchip-ep.c

5.1 绑定与框架

  • rockchip->is_rc = falsecompatiblerockchip,rk3399-pcie-ep
  • devm_pci_epc_create(dev, &rockchip_pcie_epc_ops),对上 pci_epf 驱动。

5.2 pci_epc_ops 要点

回调 作用
write_header Vendor/Device/Class/Subsystem/IRQ pin 等到 PCIE_EP_PF_CONFIG 区域
set_bar / clear_bar BAR aperture/type + ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_*(inbound:PCI→AXI)
map_addr / unmap_addr Outbound ATU:EP 访问 pci_addr 映射到本地 cpu_addr
set_msi / get_msi 编程片上 MSI capability 寄存器
raise_irq LEGACY:INTx pulse;MSI:配 OB ATU 后 writewirq_cpu_addr
start PCIE_CORE_PHY_FUNC_CFG 按已注册的 **pci_epf function_no` 使能

5.3 内存与链路

  • pci_epc_multi_mem_init:默认 mem-base 上每 SZ_1M 一块窗口。
  • irq_cpu_addr:从 pci_epc_mem_alloc_addr 分配 MSI 触发窗口
  • 链路: probe 末尾 PCIE_CLIENT_LINK_TRAIN_ENABLE,最后再 PCIE_CLIENT_CONF_ENABLE
  • MSI-X:通过改写 capability next pointer 把 MSI-X 条目移出链表,避免 RC 分配不可用向量。

5.4 与本目录 DMA 文件的关系

  • **pcie-rockchip-ep.c 不调用 rk_pcie_dma_obj_probe
  • 需要 片上 PCIe DMA + misc/ioctl 的 EP 场景,在同内核树中常体现在 dwc/pcie-dw-ep-rockchip.c(DesignWare)。

6. rockchip-pcie-dma.c — UDMA 与用户态协议

6.1 依赖配置

  • CONFIG_ROCKCHIP_PCIE_DMA_OBJ=yrk_pcie_dma_obj_probe/remove 为真实实现;否则 rockchip-pcie-dma.h 内联为空操作。

6.2 硬件抽象

  • struct dma_trx_obj:本地一致性缓冲区 dma_alloc_coherent、远端 PCI 地址 remote_mem_start(可由 region_base 共享内存握手)、多张 dma_tableworkqueuehrtimer rk_pcie_scan_timer(默认约 100µs 周期扫描 magic)。
  • RC 判定obj->busno == 0is_rc(obj)

6.3 缓冲区协议(注释摘要)

  • 每方向约 8MB 分区:wr buf / rd buf1MB 槽 × 多槽,头部 magic 0x12345678local idxpayload sizeack 使用 0xdeadbeef / 0xcafebabe
  • rk_pcie_prepare_dma()PCIE_DMA_DATA_SND / RCV_ACK / FREE_ACK / READ_REMOTEdma_table,调用 obj->config_dma_func(由 host 设为 rk_pcie_config_dma_rk3399 或 DWC 变体),并入队 dma_trx_workstart_dma_func

6.4 用户态接口

  • miscdeviceopen 初始化 dma_free、bitmapmmap remap_pfn_range(local_mem_start)
  • ioctl(见 rk-pcie-dma.h):PCIE_DMA_STARTGET_LOCAL_READ_BUFFER_INDEXFREE_LOCAL_READ_BUFFER_INDEXSYNC_*WAIT_TRANSFER_COMPLETESET_LOOP_COUNTREAD_FROM_REMOTE 等。
  • 缓存一致性:发送路径 dma_sync_single_for_device,接收 dma_sync_single_for_cpu

7. 与 DesignWare(RK3588 常用)对照

项目 本文 AXI 四文件 DWC:pcie-dw-rockchip.c / pcie-dw-ep-rockchip.c
Host compatible rockchip,rk3399-pcie rockchip,rk3568-pcie / rk3588-pcie
EP pcie-rockchip-ep.c pcie-dw-ep-rockchip.c
DMA 寄存器 APB PCIE_APB_CORE_UDMA_* DWC CDM / doorbell / context(rockchip_pcie_start_dma_dwc
dma_trx_obj host:rk_pcie_start_dma_rk3399 DWC:rockchip_pcie_init_dma_trx

移植或调试时请以 实际编译进内核的驱动 + DTS 为准。


8. 相关文档

文档 内容
rk3588-kernel-6.1-驱动DMA编程与PCIe设备DMA传输分析.md 通用 PCI 设备 DMA 编程
rk3588-kernel-6.1-pci总线架构分析.md drivers/pci 与 RK Host

9. 修订记录

日期 说明
2026-05-08 初版:pcie-rockchip* RC/EP、rockchip-pcie-dma、与 DWC 对照、dma_trx_enabled 说明

drivers/pci 源码目录、构建配置与模块索引

drivers/pci 源码目录、构建配置与模块索引

1. 范围与规模

源码基准为 rk3588/kernel-6.1/drivers/pci/。本树包含约 177 个 C 文件和 23 个内部头文件,既有跨架构 PCI Core,也有平台控制器、Endpoint、热插拔及 PCIe 端口服务。目录名虽为 PCI,但现代系统中的主要硬件通常是 PCI Express。

2. 顶层常驻 Core

CONFIG_PCI=y 时,顶层 Makefile固定编入:

文件 主要职责
access.c 配置空间读写、访问锁和用户态配置访问
bus.c pci_bus资源窗口、设备加入和总线遍历
probe.c Host Bridge 注册、BDF 扫描、pci_dev创建及桥递归
host-bridge.c Host Bridge 窗口和固件节点辅助
remove.c 设备停止、注销及子总线逆序拆除
pci.c 设备使能、电源、状态保存、复位、PCIe Capability 通用操作
pci-driver.c pci_bus_type、ID 匹配、probe/remove、PM 和错误回调
search.c 在已枚举对象中按 BDF、ID、Class 查找;不探测硬件
pci-sysfs.c 设备、总线、资源、配置空间及控制属性
rom.c Expansion ROM 资源与映射
setup-res.c 单设备 BAR 分配、写回和资源 claim
setup-bus.c 全拓扑桥窗口 sizing 与未分配资源处理
irq.csetup-irq.c INTx 路由及 IRQ 分配
vpd.c Vital Product Data 访问
vc.c PCIe Virtual Channel
mmap.c PCI 资源映射辅助

CONFIG_PCI还递归进入msi/pcie/,但其中对象继续受各自 Kconfig 控制。

3. 顶层条件模块

配置 文件/目录 功能
CONFIG_OF of.c DT ranges、bus-range、IRQ 等解析
CONFIG_ACPI pci-acpi.c ACPI companion、PM、_OSC 等协作
CONFIG_PCI_QUIRKS quirks.c Header/Final/Early/Enable/Resume fixup
CONFIG_HOTPLUG_PCI hotplug/ 热插拔 Core 及各类控制器
CONFIG_PCI_ATS ats.c ATS、PRI、PASID
CONFIG_PCI_IOV iov.c SR-IOV PF/VF
CONFIG_PCI_ECAM ecam.c Enhanced Configuration Access Mechanism
CONFIG_PCI_P2PDMA p2pdma.c PCIe Peer-to-Peer DMA
CONFIG_PCI_DOE doe.c Data Object Exchange mailbox
CONFIG_VGA_ARB vgaarb.c Legacy VGA 资源仲裁
CONFIG_PROC_FS proc.c /proc/bus/pci兼容接口

4. 子目录地图

子目录 定位
pcie/ PCIe Port Bus、AER、DPC、PME、ASPM、PTM、RCEC、EDR
msi/ MSI/MSI-X 描述符、IRQ domain 和向量生命周期
hotplug/ pciehp、ACPI、SHPC、GPIO 及架构专用热插拔
endpoint/ EPC、EPF、ConfigFS 和测试/NTB Function
controller/ Host/Endpoint 控制器平台驱动
controller/dwc/ Synopsys DesignWare 公共 Host/EP 层及平台 glue
controller/cadence/mobiveil/ 其它 PCIe IP 公共层
switch/ Switchtec 等 PCIe Switch 管理驱动

5. RK3588 实际重点

Rockchip defconfig 启用CONFIG_PCICONFIG_PCIEPORTBUS、ASPM、CONFIG_PCIE_ROCKCHIP_HOSTCONFIG_PCIE_DW_ROCKCHIP。其中:

  • RK3588 RC 主路径:controller/dwc/pcie-dw-rockchip.c
  • DWC 公共层:pcie-designware.cpcie-designware-host.c
  • Endpoint:部分配置启用pcie-dw-ep-rockchip.c
  • pcie-rockchip-host.c是较早 Rockchip PCIe IP 路线,不能与 RK3588 DWC 路线混为一谈;
  • x86、PowerPC、s390 等平台专用控制器和热插拔文件虽然在源码树中,但不会因“位于该目录”就在 RK3588 上运行。

6. 阅读顺序

建议按controller -> DWC Host -> probe -> setup-bus/setup-res -> bus -> pci-driver理解启动主链,再分别进入 MSI、PCIe 端口服务、PM/错误恢复和 Endpoint。只从probe.c开始会看不到配置事务如何由 RK3588 控制器真正发出。