X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fsibyte%2Fbcm1480%2Firq.c;h=2e8f6b2e2420e8c7eb485ec575b7f14bf085d77c;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=9cf7d713b13ccbaccf782db784cbe82f0c395167;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 9cf7d713b..2e8f6b2e2 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -15,7 +15,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include #include #include @@ -26,9 +25,9 @@ #include #include +#include #include #include -#include #include #include @@ -46,11 +45,9 @@ */ -#define shutdown_bcm1480_irq disable_bcm1480_irq 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 unsigned int startup_bcm1480_irq(unsigned int irq); static void ack_bcm1480_irq(unsigned int irq); #ifdef CONFIG_SMP static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask); @@ -84,13 +81,12 @@ extern char sb1250_duart_present[]; #endif #endif -static struct hw_interrupt_type bcm1480_irq_type = { +static struct irq_chip bcm1480_irq_type = { .typename = "BCM1480-IMR", - .startup = startup_bcm1480_irq, - .shutdown = shutdown_bcm1480_irq, - .enable = enable_bcm1480_irq, - .disable = disable_bcm1480_irq, .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 @@ -141,7 +137,7 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask) { int i = 0, old_cpu, cpu, int_on, k; u64 cur_ints; - irq_desc_t *desc = irq_desc + irq; + struct irq_desc *desc = irq_desc + irq; unsigned long flags; unsigned int irq_dirty; @@ -187,19 +183,8 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask) #endif -/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */ -extern void bcm1480_irq_handler(void); - /*****************************************************************************/ -static unsigned int startup_bcm1480_irq(unsigned int irq) -{ - bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); - - return 0; /* never anything pending */ -} - - static void disable_bcm1480_irq(unsigned int irq) { bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); @@ -274,22 +259,14 @@ void __init init_bcm1480_irqs(void) { int i; - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - if (i < BCM1480_NR_IRQS) { - irq_desc[i].handler = &bcm1480_irq_type; - bcm1480_irq_owner[i] = 0; - } else { - irq_desc[i].handler = &no_irq_type; - } + for (i = 0; i < BCM1480_NR_IRQS; i++) { + set_irq_chip(i, &bcm1480_irq_type); + bcm1480_irq_owner[i] = 0; } } -static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id) { return IRQ_NONE; } @@ -305,7 +282,7 @@ static struct irqaction bcm1480_dummy_action = { int bcm1480_steal_irq(int irq) { - irq_desc_t *desc = irq_desc + irq; + struct irq_desc *desc = irq_desc + irq; unsigned long flags; int retval = 0; @@ -422,7 +399,6 @@ void __init arch_init_irq(void) #endif /* Enable necessary IPs, disable the rest */ change_c0_status(ST0_IM, imask); - set_except_vector(0, bcm1480_irq_handler); #ifdef CONFIG_KGDB if (kgdb_flag) { @@ -458,7 +434,7 @@ void __init arch_init_irq(void) #define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) #define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) -void bcm1480_kgdb_interrupt(struct pt_regs *regs) +static void bcm1480_kgdb_interrupt(void) { /* * Clear break-change status (allow some time for the remote @@ -469,7 +445,65 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs) mdelay(500); duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT | M_DUART_RX_EN | M_DUART_TX_EN); - set_async_breakpoint(®s->cp0_epc); + set_async_breakpoint(&get_irq_regs()->cp0_epc); } #endif /* CONFIG_KGDB */ + +extern void bcm1480_timer_interrupt(void); +extern void bcm1480_mailbox_interrupt(void); + +asmlinkage void plat_irq_dispatch(void) +{ + 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) + bcm1480_timer_interrupt(); + +#ifdef CONFIG_SMP + else if (pending & CAUSEF_IP3) + bcm1480_mailbox_interrupt(); +#endif + +#ifdef CONFIG_KGDB + else if (pending & CAUSEF_IP6) + bcm1480_kgdb_interrupt(); /* KGDB (uart 1) */ +#endif + + else if (pending & CAUSEF_IP2) { + unsigned long long mask_h, mask_l; + unsigned long base; + + /* + * 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 to detect which CPU we're on, now that + * smp_affinity is supported. + */ + base = A_BCM1480_IMR_MAPPER(smp_processor_id()); + mask_h = __raw_readq( + IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H)); + mask_l = __raw_readq( + IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L)); + + if (mask_h) { + if (mask_h ^ 1) + do_IRQ(fls64(mask_h) - 1); + else + do_IRQ(63 + fls64(mask_l)); + } + } +}