]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 28 Nov 2021 12:51:29 +0000 (13:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 28 Nov 2021 12:51:29 +0000 (13:51 +0100)
added patches:
arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch
pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch
pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch
pci-aardvark-fix-big-endian-support.patch
pci-aardvark-fix-compilation-on-s390.patch
pci-aardvark-fix-link-training.patch
pci-aardvark-fix-pcie-max-payload-size-setting.patch
pci-aardvark-fix-support-for-bus-mastering-and-pci_command-on-emulated-bridge.patch
pci-aardvark-fix-support-for-pci_bridge_ctl_bus_reset-on-emulated-bridge.patch
pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
pci-aardvark-improve-link-training.patch
pci-aardvark-issue-perst-via-gpio.patch
pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch
pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch
pci-aardvark-set-pci-bridge-class-code-to-pci-bridge.patch
pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
pci-aardvark-train-link-immediately-after-enabling-training.patch
pci-aardvark-update-comment-about-disabling-link-training.patch
pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch
pci-pci-bridge-emul-fix-array-overruns-improve-safety.patch
pinctrl-armada-37xx-correct-pwm-pins-definitions.patch

23 files changed:
queue-5.4/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-big-endian-support.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-compilation-on-s390.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-link-training.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-pcie-max-payload-size-setting.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-support-for-bus-mastering-and-pci_command-on-emulated-bridge.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-fix-support-for-pci_bridge_ctl_bus_reset-on-emulated-bridge.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-improve-link-training.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-issue-perst-via-gpio.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-set-pci-bridge-class-code-to-pci-bridge.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-train-link-immediately-after-enabling-training.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-update-comment-about-disabling-link-training.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch [new file with mode: 0644]
queue-5.4/pci-pci-bridge-emul-fix-array-overruns-improve-safety.patch [new file with mode: 0644]
queue-5.4/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch b/queue-5.4/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch
new file mode 100644 (file)
index 0000000..af1e869
--- /dev/null
@@ -0,0 +1,98 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:16 +0100
+Subject: arm64: dts: marvell: armada-37xx: Set pcie_reset_pin to gpio function
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <marek.behun@nic.cz>, "Remi Pommarel" <repk@triplefau.lt>, "Tomasz Maciej Nowak" <tmn505@gmail.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Gregory CLEMENT" <gregory.clement@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-23-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit 715878016984b2617f6c1f177c50039e12e7bd5b upstream.
+
+We found out that we are unable to control the PERST# signal via the
+default pin dedicated to be PERST# pin (GPIO2[3] pin) on A3700 SOC when
+this pin is in EP_PCIE1_Resetn mode. There is a register in the PCIe
+register space called PERSTN_GPIO_EN (D0088004[3]), but changing the
+value of this register does not change the pin output when measuring
+with voltmeter.
+
+We do not know if this is a bug in the SOC, or if it works only when
+PCIe controller is in a certain state.
+
+Commit f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready
+before training link") says that when this pin changes pinctrl mode
+from EP_PCIE1_Resetn to GPIO, the PERST# signal is asserted for a brief
+moment.
+
+So currently the situation is that on A3700 boards the PERST# signal is
+asserted in U-Boot (because the code in U-Boot issues reset via this pin
+via GPIO mode), and then in Linux by the obscure and undocumented
+mechanism described by the above mentioned commit.
+
+We want to issue PERST# signal in a known way, therefore this patch
+changes the pcie_reset_pin function from "pcie" to "gpio" and adds the
+reset-gpios property to the PCIe node in device tree files of
+EspressoBin and Armada 3720 Dev Board (Turris Mox device tree already
+has this property and uDPU does not have a PCIe port).
+
+Signed-off-by: Marek Behún <marek.behun@nic.cz>
+Cc: Remi Pommarel <repk@triplefau.lt>
+Tested-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/marvell/armada-3720-db.dts          |    3 +++
+ arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts |    1 +
+ arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts  |    4 ----
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi            |    2 +-
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+@@ -128,6 +128,9 @@
+ /* CON15(V2.0)/CON17(V1.4) : PCIe / CON15(V2.0)/CON12(V1.4) :mini-PCIe */
+ &pcie0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
++      reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
+       status = "okay";
+ };
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -59,6 +59,7 @@
+       phys = <&comphy1 0>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
++      reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
+ };
+ /* J6 */
+--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+@@ -127,10 +127,6 @@
+       };
+ };
+-&pcie_reset_pins {
+-      function = "gpio";
+-};
+-
+ &pcie0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -318,7 +318,7 @@
+                               pcie_reset_pins: pcie-reset-pins {
+                                       groups = "pcie1";
+-                                      function = "pcie";
++                                      function = "gpio";
+                               };
+                               pcie_clkreq_pins: pcie-clkreq-pins {
diff --git a/queue-5.4/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch b/queue-5.4/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch
new file mode 100644 (file)
index 0000000..e44549e
--- /dev/null
@@ -0,0 +1,297 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:06 +0100
+Subject: PCI: aardvark: Configure PCIe resources from 'ranges' DT property
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-13-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 64f160e19e9264a7f6d89c516baae1473b6f8359 upstream.
+
+In commit 6df6ba974a55 ("PCI: aardvark: Remove PCIe outbound window
+configuration") was removed aardvark PCIe outbound window configuration and
+commit description said that was recommended solution by HW designers.
+
+But that commit completely removed support for configuring PCIe IO
+resources without removing PCIe IO 'ranges' from DTS files. After that
+commit PCIe IO space started to be treated as PCIe MEM space and accessing
+it just caused kernel crash.
+
+Moreover implementation of PCIe outbound windows prior that commit was
+incorrect. It completely ignored offset between CPU address and PCIe bus
+address and expected that in DTS is CPU address always same as PCIe bus
+address without doing any checks. Also it completely ignored size of every
+PCIe resource specified in 'ranges' DTS property and expected that every
+PCIe resource has size 128 MB (also for PCIe IO range). Again without any
+check. Apparently none of PCIe resource has in DTS specified size of 128
+MB. So it was completely broken and thanks to how aardvark mask works,
+configuration was completely ignored.
+
+This patch reverts back support for PCIe outbound window configuration but
+implementation is a new without issues mentioned above. PCIe outbound
+window is required when DTS specify in 'ranges' property non-zero offset
+between CPU and PCIe address space. To address recommendation by HW
+designers as specified in commit description of 6df6ba974a55, set default
+outbound parameters as PCIe MEM access without translation and therefore
+for this PCIe 'ranges' it is not needed to configure PCIe outbound window.
+For PCIe IO space is needed to configure aardvark PCIe outbound window.
+
+This patch fixes kernel crash when trying to access PCIe IO space.
+
+Link: https://lore.kernel.org/r/20210624215546.4015-2-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org # 6df6ba974a55 ("PCI: aardvark: Remove PCIe outbound window configuration")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |  190 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 189 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -114,6 +114,46 @@
+ #define PCIE_MSI_PAYLOAD_REG                  (CONTROL_BASE_ADDR + 0x9C)
+ #define     PCIE_MSI_DATA_MASK                        GENMASK(15, 0)
++/* PCIe window configuration */
++#define OB_WIN_BASE_ADDR                      0x4c00
++#define OB_WIN_BLOCK_SIZE                     0x20
++#define OB_WIN_COUNT                          8
++#define OB_WIN_REG_ADDR(win, offset)          (OB_WIN_BASE_ADDR + \
++                                                OB_WIN_BLOCK_SIZE * (win) + \
++                                                (offset))
++#define OB_WIN_MATCH_LS(win)                  OB_WIN_REG_ADDR(win, 0x00)
++#define     OB_WIN_ENABLE                     BIT(0)
++#define OB_WIN_MATCH_MS(win)                  OB_WIN_REG_ADDR(win, 0x04)
++#define OB_WIN_REMAP_LS(win)                  OB_WIN_REG_ADDR(win, 0x08)
++#define OB_WIN_REMAP_MS(win)                  OB_WIN_REG_ADDR(win, 0x0c)
++#define OB_WIN_MASK_LS(win)                   OB_WIN_REG_ADDR(win, 0x10)
++#define OB_WIN_MASK_MS(win)                   OB_WIN_REG_ADDR(win, 0x14)
++#define OB_WIN_ACTIONS(win)                   OB_WIN_REG_ADDR(win, 0x18)
++#define OB_WIN_DEFAULT_ACTIONS                        (OB_WIN_ACTIONS(OB_WIN_COUNT-1) + 0x4)
++#define     OB_WIN_FUNC_NUM_MASK              GENMASK(31, 24)
++#define     OB_WIN_FUNC_NUM_SHIFT             24
++#define     OB_WIN_FUNC_NUM_ENABLE            BIT(23)
++#define     OB_WIN_BUS_NUM_BITS_MASK          GENMASK(22, 20)
++#define     OB_WIN_BUS_NUM_BITS_SHIFT         20
++#define     OB_WIN_MSG_CODE_ENABLE            BIT(22)
++#define     OB_WIN_MSG_CODE_MASK              GENMASK(21, 14)
++#define     OB_WIN_MSG_CODE_SHIFT             14
++#define     OB_WIN_MSG_PAYLOAD_LEN            BIT(12)
++#define     OB_WIN_ATTR_ENABLE                        BIT(11)
++#define     OB_WIN_ATTR_TC_MASK                       GENMASK(10, 8)
++#define     OB_WIN_ATTR_TC_SHIFT              8
++#define     OB_WIN_ATTR_RELAXED                       BIT(7)
++#define     OB_WIN_ATTR_NOSNOOP                       BIT(6)
++#define     OB_WIN_ATTR_POISON                        BIT(5)
++#define     OB_WIN_ATTR_IDO                   BIT(4)
++#define     OB_WIN_TYPE_MASK                  GENMASK(3, 0)
++#define     OB_WIN_TYPE_SHIFT                 0
++#define     OB_WIN_TYPE_MEM                   0x0
++#define     OB_WIN_TYPE_IO                    0x4
++#define     OB_WIN_TYPE_CONFIG_TYPE0          0x8
++#define     OB_WIN_TYPE_CONFIG_TYPE1          0x9
++#define     OB_WIN_TYPE_MSG                   0xc
++
+ /* LMI registers base address and register offsets */
+ #define LMI_BASE_ADDR                         0x6000
+ #define CFG_REG                                       (LMI_BASE_ADDR + 0x0)
+@@ -229,6 +269,13 @@ struct advk_pcie {
+       struct platform_device *pdev;
+       void __iomem *base;
+       struct list_head resources;
++      struct {
++              phys_addr_t match;
++              phys_addr_t remap;
++              phys_addr_t mask;
++              u32 actions;
++      } wins[OB_WIN_COUNT];
++      u8 wins_count;
+       struct irq_domain *irq_domain;
+       struct irq_chip irq_chip;
+       raw_spinlock_t irq_lock;
+@@ -452,9 +499,39 @@ err:
+       dev_err(dev, "link never came up\n");
+ }
++/*
++ * Set PCIe address window register which could be used for memory
++ * mapping.
++ */
++static void advk_pcie_set_ob_win(struct advk_pcie *pcie, u8 win_num,
++                               phys_addr_t match, phys_addr_t remap,
++                               phys_addr_t mask, u32 actions)
++{
++      advk_writel(pcie, OB_WIN_ENABLE |
++                        lower_32_bits(match), OB_WIN_MATCH_LS(win_num));
++      advk_writel(pcie, upper_32_bits(match), OB_WIN_MATCH_MS(win_num));
++      advk_writel(pcie, lower_32_bits(remap), OB_WIN_REMAP_LS(win_num));
++      advk_writel(pcie, upper_32_bits(remap), OB_WIN_REMAP_MS(win_num));
++      advk_writel(pcie, lower_32_bits(mask), OB_WIN_MASK_LS(win_num));
++      advk_writel(pcie, upper_32_bits(mask), OB_WIN_MASK_MS(win_num));
++      advk_writel(pcie, actions, OB_WIN_ACTIONS(win_num));
++}
++
++static void advk_pcie_disable_ob_win(struct advk_pcie *pcie, u8 win_num)
++{
++      advk_writel(pcie, 0, OB_WIN_MATCH_LS(win_num));
++      advk_writel(pcie, 0, OB_WIN_MATCH_MS(win_num));
++      advk_writel(pcie, 0, OB_WIN_REMAP_LS(win_num));
++      advk_writel(pcie, 0, OB_WIN_REMAP_MS(win_num));
++      advk_writel(pcie, 0, OB_WIN_MASK_LS(win_num));
++      advk_writel(pcie, 0, OB_WIN_MASK_MS(win_num));
++      advk_writel(pcie, 0, OB_WIN_ACTIONS(win_num));
++}
++
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
+       u32 reg;
++      int i;
+       /* Set to Direct mode */
+       reg = advk_readl(pcie, CTRL_CONFIG_REG);
+@@ -528,15 +605,51 @@ static void advk_pcie_setup_hw(struct ad
+       reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
+       advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG);
++      /*
++       * Enable AXI address window location generation:
++       * When it is enabled, the default outbound window
++       * configurations (Default User Field: 0xD0074CFC)
++       * are used to transparent address translation for
++       * the outbound transactions. Thus, PCIe address
++       * windows are not required for transparent memory
++       * access when default outbound window configuration
++       * is set for memory access.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
+       reg |= PCIE_CORE_CTRL2_OB_WIN_ENABLE;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
+-      /* Bypass the address window mapping for PIO */
++      /*
++       * Set memory access in Default User Field so it
++       * is not required to configure PCIe address for
++       * transparent memory access.
++       */
++      advk_writel(pcie, OB_WIN_TYPE_MEM, OB_WIN_DEFAULT_ACTIONS);
++
++      /*
++       * Bypass the address window mapping for PIO:
++       * Since PIO access already contains all required
++       * info over AXI interface by PIO registers, the
++       * address window is not required.
++       */
+       reg = advk_readl(pcie, PIO_CTRL);
+       reg |= PIO_CTRL_ADDR_WIN_DISABLE;
+       advk_writel(pcie, reg, PIO_CTRL);
++      /*
++       * Configure PCIe address windows for non-memory or
++       * non-transparent access as by default PCIe uses
++       * transparent memory access.
++       */
++      for (i = 0; i < pcie->wins_count; i++)
++              advk_pcie_set_ob_win(pcie, i,
++                                   pcie->wins[i].match, pcie->wins[i].remap,
++                                   pcie->wins[i].mask, pcie->wins[i].actions);
++
++      /* Disable remaining PCIe outbound windows */
++      for (i = pcie->wins_count; i < OB_WIN_COUNT; i++)
++              advk_pcie_disable_ob_win(pcie, i);
++
+       advk_pcie_train_link(pcie);
+       reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+@@ -1345,6 +1458,7 @@ static int advk_pcie_probe(struct platfo
+       struct advk_pcie *pcie;
+       struct resource *res;
+       struct pci_host_bridge *bridge;
++      struct resource_entry *entry;
+       int ret, irq;
+       bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie));
+@@ -1374,6 +1488,80 @@ static int advk_pcie_probe(struct platfo
+               return ret;
+       }
++      resource_list_for_each_entry(entry, &pcie->resources) {
++              resource_size_t start = entry->res->start;
++              resource_size_t size = resource_size(entry->res);
++              unsigned long type = resource_type(entry->res);
++              u64 win_size;
++
++              /*
++               * Aardvark hardware allows to configure also PCIe window
++               * for config type 0 and type 1 mapping, but driver uses
++               * only PIO for issuing configuration transfers which does
++               * not use PCIe window configuration.
++               */
++              if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 &&
++                  type != IORESOURCE_IO)
++                      continue;
++
++              /*
++               * Skip transparent memory resources. Default outbound access
++               * configuration is set to transparent memory access so it
++               * does not need window configuration.
++               */
++              if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) &&
++                  entry->offset == 0)
++                      continue;
++
++              /*
++               * The n-th PCIe window is configured by tuple (match, remap, mask)
++               * and an access to address A uses this window if A matches the
++               * match with given mask.
++               * So every PCIe window size must be a power of two and every start
++               * address must be aligned to window size. Minimal size is 64 KiB
++               * because lower 16 bits of mask must be zero. Remapped address
++               * may have set only bits from the mask.
++               */
++              while (pcie->wins_count < OB_WIN_COUNT && size > 0) {
++                      /* Calculate the largest aligned window size */
++                      win_size = (1ULL << (fls64(size)-1)) |
++                                 (start ? (1ULL << __ffs64(start)) : 0);
++                      win_size = 1ULL << __ffs64(win_size);
++                      if (win_size < 0x10000)
++                              break;
++
++                      dev_dbg(dev,
++                              "Configuring PCIe window %d: [0x%llx-0x%llx] as %lu\n",
++                              pcie->wins_count, (unsigned long long)start,
++                              (unsigned long long)start + win_size, type);
++
++                      if (type == IORESOURCE_IO) {
++                              pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_IO;
++                              pcie->wins[pcie->wins_count].match = pci_pio_to_address(start);
++                      } else {
++                              pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_MEM;
++                              pcie->wins[pcie->wins_count].match = start;
++                      }
++                      pcie->wins[pcie->wins_count].remap = start - entry->offset;
++                      pcie->wins[pcie->wins_count].mask = ~(win_size - 1);
++
++                      if (pcie->wins[pcie->wins_count].remap & (win_size - 1))
++                              break;
++
++                      start += win_size;
++                      size -= win_size;
++                      pcie->wins_count++;
++              }
++
++              if (size > 0) {
++                      dev_err(&pcie->pdev->dev,
++                              "Invalid PCIe region [0x%llx-0x%llx]\n",
++                              (unsigned long long)entry->res->start,
++                              (unsigned long long)entry->res->end + 1);
++                      return -EINVAL;
++              }
++      }
++
+       pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
+                                                      "reset-gpios", 0,
+                                                      GPIOD_OUT_LOW,
diff --git a/queue-5.4/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch b/queue-5.4/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
new file mode 100644 (file)
index 0000000..3a26e9d
--- /dev/null
@@ -0,0 +1,98 @@
+From 67cb2a4c93499c2c22704998fd1fd2bc35194d8e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Tue, 5 Oct 2021 20:09:47 +0200
+Subject: PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+commit 67cb2a4c93499c2c22704998fd1fd2bc35194d8e upstream.
+
+Avoid code repetition in advk_pcie_rd_conf() by handling errors with
+goto jump, as is customary in kernel.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-9-kabel@kernel.org
+Fixes: 43f5c77bcbd2 ("PCI: aardvark: Fix reporting CRS value")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   48 ++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 28 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -773,18 +773,8 @@ static int advk_pcie_rd_conf(struct pci_
+                   (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) &
+                    PCI_EXP_RTCTL_CRSSVE);
+-      if (advk_pcie_pio_is_running(pcie)) {
+-              /*
+-               * If it is possible return Completion Retry Status so caller
+-               * tries to issue the request again instead of failing.
+-               */
+-              if (allow_crs) {
+-                      *val = CFG_RD_CRS_VAL;
+-                      return PCIBIOS_SUCCESSFUL;
+-              }
+-              *val = 0xffffffff;
+-              return PCIBIOS_SET_FAILED;
+-      }
++      if (advk_pcie_pio_is_running(pcie))
++              goto try_crs;
+       /* Program the control register */
+       reg = advk_readl(pcie, PIO_CTRL);
+@@ -808,25 +798,13 @@ static int advk_pcie_rd_conf(struct pci_
+       advk_writel(pcie, 1, PIO_START);
+       ret = advk_pcie_wait_pio(pcie);
+-      if (ret < 0) {
+-              /*
+-               * If it is possible return Completion Retry Status so caller
+-               * tries to issue the request again instead of failing.
+-               */
+-              if (allow_crs) {
+-                      *val = CFG_RD_CRS_VAL;
+-                      return PCIBIOS_SUCCESSFUL;
+-              }
+-              *val = 0xffffffff;
+-              return PCIBIOS_SET_FAILED;
+-      }
++      if (ret < 0)
++              goto try_crs;
+       /* Check PIO status and get the read result */
+       ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
+-      if (ret < 0) {
+-              *val = 0xffffffff;
+-              return PCIBIOS_SET_FAILED;
+-      }
++      if (ret < 0)
++              goto fail;
+       if (size == 1)
+               *val = (*val >> (8 * (where & 3))) & 0xff;
+@@ -834,6 +812,20 @@ static int advk_pcie_rd_conf(struct pci_
+               *val = (*val >> (8 * (where & 3))) & 0xffff;
+       return PCIBIOS_SUCCESSFUL;
++
++try_crs:
++      /*
++       * If it is possible, return Completion Retry Status so that caller
++       * tries to issue the request again instead of failing.
++       */
++      if (allow_crs) {
++              *val = CFG_RD_CRS_VAL;
++              return PCIBIOS_SUCCESSFUL;
++      }
++
++fail:
++      *val = 0xffffffff;
++      return PCIBIOS_SET_FAILED;
+ }
+ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
diff --git a/queue-5.4/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch b/queue-5.4/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch
new file mode 100644 (file)
index 0000000..d7f19e9
--- /dev/null
@@ -0,0 +1,55 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:01 +0100
+Subject: PCI: aardvark: Don't touch PCIe registers if no card connected
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-8-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 70e380250c3621c55ff218cbaf2272830d9dbb1d upstream.
+
+When there is no PCIe card connected and advk_pcie_rd_conf() or
+advk_pcie_wr_conf() is called for PCI bus which doesn't belong to emulated
+root bridge, the aardvark driver throws the following error message:
+
+  advk-pcie d0070000.pcie: config read/write timed out
+
+Obviously accessing PCIe registers of disconnected card is not possible.
+
+Extend check in advk_pcie_valid_device() function for validating
+availability of PCIe bus. If PCIe link is down, then the device is marked
+as Not Found and the driver does not try to access these registers.
+
+This is just an optimization to prevent accessing PCIe registers when card
+is disconnected. Trying to access PCIe registers of disconnected card does
+not cause any crash, kernel just needs to wait for a timeout. So if card
+disappear immediately after checking for PCIe link (before accessing PCIe
+registers), it does not cause any problems.
+
+Link: https://lore.kernel.org/r/20200702083036.12230-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -806,6 +806,13 @@ static bool advk_pcie_valid_device(struc
+       if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0)
+               return false;
++      /*
++       * If the link goes down after we check for link-up, nothing bad
++       * happens but the config access times out.
++       */
++      if (bus->number != pcie->root_bus_nr && !advk_pcie_link_up(pcie))
++              return false;
++
+       return true;
+ }
diff --git a/queue-5.4/pci-aardvark-fix-big-endian-support.patch b/queue-5.4/pci-aardvark-fix-big-endian-support.patch
new file mode 100644 (file)
index 0000000..5ecb3f0
--- /dev/null
@@ -0,0 +1,53 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:25:56 +0100
+Subject: PCI: aardvark: Fix big endian support
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Grzegorz Jaszczyk" <jaz@semihalf.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-3-kabel@kernel.org>
+
+From: Grzegorz Jaszczyk <jaz@semihalf.com>
+
+commit e078723f9cccd509482fd7f30a4afb1125ca7a2a upstream.
+
+Initialise every multiple-byte field of emulated PCI bridge config
+space with proper cpu_to_le* macro. This is required since the structure
+describing config space of emulated bridge assumes little-endian
+convention.
+
+Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -686,18 +686,20 @@ static int advk_sw_pci_bridge_init(struc
+       struct pci_bridge_emul *bridge = &pcie->bridge;
+       int ret;
+-      bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff;
+-      bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16;
++      bridge->conf.vendor =
++              cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
++      bridge->conf.device =
++              cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16);
+       bridge->conf.class_revision =
+-              advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff;
++              cpu_to_le32(advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff);
+       /* Support 32 bits I/O addressing */
+       bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
+       bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;
+       /* Support 64 bits memory pref */
+-      bridge->conf.pref_mem_base = PCI_PREF_RANGE_TYPE_64;
+-      bridge->conf.pref_mem_limit = PCI_PREF_RANGE_TYPE_64;
++      bridge->conf.pref_mem_base = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
++      bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
+       /* Support interrupt A for MSI feature */
+       bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
diff --git a/queue-5.4/pci-aardvark-fix-compilation-on-s390.patch b/queue-5.4/pci-aardvark-fix-compilation-on-s390.patch
new file mode 100644 (file)
index 0000000..c7e3842
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:02 +0100
+Subject: PCI: aardvark: Fix compilation on s390
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "kernel test robot" <lkp@intel.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <marek.behun@nic.cz>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-9-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit b32c012e4b98f0126aa327be2d1f409963057643 upstream.
+
+Include linux/gpio/consumer.h instead of linux/gpio.h, as is said in the
+latter file.
+
+This was reported by kernel test bot when compiling for s390.
+
+  drivers/pci/controller/pci-aardvark.c:350:2: error: implicit declaration of function 'gpiod_set_value_cansleep' [-Werror,-Wimplicit-function-declaration]
+  drivers/pci/controller/pci-aardvark.c:1074:21: error: implicit declaration of function 'devm_gpiod_get_from_of_node' [-Werror,-Wimplicit-function-declaration]
+  drivers/pci/controller/pci-aardvark.c:1076:14: error: use of undeclared identifier 'GPIOD_OUT_LOW'
+
+Link: https://lore.kernel.org/r/202006211118.LxtENQfl%25lkp@intel.com
+Link: https://lore.kernel.org/r/20200907111038.5811-2-pali@kernel.org
+Fixes: 5169a9851daa ("PCI: aardvark: Issue PERST via GPIO")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <marek.behun@nic.cz>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -9,7 +9,7 @@
+  */
+ #include <linux/delay.h>
+-#include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/irqdomain.h>
diff --git a/queue-5.4/pci-aardvark-fix-link-training.patch b/queue-5.4/pci-aardvark-fix-link-training.patch
new file mode 100644 (file)
index 0000000..09cc0c2
--- /dev/null
@@ -0,0 +1,320 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:11 +0100
+Subject: PCI: aardvark: Fix link training
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-18-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit f76b36d40beee0a13aa8f6aa011df0d7cbbb8a7f upstream.
+
+Fix multiple link training issues in aardvark driver. The main reason of
+these issues was misunderstanding of what certain registers do, since their
+names and comments were misleading: before commit 96be36dbffac ("PCI:
+aardvark: Replace custom macros by standard linux/pci_regs.h macros"), the
+pci-aardvark.c driver used custom macros for accessing standard PCIe Root
+Bridge registers, and misleading comments did not help to understand what
+the code was really doing.
+
+After doing more tests and experiments I've come to the conclusion that the
+SPEED_GEN register in aardvark sets the PCIe revision / generation
+compliance and forces maximal link speed. Both GEN3 and GEN2 values set the
+read-only PCI_EXP_FLAGS_VERS bits (PCIe capabilities version of Root
+Bridge) to value 2, while GEN1 value sets PCI_EXP_FLAGS_VERS to 1, which
+matches with PCI Express specifications revisions 3, 2 and 1 respectively.
+Changing SPEED_GEN also sets the read-only bits PCI_EXP_LNKCAP_SLS and
+PCI_EXP_LNKCAP2_SLS to corresponding speed.
+
+(Note that PCI Express rev 1 specification does not define PCI_EXP_LNKCAP2
+ and PCI_EXP_LNKCTL2 registers and when SPEED_GEN is set to GEN1 (which
+ also sets PCI_EXP_FLAGS_VERS set to 1), lspci cannot access
+ PCI_EXP_LNKCAP2 and PCI_EXP_LNKCTL2 registers.)
+
+Changing PCIe link speed can be done via PCI_EXP_LNKCTL2_TLS bits of
+PCI_EXP_LNKCTL2 register. Armada 3700 Functional Specifications says that
+the default value of PCI_EXP_LNKCTL2_TLS is based on SPEED_GEN value, but
+tests showed that the default value is always 8.0 GT/s, independently of
+speed set by SPEED_GEN. So after setting SPEED_GEN, we must also set value
+in PCI_EXP_LNKCTL2 register via PCI_EXP_LNKCTL2_TLS bits.
+
+Triggering PCI_EXP_LNKCTL_RL bit immediately after setting LINK_TRAINING_EN
+bit actually doesn't do anything. Tests have shown that a delay is needed
+after enabling LINK_TRAINING_EN bit. As triggering PCI_EXP_LNKCTL_RL
+currently does nothing, remove it.
+
+Commit 43fc679ced18 ("PCI: aardvark: Improve link training") introduced
+code which sets SPEED_GEN register based on negotiated link speed from
+PCI_EXP_LNKSTA_CLS bits of PCI_EXP_LNKSTA register. This code was added to
+fix detection of Compex WLE900VX (Atheros QCA9880) WiFi GEN1 PCIe cards, as
+otherwise these cards were "invisible" on PCIe bus (probably because they
+crashed). But apparently more people reported the same issues with these
+cards also with other PCIe controllers [1] and I was able to reproduce this
+issue also with other "noname" WiFi cards based on Atheros QCA9890 chip
+(with the same PCI vendor/device ids as Atheros QCA9880). So this is not an
+issue in aardvark but rather an issue in Atheros QCA98xx chips. Also, this
+issue only exists if the kernel is compiled with PCIe ASPM support, and a
+generic workaround for this is to change PCIe Bridge to 2.5 GT/s link speed
+via PCI_EXP_LNKCTL2_TLS_2_5GT bits in PCI_EXP_LNKCTL2 register [2], before
+triggering PCI_EXP_LNKCTL_RL bit. This workaround also works when SPEED_GEN
+is set to value GEN2 (5 GT/s). So remove this hack completely in the
+aardvark driver and always set SPEED_GEN to value from 'max-link-speed' DT
+property. Fix for Atheros QCA98xx chips is handled separately by patch [2].
+
+These two things (code for triggering PCI_EXP_LNKCTL_RL bit and changing
+SPEED_GEN value) also explain why commit 6964494582f5 ("PCI: aardvark:
+Train link immediately after enabling training") somehow fixed detection of
+those problematic Compex cards with Atheros chips: if triggering link
+retraining (via PCI_EXP_LNKCTL_RL bit) was done immediately after enabling
+link training (via LINK_TRAINING_EN), it did nothing. If there was a
+specific delay, aardvark HW already initialized PCIe link and therefore
+triggering link retraining caused the above issue. Compex cards triggered
+link down event and disappeared from the PCIe bus.
+
+Commit f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready before
+training link") added 100ms sleep before calling 'Start link training'
+command and explained that it is a requirement of PCI Express
+specification. But the code after this 100ms sleep was not doing 'Start
+link training', rather it triggered PCI_EXP_LNKCTL_RL bit via PCIe Root
+Bridge to put link into Recovery state.
+
+The required delay after fundamental reset is already done in function
+advk_pcie_wait_for_link() which also checks whether PCIe link is up.
+So after removing the code which triggers PCI_EXP_LNKCTL_RL bit on PCIe
+Root Bridge, there is no need to wait 100ms again. Remove the extra
+msleep() call and update comment about the delay required by the PCI
+Express specification.
+
+According to Marvell Armada 3700 Functional Specifications, Link training
+should be enabled via aardvark register LINK_TRAINING_EN after selecting
+PCIe generation and x1 lane. There is no need to disable it prior resetting
+card via PERST# signal. This disabling code was introduced in commit
+5169a9851daa ("PCI: aardvark: Issue PERST via GPIO") as a workaround for
+some Atheros cards. It turns out that this also is Atheros specific issue
+and affects any PCIe controller, not only aardvark. Moreover this Atheros
+issue was triggered by juggling with PCI_EXP_LNKCTL_RL, LINK_TRAINING_EN
+and SPEED_GEN bits interleaved with sleeps. Now, after removing triggering
+PCI_EXP_LNKCTL_RL, there is no need to explicitly disable LINK_TRAINING_EN
+bit. So remove this code too. The problematic Compex cards described in
+previous git commits are correctly detected in advk_pcie_train_link()
+function even after applying all these changes.
+
+Note that with this patch, and also prior this patch, some NVMe disks which
+support PCIe GEN3 with 8 GT/s speed are negotiated only at the lowest link
+speed 2.5 GT/s, independently of SPEED_GEN value. After manually triggering
+PCI_EXP_LNKCTL_RL bit (e.g. from userspace via setpci), these NVMe disks
+change link speed to 5 GT/s when SPEED_GEN was configured to GEN2. This
+issue first needs to be properly investigated. I will send a fix in the
+future.
+
+On the other hand, some other GEN2 PCIe cards with 5 GT/s speed are
+autonomously by HW autonegotiated at full 5 GT/s speed without need of any
+software interaction.
+
+Armada 3700 Functional Specifications describes the following steps for
+link training: set SPEED_GEN to GEN2, enable LINK_TRAINING_EN, poll until
+link training is complete, trigger PCI_EXP_LNKCTL_RL, poll until signal
+rate is 5 GT/s, poll until link training is complete, enable ASPM L0s.
+
+The requirement for triggering PCI_EXP_LNKCTL_RL can be explained by the
+need to achieve 5 GT/s speed (as changing link speed is done by throw to
+recovery state entered by PCI_EXP_LNKCTL_RL) or maybe as a part of enabling
+ASPM L0s (but in this case ASPM L0s should have been enabled prior
+PCI_EXP_LNKCTL_RL).
+
+It is unknown why the original pci-aardvark.c driver was triggering
+PCI_EXP_LNKCTL_RL bit before waiting for the link to be up. This does not
+align with neither PCIe base specifications nor with Armada 3700 Functional
+Specification. (Note that in older versions of aardvark, this bit was
+called incorrectly PCIE_CORE_LINK_TRAINING, so this may be the reason.)
+
+It is also unknown why Armada 3700 Functional Specification says that it is
+needed to trigger PCI_EXP_LNKCTL_RL for GEN2 mode, as according to PCIe
+base specification 5 GT/s speed negotiation is supposed to be entirely
+autonomous, even if initial speed is 2.5 GT/s.
+
+[1] - https://lore.kernel.org/linux-pci/87h7l8axqp.fsf@toke.dk/
+[2] - https://lore.kernel.org/linux-pci/20210326124326.21163-1-pali@kernel.org/
+
+Link: https://lore.kernel.org/r/20211005180952.6812-12-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |  119 ++++++++++------------------------
+ 1 file changed, 35 insertions(+), 84 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -303,11 +303,6 @@ static inline u32 advk_readl(struct advk
+       return readl(pcie->base + reg);
+ }
+-static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg)
+-{
+-      return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8);
+-}
+-
+ static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
+ {
+       u32 val;
+@@ -381,23 +376,9 @@ static void advk_pcie_wait_for_retrain(s
+ static void advk_pcie_issue_perst(struct advk_pcie *pcie)
+ {
+-      u32 reg;
+-
+       if (!pcie->reset_gpio)
+               return;
+-      /*
+-       * As required by PCI Express spec (PCI Express Base Specification, REV.
+-       * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay
+-       * for at least 100ms after de-asserting PERST# signal is needed before
+-       * link training is enabled. So ensure that link training is disabled
+-       * prior de-asserting PERST# signal to fulfill that PCI Express spec
+-       * requirement.
+-       */
+-      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);
+@@ -405,54 +386,47 @@ static void advk_pcie_issue_perst(struct
+       gpiod_set_value_cansleep(pcie->reset_gpio, 0);
+ }
+-static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
++static void advk_pcie_train_link(struct advk_pcie *pcie)
+ {
+-      int ret, neg_gen;
++      struct device *dev = &pcie->pdev->dev;
+       u32 reg;
++      int ret;
+-      /* Setup link speed */
++      /*
++       * Setup PCIe rev / gen compliance based on device tree property
++       * 'max-link-speed' which also forces maximal link speed.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg &= ~PCIE_GEN_SEL_MSK;
+-      if (gen == 3)
++      if (pcie->link_gen == 3)
+               reg |= SPEED_GEN_3;
+-      else if (gen == 2)
++      else if (pcie->link_gen == 2)
+               reg |= SPEED_GEN_2;
+       else
+               reg |= SPEED_GEN_1;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+       /*
+-       * Enable link training. This is not needed in every call to this
+-       * function, just once suffices, but it does not break anything either.
+-       */
++       * Set maximal link speed value also into PCIe Link Control 2 register.
++       * Armada 3700 Functional Specification says that default value is based
++       * on SPEED_GEN but tests showed that default value is always 8.0 GT/s.
++       */
++      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
++      reg &= ~PCI_EXP_LNKCTL2_TLS;
++      if (pcie->link_gen == 3)
++              reg |= PCI_EXP_LNKCTL2_TLS_8_0GT;
++      else if (pcie->link_gen == 2)
++              reg |= PCI_EXP_LNKCTL2_TLS_5_0GT;
++      else
++              reg |= PCI_EXP_LNKCTL2_TLS_2_5GT;
++      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
++
++      /* Enable link training after selecting PCIe generation */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg |= LINK_TRAINING_EN;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+       /*
+-       * Start link training immediately after enabling it.
+-       * This solves problems for some buggy cards.
+-       */
+-      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
+-      reg |= PCI_EXP_LNKCTL_RL;
+-      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
+-
+-      ret = advk_pcie_wait_for_link(pcie);
+-      if (ret)
+-              return ret;
+-
+-      reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA);
+-      neg_gen = reg & PCI_EXP_LNKSTA_CLS;
+-
+-      return neg_gen;
+-}
+-
+-static void advk_pcie_train_link(struct advk_pcie *pcie)
+-{
+-      struct device *dev = &pcie->pdev->dev;
+-      int neg_gen = -1, gen;
+-
+-      /*
+        * Reset PCIe card via PERST# signal. Some cards are not detected
+        * during link training when they are in some non-initial state.
+        */
+@@ -462,41 +436,18 @@ static void advk_pcie_train_link(struct
+        * PERST# signal could have been asserted by pinctrl subsystem before
+        * 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.
+-       */
+-      msleep(PCI_PM_D3COLD_WAIT);
+-
+-      /*
+-       * Try link training at link gen specified by device tree property
+-       * 'max-link-speed'. If this fails, iteratively train at lower gen.
+-       */
+-      for (gen = pcie->link_gen; gen > 0; --gen) {
+-              neg_gen = advk_pcie_train_at_gen(pcie, gen);
+-              if (neg_gen > 0)
+-                      break;
+-      }
+-
+-      if (neg_gen < 0)
+-              goto err;
+-
+-      /*
+-       * After successful training if negotiated gen is lower than requested,
+-       * train again on negotiated gen. This solves some stability issues for
+-       * some buggy gen1 cards.
++       * fundamental reset. As required by PCI Express spec (PCI Express
++       * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1
++       * Conventional Reset) a delay for at least 100ms after such a reset
++       * before sending a Configuration Request to the device is needed.
++       * So wait until PCIe link is up. Function advk_pcie_wait_for_link()
++       * waits for link at least 900ms.
+        */
+-      if (neg_gen < gen) {
+-              gen = neg_gen;
+-              neg_gen = advk_pcie_train_at_gen(pcie, gen);
+-      }
+-
+-      if (neg_gen == gen) {
+-              dev_info(dev, "link up at gen %i\n", gen);
+-              return;
+-      }
+-
+-err:
+-      dev_err(dev, "link never came up\n");
++      ret = advk_pcie_wait_for_link(pcie);
++      if (ret < 0)
++              dev_err(dev, "link never came up\n");
++      else
++              dev_info(dev, "link up\n");
+ }
+ /*
diff --git a/queue-5.4/pci-aardvark-fix-pcie-max-payload-size-setting.patch b/queue-5.4/pci-aardvark-fix-pcie-max-payload-size-setting.patch
new file mode 100644 (file)
index 0000000..a23057f
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:07 +0100
+Subject: PCI: aardvark: Fix PCIe Max Payload Size setting
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-14-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit a4e17d65dafdd3513042d8f00404c9b6068a825c upstream.
+
+Change PCIe Max Payload Size setting in PCIe Device Control register to 512
+bytes to align with PCIe Link Initialization sequence as defined in Marvell
+Armada 3700 Functional Specification. According to the specification,
+maximal Max Payload Size supported by this device is 512 bytes.
+
+Without this kernel prints suspicious line:
+
+    pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 256 (was 16384, max 512)
+
+With this change it changes to:
+
+    pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 256 (was 512, max 512)
+
+Link: https://lore.kernel.org/r/20211005180952.6812-3-kabel@kernel.org
+Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -565,8 +565,9 @@ static void advk_pcie_setup_hw(struct ad
+       reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
+       reg &= ~PCI_EXP_DEVCTL_RELAX_EN;
+       reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
++      reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
+       reg &= ~PCI_EXP_DEVCTL_READRQ;
+-      reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */
++      reg |= PCI_EXP_DEVCTL_PAYLOAD_512B;
+       reg |= PCI_EXP_DEVCTL_READRQ_512B;
+       advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
diff --git a/queue-5.4/pci-aardvark-fix-support-for-bus-mastering-and-pci_command-on-emulated-bridge.patch b/queue-5.4/pci-aardvark-fix-support-for-bus-mastering-and-pci_command-on-emulated-bridge.patch
new file mode 100644 (file)
index 0000000..7802898
--- /dev/null
@@ -0,0 +1,125 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:12 +0100
+Subject: PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-19-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 771153fc884f566a89af2d30033b7f3bc6e24e84 upstream.
+
+>From very vague, ambiguous and incomplete information from Marvell we
+deduced that the 32-bit Aardvark register at address 0x4
+(PCIE_CORE_CMD_STATUS_REG), which is not documented for Root Complex mode
+in the Functional Specification (only for Endpoint mode), controls two
+16-bit PCIe registers: Command Register and Status Registers of PCIe Root
+Port.
+
+This means that bit 2 controls bus mastering and forwarding of memory and
+I/O requests in the upstream direction. According to PCI specifications
+bits [0:2] of Command Register, this should be by default disabled on
+reset. So explicitly disable these bits at early setup of the Aardvark
+driver.
+
+Remove code which unconditionally enables all 3 bits and let kernel code
+(via pci_set_master() function) to handle bus mastering of Root PCIe
+Bridge via emulated PCI_COMMAND on emulated bridge.
+
+Link: https://lore.kernel.org/r/20211028185659.20329-5-kabel@kernel.org
+Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org # b2a56469d550 ("PCI: aardvark: Add FIXME comment for PCIE_CORE_CMD_STATUS_REG access")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   47 +++++++++++++++++++++++++++-------
+ 1 file changed, 38 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -27,9 +27,6 @@
+ /* PCIe core registers */
+ #define PCIE_CORE_DEV_ID_REG                                  0x0
+ #define PCIE_CORE_CMD_STATUS_REG                              0x4
+-#define     PCIE_CORE_CMD_IO_ACCESS_EN                                BIT(0)
+-#define     PCIE_CORE_CMD_MEM_ACCESS_EN                               BIT(1)
+-#define     PCIE_CORE_CMD_MEM_IO_REQ_EN                               BIT(2)
+ #define PCIE_CORE_DEV_REV_REG                                 0x8
+ #define PCIE_CORE_PCIEXP_CAP                                  0xc0
+ #define PCIE_CORE_ERR_CAPCTL_REG                              0x118
+@@ -505,6 +502,11 @@ static void advk_pcie_setup_hw(struct ad
+       reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL;
+       advk_writel(pcie, reg, VENDOR_ID_REG);
++      /* Disable Root Bridge I/O space, memory space and bus mastering */
++      reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
++      reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++      advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
++
+       /* Set Advanced Error Capabilities and Control PF0 register */
+       reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |
+               PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN |
+@@ -603,12 +605,6 @@ static void advk_pcie_setup_hw(struct ad
+               advk_pcie_disable_ob_win(pcie, i);
+       advk_pcie_train_link(pcie);
+-
+-      reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+-      reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
+-              PCIE_CORE_CMD_IO_ACCESS_EN |
+-              PCIE_CORE_CMD_MEM_IO_REQ_EN;
+-      advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
+ }
+ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val)
+@@ -737,6 +733,37 @@ static int advk_pcie_wait_pio(struct adv
+       return -ETIMEDOUT;
+ }
++static pci_bridge_emul_read_status_t
++advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
++                                  int reg, u32 *value)
++{
++      struct advk_pcie *pcie = bridge->data;
++
++      switch (reg) {
++      case PCI_COMMAND:
++              *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
++              return PCI_BRIDGE_EMUL_HANDLED;
++
++      default:
++              return PCI_BRIDGE_EMUL_NOT_HANDLED;
++      }
++}
++
++static void
++advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
++                                   int reg, u32 old, u32 new, u32 mask)
++{
++      struct advk_pcie *pcie = bridge->data;
++
++      switch (reg) {
++      case PCI_COMMAND:
++              advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG);
++              break;
++
++      default:
++              break;
++      }
++}
+ static pci_bridge_emul_read_status_t
+ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+@@ -838,6 +865,8 @@ advk_pci_bridge_emul_pcie_conf_write(str
+ }
+ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
++      .read_base = advk_pci_bridge_emul_base_conf_read,
++      .write_base = advk_pci_bridge_emul_base_conf_write,
+       .read_pcie = advk_pci_bridge_emul_pcie_conf_read,
+       .write_pcie = advk_pci_bridge_emul_pcie_conf_write,
+ };
diff --git a/queue-5.4/pci-aardvark-fix-support-for-pci_bridge_ctl_bus_reset-on-emulated-bridge.patch b/queue-5.4/pci-aardvark-fix-support-for-pci_bridge_ctl_bus_reset-on-emulated-bridge.patch
new file mode 100644 (file)
index 0000000..a87b6bc
--- /dev/null
@@ -0,0 +1,78 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:14 +0100
+Subject: PCI: aardvark: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-21-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit bc4fac42e5f8460af09c0a7f2f1915be09e20c71 upstream.
+
+Aardvark supports PCIe Hot Reset via PCIE_CORE_CTRL1_REG.
+
+Use it for implementing PCI_BRIDGE_CTL_BUS_RESET bit of PCI_BRIDGE_CONTROL
+register on emulated bridge.
+
+With this, the function pci_reset_secondary_bus() starts working and can
+reset connected PCIe card. Custom userspace script [1] which uses setpci
+can trigger PCIe Hot Reset and reset the card manually.
+
+[1] https://alexforencich.com/wiki/en/pcie/hot-reset-linux
+
+Link: https://lore.kernel.org/r/20211028185659.20329-7-kabel@kernel.org
+Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -764,6 +764,22 @@ advk_pci_bridge_emul_base_conf_read(stru
+               *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+               return PCI_BRIDGE_EMUL_HANDLED;
++      case PCI_INTERRUPT_LINE: {
++              /*
++               * From the whole 32bit register we support reading from HW only
++               * one bit: PCI_BRIDGE_CTL_BUS_RESET.
++               * Other bits are retrieved only from emulated config buffer.
++               */
++              __le32 *cfgspace = (__le32 *)&bridge->conf;
++              u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
++              if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN)
++                      val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
++              else
++                      val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16);
++              *value = val;
++              return PCI_BRIDGE_EMUL_HANDLED;
++      }
++
+       default:
+               return PCI_BRIDGE_EMUL_NOT_HANDLED;
+       }
+@@ -780,6 +796,17 @@ advk_pci_bridge_emul_base_conf_write(str
+               advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG);
+               break;
++      case PCI_INTERRUPT_LINE:
++              if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
++                      u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG);
++                      if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
++                              val |= HOT_RESET_GEN;
++                      else
++                              val &= ~HOT_RESET_GEN;
++                      advk_writel(pcie, val, PCIE_CORE_CTRL1_REG);
++              }
++              break;
++
+       default:
+               break;
+       }
diff --git a/queue-5.4/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch b/queue-5.4/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
new file mode 100644 (file)
index 0000000..ddef196
--- /dev/null
@@ -0,0 +1,212 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:09 +0100
+Subject: PCI: aardvark: Implement re-issuing config requests on CRS response
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-16-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 223dec14a05337a4155f1deed46d2becce4d00fd upstream.
+
+Commit 43f5c77bcbd2 ("PCI: aardvark: Fix reporting CRS value") fixed
+handling of CRS response and when CRSSVE flag was not enabled it marked CRS
+response as failed transaction (due to simplicity).
+
+But pci-aardvark.c driver is already waiting up to the PIO_RETRY_CNT count
+for PIO config response and so we can with a small change implement
+re-issuing of config requests as described in PCIe base specification.
+
+This change implements re-issuing of config requests when response is CRS.
+Set upper bound of wait cycles to around PIO_RETRY_CNT, afterwards the
+transaction is marked as failed and an all-ones value is returned as
+before.
+
+We do this by returning appropriate error codes from function
+advk_pcie_check_pio_status(). On CRS we return -EAGAIN and caller then
+reissues transaction.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-10-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   69 +++++++++++++++++++++-------------
+ 1 file changed, 44 insertions(+), 25 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -666,6 +666,7 @@ static int advk_pcie_check_pio_status(st
+       u32 reg;
+       unsigned int status;
+       char *strcomp_status, *str_posted;
++      int ret;
+       reg = advk_readl(pcie, PIO_STAT);
+       status = (reg & PIO_COMPLETION_STATUS_MASK) >>
+@@ -690,6 +691,7 @@ static int advk_pcie_check_pio_status(st
+       case PIO_COMPLETION_STATUS_OK:
+               if (reg & PIO_ERR_STATUS) {
+                       strcomp_status = "COMP_ERR";
++                      ret = -EFAULT;
+                       break;
+               }
+               /* Get the read result */
+@@ -697,9 +699,11 @@ static int advk_pcie_check_pio_status(st
+                       *val = advk_readl(pcie, PIO_RD_DATA);
+               /* No error */
+               strcomp_status = NULL;
++              ret = 0;
+               break;
+       case PIO_COMPLETION_STATUS_UR:
+               strcomp_status = "UR";
++              ret = -EOPNOTSUPP;
+               break;
+       case PIO_COMPLETION_STATUS_CRS:
+               if (allow_crs && val) {
+@@ -717,6 +721,7 @@ static int advk_pcie_check_pio_status(st
+                        */
+                       *val = CFG_RD_CRS_VAL;
+                       strcomp_status = NULL;
++                      ret = 0;
+                       break;
+               }
+               /* PCIe r4.0, sec 2.3.2, says:
+@@ -732,21 +737,24 @@ static int advk_pcie_check_pio_status(st
+                * Request and taking appropriate action, e.g., complete the
+                * Request to the host as a failed transaction.
+                *
+-               * To simplify implementation do not re-issue the Configuration
+-               * Request and complete the Request as a failed transaction.
++               * So return -EAGAIN and caller (pci-aardvark.c driver) will
++               * re-issue request again up to the PIO_RETRY_CNT retries.
+                */
+               strcomp_status = "CRS";
++              ret = -EAGAIN;
+               break;
+       case PIO_COMPLETION_STATUS_CA:
+               strcomp_status = "CA";
++              ret = -ECANCELED;
+               break;
+       default:
+               strcomp_status = "Unknown";
++              ret = -EINVAL;
+               break;
+       }
+       if (!strcomp_status)
+-              return 0;
++              return ret;
+       if (reg & PIO_NON_POSTED_REQ)
+               str_posted = "Non-posted";
+@@ -756,7 +764,7 @@ static int advk_pcie_check_pio_status(st
+       dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n",
+               str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS));
+-      return -EFAULT;
++      return ret;
+ }
+ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
+@@ -764,13 +772,13 @@ static int advk_pcie_wait_pio(struct adv
+       struct device *dev = &pcie->pdev->dev;
+       int i;
+-      for (i = 0; i < PIO_RETRY_CNT; i++) {
++      for (i = 1; i <= PIO_RETRY_CNT; i++) {
+               u32 start, isr;
+               start = advk_readl(pcie, PIO_START);
+               isr = advk_readl(pcie, PIO_ISR);
+               if (!start && isr)
+-                      return 0;
++                      return i;
+               udelay(PIO_RETRY_DELAY);
+       }
+@@ -974,6 +982,7 @@ static int advk_pcie_rd_conf(struct pci_
+                            int where, int size, u32 *val)
+ {
+       struct advk_pcie *pcie = bus->sysdata;
++      int retry_count;
+       bool allow_crs;
+       u32 reg;
+       int ret;
+@@ -1016,16 +1025,22 @@ static int advk_pcie_rd_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
+-      /* Clear PIO DONE ISR and start the transfer */
+-      advk_writel(pcie, 1, PIO_ISR);
+-      advk_writel(pcie, 1, PIO_START);
+-
+-      ret = advk_pcie_wait_pio(pcie);
+-      if (ret < 0)
+-              goto try_crs;
++      retry_count = 0;
++      do {
++              /* Clear PIO DONE ISR and start the transfer */
++              advk_writel(pcie, 1, PIO_ISR);
++              advk_writel(pcie, 1, PIO_START);
++
++              ret = advk_pcie_wait_pio(pcie);
++              if (ret < 0)
++                      goto try_crs;
++
++              retry_count += ret;
++
++              /* Check PIO status and get the read result */
++              ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
++      } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
+-      /* Check PIO status and get the read result */
+-      ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
+       if (ret < 0)
+               goto fail;
+@@ -1057,6 +1072,7 @@ static int advk_pcie_wr_conf(struct pci_
+       struct advk_pcie *pcie = bus->sysdata;
+       u32 reg;
+       u32 data_strobe = 0x0;
++      int retry_count;
+       int offset;
+       int ret;
+@@ -1098,19 +1114,22 @@ static int advk_pcie_wr_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB);
+-      /* Clear PIO DONE ISR and start the transfer */
+-      advk_writel(pcie, 1, PIO_ISR);
+-      advk_writel(pcie, 1, PIO_START);
++      retry_count = 0;
++      do {
++              /* Clear PIO DONE ISR and start the transfer */
++              advk_writel(pcie, 1, PIO_ISR);
++              advk_writel(pcie, 1, PIO_START);
++
++              ret = advk_pcie_wait_pio(pcie);
++              if (ret < 0)
++                      return PCIBIOS_SET_FAILED;
+-      ret = advk_pcie_wait_pio(pcie);
+-      if (ret < 0)
+-              return PCIBIOS_SET_FAILED;
++              retry_count += ret;
+-      ret = advk_pcie_check_pio_status(pcie, false, NULL);
+-      if (ret < 0)
+-              return PCIBIOS_SET_FAILED;
++              ret = advk_pcie_check_pio_status(pcie, false, NULL);
++      } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
+-      return PCIBIOS_SUCCESSFUL;
++      return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;
+ }
+ static struct pci_ops advk_pcie_ops = {
diff --git a/queue-5.4/pci-aardvark-improve-link-training.patch b/queue-5.4/pci-aardvark-improve-link-training.patch
new file mode 100644 (file)
index 0000000..73a1f1b
--- /dev/null
@@ -0,0 +1,214 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:25:58 +0100
+Subject: PCI: aardvark: Improve link training
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <marek.behun@nic.cz>, "Tomasz Maciej Nowak" <tmn505@gmail.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Rob Herring" <robh@kernel.org>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-5-kabel@kernel.org>
+
+From: Marek Behún <marek.behun@nic.cz>
+
+commit 43fc679ced18006b12d918d7a8a4af392b7fbfe7 upstream.
+
+Currently the aardvark driver trains link in PCIe gen2 mode. This may
+cause some buggy gen1 cards (such as Compex WLE900VX) to be unstable or
+even not detected. Moreover when ASPM code tries to retrain link second
+time, these cards may stop responding and link goes down. If gen1 is
+used this does not happen.
+
+Unconditionally forcing gen1 is not a good solution since it may have
+performance impact on gen2 cards.
+
+To overcome this, read 'max-link-speed' property (as defined in PCI
+device tree bindings) and use this as max gen mode. Then iteratively try
+link training at this mode or lower until successful. After successful
+link training choose final controller gen based on Negotiated Link Speed
+from Link Status register, which should match card speed.
+
+Link: https://lore.kernel.org/r/20200430080625.26070-5-pali@kernel.org
+Tested-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <marek.behun@nic.cz>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |  114 ++++++++++++++++++++++++++--------
+ 1 file changed, 89 insertions(+), 25 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -39,6 +39,7 @@
+ #define PCIE_CORE_LINK_CTRL_STAT_REG                          0xd0
+ #define     PCIE_CORE_LINK_L0S_ENTRY                          BIT(0)
+ #define     PCIE_CORE_LINK_TRAINING                           BIT(5)
++#define     PCIE_CORE_LINK_SPEED_SHIFT                                16
+ #define     PCIE_CORE_LINK_WIDTH_SHIFT                                20
+ #define PCIE_CORE_ERR_CAPCTL_REG                              0x118
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX                  BIT(5)
+@@ -249,6 +250,7 @@ struct advk_pcie {
+       struct mutex msi_used_lock;
+       u16 msi_msg;
+       int root_bus_nr;
++      int link_gen;
+       struct pci_bridge_emul bridge;
+ };
+@@ -309,20 +311,16 @@ static inline bool advk_pcie_link_traini
+ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
+ {
+-      struct device *dev = &pcie->pdev->dev;
+       int retries;
+       /* check if the link is up or not */
+       for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+-              if (advk_pcie_link_up(pcie)) {
+-                      dev_info(dev, "link up\n");
++              if (advk_pcie_link_up(pcie))
+                       return 0;
+-              }
+               usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+       }
+-      dev_err(dev, "link never came up\n");
+       return -ETIMEDOUT;
+ }
+@@ -337,6 +335,85 @@ static void advk_pcie_wait_for_retrain(s
+       }
+ }
++static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
++{
++      int ret, neg_gen;
++      u32 reg;
++
++      /* Setup link speed */
++      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++      reg &= ~PCIE_GEN_SEL_MSK;
++      if (gen == 3)
++              reg |= SPEED_GEN_3;
++      else if (gen == 2)
++              reg |= SPEED_GEN_2;
++      else
++              reg |= SPEED_GEN_1;
++      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
++
++      /*
++       * Enable link training. This is not needed in every call to this
++       * function, just once suffices, but it does not break anything either.
++       */
++      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++      reg |= LINK_TRAINING_EN;
++      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
++
++      /*
++       * Start link training immediately after enabling it.
++       * This solves problems for some buggy cards.
++       */
++      reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
++      reg |= PCIE_CORE_LINK_TRAINING;
++      advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
++
++      ret = advk_pcie_wait_for_link(pcie);
++      if (ret)
++              return ret;
++
++      reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
++      neg_gen = (reg >> PCIE_CORE_LINK_SPEED_SHIFT) & 0xf;
++
++      return neg_gen;
++}
++
++static void advk_pcie_train_link(struct advk_pcie *pcie)
++{
++      struct device *dev = &pcie->pdev->dev;
++      int neg_gen = -1, gen;
++
++      /*
++       * Try link training at link gen specified by device tree property
++       * 'max-link-speed'. If this fails, iteratively train at lower gen.
++       */
++      for (gen = pcie->link_gen; gen > 0; --gen) {
++              neg_gen = advk_pcie_train_at_gen(pcie, gen);
++              if (neg_gen > 0)
++                      break;
++      }
++
++      if (neg_gen < 0)
++              goto err;
++
++      /*
++       * After successful training if negotiated gen is lower than requested,
++       * train again on negotiated gen. This solves some stability issues for
++       * some buggy gen1 cards.
++       */
++      if (neg_gen < gen) {
++              gen = neg_gen;
++              neg_gen = advk_pcie_train_at_gen(pcie, gen);
++      }
++
++      if (neg_gen == gen) {
++              dev_info(dev, "link up at gen %i\n", gen);
++              return;
++      }
++
++err:
++      dev_err(dev, "link never came up\n");
++}
++
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
+       u32 reg;
+@@ -382,12 +459,6 @@ static void advk_pcie_setup_hw(struct ad
+               PCIE_CORE_CTRL2_TD_ENABLE;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
+-      /* Set GEN2 */
+-      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+-      reg &= ~PCIE_GEN_SEL_MSK;
+-      reg |= SPEED_GEN_2;
+-      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+-
+       /* Set lane X1 */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg &= ~LANE_CNT_MSK;
+@@ -435,20 +506,7 @@ static void advk_pcie_setup_hw(struct ad
+        */
+       msleep(PCI_PM_D3COLD_WAIT);
+-      /* Enable link training */
+-      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+-      reg |= LINK_TRAINING_EN;
+-      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+-
+-      /*
+-       * Start link training immediately after enabling it.
+-       * This solves problems for some buggy cards.
+-       */
+-      reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
+-      reg |= PCIE_CORE_LINK_TRAINING;
+-      advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
+-
+-      advk_pcie_wait_for_link(pcie);
++      advk_pcie_train_link(pcie);
+       reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+       reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
+@@ -1278,6 +1336,12 @@ static int advk_pcie_probe(struct platfo
+               return ret;
+       }
++      ret = of_pci_get_max_link_speed(dev->of_node);
++      if (ret <= 0 || ret > 3)
++              pcie->link_gen = 3;
++      else
++              pcie->link_gen = ret;
++
+       advk_pcie_setup_hw(pcie);
+       ret = advk_sw_pci_bridge_init(pcie);
diff --git a/queue-5.4/pci-aardvark-issue-perst-via-gpio.patch b/queue-5.4/pci-aardvark-issue-perst-via-gpio.patch
new file mode 100644 (file)
index 0000000..782968f
--- /dev/null
@@ -0,0 +1,129 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:25:59 +0100
+Subject: PCI: aardvark: Issue PERST via GPIO
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" <tmn505@gmail.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-6-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 5169a9851daaa2782a7bd2bb83d5b1bd224b2879 upstream.
+
+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>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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"
+@@ -252,6 +254,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)
+@@ -414,10 +417,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);
+@@ -500,7 +524,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.
+        */
+@@ -1336,6 +1361,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;
diff --git a/queue-5.4/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch b/queue-5.4/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch
new file mode 100644 (file)
index 0000000..abc6d44
--- /dev/null
@@ -0,0 +1,130 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:03 +0100
+Subject: PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link()
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <marek.behun@nic.cz>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-10-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit d0c6a3475b033960e85ae2bf176b14cab0a627d2 upstream.
+
+Move code which belongs to link training (delays and resets) into
+advk_pcie_train_link() function, so everything related to link training,
+including timings is at one place.
+
+After experiments it can be observed that link training in aardvark
+hardware is very sensitive to timings and delays, so it is a good idea to
+have this code at the same place as link training calls.
+
+This patch does not change behavior of aardvark initialization.
+
+Link: https://lore.kernel.org/r/20200907111038.5811-6-pali@kernel.org
+Tested-by: Marek Behún <marek.behun@nic.cz>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   64 ++++++++++++++++++----------------
+ 1 file changed, 34 insertions(+), 30 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -332,6 +332,25 @@ static void advk_pcie_wait_for_retrain(s
+       }
+ }
++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 int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
+ {
+       int ret, neg_gen;
+@@ -380,6 +399,21 @@ static void advk_pcie_train_link(struct
+       int neg_gen = -1, gen;
+       /*
++       * Reset PCIe card via PERST# signal. Some cards are not detected
++       * during link training when they are in some non-initial state.
++       */
++      advk_pcie_issue_perst(pcie);
++
++      /*
++       * PERST# signal could have been asserted by pinctrl subsystem before
++       * 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.
++       */
++      msleep(PCI_PM_D3COLD_WAIT);
++
++      /*
+        * Try link training at link gen specified by device tree property
+        * 'max-link-speed'. If this fails, iteratively train at lower gen.
+        */
+@@ -411,31 +445,10 @@ 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);
+@@ -517,15 +530,6 @@ static void advk_pcie_setup_hw(struct ad
+       reg |= PIO_CTRL_ADDR_WIN_DISABLE;
+       advk_writel(pcie, reg, PIO_CTRL);
+-      /*
+-       * PERST# signal could have been asserted by pinctrl subsystem before
+-       * 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.
+-       */
+-      msleep(PCI_PM_D3COLD_WAIT);
+-
+       advk_pcie_train_link(pcie);
+       reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
diff --git a/queue-5.4/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch b/queue-5.4/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch
new file mode 100644 (file)
index 0000000..f2f5840
--- /dev/null
@@ -0,0 +1,103 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:00 +0100
+Subject: PCI: aardvark: Replace custom macros by standard linux/pci_regs.h macros
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" <tmn505@gmail.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Rob Herring" <robh@kernel.org>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-7-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 96be36dbffacea0aa9e6ec4839583e79faa141a1 upstream.
+
+PCI-E capability macros are already defined in linux/pci_regs.h.
+Remove their reimplementation in pcie-aardvark.
+
+Link: https://lore.kernel.org/r/20200430080625.26070-9-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>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   41 ++++++++++++++--------------------
+ 1 file changed, 18 insertions(+), 23 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -32,17 +32,6 @@
+ #define     PCIE_CORE_CMD_MEM_IO_REQ_EN                               BIT(2)
+ #define PCIE_CORE_DEV_REV_REG                                 0x8
+ #define PCIE_CORE_PCIEXP_CAP                                  0xc0
+-#define PCIE_CORE_DEV_CTRL_STATS_REG                          0xc8
+-#define     PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE      (0 << 4)
+-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT     5
+-#define     PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE            (0 << 11)
+-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT    12
+-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ            0x2
+-#define PCIE_CORE_LINK_CTRL_STAT_REG                          0xd0
+-#define     PCIE_CORE_LINK_L0S_ENTRY                          BIT(0)
+-#define     PCIE_CORE_LINK_TRAINING                           BIT(5)
+-#define     PCIE_CORE_LINK_SPEED_SHIFT                                16
+-#define     PCIE_CORE_LINK_WIDTH_SHIFT                                20
+ #define PCIE_CORE_ERR_CAPCTL_REG                              0x118
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX                  BIT(5)
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN                       BIT(6)
+@@ -267,6 +256,11 @@ static inline u32 advk_readl(struct advk
+       return readl(pcie->base + reg);
+ }
++static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg)
++{
++      return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8);
++}
++
+ static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
+ {
+       u32 val;
+@@ -366,16 +360,16 @@ static int advk_pcie_train_at_gen(struct
+        * Start link training immediately after enabling it.
+        * This solves problems for some buggy cards.
+        */
+-      reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
+-      reg |= PCIE_CORE_LINK_TRAINING;
+-      advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
++      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
++      reg |= PCI_EXP_LNKCTL_RL;
++      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
+       ret = advk_pcie_wait_for_link(pcie);
+       if (ret)
+               return ret;
+-      reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
+-      neg_gen = (reg >> PCIE_CORE_LINK_SPEED_SHIFT) & 0xf;
++      reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA);
++      neg_gen = reg & PCI_EXP_LNKSTA_CLS;
+       return neg_gen;
+ }
+@@ -470,13 +464,14 @@ static void advk_pcie_setup_hw(struct ad
+               PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV;
+       advk_writel(pcie, reg, PCIE_CORE_ERR_CAPCTL_REG);
+-      /* Set PCIe Device Control and Status 1 PF0 register */
+-      reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
+-              (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
+-              PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
+-              (PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ <<
+-               PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT);
+-      advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
++      /* Set PCIe Device Control register */
++      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
++      reg &= ~PCI_EXP_DEVCTL_RELAX_EN;
++      reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
++      reg &= ~PCI_EXP_DEVCTL_READRQ;
++      reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */
++      reg |= PCI_EXP_DEVCTL_READRQ_512B;
++      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
+       /* Program PCIe Control 2 to disable strict ordering */
+       reg = PCIE_CORE_CTRL2_RESERVED |
diff --git a/queue-5.4/pci-aardvark-set-pci-bridge-class-code-to-pci-bridge.patch b/queue-5.4/pci-aardvark-set-pci-bridge-class-code-to-pci-bridge.patch
new file mode 100644 (file)
index 0000000..a0104a1
--- /dev/null
@@ -0,0 +1,65 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:13 +0100
+Subject: PCI: aardvark: Set PCI Bridge Class Code to PCI Bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-20-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 84e1b4045dc887b78bdc87d92927093dc3a465aa upstream.
+
+Aardvark controller has something like config space of a Root Port
+available at offset 0x0 of internal registers - these registers are used
+for implementation of the emulated bridge.
+
+The default value of Class Code of this bridge corresponds to a RAID Mass
+storage controller, though. (This is probably intended for when the
+controller is used as Endpoint.)
+
+Change the Class Code to correspond to a PCI Bridge.
+
+Add comment explaining this change.
+
+Link: https://lore.kernel.org/r/20211028185659.20329-6-kabel@kernel.org
+Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -502,6 +502,26 @@ static void advk_pcie_setup_hw(struct ad
+       reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL;
+       advk_writel(pcie, reg, VENDOR_ID_REG);
++      /*
++       * Change Class Code of PCI Bridge device to PCI Bridge (0x600400),
++       * because the default value is Mass storage controller (0x010400).
++       *
++       * Note that this Aardvark PCI Bridge does not have compliant Type 1
++       * Configuration Space and it even cannot be accessed via Aardvark's
++       * PCI config space access method. Something like config space is
++       * available in internal Aardvark registers starting at offset 0x0
++       * and is reported as Type 0. In range 0x10 - 0x34 it has totally
++       * different registers.
++       *
++       * Therefore driver uses emulation of PCI Bridge which emulates
++       * access to configuration space via internal Aardvark registers or
++       * emulated configuration buffer.
++       */
++      reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG);
++      reg &= ~0xffffff00;
++      reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
++      advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG);
++
+       /* Disable Root Bridge I/O space, memory space and bus mastering */
+       reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+       reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
diff --git a/queue-5.4/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch b/queue-5.4/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
new file mode 100644 (file)
index 0000000..219dd6e
--- /dev/null
@@ -0,0 +1,63 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:10 +0100
+Subject: PCI: aardvark: Simplify initialization of rootcap on virtual bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
+Message-ID: <20211125002616.31363-17-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 454c53271fc11f3aa5e44e41fd99ca181bd32c62 upstream.
+
+PCIe config space can be initialized also before pci_bridge_emul_init()
+call, so move rootcap initialization after PCI config space initialization.
+
+This simplifies the function a little since it removes one if (ret < 0)
+check.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-11-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -898,7 +898,6 @@ static struct pci_bridge_emul_ops advk_p
+ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
+ {
+       struct pci_bridge_emul *bridge = &pcie->bridge;
+-      int ret;
+       bridge->conf.vendor =
+               cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
+@@ -918,19 +917,14 @@ static int advk_sw_pci_bridge_init(struc
+       /* Support interrupt A for MSI feature */
+       bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
++      /* Indicates supports for Completion Retry Status */
++      bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
++
+       bridge->has_pcie = true;
+       bridge->data = pcie;
+       bridge->ops = &advk_pci_bridge_emul_ops;
+-      /* PCIe config space can be initialized after pci_bridge_emul_init() */
+-      ret = pci_bridge_emul_init(bridge, 0);
+-      if (ret < 0)
+-              return ret;
+-
+-      /* Indicates supports for Completion Retry Status */
+-      bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
+-
+-      return 0;
++      return pci_bridge_emul_init(bridge, 0);
+ }
+ static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
diff --git a/queue-5.4/pci-aardvark-train-link-immediately-after-enabling-training.patch b/queue-5.4/pci-aardvark-train-link-immediately-after-enabling-training.patch
new file mode 100644 (file)
index 0000000..32d9c74
--- /dev/null
@@ -0,0 +1,66 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:25:57 +0100
+Subject: PCI: aardvark: Train link immediately after enabling training
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" <tmn505@gmail.com>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Rob Herring" <robh@kernel.org>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-4-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 6964494582f56a3882c2c53b0edbfe99eb32b2e1 upstream.
+
+Adding even 100ms (PCI_PM_D3COLD_WAIT) delay between enabling link
+training and starting link training causes detection issues with some
+buggy cards (such as Compex WLE900VX).
+
+Move the code which enables link training immediately before the one
+which starts link traning.
+
+This fixes detection issues of Compex WLE900VX card on Turris MOX after
+cold boot.
+
+Link: https://lore.kernel.org/r/20200430080625.26070-2-pali@kernel.org
+Fixes: f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready...")
+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: Rob Herring <robh@kernel.org>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -394,11 +394,6 @@ static void advk_pcie_setup_hw(struct ad
+       reg |= LANE_COUNT_1;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+-      /* Enable link training */
+-      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+-      reg |= LINK_TRAINING_EN;
+-      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+-
+       /* Enable MSI */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
+       reg |= PCIE_CORE_CTRL2_MSI_ENABLE;
+@@ -440,7 +435,15 @@ static void advk_pcie_setup_hw(struct ad
+        */
+       msleep(PCI_PM_D3COLD_WAIT);
+-      /* Start link training */
++      /* Enable link training */
++      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++      reg |= LINK_TRAINING_EN;
++      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
++
++      /*
++       * Start link training immediately after enabling it.
++       * This solves problems for some buggy cards.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
+       reg |= PCIE_CORE_LINK_TRAINING;
+       advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
diff --git a/queue-5.4/pci-aardvark-update-comment-about-disabling-link-training.patch b/queue-5.4/pci-aardvark-update-comment-about-disabling-link-training.patch
new file mode 100644 (file)
index 0000000..504a41c
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:04 +0100
+Subject: PCI: aardvark: Update comment about disabling link training
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-11-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1d1cd163d0de22a4041a6f1aeabcf78f80076539 upstream.
+
+According to PCI Express Base Specifications (rev 4.0, 6.6.1
+"Conventional reset"), after fundamental reset a 100ms delay is needed
+prior to enabling link training.
+
+Update comment in code to reflect this requirement.
+
+Link: https://lore.kernel.org/r/20201202184659.3795-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -339,7 +339,14 @@ static void advk_pcie_issue_perst(struct
+       if (!pcie->reset_gpio)
+               return;
+-      /* PERST does not work for some cards when link training is enabled */
++      /*
++       * As required by PCI Express spec (PCI Express Base Specification, REV.
++       * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay
++       * for at least 100ms after de-asserting PERST# signal is needed before
++       * link training is enabled. So ensure that link training is disabled
++       * prior de-asserting PERST# signal to fulfill that PCI Express spec
++       * requirement.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg &= ~LINK_TRAINING_EN;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
diff --git a/queue-5.4/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch b/queue-5.4/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch
new file mode 100644 (file)
index 0000000..0f6a7ea
--- /dev/null
@@ -0,0 +1,58 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:25:55 +0100
+Subject: PCI: aardvark: Wait for endpoint to be ready before training link
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Remi Pommarel" <repk@triplefau.lt>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-2-kabel@kernel.org>
+
+From: Remi Pommarel <repk@triplefau.lt>
+
+commit f4c7d053d7f77cd5c1a1ba7c7ce085ddba13d1d7 upstream.
+
+When configuring pcie reset pin from gpio (e.g. initially set by
+u-boot) to pcie function this pin goes low for a brief moment
+asserting the PERST# signal. Thus connected device enters fundamental
+reset process and link configuration can only begin after a minimal
+100ms delay (see [1]).
+
+Because the pin configuration comes from the "default" pinctrl it is
+implicitly configured before the probe callback is called:
+
+driver_probe_device()
+  really_probe()
+    ...
+    pinctrl_bind_pins() /* Here pin goes from gpio to PCIE reset
+                           function and PERST# is asserted */
+    ...
+    drv->probe()
+
+[1] "PCI Express Base Specification", REV. 4.0
+    PCI Express, February 19 2014, 6.6.1 Conventional Reset
+
+Signed-off-by: Remi Pommarel <repk@triplefau.lt>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -432,6 +432,14 @@ static void advk_pcie_setup_hw(struct ad
+       reg |= PIO_CTRL_ADDR_WIN_DISABLE;
+       advk_writel(pcie, reg, PIO_CTRL);
++      /*
++       * PERST# signal could have been asserted by pinctrl subsystem before
++       * probe() callback has been called, 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.
++       */
++      msleep(PCI_PM_D3COLD_WAIT);
++
+       /* Start link training */
+       reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
+       reg |= PCIE_CORE_LINK_TRAINING;
diff --git a/queue-5.4/pci-pci-bridge-emul-fix-array-overruns-improve-safety.patch b/queue-5.4/pci-pci-bridge-emul-fix-array-overruns-improve-safety.patch
new file mode 100644 (file)
index 0000000..8439db3
--- /dev/null
@@ -0,0 +1,72 @@
+From foo@baz Sun Nov 28 01:44:17 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:05 +0100
+Subject: PCI: pci-bridge-emul: Fix array overruns, improve safety
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Russell King" <rmk+kernel@armlinux.org.uk>, "Bjorn Helgaas" <bhelgaas@google.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211125002616.31363-12-kabel@kernel.org>
+
+From: Russell King <rmk+kernel@armlinux.org.uk>
+
+commit f8ee579d53aca887d93f5f411462f25c085a5106 upstream.
+
+We allow up to PCI_EXP_SLTSTA2 registers to be accessed, but the
+pcie_cap_regs_behavior[] array only covers up to PCI_EXP_RTSTA.  Expand
+this array to avoid walking off the end of it.
+
+Do the same for pci_regs_behavior for consistency[], and add a
+BUILD_BUG_ON() to also check the bridge->conf structure size.
+
+Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic")
+Link: https://lore.kernel.org/r/E1l6z9W-0006Re-MQ@rmk-PC.armlinux.org.uk
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pci-bridge-emul.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/pci-bridge-emul.c
++++ b/drivers/pci/pci-bridge-emul.c
+@@ -21,8 +21,9 @@
+ #include "pci-bridge-emul.h"
+ #define PCI_BRIDGE_CONF_END   PCI_STD_HEADER_SIZEOF
++#define PCI_CAP_PCIE_SIZEOF   (PCI_EXP_SLTSTA2 + 2)
+ #define PCI_CAP_PCIE_START    PCI_BRIDGE_CONF_END
+-#define PCI_CAP_PCIE_END      (PCI_CAP_PCIE_START + PCI_EXP_SLTSTA2 + 2)
++#define PCI_CAP_PCIE_END      (PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
+ struct pci_bridge_reg_behavior {
+       /* Read-only bits */
+@@ -38,7 +39,8 @@ struct pci_bridge_reg_behavior {
+       u32 rsvd;
+ };
+-static const struct pci_bridge_reg_behavior pci_regs_behavior[] = {
++static const
++struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = {
+       [PCI_VENDOR_ID / 4] = { .ro = ~0 },
+       [PCI_COMMAND / 4] = {
+               .rw = (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+@@ -173,7 +175,8 @@ static const struct pci_bridge_reg_behav
+       },
+ };
+-static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = {
++static const
++struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = {
+       [PCI_CAP_LIST_ID / 4] = {
+               /*
+                * Capability ID, Next Capability Pointer and
+@@ -270,6 +273,8 @@ static const struct pci_bridge_reg_behav
+ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
+                        unsigned int flags)
+ {
++      BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END);
++
+       bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
+       bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
+       bridge->conf.cache_line_size = 0x10;
diff --git a/queue-5.4/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch b/queue-5.4/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch
new file mode 100644 (file)
index 0000000..36b9827
--- /dev/null
@@ -0,0 +1,101 @@
+From foo@baz Sun Nov 28 01:44:18 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 01:26:15 +0100
+Subject: pinctrl: armada-37xx: Correct PWM pins definitions
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" <kabel@kernel.org>, "Rob Herring" <robh@kernel.org>, "Linus Walleij" <linus.walleij@linaro.org>
+Message-ID: <20211125002616.31363-22-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit baf8d6899b1e8906dc076ef26cc633e96a8bb0c3 upstream.
+
+The PWM pins on North Bridge on Armada 37xx can be configured into PWM
+or GPIO functions. When in PWM function, each pin can also be configured
+to drive low on 0 and tri-state on 1 (LED mode).
+
+The current definitions handle this by declaring two pin groups for each
+pin:
+- group "pwmN" with functions "pwm" and "gpio"
+- group "ledN_od" ("od" for open drain) with functions "led" and "gpio"
+
+This is semantically incorrect. The correct definition for each pin
+should be one group with three functions: "pwm", "led" and "gpio".
+
+Change the "pwmN" groups to support "led" function.
+
+Remove "ledN_od" groups. This cannot break backwards compatibility with
+older device trees: no device tree uses it since there is no PWM driver
+for this SOC yet. Also "ledN_od" groups are not even documented.
+
+Fixes: b835d6953009 ("pinctrl: armada-37xx: swap polarity on LED group")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Acked-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20210719112938.27594-1-kabel@kernel.org
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt |    8 ++--
+ drivers/pinctrl/mvebu/pinctrl-armada-37xx.c                               |   17 ++++------
+ 2 files changed, 12 insertions(+), 13 deletions(-)
+
+--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
+@@ -43,19 +43,19 @@ group emmc_nb
+ group pwm0
+  - pin 11 (GPIO1-11)
+- - functions pwm, gpio
++ - functions pwm, led, gpio
+ group pwm1
+  - pin 12
+- - functions pwm, gpio
++ - functions pwm, led, gpio
+ group pwm2
+  - pin 13
+- - functions pwm, gpio
++ - functions pwm, led, gpio
+ group pwm3
+  - pin 14
+- - functions pwm, gpio
++ - functions pwm, led, gpio
+ group pmic1
+  - pin 7
+--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+@@ -166,10 +166,14 @@ static struct armada_37xx_pin_group arma
+       PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"),
+       PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"),
+       PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"),
+-      PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"),
+-      PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
+-      PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
+-      PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
++      PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3),
++                     "pwm", "led"),
++      PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4),
++                     "pwm", "led"),
++      PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5),
++                     "pwm", "led"),
++      PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6),
++                     "pwm", "led"),
+       PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
+       PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
+       PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
+@@ -183,11 +187,6 @@ static struct armada_37xx_pin_group arma
+       PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19),
+                     BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19),
+                     18, 2, "gpio", "uart"),
+-      PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"),
+-      PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
+-      PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
+-      PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
+-
+ };
+ static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
index 1bdb07398c78bd9796c55e368248615a25e52a97..feb0292a13b43151cd54888454ea30f5ba76d792 100644 (file)
@@ -20,3 +20,25 @@ tracing-uprobe-fix-uprobe_perf_open-probes-iteration.patch
 tracing-fix-pid-filtering-when-triggers-are-attached.patch
 mmc-sdhci-fix-adma-for-page_size-64kib.patch
 mdio-aspeed-fix-link-is-down-issue.patch
+pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
+pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch
+pci-aardvark-fix-big-endian-support.patch
+pci-aardvark-train-link-immediately-after-enabling-training.patch
+pci-aardvark-improve-link-training.patch
+pci-aardvark-issue-perst-via-gpio.patch
+pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch
+pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch
+pci-aardvark-fix-compilation-on-s390.patch
+pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch
+pci-aardvark-update-comment-about-disabling-link-training.patch
+pci-pci-bridge-emul-fix-array-overruns-improve-safety.patch
+pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch
+pci-aardvark-fix-pcie-max-payload-size-setting.patch
+pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
+pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
+pci-aardvark-fix-link-training.patch
+pci-aardvark-fix-support-for-bus-mastering-and-pci_command-on-emulated-bridge.patch
+pci-aardvark-set-pci-bridge-class-code-to-pci-bridge.patch
+pci-aardvark-fix-support-for-pci_bridge_ctl_bus_reset-on-emulated-bridge.patch
+pinctrl-armada-37xx-correct-pwm-pins-definitions.patch
+arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch