diff options
author | Andrew Bresticker <abrestic@chromium.org> | 2014-10-20 15:03:59 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:45:15 -0500 |
commit | a331ce63c85080f554e0a19fc4189a520c65267b (patch) | |
tree | be84ac9416e957f7d601337f0f17bf327aebf80c /drivers/clocksource | |
parent | fa5635a277171021d364f6a3fab4addce8f358d2 (diff) |
clocksource: mips-gic: Combine with GIC clockevent driver
Combine the GIC clocksource driver with the GIC clockevent driver from
arch/mips/kernel/cevt-gic.c and remove the clockevent driver's separate
Kconfig symbol.
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: Andrew Bresticker <abrestic@chromium.org>
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/8132/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 0bf28e6aca7a..3cf5912c4054 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c | |||
@@ -5,10 +5,100 @@ | |||
5 | * | 5 | * |
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/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/interrupt.h> | ||
9 | #include <linux/irqchip/mips-gic.h> | 11 | #include <linux/irqchip/mips-gic.h> |
12 | #include <linux/percpu.h> | ||
13 | #include <linux/smp.h> | ||
10 | #include <linux/time.h> | 14 | #include <linux/time.h> |
11 | 15 | ||
16 | #include <asm/time.h> | ||
17 | |||
18 | DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); | ||
19 | int gic_timer_irq_installed; | ||
20 | |||
21 | static int gic_next_event(unsigned long delta, struct clock_event_device *evt) | ||
22 | { | ||
23 | u64 cnt; | ||
24 | int res; | ||
25 | |||
26 | cnt = gic_read_count(); | ||
27 | cnt += (u64)delta; | ||
28 | gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask)); | ||
29 | res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; | ||
30 | return res; | ||
31 | } | ||
32 | |||
33 | void gic_set_clock_mode(enum clock_event_mode mode, | ||
34 | struct clock_event_device *evt) | ||
35 | { | ||
36 | /* Nothing to do ... */ | ||
37 | } | ||
38 | |||
39 | irqreturn_t gic_compare_interrupt(int irq, void *dev_id) | ||
40 | { | ||
41 | struct clock_event_device *cd; | ||
42 | int cpu = smp_processor_id(); | ||
43 | |||
44 | gic_write_compare(gic_read_compare()); | ||
45 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
46 | cd->event_handler(cd); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | struct irqaction gic_compare_irqaction = { | ||
51 | .handler = gic_compare_interrupt, | ||
52 | .flags = IRQF_PERCPU | IRQF_TIMER, | ||
53 | .name = "timer", | ||
54 | }; | ||
55 | |||
56 | void gic_event_handler(struct clock_event_device *dev) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | int gic_clockevent_init(void) | ||
61 | { | ||
62 | unsigned int cpu = smp_processor_id(); | ||
63 | struct clock_event_device *cd; | ||
64 | unsigned int irq; | ||
65 | |||
66 | if (!cpu_has_counter || !gic_frequency) | ||
67 | return -ENXIO; | ||
68 | |||
69 | irq = MIPS_GIC_IRQ_BASE + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); | ||
70 | |||
71 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
72 | |||
73 | cd->name = "MIPS GIC"; | ||
74 | cd->features = CLOCK_EVT_FEAT_ONESHOT | | ||
75 | CLOCK_EVT_FEAT_C3STOP; | ||
76 | |||
77 | clockevent_set_clock(cd, gic_frequency); | ||
78 | |||
79 | /* Calculate the min / max delta */ | ||
80 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
81 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
82 | |||
83 | cd->rating = 300; | ||
84 | cd->irq = irq; | ||
85 | cd->cpumask = cpumask_of(cpu); | ||
86 | cd->set_next_event = gic_next_event; | ||
87 | cd->set_mode = gic_set_clock_mode; | ||
88 | cd->event_handler = gic_event_handler; | ||
89 | |||
90 | clockevents_register_device(cd); | ||
91 | |||
92 | if (!gic_timer_irq_installed) { | ||
93 | setup_percpu_irq(irq, &gic_compare_irqaction); | ||
94 | gic_timer_irq_installed = 1; | ||
95 | } | ||
96 | |||
97 | enable_percpu_irq(irq, IRQ_TYPE_NONE); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
12 | static cycle_t gic_hpt_read(struct clocksource *cs) | 102 | static cycle_t gic_hpt_read(struct clocksource *cs) |
13 | { | 103 | { |
14 | return gic_read_count(); | 104 | return gic_read_count(); |