aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/bcm1480/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sibyte/bcm1480/irq.c')
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 9cf7d713b13c..e61760b14d99 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -187,9 +187,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
187#endif 187#endif
188 188
189 189
190/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
191extern void bcm1480_irq_handler(void);
192
193/*****************************************************************************/ 190/*****************************************************************************/
194 191
195static unsigned int startup_bcm1480_irq(unsigned int irq) 192static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@ void __init arch_init_irq(void)
422#endif 419#endif
423 /* Enable necessary IPs, disable the rest */ 420 /* Enable necessary IPs, disable the rest */
424 change_c0_status(ST0_IM, imask); 421 change_c0_status(ST0_IM, imask);
425 set_except_vector(0, bcm1480_irq_handler);
426 422
427#ifdef CONFIG_KGDB 423#ifdef CONFIG_KGDB
428 if (kgdb_flag) { 424 if (kgdb_flag) {
@@ -473,3 +469,76 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
473} 469}
474 470
475#endif /* CONFIG_KGDB */ 471#endif /* CONFIG_KGDB */
472
473static inline int dclz(unsigned long long x)
474{
475 int lz;
476
477 __asm__ (
478 " .set push \n"
479 " .set mips64 \n"
480 " dclz %0, %1 \n"
481 " .set pop \n"
482 : "=r" (lz)
483 : "r" (x));
484
485 return lz;
486}
487
488extern void bcm1480_timer_interrupt(struct pt_regs *regs);
489extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
490extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
491
492asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
493{
494 unsigned int pending;
495
496#ifdef CONFIG_SIBYTE_BCM1480_PROF
497 /* Set compare to count to silence count/compare timer interrupts */
498 write_c0_compare(read_c0_count());
499#endif
500
501 pending = read_c0_cause();
502
503#ifdef CONFIG_SIBYTE_BCM1480_PROF
504 if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
505 sbprof_cpu_intr(exception_epc(regs));
506#endif
507
508 if (pending & CAUSEF_IP4)
509 bcm1480_timer_interrupt(regs);
510
511#ifdef CONFIG_SMP
512 if (pending & CAUSEF_IP3)
513 bcm1480_mailbox_interrupt(regs);
514#endif
515
516#ifdef CONFIG_KGDB
517 if (pending & CAUSEF_IP6)
518 bcm1480_kgdb_interrupt(regs); /* KGDB (uart 1) */
519#endif
520
521 if (pending & CAUSEF_IP2) {
522 unsigned long long mask_h, mask_l;
523 unsigned long base;
524
525 /*
526 * Default...we've hit an IP[2] interrupt, which means we've
527 * got to check the 1480 interrupt registers to figure out what
528 * to do. Need to detect which CPU we're on, now that
529 * smp_affinity is supported.
530 */
531 base = A_BCM1480_IMR_MAPPER(smp_processor_id());
532 mask_h = __raw_readq(
533 IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
534 mask_l = __raw_readq(
535 IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
536
537 if (!mask_h) {
538 if (mask_h ^ 1)
539 do_IRQ(63 - dclz(mask_h), regs);
540 else
541 do_IRQ(127 - dclz(mask_l), regs);
542 }
543 }
544}