本文主要以rk3588 pcie3.0 x4节点为例,说明pcie设备树配置内容的含义
1、rk3588 pcie设备树配置
bash
arch/arm64/boot/dts/rockchip/rk3588.dtsi
pcie3x4: pcie@fe150000/*APB 控制寄存器基地址*/ {
compatible = "rockchip,rk3588-pcie", "snps,dw-pcie"/*Synopsys DesignWare PCIe IP 核心*/;
#address-cells = <3>;
#size-cells = <2>;
bus-range = <0x00 0x0f>;
clocks = <&cru ACLK_PCIE_4L_MSTR>, <&cru ACLK_PCIE_4L_SLV>,
<&cru ACLK_PCIE_4L_DBI>, <&cru PCLK_PCIE_4L>,
<&cru CLK_PCIE_AUX0>, <&cru CLK_PCIE4L_PIPE>;
clock-names = "aclk_mst", "aclk_slv",
"aclk_dbi", "pclk",
"aux", "pipe";
device_type = "pci"; /*设备节点的类型,这里为pci*/
interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "sys", "pmc", "msg", "legacy", "err";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie3x4_intc 0>,
<0 0 0 2 &pcie3x4_intc 1>,
<0 0 0 3 &pcie3x4_intc 2>,
<0 0 0 4 &pcie3x4_intc 3>;
linux,pci-domain = <0>;
num-ib-windows = <16>;
num-ob-windows = <16>;
num-viewport = <8>;
max-link-speed = <3>;
msi-map = <0x0000 &its1 0x0000 0x1000>;
num-lanes = <4>;
phys = <&pcie30phy>;
phy-names = "pcie-phy";
power-domains = <&power RK3588_PD_PCIE>;
ranges = <0x00000800 0x0 0xf0000000 0x0 0xf0000000 0x0 0x100000 /*配置空间*/
0x81000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x100000 /*I/O空间*/
0x82000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0xe00000 /*32bit非预取内存空间*/
0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>; /*64bit预取内存空间*/
reg = <0x0 0xfe150000 0x0 0x10000>, /*APB*/
<0xa 0x40000000 0x0 0x400000>; /*DBI*/
reg-names = "pcie-apb", "pcie-dbi";
resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>;
reset-names = "pcie", "periph";
rockchip,pipe-grf = <&php_grf>;
status = "disabled";
pcie3x4_intc: legacy-interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 260 IRQ_TYPE_EDGE_RISING>;
};
};
&pcie3x4 {
reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie30>;
pinctrl-names = "default"; /*管脚复用配置*/
pinctrl-0 = <&pcie30x4_clkreqn_m1>;
status = "okay";
};
2、芯片支持分配的BAR空间地址域

低端BAR地址范围是给32bit地址空间使用,高端BAR地址范围是给64bit地址空间使用。
3、PCI地址转换
PCI地址空间和CPU地址空间完全独立,所以地址转换是将PCI地址转换为CPU地址,在设备树中需要使用range,#address-cells和#size-cells属性来完成。
PCI设备配置空间中BAR空间配置的是PCIE域地址空间范围,而设备树中ranges中配置的是cpu域地址范围。
PCI地址使用3个cells,cpu地址使用2个cells,空间大小使用2个cells,cells的大小为4字节。
为什么PCI地址需要使用3个cells?这三个cells分别是标识phys.hi, phys.mid and phys.low
- phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
- phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh
- phys.low cell: llllllll llllllll llllllll llllllll
如果PCI地址为64位,就使用phys.mid and phys.low构成64位地址
phys.high的成员含义如下:
n(bit 31): relocatable region flag (在此不起作用)
p(bit 30): prefetchable (cacheable) region flag,1:预取,0:非预取
t(bit 29): aliased address flag (在此不起作用)
ss(bit 25 24): space code,空间类型编码
- 00: configuration space,配置空间
- 01: I/O space,I/O空间
- 10: 32 bit memory space,32bit 存储空间
- 11: 64 bit memory space,64bit 存储空间
bbbbbbbb: The PCI bus number. 总线号(8bit)
ddddd: The device number. 设备号(5bit)
fff: The function number. Used for multifunction PCI devices.功能号(3bit)
rrrrrrrr: Register number; used for configuration cycles. 寄存器号(8bit)
就PCI地址转换而言,关键字段是p和ss。phys.hi中的p和ss值决定了当前访问的是哪一类PCI地址空间。
所以range中配置信息分析如下:
0x00000800 0x0 0xf0000000 0x0 0xf0000000 0x0 0x100000,配置空间,起始于PCI地址0xf0000000,大小为1MB,将被映射到主机CPU的0xf0000000地址上。
0x81000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x1000000,I/0空间,起始于PCI地址0xf0100000,大小为1MB,将被映射到主机CPU的0xf0100000地址上。
0x82000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0xe00000,32位不可预取内存区域,起始于PCI地址0xf0200000,大小为14MB,将被映射到主机CPU的0xf0200000地址上。
0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;,64位可预取内存区域,起始于PCI地址0x900000000,大小为1GB,将被映射到主机CPU的0x900000000地址上。
设备树中其他成员的含义在后续驱动详述中会描述其功能以及作用。