Root/target/linux/ar71xx/patches-3.2/113-MIPS-ath79-add-PCI-IRQ-handling-code-for-AR724X-SoCs.patch

1From a4fbc2dec67a5d760e25e3c3a6c392191a5405c6 Mon Sep 17 00:00:00 2001
2From: Gabor Juhos <juhosg@openwrt.org>
3Date: Tue, 22 Nov 2011 14:11:19 +0100
4Subject: [PATCH 13/35] MIPS: ath79: add PCI IRQ handling code for AR724X SoCs
5
6The PCI Host Controller of the AR724x SoC has a
7built-in IRQ controller. The current code does
8not supports that, so the IRQ lines wired to this
9controller are not usable. This leads to failed
10'request_irq' calls:
11
12  ath9k 0000:00:00.0: request_irq failed
13  ath9k: probe of 0000:00:00.0 failed with error -89
14
15This patch adds support for the IRQ controller
16in order to make PCI IRQs work.
17
18Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
19
20v2: - move the interrupt controller related defines from
21      the workaround patch
22---
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(-)
27
28--- a/arch/mips/ath79/pci.c
29+++ b/arch/mips/ath79/pci.c
30@@ -10,6 +10,7 @@
31 
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>
36 #include "pci.h"
37 
38@@ -50,7 +51,7 @@ int pcibios_plat_dev_init(struct pci_dev
39 int __init ath79_register_pci(void)
40 {
41     if (soc_is_ar724x())
42- return ar724x_pcibios_init();
43+ return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
44 
45     return -ENODEV;
46 }
47--- a/arch/mips/include/asm/mach-ath79/pci.h
48+++ b/arch/mips/include/asm/mach-ath79/pci.h
49@@ -12,9 +12,9 @@
50 #define __ASM_MACH_ATH79_PCI_H
51 
52 #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X)
53-int ar724x_pcibios_init(void);
54+int ar724x_pcibios_init(int irq);
55 #else
56-static inline int ar724x_pcibios_init(void) { return 0 };
57+static inline int ar724x_pcibios_init(int irq) { return 0 };
58 #endif
59 
60 #endif /* __ASM_MACH_ATH79_PCI_H */
61--- a/arch/mips/pci/pci-ar724x.c
62+++ b/arch/mips/pci/pci-ar724x.c
63@@ -8,19 +8,32 @@
64  * by the Free Software Foundation.
65  */
66 
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>
72 
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
77+
78 #define AR724X_PCI_MEM_BASE 0x10000000
79 #define AR724X_PCI_MEM_SIZE 0x08000000
80 
81+#define AR724X_PCI_REG_INT_STATUS 0x4c
82+#define AR724X_PCI_REG_INT_MASK 0x50
83+
84+#define AR724X_PCI_INT_DEV0 BIT(14)
85+
86+#define AR724X_PCI_IRQ_COUNT 1
87+
88 #define AR7240_BAR0_WAR_VALUE 0xffff
89 
90 static DEFINE_SPINLOCK(ar724x_pci_lock);
91 static void __iomem *ar724x_pci_devcfg_base;
92+static void __iomem *ar724x_pci_ctrl_base;
93 
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,
98 };
99 
100-int __init ar724x_pcibios_init(void)
101+static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
102+{
103+ void __iomem *base;
104+ u32 pending;
105+
106+ base = ar724x_pci_ctrl_base;
107+
108+ pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
109+ __raw_readl(base + AR724X_PCI_REG_INT_MASK);
110+
111+ if (pending & AR724X_PCI_INT_DEV0)
112+ generic_handle_irq(ATH79_PCI_IRQ(0));
113+
114+ else
115+ spurious_interrupt();
116+}
117+
118+static void ar724x_pci_irq_unmask(struct irq_data *d)
119+{
120+ void __iomem *base;
121+ u32 t;
122+
123+ base = ar724x_pci_ctrl_base;
124+
125+ switch (d->irq) {
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);
130+ /* flush write */
131+ __raw_readl(base + AR724X_PCI_REG_INT_MASK);
132+ }
133+}
134+
135+static void ar724x_pci_irq_mask(struct irq_data *d)
136+{
137+ void __iomem *base;
138+ u32 t;
139+
140+ base = ar724x_pci_ctrl_base;
141+
142+ switch (d->irq) {
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);
147+
148+ /* flush write */
149+ __raw_readl(base + AR724X_PCI_REG_INT_MASK);
150+
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);
154+
155+ /* flush write */
156+ __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
157+ }
158+}
159+
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,
165+};
166+
167+static void __init ar724x_pci_irq_init(int irq)
168+{
169+ void __iomem *base;
170+ int i;
171+
172+ base = ar724x_pci_ctrl_base;
173+
174+ __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
175+ __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
176+
177+ BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
178+
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,
182+ handle_level_irq);
183+
184+ irq_set_chained_handler(irq, ar724x_pci_irq_handler);
185+}
186+
187+int __init ar724x_pcibios_init(int irq)
188 {
189+ int ret;
190+
191+ ret = -ENOMEM;
192+
193     ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
194                      AR724X_PCI_CFG_SIZE);
195     if (ar724x_pci_devcfg_base == NULL)
196- return -ENOMEM;
197+ goto err;
198 
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;
203+
204+ ar724x_pci_irq_init(irq);
205     register_pci_controller(&ar724x_pci_controller);
206 
207     return PCIBIOS_SUCCESSFUL;
208+
209+err_unmap_devcfg:
210+ iounmap(ar724x_pci_devcfg_base);
211+err:
212+ return ret;
213 }
214

Archive Download this file



interactive