图:PCIe 设备连接链路
设备之间的路径称为链路(Link)。它由一个或多个发送和接收对组成。链路的一个收发对称为通道(Lane)。Qualcomm Linux 设备中的 PCIe 设备连接支持 16 条通道。通道数量或链路宽度为 x16。 下表列出了设备的 PCIe 连接类型。表:PCIe 连接
| PCIe 类型 | 描述 |
|---|---|
| 根复合体(RC) | 将 CPU 连接到 PCIe 拓扑 |
| 交换机 | 连接 2 个以上的端口,并充当数据包路由器 |
| 桥 | 连接不同的总线:例如,PCIe 到 PCIe,或 PCIe 到外设组件互连(PCI) |
| 端点(EP) | 位于 PCIe 拓扑树结构的底部,只有一个上游端口 |
| 传统端点 | 使用较旧的 PCI 总线操作以支持向后兼容 |
PCIe 主机模式枚举功能
系统首次上电时,运行在系统主处理器上的配置软件仅知道 Bus 0 的存在(如果支持 PCIe)。该软件不了解总线拓扑或连接到总线的任何设备。枚举过程会发现系统中存在的各种总线、设备和功能。 枚举完成后,系统中的每条总线按如下方式编号:- 主总线编号(primary bus number)表示直接连接到桥的主接口的总线(朝向根复合体)。
- 次总线编号(secondary bus number)表示直接连接到桥的次接口的总线(远离根复合体)。
- 从属总线编号(subordinate bus number)表示桥下游侧存在的编号最高的总线。
- 链路训练
- 扫描总线上的设备
- 注册
PCIe 分层架构
下图显示了 PCIe 软件架构。
图:PCIe 软件架构
下图显示了 PCIe 的分层架构模型。图:PCIe 分层架构
交换的传输单元如下。- 物理层实体之间的有序集(Ordered set)。
- 数据链路层实体之间的数据链路层数据包(DLLP)。
- 事务层实体之间的事务层数据包(TLP)。
表:PCIe 架构中的层
| 层 | 功能 |
|---|---|
| 物理层 | 逻辑子块:链路训练、初始化和维护。 |
| 物理子块:8b/10b 编码和解码,以及并串和串并转换。 | |
| 数据链路层 | DLLP 数据包的组装和拆解。 |
| 链路层 CRC(LCRC)的生成和验证。 | |
| 应答和非应答协议(重放出错的 TLP)。 | |
| 事务层 | TLP 数据包的组装和拆解。 |
| 端到端 CRC(ECRC)的生成和验证。 | |
| 流量控制:接收实体使用 DLLP 通告可用的接收缓冲区大小信息。 | |
| 服务质量(QoS):流量类别(TC)到虚拟通道(VC)的映射。 | |
| 事务排序:在 VC 内实现事务排序规则。 |
图:PCIe 配置地址空间
PCIe 软件驱动程序配置
PCIe 控制器驱动程序初始化 PCIe 资源并执行链路训练。训练成功后,控制器驱动程序调用 PCIe 框架进行链路枚举,例如端点发现、识别客户端驱动程序以及探测这些驱动程序。有关 PCIe 框架和客户端驱动程序 PCIe 注册的更多信息,请参阅 https://www.kernel.org/doc/html/latest/PCI/index.html。链路训练
链路训练包括以下操作:- 位于 https://github.com/torvalds/linux/blob/master/drivers/pci/controller/dwc/pcie-qcom.c 的 PCIe 驱动程序
pcie-qcom.c文件从设备树获取所需资源,例如稳压器、时钟。 - PCIe 驱动程序调用位于 https://github.com/torvalds/linux/blob/master/drivers/pci/controller/dwc/pcie-designware-host.c 的 Synopsys DesignWare® Core 主机驱动程序 pcie-designware-host.c 文件来初始化根复合体。
- Synopsys DesignWare Core 驱动程序执行所有必要的初始化。
- Synopsys DesignWare Core 驱动程序调用函数指针以执行主机初始化。
- Qualcomm PCIe 驱动程序执行 PHY 上电,启用所有稳压器、时钟。
- Synopsys DesignWare Core 驱动程序通过调用启动链路的函数指针来开始链路训练。
硬件初始化
驱动程序初始化并配置 PCIe 硬件模块并执行链路训练。初始化在调用platform _probe() 驱动程序函数之后进行。
注意:PCIE_0 根复合体实例默认启用,用于 WLAN EP 连接。
启用 QPS615 PCIe 交换机
本节介绍如何在 Qualcomm Linux 硬件 SoC 中启用 QPS615 PCIe 交换机。QPS615 交换机端点在PCIe1 实例上受支持。下图显示了 QPS615 端点及其连接。
图:QPS615 PCIe 交换机连接图
可以在以下位置访问 Qualcomm PCIe 驱动程序文档:- https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/pci/qcom%2Cpcie-sc8280xp.yaml
- https://elixir.bootlin.com/linux/v6.6.48/source/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
- https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/phy/qcom%2Csc8280xp-qmp-pcie-phy.yaml
PCIe 相关配置
以下配置默认启用以支持 QPS615 交换机。若要将其用于其他 PCIe 端点,请通过还原代码更改来禁用 QPS615 交换机的默认支持。 要启用 PCIe 相关configs,请将以下补丁应用于 /arch/arm64/configs/qcom_addons.config 文件。
消息信号中断(MSI)
当前的 MSI 映射并不包含所有向量。Qualcomm Linux 硬件 SoC 支持八个向量。每个向量又支持 32 个 MSI。因此,总共支持 256 个 MSI。 有关为此 PCIe 实例添加所有受支持 MSI 组的信息,请参阅 https://lore.kernel.org/linux-arm-msm/f1168212-bc6e-4570-869c-2870d6f248ad@linaro.org/T/。PCIe 内核驱动程序日志示例
以下是来自 QPS615 设备枚举的 PCIe 内核驱动程序日志示例。通过 QPS615 PCIe 交换机支持的以太网接口
QPS615 PCIe 交换机为设备启用以太网连接。当设备加载 QPS615 驱动程序并建立 PCIe 链路后,默认情况下会在设备启动期间自动激活受支持的以太网接口。 要自定义默认配置或启用 Qualcomm 硬件设置之外的额外 MAC/PHY 组件,请参阅 Qualcomm Linux 以太网指南中的 Bring up Ethernet 部分。表:支持的以太网接口
| 接口类型 | 速度 | 连接器类型 | 描述 |
|---|---|---|---|
| QEP PHY (SGMII) | 2.5 GbE | IX/RJ45 连接器(QEP8121) |
|
| AQR PHY (USXGMII) | 10 GbE | IX/RJ45 连接器(AQR113C) |
|
启用备用硬件组件
您可以连接 Qualcomm 提供的硬件配置之外的其他 MAC/PHY 组件并将其启用。 要用其他基于 PCIe 的 MAC/PHY 替换 QPS615,请参阅启用 QPS615 PCIe 交换机。注意:您必须从相应供应商处获取 MAC/PHY 驱动程序和固件。Qualcomm 不对这些配置更改负责。
通过 PCIe 交换机启用 USB 接口
本节说明如何在 Qualcomm Linux 硬件 SoC 中通过 PCIe 交换机激活 USB 接口。PCIE1 实例连接到 QPS615 交换机的端点,QPS615 的下游端口连接到 PCIe 转 USB 端点。有关使用 QPS615 的 PCIe 转 USB 端点连接,请参阅 https://docs.qualcomm.com/bundle/publicresource/topics/80-80021-251/rb3_hardware_overview.html 中的主板和转接板框图。注意:Dragonwing IQ-9075 PCIe 软件不支持 USB。
下载 PCIe 转 USB 控制器固件
要从 https://www.renesas.com/us/en/products/interface/usb-switches-hubs/upd720201-usb-30-host-controller#design_development 下载固件,请在 https://www.renesas.com/ 注册并登录。将下载的固件文件重命名为 renesas_usb_fw.mem。注意:为防止命令失败,请在更新 Renesas 固件之前,按照设置设备部分中的说明更新软件。
- 通过 USB 线将设备连接到主机 PC 以使用 adb。
- 将固件推送到设备。
- 要激活固件,请执行以下任一选项。
- 选项 A:重启目标设备以启用 USB Type A 端口。
- 选项 B:手动绑定 Renesas xHCI 驱动程序。
- 验证固件枚举。
PCIe 转 USB 设备枚举参考的 PCIe 内核驱动程序日志
您可以运行以下命令查看设备信息:- 要显示 USB 中的设备信息,请运行以下命令。
将显示以下消息。
- 要显示 PCIe 中的设备信息,请运行以下命令。
将显示以下消息。
级联连接 QPS615 交换机
以级联方式连接 QPS615 交换机可启用额外的以太网、PCIe 和 USB 端口。注意:此功能仅在 QCS6490 中受支持。
图:QPS615 交换机级联连接
- 要重置 QPS615 交换机,请切换 QPS615 #1 和 QPS615 #2 的 RESX GPIO。
- 要控制端点重置,请触发 PERST。两个交换机共享 PERST。
- 连接到交换机的设备:
- QPS615 PCIe 树节点层次结构是静态固定的。
- 用于交换 USP 和 DSP 端口的所有节点都在 PCIe 初始化期间创建。
- 交换机 DSP 端口之一代表 WLAN。
- 如果禁用 WLAN 节点,则会禁用 WLAN 设备,但 PCIe 下游端口仍保持启用状态,并返回默认最大链路宽度。
- 直接连接的 WLAN 设备:
- 仅禁用单个节点。
- 禁用 WLAN 时,返回 Invalid argument。
通过 PCIe 接口启用 NVMe
本节介绍如何使用 PCIe 启用 NVMe 以进行存储扩展。要验证 NVMe 是否通过 PCIe 接口连接,请执行以下操作:- 要显示 PCIe 设备信息,请运行以下命令。
输出:
- 找到 PCIe 日志。
输出:
- 要找到 NVMe 目录,请运行以下命令。
输出:
PCIe 客户端驱动程序示例
客户端驱动程序定义device-id 表和 pci_driver 结构,并向 PCIe 框架注册。以下是一些 PCIe 客户端驱动程序示例,供参考。
- 用于保存客户端特定私有数据的示例数据结构。
- 示例驱动程序:您可以根据驱动程序特定的数据结构提供数据。
- 包含驱动程序特定数据的示例设备 ID 表。客户端驱动程序以
0x306设备 ID 进行注册。
注意:
MODULE_DEVICE_TABLE(pci, sample_pci_id_table); 是必需的。- 包含客户端驱动程序名称、
pci-id表和回调的示例pci_driver数据结构。在向 PCI 框架注册时会传递指向此结构的指针。 - 要向 PCI 框架注册,请从
module_init()中调用pci_register_driver(&sample_pci_driver)。
PCIe 启动(bringup)
有关 PCIe 启动的信息,请参阅 PCIe 相关配置和 QPS615 交换机支持。PCIe 电源优化
PCIe 定义了两种电源管理方法。- 电源管理软件:确定每个设备的电源管理能力,并单独管理每个设备
- 无需软件干预的机制,例如活动状态电源管理(ASPM)
PCIe L0 链路状态
PCIe 电源管理定义了以下 L0 链路状态:- L0:活动状态,所有 PCIe 事务和其他操作均已启用
- L0s:具有低恢复延迟的 ASPM 状态(节能待机状态)
PCIe 设备状态
PCIe 电源管理定义了以下设备状态:- D0(必需):设备处于完全开启状态,其中有两个子状态
- D0uninitialized:设备复位后,功能处于 D0uninitialized 状态,等待被枚举和配置。
- D0active
- 枚举和配置过程完成后,功能处于 D0active 状态。
- 当系统软件启用一个或多个(任意组合)功能参数(例如内存空间使能、I/O 空间使能或 BME 位)时,功能进入 D0active 状态。
- D1(可选):浅睡眠状态
- 除 PME 消息外,功能不能发起 TLP
- 除配置事务外,功能不能作为事务的目标。
- 功能通过对 PM 控制和状态寄存器进行编程来发出软件命令以进入 D1 状态。
- D2(可选):深睡眠状态
- 除 PME 消息外,功能不能发起 TLP
- 除配置事务外,功能不能作为事务的目标。
- 功能通过对 PM 控制和状态寄存器进行编程来发出软件命令以进入 D2 状态。
- D3(必需):设备处于最低功耗状态,功能必须同时支持两种 D3 状态
- D3hot
- 除 PME 消息外,功能不能发起 TLP。
- 除配置事务外,功能不能作为事务的目标。
- 功能通过对电源状态字段进行编程来发出软件命令以进入 D3hot 状态。
- D3cold:设备进入 D3cold 状态并断电;恢复供电后,设备进入 D0uninitialized 状态。
PCIe 验证
有关 PCIe 验证的信息,请参阅 PCIe 相关配置和 QPS615 交换机支持。调试 PCIe 问题
lspci 和 setpci 命令是 Linux 发行版的原生命令。这些命令有多种级别的输出。这些命令还提供了一个有用的即时视图,用于查看 PCI 总线上完成训练的不同组件的能力和状态。这些能力大多是 PCIe 基础规范所要求的配置空间寄存器的映射。有关更多详细信息,请参阅 https://pcisig.com/specifications。要查看使用说明,请运行以下命令。
- 显示设备信息
将显示以下消息。
- 显示设备控制寄存器中的 PCIe 设备和供应商 ID。
将显示以下消息。
PCIe 示例
有关上游设备树参考的信息,请参阅以下文件。- QCS6490 和 QCS5430:https://elixir.bootlin.com/linux/v7.0-rc7/source/arch/arm64/boot/dts/qcom/kodiak.dtsi
- Dragonwing IQ-9075:https://elixir.bootlin.com/linux/v7.0-rc7/source/arch/arm64/boot/dts/qcom/lemans.dtsi
- Dragonwing IQ-615:https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/tree/arch/arm64/boot/dts/qcom/qcs615.dtsi?h=arm64-for-6.16
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/dwc/pcie-qcom.c?h=v6.8-rc6#n1634
- QCS6490 和 QCS5430:https://elixir.bootlin.com/linux/v7.0-rc7/source/arch/arm64/boot/dts/qcom/kodiak.dtsi
- Dragonwing IQ-9075:https://elixir.bootlin.com/linux/v7.0-rc7/source/arch/arm64/boot/dts/qcom/lemans.dtsi
- Dragonwing IQ-615:https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git/tree/arch/arm64/boot/dts/qcom/qcs615.dtsi?h=arm64-for-6.16
客户端与 PCI 驱动程序操作流程示例
下图显示了 PCIe 客户端驱动程序为客户端配置 PCIe 驱动程序所遵循的序列。
客户端与 PCI 驱动程序高层调用流程示例
下图显示了 PCIe 客户端驱动程序与 PCIe 驱动程序之间的高层调用流程和调用详情。

