aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-03-14 05:36:07 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-05-15 11:49:04 -0400
commit4c07c7dfa0f3575dc3276c544349fbf181381167 (patch)
tree4b39750ce1284ec0032b21508fa56a8201a7dea1 /arch
parent93ef85b5598ad2cc23f38d97ed565027b969c0aa (diff)
MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
The PCI Host Controller of the AR724x SoC has a built-in IRQ controller. The current code does not supports that, so the IRQ lines wired to this controller are not usable. This leads to failed 'request_irq' calls: ath9k 0000:00:00.0: request_irq failed ath9k: probe of 0000:00:00.0 failed with error -89 This patch adds support for the IRQ controller in order to make PCI IRQs work. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3496/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/ath79/pci.c3
-rw-r--r--arch/mips/include/asm/mach-ath79/pci.h4
-rw-r--r--arch/mips/pci/pci-ar724x.c118
3 files changed, 120 insertions, 5 deletions
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 72281fb5360f..14f981c295d2 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -10,6 +10,7 @@
10 10
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <asm/mach-ath79/ath79.h> 12#include <asm/mach-ath79/ath79.h>
13#include <asm/mach-ath79/irq.h>
13#include <asm/mach-ath79/pci.h> 14#include <asm/mach-ath79/pci.h>
14#include "pci.h" 15#include "pci.h"
15 16
@@ -50,7 +51,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
50int __init ath79_register_pci(void) 51int __init ath79_register_pci(void)
51{ 52{
52 if (soc_is_ar724x()) 53 if (soc_is_ar724x())
53 return ar724x_pcibios_init(); 54 return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
54 55
55 return -ENODEV; 56 return -ENODEV;
56} 57}
diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h
index 6d7a837e6055..2eb01815d54e 100644
--- a/arch/mips/include/asm/mach-ath79/pci.h
+++ b/arch/mips/include/asm/mach-ath79/pci.h
@@ -12,9 +12,9 @@
12#define __ASM_MACH_ATH79_PCI_H 12#define __ASM_MACH_ATH79_PCI_H
13 13
14#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) 14#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X)
15int ar724x_pcibios_init(void); 15int ar724x_pcibios_init(int irq);
16#else 16#else
17static inline int ar724x_pcibios_init(void) { return 0; } 17static inline int ar724x_pcibios_init(int irq) { return 0; }
18#endif 18#endif
19 19
20#endif /* __ASM_MACH_ATH79_PCI_H */ 20#endif /* __ASM_MACH_ATH79_PCI_H */
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 07b7e3071735..04f433a823da 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -8,19 +8,32 @@
8 * by the Free Software Foundation. 8 * by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/irq.h>
11#include <linux/pci.h> 12#include <linux/pci.h>
12#include <asm/mach-ath79/ath79.h> 13#include <asm/mach-ath79/ath79.h>
14#include <asm/mach-ath79/ar71xx_regs.h>
13#include <asm/mach-ath79/pci.h> 15#include <asm/mach-ath79/pci.h>
14 16
15#define AR724X_PCI_CFG_BASE 0x14000000 17#define AR724X_PCI_CFG_BASE 0x14000000
16#define AR724X_PCI_CFG_SIZE 0x1000 18#define AR724X_PCI_CFG_SIZE 0x1000
19#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000)
20#define AR724X_PCI_CTRL_SIZE 0x100
21
17#define AR724X_PCI_MEM_BASE 0x10000000 22#define AR724X_PCI_MEM_BASE 0x10000000
18#define AR724X_PCI_MEM_SIZE 0x08000000 23#define AR724X_PCI_MEM_SIZE 0x08000000
19 24
25#define AR724X_PCI_REG_INT_STATUS 0x4c
26#define AR724X_PCI_REG_INT_MASK 0x50
27
28#define AR724X_PCI_INT_DEV0 BIT(14)
29
30#define AR724X_PCI_IRQ_COUNT 1
31
20#define AR7240_BAR0_WAR_VALUE 0xffff 32#define AR7240_BAR0_WAR_VALUE 0xffff
21 33
22static DEFINE_SPINLOCK(ar724x_pci_lock); 34static DEFINE_SPINLOCK(ar724x_pci_lock);
23static void __iomem *ar724x_pci_devcfg_base; 35static void __iomem *ar724x_pci_devcfg_base;
36static void __iomem *ar724x_pci_ctrl_base;
24 37
25static u32 ar724x_pci_bar0_value; 38static u32 ar724x_pci_bar0_value;
26static bool ar724x_pci_bar0_is_cached; 39static bool ar724x_pci_bar0_is_cached;
@@ -164,14 +177,115 @@ static struct pci_controller ar724x_pci_controller = {
164 .mem_resource = &ar724x_mem_resource, 177 .mem_resource = &ar724x_mem_resource,
165}; 178};
166 179
167int __init ar724x_pcibios_init(void) 180static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
181{
182 void __iomem *base;
183 u32 pending;
184
185 base = ar724x_pci_ctrl_base;
186
187 pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
188 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
189
190 if (pending & AR724X_PCI_INT_DEV0)
191 generic_handle_irq(ATH79_PCI_IRQ(0));
192
193 else
194 spurious_interrupt();
195}
196
197static void ar724x_pci_irq_unmask(struct irq_data *d)
198{
199 void __iomem *base;
200 u32 t;
201
202 base = ar724x_pci_ctrl_base;
203
204 switch (d->irq) {
205 case ATH79_PCI_IRQ(0):
206 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
207 __raw_writel(t | AR724X_PCI_INT_DEV0,
208 base + AR724X_PCI_REG_INT_MASK);
209 /* flush write */
210 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
211 }
212}
213
214static void ar724x_pci_irq_mask(struct irq_data *d)
215{
216 void __iomem *base;
217 u32 t;
218
219 base = ar724x_pci_ctrl_base;
220
221 switch (d->irq) {
222 case ATH79_PCI_IRQ(0):
223 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
224 __raw_writel(t & ~AR724X_PCI_INT_DEV0,
225 base + AR724X_PCI_REG_INT_MASK);
226
227 /* flush write */
228 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
229
230 t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
231 __raw_writel(t | AR724X_PCI_INT_DEV0,
232 base + AR724X_PCI_REG_INT_STATUS);
233
234 /* flush write */
235 __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
236 }
237}
238
239static struct irq_chip ar724x_pci_irq_chip = {
240 .name = "AR724X PCI ",
241 .irq_mask = ar724x_pci_irq_mask,
242 .irq_unmask = ar724x_pci_irq_unmask,
243 .irq_mask_ack = ar724x_pci_irq_mask,
244};
245
246static void __init ar724x_pci_irq_init(int irq)
247{
248 void __iomem *base;
249 int i;
250
251 base = ar724x_pci_ctrl_base;
252
253 __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
254 __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
255
256 BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
257
258 for (i = ATH79_PCI_IRQ_BASE;
259 i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++)
260 irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
261 handle_level_irq);
262
263 irq_set_chained_handler(irq, ar724x_pci_irq_handler);
264}
265
266int __init ar724x_pcibios_init(int irq)
168{ 267{
268 int ret;
269
270 ret = -ENOMEM;
271
169 ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, 272 ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
170 AR724X_PCI_CFG_SIZE); 273 AR724X_PCI_CFG_SIZE);
171 if (ar724x_pci_devcfg_base == NULL) 274 if (ar724x_pci_devcfg_base == NULL)
172 return -ENOMEM; 275 goto err;
173 276
277 ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE,
278 AR724X_PCI_CTRL_SIZE);
279 if (ar724x_pci_ctrl_base == NULL)
280 goto err_unmap_devcfg;
281
282 ar724x_pci_irq_init(irq);
174 register_pci_controller(&ar724x_pci_controller); 283 register_pci_controller(&ar724x_pci_controller);
175 284
176 return PCIBIOS_SUCCESSFUL; 285 return PCIBIOS_SUCCESSFUL;
286
287err_unmap_devcfg:
288 iounmap(ar724x_pci_devcfg_base);
289err:
290 return ret;
177} 291}