777a078ef91022a452650de082ad4de88b533a12
[oweals/openwrt.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);