777a078ef91022a452650de082ad4de88b533a12
[openwrt/staging/jow.git] /
1 From patchwork Thu Sep 28 12:58:35 2017
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 Subject: [v2,
6 4/7] PCI: aardvark: use isr1 instead of isr0 interrupt in legacy irq
7 mode
8 X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 X-Patchwork-Id: 819592
10 Message-Id: <20170928125838.11887-5-thomas.petazzoni@free-electrons.com>
11 To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
12 Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
13 Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
14 <gregory.clement@free-electrons.com>,
15 Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
16 Yehuda Yitschak <yehuday@marvell.com>,
17 linux-arm-kernel@lists.infradead.org, Antoine Tenart
18 <antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
19 <miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
20 Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
21 Date: Thu, 28 Sep 2017 14:58:35 +0200
22 From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
23 List-Id: <linux-pci.vger.kernel.org>
24
25 From: Victor Gu <xigu@marvell.com>
26
27 The Aardvark has two interrupts sets:
28
29 - first set is bit[23:16] of PCIe ISR 0 register(RD0074840h)
30
31 - second set is bit[11:8] of PCIe ISR 1 register(RD0074848h)
32
33 Only one set should be used, while another set should be masked.
34
35 The second set, ISR1, is more advanced, the Legacy INT_X status bit is
36 asserted once Assert_INTX message is received, and de-asserted after
37 Deassert_INTX message is received. Therefore, it matches what the
38 driver is currently doing in the ->irq_mask() and ->irq_unmask()
39 functions. The ISR0 requires additional work to deassert the
40 interrupt, which the driver doesn't do currently.
41
42 This commit resolves a number of issues with legacy interrupts.
43
44 This is part of fixing bug
45 https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
46 reported as the user to be important to get a Intel 7260 mini-PCIe
47 WiFi card working.
48
49 Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
50 Signed-off-by: Victor Gu <xigu@marvell.com>
51 Reviewed-by: Evan Wang <xswang@marvell.com>
52 Reviewed-by: Nadav Haklai <nadavh@marvell.com>
53 [Thomas: tweak commit log.]
54 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
55 ---
56 drivers/pci/host/pci-aardvark.c | 41 ++++++++++++++++++++++++-----------------
57 1 file changed, 24 insertions(+), 17 deletions(-)
58
59 --- a/drivers/pci/host/pci-aardvark.c
60 +++ b/drivers/pci/host/pci-aardvark.c
61 @@ -105,7 +105,8 @@
62 #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C)
63 #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4)
64 #define PCIE_ISR1_FLUSH BIT(5)
65 -#define PCIE_ISR1_ALL_MASK GENMASK(5, 4)
66 +#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val))
67 +#define PCIE_ISR1_ALL_MASK GENMASK(11, 4)
68 #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50)
69 #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
70 #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
71 @@ -615,9 +616,9 @@ static void advk_pcie_irq_mask(struct ir
72 irq_hw_number_t hwirq = irqd_to_hwirq(d);
73 u32 mask;
74
75 - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
76 - mask |= PCIE_ISR0_INTX_ASSERT(hwirq);
77 - advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
78 + mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
79 + mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
80 + advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
81 }
82
83 static void advk_pcie_irq_unmask(struct irq_data *d)
84 @@ -626,9 +627,9 @@ static void advk_pcie_irq_unmask(struct
85 irq_hw_number_t hwirq = irqd_to_hwirq(d);
86 u32 mask;
87
88 - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
89 - mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq);
90 - advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
91 + mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
92 + mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
93 + advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
94 }
95
96 static int advk_pcie_irq_map(struct irq_domain *h,
97 @@ -771,29 +772,35 @@ static void advk_pcie_handle_msi(struct
98
99 static void advk_pcie_handle_int(struct advk_pcie *pcie)
100 {
101 - u32 val, mask, status;
102 + u32 isr0_val, isr0_mask, isr0_status;
103 + u32 isr1_val, isr1_mask, isr1_status;
104 int i, virq;
105
106 - val = advk_readl(pcie, PCIE_ISR0_REG);
107 - mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
108 - status = val & ((~mask) & PCIE_ISR0_ALL_MASK);
109 -
110 - if (!status) {
111 - advk_writel(pcie, val, PCIE_ISR0_REG);
112 + isr0_val = advk_readl(pcie, PCIE_ISR0_REG);
113 + isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
114 + isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK);
115 +
116 + isr1_val = advk_readl(pcie, PCIE_ISR1_REG);
117 + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
118 + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
119 +
120 + if (!isr0_status && !isr1_status) {
121 + advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
122 + advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
123 return;
124 }
125
126 /* Process MSI interrupts */
127 - if (status & PCIE_ISR0_MSI_INT_PENDING)
128 + if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
129 advk_pcie_handle_msi(pcie);
130
131 /* Process legacy interrupts */
132 for (i = 0; i < PCI_NUM_INTX; i++) {
133 - if (!(status & PCIE_ISR0_INTX_ASSERT(i)))
134 + if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i)))
135 continue;
136
137 - advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i),
138 - PCIE_ISR0_REG);
139 + advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
140 + PCIE_ISR1_REG);
141
142 virq = irq_find_mapping(pcie->irq_domain, i);
143 generic_handle_irq(virq);