diff options
author | Noam Camus <noamc@ezchip.com> | 2016-01-01 10:18:49 (GMT) |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2016-05-09 04:02:28 (GMT) |
commit | eec3c58efa271d7dfa30c978dda2c88280212634 (patch) | |
tree | 028246d1987a60246134ebdee95da4d634445b4e /arch/arc | |
parent | 0eeb3dfe4b85aa7367e5e4efc365abbe4e50bbfa (diff) | |
download | linux-eec3c58efa271d7dfa30c978dda2c88280212634.tar.xz |
ARC: clockevent: switch to cpu notifier for clockevent setup
ARC Timers so far have been handled as "legacy" w/o explicit description
in DT. This poses challenge for newer platforms wanting to use them.
This series will eventually help move timers over to DT.
This patch does a small change of using a CPU notifier to set clockevent
on non-boot CPUs. So explicit setup is done only on boot CPU (which will
later be done by DT)
Signed-off-by: Noam Camus <noamc@ezchip.com>
[vgupta: broken off from a bigger patch]
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r-- | arch/arc/include/asm/irq.h | 1 | ||||
-rw-r--r-- | arch/arc/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/time.c | 62 |
3 files changed, 41 insertions, 24 deletions
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index f9c735e..5c0b5ab 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -25,6 +25,5 @@ #include <asm-generic/irq.h> extern void arc_init_IRQ(void); -void arc_local_timer_setup(void); #endif diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index ca83ebe..6b18134 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -138,8 +138,6 @@ void start_kernel_secondary(void) if (machine_desc->init_per_cpu) machine_desc->init_per_cpu(cpu); - arc_local_timer_setup(); - local_irq_enable(); preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 146da3c..e97be74 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -29,17 +29,14 @@ * which however is currently broken */ -#include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/sched.h> #include <linux/kernel.h> #include <linux/time.h> #include <linux/init.h> -#include <linux/timex.h> -#include <linux/profile.h> #include <linux/clocksource.h> #include <linux/clockchips.h> +#include <linux/cpu.h> #include <asm/irq.h> #include <asm/arcregs.h> #include <asm/clk.h> @@ -183,6 +180,8 @@ static struct clocksource arc_counter = { /********** Clock Event Device *********/ +static int arc_timer_irq = TIMER0_IRQ; + /* * Arm the timer to interrupt after @cycles * The distinction for oneshot/periodic is done in arc_event_timer_ack() below @@ -218,7 +217,6 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 300, - .irq = TIMER0_IRQ, /* hardwired, no need for resources */ .set_next_event = arc_clkevent_set_next_event, .set_state_periodic = arc_clkevent_set_periodic, }; @@ -244,29 +242,52 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static int arc_timer_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + + evt->cpumask = cpumask_of(smp_processor_id()); + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + clockevents_config_and_register(evt, arc_get_core_freq(), + 0, ULONG_MAX); + enable_percpu_irq(arc_timer_irq, 0); + break; + case CPU_DYING: + disable_percpu_irq(arc_timer_irq); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block arc_timer_cpu_nb = { + .notifier_call = arc_timer_cpu_notify, +}; + /* - * Setup the local event timer for @cpu + * clockevent setup for boot CPU */ -void arc_local_timer_setup() +static void __init arc_clockevent_setup(void) { struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); - int cpu = smp_processor_id(); - int irq = TIMER0_IRQ; + int ret; - evt->cpumask = cpumask_of(cpu); + register_cpu_notifier(&arc_timer_cpu_nb); + + evt->cpumask = cpumask_of(smp_processor_id()); clockevents_config_and_register(evt, arc_get_core_freq(), 0, ARC_TIMER_MAX); - if (!cpu) { - int rc; - - rc = request_percpu_irq(irq, timer_irq_handler, - "Timer0 (per-cpu-tick)", evt); - if (rc) - panic("Percpu IRQ request failed for TIMER\n"); - } + /* Needs apriori irq_set_percpu_devid() done in intc map function */ + ret = request_percpu_irq(arc_timer_irq, timer_irq_handler, + "Timer0 (per-cpu-tick)", evt); + if (ret) + pr_err("Unable to register interrupt\n"); - enable_percpu_irq(irq, 0); + enable_percpu_irq(arc_timer_irq, 0); } /* @@ -291,6 +312,5 @@ void __init time_init(void) */ clocksource_register_hz(&arc_counter, arc_get_core_freq()); - /* sets up the periodic event timer */ - arc_local_timer_setup(); + arc_clockevent_setup(); } |