Skip to main content
PCIe 使用双向连接同时发送和接收信息,如下图所示。
PCIe 设备连接链路

图: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)表示桥下游侧存在的编号最高的总线。
BDF 编号唯一标识每个设备。事务层数据包(TLP)的基于 ID 的路由方法使用此编号。PCIe 主机模式枚举过程包括以下步骤:
  1. 链路训练
  2. 扫描总线上的设备
  3. 注册
有关 PCIe 设备初始化、枚举过程的更多信息,请参阅 https://www.kernel.org/doc/html/latest/PCI/index.html

PCIe 分层架构

下图显示了 PCIe 软件架构。
PCIe 软件架构

图:PCIe 软件架构

下图显示了 PCIe 的分层架构模型。
PCIe 分层架构

图:PCIe 分层架构

交换的传输单元如下。
  • 物理层实体之间的有序集(Ordered set)。
  • 数据链路层实体之间的数据链路层数据包(DLLP)。
  • 事务层实体之间的事务层数据包(TLP)。
下表列出了 PCIe 架构中的三个层及其各自的功能。

表:PCIe 架构中的层

功能
物理层逻辑子块:链路训练、初始化和维护。
物理子块:8b/10b 编码和解码,以及并串和串并转换。
数据链路层DLLP 数据包的组装和拆解。
链路层 CRC(LCRC)的生成和验证。
应答和非应答协议(重放出错的 TLP)。
事务层TLP 数据包的组装和拆解。
端到端 CRC(ECRC)的生成和验证。
流量控制:接收实体使用 DLLP 通告可用的接收缓冲区大小信息。
服务质量(QoS):流量类别(TC)到虚拟通道(VC)的映射。
事务排序:在 VC 内实现事务排序规则。
如下图所示,PCI 为每个功能定义了一块专用的配置地址空间。软件确定功能的存在,对其进行配置,并检查和控制其状态。
PCIe 配置地址空间

图:PCIe 配置地址空间

PCIe 软件驱动程序配置

PCIe 控制器驱动程序初始化 PCIe 资源并执行链路训练。训练成功后,控制器驱动程序调用 PCIe 框架进行链路枚举,例如端点发现、识别客户端驱动程序以及探测这些驱动程序。有关 PCIe 框架和客户端驱动程序 PCIe 注册的更多信息,请参阅 https://www.kernel.org/doc/html/latest/PCI/index.html

链路训练

链路训练包括以下操作:
  1. 位于 https://github.com/torvalds/linux/blob/master/drivers/pci/controller/dwc/pcie-qcom.c 的 PCIe 驱动程序 pcie-qcom.c 文件从设备树获取所需资源,例如稳压器、时钟。
  2. PCIe 驱动程序调用位于 https://github.com/torvalds/linux/blob/master/drivers/pci/controller/dwc/pcie-designware-host.c 的 Synopsys DesignWare® Core 主机驱动程序 pcie-designware-host.c 文件来初始化根复合体。
  3. Synopsys DesignWare Core 驱动程序执行所有必要的初始化。
  4. Synopsys DesignWare Core 驱动程序调用函数指针以执行主机初始化。
  5. Qualcomm PCIe 驱动程序执行 PHY 上电,启用所有稳压器、时钟。
  6. Synopsys DesignWare Core 驱动程序通过调用启动链路的函数指针来开始链路训练。

硬件初始化

驱动程序初始化并配置 PCIe 硬件模块并执行链路训练。初始化在调用 platform _probe() 驱动程序函数之后进行。
当 Synopsys DesignWare Core 驱动程序初始化时,它还会初始化 MSI、MSIx 和控制器。该驱动程序调用 Qualcomm 函数指针来启动链路训练。
Synopsys DesignWare Core 驱动程序等待链路激活后再对 PCI 框架进行枚举。Qualcomm PCIe 驱动程序仅启用链路训练。
注意:PCIE_0 根复合体实例默认启用,用于 WLAN EP 连接。

启用 QPS615 PCIe 交换机

本节介绍如何在 Qualcomm Linux 硬件 SoC 中启用 QPS615 PCIe 交换机。QPS615 交换机端点在 PCIe1 实例上受支持。下图显示了 QPS615 端点及其连接。
QPS615 PCIe 交换机连接图

图:QPS615 PCIe 交换机连接图

可以在以下位置访问 Qualcomm PCIe 驱动程序文档:

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 GbEIX/RJ45 连接器(QEP8121)
  • 默认启用。
