diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-10-11 23:46:09 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-10-11 23:46:09 +0100 |
commit | 7bcf7717b6a047c272410d0cd00213185fe6b99d (patch) | |
tree | 81c5d6bbc2130815713e22bb5408ea80b6e1c499 /arch/mips/sibyte/sb1250/irq.c | |
parent | 91a2fcc88634663e9e13dcdfad0e4a860e64aeee (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.c | 50 |
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 @@ #include <asm/errno.h> #include <asm/signal.h> #include <asm/system.h> +#include <asm/time.h> #include <asm/io.h> #include <asm/sibyte/sb1250_regs.h> @@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void) #endif /* CONFIG_KGDB */ -extern void sb1250_timer_interrupt(void); +static inline void sb1250_timer_interrupt(void) +{ + int cpu = smp_processor_id(); + int irq = K_INT_TIMER_0 + cpu; + + irq_enter(); + kstat_this_cpu.irqs[irq]++; + + write_seqlock(&xtime_lock); + + /* ACK interrupt */ + ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, + IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); + + /* + * call the generic timer interrupt handling + */ + do_timer(1); + + write_sequnlock(&xtime_lock); + + /* + * In UP mode, we call local_timer_interrupt() to do profiling + * and process accouting. + * + * In SMP mode, local_timer_interrupt() is invoked by appropriate + * low-level local timer interrupt handler. + */ + local_timer_interrupt(irq); + + irq_exit(); +} + extern void sb1250_mailbox_interrupt(void); asmlinkage void plat_irq_dispatch(void) { unsigned int pending; -#ifdef CONFIG_SIBYTE_SB1250_PROF - /* Set compare to count to silence count/compare timer interrupts */ - write_c0_compare(read_c0_count()); -#endif - /* * What a pain. We have to be really careful saving the upper 32 bits * of any * register across function calls if we don't want them @@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void) pending = read_c0_cause() & read_c0_status() & ST0_IM; -#ifdef CONFIG_SIBYTE_SB1250_PROF - if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ - sbprof_cpu_intr(); - else -#endif - - if (pending & CAUSEF_IP4) + if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */ + do_IRQ(MIPS_CPU_IRQ_BASE + 7); + else if (pending & CAUSEF_IP4) sb1250_timer_interrupt(); #ifdef CONFIG_SMP |