aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2009-06-06 12:15:03 -0400
committerGrant Likely <grant.likely@secretlab.ca>2009-06-06 12:15:03 -0400
commit1745fbc744a934b235c2e5ecb5380079fa54be38 (patch)
tree6db68cba9637ca11448e127a32e0c92fdd2b635c /arch
parent64f16502475ddf663169369fffff6da9b10ea9fb (diff)
powerpc/virtex: refactor intc driver and add support for i8259 cascading
This patch refactors some of the xilinx_intc interrupt controller driver and adds support for cascading an i8259 off one of the irq lines. This patch was based on the ML510 support work done by Roderick Colenbrander. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index c658b413c9b4..90b57724a5e4 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -25,6 +25,7 @@
25#include <linux/of.h> 25#include <linux/of.h>
26#include <asm/io.h> 26#include <asm/io.h>
27#include <asm/processor.h> 27#include <asm/processor.h>
28#include <asm/i8259.h>
28#include <asm/irq.h> 29#include <asm/irq.h>
29 30
30/* 31/*
@@ -191,20 +192,14 @@ struct irq_host * __init
191xilinx_intc_init(struct device_node *np) 192xilinx_intc_init(struct device_node *np)
192{ 193{
193 struct irq_host * irq; 194 struct irq_host * irq;
194 struct resource res;
195 void * regs; 195 void * regs;
196 int rc;
197 196
198 /* Find and map the intc registers */ 197 /* Find and map the intc registers */
199 rc = of_address_to_resource(np, 0, &res); 198 regs = of_iomap(np, 0);
200 if (rc) { 199 if (!regs) {
201 printk(KERN_ERR __FILE__ ": of_address_to_resource() failed\n"); 200 pr_err("xilinx_intc: could not map registers\n");
202 return NULL; 201 return NULL;
203 } 202 }
204 regs = ioremap(res.start, 32);
205
206 printk(KERN_INFO "Xilinx intc at 0x%08llx mapped to 0x%p\n",
207 (unsigned long long) res.start, regs);
208 203
209 /* Setup interrupt controller */ 204 /* Setup interrupt controller */
210 out_be32(regs + XINTC_IER, 0); /* disable all irqs */ 205 out_be32(regs + XINTC_IER, 0); /* disable all irqs */
@@ -217,6 +212,7 @@ xilinx_intc_init(struct device_node *np)
217 if (!irq) 212 if (!irq)
218 panic(__FILE__ ": Cannot allocate IRQ host\n"); 213 panic(__FILE__ ": Cannot allocate IRQ host\n");
219 irq->host_data = regs; 214 irq->host_data = regs;
215
220 return irq; 216 return irq;
221} 217}
222 218
@@ -227,23 +223,65 @@ int xilinx_intc_get_irq(void)
227 return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR)); 223 return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
228} 224}
229 225
226#if defined(CONFIG_PPC_I8259)
227/*
228 * Support code for cascading to 8259 interrupt controllers
229 */
230static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
231{
232 unsigned int cascade_irq = i8259_irq();
233 if (cascade_irq)
234 generic_handle_irq(cascade_irq);
235
236 /* Let xilinx_intc end the interrupt */
237 desc->chip->ack(irq);
238 desc->chip->unmask(irq);
239}
240
241static void __init xilinx_i8259_setup_cascade(void)
242{
243 struct device_node *cascade_node;
244 int cascade_irq;
245
246 /* Initialize i8259 controller */
247 cascade_node = of_find_compatible_node(NULL, NULL, "chrp,iic");
248 if (!cascade_node)
249 return;
250
251 cascade_irq = irq_of_parse_and_map(cascade_node, 0);
252 if (!cascade_irq) {
253 pr_err("virtex_ml510: Failed to map cascade interrupt\n");
254 goto out;
255 }
256
257 i8259_init(cascade_node, 0);
258 set_irq_chained_handler(cascade_irq, xilinx_i8259_cascade);
259
260 out:
261 of_node_put(cascade_node);
262}
263#else
264static inline void xilinx_i8259_setup_cascade(void) { return; }
265#endif /* defined(CONFIG_PPC_I8259) */
266
267static struct of_device_id xilinx_intc_match[] __initconst = {
268 { .compatible = "xlnx,opb-intc-1.00.c", },
269 { .compatible = "xlnx,xps-intc-1.00.a", },
270 {}
271};
272
273/*
274 * Initialize master Xilinx interrupt controller
275 */
230void __init xilinx_intc_init_tree(void) 276void __init xilinx_intc_init_tree(void)
231{ 277{
232 struct device_node *np; 278 struct device_node *np;
233 279
234 /* find top level interrupt controller */ 280 /* find top level interrupt controller */
235 for_each_compatible_node(np, NULL, "xlnx,opb-intc-1.00.c") { 281 for_each_matching_node(np, xilinx_intc_match) {
236 if (!of_get_property(np, "interrupts", NULL)) 282 if (!of_get_property(np, "interrupts", NULL))
237 break; 283 break;
238 } 284 }
239 if (!np) {
240 for_each_compatible_node(np, NULL, "xlnx,xps-intc-1.00.a") {
241 if (!of_get_property(np, "interrupts", NULL))
242 break;
243 }
244 }
245
246 /* xilinx interrupt controller needs to be top level */
247 BUG_ON(!np); 285 BUG_ON(!np);
248 286
249 master_irqhost = xilinx_intc_init(np); 287 master_irqhost = xilinx_intc_init(np);
@@ -251,4 +289,6 @@ void __init xilinx_intc_init_tree(void)
251 289
252 irq_set_default_host(master_irqhost); 290 irq_set_default_host(master_irqhost);
253 of_node_put(np); 291 of_node_put(np);
292
293 xilinx_i8259_setup_cascade();
254} 294}