aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:51:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:51:02 -0400
commit32c15bb978c0e6ff65b3012a6af5a14c899005ce (patch)
tree29b40c7dc083a1f0e3fb199963e88bb73c8b6ea7 /arch
parent53253383fde9e41bc07ad4d99f1c8b537fef71d6 (diff)
parent42f77542f4a1c104bb6fbba2e18e04e84415a96b (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: [MIPS] time: Move R4000 clockevent device code to separate configurable file [MIPS] time: Delete dead cycles_per_jiffy, mips_timer_ack and null_timer_ack [MIPS] IP32: Retire use of plat_timer_setup. [MIPS] Jazz: Retire use of plat_timer_setup. [MIPS] IP27: Convert to clock_event_device. [MIPS] JMR3927: Convert to clock_event_device. [MIPS] Always do the ARC64_TWIDDLE_PC thing.
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig24
-rw-r--r--arch/mips/au1000/Kconfig1
-rw-r--r--arch/mips/jazz/irq.c6
-rw-r--r--arch/mips/jazz/setup.c8
-rw-r--r--arch/mips/jmr3927/rbhma3100/setup.c66
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/cevt-r4k.c272
-rw-r--r--arch/mips/kernel/head.S16
-rw-r--r--arch/mips/kernel/time.c262
-rw-r--r--arch/mips/kernel/traps.c11
-rw-r--r--arch/mips/pmc-sierra/Kconfig2
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c5
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c155
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c6
-rw-r--r--arch/mips/vr41xx/Kconfig6
15 files changed, 469 insertions, 373 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 235d4514e0a9..cb027580cd1d 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 a23d4154da01..b36cec58a9a8 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/jazz/irq.c b/arch/mips/jazz/irq.c
index 835b056cea36..ae25b480723e 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -4,7 +4,7 @@
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 1992 Linus Torvalds 6 * Copyright (C) 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2001, 2003 Ralf Baechle 7 * Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle
8 */ 8 */
9#include <linux/clockchips.h> 9#include <linux/clockchips.h>
10#include <linux/init.h> 10#include <linux/init.h>
@@ -13,6 +13,7 @@
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14 14
15#include <asm/irq_cpu.h> 15#include <asm/irq_cpu.h>
16#include <asm/i8253.h>
16#include <asm/i8259.h> 17#include <asm/i8259.h>
17#include <asm/io.h> 18#include <asm/io.h>
18#include <asm/jazz.h> 19#include <asm/jazz.h>
@@ -136,7 +137,7 @@ static struct irqaction r4030_timer_irqaction = {
136 .name = "timer", 137 .name = "timer",
137}; 138};
138 139
139void __init plat_timer_setup(struct irqaction *ignored) 140void __init plat_time_init(void)
140{ 141{
141 struct irqaction *irq = &r4030_timer_irqaction; 142 struct irqaction *irq = &r4030_timer_irqaction;
142 143
@@ -152,4 +153,5 @@ void __init plat_timer_setup(struct irqaction *ignored)
152 setup_irq(JAZZ_TIMER_IRQ, irq); 153 setup_irq(JAZZ_TIMER_IRQ, irq);
153 154
154 clockevents_register_device(&r4030_clockevent); 155 clockevents_register_device(&r4030_clockevent);
156 setup_pit_timer();
155} 157}
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index cfc7dce78dab..a7857973ca03 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 1996, 1997, 1998, 2001 by Ralf Baechle 8 * Copyright (C) 1996, 1997, 1998, 2001, 07 by Ralf Baechle
9 * Copyright (C) 2001 MIPS Technologies, Inc. 9 * Copyright (C) 2001 MIPS Technologies, Inc.
10 * Copyright (C) 2007 by Thomas Bogendoerfer 10 * Copyright (C) 2007 by Thomas Bogendoerfer
11 */ 11 */
@@ -25,7 +25,6 @@
25#include <linux/serial_8250.h> 25#include <linux/serial_8250.h>
26 26
27#include <asm/bootinfo.h> 27#include <asm/bootinfo.h>
28#include <asm/i8253.h>
29#include <asm/irq.h> 28#include <asm/irq.h>
30#include <asm/jazz.h> 29#include <asm/jazz.h>
31#include <asm/jazzdma.h> 30#include <asm/jazzdma.h>
@@ -64,11 +63,6 @@ static struct resource jazz_io_resources[] = {
64 } 63 }
65}; 64};
66 65
67void __init plat_time_init(void)
68{
69 setup_pit_timer();
70}
71
72void __init plat_mem_setup(void) 66void __init plat_mem_setup(void)
73{ 67{
74 int i; 68 int i;
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 0c7aee1682cd..edb9e59248ec 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -1,15 +1,4 @@
1/*********************************************************************** 1/*
2 *
3 * Copyright 2001 MontaVista Software Inc.
4 * Author: MontaVista Software, Inc.
5 * ahennessy@mvista.com
6 *
7 * Based on arch/mips/ddb5xxx/ddb5477/setup.c
8 *
9 * Setup file for JMR3927.
10 *
11 * Copyright (C) 2000-2001 Toshiba Corporation
12 *
13 * This program is free software; you can redistribute it and/or modify it 2 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the 3 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your 4 * Free Software Foundation; either version 2 of the License, or (at your
@@ -30,9 +19,15 @@
30 * with this program; if not, write to the Free Software Foundation, Inc., 19 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 * 21 *
33 *********************************************************************** 22 * Copyright 2001 MontaVista Software Inc.
23 * Author: MontaVista Software, Inc.
24 * ahennessy@mvista.com
25 *
26 * Copyright (C) 2000-2001 Toshiba Corporation
27 * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
34 */ 28 */
35 29
30#include <linux/clockchips.h>
36#include <linux/init.h> 31#include <linux/init.h>
37#include <linux/kernel.h> 32#include <linux/kernel.h>
38#include <linux/kdev_t.h> 33#include <linux/kdev_t.h>
@@ -104,27 +99,60 @@ static cycle_t jmr3927_hpt_read(void)
104 return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; 99 return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr;
105} 100}
106 101
107static void jmr3927_timer_ack(void) 102static void jmr3927_set_mode(enum clock_event_mode mode,
103 struct clock_event_device *evt)
104{
105 /* Nothing to do here */
106}
107
108struct clock_event_device jmr3927_clock_event_device = {
109 .name = "MIPS",
110 .features = CLOCK_EVT_FEAT_PERIODIC,
111 .shift = 32,
112 .rating = 300,
113 .cpumask = CPU_MASK_CPU0,
114 .irq = JMR3927_IRQ_TICK,
115 .set_mode = jmr3927_set_mode,
116};
117
118static irqreturn_t jmr3927_timer_interrupt(int irq, void *dev_id)
108{ 119{
120 struct clock_event_device *cd = &jmr3927_clock_event_device;
121
109 jmr3927_tmrptr->tisr = 0; /* ack interrupt */ 122 jmr3927_tmrptr->tisr = 0; /* ack interrupt */
123
124 cd->event_handler(cd);
125
126 return IRQ_HANDLED;
110} 127}
111 128
129static struct irqaction jmr3927_timer_irqaction = {
130 .handler = jmr3927_timer_interrupt,
131 .flags = IRQF_DISABLED | IRQF_PERCPU,
132 .name = "jmr3927-timer",
133};
134
112void __init plat_time_init(void) 135void __init plat_time_init(void)
113{ 136{
137 struct clock_event_device *cd;
138
114 clocksource_mips.read = jmr3927_hpt_read; 139 clocksource_mips.read = jmr3927_hpt_read;
115 mips_timer_ack = jmr3927_timer_ack;
116 mips_hpt_frequency = JMR3927_TIMER_CLK; 140 mips_hpt_frequency = JMR3927_TIMER_CLK;
117}
118 141
119void __init plat_timer_setup(struct irqaction *irq)
120{
121 jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; 142 jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ;
122 jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; 143 jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE;
123 jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; 144 jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD;
124 jmr3927_tmrptr->tcr = 145 jmr3927_tmrptr->tcr =
125 TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL; 146 TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL;
126 147
127 setup_irq(JMR3927_IRQ_TICK, irq); 148 cd = &jmr3927_clock_event_device;
149 /* Calculate the min / max delta */
150 cd->mult = div_sc((unsigned long) JMR3927_IMCLK, NSEC_PER_SEC, 32);
151 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
152 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
153 clockevents_register_device(cd);
154
155 setup_irq(JMR3927_IRQ_TICK, &jmr3927_timer_irqaction);
128} 156}
129 157
130#define DO_WRITE_THROUGH 158#define DO_WRITE_THROUGH
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 95a356ef3910..a3afa39faae5 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 000000000000..08b84d476c87
--- /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/head.S b/arch/mips/kernel/head.S
index bf164a562acb..236768731063 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -27,16 +27,6 @@
27 27
28#include <kernel-entry-init.h> 28#include <kernel-entry-init.h>
29 29
30 .macro ARC64_TWIDDLE_PC
31#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
32 /* We get launched at a XKPHYS address but the kernel is linked to
33 run at a KSEG0 address, so jump there. */
34 PTR_LA t0, \@f
35 jr t0
36\@:
37#endif
38 .endm
39
40 /* 30 /*
41 * inputs are the text nasid in t1, data nasid in t2. 31 * inputs are the text nasid in t1, data nasid in t2.
42 */ 32 */
@@ -157,7 +147,11 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
157 147
158 setup_c0_status_pri 148 setup_c0_status_pri
159 149
160 ARC64_TWIDDLE_PC 150 /* We might not get launched at the address the kernel is linked to,
151 so we jump there. */
152 PTR_LA t0, 0f
153 jr t0
1540:
161 155
162#ifdef CONFIG_MIPS_MT_SMTC 156#ifdef CONFIG_MIPS_MT_SMTC
163 /* 157 /*
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e4b5e647b142..ea7cfe766a8e 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -72,14 +72,6 @@ int update_persistent_clock(struct timespec now)
72 return rtc_mips_set_mmss(now.tv_sec); 72 return rtc_mips_set_mmss(now.tv_sec);
73} 73}
74 74
75/* how many counter cycles in a jiffy */
76static unsigned long cycles_per_jiffy __read_mostly;
77
78/*
79 * Null timer ack for systems not needing one (e.g. i8254).
80 */
81static void null_timer_ack(void) { /* nothing */ }
82
83/* 75/*
84 * Null high precision timer functions for systems lacking one. 76 * Null high precision timer functions for systems lacking one.
85 */ 77 */
@@ -89,14 +81,6 @@ static cycle_t null_hpt_read(void)
89} 81}
90 82
91/* 83/*
92 * Timer ack for an R4k-compatible timer of a known frequency.
93 */
94static void c0_timer_ack(void)
95{
96 write_c0_compare(read_c0_compare());
97}
98
99/*
100 * High precision timer functions for a R4k-compatible timer. 84 * High precision timer functions for a R4k-compatible timer.
101 */ 85 */
102static cycle_t c0_hpt_read(void) 86static cycle_t c0_hpt_read(void)
@@ -105,7 +89,6 @@ static cycle_t c0_hpt_read(void)
105} 89}
106 90
107int (*mips_timer_state)(void); 91int (*mips_timer_state)(void);
108void (*mips_timer_ack)(void);
109 92
110/* 93/*
111 * local_timer_interrupt() does profiling and process accounting 94 * local_timer_interrupt() does profiling and process accounting
@@ -135,35 +118,6 @@ int (*perf_irq)(void) = null_perf_irq;
135EXPORT_SYMBOL(perf_irq); 118EXPORT_SYMBOL(perf_irq);
136 119
137/* 120/*
138 * Timer interrupt
139 */
140int cp0_compare_irq;
141
142/*
143 * Performance counter IRQ or -1 if shared with timer
144 */
145int cp0_perfcount_irq;
146EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
147
148/*
149 * Possibly handle a performance counter interrupt.
150 * Return true if the timer interrupt should not be checked
151 */
152static inline int handle_perf_irq(int r2)
153{
154 /*
155 * The performance counter overflow interrupt may be shared with the
156 * timer interrupt (cp0_perfcount_irq < 0). If it is and a
157 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
158 * and we can't reliably determine if a counter interrupt has also
159 * happened (!r2) then don't check for a timer interrupt.
160 */
161 return (cp0_perfcount_irq < 0) &&
162 perf_irq() == IRQ_HANDLED &&
163 !r2;
164}
165
166/*
167 * time_init() - it does the following things. 121 * time_init() - it does the following things.
168 * 122 *
169 * 1) plat_time_init() - 123 * 1) plat_time_init() -
@@ -228,84 +182,6 @@ struct clocksource clocksource_mips = {
228 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 182 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
229}; 183};
230 184
231static int mips_next_event(unsigned long delta,
232 struct clock_event_device *evt)
233{
234 unsigned int cnt;
235 int res;
236
237#ifdef CONFIG_MIPS_MT_SMTC
238 {
239 unsigned long flags, vpflags;
240 local_irq_save(flags);
241 vpflags = dvpe();
242#endif
243 cnt = read_c0_count();
244 cnt += delta;
245 write_c0_compare(cnt);
246 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0;
247#ifdef CONFIG_MIPS_MT_SMTC
248 evpe(vpflags);
249 local_irq_restore(flags);
250 }
251#endif
252 return res;
253}
254
255static void mips_set_mode(enum clock_event_mode mode,
256 struct clock_event_device *evt)
257{
258 /* Nothing to do ... */
259}
260
261static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
262static int cp0_timer_irq_installed;
263
264static irqreturn_t timer_interrupt(int irq, void *dev_id)
265{
266 const int r2 = cpu_has_mips_r2;
267 struct clock_event_device *cd;
268 int cpu = smp_processor_id();
269
270 /*
271 * Suckage alert:
272 * Before R2 of the architecture there was no way to see if a
273 * performance counter interrupt was pending, so we have to run
274 * the performance counter interrupt handler anyway.
275 */
276 if (handle_perf_irq(r2))
277 goto out;
278
279 /*
280 * The same applies to performance counter interrupts. But with the
281 * above we now know that the reason we got here must be a timer
282 * interrupt. Being the paranoiacs we are we check anyway.
283 */
284 if (!r2 || (read_c0_cause() & (1 << 30))) {
285 c0_timer_ack();
286#ifdef CONFIG_MIPS_MT_SMTC
287 if (cpu_data[cpu].vpe_id)
288 goto out;
289 cpu = 0;
290#endif
291 cd = &per_cpu(mips_clockevent_device, cpu);
292 cd->event_handler(cd);
293 }
294
295out:
296 return IRQ_HANDLED;
297}
298
299static struct irqaction timer_irqaction = {
300 .handler = timer_interrupt,
301#ifdef CONFIG_MIPS_MT_SMTC
302 .flags = IRQF_DISABLED,
303#else
304 .flags = IRQF_DISABLED | IRQF_PERCPU,
305#endif
306 .name = "timer",
307};
308
309static void __init init_mips_clocksource(void) 185static void __init init_mips_clocksource(void)
310{ 186{
311 u64 temp; 187 u64 temp;
@@ -345,8 +221,6 @@ static void smtc_set_mode(enum clock_event_mode mode,
345{ 221{
346} 222}
347 223
348int dummycnt[NR_CPUS];
349
350static void mips_broadcast(cpumask_t mask) 224static void mips_broadcast(cpumask_t mask)
351{ 225{
352 unsigned int cpu; 226 unsigned int cpu;
@@ -387,113 +261,6 @@ static void setup_smtc_dummy_clockevent_device(void)
387} 261}
388#endif 262#endif
389 263
390static void mips_event_handler(struct clock_event_device *dev)
391{
392}
393
394/*
395 * FIXME: This doesn't hold for the relocated E9000 compare interrupt.
396 */
397static int c0_compare_int_pending(void)
398{
399 return (read_c0_cause() >> cp0_compare_irq) & 0x100;
400}
401
402static int c0_compare_int_usable(void)
403{
404 const unsigned int delta = 0x300000;
405 unsigned int cnt;
406
407 /*
408 * IP7 already pending? Try to clear it by acking the timer.
409 */
410 if (c0_compare_int_pending()) {
411 write_c0_compare(read_c0_compare());
412 irq_disable_hazard();
413 if (c0_compare_int_pending())
414 return 0;
415 }
416
417 cnt = read_c0_count();
418 cnt += delta;
419 write_c0_compare(cnt);
420
421 while ((long)(read_c0_count() - cnt) <= 0)
422 ; /* Wait for expiry */
423
424 if (!c0_compare_int_pending())
425 return 0;
426
427 write_c0_compare(read_c0_compare());
428 irq_disable_hazard();
429 if (c0_compare_int_pending())
430 return 0;
431
432 /*
433 * Feels like a real count / compare timer.
434 */
435 return 1;
436}
437
438void __cpuinit mips_clockevent_init(void)
439{
440 uint64_t mips_freq = mips_hpt_frequency;
441 unsigned int cpu = smp_processor_id();
442 struct clock_event_device *cd;
443 unsigned int irq = MIPS_CPU_IRQ_BASE + 7;
444
445 if (!cpu_has_counter)
446 return;
447
448#ifdef CONFIG_MIPS_MT_SMTC
449 setup_smtc_dummy_clockevent_device();
450
451 /*
452 * On SMTC we only register VPE0's compare interrupt as clockevent
453 * device.
454 */
455 if (cpu)
456 return;
457#endif
458
459 if (!c0_compare_int_usable())
460 return;
461
462 cd = &per_cpu(mips_clockevent_device, cpu);
463
464 cd->name = "MIPS";
465 cd->features = CLOCK_EVT_FEAT_ONESHOT;
466
467 /* Calculate the min / max delta */
468 cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
469 cd->shift = 32;
470 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
471 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
472
473 cd->rating = 300;
474 cd->irq = irq;
475#ifdef CONFIG_MIPS_MT_SMTC
476 cd->cpumask = CPU_MASK_ALL;
477#else
478 cd->cpumask = cpumask_of_cpu(cpu);
479#endif
480 cd->set_next_event = mips_next_event;
481 cd->set_mode = mips_set_mode;
482 cd->event_handler = mips_event_handler;
483
484 clockevents_register_device(cd);
485
486 if (!cp0_timer_irq_installed) {
487#ifdef CONFIG_MIPS_MT_SMTC
488#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
489 setup_irq_smtc(irq, &timer_irqaction, CPUCTR_IMASKBIT);
490#else
491 setup_irq(irq, &timer_irqaction);
492#endif /* CONFIG_MIPS_MT_SMTC */
493 cp0_timer_irq_installed = 1;
494 }
495}
496
497void __init time_init(void) 264void __init time_init(void)
498{ 265{
499 plat_time_init(); 266 plat_time_init();
@@ -512,14 +279,6 @@ void __init time_init(void)
512 if (!clocksource_mips.read) { 279 if (!clocksource_mips.read) {
513 /* No external high precision timer -- use R4k. */ 280 /* No external high precision timer -- use R4k. */
514 clocksource_mips.read = c0_hpt_read; 281 clocksource_mips.read = c0_hpt_read;
515
516 if (!mips_timer_state) {
517 /* No external timer interrupt -- use R4k. */
518 mips_timer_ack = c0_timer_ack;
519 /* Calculate cache parameters. */
520 cycles_per_jiffy =
521 (mips_hpt_frequency + HZ / 2) / HZ;
522 }
523 } 282 }
524 if (!mips_hpt_frequency) 283 if (!mips_hpt_frequency)
525 mips_hpt_frequency = calibrate_hpt(); 284 mips_hpt_frequency = calibrate_hpt();
@@ -528,29 +287,8 @@ void __init time_init(void)
528 printk("Using %u.%03u MHz high precision timer.\n", 287 printk("Using %u.%03u MHz high precision timer.\n",
529 ((mips_hpt_frequency + 500) / 1000) / 1000, 288 ((mips_hpt_frequency + 500) / 1000) / 1000,
530 ((mips_hpt_frequency + 500) / 1000) % 1000); 289 ((mips_hpt_frequency + 500) / 1000) % 1000);
531
532#ifdef CONFIG_IRQ_CPU
533 setup_irq(MIPS_CPU_IRQ_BASE + 7, &timer_irqaction);
534#endif
535 } 290 }
536 291
537 if (!mips_timer_ack)
538 /* No timer interrupt ack (e.g. i8254). */
539 mips_timer_ack = null_timer_ack;
540
541 /*
542 * Call board specific timer interrupt setup.
543 *
544 * this pointer must be setup in machine setup routine.
545 *
546 * Even if a machine chooses to use a low-level timer interrupt,
547 * it still needs to setup the timer_irqaction.
548 * In that case, it might be better to set timer_irqaction.handler
549 * to be NULL function so that we are sure the high-level code
550 * is not invoked accidentally.
551 */
552 plat_timer_setup(&timer_irqaction);
553
554 init_mips_clocksource(); 292 init_mips_clocksource();
555 mips_clockevent_init(); 293 mips_clockevent_init();
556} 294}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index bbf01b81a4ff..7b78d137259f 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 abbd0bbfabd7..6b293ce0935f 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/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 856649cf9f1e..1bb692a3b319 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -374,14 +374,13 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
374 return irq; 374 return irq;
375} 375}
376 376
377extern void ip27_rt_timer_interrupt(void);
378
379asmlinkage void plat_irq_dispatch(void) 377asmlinkage void plat_irq_dispatch(void)
380{ 378{
381 unsigned long pending = read_c0_cause() & read_c0_status(); 379 unsigned long pending = read_c0_cause() & read_c0_status();
380 extern unsigned int rt_timer_irq;
382 381
383 if (pending & CAUSEF_IP4) 382 if (pending & CAUSEF_IP4)
384 ip27_rt_timer_interrupt(); 383 do_IRQ(rt_timer_irq);
385 else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ 384 else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */
386 ip27_do_irq_mask0(); 385 ip27_do_irq_mask0();
387 else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ 386 else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index b7b3479b6bce..d467bf4f6c3f 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -3,6 +3,7 @@
3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc. 3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
4 */ 4 */
5#include <linux/bcd.h> 5#include <linux/bcd.h>
6#include <linux/clockchips.h>
6#include <linux/init.h> 7#include <linux/init.h>
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/sched.h> 9#include <linux/sched.h>
@@ -25,22 +26,8 @@
25#include <asm/sn/sn0/ip27.h> 26#include <asm/sn/sn0/ip27.h>
26#include <asm/sn/sn0/hub.h> 27#include <asm/sn/sn0/hub.h>
27 28
28/*
29 * This is a hack; we really need to figure these values out dynamically
30 *
31 * Since 800 ns works very well with various HUB frequencies, such as
32 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
33 *
34 * Ralf: which clock rate is used to feed the counter?
35 */
36#define NSEC_PER_CYCLE 800
37#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE)
38#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ)
39
40#define TICK_SIZE (tick_nsec / 1000) 29#define TICK_SIZE (tick_nsec / 1000)
41 30
42static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */
43
44#if 0 31#if 0
45static int set_rtc_mmss(unsigned long nowtime) 32static int set_rtc_mmss(unsigned long nowtime)
46{ 33{
@@ -86,36 +73,6 @@ static int set_rtc_mmss(unsigned long nowtime)
86} 73}
87#endif 74#endif
88 75
89static unsigned int rt_timer_irq;
90
91void ip27_rt_timer_interrupt(void)
92{
93 int cpu = smp_processor_id();
94 int cpuA = cputoslice(cpu) == 0;
95 unsigned int irq = rt_timer_irq;
96
97 irq_enter();
98 write_seqlock(&xtime_lock);
99
100again:
101 LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
102 ct_cur[cpu] += CYCLES_PER_JIFFY;
103 LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
104
105 if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
106 goto again;
107
108 kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */
109
110 if (cpu == 0)
111 do_timer(1);
112
113 update_process_times(user_mode(get_irq_regs()));
114
115 write_sequnlock(&xtime_lock);
116 irq_exit();
117}
118
119/* Includes for ioc3_init(). */ 76/* Includes for ioc3_init(). */
120#include <asm/sn/types.h> 77#include <asm/sn/types.h>
121#include <asm/sn/sn0/addrs.h> 78#include <asm/sn/sn0/addrs.h>
@@ -154,6 +111,46 @@ unsigned long read_persistent_clock(void)
154 return mktime(year, month, date, hour, min, sec); 111 return mktime(year, month, date, hour, min, sec);
155} 112}
156 113
114static int rt_set_next_event(unsigned long delta,
115 struct clock_event_device *evt)
116{
117 unsigned int cpu = smp_processor_id();
118 int slice = cputoslice(cpu) == 0;
119 unsigned long cnt;
120
121 cnt = LOCAL_HUB_L(PI_RT_COUNT);
122 cnt += delta;
123 LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt);
124
125 return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
126}
127
128static void rt_set_mode(enum clock_event_mode mode,
129 struct clock_event_device *evt)
130{
131 switch (mode) {
132 case CLOCK_EVT_MODE_PERIODIC:
133 /* The only mode supported */
134 break;
135
136 case CLOCK_EVT_MODE_UNUSED:
137 case CLOCK_EVT_MODE_SHUTDOWN:
138 case CLOCK_EVT_MODE_ONESHOT:
139 case CLOCK_EVT_MODE_RESUME:
140 /* Nothing to do */
141 break;
142 }
143}
144
145struct clock_event_device rt_clock_event_device = {
146 .name = "HUB-RT",
147 .features = CLOCK_EVT_FEAT_ONESHOT,
148
149 .rating = 300,
150 .set_next_event = rt_set_next_event,
151 .set_mode = rt_set_mode,
152};
153
157static void enable_rt_irq(unsigned int irq) 154static void enable_rt_irq(unsigned int irq)
158{ 155{
159} 156}
@@ -171,6 +168,20 @@ static struct irq_chip rt_irq_type = {
171 .eoi = enable_rt_irq, 168 .eoi = enable_rt_irq,
172}; 169};
173 170
171unsigned int rt_timer_irq;
172
173static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id)
174{
175 struct clock_event_device *cd = &rt_clock_event_device;
176 unsigned int cpu = smp_processor_id();
177 int slice = cputoslice(cpu) == 0;
178
179 LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
180 cd->event_handler(cd);
181
182 return IRQ_HANDLED;
183}
184
174static struct irqaction rt_irqaction = { 185static struct irqaction rt_irqaction = {
175 .handler = (irq_handler_t) ip27_rt_timer_interrupt, 186 .handler = (irq_handler_t) ip27_rt_timer_interrupt,
176 .flags = IRQF_DISABLED, 187 .flags = IRQF_DISABLED,
@@ -178,26 +189,43 @@ static struct irqaction rt_irqaction = {
178 .name = "timer" 189 .name = "timer"
179}; 190};
180 191
181void __init plat_timer_setup(struct irqaction *irq) 192/*
193 * This is a hack; we really need to figure these values out dynamically
194 *
195 * Since 800 ns works very well with various HUB frequencies, such as
196 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
197 *
198 * Ralf: which clock rate is used to feed the counter?
199 */
200#define NSEC_PER_CYCLE 800
201#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE)
202
203static void __init ip27_rt_clock_event_init(void)
182{ 204{
183 int irqno = allocate_irqno(); 205 struct clock_event_device *cd = &rt_clock_event_device;
206 unsigned int cpu = smp_processor_id();
207 int irq = allocate_irqno();
184 208
185 if (irqno < 0) 209 if (irq < 0)
186 panic("Can't allocate interrupt number for timer interrupt"); 210 panic("Can't allocate interrupt number for timer interrupt");
187 211
188 set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq); 212 rt_timer_irq = irq;
189 213
190 /* over-write the handler, we use our own way */ 214 cd->irq = irq,
191 irq->handler = no_action; 215 cd->cpumask = cpumask_of_cpu(cpu),
192 216
193 /* setup irqaction */
194 irq_desc[irqno].status |= IRQ_PER_CPU;
195
196 rt_timer_irq = irqno;
197 /* 217 /*
198 * Only needed to get /proc/interrupt to display timer irq stats 218 * Calculate the min / max delta
199 */ 219 */
200 setup_irq(irqno, &rt_irqaction); 220 cd->mult =
221 div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32);
222 cd->shift = 32;
223 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
224 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
225 clockevents_register_device(cd);
226
227 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
228 setup_irq(irq, &rt_irqaction);
201} 229}
202 230
203static cycle_t hub_rt_read(void) 231static cycle_t hub_rt_read(void)
@@ -206,7 +234,7 @@ static cycle_t hub_rt_read(void)
206} 234}
207 235
208struct clocksource ht_rt_clocksource = { 236struct clocksource ht_rt_clocksource = {
209 .name = "HUB", 237 .name = "HUB-RT",
210 .rating = 200, 238 .rating = 200,
211 .read = hub_rt_read, 239 .read = hub_rt_read,
212 .mask = CLOCKSOURCE_MASK(52), 240 .mask = CLOCKSOURCE_MASK(52),
@@ -214,11 +242,17 @@ struct clocksource ht_rt_clocksource = {
214 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 242 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
215}; 243};
216 244
217void __init plat_time_init(void) 245static void __init ip27_rt_clocksource_init(void)
218{ 246{
219 clocksource_register(&ht_rt_clocksource); 247 clocksource_register(&ht_rt_clocksource);
220} 248}
221 249
250void __init plat_time_init(void)
251{
252 ip27_rt_clock_event_init();
253 ip27_rt_clocksource_init();
254}
255
222void __init cpu_time_init(void) 256void __init cpu_time_init(void)
223{ 257{
224 lboard_t *board; 258 lboard_t *board;
@@ -248,17 +282,12 @@ void __init hub_rtc_init(cnodeid_t cnode)
248 * node and timeouts will not happen there. 282 * node and timeouts will not happen there.
249 */ 283 */
250 if (get_compact_nodeid() == cnode) { 284 if (get_compact_nodeid() == cnode) {
251 int cpu = smp_processor_id();
252 LOCAL_HUB_S(PI_RT_EN_A, 1); 285 LOCAL_HUB_S(PI_RT_EN_A, 1);
253 LOCAL_HUB_S(PI_RT_EN_B, 1); 286 LOCAL_HUB_S(PI_RT_EN_B, 1);
254 LOCAL_HUB_S(PI_PROF_EN_A, 0); 287 LOCAL_HUB_S(PI_PROF_EN_A, 0);
255 LOCAL_HUB_S(PI_PROF_EN_B, 0); 288 LOCAL_HUB_S(PI_PROF_EN_B, 0);
256 ct_cur[cpu] = CYCLES_PER_JIFFY;
257 LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
258 LOCAL_HUB_S(PI_RT_COUNT, 0); 289 LOCAL_HUB_S(PI_RT_COUNT, 0);
259 LOCAL_HUB_S(PI_RT_PEND_A, 0); 290 LOCAL_HUB_S(PI_RT_PEND_A, 0);
260 LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
261 LOCAL_HUB_S(PI_RT_COUNT, 0);
262 LOCAL_HUB_S(PI_RT_PEND_B, 0); 291 LOCAL_HUB_S(PI_RT_PEND_B, 0);
263 } 292 }
264} 293}
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index fc75bfcb0c0e..1024bf40bd9e 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -80,12 +80,6 @@ void __init plat_time_init(void)
80 printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000); 80 printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000);
81} 81}
82 82
83void __init plat_timer_setup(struct irqaction *irq)
84{
85 irq->handler = no_action;
86 setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
87}
88
89void __init plat_mem_setup(void) 83void __init plat_mem_setup(void)
90{ 84{
91 board_be_init = ip32_be_init; 85 board_be_init = ip32_be_init;
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index 8f4d3e74c230..eeb089f20c0d 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