rk3588 pcie驱动分析之一 (pcie控制器抽象)

本系列文章将完整描述rk3588 pcie驱动内容。涉及pcie协议相关的内容请参考王齐的 《PCIExpress体系结构导读》。本文是整个系列的前置内容,主要讲述pcie控制器自身在linux pci子系统中的抽象,后面在讲述pcie设备的整个枚举流程时这些抽象部件会再次出现。

1、rk3588 pcie控制器抽象

RK3588的PCIe控制器内部构成,可以理解为一个从软件到硬件的层级结构。

1.1、软件抽象层:Linux内核PCI子系统

在Linux内核中,PCIe控制器被抽象为以下几个核心数据结构,它们是理解整个架构的基础:

它负责管理该控制器下的所有总线和设备,并提供访问配置空间方法。

  • pci_host_bridge(主机桥):这是整个PCIe树的软件起点,在RK3588的驱动中,它代表了一个PCIe控制器实例(例如pcie@fe150000节点),
  • pci_bus(总线):代表一条PCIe总线,通过pci_host_bridge创建根总线(Root Bus,通常是Bus 0),之后通过桥设备级联出更多的子总线形成树状结构。
  • pci_dev(设备):代表总线上的一个具体设备,比如根端口(Root Port)或终端设备(Endpoint),在枚举过程中,内核会为每个发现的设备创建此结构。

1.2、硬件层:RK3588 PCIe控制器

RK3588的PCIe控制器基于Synopsys DesignWare PCIe IP构建,其内部包含多个关键硬件模块:

  • Root Complex(RC,根复合体):这是PCIe拓扑的根节点,负责连接CPU/内存子系统与PCIe链路,RK3588的每个PCIe控制器内部都包含一个RC。
  • Root Port(RP,根端口):这是RC内部的一个逻辑端口,可以理解为PCIe总线树的"出口",每个Root Port下会挂载一条独立的PCIe总线,
  • iATU(内部地址转换单元):这是DesignWare PCIe IP的核心地址映射引擎,它负责在CPU的物理地址空间和PCIe的总线地址空间之间进行转换。

RK3588的控制器支持多个iATU Region(如8 ATU inbound regions,8 ATU outbound regions),用于高效地管理地址映射。

1.3、host bridge

Host Bridge(主机桥):是整个PCIe域的软件抽象(struct pci_host_bridge),代表一个PCIe控制器(Root Complex)。

它负责创建并管理根总线(Bus 0),并提供配置空间访问方法(pci_ops),它本身不是一个挂在总线上的PCI设备,因此不会出现在Bus 0的设备列表中。

Bus 0(根总线):Host Bridge创建的第一条PCIe总线,也是整个PCIe树的根。

它由pci_host_bridge通过pci_register_host_bridge()创建,其总线号通常为0(但也可以由设备树指定其他起始号)

Bus 0上的设备包括Root Port,Bus 1上的设备包括PCIe交换机上行端口,以及直接连接的端点设备(Endpoint)等。

分析下面rk3588的pcie拓扑结构:

lspci -t

-0000:00---00.0-01-ff----00.0

lspci -nn

00:00.0 PCI bridge 0604: Rockchip Electronics Co., Ltd Device 1d87:3588 (rev 01)

01:00.0 Processing accelerators 1200: Huawei Technologies Co., Ltd. Device 19e5:d500 (rev 23)

00:00.0:位于Bus 0,设备 0,功能 0,是一个PCI 桥(Root Port),来自Rockchip RK3588

01:00.0:位于Bus 1,设备 0,功能 0,是一个处理加速器(Endpoint),来自华为AScend

分析下面rk3588的pcie拓扑结构:

root@OpenEuler \~# lspci -t

-+-0000:00-

+-0002:20---00.0-21----00.0

\-0003:30---00.0-31----00.0

-+-0000:00-

表示Domain 0000,Bus 00的根总线,它是系统的主PCI域,但总线下方没有列出任何设备

+-0002:20---00.0-21----00.0

这是一个独立的PCI域:

0002:20:Domain 0002,Bus 20的根总线,该根总线为RK3588内部PCIe 控制器的Root Complex内部总线

---00.0:该总线上有一个设备,地址为00.0(设备 0,功能 0),是RK3588 PCIe控制器内部的Root Port

-21:这个设备是一个PCI桥(Root Port),它的下游总线号是21

