diff options
Diffstat (limited to 'arch/arc/kernel/time.c')
| -rw-r--r-- | arch/arc/kernel/time.c | 58 |
1 files changed, 26 insertions, 32 deletions
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 0e51e69cf30..36c2aa99436 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -63,9 +63,10 @@ int arc_counter_setup(void) { - /* RTSC insn taps into cpu clk, needs no setup */ - - /* For SMP, only allowed if cross-core-sync, hence usable as cs */ + /* + * For SMP this needs to be 0. However Kconfig glue doesn't + * enable this option for SMP configs + */ return 1; } @@ -154,22 +155,6 @@ static void arc_timer_event_setup(unsigned int limit) write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH); } -/* - * Acknowledge the interrupt (oneshot) and optionally re-arm it (periodic) - * -Any write to CTRL Reg will ack the intr (NH bit: Count when not halted) - * -Rearming is done by setting the IE bit - * - * Small optimisation: Normal code would have been - * if (irq_reenable) - * CTRL_REG = (IE | NH); - * else - * CTRL_REG = NH; - * However since IE is BIT0 we can fold the branch - */ -static void arc_timer_event_ack(unsigned int irq_reenable) -{ - write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH); -} static int arc_clkevent_set_next_event(unsigned long delta, struct clock_event_device *dev) @@ -206,10 +191,22 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { static irqreturn_t timer_irq_handler(int irq, void *dev_id) { - struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device); + /* + * Note that generic IRQ core could have passed @evt for @dev_id if + * irq_set_chip_and_handler() asked for handle_percpu_devid_irq() + */ + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + int irq_reenable = evt->mode == CLOCK_EVT_MODE_PERIODIC; + + /* + * Any write to CTRL reg ACks the interrupt, we rewrite the + * Count when [N]ot [H]alted bit. + * And re-arm it if perioid by [I]nterrupt [E]nable bit + */ + write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH); + + evt->event_handler(evt); - arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC); - clk->event_handler(clk); return IRQ_HANDLED; } @@ -221,18 +218,15 @@ static struct irqaction arc_timer_irq = { /* * Setup the local event timer for @cpu - * N.B. weak so that some exotic ARC SoCs can completely override it */ -void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu) +void arc_local_timer_setup() { - struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); - - clockevents_calc_mult_shift(clk, arc_get_core_freq(), 5); - - clk->max_delta_ns = clockevent_delta2ns(ARC_TIMER_MAX, clk); - clk->cpumask = cpumask_of(cpu); + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + int cpu = smp_processor_id(); - clockevents_register_device(clk); + evt->cpumask = cpumask_of(cpu); + clockevents_config_and_register(evt, arc_get_core_freq(), + 0, ARC_TIMER_MAX); /* * setup the per-cpu timer IRQ handler - for all cpus @@ -268,7 +262,7 @@ void __init time_init(void) clocksource_register_hz(&arc_counter, arc_get_core_freq()); /* sets up the periodic event timer */ - arc_local_timer_setup(smp_processor_id()); + arc_local_timer_setup(); if (machine_desc->init_time) machine_desc->init_time(); |
