| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001
- From: Daniel Hellstrom <[email protected]>
- Date: Thu, 16 Sep 2010 11:12:41 +0200
- Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree.
- Signed-off-by: Daniel Hellstrom <[email protected]>
- ---
- arch/sparc/include/asm/irq_32.h | 4 ++++
- arch/sparc/kernel/irq_32.c | 32 ++++++++++++++++++++++++++------
- arch/sparc/kernel/leon_kernel.c | 8 +++++++-
- 3 files changed, 37 insertions(+), 7 deletions(-)
- --- a/arch/sparc/include/asm/irq_32.h
- +++ b/arch/sparc/include/asm/irq_32.h
- @@ -6,7 +6,11 @@
- #ifndef _SPARC_IRQ_H
- #define _SPARC_IRQ_H
-
- +#ifdef CONFIG_SPARC_LEON
- +#define NR_IRQS 32
- +#else
- #define NR_IRQS 16
- +#endif
-
- #include <linux/interrupt.h>
-
- --- a/arch/sparc/kernel/irq_32.c
- +++ b/arch/sparc/kernel/irq_32.c
- @@ -110,6 +110,11 @@ EXPORT_SYMBOL(__raw_local_irq_save);
- EXPORT_SYMBOL(raw_local_irq_enable);
- EXPORT_SYMBOL(raw_local_irq_restore);
-
- +#ifdef CONFIG_SPARC_LEON
- +extern unsigned int sparc_leon_eirq;
- +extern int sparc_leon_eirq_get(int eirq, int cpu);
- +#endif
- +
- /*
- * Dave Redman ([email protected])
- *
- @@ -222,10 +227,11 @@ void free_irq(unsigned int irq, void *de
- return;
- }
- cpu_irq = irq & (NR_IRQS - 1);
- - if (cpu_irq > 14) { /* 14 irq levels on the sparc */
- - printk("Trying to free bogus IRQ %d\n", irq);
- - return;
- - }
- + /* 14 irq levels on the sparc, however some LEON systems have 31 IRQs */
- + if ((cpu_irq == 15) || (cpu_irq >= NR_IRQS)) {
- + printk("Trying to free bogus IRQ %d\n", irq);
- + return;
- + }
-
- spin_lock_irqsave(&irq_action_lock, flags);
-
- @@ -303,7 +309,14 @@ void unexpected_irq(int irq, void *dev_i
- int i;
- struct irqaction * action;
- unsigned int cpu_irq;
- -
- +
- +#ifdef CONFIG_SPARC_LEON
- + /* LEON Extended IRQ requires one extra IRQ Number fetch stage */
- + if ( sparc_leon_eirq == irq ) {
- + irq = sparc_leon_eirq_get(irq, smp_processor_id());
- + }
- +#endif
- +
- cpu_irq = irq & (NR_IRQS - 1);
- action = sparc_irq[cpu_irq].action;
-
- @@ -330,6 +343,13 @@ void handler_irq(int irq, struct pt_regs
- extern void smp4m_irq_rotate(int cpu);
- #endif
-
- +#ifdef CONFIG_SPARC_LEON
- + /* LEON Extended IRQ requires one extra IRQ Number fetch stage */
- + if ( sparc_leon_eirq == irq ) {
- + irq = sparc_leon_eirq_get(irq, cpu);
- + }
- +#endif
- +
- old_regs = set_irq_regs(regs);
- irq_enter();
- disable_pil_irq(irq);
- @@ -526,7 +546,7 @@ int request_irq(unsigned int irq,
- return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
- }
- cpu_irq = irq & (NR_IRQS - 1);
- - if(cpu_irq > 14) {
- + if(cpu_irq == 15) {
- ret = -EINVAL;
- goto out;
- }
- --- a/arch/sparc/kernel/leon_kernel.c
- +++ b/arch/sparc/kernel/leon_kernel.c
- @@ -104,7 +104,7 @@ static void leon_disable_irq(unsigned in
-
- void __init leon_init_timers(irq_handler_t counter_fn)
- {
- - int irq;
- + int irq, eirq;
- struct device_node *rootnp, *np;
- struct property *pp;
- int len;
- @@ -153,6 +153,12 @@ void __init leon_init_timers(irq_handler
- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
- # endif
-
- + LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
- + eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf;
- + if ( eirq != 0 ) {
- + /* Extended IRQ controller available */
- + sparc_leon_eirq_register(eirq);
- + }
- } else {
- printk(KERN_ERR "No Timer/irqctrl found\n");
- BUG();
|