1. 简介

不多说,灵车,IPQ4019,OpenWrt没支持,国产X-Wrt不想用,拿ImageBuilder打Patch吧。

2. 系统

打Patch的话参见X-Wrt的commit,这个就差不多了。

但是PCIe并不能开箱即用。

要想PCIe能用的话还存在三个问题

  • 没设备树
  • 没电
  • 没REFCLK

miniPCIe接口3.3V AUX没电的问题可以看下图

miniPCIe的供电部分,缺焊元件为bypass电阻

恩山的方案是短路这个电阻,但是这需要一定的焊接,而且也不便使用,根据观察可以发现左侧SOP-8封装的器件为International Rectifier IRF7416PbF 功率MOSFET,封装如下:

IRF7416PbF Datasheet

这个MOSFET的源极和漏极接在整板3.3V与miniPCIe的供电3.3V中间,我们可以推断该MOSFET的用途是miniPCIe的供电控制,那么栅极推断应为SoC GPIO控制。

问题来了,这货有100个GPIO,我们如何找到正确的控制这个MOSFET的GPIO呢?

根据实际插入PCIe模块的情况及万用表测试的结果,该IO的状态只存在是两种可能:

  • 输出模式,高电平
  • 输入模式,内部上拉

那么范围缩小到了状态为输出高或者输入上拉,且没被其他外设占用的GPIO,可以通过/sys/kernel/debug/gpio查看符合条件的Pin,如下:

root@OpenWrt:~# cat /sys/kernel/debug/gpio  | grep "pull up"
 gpio0   : in  high func0 2mA pull up
 gpio1   : in  high func0 2mA pull up
 gpio6   : in  high func1 2mA pull up
 gpio7   : in  high func1 2mA pull up
 gpio10  : in  high func0 2mA pull up
 gpio11  : in  high func0 2mA pull up
 gpio12  : in  high func1 2mA pull up
 gpio13  : in  high func1 2mA pull up
 gpio14  : in  low  func1 2mA pull up
 gpio15  : in  low  func1 2mA pull up
 gpio20  : in  high func0 2mA pull up
 gpio21  : in  high func0 2mA pull up
 gpio22  : in  low  func0 2mA pull up
 gpio23  : in  high func1 10mA pull up
 gpio24  : in  high func1 10mA pull up
 gpio25  : in  high func1 10mA pull up
 gpio26  : in  high func1 10mA pull up
 gpio27  : in  high func1 16mA pull up
 gpio28  : in  high func1 10mA pull up
 gpio29  : in  high func0 2mA pull up
 gpio30  : in  high func0 2mA pull up
 gpio31  : in  high func0 2mA pull up
 gpio32  : out low  func0 2mA pull up
 gpio34  : in  high func0 2mA pull up
 gpio35  : in  high func0 2mA pull up
 gpio39  : out high func0 2mA pull up
 gpio40  : in  high func0 2mA pull up
 gpio50  : out high func0 2mA pull up
 gpio52  : out high func0 2mA pull up
 gpio53  : in  high func1 2mA pull up
 gpio58  : in  low  func1 2mA pull up
 gpio59  : in  low  func1 2mA pull up
root@OpenWrt:~# cat /sys/kernel/debug/gpio  | grep "out high"
 gpio4   : out high func0 2mA pull down
 gpio39  : out high func0 2mA pull up
 gpio50  : out high func0 2mA pull up
 gpio52  : out high func0 2mA pull up
 gpio61  : out high func0 2mA pull down
root@OpenWrt:~# 

其中可以筛选出func0的IO即为GPIO function。

根据依次尝试,GPIO2 即为我们要找的GPIO。

之后我们需要在设备树里让kernel在配置PCIe的时候初始化好这个GPIO,如下所示

