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 | |
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>
-rw-r--r-- | arch/mips/Kconfig | 13 | ||||
-rw-r--r-- | arch/mips/include/asm/time.h | 2 | ||||
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/cevt-gic.c | 103 | ||||
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 90 | ||||
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 2 |
6 files changed, 92 insertions, 119 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5b690cf0fec7..97bbb3b09d4b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -935,10 +935,6 @@ config CEVT_GT641XX | |||
935 | config CEVT_R4K | 935 | config CEVT_R4K |
936 | bool | 936 | bool |
937 | 937 | ||
938 | config CEVT_GIC | ||
939 | select MIPS_CM | ||
940 | bool | ||
941 | |||
942 | config CEVT_SB1250 | 938 | config CEVT_SB1250 |
943 | bool | 939 | bool |
944 | 940 | ||
@@ -1911,15 +1907,6 @@ config FORCE_MAX_ZONEORDER | |||
1911 | The page size is not necessarily 4KB. Keep this in mind | 1907 | The page size is not necessarily 4KB. Keep this in mind |
1912 | when choosing a value for this option. | 1908 | when choosing a value for this option. |
1913 | 1909 | ||
1914 | config CEVT_GIC | ||
1915 | bool "Use GIC global counter for clock events" | ||
1916 | depends on MIPS_GIC && !MIPS_SEAD3 | ||
1917 | help | ||
1918 | Use the GIC global counter for the clock events. The R4K clock | ||
1919 | event driver is always present, so if the platform ends up not | ||
1920 | detecting a GIC, it will fall back to the R4K timer for the | ||
1921 | generation of clock events. | ||
1922 | |||
1923 | config BOARD_SCACHE | 1910 | config BOARD_SCACHE |
1924 | bool | 1911 | bool |
1925 | 1912 | ||
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index 7969933ba89a..5f30aabbb598 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h | |||
@@ -57,7 +57,7 @@ extern int gic_clockevent_init(void); | |||
57 | 57 | ||
58 | static inline int mips_clockevent_init(void) | 58 | static inline int mips_clockevent_init(void) |
59 | { | 59 | { |
60 | #if defined(CONFIG_CEVT_GIC) | 60 | #if defined(CONFIG_CLKSRC_MIPS_GIC) |
61 | return (gic_clockevent_init() | r4k_clockevent_init()); | 61 | return (gic_clockevent_init() | r4k_clockevent_init()); |
62 | #elif defined(CONFIG_CEVT_R4K) | 62 | #elif defined(CONFIG_CEVT_R4K) |
63 | return r4k_clockevent_init(); | 63 | return r4k_clockevent_init(); |
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 1aedbf5e4232..92987d1bbe5f 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -19,7 +19,6 @@ endif | |||
19 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o | 19 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o |
20 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o | 20 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o |
21 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o | 21 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o |
22 | obj-$(CONFIG_CEVT_GIC) += cevt-gic.o | ||
23 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o | 22 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o |
24 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o | 23 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o |
25 | obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o | 24 | obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o |
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c deleted file mode 100644 index 9caa68a2bcdc..000000000000 --- a/arch/mips/kernel/cevt-gic.c +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2013 Imagination Technologies Ltd. | ||
7 | */ | ||
8 | #include <linux/clockchips.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/percpu.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/irqchip/mips-gic.h> | ||
14 | |||
15 | #include <asm/time.h> | ||
16 | #include <asm/mips-boards/maltaint.h> | ||
17 | |||
18 | DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); | ||
19 | int gic_timer_irq_installed; | ||
20 | |||
21 | |||
22 | static int gic_next_event(unsigned long delta, struct clock_event_device *evt) | ||
23 | { | ||
24 | u64 cnt; | ||
25 | int res; | ||
26 | |||
27 | cnt = gic_read_count(); | ||
28 | cnt += (u64)delta; | ||
29 | gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask)); | ||
30 | res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; | ||
31 | return res; | ||
32 | } | ||
33 | |||
34 | void gic_set_clock_mode(enum clock_event_mode mode, | ||
35 | struct clock_event_device *evt) | ||
36 | { | ||
37 | /* Nothing to do ... */ | ||
38 | } | ||
39 | |||
40 | irqreturn_t gic_compare_interrupt(int irq, void *dev_id) | ||
41 | { | ||
42 | struct clock_event_device *cd; | ||
43 | int cpu = smp_processor_id(); | ||
44 | |||
45 | gic_write_compare(gic_read_compare()); | ||
46 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
47 | cd->event_handler(cd); | ||
48 | return IRQ_HANDLED; | ||
49 | } | ||
50 | |||
51 | struct irqaction gic_compare_irqaction = { | ||
52 | .handler = gic_compare_interrupt, | ||
53 | .flags = IRQF_PERCPU | IRQF_TIMER, | ||
54 | .name = "timer", | ||
55 | }; | ||
56 | |||
57 | |||
58 | void gic_event_handler(struct clock_event_device *dev) | ||
59 | { | ||
60 | } | ||
61 | |||
62 | int gic_clockevent_init(void) | ||
63 | { | ||
64 | unsigned int cpu = smp_processor_id(); | ||
65 | struct clock_event_device *cd; | ||
66 | unsigned int irq; | ||
67 | |||
68 | if (!cpu_has_counter || !gic_frequency) | ||
69 | return -ENXIO; | ||
70 | |||
71 | irq = MIPS_GIC_IRQ_BASE + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); | ||
72 | |||
73 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
74 | |||
75 | cd->name = "MIPS GIC"; | ||
76 | cd->features = CLOCK_EVT_FEAT_ONESHOT | | ||
77 | CLOCK_EVT_FEAT_C3STOP; | ||
78 | |||
79 | clockevent_set_clock(cd, gic_frequency); | ||
80 | |||
81 | /* Calculate the min / max delta */ | ||
82 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
83 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
84 | |||
85 | cd->rating = 300; | ||
86 | cd->irq = irq; | ||
87 | cd->cpumask = cpumask_of(cpu); | ||
88 | cd->set_next_event = gic_next_event; | ||
89 | cd->set_mode = gic_set_clock_mode; | ||
90 | cd->event_handler = gic_event_handler; | ||
91 | |||
92 | clockevents_register_device(cd); | ||
93 | |||
94 | if (!gic_timer_irq_installed) { | ||
95 | setup_percpu_irq(irq, &gic_compare_irqaction); | ||
96 | gic_timer_irq_installed = 1; | ||
97 | } | ||
98 | |||
99 | enable_percpu_irq(irq, IRQ_TYPE_NONE); | ||
100 | |||
101 | |||
102 | return 0; | ||
103 | } | ||
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(); |
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 035d5ad435f9..cb674696810d 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -103,7 +103,7 @@ static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe) | |||
103 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)); | 103 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)); |
104 | } | 104 | } |
105 | 105 | ||
106 | #if defined(CONFIG_CLKSRC_MIPS_GIC) || defined(CONFIG_CEVT_GIC) | 106 | #ifdef CONFIG_CLKSRC_MIPS_GIC |
107 | cycle_t gic_read_count(void) | 107 | cycle_t gic_read_count(void) |
108 | { | 108 | { |
109 | unsigned int hi, hi2, lo; | 109 | unsigned int hi, hi2, lo; |