1 From a4fbc2dec67a5d760e25e3c3a6c392191a5405c6 Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Tue, 22 Nov 2011 14:11:19 +0100
4 Subject: [PATCH 13/35] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
6 The PCI Host Controller of the AR724x SoC has a
7 built-in IRQ controller. The current code does
8 not supports that, so the IRQ lines wired to this
9 controller are not usable. This leads to failed
12 ath9k 0000:00:00.0: request_irq failed
13 ath9k: probe of 0000:00:00.0 failed with error -89
15 This patch adds support for the IRQ controller
16 in order to make PCI IRQs work.
18 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
20 v2: - move the interrupt controller related defines from
23 arch/mips/ath79/pci.c | 3 +-
24 arch/mips/include/asm/mach-ath79/pci.h | 4 +-
25 arch/mips/pci/pci-ar724x.c | 118 +++++++++++++++++++++++++++++++-
26 3 files changed, 120 insertions(+), 5 deletions(-)
28 --- a/arch/mips/ath79/pci.c
29 +++ b/arch/mips/ath79/pci.c
32 #include <linux/pci.h>
33 #include <asm/mach-ath79/ath79.h>
34 +#include <asm/mach-ath79/irq.h>
35 #include <asm/mach-ath79/pci.h>
38 @@ -50,7 +51,7 @@ int pcibios_plat_dev_init(struct pci_dev
39 int __init ath79_register_pci(void)
42 - return ar724x_pcibios_init();
43 + return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
47 --- a/arch/mips/include/asm/mach-ath79/pci.h
48 +++ b/arch/mips/include/asm/mach-ath79/pci.h
50 #define __ASM_MACH_ATH79_PCI_H
52 #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X)
53 -int ar724x_pcibios_init(void);
54 +int ar724x_pcibios_init(int irq);
56 -static inline int ar724x_pcibios_init(void) { return 0 };
57 +static inline int ar724x_pcibios_init(int irq) { return 0 };
60 #endif /* __ASM_MACH_ATH79_PCI_H */
61 --- a/arch/mips/pci/pci-ar724x.c
62 +++ b/arch/mips/pci/pci-ar724x.c
64 * by the Free Software Foundation.
67 +#include <linux/irq.h>
68 #include <linux/pci.h>
69 #include <asm/mach-ath79/ath79.h>
70 +#include <asm/mach-ath79/ar71xx_regs.h>
71 #include <asm/mach-ath79/pci.h>
73 #define AR724X_PCI_CFG_BASE 0x14000000
74 #define AR724X_PCI_CFG_SIZE 0x1000
75 +#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000)
76 +#define AR724X_PCI_CTRL_SIZE 0x100
78 #define AR724X_PCI_MEM_BASE 0x10000000
79 #define AR724X_PCI_MEM_SIZE 0x08000000
81 +#define AR724X_PCI_REG_INT_STATUS 0x4c
82 +#define AR724X_PCI_REG_INT_MASK 0x50
84 +#define AR724X_PCI_INT_DEV0 BIT(14)
86 +#define AR724X_PCI_IRQ_COUNT 1
88 #define AR7240_BAR0_WAR_VALUE 0xffff
90 static DEFINE_SPINLOCK(ar724x_pci_lock);
91 static void __iomem *ar724x_pci_devcfg_base;
92 +static void __iomem *ar724x_pci_ctrl_base;
94 static u32 ar724x_pci_bar0_value;
95 static bool ar724x_pci_bar0_is_cached;
96 @@ -164,14 +177,115 @@ static struct pci_controller ar724x_pci_
97 .mem_resource = &ar724x_mem_resource,
100 -int __init ar724x_pcibios_init(void)
101 +static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
103 + void __iomem *base;
106 + base = ar724x_pci_ctrl_base;
108 + pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
109 + __raw_readl(base + AR724X_PCI_REG_INT_MASK);
111 + if (pending & AR724X_PCI_INT_DEV0)
112 + generic_handle_irq(ATH79_PCI_IRQ(0));
115 + spurious_interrupt();
118 +static void ar724x_pci_irq_unmask(struct irq_data *d)
120 + void __iomem *base;
123 + base = ar724x_pci_ctrl_base;
126 + case ATH79_PCI_IRQ(0):
127 + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
128 + __raw_writel(t | AR724X_PCI_INT_DEV0,
129 + base + AR724X_PCI_REG_INT_MASK);
131 + __raw_readl(base + AR724X_PCI_REG_INT_MASK);
135 +static void ar724x_pci_irq_mask(struct irq_data *d)
137 + void __iomem *base;
140 + base = ar724x_pci_ctrl_base;
143 + case ATH79_PCI_IRQ(0):
144 + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
145 + __raw_writel(t & ~AR724X_PCI_INT_DEV0,
146 + base + AR724X_PCI_REG_INT_MASK);
149 + __raw_readl(base + AR724X_PCI_REG_INT_MASK);
151 + t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
152 + __raw_writel(t | AR724X_PCI_INT_DEV0,
153 + base + AR724X_PCI_REG_INT_STATUS);
156 + __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
160 +static struct irq_chip ar724x_pci_irq_chip = {
161 + .name = "AR724X PCI ",
162 + .irq_mask = ar724x_pci_irq_mask,
163 + .irq_unmask = ar724x_pci_irq_unmask,
164 + .irq_mask_ack = ar724x_pci_irq_mask,
167 +static void __init ar724x_pci_irq_init(int irq)
169 + void __iomem *base;
172 + base = ar724x_pci_ctrl_base;
174 + __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
175 + __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
177 + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
179 + for (i = ATH79_PCI_IRQ_BASE;
180 + i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++)
181 + irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
184 + irq_set_chained_handler(irq, ar724x_pci_irq_handler);
187 +int __init ar724x_pcibios_init(int irq)
193 ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
194 AR724X_PCI_CFG_SIZE);
195 if (ar724x_pci_devcfg_base == NULL)
199 + ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE,
200 + AR724X_PCI_CTRL_SIZE);
201 + if (ar724x_pci_ctrl_base == NULL)
202 + goto err_unmap_devcfg;
204 + ar724x_pci_irq_init(irq);
205 register_pci_controller(&ar724x_pci_controller);
207 return PCIBIOS_SUCCESSFUL;
210 + iounmap(ar724x_pci_devcfg_base);