18.PCIe总线入门理解与Linux上PCIe设备配置与使用

一、ARM和x86上PCIe接口

参考传送门:

mini PCIe

https://blog.csdn.net/huxyc/article/details/124854928

PCI、PCIe、Mini PCIe、SATA、mSATA、M.2

https://blog.csdn.net/lyndon_li/article/details/120662832?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword\~default-0-120662832-blog-128689170.235

PCie接口的设备很多很常见,例如显卡(GPU)、网卡、声卡和NVMe固态硬盘(SSD)等,但说的是在x86上。ARM相比x86的一个优势就是体积小,在一块板子上完成很多功能,而不是留下很多接口来保证可扩展性,所以很多ARM开发者可能对PCIe设备都没有概念或概念混成一团(没错就是我)。

认识一个事物,最简单的方法是从实物出发,下面是一个x86上使用的PCIe的显卡,和一个PCIe转SATA3.0的转接卡

其在x86上的插槽大致模样如下:

"miniPCIe",则是基于PCIe总线的一种较小型的接口,专门用于笔记本电脑、平板电脑、嵌入式系统和其他便携式电子设备。它继承了PCIe的高速串行通信特点,但体积更小下面是祥硕ASM1061芯片,支持mini PCIe转双SATA3接口,以及主板上的mini PCIe的插槽。


二、miniPCIe引脚定义

PCIe总线使用了高速差分异步总线,并采用端到端的连接方式,因此在每一条PCIe链路中只能连接两个设备。

如上图所示每一个PCIe链路(Link)只能连接两个设备,PCIe的link宽度支持的Lane数为x1, x2, x4, x8, x12, x16, x32。PCIe的一条lane由两个信号线(Signal TX和Signal Rx)组成,每个Signal由两根线Wire组成。

以ASM1061为例,The ASM1061, X1 PCI Express Gen2 to two-ports Serial ATA Controller,结合PCIe总线的性质,不难猜出其芯片的接口大致分为,PCIe的供电引脚,PCIe的差分时钟线,x1Lane的四条线,两个SATA的数据、时钟、供电复位线。

在firefly-RK3399原理图上(J29)PCIE M2.NGFF B-KEY 接口

三、设备树节点

复制代码
	pcie0: pcie@f8000000 {
		compatible = "rockchip,rk3399-pcie";
		#address-cells = <3>;
		#size-cells = <2>;
		aspm-no-l0s;
		clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
			 <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
		clock-names = "aclk", "aclk-perf",
			      "hclk", "pm";
		bus-range = <0x0 0x1f>;
		max-link-speed = <1>;
		linux,pci-domain = <0>;
		msi-map = <0x0 &its 0x0 0x1000>;
		interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
			     <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
			     <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
		interrupt-names = "sys", "legacy", "client";
		#interrupt-cells = <1>;
		interrupt-map-mask = <0 0 0 7>;
		interrupt-map = <0 0 0 1 &pcie0_intc 0>,
				<0 0 0 2 &pcie0_intc 1>,
				<0 0 0 3 &pcie0_intc 2>,
				<0 0 0 4 &pcie0_intc 3>;
		power-domains = <&power RK3399_PD_PERIHP>;
		phys = <&pcie_phy>;
		phy-names = "pcie-phy";
		ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000
			  0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>;
		reg = <0x0 0xf8000000 0x0 0x2000000>,
		      <0x0 0xfd000000 0x0 0x1000000>;
		reg-names = "axi-base", "apb-base";
		resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
			 <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
			 <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>,
			 <&cru SRST_A_PCIE>;
		reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
			      "pm", "pclk", "aclk";
		status = "disabled";
		pcie0_intc: interrupt-controller {
			interrupt-controller;
			#address-cells = <0>;
			#interrupt-cells = <1>;
		};
	};

pcie_phy: pcie-phy {
		compatible = "rockchip,rk3399-pcie-phy";
		#phy-cells = <0>;
		rockchip,grf = <&grf>;
		clocks = <&cru SCLK_PCIEPHY_REF>;
		clock-names = "refclk";
		resets = <&cru SRST_PCIEPHY>;
		reset-names = "phy";
		status = "disabled";
	};
	
&pcie_phy {
	status = "okay";
};

&pcie0 {
	ep-gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>;
	num-lanes = <4>;
	pinctrl-names = "default";
	pinctrl-0 = <&pcie_clkreqn>;
	status = "okay";
};

