Skip to content

Commit

Permalink
nuumio: dts/c: rockpro64: add pcie scan sleep and enable it for rockp…
Browse files Browse the repository at this point in the history
…ro64 (#45)

* PCI: rockchip: Workaround bus scan crashes with some PCIe devices

Some PCIe devices (like LSI SAS2008 based SAS controllers) caused bus
scan to crash when reading vendor id from the device.

It looks like these devices need a little sleep between link training
and bus scan to work correctly. What causes this or why is currently a
mystery for me so I'll be calling this a workaround, not a fix. The
amount of sleep needed is suspiciously close to those needed in sdio
defer to make PCIe work. So the root cause may even be common.

To set the amount of sleep you can use device tree (will default to
850 ms) or kernel command-line (defaults to "ignored"). Command-line
overrides device tree.

In my current test rig (Rockpro64 4GB + WiFi enabled with Pine module +
LSI 9201, BIOS erased) 800 ms is not enough. 850 ms seems stable.
So at least with my system 4.4 needs a bit more sleep than mainline
(without WiFi). Other connected devices may have effect on needed
amout of sleep.

* dts: rockpro64: set PCIe bus scan delay to 1000 ms

850 ms seemed stable for my current setup but let's add a bit of
safety margin.

* defconfig: Add MP3SAS driver for Rockchip linux
  • Loading branch information
nuumio authored and ayufan committed Apr 4, 2019
1 parent 67a56a9 commit 3cde5c6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2983,6 +2983,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
nomsi Do not use MSI for native PCIe PME signaling (this makes
all PCIe root ports use INTx for all services).

pcie_rk_bus_scan_delay= [PCIE] Delay in ms before
scanning PCIe bus in Rockchip PCIe host driver. Some PCIe
cards seem to need delays that can be several hundred ms.
If set to greater than or equal to 0 this parameter will
override delay that can be set in device tree.
Values less than 0 mean that this parameter is ignored.
default=-1

pcmv= [HW,PCMCIA] BadgePAD 4

pd_ignore_unused
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pcie_clkreqn>;
vpcie3v3-supply = <&vcc3v3_pcie>;
bus-scan-delay-ms = <1000>;
status = "okay";
};

Expand Down
5 changes: 5 additions & 0 deletions arch/arm64/configs/rockchip_linux_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,11 @@ CONFIG_BLK_DEV_NVME=y
CONFIG_SRAM=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI_SAS_ATTRS=m
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_SPI_ATTRS=y
Expand Down
26 changes: 26 additions & 0 deletions drivers/pci/host/pcie-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/moduleparam.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_pci.h>
Expand Down Expand Up @@ -253,8 +254,12 @@ struct rockchip_pcie {
int wait_ep;
struct dma_trx_obj *dma_obj;
struct list_head resources;
u32 bus_scan_delay;
};

static int bus_scan_delay = -1;
core_param(pcie_rk_bus_scan_delay, bus_scan_delay, int, S_IRUGO);

static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg)
{
return readl(rockchip->apb_base + reg);
Expand Down Expand Up @@ -1075,6 +1080,14 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
dev_info(dev, "no vpcie0v9 regulator found\n");
}

err = of_property_read_u32(node, "bus-scan-delay-ms", &rockchip->bus_scan_delay);
if (err) {
dev_info(dev, "no bus-scan-delay-ms in device tree, default 0 ms\n");
rockchip->bus_scan_delay = 0;
} else {
dev_info(dev, "bus-scan-delay-ms in device tree is %u ms\n", rockchip->bus_scan_delay);
}

mem = of_parse_phandle(node, "memory-region", 0);
if (!mem) {
dev_warn(dev, "missing \"memory-region\" property\n");
Expand Down Expand Up @@ -1399,6 +1412,7 @@ static int rockchip_pcie_really_probe(struct rockchip_pcie *rockchip)
int err;
struct pci_bus *bus, *child;
struct device *dev = rockchip->dev;
u32 delay = 0;

err = rockchip_pcie_init_port(rockchip);
if (err)
Expand All @@ -1410,6 +1424,18 @@ static int rockchip_pcie_really_probe(struct rockchip_pcie *rockchip)
if (err)
return err;

/* Prefer command-line param over device tree */
if (bus_scan_delay > 0) {
delay = bus_scan_delay;
dev_info(dev, "wait %u ms (from command-line) before bus scan\n", delay);
} else if (rockchip->bus_scan_delay > 0 && bus_scan_delay < 0) {
delay = rockchip->bus_scan_delay;
dev_info(dev, "wait %u ms (from device tree) before bus scan\n", delay);
}
if (delay > 0) {
msleep(delay);
}

bus = pci_scan_root_bus(dev, 0, &rockchip_pcie_ops,
rockchip, &rockchip->resources);
if (!bus)
Expand Down

1 comment on commit 3cde5c6

@prusnak
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey@nuumio @ayufan! Have you tried upstreaming this patch?

Please sign in to comment.