While there was a platform hook for setting the compare timer interrupt before, it was implemented in a somewhat arkward way, and no such hook existed for the performance counter interrupt. This change aims at a cleaner solution, by using the platform-supplied values right from the beginning instead of setting up the standard irq first, and then ignoring it. Signed-off-by: Thomas Koeller <thomas.koeller@xxxxxxxxxxxxx> diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 24a2d90..3b1407e 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -9,6 +9,7 @@ #include <linux/clockchips.h> #include <linux/interrupt.h> #include <linux/percpu.h> +#include <linux/kernel.h> #include <asm/smtc_ipi.h> #include <asm/time.h> @@ -76,8 +77,8 @@ static irqreturn_t c0_compare_interrupt(int irq, void *dev_id) { const int r2 = cpu_has_mips_r2; struct clock_event_device *cd; - int cpu = smp_processor_id(); - + const int cpu = smp_processor_id(); + /* * Suckage alert: * Before R2 of the architecture there was no way to see if a @@ -169,9 +170,6 @@ static void mips_event_handler(struct clock_event_device *dev) { } -/* - * FIXME: This doesn't hold for the relocated E9000 compare interrupt. - */ static int c0_compare_int_pending(void) { return (read_c0_cause() >> cp0_compare_irq) & 0x100; @@ -183,7 +181,8 @@ static int c0_compare_int_usable(void) unsigned int cnt; /* - * IP7 already pending? Try to clear it by acking the timer. + * Compare interrupt already pending? + * Try to clear it by acking the timer. */ if (c0_compare_int_pending()) { write_c0_compare(read_c0_count()); @@ -221,8 +220,8 @@ static int c0_compare_int_usable(void) int __cpuinit mips_clockevent_init(void) { - uint64_t mips_freq = mips_hpt_frequency; - unsigned int cpu = smp_processor_id(); + const uint64_t mips_freq = mips_hpt_frequency; + const unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq; @@ -240,17 +239,12 @@ int __cpuinit mips_clockevent_init(void) return 0; #endif - if (!c0_compare_int_usable()) + if (!c0_compare_int_usable()) { + pr_crit("MIPS compare interrupt not working - no timer clock\n"); return -ENXIO; + } - /* - * With vectored interrupts things are getting platform specific. - * get_c0_compare_int is a hook to allow a platform to return the - * interrupt number of it's liking. - */ irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; - if (get_c0_compare_int) - irq = get_c0_compare_int(); cd = &per_cpu(mips_clockevent_device, cpu); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fcae667..268247d 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1281,6 +1281,20 @@ extern void flush_tlb_handlers(void); */ int cp0_compare_irq; +unsigned int __init __weak +get_c0_compare_int(void) +{ + return cpu_has_mips_r2 ? + (read_c0_intctl() >> 29) & 7 : CP0_LEGACY_COMPARE_IRQ; +} + +unsigned int __init __weak +get_c0_perfcount_int(void) +{ + return cpu_has_mips_r2 ? + (read_c0_intctl() >> 26) & 7 : -1; +} + /* * Performance counter IRQ or -1 if shared with timer */ @@ -1352,21 +1366,11 @@ void __init per_cpu_trap_init(void) set_c0_cause(CAUSEF_IV); } - /* - * Before R2 both interrupt numbers were fixed to 7, so on R2 only: - * - * o read IntCtl.IPTI to determine the timer interrupt - * o read IntCtl.IPPCI to determine the performance counter interrupt - */ - if (cpu_has_mips_r2) { - cp0_compare_irq = (read_c0_intctl() >> 29) & 7; - cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7; - if (cp0_perfcount_irq == cp0_compare_irq) - cp0_perfcount_irq = -1; - } else { - cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; + /* Set up timer & performance counter interrupts */ + cp0_compare_irq = get_c0_compare_int(); + cp0_perfcount_irq = get_c0_perfcount_int(); + if (cp0_perfcount_irq == cp0_compare_irq) cp0_perfcount_irq = -1; - } #ifdef CONFIG_MIPS_MT_SMTC } diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 7717934..be0d157 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -59,7 +59,8 @@ extern int (*perf_irq)(void); */ #ifdef CONFIG_CEVT_R4K extern int mips_clockevent_init(void); -extern unsigned int __weak get_c0_compare_int(void); +extern unsigned int get_c0_compare_int(void); +extern unsigned int get_c0_perfcount_int(void); #else static inline int mips_clockevent_init(void) { -- 1.5.3.6