From: John Crispin Date: Sun, 14 Jul 2013 23:08:11 +0200 Subject: [PATCH 1/2] MIPS: use set_mode() to enable/disable the cevt-r4k irq Signed-off-by: John Crispin --- arch/mips/kernel/cevt-r4k.c | 43 +++++++++++++++++++++++++++++++++++++ drivers/clocksource/Kconfig | 5 +++++ 2 files changed, 48 insertions(+) --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -16,6 +16,31 @@ #include #include +#ifdef CONFIG_CEVT_SYSTICK_QUIRK +static int mips_state_oneshot(struct clock_event_device *evt) +{ + unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED; + if (!cp0_timer_irq_installed) { + cp0_timer_irq_installed = 1; + if (request_irq(evt->irq, c0_compare_interrupt, flags, "timer", + c0_compare_interrupt)) + pr_err("Failed to request irq %d (timer)\n", evt->irq); + } + + return 0; +} + +static int mips_state_shutdown(struct clock_event_device *evt) +{ + if (cp0_timer_irq_installed) { + cp0_timer_irq_installed = 0; + free_irq(evt->irq, NULL); + } + + return 0; +} +#endif + static int mips_next_event(unsigned long delta, struct clock_event_device *evt) { @@ -292,7 +317,9 @@ core_initcall(r4k_register_cpufreq_notif int r4k_clockevent_init(void) { +#ifndef CONFIG_CEVT_SYSTICK_QUIRK unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED; +#endif unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq, min_delta; @@ -303,6 +330,15 @@ int r4k_clockevent_init(void) if (!c0_compare_int_usable()) return -ENXIO; +#ifdef CONFIG_CEVT_SYSTICK_QUIRK + /* + * 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 its liking. + */ + irq = get_c0_compare_int(); +#endif + cd = &per_cpu(mips_clockevent_device, cpu); cd->name = "MIPS"; @@ -314,11 +350,17 @@ int r4k_clockevent_init(void) cd->rating = 300; cd->cpumask = cpumask_of(cpu); +#ifdef CONFIG_CEVT_SYSTICK_QUIRK + cd->irq = irq; + cd->set_state_shutdown = mips_state_shutdown; + cd->set_state_oneshot = mips_state_oneshot; +#endif cd->set_next_event = mips_next_event; cd->event_handler = mips_event_handler; clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); +#ifndef CONFIG_CEVT_SYSTICK_QUIRK if (cp0_timer_irq_installed) return 0; @@ -334,6 +376,7 @@ int r4k_clockevent_init(void) if (request_irq(irq, c0_compare_interrupt, flags, "timer", c0_compare_interrupt)) pr_err("Failed to request irq %d (timer)\n", irq); +#endif return 0; } --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -731,10 +731,15 @@ config GOLDFISH_TIMER depends on RTC_DRV_GOLDFISH help Support for the timer/counter of goldfish-rtc + +config CEVT_SYSTICK_QUIRK + bool + default n config RALINK_TIMER bool "Ralink System Tick Counter" depends on SOC_RT305X || SOC_MT7620 || COMPILE_TEST + select CEVT_SYSTICK_QUIRK select CLKSRC_MMIO select TIMER_OF help