aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-18 12:48:11 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-18 13:11:47 -0400
commit42f77542f4a1c104bb6fbba2e18e04e84415a96b (patch)
tree79b58e2d3e93abacbdd535684e2627231d2e0ffc /arch
parent2cfa7660dbf94a61b9d43edaa84be454f9dc25fc (diff)
[MIPS] time: Move R4000 clockevent device code to separate configurable file
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig24
-rw-r--r--arch/mips/au1000/Kconfig1
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/cevt-r4k.c272
-rw-r--r--arch/mips/kernel/time.c241
-rw-r--r--arch/mips/kernel/traps.c11
-rw-r--r--arch/mips/pmc-sierra/Kconfig2
-rw-r--r--arch/mips/vr41xx/Kconfig6
8 files changed, 318 insertions, 241 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 235d4514e0a..cb027580cd1 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -21,6 +21,7 @@ config MACH_ALCHEMY
21 21
22config BASLER_EXCITE 22config BASLER_EXCITE
23 bool "Basler eXcite smart camera" 23 bool "Basler eXcite smart camera"
24 select CEVT_R4K
24 select DMA_COHERENT 25 select DMA_COHERENT
25 select HW_HAS_PCI 26 select HW_HAS_PCI
26 select IRQ_CPU 27 select IRQ_CPU
@@ -47,6 +48,7 @@ config BASLER_EXCITE_PROTOTYPE
47 48
48config BCM47XX 49config BCM47XX
49 bool "BCM47XX based boards" 50 bool "BCM47XX based boards"
51 select CEVT_R4K
50 select DMA_NONCOHERENT 52 select DMA_NONCOHERENT
51 select HW_HAS_PCI 53 select HW_HAS_PCI
52 select IRQ_CPU 54 select IRQ_CPU
@@ -63,6 +65,7 @@ config BCM47XX
63 65
64config MIPS_COBALT 66config MIPS_COBALT
65 bool "Cobalt Server" 67 bool "Cobalt Server"
68 select CEVT_R4K
66 select DMA_NONCOHERENT 69 select DMA_NONCOHERENT
67 select HW_HAS_PCI 70 select HW_HAS_PCI
68 select I8253 71 select I8253
@@ -80,6 +83,7 @@ config MIPS_COBALT
80config MACH_DECSTATION 83config MACH_DECSTATION
81 bool "DECstations" 84 bool "DECstations"
82 select BOOT_ELF32 85 select BOOT_ELF32
86 select CEVT_R4K
83 select DMA_NONCOHERENT 87 select DMA_NONCOHERENT
84 select NO_IOPORT 88 select NO_IOPORT
85 select IRQ_CPU 89 select IRQ_CPU
@@ -111,6 +115,7 @@ config MACH_JAZZ
111 select ARC 115 select ARC
112 select ARC32 116 select ARC32
113 select ARCH_MAY_HAVE_PC_FDC 117 select ARCH_MAY_HAVE_PC_FDC
118 select CEVT_R4K
114 select GENERIC_ISA_DMA 119 select GENERIC_ISA_DMA
115 select IRQ_CPU 120 select IRQ_CPU
116 select I8253 121 select I8253
@@ -130,6 +135,7 @@ config MACH_JAZZ
130 135
131config LASAT 136config LASAT
132 bool "LASAT Networks platforms" 137 bool "LASAT Networks platforms"
138 select CEVT_R4K
133 select DMA_NONCOHERENT 139 select DMA_NONCOHERENT
134 select SYS_HAS_EARLY_PRINTK 140 select SYS_HAS_EARLY_PRINTK
135 select HW_HAS_PCI 141 select HW_HAS_PCI
@@ -146,6 +152,7 @@ config LASAT
146config LEMOTE_FULONG 152config LEMOTE_FULONG
147 bool "Lemote Fulong mini-PC" 153 bool "Lemote Fulong mini-PC"
148 select ARCH_SPARSEMEM_ENABLE 154 select ARCH_SPARSEMEM_ENABLE
155 select CEVT_R4K
149 select SYS_HAS_CPU_LOONGSON2 156 select SYS_HAS_CPU_LOONGSON2
150 select DMA_NONCOHERENT 157 select DMA_NONCOHERENT
151 select BOOT_ELF32 158 select BOOT_ELF32
@@ -170,6 +177,7 @@ config LEMOTE_FULONG
170config MIPS_ATLAS 177config MIPS_ATLAS
171 bool "MIPS Atlas board" 178 bool "MIPS Atlas board"
172 select BOOT_ELF32 179 select BOOT_ELF32
180 select CEVT_R4K
173 select DMA_NONCOHERENT 181 select DMA_NONCOHERENT
174 select SYS_HAS_EARLY_PRINTK 182 select SYS_HAS_EARLY_PRINTK
175 select IRQ_CPU 183 select IRQ_CPU
@@ -200,6 +208,7 @@ config MIPS_MALTA
200 bool "MIPS Malta board" 208 bool "MIPS Malta board"
201 select ARCH_MAY_HAVE_PC_FDC 209 select ARCH_MAY_HAVE_PC_FDC
202 select BOOT_ELF32 210 select BOOT_ELF32
211 select CEVT_R4K
203 select DMA_NONCOHERENT 212 select DMA_NONCOHERENT
204 select GENERIC_ISA_DMA 213 select GENERIC_ISA_DMA
205 select IRQ_CPU 214 select IRQ_CPU
@@ -230,6 +239,7 @@ config MIPS_MALTA
230 239
231config MIPS_SEAD 240config MIPS_SEAD
232 bool "MIPS SEAD board" 241 bool "MIPS SEAD board"
242 select CEVT_R4K
233 select IRQ_CPU 243 select IRQ_CPU
234 select DMA_NONCOHERENT 244 select DMA_NONCOHERENT
235 select SYS_HAS_EARLY_PRINTK 245 select SYS_HAS_EARLY_PRINTK
@@ -248,6 +258,7 @@ config MIPS_SEAD
248 258
249config MIPS_SIM 259config MIPS_SIM
250 bool 'MIPS simulator (MIPSsim)' 260 bool 'MIPS simulator (MIPSsim)'
261 select CEVT_R4K
251 select DMA_NONCOHERENT 262 select DMA_NONCOHERENT
252 select SYS_HAS_EARLY_PRINTK 263 select SYS_HAS_EARLY_PRINTK
253 select IRQ_CPU 264 select IRQ_CPU
@@ -265,6 +276,7 @@ config MIPS_SIM
265 276
266config MARKEINS 277config MARKEINS
267 bool "NEC EMMA2RH Mark-eins" 278 bool "NEC EMMA2RH Mark-eins"
279 select CEVT_R4K
268 select DMA_NONCOHERENT 280 select DMA_NONCOHERENT
269 select HW_HAS_PCI 281 select HW_HAS_PCI
270 select IRQ_CPU 282 select IRQ_CPU
@@ -279,6 +291,7 @@ config MARKEINS
279 291
280config MACH_VR41XX 292config MACH_VR41XX
281 bool "NEC VR4100 series based machines" 293 bool "NEC VR4100 series based machines"
294 select CEVT_R4K
282 select SYS_HAS_CPU_VR41XX 295 select SYS_HAS_CPU_VR41XX
283 select GENERIC_HARDIRQS_NO__DO_IRQ 296 select GENERIC_HARDIRQS_NO__DO_IRQ
284 297
@@ -315,6 +328,7 @@ config PMC_MSP
315 328
316config PMC_YOSEMITE 329config PMC_YOSEMITE
317 bool "PMC-Sierra Yosemite eval board" 330 bool "PMC-Sierra Yosemite eval board"
331 select CEVT_R4K
318 select DMA_COHERENT 332 select DMA_COHERENT
319 select HW_HAS_PCI 333 select HW_HAS_PCI
320 select IRQ_CPU 334 select IRQ_CPU
@@ -335,6 +349,7 @@ config PMC_YOSEMITE
335 349
336config QEMU 350config QEMU
337 bool "Qemu" 351 bool "Qemu"
352 select CEVT_R4K
338 select DMA_COHERENT 353 select DMA_COHERENT
339 select GENERIC_ISA_DMA 354 select GENERIC_ISA_DMA
340 select HAVE_STD_PC_SERIAL_PORT 355 select HAVE_STD_PC_SERIAL_PORT
@@ -365,6 +380,7 @@ config SGI_IP22
365 select ARC 380 select ARC
366 select ARC32 381 select ARC32
367 select BOOT_ELF32 382 select BOOT_ELF32
383 select CEVT_R4K
368 select DMA_NONCOHERENT 384 select DMA_NONCOHERENT
369 select HW_HAS_EISA 385 select HW_HAS_EISA
370 select I8253 386 select I8253
@@ -409,6 +425,7 @@ config SGI_IP32
409 select ARC 425 select ARC
410 select ARC32 426 select ARC32
411 select BOOT_ELF32 427 select BOOT_ELF32
428 select CEVT_R4K
412 select DMA_NONCOHERENT 429 select DMA_NONCOHERENT
413 select HW_HAS_PCI 430 select HW_HAS_PCI
414 select IRQ_CPU 431 select IRQ_CPU
@@ -536,6 +553,7 @@ config SNI_RM
536 select ARC32 if CPU_LITTLE_ENDIAN 553 select ARC32 if CPU_LITTLE_ENDIAN
537 select ARCH_MAY_HAVE_PC_FDC 554 select ARCH_MAY_HAVE_PC_FDC
538 select BOOT_ELF32 555 select BOOT_ELF32
556 select CEVT_R4K
539 select DMA_NONCOHERENT 557 select DMA_NONCOHERENT
540 select GENERIC_ISA_DMA 558 select GENERIC_ISA_DMA
541 select HW_HAS_EISA 559 select HW_HAS_EISA
@@ -577,6 +595,7 @@ config TOSHIBA_JMR3927
577 595
578config TOSHIBA_RBTX4927 596config TOSHIBA_RBTX4927
579 bool "Toshiba RBTX49[23]7 board" 597 bool "Toshiba RBTX49[23]7 board"
598 select CEVT_R4K
580 select DMA_NONCOHERENT 599 select DMA_NONCOHERENT
581 select HAS_TXX9_SERIAL 600 select HAS_TXX9_SERIAL
582 select HW_HAS_PCI 601 select HW_HAS_PCI
@@ -597,6 +616,7 @@ config TOSHIBA_RBTX4927
597 616
598config TOSHIBA_RBTX4938 617config TOSHIBA_RBTX4938
599 bool "Toshiba RBTX4938 board" 618 bool "Toshiba RBTX4938 board"
619 select CEVT_R4K
600 select DMA_NONCOHERENT 620 select DMA_NONCOHERENT
601 select HAS_TXX9_SERIAL 621 select HAS_TXX9_SERIAL
602 select HW_HAS_PCI 622 select HW_HAS_PCI
@@ -616,6 +636,7 @@ config TOSHIBA_RBTX4938
616 636
617config WR_PPMC 637config WR_PPMC
618 bool "Wind River PPMC board" 638 bool "Wind River PPMC board"
639 select CEVT_R4K
619 select IRQ_CPU 640 select IRQ_CPU
620 select BOOT_ELF32 641 select BOOT_ELF32
621 select DMA_NONCOHERENT 642 select DMA_NONCOHERENT
@@ -708,6 +729,9 @@ config ARCH_MAY_HAVE_PC_FDC
708config BOOT_RAW 729config BOOT_RAW
709 bool 730 bool
710 731
732config CEVT_R4K
733 bool
734
711config CFE 735config CFE
712 bool 736 bool
713 737
diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig
index a23d4154da0..b36cec58a9a 100644
--- a/arch/mips/au1000/Kconfig
+++ b/arch/mips/au1000/Kconfig
@@ -137,6 +137,7 @@ config SOC_AU1200
137config SOC_AU1X00 137config SOC_AU1X00
138 bool 138 bool
139 select 64BIT_PHYS_ADDR 139 select 64BIT_PHYS_ADDR
140 select CEVT_R4K
140 select IRQ_CPU 141 select IRQ_CPU
141 select SYS_HAS_CPU_MIPS32_R1 142 select SYS_HAS_CPU_MIPS32_R1
142 select SYS_SUPPORTS_32BIT_KERNEL 143 select SYS_SUPPORTS_32BIT_KERNEL
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 95a356ef391..a3afa39faae 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -8,6 +8,8 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
8 ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ 8 ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
9 time.o topology.o traps.o unaligned.o 9 time.o topology.o traps.o unaligned.o
10 10
11obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
12
11binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ 13binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
12 irix5sys.o sysirix.o 14 irix5sys.o sysirix.o
13 15
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
new file mode 100644
index 00000000000..08b84d476c8
--- /dev/null
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -0,0 +1,272 @@
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) 2007 MIPS Technologies, Inc.
7 * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
8 */
9#include <linux/clockchips.h>
10#include <linux/interrupt.h>
11#include <linux/percpu.h>
12
13#include <asm/time.h>
14
15static int mips_next_event(unsigned long delta,
16 struct clock_event_device *evt)
17{
18 unsigned int cnt;
19 int res;
20
21#ifdef CONFIG_MIPS_MT_SMTC
22 {
23 unsigned long flags, vpflags;
24 local_irq_save(flags);
25 vpflags = dvpe();
26#endif
27 cnt = read_c0_count();
28 cnt += delta;
29 write_c0_compare(cnt);
30 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0;
31#ifdef CONFIG_MIPS_MT_SMTC
32 evpe(vpflags);
33 local_irq_restore(flags);
34 }
35#endif
36 return res;
37}
38
39static void mips_set_mode(enum clock_event_mode mode,
40 struct clock_event_device *evt)
41{
42 /* Nothing to do ... */
43}
44
45static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
46static int cp0_timer_irq_installed;
47
48/*
49 * Timer ack for an R4k-compatible timer of a known frequency.
50 */
51static void c0_timer_ack(void)
52{
53 write_c0_compare(read_c0_compare());
54}
55
56/*
57 * Possibly handle a performance counter interrupt.
58 * Return true if the timer interrupt should not be checked
59 */
60static inline int handle_perf_irq(int r2)
61{
62 /*
63 * The performance counter overflow interrupt may be shared with the
64 * timer interrupt (cp0_perfcount_irq < 0). If it is and a
65 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
66 * and we can't reliably determine if a counter interrupt has also
67 * happened (!r2) then don't check for a timer interrupt.
68 */
69 return (cp0_perfcount_irq < 0) &&
70 perf_irq() == IRQ_HANDLED &&
71 !r2;
72}
73
74static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
75{
76 const int r2 = cpu_has_mips_r2;
77 struct clock_event_device *cd;
78 int cpu = smp_processor_id();
79
80 /*
81 * Suckage alert:
82 * Before R2 of the architecture there was no way to see if a
83 * performance counter interrupt was pending, so we have to run
84 * the performance counter interrupt handler anyway.
85 */
86 if (handle_perf_irq(r2))
87 goto out;
88
89 /*
90 * The same applies to performance counter interrupts. But with the
91 * above we now know that the reason we got here must be a timer
92 * interrupt. Being the paranoiacs we are we check anyway.
93 */
94 if (!r2 || (read_c0_cause() & (1 << 30))) {
95 c0_timer_ack();
96#ifdef CONFIG_MIPS_MT_SMTC
97 if (cpu_data[cpu].vpe_id)
98 goto out;
99 cpu = 0;
100#endif
101 cd = &per_cpu(mips_clockevent_device, cpu);
102 cd->event_handler(cd);
103 }
104
105out:
106 return IRQ_HANDLED;
107}
108
109static struct irqaction c0_compare_irqaction = {
110 .handler = c0_compare_interrupt,
111#ifdef CONFIG_MIPS_MT_SMTC
112 .flags = IRQF_DISABLED,
113#else
114 .flags = IRQF_DISABLED | IRQF_PERCPU,
115#endif
116 .name = "timer",
117};
118
119#ifdef CONFIG_MIPS_MT_SMTC
120DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
121
122static void smtc_set_mode(enum clock_event_mode mode,
123 struct clock_event_device *evt)
124{
125}
126
127static void mips_broadcast(cpumask_t mask)
128{
129 unsigned int cpu;
130
131 for_each_cpu_mask(cpu, mask)
132 smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
133}
134
135static void setup_smtc_dummy_clockevent_device(void)
136{
137 //uint64_t mips_freq = mips_hpt_^frequency;
138 unsigned int cpu = smp_processor_id();
139 struct clock_event_device *cd;
140
141 cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
142
143 cd->name = "SMTC";
144 cd->features = CLOCK_EVT_FEAT_DUMMY;
145
146 /* Calculate the min / max delta */
147 cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
148 cd->shift = 0; //32;
149 cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
150 cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
151
152 cd->rating = 200;
153 cd->irq = 17; //-1;
154// if (cpu)
155// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
156// else
157 cd->cpumask = cpumask_of_cpu(cpu);
158
159 cd->set_mode = smtc_set_mode;
160
161 cd->broadcast = mips_broadcast;
162
163 clockevents_register_device(cd);
164}
165#endif
166
167static void mips_event_handler(struct clock_event_device *dev)
168{
169}
170
171/*
172 * FIXME: This doesn't hold for the relocated E9000 compare interrupt.
173 */
174static int c0_compare_int_pending(void)
175{
176 return (read_c0_cause() >> cp0_compare_irq) & 0x100;
177}
178
179static int c0_compare_int_usable(void)
180{
181 const unsigned int delta = 0x300000;
182 unsigned int cnt;
183
184 /*
185 * IP7 already pending? Try to clear it by acking the timer.
186 */
187 if (c0_compare_int_pending()) {
188 write_c0_compare(read_c0_compare());
189 irq_disable_hazard();
190 if (c0_compare_int_pending())
191 return 0;
192 }
193
194 cnt = read_c0_count();
195 cnt += delta;
196 write_c0_compare(cnt);
197
198 while ((long)(read_c0_count() - cnt) <= 0)
199 ; /* Wait for expiry */
200
201 if (!c0_compare_int_pending())
202 return 0;
203
204 write_c0_compare(read_c0_compare());
205 irq_disable_hazard();
206 if (c0_compare_int_pending())
207 return 0;
208
209 /*
210 * Feels like a real count / compare timer.
211 */
212 return 1;
213}
214
215void __cpuinit mips_clockevent_init(void)
216{
217 uint64_t mips_freq = mips_hpt_frequency;
218 unsigned int cpu = smp_processor_id();
219 struct clock_event_device *cd;
220 unsigned int irq = MIPS_CPU_IRQ_BASE + 7;
221
222 if (!cpu_has_counter)
223 return;
224
225#ifdef CONFIG_MIPS_MT_SMTC
226 setup_smtc_dummy_clockevent_device();
227
228 /*
229 * On SMTC we only register VPE0's compare interrupt as clockevent
230 * device.
231 */
232 if (cpu)
233 return;
234#endif
235
236 if (!c0_compare_int_usable())
237 return;
238
239 cd = &per_cpu(mips_clockevent_device, cpu);
240
241 cd->name = "MIPS";
242 cd->features = CLOCK_EVT_FEAT_ONESHOT;
243
244 /* Calculate the min / max delta */
245 cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
246 cd->shift = 32;
247 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
248 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
249
250 cd->rating = 300;
251 cd->irq = irq;
252#ifdef CONFIG_MIPS_MT_SMTC
253 cd->cpumask = CPU_MASK_ALL;
254#else
255 cd->cpumask = cpumask_of_cpu(cpu);
256#endif
257 cd->set_next_event = mips_next_event;
258 cd->set_mode = mips_set_mode;
259 cd->event_handler = mips_event_handler;
260
261 clockevents_register_device(cd);
262
263 if (!cp0_timer_irq_installed) {
264#ifdef CONFIG_MIPS_MT_SMTC
265#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
266 setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
267#else
268 setup_irq(irq, &c0_compare_irqaction);
269#endif /* CONFIG_MIPS_MT_SMTC */
270 cp0_timer_irq_installed = 1;
271 }
272}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index abadb8cb77c..ea7cfe766a8 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -81,14 +81,6 @@ static cycle_t null_hpt_read(void)
81} 81}
82 82
83/* 83/*
84 * Timer ack for an R4k-compatible timer of a known frequency.
85 */
86static void c0_timer_ack(void)
87{
88 write_c0_compare(read_c0_compare());
89}
90
91/*
92 * High precision timer functions for a R4k-compatible timer. 84 * High precision timer functions for a R4k-compatible timer.
93 */ 85 */
94static cycle_t c0_hpt_read(void) 86static cycle_t c0_hpt_read(void)
@@ -126,35 +118,6 @@ int (*perf_irq)(void) = null_perf_irq;
126EXPORT_SYMBOL(perf_irq); 118EXPORT_SYMBOL(perf_irq);
127 119
128/* 120/*
129 * Timer interrupt
130 */
131int cp0_compare_irq;
132
133/*
134 * Performance counter IRQ or -1 if shared with timer
135 */
136int cp0_perfcount_irq;
137EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
138
139/*
140 * Possibly handle a performance counter interrupt.
141 * Return true if the timer interrupt should not be checked
142 */
143static inline int handle_perf_irq(int r2)
144{
145 /*
146 * The performance counter overflow interrupt may be shared with the
147 * timer interrupt (cp0_perfcount_irq < 0). If it is and a
148 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
149 * and we can't reliably determine if a counter interrupt has also
150 * happened (!r2) then don't check for a timer interrupt.
151 */
152 return (cp0_perfcount_irq < 0) &&
153 perf_irq() == IRQ_HANDLED &&
154 !r2;
155}
156
157/*
158 * time_init() - it does the following things. 121 * time_init() - it does the following things.
159 * 122 *
160 * 1) plat_time_init() - 123 * 1) plat_time_init() -
@@ -219,84 +182,6 @@ struct clocksource clocksource_mips = {
219 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 182 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
220}; 183};
221 184
222static int mips_next_event(unsigned long delta,
223 struct clock_event_device *evt)
224{
225 unsigned int cnt;
226 int res;
227
228#ifdef CONFIG_MIPS_MT_SMTC
229 {
230 unsigned long flags, vpflags;
231 local_irq_save(flags);
232 vpflags = dvpe();
233#endif
234 cnt = read_c0_count();
235 cnt += delta;
236 write_c0_compare(cnt);
237 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0;
238#ifdef CONFIG_MIPS_MT_SMTC
239 evpe(vpflags);
240 local_irq_restore(flags);
241 }
242#endif
243 return res;
244}
245
246static void mips_set_mode(enum clock_event_mode mode,
247 struct clock_event_device *evt)
248{
249 /* Nothing to do ... */
250}
251
252static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
253static int cp0_timer_irq_installed;
254
255static irqreturn_t timer_interrupt(int irq, void *dev_id)
256{
257 const int r2 = cpu_has_mips_r2;
258 struct clock_event_device *cd;
259 int cpu = smp_processor_id();
260
261 /*
262 * Suckage alert:
263 * Before R2 of the architecture there was no way to see if a
264 * performance counter interrupt was pending, so we have to run
265 * the performance counter interrupt handler anyway.
266 */
267 if (handle_perf_irq(r2))
268 goto out;
269
270 /*
271 * The same applies to performance counter interrupts. But with the
272 * above we now know that the reason we got here must be a timer
273 * interrupt. Being the paranoiacs we are we check anyway.
274 */
275 if (!r2 || (read_c0_cause() & (1 << 30))) {
276 c0_timer_ack();
277#ifdef CONFIG_MIPS_MT_SMTC
278 if (cpu_data[cpu].vpe_id)
279 goto out;
280 cpu = 0;
281#endif
282 cd = &per_cpu(mips_clockevent_device, cpu);
283 cd->event_handler(cd);
284 }
285
286out:
287 return IRQ_HANDLED;
288}
289
290static struct irqaction timer_irqaction = {
291 .handler = timer_interrupt,
292#ifdef CONFIG_MIPS_MT_SMTC
293 .flags = IRQF_DISABLED,
294#else
295 .flags = IRQF_DISABLED | IRQF_PERCPU,
296#endif
297 .name = "timer",
298};
299
300static void __init init_mips_clocksource(void) 185static void __init init_mips_clocksource(void)
301{ 186{
302 u64 temp; 187 u64 temp;
@@ -336,8 +221,6 @@ static void smtc_set_mode(enum clock_event_mode mode,
336{ 221{
337} 222}
338 223
339int dummycnt[NR_CPUS];
340
341static void mips_broadcast(cpumask_t mask) 224static void mips_broadcast(cpumask_t mask)
342{ 225{
343 unsigned int cpu; 226 unsigned int cpu;
@@ -378,113 +261,6 @@ static void setup_smtc_dummy_clockevent_device(void)
378} 261}
379#endif 262#endif
380 263
381static void mips_event_handler(struct clock_event_device *dev)
382{
383}
384
385/*
386 * FIXME: This doesn't hold for the relocated E9000 compare interrupt.
387 */
388static int c0_compare_int_pending(void)
389{
390 return (read_c0_cause() >> cp0_compare_irq) & 0x100;
391}
392
393static int c0_compare_int_usable(void)
394{
395 const unsigned int delta = 0x300000;
396 unsigned int cnt;
397
398 /*
399 * IP7 already pending? Try to clear it by acking the timer.
400 */
401 if (c0_compare_int_pending()) {
402 write_c0_compare(read_c0_compare());
403 irq_disable_hazard();
404 if (c0_compare_int_pending())
405 return 0;
406 }
407
408 cnt = read_c0_count();
409 cnt += delta;
410 write_c0_compare(cnt);
411
412 while ((long)(read_c0_count() - cnt) <= 0)
413 ; /* Wait for expiry */
414
415 if (!c0_compare_int_pending())
416 return 0;
417
418 write_c0_compare(read_c0_compare());
419 irq_disable_hazard();
420 if (c0_compare_int_pending())
421 return 0;
422
423 /*
424 * Feels like a real count / compare timer.
425 */
426 return 1;
427}
428
429void __cpuinit mips_clockevent_init(void)
430{
431 uint64_t mips_freq = mips_hpt_frequency;
432 unsigned int cpu = smp_processor_id();
433 struct clock_event_device *cd;
434 unsigned int irq = MIPS_CPU_IRQ_BASE + 7;
435
436 if (!cpu_has_counter)
437 return;
438
439#ifdef CONFIG_MIPS_MT_SMTC
440 setup_smtc_dummy_clockevent_device();
441
442 /*
443 * On SMTC we only register VPE0's compare interrupt as clockevent
444 * device.
445 */
446 if (cpu)
447 return;
448#endif
449
450 if (!c0_compare_int_usable())
451 return;
452
453 cd = &per_cpu(mips_clockevent_device, cpu);
454
455 cd->name = "MIPS";
456 cd->features = CLOCK_EVT_FEAT_ONESHOT;
457
458 /* Calculate the min / max delta */
459 cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
460 cd->shift = 32;
461 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
462 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
463
464 cd->rating = 300;
465 cd->irq = irq;
466#ifdef CONFIG_MIPS_MT_SMTC
467 cd->cpumask = CPU_MASK_ALL;
468#else
469 cd->cpumask = cpumask_of_cpu(cpu);
470#endif
471 cd->set_next_event = mips_next_event;
472 cd->set_mode = mips_set_mode;
473 cd->event_handler = mips_event_handler;
474
475 clockevents_register_device(cd);
476
477 if (!cp0_timer_irq_installed) {
478#ifdef CONFIG_MIPS_MT_SMTC
479#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
480 setup_irq_smtc(irq, &timer_irqaction, CPUCTR_IMASKBIT);
481#else
482 setup_irq(irq, &timer_irqaction);
483#endif /* CONFIG_MIPS_MT_SMTC */
484 cp0_timer_irq_installed = 1;
485 }
486}
487
488void __init time_init(void) 264void __init time_init(void)
489{ 265{
490 plat_time_init(); 266 plat_time_init();
@@ -511,25 +287,8 @@ void __init time_init(void)
511 printk("Using %u.%03u MHz high precision timer.\n", 287 printk("Using %u.%03u MHz high precision timer.\n",
512 ((mips_hpt_frequency + 500) / 1000) / 1000, 288 ((mips_hpt_frequency + 500) / 1000) / 1000,
513 ((mips_hpt_frequency + 500) / 1000) % 1000); 289 ((mips_hpt_frequency + 500) / 1000) % 1000);
514
515#ifdef CONFIG_IRQ_CPU
516 setup_irq(MIPS_CPU_IRQ_BASE + 7, &timer_irqaction);
517#endif
518 } 290 }
519 291
520 /*
521 * Call board specific timer interrupt setup.
522 *
523 * this pointer must be setup in machine setup routine.
524 *
525 * Even if a machine chooses to use a low-level timer interrupt,
526 * it still needs to setup the timer_irqaction.
527 * In that case, it might be better to set timer_irqaction.handler
528 * to be NULL function so that we are sure the high-level code
529 * is not invoked accidentally.
530 */
531 plat_timer_setup(&timer_irqaction);
532
533 init_mips_clocksource(); 292 init_mips_clocksource();
534 mips_clockevent_init(); 293 mips_clockevent_init();
535} 294}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index bbf01b81a4f..7b78d137259 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1336,6 +1336,17 @@ extern void cpu_cache_init(void);
1336extern void tlb_init(void); 1336extern void tlb_init(void);
1337extern void flush_tlb_handlers(void); 1337extern void flush_tlb_handlers(void);
1338 1338
1339/*
1340 * Timer interrupt
1341 */
1342int cp0_compare_irq;
1343
1344/*
1345 * Performance counter IRQ or -1 if shared with timer
1346 */
1347int cp0_perfcount_irq;
1348EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
1349
1339void __init per_cpu_trap_init(void) 1350void __init per_cpu_trap_init(void)
1340{ 1351{
1341 unsigned int cpu = smp_processor_id(); 1352 unsigned int cpu = smp_processor_id();
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index abbd0bbfabd..6b293ce0935 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -4,11 +4,13 @@ choice
4 4
5config PMC_MSP4200_EVAL 5config PMC_MSP4200_EVAL
6 bool "PMC-Sierra MSP4200 Eval Board" 6 bool "PMC-Sierra MSP4200 Eval Board"
7 select CEVT_R4K
7 select IRQ_MSP_SLP 8 select IRQ_MSP_SLP
8 select HW_HAS_PCI 9 select HW_HAS_PCI
9 10
10config PMC_MSP4200_GW 11config PMC_MSP4200_GW
11 bool "PMC-Sierra MSP4200 VoIP Gateway" 12 bool "PMC-Sierra MSP4200 VoIP Gateway"
13 select CEVT_R4K
12 select IRQ_MSP_SLP 14 select IRQ_MSP_SLP
13 select HW_HAS_PCI 15 select HW_HAS_PCI
14 16
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index 8f4d3e74c23..eeb089f20c0 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -5,6 +5,7 @@ choice
5 5
6config CASIO_E55 6config CASIO_E55
7 bool "CASIO CASSIOPEIA E-10/15/55/65" 7 bool "CASIO CASSIOPEIA E-10/15/55/65"
8 select CEVT_R4K
8 select DMA_NONCOHERENT 9 select DMA_NONCOHERENT
9 select IRQ_CPU 10 select IRQ_CPU
10 select ISA 11 select ISA
@@ -13,6 +14,7 @@ config CASIO_E55
13 14
14config IBM_WORKPAD 15config IBM_WORKPAD
15 bool "IBM WorkPad z50" 16 bool "IBM WorkPad z50"
17 select CEVT_R4K
16 select DMA_NONCOHERENT 18 select DMA_NONCOHERENT
17 select IRQ_CPU 19 select IRQ_CPU
18 select ISA 20 select ISA
@@ -21,6 +23,7 @@ config IBM_WORKPAD
21 23
22config NEC_CMBVR4133 24config NEC_CMBVR4133
23 bool "NEC CMB-VR4133" 25 bool "NEC CMB-VR4133"
26 select CEVT_R4K
24 select DMA_NONCOHERENT 27 select DMA_NONCOHERENT
25 select IRQ_CPU 28 select IRQ_CPU
26 select HW_HAS_PCI 29 select HW_HAS_PCI
@@ -29,6 +32,7 @@ config NEC_CMBVR4133
29 32
30config TANBAC_TB022X 33config TANBAC_TB022X
31 bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM" 34 bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
35 select CEVT_R4K
32 select DMA_NONCOHERENT 36 select DMA_NONCOHERENT
33 select IRQ_CPU 37 select IRQ_CPU
34 select HW_HAS_PCI 38 select HW_HAS_PCI
@@ -43,6 +47,7 @@ config TANBAC_TB022X
43 47
44config VICTOR_MPC30X 48config VICTOR_MPC30X
45 bool "Victor MP-C303/304" 49 bool "Victor MP-C303/304"
50 select CEVT_R4K
46 select DMA_NONCOHERENT 51 select DMA_NONCOHERENT
47 select IRQ_CPU 52 select IRQ_CPU
48 select HW_HAS_PCI 53 select HW_HAS_PCI
@@ -52,6 +57,7 @@ config VICTOR_MPC30X
52 57
53config ZAO_CAPCELLA 58config ZAO_CAPCELLA
54 bool "ZAO Networks Capcella" 59 bool "ZAO Networks Capcella"
60 select CEVT_R4K
55 select DMA_NONCOHERENT 61 select DMA_NONCOHERENT
56 select IRQ_CPU 62 select IRQ_CPU
57 select HW_HAS_PCI 63 select HW_HAS_PCI