aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch')
-rw-r--r--target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch143
1 files changed, 143 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch b/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch
new file mode 100644
index 0000000000..777a078ef9
--- /dev/null
+++ b/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch
@@ -0,0 +1,143 @@
+From patchwork Thu Sep 28 12:58:35 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,
+ 4/7] PCI: aardvark: use isr1 instead of isr0 interrupt in legacy irq
+ mode
+X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+X-Patchwork-Id: 819592
+Message-Id: <20170928125838.11887-5-thomas.petazzoni@free-electrons.com>
+To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
+Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
+ Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
+ <gregory.clement@free-electrons.com>,
+ Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
+ Yehuda Yitschak <yehuday@marvell.com>,
+ linux-arm-kernel@lists.infradead.org, Antoine Tenart
+ <antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
+ <miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
+ Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 28 Sep 2017 14:58:35 +0200
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+List-Id: <linux-pci.vger.kernel.org>
+
+From: Victor Gu <xigu@marvell.com>
+
+The Aardvark has two interrupts sets:
+
+ - first set is bit[23:16] of PCIe ISR 0 register(RD0074840h)
+
+ - second set is bit[11:8] of PCIe ISR 1 register(RD0074848h)
+
+Only one set should be used, while another set should be masked.
+
+The second set, ISR1, is more advanced, the Legacy INT_X status bit is
+asserted once Assert_INTX message is received, and de-asserted after
+Deassert_INTX message is received. Therefore, it matches what the
+driver is currently doing in the ->irq_mask() and ->irq_unmask()
+functions. The ISR0 requires additional work to deassert the
+interrupt, which the driver doesn't do currently.
+
+This commit resolves a number of issues with legacy interrupts.
+
+This is part of fixing bug
+https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
+reported as the user to be important to get a Intel 7260 mini-PCIe
+WiFi card working.
+
+Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Victor Gu <xigu@marvell.com>
+Reviewed-by: Evan Wang <xswang@marvell.com>
+Reviewed-by: Nadav Haklai <nadavh@marvell.com>
+[Thomas: tweak commit log.]
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/pci/host/pci-aardvark.c | 41 ++++++++++++++++++++++++-----------------
+ 1 file changed, 24 insertions(+), 17 deletions(-)
+
+--- a/drivers/pci/host/pci-aardvark.c
++++ b/drivers/pci/host/pci-aardvark.c
+@@ -105,7 +105,8 @@
+ #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C)
+ #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4)
+ #define PCIE_ISR1_FLUSH BIT(5)
+-#define PCIE_ISR1_ALL_MASK GENMASK(5, 4)
++#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val))
++#define PCIE_ISR1_ALL_MASK GENMASK(11, 4)
+ #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50)
+ #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
+ #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
+@@ -615,9 +616,9 @@ static void advk_pcie_irq_mask(struct ir
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 mask;
+
+- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+- mask |= PCIE_ISR0_INTX_ASSERT(hwirq);
+- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
++ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
++ mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
++ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
+ }
+
+ static void advk_pcie_irq_unmask(struct irq_data *d)
+@@ -626,9 +627,9 @@ static void advk_pcie_irq_unmask(struct
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 mask;
+
+- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+- mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq);
+- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
++ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
++ mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
++ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
+ }
+
+ static int advk_pcie_irq_map(struct irq_domain *h,
+@@ -771,29 +772,35 @@ static void advk_pcie_handle_msi(struct
+
+ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ {
+- u32 val, mask, status;
++ u32 isr0_val, isr0_mask, isr0_status;
++ u32 isr1_val, isr1_mask, isr1_status;
+ int i, virq;
+
+- val = advk_readl(pcie, PCIE_ISR0_REG);
+- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+- status = val & ((~mask) & PCIE_ISR0_ALL_MASK);
+-
+- if (!status) {
+- advk_writel(pcie, val, PCIE_ISR0_REG);
++ isr0_val = advk_readl(pcie, PCIE_ISR0_REG);
++ isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++ isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK);
++
++ isr1_val = advk_readl(pcie, PCIE_ISR1_REG);
++ isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
++ isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
++
++ if (!isr0_status && !isr1_status) {
++ advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
++ advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
+ return;
+ }
+
+ /* Process MSI interrupts */
+- if (status & PCIE_ISR0_MSI_INT_PENDING)
++ if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
+ advk_pcie_handle_msi(pcie);
+
+ /* Process legacy interrupts */
+ for (i = 0; i < PCI_NUM_INTX; i++) {
+- if (!(status & PCIE_ISR0_INTX_ASSERT(i)))
++ if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i)))
+ continue;
+
+- advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i),
+- PCIE_ISR0_REG);
++ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
++ PCIE_ISR1_REG);
+
+ virq = irq_find_mapping(pcie->irq_domain, i);
+ generic_handle_irq(virq);