aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/sb1250/irq.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-11 18:46:09 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-11 18:46:09 -0400
commit7bcf7717b6a047c272410d0cd00213185fe6b99d (patch)
tree81c5d6bbc2130815713e22bb5408ea80b6e1c499 /arch/mips/sibyte/sb1250/irq.c
parent91a2fcc88634663e9e13dcdfad0e4a860e64aeee (diff)
[MIPS] Implement clockevents for R4000-style cp0 count/compare interrupt
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sibyte/sb1250/irq.c')
-rw-r--r--arch/mips/sibyte/sb1250/irq.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index ad593a6c20b..6a4cc84194a 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -28,6 +28,7 @@
28#include <asm/errno.h> 28#include <asm/errno.h>
29#include <asm/signal.h> 29#include <asm/signal.h>
30#include <asm/system.h> 30#include <asm/system.h>
31#include <asm/time.h>
31#include <asm/io.h> 32#include <asm/io.h>
32 33
33#include <asm/sibyte/sb1250_regs.h> 34#include <asm/sibyte/sb1250_regs.h>
@@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void)
399 400
400#endif /* CONFIG_KGDB */ 401#endif /* CONFIG_KGDB */
401 402
402extern void sb1250_timer_interrupt(void); 403static inline void sb1250_timer_interrupt(void)
404{
405 int cpu = smp_processor_id();
406 int irq = K_INT_TIMER_0 + cpu;
407
408 irq_enter();
409 kstat_this_cpu.irqs[irq]++;
410
411 write_seqlock(&xtime_lock);
412
413 /* ACK interrupt */
414 ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
415 IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
416
417 /*
418 * call the generic timer interrupt handling
419 */
420 do_timer(1);
421
422 write_sequnlock(&xtime_lock);
423
424 /*
425 * In UP mode, we call local_timer_interrupt() to do profiling
426 * and process accouting.
427 *
428 * In SMP mode, local_timer_interrupt() is invoked by appropriate
429 * low-level local timer interrupt handler.
430 */
431 local_timer_interrupt(irq);
432
433 irq_exit();
434}
435
403extern void sb1250_mailbox_interrupt(void); 436extern void sb1250_mailbox_interrupt(void);
404 437
405asmlinkage void plat_irq_dispatch(void) 438asmlinkage void plat_irq_dispatch(void)
406{ 439{
407 unsigned int pending; 440 unsigned int pending;
408 441
409#ifdef CONFIG_SIBYTE_SB1250_PROF
410 /* Set compare to count to silence count/compare timer interrupts */
411 write_c0_compare(read_c0_count());
412#endif
413
414 /* 442 /*
415 * What a pain. We have to be really careful saving the upper 32 bits 443 * What a pain. We have to be really careful saving the upper 32 bits
416 * of any * register across function calls if we don't want them 444 * of any * register across function calls if we don't want them
@@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void)
423 451
424 pending = read_c0_cause() & read_c0_status() & ST0_IM; 452 pending = read_c0_cause() & read_c0_status() & ST0_IM;
425 453
426#ifdef CONFIG_SIBYTE_SB1250_PROF 454 if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */
427 if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ 455 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
428 sbprof_cpu_intr(); 456 else if (pending & CAUSEF_IP4)
429 else
430#endif
431
432 if (pending & CAUSEF_IP4)
433 sb1250_timer_interrupt(); 457 sb1250_timer_interrupt();
434 458
435#ifdef CONFIG_SMP 459#ifdef CONFIG_SMP