pinctl{		
	...
		pcie {
			pcie_clkreqn: pci-clkreqn {
				rockchip,pins =
					<2 26 RK_FUNC_2 &pcfg_pull_none>;
			};

			pcie_clkreqnb: pci-clkreqnb {
				rockchip,pins =
					<4 24 RK_FUNC_1 &pcfg_pull_none>;
			};
	...
			
	}

1.ep-gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>;

​ 此项是设置 PCIe 接口的 PERST#复位信号;

2.num-lanes = <4>;

​ 此配置设置 PCIe 设备所使用的 lane 数量,默认不需要调整,软件可以自己探测并关闭不需要的 lane以节省功耗。

3.max-link-speed = <1>;

​ 配置设置 PCIe 的速度登记,1 表示 gen1,2 表示 gen2。RK3399 限制不超过 gen2。另,此配置默认是写在 dtsi,也就是说默认限制为 gen1,这与ASM1061不符,原因是 gen2 的 TX 测试指标无法达到标准,所以不推荐客户开启 gen2 模式,以免引起不必要的链路异常。

4.status = <okay>;

​ 此配置需要在 pcie0 和和 pcie_phy 节点同时使能。默认不使能的原因是如果没有外设,pcie 在初始化时有一个较大的检测延时,会额外增加不必要的开机时间。故,有需要 PCIe 的项目自行开启。

5.pinctrl-0 = <&pcie_clkreqn>;

​ 这里加了一个pinctrl,但我感觉firefly加错了,随他吧,反正RK也没让加,加的GPIO2_D2是蓝牙的唤醒引脚


四、menuconfig配置

  1. 需要确保如下配置打开,方可正确的使用 PCIe 相关功能

    CONFIG_PCI=y
    CONFIG_PCI_DOMAINS=y
    CONFIG_PCI_DOMAINS_GENERIC=y
    CONFIG_PCI_SYSCALL=y
    CONFIG_PCI_BUS_ADDR_T_64BIT=y
    CONFIG_PCI_MSI=y
    CONFIG_PCI_MSI_IRQ_DOMAIN=y
    CONFIG_PHY_ROCKCHIP_PCIE=y
    CONFIG_PCIE_ROCKCHIP=y
    CONFIG_PCIEPORTBUS=y
    CONFIG_PCIEASPM=y
    CONFIG_PCIEASPM_POWERSAVE=y
    CONFIG_PCIE_PME=y
    CONFIG_GENERIC_MSI_IRQ=y
    CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
    CONFIG_IRQ_DOMAIN=y
    CONFIG_IRQ_DOMAIN_HIERARCHY=y

  2. 使能 NVMe 设备(建立在 PCIe 接口的 SSD)

    CONFIG_BLK_DEV_NVME=y

  3. 使能 AHCI 设备(PCIe 转接成 SATA 的 SSD)

    CONFIG_SATA_PMP=y
    CONFIG_SATA_AHCI=y
    CONFIG_ATA_SFF=y
    CONFIG_ATA=y

特别说明,默认 4.4 开源内核仅支持 drivers/ata/ahci.c 中列表内的设备,超出部分请找原厂或者代理商支持。

五、用户空间调试

1.查看pci设备
复制代码
root@firefly:~# lspci
00:00.0 PCI bridge: Fuzhou Rockchip Electronics Co., Ltd Device 0100
01:00.0 IDE interface: ASMedia Technology Inc. ASM1061 SATA IDE Controller (rev 02)

root@firefly:/sys/bus/pci/devices/0000:01:00.0# cat device
0x0611
#可以看到ID和.c中的一致
相关推荐
想躺在地上晒成地瓜干44 分钟前
树莓派超全系列文档--(14)无需交互使用raspi-config工具其一
linux·树莓派·raspberrypi·树莓派教程
Shier833_Ww1 小时前
目标识别与双目测距(1)环境搭建:Ubuntu+yolov5+pcl库
linux·yolo·ubuntu
相醉为友1 小时前
001 使用单片机实现的逻辑分析仪——吸收篇
笔记·单片机·嵌入式硬件·fpga开发·嵌入式
唐青枫2 小时前
Linux 历史命令操作教程
linux
【云轩】2 小时前
《哪吒的混天绫FPGA》
笔记·嵌入式硬件·fpga开发
愚润求学2 小时前
Linux基础指令(一)
linux·服务器·语法
IEVEl3 小时前
CentOS 7 安装 EMQX (MQTT)
linux·运维·centos
好多知识都想学3 小时前
Centos 7 搭建 jumpserver 堡垒机
linux
vortex53 小时前
深入理解 Linux 文件权限:从 ACL 到扩展属性,解剖底层技术细节与命令应用
linux·运维·服务器
Cyber4K3 小时前
《零基础实战:手把手教你用LNMP环境搭建Discuz论坛》
linux