aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2020-07-21 14:11:08 +0200
committerHauke Mehrtens <hauke@hauke-m.de>2020-10-11 16:16:24 +0200
commiteb777539fd18fec624aa461feec20f1f92624620 (patch)
tree62bf7ceb2cceaee9184b99356f8561a3af8dc073 /target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch
parent5b3ff53ebd6846a0f03bfa29d9aa5d22a6a05bfb (diff)
downloadupstream-eb777539fd18fec624aa461feec20f1f92624620.tar.gz
upstream-eb777539fd18fec624aa461feec20f1f92624620.tar.bz2
upstream-eb777539fd18fec624aa461feec20f1f92624620.zip
mvebu: armada-37xx: Backport PCI aardvark patches
This commit contains patches for PCI aardvark driver and relevant DTS changes for Turris MOX and EspressoBin backported from mainline kernel. It fixes support for old ATF, various wifi cards, mainly Compex WLE900VX. Signed-off-by: Pali Rohár <pali@kernel.org>
Diffstat (limited to 'target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch')
-rw-r--r--target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch123
1 files changed, 123 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch b/target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch
new file mode 100644
index 0000000000..1ba70dd6f7
--- /dev/null
+++ b/target/linux/mvebu/patches-5.4/406-PCI-aardvark-Issue-PERST-via-GPIO.patch
@@ -0,0 +1,123 @@
+From 5169a9851daaa2782a7bd2bb83d5b1bd224b2879 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 30 Apr 2020 10:06:18 +0200
+Subject: [PATCH] PCI: aardvark: Issue PERST via GPIO
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add support for issuing PERST via GPIO specified in 'reset-gpios'
+property (as described in PCI device tree bindings).
+
+Some buggy cards (e.g. Compex WLE900VX or WLE1216) are not detected
+after reboot when PERST is not issued during driver initialization.
+
+If bootloader already enabled link training then issuing PERST has no
+effect for some buggy cards (e.g. Compex WLE900VX) and these cards are
+not detected. We therefore clear the LINK_TRAINING_EN register before.
+
+It was observed that Compex WLE900VX card needs to be in PERST reset
+for at least 10ms if bootloader enabled link training.
+
+Tested on Turris MOX.
+
+Link: https://lore.kernel.org/r/20200430080625.26070-6-pali@kernel.org
+Tested-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+---
+ drivers/pci/controller/pci-aardvark.c | 43 ++++++++++++++++++++++++++-
+ 1 file changed, 42 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -9,6 +9,7 @@
+ */
+
+ #include <linux/delay.h>
++#include <linux/gpio.h>
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/irqdomain.h>
+@@ -17,6 +18,7 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/of_address.h>
++#include <linux/of_gpio.h>
+ #include <linux/of_pci.h>
+
+ #include "../pci.h"
+@@ -204,6 +206,7 @@ struct advk_pcie {
+ int root_bus_nr;
+ int link_gen;
+ struct pci_bridge_emul bridge;
++ struct gpio_desc *reset_gpio;
+ };
+
+ static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
+@@ -330,10 +333,31 @@ err:
+ dev_err(dev, "link never came up\n");
+ }
+
++static void advk_pcie_issue_perst(struct advk_pcie *pcie)
++{
++ u32 reg;
++
++ if (!pcie->reset_gpio)
++ return;
++
++ /* PERST does not work for some cards when link training is enabled */
++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++ reg &= ~LINK_TRAINING_EN;
++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
++
++ /* 10ms delay is needed for some cards */
++ dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
++ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
++ usleep_range(10000, 11000);
++ gpiod_set_value_cansleep(pcie->reset_gpio, 0);
++}
++
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
+ u32 reg;
+
++ advk_pcie_issue_perst(pcie);
++
+ /* Set to Direct mode */
+ reg = advk_readl(pcie, CTRL_CONFIG_REG);
+ reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT);
+@@ -406,7 +430,8 @@ static void advk_pcie_setup_hw(struct ad
+
+ /*
+ * PERST# signal could have been asserted by pinctrl subsystem before
+- * probe() callback has been called, making the endpoint going into
++ * probe() callback has been called or issued explicitly by reset gpio
++ * function advk_pcie_issue_perst(), making the endpoint going into
+ * fundamental reset. As required by PCI Express spec a delay for at
+ * least 100ms after such a reset before link training is needed.
+ */
+@@ -1094,6 +1119,22 @@ static int advk_pcie_probe(struct platfo
+ return ret;
+ }
+
++ pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
++ "reset-gpios", 0,
++ GPIOD_OUT_LOW,
++ "pcie1-reset");
++ ret = PTR_ERR_OR_ZERO(pcie->reset_gpio);
++ if (ret) {
++ if (ret == -ENOENT) {
++ pcie->reset_gpio = NULL;
++ } else {
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "Failed to get reset-gpio: %i\n",
++ ret);
++ return ret;
++ }
++ }
++
+ ret = of_pci_get_max_link_speed(dev->of_node);
+ if (ret <= 0 || ret > 3)
+ pcie->link_gen = 3;