--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:59 +0100
+Subject: arm64: dts: marvell: armada-37xx: declare PCIe reset pin
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Miquel Raynal" <miquel.raynal@bootlin.com>, "Gregory CLEMENT" <gregory.clement@bootlin.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211124230500.27109-20-kabel@kernel.org>
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+commit a5470af981a0cc14a650af8da5186668971a4fc8 upstream.
+
+One pin can be muxed as PCIe endpoint card reset.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@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-37xx.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -254,6 +254,15 @@
+ function = "mii";
+ };
+
++ pcie_reset_pins: pcie-reset-pins {
++ groups = "pcie1";
++ function = "pcie";
++ };
++
++ pcie_clkreq_pins: pcie-clkreq-pins {
++ groups = "pcie1_clkreq";
++ function = "pcie";
++ };
+ };
+
+ eth0: ethernet@30000 {
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:05:00 +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: <20211124230500.27109-21-kabel@kernel.org>
+
+From: Marek Behún <marek.behun@nic.cz>
+
+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 | 3 +++
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +-
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+--- 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
+@@ -55,6 +55,9 @@
+
+ /* J9 */
+ &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-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -256,7 +256,7 @@
+
+ pcie_reset_pins: pcie-reset-pins {
+ groups = "pcie1";
+- function = "pcie";
++ function = "gpio";
+ };
+
+ pcie_clkreq_pins: pcie-clkreq-pins {
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:52 +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: <20211124230500.27109-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
+@@ -106,6 +106,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)
+@@ -174,6 +214,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;
+@@ -349,9 +396,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);
+@@ -415,15 +492,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);
+@@ -1038,6 +1151,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));
+@@ -1067,6 +1181,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,
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:48 +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: <20211124230500.27109-9-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
+@@ -525,6 +525,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;
+ }
+
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:41 +0100
+Subject: PCI: aardvark: Fix a leaked reference by adding missing of_node_put()
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Wen Yang" <wen.yang99@zte.com.cn>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Bjorn Helgaas" <bhelgaas@google.com>, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211124230500.27109-2-kabel@kernel.org>
+
+From: Wen Yang <wen.yang99@zte.com.cn>
+
+commit 3842f5166bf1ef286fe7a39f262b5c9581308366 upstream.
+
+The call to of_get_next_child() returns a node pointer with refcount
+incremented thus it must be explicitly decremented after the last
+usage.
+
+irq_domain_add_linear() also calls of_node_get() to increase refcount,
+so irq_domain will not be affected when it is released.
+
+Detected by coccinelle with the following warnings:
+ ./drivers/pci/controller/pci-aardvark.c:826:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 798, but without a corresponding object release within this function.
+
+Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: linux-pci@vger.kernel.org
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@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 | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -754,6 +754,7 @@ static int advk_pcie_init_irq_domain(str
+ struct device_node *node = dev->of_node;
+ struct device_node *pcie_intc_node;
+ struct irq_chip *irq_chip;
++ int ret = 0;
+
+ raw_spin_lock_init(&pcie->irq_lock);
+
+@@ -768,8 +769,8 @@ static int advk_pcie_init_irq_domain(str
+ irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq",
+ dev_name(dev));
+ if (!irq_chip->name) {
+- of_node_put(pcie_intc_node);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto out_put_node;
+ }
+
+ irq_chip->irq_mask = advk_pcie_irq_mask;
+@@ -781,11 +782,13 @@ static int advk_pcie_init_irq_domain(str
+ &advk_pcie_irq_domain_ops, pcie);
+ if (!pcie->irq_domain) {
+ dev_err(dev, "Failed to get a INTx IRQ domain\n");
+- of_node_put(pcie_intc_node);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto out_put_node;
+ }
+
+- return 0;
++out_put_node:
++ of_node_put(pcie_intc_node);
++ return ret;
+ }
+
+ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:55 +0100
+Subject: PCI: aardvark: Fix checking for link up via LTSSM state
+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>, "Remi Pommarel" <repk@triplefau.lt>
+Message-ID: <20211124230500.27109-16-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 661c399a651c11aaf83c45cbfe0b4a1fb7bc3179 upstream.
+
+Current implementation of advk_pcie_link_up() is wrong as it marks also
+link disabled or hot reset states as link up.
+
+Fix it by marking link up only to those states which are defined in PCIe
+Base specification 3.0, Table 4-14: Link Status Mapped to the LTSSM.
+
+To simplify implementation, Define macros for every LTSSM state which
+aardvark hardware can return in CFG_REG register.
+
+Fix also checking for link training according to the same Table 4-14.
+Define a new function advk_pcie_link_training() for this purpose.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-13-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
+Cc: Remi Pommarel <repk@triplefau.lt>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 71 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 67 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -151,9 +151,50 @@
+ #define CFG_REG (LMI_BASE_ADDR + 0x0)
+ #define LTSSM_SHIFT 24
+ #define LTSSM_MASK 0x3f
+-#define LTSSM_L0 0x10
+ #define RC_BAR_CONFIG 0x300
+
++/* LTSSM values in CFG_REG */
++enum {
++ LTSSM_DETECT_QUIET = 0x0,
++ LTSSM_DETECT_ACTIVE = 0x1,
++ LTSSM_POLLING_ACTIVE = 0x2,
++ LTSSM_POLLING_COMPLIANCE = 0x3,
++ LTSSM_POLLING_CONFIGURATION = 0x4,
++ LTSSM_CONFIG_LINKWIDTH_START = 0x5,
++ LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6,
++ LTSSM_CONFIG_LANENUM_ACCEPT = 0x7,
++ LTSSM_CONFIG_LANENUM_WAIT = 0x8,
++ LTSSM_CONFIG_COMPLETE = 0x9,
++ LTSSM_CONFIG_IDLE = 0xa,
++ LTSSM_RECOVERY_RCVR_LOCK = 0xb,
++ LTSSM_RECOVERY_SPEED = 0xc,
++ LTSSM_RECOVERY_RCVR_CFG = 0xd,
++ LTSSM_RECOVERY_IDLE = 0xe,
++ LTSSM_L0 = 0x10,
++ LTSSM_RX_L0S_ENTRY = 0x11,
++ LTSSM_RX_L0S_IDLE = 0x12,
++ LTSSM_RX_L0S_FTS = 0x13,
++ LTSSM_TX_L0S_ENTRY = 0x14,
++ LTSSM_TX_L0S_IDLE = 0x15,
++ LTSSM_TX_L0S_FTS = 0x16,
++ LTSSM_L1_ENTRY = 0x17,
++ LTSSM_L1_IDLE = 0x18,
++ LTSSM_L2_IDLE = 0x19,
++ LTSSM_L2_TRANSMIT_WAKE = 0x1a,
++ LTSSM_DISABLED = 0x20,
++ LTSSM_LOOPBACK_ENTRY_MASTER = 0x21,
++ LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22,
++ LTSSM_LOOPBACK_EXIT_MASTER = 0x23,
++ LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24,
++ LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25,
++ LTSSM_LOOPBACK_EXIT_SLAVE = 0x26,
++ LTSSM_HOT_RESET = 0x27,
++ LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28,
++ LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29,
++ LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a,
++ LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b,
++};
++
+ /* PCIe core controller registers */
+ #define CTRL_CORE_BASE_ADDR 0x18000
+ #define CTRL_CONFIG_REG (CTRL_CORE_BASE_ADDR + 0x0)
+@@ -247,13 +288,35 @@ static inline u32 advk_readl(struct advk
+ return readl(pcie->base + reg);
+ }
+
+-static int advk_pcie_link_up(struct advk_pcie *pcie)
++static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
+ {
+- u32 val, ltssm_state;
++ u32 val;
++ u8 ltssm_state;
+
+ val = advk_readl(pcie, CFG_REG);
+ ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
+- return ltssm_state >= LTSSM_L0;
++ return ltssm_state;
++}
++
++static inline bool advk_pcie_link_up(struct advk_pcie *pcie)
++{
++ /* check if LTSSM is in normal operation - some L* state */
++ u8 ltssm_state = advk_pcie_ltssm_state(pcie);
++ return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
++}
++
++static inline bool advk_pcie_link_training(struct advk_pcie *pcie)
++{
++ /*
++ * According to PCIe Base specification 3.0, Table 4-14: Link
++ * Status Mapped to the LTSSM is Link Training mapped to LTSSM
++ * Configuration and Recovery states.
++ */
++ u8 ltssm_state = advk_pcie_ltssm_state(pcie);
++ return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START &&
++ ltssm_state < LTSSM_L0) ||
++ (ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 &&
++ ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3));
+ }
+
+ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:49 +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: <20211124230500.27109-10-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>
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:54 +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: <20211124230500.27109-15-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: 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
+@@ -247,11 +247,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 int advk_pcie_link_up(struct advk_pcie *pcie)
+ {
+ u32 val, ltssm_state;
+@@ -278,23 +273,9 @@ static int advk_pcie_wait_for_link(struc
+
+ 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);
+@@ -302,54 +283,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.
+ */
+@@ -359,41 +333,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");
+ }
+
+ /*
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:53 +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: <20211124230500.27109-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
+@@ -452,8 +452,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);
+
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:44 +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: <20211124230500.27109-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
+@@ -35,6 +35,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)
+@@ -193,6 +194,7 @@ struct advk_pcie {
+ struct mutex msi_used_lock;
+ u16 msi_msg;
+ int root_bus_nr;
++ int link_gen;
+ };
+
+ static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
+@@ -216,23 +218,98 @@ static int advk_pcie_link_up(struct advk
+
+ 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;
+ }
+
++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;
+@@ -268,12 +345,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;
+@@ -321,20 +392,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 |
+@@ -968,6 +1026,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_pcie_init_irq_domain(pcie);
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:47 +0100
+Subject: PCI: aardvark: Indicate error in 'val' when config read fails
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Bjorn Helgaas" <helgaas@kernel.org>, "Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211124230500.27109-8-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit b1bd5714472cc72e14409f5659b154c765a76c65 upstream.
+
+Most callers of config read do not check for return value. But most of the
+ones that do, checks for error indication in 'val' variable.
+
+This patch updates error handling in advk_pcie_rd_conf() function. If PIO
+transfer fails then 'val' variable is set to 0xffffffff which indicates
+failture.
+
+Link: https://lore.kernel.org/r/20200528162604.GA323482@bjorn-Precision-5520
+Link: https://lore.kernel.org/r/20200601130315.18895-1-pali@kernel.org
+Reported-by: Bjorn Helgaas <helgaas@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 | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -596,8 +596,10 @@ static int advk_pcie_rd_conf(struct pci_
+ advk_writel(pcie, 1, PIO_START);
+
+ ret = advk_pcie_wait_pio(pcie);
+- if (ret < 0)
++ if (ret < 0) {
++ *val = 0xffffffff;
+ return PCIBIOS_SET_FAILED;
++ }
+
+ /* Check PIO status and get the read result */
+ ret = advk_pcie_check_pio_status(pcie, val);
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:45 +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: <20211124230500.27109-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"
+@@ -195,6 +197,7 @@ struct advk_pcie {
+ u16 msi_msg;
+ int root_bus_nr;
+ int link_gen;
++ struct gpio_desc *reset_gpio;
+ };
+
+ static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
+@@ -310,10 +313,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);
+@@ -386,7 +410,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.
+ */
+@@ -1026,6 +1051,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;
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:50 +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: <20211124230500.27109-11-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
+@@ -229,6 +229,25 @@ static int advk_pcie_wait_for_link(struc
+ return -ETIMEDOUT;
+ }
+
++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;
+@@ -277,6 +296,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.
+ */
+@@ -308,31 +342,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);
+@@ -404,15 +417,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);
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:46 +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: <20211124230500.27109-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 | 42 +++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 23 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -28,17 +28,7 @@
+ #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_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_PCIEXP_CAP 0xc0
+ #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)
+@@ -210,6 +200,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 int advk_pcie_link_up(struct advk_pcie *pcie)
+ {
+ u32 val, ltssm_state;
+@@ -262,16 +257,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;
+ }
+@@ -356,13 +351,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 |
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:43 +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: <20211124230500.27109-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
+@@ -280,11 +280,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;
+@@ -326,7 +321,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);
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:51 +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: <20211124230500.27109-12-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
+@@ -236,7 +236,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);
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:42 +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: <20211124230500.27109-3-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
+@@ -318,6 +318,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;
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:57 +0100
+Subject: pinctrl: armada-37xx: add missing pin: PCIe1 Wakeup
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: pali@kernel.org, stable@vger.kernel.org, "Gregory CLEMENT" <gregory.clement@bootlin.com>, "Miquel Raynal" <miquel.raynal@bootlin.com>, "Linus Walleij" <linus.walleij@linaro.org>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211124230500.27109-18-kabel@kernel.org>
+
+From: Gregory CLEMENT <gregory.clement@bootlin.com>
+
+commit 4d98fbaacd79a82f408febb66a9c42fe42361b16 upstream.
+
+Declare the PCIe1 Wakeup which was initially missing.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Tested-by: Miquel Raynal <miquel.raynal@bootlin.com>
+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>
+---
+ drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+@@ -198,6 +198,7 @@ static struct armada_37xx_pin_group arma
+ PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"),
+ PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"),
+ PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"),
++ PIN_GRP_GPIO("pcie1_wakeup", 5, 1, BIT(10), "pcie"),
+ PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"),
+ PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
+ PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:56 +0100
+Subject: pinctrl: armada-37xx: Correct mpp definitions
+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>, "Gregory CLEMENT" <gregory.clement@bootlin.com>, "Miquel Raynal" <miquel.raynal@bootlin.com>, "Linus Walleij" <linus.walleij@linaro.org>, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20211124230500.27109-17-kabel@kernel.org>
+
+From: Marek Behún <marek.behun@nic.cz>
+
+commit 823868fceae3bac07cf5eccb128d6916e7a5ae9d upstream.
+
+This is a cleanup and fix of the patch by Ken Ma <make@marvell.com>.
+
+Fix the mpp definitions according to newest revision of the
+specification:
+ - northbridge:
+ fix pmic1 gpio number to 7
+ fix pmic0 gpio number to 6
+ - southbridge
+ split pcie1 group bit mask to BIT(5) and BIT(9)
+ fix ptp group bit mask to BIT(11) | BIT(12) | BIT(13)
+ add smi group with bit mask BIT(4)
+
+[gregory: split the pcie group in 2, as at hardware level they can be
+configured separately]
+Signed-off-by: Marek Behún <marek.behun@nic.cz>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Tested-by: Miquel Raynal <miquel.raynal@bootlin.com>
+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 | 18 +++++++---
+ drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 10 +++--
+ 2 files changed, 19 insertions(+), 9 deletions(-)
+
+--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
+@@ -58,11 +58,11 @@ group pwm3
+ - functions pwm, gpio
+
+ group pmic1
+- - pin 17
++ - pin 7
+ - functions pmic, gpio
+
+ group pmic0
+- - pin 16
++ - pin 6
+ - functions pmic, gpio
+
+ group i2c2
+@@ -112,17 +112,25 @@ group usb2_drvvbus1
+ - functions drvbus, gpio
+
+ group sdio_sb
+- - pins 60-64
++ - pins 60-65
+ - functions sdio, gpio
+
+ group rgmii
+- - pins 42-55
++ - pins 42-53
+ - functions mii, gpio
+
+ group pcie1
+- - pins 39-40
++ - pins 39
++ - functions pcie, gpio
++
++group pcie1_clkreq
++ - pins 40
+ - functions pcie, gpio
+
++group smi
++ - pins 54-55
++ - functions smi, gpio
++
+ group ptp
+ - pins 56-58
+ - functions ptp, gpio
+--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+@@ -170,8 +170,8 @@ static struct armada_37xx_pin_group arma
+ 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("pmic1", 17, 1, BIT(7), "pmic"),
+- PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"),
++ 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"),
+ PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"),
+ PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"),
+@@ -195,8 +195,10 @@ static struct armada_37xx_pin_group arma
+ PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"),
+ PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"),
+ PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"),
+- PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"),
+- PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"),
++ PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"),
++ PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"),
++ PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"),
++ PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"),
+ PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
+ PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
+ PIN_GRP_GPIO_3("mii_col", 23, 1, BIT(8) | BIT(14), 0, BIT(8), BIT(14),
--- /dev/null
+From foo@baz Sun Nov 28 02:10:56 PM CET 2021
+From: "Marek Behún" <kabel@kernel.org>
+Date: Thu, 25 Nov 2021 00:04:58 +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: <20211124230500.27109-19-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[] = {
--- /dev/null
+From c1e63117711977cc4295b2ce73de29dd17066c82 Mon Sep 17 00:00:00 2001
+From: David Hildenbrand <david@redhat.com>
+Date: Fri, 19 Nov 2021 16:43:58 -0800
+Subject: proc/vmcore: fix clearing user buffer by properly using clear_user()
+
+From: David Hildenbrand <david@redhat.com>
+
+commit c1e63117711977cc4295b2ce73de29dd17066c82 upstream.
+
+To clear a user buffer we cannot simply use memset, we have to use
+clear_user(). With a virtio-mem device that registers a vmcore_cb and
+has some logically unplugged memory inside an added Linux memory block,
+I can easily trigger a BUG by copying the vmcore via "cp":
+
+ systemd[1]: Starting Kdump Vmcore Save Service...
+ kdump[420]: Kdump is using the default log level(3).
+ kdump[453]: saving to /sysroot/var/crash/127.0.0.1-2021-11-11-14:59:22/
+ kdump[458]: saving vmcore-dmesg.txt to /sysroot/var/crash/127.0.0.1-2021-11-11-14:59:22/
+ kdump[465]: saving vmcore-dmesg.txt complete
+ kdump[467]: saving vmcore
+ BUG: unable to handle page fault for address: 00007f2374e01000
+ #PF: supervisor write access in kernel mode
+ #PF: error_code(0x0003) - permissions violation
+ PGD 7a523067 P4D 7a523067 PUD 7a528067 PMD 7a525067 PTE 800000007048f867
+ Oops: 0003 [#1] PREEMPT SMP NOPTI
+ CPU: 0 PID: 468 Comm: cp Not tainted 5.15.0+ #6
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.14.0-27-g64f37cc530f1-prebuilt.qemu.org 04/01/2014
+ RIP: 0010:read_from_oldmem.part.0.cold+0x1d/0x86
+ Code: ff ff ff e8 05 ff fe ff e9 b9 e9 7f ff 48 89 de 48 c7 c7 38 3b 60 82 e8 f1 fe fe ff 83 fd 08 72 3c 49 8d 7d 08 4c 89 e9 89 e8 <49> c7 45 00 00 00 00 00 49 c7 44 05 f8 00 00 00 00 48 83 e7 f81
+ RSP: 0018:ffffc9000073be08 EFLAGS: 00010212
+ RAX: 0000000000001000 RBX: 00000000002fd000 RCX: 00007f2374e01000
+ RDX: 0000000000000001 RSI: 00000000ffffdfff RDI: 00007f2374e01008
+ RBP: 0000000000001000 R08: 0000000000000000 R09: ffffc9000073bc50
+ R10: ffffc9000073bc48 R11: ffffffff829461a8 R12: 000000000000f000
+ R13: 00007f2374e01000 R14: 0000000000000000 R15: ffff88807bd421e8
+ FS: 00007f2374e12140(0000) GS:ffff88807f000000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007f2374e01000 CR3: 000000007a4aa000 CR4: 0000000000350eb0
+ Call Trace:
+ read_vmcore+0x236/0x2c0
+ proc_reg_read+0x55/0xa0
+ vfs_read+0x95/0x190
+ ksys_read+0x4f/0xc0
+ do_syscall_64+0x3b/0x90
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+Some x86-64 CPUs have a CPU feature called "Supervisor Mode Access
+Prevention (SMAP)", which is used to detect wrong access from the kernel
+to user buffers like this: SMAP triggers a permissions violation on
+wrong access. In the x86-64 variant of clear_user(), SMAP is properly
+handled via clac()+stac().
+
+To fix, properly use clear_user() when we're dealing with a user buffer.
+
+Link: https://lkml.kernel.org/r/20211112092750.6921-1-david@redhat.com
+Fixes: 997c136f518c ("fs/proc/vmcore.c: add hook to read_from_oldmem() to check for non-ram pages")
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Acked-by: Baoquan He <bhe@redhat.com>
+Cc: Dave Young <dyoung@redhat.com>
+Cc: Baoquan He <bhe@redhat.com>
+Cc: Vivek Goyal <vgoyal@redhat.com>
+Cc: Philipp Rudo <prudo@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/vmcore.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/fs/proc/vmcore.c
++++ b/fs/proc/vmcore.c
+@@ -117,14 +117,19 @@ static ssize_t read_from_oldmem(char *bu
+ nr_bytes = count;
+
+ /* If pfn is not ram, return zeros for sparse dump files */
+- if (pfn_is_ram(pfn) == 0)
+- memset(buf, 0, nr_bytes);
+- else {
++ if (pfn_is_ram(pfn) == 0) {
++ tmp = 0;
++ if (!userbuf)
++ memset(buf, 0, nr_bytes);
++ else if (clear_user(buf, nr_bytes))
++ tmp = -EFAULT;
++ } else {
+ tmp = copy_oldmem_page(pfn, buf, nr_bytes,
+ offset, userbuf);
+- if (tmp < 0)
+- return tmp;
+ }
++ if (tmp < 0)
++ return tmp;
++
+ *ppos += nr_bytes;
+ count -= nr_bytes;
+ buf += nr_bytes;
xen-don-t-continue-xenstore-initialization-in-case-of-errors.patch
xen-detect-uninitialized-xenbus-in-xenbus_init.patch
tracing-fix-pid-filtering-when-triggers-are-attached.patch
+xtensa-use-config_use_of-instead-of-config_of.patch
+proc-vmcore-fix-clearing-user-buffer-by-properly-using-clear_user.patch
+pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch
+pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.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-indicate-error-in-val-when-config-read-fails.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-aardvark-configure-pcie-resources-from-ranges-dt-property.patch
+pci-aardvark-fix-pcie-max-payload-size-setting.patch
+pci-aardvark-fix-link-training.patch
+pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch
+pinctrl-armada-37xx-correct-mpp-definitions.patch
+pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch
+pinctrl-armada-37xx-correct-pwm-pins-definitions.patch
+arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch
+arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch
--- /dev/null
+From d67ed2510d28a1eb33171010d35cf52178cfcbdd Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Fri, 24 Sep 2021 20:29:51 -0700
+Subject: xtensa: use CONFIG_USE_OF instead of CONFIG_OF
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+commit d67ed2510d28a1eb33171010d35cf52178cfcbdd upstream.
+
+CONFIG_OF can be set by a randconfig or by a user -- without setting the
+early flattree option (OF_EARLY_FLATTREE). This causes build errors.
+However, if randconfig or a user sets USE_OF in the Xtensa config,
+the right kconfig symbols are set to fix the build.
+
+Fixes these build errors:
+
+../arch/xtensa/kernel/setup.c:67:19: error: ‘__dtb_start’ undeclared here (not in a function); did you mean ‘dtb_start’?
+ 67 | void *dtb_start = __dtb_start;
+ | ^~~~~~~~~~~
+../arch/xtensa/kernel/setup.c: In function 'xtensa_dt_io_area':
+../arch/xtensa/kernel/setup.c:201:14: error: implicit declaration of function 'of_flat_dt_is_compatible'; did you mean 'of_machine_is_compatible'? [-Werror=implicit-function-declaration]
+ 201 | if (!of_flat_dt_is_compatible(node, "simple-bus"))
+../arch/xtensa/kernel/setup.c:204:18: error: implicit declaration of function 'of_get_flat_dt_prop' [-Werror=implicit-function-declaration]
+ 204 | ranges = of_get_flat_dt_prop(node, "ranges", &len);
+../arch/xtensa/kernel/setup.c:204:16: error: assignment to 'const __be32 *' {aka 'const unsigned int *'} from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
+ 204 | ranges = of_get_flat_dt_prop(node, "ranges", &len);
+ | ^
+../arch/xtensa/kernel/setup.c: In function 'early_init_devtree':
+../arch/xtensa/kernel/setup.c:228:9: error: implicit declaration of function 'early_init_dt_scan'; did you mean 'early_init_devtree'? [-Werror=implicit-function-declaration]
+ 228 | early_init_dt_scan(params);
+../arch/xtensa/kernel/setup.c:229:9: error: implicit declaration of function 'of_scan_flat_dt' [-Werror=implicit-function-declaration]
+ 229 | of_scan_flat_dt(xtensa_dt_io_area, NULL);
+
+xtensa-elf-ld: arch/xtensa/mm/mmu.o:(.text+0x0): undefined reference to `xtensa_kio_paddr'
+
+Fixes: da844a81779e ("xtensa: add device trees support")
+Fixes: 6cb971114f63 ("xtensa: remap io area defined in device tree")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/xtensa/kernel/setup.c | 12 ++++++------
+ arch/xtensa/mm/mmu.c | 2 +-
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/arch/xtensa/kernel/setup.c
++++ b/arch/xtensa/kernel/setup.c
+@@ -65,7 +65,7 @@ int initrd_is_mapped = 0;
+ extern int initrd_below_start_ok;
+ #endif
+
+-#ifdef CONFIG_OF
++#ifdef CONFIG_USE_OF
+ void *dtb_start = __dtb_start;
+ #endif
+
+@@ -127,7 +127,7 @@ __tagtable(BP_TAG_INITRD, parse_tag_init
+
+ #endif /* CONFIG_BLK_DEV_INITRD */
+
+-#ifdef CONFIG_OF
++#ifdef CONFIG_USE_OF
+
+ static int __init parse_tag_fdt(const bp_tag_t *tag)
+ {
+@@ -137,7 +137,7 @@ static int __init parse_tag_fdt(const bp
+
+ __tagtable(BP_TAG_FDT, parse_tag_fdt);
+
+-#endif /* CONFIG_OF */
++#endif /* CONFIG_USE_OF */
+
+ static int __init parse_tag_cmdline(const bp_tag_t* tag)
+ {
+@@ -185,7 +185,7 @@ static int __init parse_bootparam(const
+ }
+ #endif
+
+-#ifdef CONFIG_OF
++#ifdef CONFIG_USE_OF
+
+ #if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
+ unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
+@@ -234,7 +234,7 @@ void __init early_init_devtree(void *par
+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ }
+
+-#endif /* CONFIG_OF */
++#endif /* CONFIG_USE_OF */
+
+ /*
+ * Initialize architecture. (Early stage)
+@@ -255,7 +255,7 @@ void __init init_arch(bp_tag_t *bp_start
+ if (bp_start)
+ parse_bootparam(bp_start);
+
+-#ifdef CONFIG_OF
++#ifdef CONFIG_USE_OF
+ early_init_devtree(dtb_start);
+ #endif
+
+--- a/arch/xtensa/mm/mmu.c
++++ b/arch/xtensa/mm/mmu.c
+@@ -98,7 +98,7 @@ void init_mmu(void)
+
+ void init_kio(void)
+ {
+-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
++#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_USE_OF)
+ /*
+ * Update the IO area mapping in case xtensa_kio_paddr has changed
+ */