一、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-2defaultbaidujs_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配置
- 需要确保如下配置打开,方可正确的使用 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
- 使能 NVMe 设备(建立在 PCIe 接口的 SSD)
CONFIG_BLK_DEV_NVME=y
- 使能 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中的一致