----00.0:在总线21上有一个端点设备,地址为00.0

\-0003:30---00.0-31----00.0

结构与上面完全类似:

0003:30:Domain 0003,Bus 30的根总线

---00.0:总线30上的桥设备(Root Port)

-31:下游总线31

----00.0:总线31上的端点设备

在PCIe体系结构中,Root Complex(RC)通常包含一个或多个Root Port,每个Root Port在PCI配置空间中表现为一个PCI-to-PCI桥设备。

PCI-to-PCI桥(简称P2P桥)是PCI/PCIe体系结构中的核心组件,用于连接两条PCI总线,实现总线间的地址转换、事务转发和资源隔离。

Linux内核在枚举PCIe总线时,会将Root Port识别为标准的PCI桥,并赋予它们独立的BDF(总线号:设备号.功能号)

root@OpenEuler \~# lspci -nn

0002:20:00.0 PCI bridge 0604: Rockchip Electronics Co., Ltd Device 1d87:3588 (rev 01)

0002:21:00.0 Ethernet controller 0200: Device 1f0a:6801 (rev 01)

0003:30:00.0 PCI bridge 0604: Rockchip Electronics Co., Ltd Device 1d87:3588 (rev 01)

0003:31:00.0 Network controller 0280: Broadcom Inc. and subsidiaries Device 14e4:449d (rev 02)

通过上述打印信息可知,root port本质就是一个pci桥设备。

1.4、root port

在Linux PCI子系统中,Host Bridge本身不是PCI设备,因此不会出现在lspci列表中,它是软件抽象,代表整个PCIe控制器(Root Complex)。

Root Port是Host Bridge内部的一个逻辑端口,它会作为PCI桥设备出现在根总线上。

根据PCIe规范,Root Port被定义为一个PCI-PCI 桥(PCI-to-PCI Bridge),具有以下核心属性:

每个Root Port管理一条独立的PCIe链路。

  • Device/Port Type:在PCIe Capability寄存器的Capabilities字段中,类型编码为0x4(PCI_EXP_TYPE_ROOT_PORT)
  • 功能定位:它是Root Complex的出口,负责将CPU/内存子系统与下游PCIe链路连接起来,一个Root Complex可以包含多个Root Port,
  • 配置空间:Root Port使用Type 1配置空间头部(与PCI-PCI桥相同)包含Primary Bus、Secondary Bus、Subordinate Bus等寄存器,

以及Memory Base/Limit,I/O Base/Limit 等资源窗口寄存器。

1.5、pcie协议中RC示意图

pcie协议中配置拓扑图,结合上面的文字描述,更加容易理解RC的内部构造。

注意:对于pcie switch,其上下游端口都是一个pci-to-pci桥。

提示:对于pcie RC结构中的host bridge,root port的理解一定要准确,因为在后面的linux内核pci子系统中会去创建host bridge,root port等数据结构,这里理解清楚了分析代码时就不会困惑了。

1.6、type 0/1配置空间

pcie协议 type 0/1 配置空间详细如下:

其中关键的寄存器的说明在驱动代码中遇到时再进行详细说明,这里不再赘述,感兴趣的同学可以参考其他文章先行查看了解。

相关推荐
Surpass-HC1 小时前
WSL2 windows-ubuntu
linux·windows·ubuntu
ss2731 小时前
PG实战笔记 | 06 PostgreSQL基础安装部署:Linux/Windows/macOS全攻略
linux·笔记·postgresql
zbyyd1 小时前
Linux 驱动开发实战:从手写 LED 字符设备驱动到设备树
linux·驱动开发
灯澜忆梦2 小时前
【Linux】#7 | vi/vim 编辑器
linux·编辑器·vim
Escalating_xu2 小时前
【Linux 网络编程】UDP Socket 编程(上):从地址与字节序到完整回显服务器
linux·服务器·网络
重生之小比特2 小时前
【Linux系统】08 进程切换
linux·运维·服务器
kyle~2 小时前
Linux --- 内存管理内核子系统
linux·运维·服务器
昌原的儿子LEO2 小时前
嵌入式 Linux I2C 驱动开发核心知识总结:设备树与 platform 架构全解析
linux·驱动开发·架构
程序员-Benothing2 小时前
Linux内存管理详解:free、vmstat、buff/cache、swap
linux·运维·服务器