+&pcie0 {
+        status = "okay";
+
+        perst-gpio = <&tlmm 4 GPIO_ACTIVE_LOW>;
+        wake-gpio = <&tlmm 40 GPIO_ACTIVE_HIGH>;
+
+       pinctrl-0 = <&pcie_pins>;
+       pinctrl-names = "default";
+
+        bridge@0,0 {
+                reg = <0x00000000 0 0 0 0>;
+                #address-cells = <3>;
+                #size-cells = <2>;
+                ranges;
+
+                wifi2: wifi@1,0 {
+                        compatible = "qcom,ath10k";
+                        reg = <0x00010000 0 0 0 0>;
+                };
+        };
+};

我在miniPCIe插槽里插入的是QCA9880 3x3模块,如果是其他模块可以修改或者干脆删除 wifi2 节点。

其中要注意的是pinctrl字段,我们并不需要使用pinctrl初始化已经有了的perst和wake,但是由于这个电源控制并不在我们的pcie能配置的GPIO里,我们需要单独配置他。

&tlmm 设备节点中添加我们的GPIO2配置,配置为输出低电平,2mA(默认)和下拉。之所以在配置下拉的同时还要设置输出是为了防止下拉强度不够导致MOS工作在线性区无法正常供电。

+       pcie_pins: pcie_pinmux {
+               mux {
+                       pins = "gpio2";
+                       function = "gpio";
+                       bias-pull-down;
+                       output-low;
+               };
+       };

按照这种方式修改编译得到的OpenWrt就可以在加载驱动时自动配置给卡供电了。

回到REFCLK的问题

REFCLK的焊盘出厂时默认留空,补焊上即可,如下图:

手头没有0402的0欧电阻了,用跳线短上

一般大多数的miniPCIe卡只需要3.3V供电,不过板子还预留了RESERVED pin的5V供电电路,据恩山说法是为内置PA的大功率无线网卡准备的。有需求可以短掉R443和R447 。如果不清楚所用模块型号则不需要,这里不做赘述。

附PCIe正常初始化日志如下:

[    0.051140] qcom-pcie 40000000.pci: host bridge /soc/pci@40000000 ranges:
[    0.051183] qcom-pcie 40000000.pci:    IO 0x40200000..0x402fffff -> 0x40200000
[    0.051210] qcom-pcie 40000000.pci:   MEM 0x40300000..0x40ffffff -> 0x40300000
[    0.326667] qcom-pcie 40000000.pci: Link up
[    0.326822] qcom-pcie 40000000.pci: PCI host bridge to bus 0000:00
[    0.326844] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.326860] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff] (bus address [0x40200000-0x402fffff])
[    0.326874] pci_bus 0000:00: root bus resource [mem 0x40300000-0x40ffffff]
[    0.326916] pci 0000:00:00.0: [17cb:1001] type 01 class 0x060400
[    0.326953] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x00000fff 64bit]
[    0.327013] pci 0000:00:00.0: PME# supported from D0 D3hot
[    0.328977] pci 0000:01:00.0: [168c:003c] type 00 class 0x028000
[    0.329176] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x001fffff 64bit]
[    0.329404] pci 0000:01:00.0: reg 0x30: [mem 0x00000000-0x0000ffff pref]
[    0.329837] pci 0000:01:00.0: supports D1 D2
[    0.329845] pci 0000:01:00.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.331776] pci 0000:00:00.0: BAR 8: assigned [mem 0x40300000-0x405fffff]
[    0.331793] pci 0000:00:00.0: BAR 0: assigned [mem 0x40600000-0x40600fff 64bit]
[    0.331821] pci 0000:01:00.0: BAR 0: assigned [mem 0x40400000-0x405fffff 64bit]
[    0.331899] pci 0000:01:00.0: BAR 6: assigned [mem 0x40300000-0x4030ffff pref]
[    0.331915] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    0.331930] pci 0000:00:00.0:   bridge window [mem 0x40300000-0x405fffff]
[    0.334340] pcieport 0000:00:00.0: AER enabled with IRQ 97

关于LTE模块

市面99.9%的LTE模块是USB通讯的,如果使用LTE模块则不需要短接REFCLK,不过上述操作依然可以实现免焊接。

3. 已知问题(WIP)

  • SDHCI在USB插入的时候会出错,估计是pinmux的问题,尚未解决
  • USB不可用