diff options
author | Andrew Bresticker <abrestic@chromium.org> | 2014-10-20 15:04:04 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:45:16 -0500 |
commit | e4752dbbc300939e14029583ba2a0b235b147649 (patch) | |
tree | ce68c23d3a64c47b765ef7436ddc8a3e25dba4fa /drivers/clocksource/mips-gic-timer.c | |
parent | f7ea3060b60a8f32794aa094f9216b198083d232 (diff) |
clocksource: mips-gic: Use CPU notifiers to setup the timer
Instead of requiring an explicit call to gic_clockevent_init in the SMP
startup path, use CPU notifiers to register and enable the GIC timer on
CPU startup.
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Qais Yousef <qais.yousef@imgtec.com>
Cc: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/8139/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/clocksource/mips-gic-timer.c')
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 05bdfe1e3e03..3ce992bc574f 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c | |||
@@ -6,9 +6,11 @@ | |||
6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | #include <linux/clockchips.h> | 8 | #include <linux/clockchips.h> |
9 | #include <linux/cpu.h> | ||
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
10 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
11 | #include <linux/irqchip/mips-gic.h> | 12 | #include <linux/irqchip/mips-gic.h> |
13 | #include <linux/notifier.h> | ||
12 | #include <linux/percpu.h> | 14 | #include <linux/percpu.h> |
13 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
14 | #include <linux/time.h> | 16 | #include <linux/time.h> |
@@ -16,7 +18,7 @@ | |||
16 | #include <asm/time.h> | 18 | #include <asm/time.h> |
17 | 19 | ||
18 | static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); | 20 | static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); |
19 | static int gic_timer_irq_installed; | 21 | static int gic_timer_irq; |
20 | static unsigned int gic_frequency; | 22 | static unsigned int gic_frequency; |
21 | 23 | ||
22 | static int gic_next_event(unsigned long delta, struct clock_event_device *evt) | 24 | static int gic_next_event(unsigned long delta, struct clock_event_device *evt) |
@@ -53,18 +55,9 @@ struct irqaction gic_compare_irqaction = { | |||
53 | .name = "timer", | 55 | .name = "timer", |
54 | }; | 56 | }; |
55 | 57 | ||
56 | int gic_clockevent_init(void) | 58 | static void gic_clockevent_cpu_init(struct clock_event_device *cd) |
57 | { | 59 | { |
58 | unsigned int cpu = smp_processor_id(); | 60 | unsigned int cpu = smp_processor_id(); |
59 | struct clock_event_device *cd; | ||
60 | unsigned int irq; | ||
61 | |||
62 | if (!cpu_has_counter || !gic_frequency) | ||
63 | return -ENXIO; | ||
64 | |||
65 | irq = MIPS_GIC_IRQ_BASE + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); | ||
66 | |||
67 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
68 | 61 | ||
69 | cd->name = "MIPS GIC"; | 62 | cd->name = "MIPS GIC"; |
70 | cd->features = CLOCK_EVT_FEAT_ONESHOT | | 63 | cd->features = CLOCK_EVT_FEAT_ONESHOT | |
@@ -77,19 +70,52 @@ int gic_clockevent_init(void) | |||
77 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | 70 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); |
78 | 71 | ||
79 | cd->rating = 300; | 72 | cd->rating = 300; |
80 | cd->irq = irq; | 73 | cd->irq = gic_timer_irq; |
81 | cd->cpumask = cpumask_of(cpu); | 74 | cd->cpumask = cpumask_of(cpu); |
82 | cd->set_next_event = gic_next_event; | 75 | cd->set_next_event = gic_next_event; |
83 | cd->set_mode = gic_set_clock_mode; | 76 | cd->set_mode = gic_set_clock_mode; |
84 | 77 | ||
85 | clockevents_register_device(cd); | 78 | clockevents_register_device(cd); |
86 | 79 | ||
87 | if (!gic_timer_irq_installed) { | 80 | enable_percpu_irq(gic_timer_irq, IRQ_TYPE_NONE); |
88 | setup_percpu_irq(irq, &gic_compare_irqaction); | 81 | } |
89 | gic_timer_irq_installed = 1; | 82 | |
83 | static void gic_clockevent_cpu_exit(struct clock_event_device *cd) | ||
84 | { | ||
85 | disable_percpu_irq(gic_timer_irq); | ||
86 | } | ||
87 | |||
88 | static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action, | ||
89 | void *data) | ||
90 | { | ||
91 | switch (action & ~CPU_TASKS_FROZEN) { | ||
92 | case CPU_STARTING: | ||
93 | gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); | ||
94 | break; | ||
95 | case CPU_DYING: | ||
96 | gic_clockevent_cpu_exit(this_cpu_ptr(&gic_clockevent_device)); | ||
97 | break; | ||
90 | } | 98 | } |
91 | 99 | ||
92 | enable_percpu_irq(irq, IRQ_TYPE_NONE); | 100 | return NOTIFY_OK; |
101 | } | ||
102 | |||
103 | static struct notifier_block gic_cpu_nb = { | ||
104 | .notifier_call = gic_cpu_notifier, | ||
105 | }; | ||
106 | |||
107 | static int gic_clockevent_init(void) | ||
108 | { | ||
109 | if (!cpu_has_counter || !gic_frequency) | ||
110 | return -ENXIO; | ||
111 | |||
112 | gic_timer_irq = MIPS_GIC_IRQ_BASE + | ||
113 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); | ||
114 | setup_percpu_irq(gic_timer_irq, &gic_compare_irqaction); | ||
115 | |||
116 | register_cpu_notifier(&gic_cpu_nb); | ||
117 | |||
118 | gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); | ||
93 | 119 | ||
94 | return 0; | 120 | return 0; |
95 | } | 121 | } |
@@ -116,4 +142,6 @@ void __init gic_clocksource_init(unsigned int frequency) | |||
116 | gic_clocksource.rating = 200 + frequency / 10000000; | 142 | gic_clocksource.rating = 200 + frequency / 10000000; |
117 | 143 | ||
118 | clocksource_register_hz(&gic_clocksource, frequency); | 144 | clocksource_register_hz(&gic_clocksource, frequency); |
145 | |||
146 | gic_clockevent_init(); | ||
119 | } | 147 | } |