diff options
Diffstat (limited to 'arch/mips/sibyte/bcm1480/irq.c')
| -rw-r--r-- | arch/mips/sibyte/bcm1480/irq.c | 107 |
1 files changed, 38 insertions, 69 deletions
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 12b465d404d..373fbbc8425 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -19,15 +19,14 @@ #include <linux/init.h> #include <linux/linkage.h> #include <linux/interrupt.h> +#include <linux/smp.h> #include <linux/spinlock.h> #include <linux/mm.h> -#include <linux/slab.h> #include <linux/kernel_stat.h> #include <asm/errno.h> #include <asm/irq_regs.h> #include <asm/signal.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/sibyte/bcm1480_regs.h> @@ -44,42 +43,21 @@ * for interrupt lines */ - -static void end_bcm1480_irq(unsigned int irq); -static void enable_bcm1480_irq(unsigned int irq); -static void disable_bcm1480_irq(unsigned int irq); -static void ack_bcm1480_irq(unsigned int irq); -#ifdef CONFIG_SMP -static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask); -#endif - #ifdef CONFIG_PCI extern unsigned long ht_eoi_space; #endif -static struct irq_chip bcm1480_irq_type = { - .name = "BCM1480-IMR", - .ack = ack_bcm1480_irq, - .mask = disable_bcm1480_irq, - .mask_ack = ack_bcm1480_irq, - .unmask = enable_bcm1480_irq, - .end = end_bcm1480_irq, -#ifdef CONFIG_SMP - .set_affinity = bcm1480_set_affinity -#endif -}; - /* Store the CPU id (not the logical number) */ int bcm1480_irq_owner[BCM1480_NR_IRQS]; -DEFINE_SPINLOCK(bcm1480_imr_lock); +static DEFINE_RAW_SPINLOCK(bcm1480_imr_lock); void bcm1480_mask_irq(int cpu, int irq) { unsigned long flags, hl_spacing; u64 cur_ints; - spin_lock_irqsave(&bcm1480_imr_lock, flags); + raw_spin_lock_irqsave(&bcm1480_imr_lock, flags); hl_spacing = 0; if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) { hl_spacing = BCM1480_IMR_HL_SPACING; @@ -88,7 +66,7 @@ void bcm1480_mask_irq(int cpu, int irq) cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing)); cur_ints |= (((u64) 1) << irq); ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing)); - spin_unlock_irqrestore(&bcm1480_imr_lock, flags); + raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags); } void bcm1480_unmask_irq(int cpu, int irq) @@ -96,7 +74,7 @@ void bcm1480_unmask_irq(int cpu, int irq) unsigned long flags, hl_spacing; u64 cur_ints; - spin_lock_irqsave(&bcm1480_imr_lock, flags); + raw_spin_lock_irqsave(&bcm1480_imr_lock, flags); hl_spacing = 0; if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) { hl_spacing = BCM1480_IMR_HL_SPACING; @@ -105,30 +83,25 @@ void bcm1480_unmask_irq(int cpu, int irq) cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing)); cur_ints &= ~(((u64) 1) << irq); ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing)); - spin_unlock_irqrestore(&bcm1480_imr_lock, flags); + raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags); } #ifdef CONFIG_SMP -static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask) +static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask, + bool force) { + unsigned int irq_dirty, irq = d->irq; int i = 0, old_cpu, cpu, int_on, k; u64 cur_ints; - struct irq_desc *desc = irq_desc + irq; unsigned long flags; - unsigned int irq_dirty; - if (cpumask_weight(mask) != 1) { - printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq); - return; - } - i = cpumask_first(mask); + i = cpumask_first_and(mask, cpu_online_mask); /* Convert logical CPU to physical CPU */ cpu = cpu_logical_map(i); /* Protect against other affinity changers and IMR manipulation */ - spin_lock_irqsave(&desc->lock, flags); - spin_lock(&bcm1480_imr_lock); + raw_spin_lock_irqsave(&bcm1480_imr_lock, flags); /* Swizzle each CPU's IMR (but leave the IP selection alone) */ old_cpu = bcm1480_irq_owner[irq]; @@ -153,29 +126,34 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask) ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING))); } } - spin_unlock(&bcm1480_imr_lock); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags); + + return 0; } #endif /*****************************************************************************/ -static void disable_bcm1480_irq(unsigned int irq) +static void disable_bcm1480_irq(struct irq_data *d) { + unsigned int irq = d->irq; + bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); } -static void enable_bcm1480_irq(unsigned int irq) +static void enable_bcm1480_irq(struct irq_data *d) { + unsigned int irq = d->irq; + bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); } -static void ack_bcm1480_irq(unsigned int irq) +static void ack_bcm1480_irq(struct irq_data *d) { + unsigned int irq_dirty, irq = d->irq; u64 pending; - unsigned int irq_dirty; int k; /* @@ -222,21 +200,23 @@ static void ack_bcm1480_irq(unsigned int irq) bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); } - -static void end_bcm1480_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); - } -} - +static struct irq_chip bcm1480_irq_type = { + .name = "BCM1480-IMR", + .irq_mask_ack = ack_bcm1480_irq, + .irq_mask = disable_bcm1480_irq, + .irq_unmask = enable_bcm1480_irq, +#ifdef CONFIG_SMP + .irq_set_affinity = bcm1480_set_affinity +#endif +}; void __init init_bcm1480_irqs(void) { int i; for (i = 0; i < BCM1480_NR_IRQS; i++) { - set_irq_chip(i, &bcm1480_irq_type); + irq_set_chip_and_handler(i, &bcm1480_irq_type, + handle_level_irq); bcm1480_irq_owner[i] = 0; } } @@ -258,7 +238,7 @@ void __init init_bcm1480_irqs(void) * On the second cpu, everything is set to IP5, which is * ignored, EXCEPT the mailbox interrupt. That one is * set to IP[2] so it is handled. This is needed so we - * can do cross-cpu function calls, as requred by SMP + * can do cross-cpu function calls, as required by SMP */ #define IMR_IP2_VAL K_BCM1480_INT_MAP_I0 @@ -303,10 +283,10 @@ void __init arch_init_irq(void) for (cpu = 0; cpu < 4; cpu++) { __raw_writeq(IMR_IP3_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (K_BCM1480_INT_MBOX_0_0 << 3))); - } + } - /* Clear the mailboxes. The firmware may leave them dirty */ + /* Clear the mailboxes. The firmware may leave them dirty */ for (cpu = 0; cpu < 4; cpu++) { __raw_writeq(0xffffffffffffffffULL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_0_CLR_CPU))); @@ -327,7 +307,7 @@ void __init arch_init_irq(void) /* * Note that the timer interrupts are also mapped, but this is - * done in bcm1480_time_init(). Also, the profiling driver + * done in bcm1480_time_init(). Also, the profiling driver * does its own management of IP7. */ @@ -345,7 +325,7 @@ static inline void dispatch_ip2(void) /* * Default...we've hit an IP[2] interrupt, which means we've got to - * check the 1480 interrupt registers to figure out what to do. Need + * check the 1480 interrupt registers to figure out what to do. Need * to detect which CPU we're on, now that smp_affinity is supported. */ base = A_BCM1480_IMR_MAPPER(cpu); @@ -367,19 +347,8 @@ asmlinkage void plat_irq_dispatch(void) unsigned int cpu = smp_processor_id(); unsigned int pending; -#ifdef CONFIG_SIBYTE_BCM1480_PROF - /* Set compare to count to silence count/compare timer interrupts */ - write_c0_compare(read_c0_count()); -#endif - pending = read_c0_cause() & read_c0_status(); -#ifdef CONFIG_SIBYTE_BCM1480_PROF - if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ - sbprof_cpu_intr(); - else -#endif - if (pending & CAUSEF_IP4) do_IRQ(K_BCM1480_INT_TIMER_0 + cpu); #ifdef CONFIG_SMP |