AQR PHY (USXGMII)10 GbEIX/RJ45 连接器(AQR113C)
  • 10 千兆以太网 AQR PHY 是 RB3 Gen 2 开发套件以及 Dragonwing IQ-8275 和 Dragonwing IQ-9075 评估套件(EVK)中的可选组件。 它已在 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。
USB 集线器的供电通过 pwrctrl 驱动程序启用,有关这些详细信息,请参阅以下上游链接。 https://elixir.bootlin.com/linux/v7.1/source/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts#L896 https://elixir.bootlin.com/linux/v7.1/source/Documentation/devicetree/bindings/usb/renesas,upd720201-pci.yaml https://elixir.bootlin.com/linux/v7.1/source/drivers/pci/pwrctrl/generic.c

下载 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 固件之前,按照设置设备部分中的说明更新软件。
选项 1(Ubuntu):使用 SCP 或类似工具推送固件文件。例如,
选项 2(Yocto):
  1. 通过 USB 线将设备连接到主机 PC 以使用 adb。
  2. 将固件推送到设备。
  3. 要激活固件,请执行以下任一选项。
    • 选项 A:重启目标设备以启用 USB Type A 端口。
    • 选项 B:手动绑定 Renesas xHCI 驱动程序。
  4. 验证固件枚举。

PCIe 转 USB 设备枚举参考的 PCIe 内核驱动程序日志

您可以运行以下命令查看设备信息:
  • 要显示 USB 中的设备信息,请运行以下命令。
    将显示以下消息。
  • 要显示 PCIe 中的设备信息,请运行以下命令。
    将显示以下消息。

级联连接 QPS615 交换机

以级联方式连接 QPS615 交换机可启用额外的以太网、PCIe 和 USB 端口。
注意:此功能仅在 QCS6490 中受支持。
下图显示了两个以级联方式连接到 PCIE1 的 QPS615 交换机,以及另一个连接到 PCIE2 的 QPS615 交换机。
QPS615 级联连接

图:QPS615 交换机级联连接

要为所有端点启动链路训练和枚举,请执行以下操作:
  1. 要重置 QPS615 交换机,请切换 QPS615 #1 和 QPS615 #2 的 RESX GPIO。
  2. 要控制端点重置,请触发 PERST。两个交换机共享 PERST。
设备可以直接连接到 QPS615 交换机。PCIe RC0 连接到 WLAN 端点。以下差异由 PCIe 节点层次结构造成。
  • 连接到交换机的设备:
    • QPS615 PCIe 树节点层次结构是静态固定的。
    • 用于交换 USP 和 DSP 端口的所有节点都在 PCIe 初始化期间创建。
    • 交换机 DSP 端口之一代表 WLAN。
    • 如果禁用 WLAN 节点,则会禁用 WLAN 设备,但 PCIe 下游端口仍保持启用状态,并返回默认最大链路宽度。
  • 直接连接的 WLAN 设备:
    • 仅禁用单个节点。
    • 禁用 WLAN 时,返回 Invalid argument。

通过 PCIe 接口启用 NVMe

本节介绍如何使用 PCIe 启用 NVMe 以进行存储扩展。要验证 NVMe 是否通过 PCIe 接口连接,请执行以下操作:
  1. 要显示 PCIe 设备信息,请运行以下命令。
    输出:
  2. 找到 PCIe 日志。
    输出:
  3. 要找到 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 问题

lspcisetpci 命令是 Linux 发行版的原生命令。这些命令有多种级别的输出。这些命令还提供了一个有用的即时视图,用于查看 PCI 总线上完成训练的不同组件的能力和状态。这些能力大多是 PCIe 基础规范所要求的配置空间寄存器的映射。有关更多详细信息,请参阅 https://pcisig.com/specifications。要查看使用说明,请运行以下命令。
以下功能对排查 PCIe 问题很有用。
  • 显示设备信息
    将显示以下消息。
  • 显示设备控制寄存器中的 PCIe 设备和供应商 ID。
    将显示以下消息。
有关 PCIe 调试的更多信息,请参阅 https://www.kernel.org/doc/html/v4.17/driver-api/pci.html

PCIe 示例

有关上游设备树参考的信息,请参阅以下文件。 有关 Qualcomm Linux 硬件 SoC 的设备树节点的信息,请参阅以下 DTSI 文件。

客户端与 PCI 驱动程序操作流程示例

下图显示了 PCIe 客户端驱动程序为客户端配置 PCIe 驱动程序所遵循的序列。
PCIe 设备连接链路

客户端与 PCI 驱动程序高层调用流程示例

下图显示了 PCIe 客户端驱动程序与 PCIe 驱动程序之间的高层调用流程和调用详情。
PCIe 设备连接链路