diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-10-11 18:46:09 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-10-11 18:46:09 -0400 |
commit | 7bcf7717b6a047c272410d0cd00213185fe6b99d (patch) | |
tree | 81c5d6bbc2130815713e22bb5408ea80b6e1c499 | |
parent | 91a2fcc88634663e9e13dcdfad0e4a860e64aeee (diff) |
[MIPS] Implement clockevents for R4000-style cp0 count/compare interrupt
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/Kconfig | 7 | ||||
-rw-r--r-- | arch/mips/au1000/common/irq.c | 2 | ||||
-rw-r--r-- | arch/mips/configs/bigsur_defconfig | 1 | ||||
-rw-r--r-- | arch/mips/configs/sb1250-swarm_defconfig | 1 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 3 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/time.c | 256 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/time.c | 26 | ||||
-rw-r--r-- | arch/mips/qemu/q-irq.c | 4 | ||||
-rw-r--r-- | arch/mips/qemu/q-setup.c | 1 | ||||
-rw-r--r-- | arch/mips/sgi-ip22/ip22-int.c | 2 | ||||
-rw-r--r-- | arch/mips/sgi-ip32/ip32-irq.c | 2 | ||||
-rw-r--r-- | arch/mips/sibyte/Kconfig | 12 | ||||
-rw-r--r-- | arch/mips/sibyte/bcm1480/irq.c | 13 | ||||
-rw-r--r-- | arch/mips/sibyte/sb1250/irq.c | 50 | ||||
-rw-r--r-- | arch/mips/sibyte/sb1250/time.c | 12 | ||||
-rw-r--r-- | include/asm-mips/mach-ip27/irq.h | 2 | ||||
-rw-r--r-- | include/asm-mips/qemu.h | 2 | ||||
-rw-r--r-- | include/asm-mips/time.h | 10 |
20 files changed, 210 insertions, 200 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0cd0f835b13d..ecce3aab1981 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -335,6 +335,7 @@ config QEMU | |||
335 | select GENERIC_ISA_DMA | 335 | select GENERIC_ISA_DMA |
336 | select HAVE_STD_PC_SERIAL_PORT | 336 | select HAVE_STD_PC_SERIAL_PORT |
337 | select I8259 | 337 | select I8259 |
338 | select IRQ_CPU | ||
338 | select ISA | 339 | select ISA |
339 | select PCSPEAKER | 340 | select PCSPEAKER |
340 | select SWAP_IO_SPACE | 341 | select SWAP_IO_SPACE |
@@ -667,6 +668,10 @@ config GENERIC_CALIBRATE_DELAY | |||
667 | bool | 668 | bool |
668 | default y | 669 | default y |
669 | 670 | ||
671 | config GENERIC_CLOCKEVENTS | ||
672 | bool | ||
673 | default y | ||
674 | |||
670 | config GENERIC_TIME | 675 | config GENERIC_TIME |
671 | bool | 676 | bool |
672 | default y | 677 | default y |
@@ -901,6 +906,8 @@ config BOOT_ELF64 | |||
901 | 906 | ||
902 | menu "CPU selection" | 907 | menu "CPU selection" |
903 | 908 | ||
909 | source "kernel/time/Kconfig" | ||
910 | |||
904 | choice | 911 | choice |
905 | prompt "CPU type" | 912 | prompt "CPU type" |
906 | default CPU_R4X00 | 913 | default CPU_R4X00 |
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 47949d6f2c10..a6640b998c6e 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c | |||
@@ -633,7 +633,7 @@ asmlinkage void plat_irq_dispatch(void) | |||
633 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; | 633 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; |
634 | 634 | ||
635 | if (pending & CAUSEF_IP7) | 635 | if (pending & CAUSEF_IP7) |
636 | ll_timer_interrupt(63); | 636 | do_IRQ(63); |
637 | else if (pending & CAUSEF_IP2) | 637 | else if (pending & CAUSEF_IP2) |
638 | intc0_req0_irqdispatch(); | 638 | intc0_req0_irqdispatch(); |
639 | else if (pending & CAUSEF_IP3) | 639 | else if (pending & CAUSEF_IP3) |
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index 700a3a2d688e..30f3e9a2466f 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig | |||
@@ -69,7 +69,6 @@ CONFIG_SIBYTE_SB1xxx_SOC=y | |||
69 | CONFIG_SIBYTE_CFE=y | 69 | CONFIG_SIBYTE_CFE=y |
70 | # CONFIG_SIBYTE_CFE_CONSOLE is not set | 70 | # CONFIG_SIBYTE_CFE_CONSOLE is not set |
71 | # CONFIG_SIBYTE_BUS_WATCHER is not set | 71 | # CONFIG_SIBYTE_BUS_WATCHER is not set |
72 | # CONFIG_SIBYTE_SB1250_PROF is not set | ||
73 | # CONFIG_SIBYTE_TBPROF is not set | 72 | # CONFIG_SIBYTE_TBPROF is not set |
74 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 73 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
75 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | 74 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set |
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 93f9e8331ad7..3d1b6281d887 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig | |||
@@ -70,7 +70,6 @@ CONFIG_SIBYTE_HAS_LDT=y | |||
70 | CONFIG_SIBYTE_CFE=y | 70 | CONFIG_SIBYTE_CFE=y |
71 | # CONFIG_SIBYTE_CFE_CONSOLE is not set | 71 | # CONFIG_SIBYTE_CFE_CONSOLE is not set |
72 | # CONFIG_SIBYTE_BUS_WATCHER is not set | 72 | # CONFIG_SIBYTE_BUS_WATCHER is not set |
73 | # CONFIG_SIBYTE_SB1250_PROF is not set | ||
74 | # CONFIG_SIBYTE_TBPROF is not set | 73 | # CONFIG_SIBYTE_TBPROF is not set |
75 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 74 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
76 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | 75 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index aadd2cd5778c..f99bb4085430 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/tick.h> | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
16 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
@@ -52,6 +53,7 @@ void __noreturn cpu_idle(void) | |||
52 | { | 53 | { |
53 | /* endless idle loop with no priority at all */ | 54 | /* endless idle loop with no priority at all */ |
54 | while (1) { | 55 | while (1) { |
56 | tick_nohz_stop_sched_tick(); | ||
55 | while (!need_resched()) { | 57 | while (!need_resched()) { |
56 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG | 58 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
57 | extern void smtc_idle_loop_hook(void); | 59 | extern void smtc_idle_loop_hook(void); |
@@ -61,6 +63,7 @@ void __noreturn cpu_idle(void) | |||
61 | if (cpu_wait) | 63 | if (cpu_wait) |
62 | (*cpu_wait)(); | 64 | (*cpu_wait)(); |
63 | } | 65 | } |
66 | tick_nohz_restart_sched_tick(); | ||
64 | preempt_enable_no_resched(); | 67 | preempt_enable_no_resched(); |
65 | schedule(); | 68 | schedule(); |
66 | preempt_disable(); | 69 | preempt_disable(); |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 73b0dab02668..500a7ec2880f 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | #include <asm/mmu_context.h> | 39 | #include <asm/mmu_context.h> |
40 | #include <asm/smp.h> | 40 | #include <asm/smp.h> |
41 | #include <asm/time.h> | ||
41 | 42 | ||
42 | #ifdef CONFIG_MIPS_MT_SMTC | 43 | #ifdef CONFIG_MIPS_MT_SMTC |
43 | #include <asm/mipsmtregs.h> | 44 | #include <asm/mipsmtregs.h> |
@@ -70,6 +71,7 @@ asmlinkage __cpuinit void start_secondary(void) | |||
70 | cpu_probe(); | 71 | cpu_probe(); |
71 | cpu_report(); | 72 | cpu_report(); |
72 | per_cpu_trap_init(); | 73 | per_cpu_trap_init(); |
74 | mips_clockevent_init(); | ||
73 | prom_init_secondary(); | 75 | prom_init_secondary(); |
74 | 76 | ||
75 | /* | 77 | /* |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a7afbf2c9710..137183bba54f 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -867,7 +867,7 @@ void ipi_decode(struct smtc_ipi *pipi) | |||
867 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG | 867 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
868 | clock_hang_reported[dest_copy] = 0; | 868 | clock_hang_reported[dest_copy] = 0; |
869 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ | 869 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
870 | local_timer_interrupt(0); | 870 | local_timer_interrupt(0, NULL); |
871 | irq_exit(); | 871 | irq_exit(); |
872 | break; | 872 | break; |
873 | case LINUX_SMP_IPI: | 873 | case LINUX_SMP_IPI: |
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index d23e6825e988..35988847c98a 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * option) any later version. | 12 | * option) any later version. |
13 | */ | 13 | */ |
14 | #include <linux/clockchips.h> | ||
14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -34,6 +35,8 @@ | |||
34 | #include <asm/sections.h> | 35 | #include <asm/sections.h> |
35 | #include <asm/time.h> | 36 | #include <asm/time.h> |
36 | 37 | ||
38 | #include <irq.h> | ||
39 | |||
37 | /* | 40 | /* |
38 | * The integer part of the number of usecs per jiffy is taken from tick, | 41 | * The integer part of the number of usecs per jiffy is taken from tick, |
39 | * but the fractional part is not recorded, so we calculate it using the | 42 | * but the fractional part is not recorded, so we calculate it using the |
@@ -70,10 +73,6 @@ int update_persistent_clock(struct timespec now) | |||
70 | /* how many counter cycles in a jiffy */ | 73 | /* how many counter cycles in a jiffy */ |
71 | static unsigned long cycles_per_jiffy __read_mostly; | 74 | static unsigned long cycles_per_jiffy __read_mostly; |
72 | 75 | ||
73 | /* expirelo is the count value for next CPU timer interrupt */ | ||
74 | static unsigned int expirelo; | ||
75 | |||
76 | |||
77 | /* | 76 | /* |
78 | * Null timer ack for systems not needing one (e.g. i8254). | 77 | * Null timer ack for systems not needing one (e.g. i8254). |
79 | */ | 78 | */ |
@@ -92,18 +91,7 @@ static cycle_t null_hpt_read(void) | |||
92 | */ | 91 | */ |
93 | static void c0_timer_ack(void) | 92 | static void c0_timer_ack(void) |
94 | { | 93 | { |
95 | unsigned int count; | 94 | write_c0_compare(read_c0_compare()); |
96 | |||
97 | /* Ack this timer interrupt and set the next one. */ | ||
98 | expirelo += cycles_per_jiffy; | ||
99 | write_c0_compare(expirelo); | ||
100 | |||
101 | /* Check to see if we have missed any timer interrupts. */ | ||
102 | while (((count = read_c0_count()) - expirelo) < 0x7fffffff) { | ||
103 | /* missed_timer_count++; */ | ||
104 | expirelo = count + cycles_per_jiffy; | ||
105 | write_c0_compare(expirelo); | ||
106 | } | ||
107 | } | 95 | } |
108 | 96 | ||
109 | /* | 97 | /* |
@@ -114,13 +102,6 @@ static cycle_t c0_hpt_read(void) | |||
114 | return read_c0_count(); | 102 | return read_c0_count(); |
115 | } | 103 | } |
116 | 104 | ||
117 | /* For use both as a high precision timer and an interrupt source. */ | ||
118 | static void __init c0_hpt_timer_init(void) | ||
119 | { | ||
120 | expirelo = read_c0_count() + cycles_per_jiffy; | ||
121 | write_c0_compare(expirelo); | ||
122 | } | ||
123 | |||
124 | int (*mips_timer_state)(void); | 105 | int (*mips_timer_state)(void); |
125 | void (*mips_timer_ack)(void); | 106 | void (*mips_timer_ack)(void); |
126 | 107 | ||
@@ -140,35 +121,6 @@ void local_timer_interrupt(int irq, void *dev_id) | |||
140 | update_process_times(user_mode(get_irq_regs())); | 121 | update_process_times(user_mode(get_irq_regs())); |
141 | } | 122 | } |
142 | 123 | ||
143 | /* | ||
144 | * High-level timer interrupt service routines. This function | ||
145 | * is set as irqaction->handler and is invoked through do_IRQ. | ||
146 | */ | ||
147 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
148 | { | ||
149 | write_seqlock(&xtime_lock); | ||
150 | |||
151 | mips_timer_ack(); | ||
152 | |||
153 | /* | ||
154 | * call the generic timer interrupt handling | ||
155 | */ | ||
156 | do_timer(1); | ||
157 | |||
158 | write_sequnlock(&xtime_lock); | ||
159 | |||
160 | /* | ||
161 | * In UP mode, we call local_timer_interrupt() to do profiling | ||
162 | * and process accouting. | ||
163 | * | ||
164 | * In SMP mode, local_timer_interrupt() is invoked by appropriate | ||
165 | * low-level local timer interrupt handler. | ||
166 | */ | ||
167 | local_timer_interrupt(irq, dev_id); | ||
168 | |||
169 | return IRQ_HANDLED; | ||
170 | } | ||
171 | |||
172 | int null_perf_irq(void) | 124 | int null_perf_irq(void) |
173 | { | 125 | { |
174 | return 0; | 126 | return 0; |
@@ -209,81 +161,6 @@ static inline int handle_perf_irq (int r2) | |||
209 | !r2; | 161 | !r2; |
210 | } | 162 | } |
211 | 163 | ||
212 | void ll_timer_interrupt(int irq, void *dev_id) | ||
213 | { | ||
214 | int cpu = smp_processor_id(); | ||
215 | |||
216 | #ifdef CONFIG_MIPS_MT_SMTC | ||
217 | /* | ||
218 | * In an SMTC system, one Count/Compare set exists per VPE. | ||
219 | * Which TC within a VPE gets the interrupt is essentially | ||
220 | * random - we only know that it shouldn't be one with | ||
221 | * IXMT set. Whichever TC gets the interrupt needs to | ||
222 | * send special interprocessor interrupts to the other | ||
223 | * TCs to make sure that they schedule, etc. | ||
224 | * | ||
225 | * That code is specific to the SMTC kernel, not to | ||
226 | * the a particular platform, so it's invoked from | ||
227 | * the general MIPS timer_interrupt routine. | ||
228 | */ | ||
229 | |||
230 | /* | ||
231 | * We could be here due to timer interrupt, | ||
232 | * perf counter overflow, or both. | ||
233 | */ | ||
234 | (void) handle_perf_irq(1); | ||
235 | |||
236 | if (read_c0_cause() & (1 << 30)) { | ||
237 | /* | ||
238 | * There are things we only want to do once per tick | ||
239 | * in an "MP" system. One TC of each VPE will take | ||
240 | * the actual timer interrupt. The others will get | ||
241 | * timer broadcast IPIs. We use whoever it is that takes | ||
242 | * the tick on VPE 0 to run the full timer_interrupt(). | ||
243 | */ | ||
244 | if (cpu_data[cpu].vpe_id == 0) { | ||
245 | timer_interrupt(irq, NULL); | ||
246 | } else { | ||
247 | write_c0_compare(read_c0_count() + | ||
248 | (mips_hpt_frequency/HZ)); | ||
249 | local_timer_interrupt(irq, dev_id); | ||
250 | } | ||
251 | smtc_timer_broadcast(cpu_data[cpu].vpe_id); | ||
252 | } | ||
253 | #else /* CONFIG_MIPS_MT_SMTC */ | ||
254 | int r2 = cpu_has_mips_r2; | ||
255 | |||
256 | if (handle_perf_irq(r2)) | ||
257 | return; | ||
258 | |||
259 | if (r2 && ((read_c0_cause() & (1 << 30)) == 0)) | ||
260 | return; | ||
261 | |||
262 | if (cpu == 0) { | ||
263 | /* | ||
264 | * CPU 0 handles the global timer interrupt job and process | ||
265 | * accounting resets count/compare registers to trigger next | ||
266 | * timer int. | ||
267 | */ | ||
268 | timer_interrupt(irq, NULL); | ||
269 | } else { | ||
270 | /* Everyone else needs to reset the timer int here as | ||
271 | ll_local_timer_interrupt doesn't */ | ||
272 | /* | ||
273 | * FIXME: need to cope with counter underflow. | ||
274 | * More support needs to be added to kernel/time for | ||
275 | * counter/timer interrupts on multiple CPU's | ||
276 | */ | ||
277 | write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ)); | ||
278 | |||
279 | /* | ||
280 | * Other CPUs should do profiling and process accounting | ||
281 | */ | ||
282 | local_timer_interrupt(irq, dev_id); | ||
283 | } | ||
284 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
285 | } | ||
286 | |||
287 | /* | 164 | /* |
288 | * time_init() - it does the following things. | 165 | * time_init() - it does the following things. |
289 | * | 166 | * |
@@ -301,12 +178,6 @@ void ll_timer_interrupt(int irq, void *dev_id) | |||
301 | 178 | ||
302 | unsigned int mips_hpt_frequency; | 179 | unsigned int mips_hpt_frequency; |
303 | 180 | ||
304 | static struct irqaction timer_irqaction = { | ||
305 | .handler = timer_interrupt, | ||
306 | .flags = IRQF_DISABLED | IRQF_PERCPU, | ||
307 | .name = "timer", | ||
308 | }; | ||
309 | |||
310 | static unsigned int __init calibrate_hpt(void) | 181 | static unsigned int __init calibrate_hpt(void) |
311 | { | 182 | { |
312 | cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; | 183 | cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; |
@@ -355,6 +226,65 @@ struct clocksource clocksource_mips = { | |||
355 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 226 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
356 | }; | 227 | }; |
357 | 228 | ||
229 | static int mips_next_event(unsigned long delta, | ||
230 | struct clock_event_device *evt) | ||
231 | { | ||
232 | unsigned int cnt; | ||
233 | |||
234 | cnt = read_c0_count(); | ||
235 | cnt += delta; | ||
236 | write_c0_compare(cnt); | ||
237 | |||
238 | return ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; | ||
239 | } | ||
240 | |||
241 | static void mips_set_mode(enum clock_event_mode mode, | ||
242 | struct clock_event_device *evt) | ||
243 | { | ||
244 | /* Nothing to do ... */ | ||
245 | } | ||
246 | |||
247 | struct clock_event_device mips_clockevent; | ||
248 | |||
249 | static struct clock_event_device *global_cd[NR_CPUS]; | ||
250 | static int cp0_timer_irq_installed; | ||
251 | |||
252 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
253 | { | ||
254 | const int r2 = cpu_has_mips_r2; | ||
255 | struct clock_event_device *cd; | ||
256 | int cpu = smp_processor_id(); | ||
257 | |||
258 | /* | ||
259 | * Suckage alert: | ||
260 | * Before R2 of the architecture there was no way to see if a | ||
261 | * performance counter interrupt was pending, so we have to run | ||
262 | * the performance counter interrupt handler anyway. | ||
263 | */ | ||
264 | if (handle_perf_irq(r2)) | ||
265 | goto out; | ||
266 | |||
267 | /* | ||
268 | * The same applies to performance counter interrupts. But with the | ||
269 | * above we now know that the reason we got here must be a timer | ||
270 | * interrupt. Being the paranoiacs we are we check anyway. | ||
271 | */ | ||
272 | if (!r2 || (read_c0_cause() & (1 << 30))) { | ||
273 | c0_timer_ack(); | ||
274 | cd = global_cd[cpu]; | ||
275 | cd->event_handler(cd); | ||
276 | } | ||
277 | |||
278 | out: | ||
279 | return IRQ_HANDLED; | ||
280 | } | ||
281 | |||
282 | static struct irqaction timer_irqaction = { | ||
283 | .handler = timer_interrupt, | ||
284 | .flags = IRQF_DISABLED | IRQF_PERCPU, | ||
285 | .name = "timer", | ||
286 | }; | ||
287 | |||
358 | static void __init init_mips_clocksource(void) | 288 | static void __init init_mips_clocksource(void) |
359 | { | 289 | { |
360 | u64 temp; | 290 | u64 temp; |
@@ -382,6 +312,56 @@ void __init __weak plat_time_init(void) | |||
382 | { | 312 | { |
383 | } | 313 | } |
384 | 314 | ||
315 | void __init __weak plat_timer_setup(struct irqaction *irq) | ||
316 | { | ||
317 | } | ||
318 | |||
319 | void __cpuinit mips_clockevent_init(void) | ||
320 | { | ||
321 | uint64_t mips_freq = mips_hpt_frequency; | ||
322 | unsigned int cpu = smp_processor_id(); | ||
323 | struct clock_event_device *cd; | ||
324 | unsigned int irq = MIPS_CPU_IRQ_BASE + 7; | ||
325 | |||
326 | if (!cpu_has_counter) | ||
327 | return; | ||
328 | |||
329 | if (cpu == 0) | ||
330 | cd = &mips_clockevent; | ||
331 | else | ||
332 | cd = kzalloc(sizeof(*cd), GFP_ATOMIC); | ||
333 | if (!cd) | ||
334 | return; /* We're probably roadkill ... */ | ||
335 | |||
336 | cd->name = "MIPS"; | ||
337 | cd->features = CLOCK_EVT_FEAT_ONESHOT; | ||
338 | |||
339 | /* Calculate the min / max delta */ | ||
340 | cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); | ||
341 | cd->shift = 32; | ||
342 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
343 | cd->min_delta_ns = clockevent_delta2ns(0x30, cd); | ||
344 | |||
345 | cd->rating = 300; | ||
346 | cd->irq = irq; | ||
347 | cd->cpumask = cpumask_of_cpu(cpu); | ||
348 | cd->set_next_event = mips_next_event; | ||
349 | cd->set_mode = mips_set_mode; | ||
350 | |||
351 | global_cd[cpu] = cd; | ||
352 | clockevents_register_device(cd); | ||
353 | |||
354 | if (!cp0_timer_irq_installed) { | ||
355 | #ifdef CONFIG_MIPS_MT_SMTC | ||
356 | #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) | ||
357 | setup_irq_smtc(irq, &timer_irqaction, CPUCTR_IMASKBIT); | ||
358 | #else | ||
359 | setup_irq(irq, &timer_irqaction); | ||
360 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
361 | cp0_timer_irq_installed = 1; | ||
362 | } | ||
363 | } | ||
364 | |||
385 | void __init time_init(void) | 365 | void __init time_init(void) |
386 | { | 366 | { |
387 | plat_time_init(); | 367 | plat_time_init(); |
@@ -407,11 +387,6 @@ void __init time_init(void) | |||
407 | /* Calculate cache parameters. */ | 387 | /* Calculate cache parameters. */ |
408 | cycles_per_jiffy = | 388 | cycles_per_jiffy = |
409 | (mips_hpt_frequency + HZ / 2) / HZ; | 389 | (mips_hpt_frequency + HZ / 2) / HZ; |
410 | /* | ||
411 | * This sets up the high precision | ||
412 | * timer for the first interrupt. | ||
413 | */ | ||
414 | c0_hpt_timer_init(); | ||
415 | } | 390 | } |
416 | } | 391 | } |
417 | if (!mips_hpt_frequency) | 392 | if (!mips_hpt_frequency) |
@@ -421,6 +396,10 @@ void __init time_init(void) | |||
421 | printk("Using %u.%03u MHz high precision timer.\n", | 396 | printk("Using %u.%03u MHz high precision timer.\n", |
422 | ((mips_hpt_frequency + 500) / 1000) / 1000, | 397 | ((mips_hpt_frequency + 500) / 1000) / 1000, |
423 | ((mips_hpt_frequency + 500) / 1000) % 1000); | 398 | ((mips_hpt_frequency + 500) / 1000) % 1000); |
399 | |||
400 | #ifdef CONFIG_IRQ_CPU | ||
401 | setup_irq(MIPS_CPU_IRQ_BASE + 7, &timer_irqaction); | ||
402 | #endif | ||
424 | } | 403 | } |
425 | 404 | ||
426 | if (!mips_timer_ack) | 405 | if (!mips_timer_ack) |
@@ -441,4 +420,5 @@ void __init time_init(void) | |||
441 | plat_timer_setup(&timer_irqaction); | 420 | plat_timer_setup(&timer_irqaction); |
442 | 421 | ||
443 | init_mips_clocksource(); | 422 | init_mips_clocksource(); |
423 | mips_clockevent_init(); | ||
444 | } | 424 | } |
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 345de881013c..2c8db3e0f4b7 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c | |||
@@ -144,20 +144,20 @@ void __init plat_time_init(void) | |||
144 | mips_scroll_message(); | 144 | mips_scroll_message(); |
145 | } | 145 | } |
146 | 146 | ||
147 | static irqreturn_t mips_perf_interrupt(int irq, void *dev_id) | 147 | //static irqreturn_t mips_perf_interrupt(int irq, void *dev_id) |
148 | { | 148 | //{ |
149 | return perf_irq(); | 149 | // return perf_irq(); |
150 | } | 150 | //} |
151 | 151 | ||
152 | static struct irqaction perf_irqaction = { | 152 | //static struct irqaction perf_irqaction = { |
153 | .handler = mips_perf_interrupt, | 153 | // .handler = mips_perf_interrupt, |
154 | .flags = IRQF_DISABLED | IRQF_PERCPU, | 154 | // .flags = IRQF_DISABLED | IRQF_PERCPU, |
155 | .name = "performance", | 155 | // .name = "performance", |
156 | }; | 156 | //}; |
157 | 157 | ||
158 | void __init plat_perf_setup(void) | 158 | void __init plat_perf_setup(void) |
159 | { | 159 | { |
160 | struct irqaction *irq = &perf_irqaction; | 160 | // struct irqaction *irq = &perf_irqaction; |
161 | 161 | ||
162 | cp0_perfcount_irq = -1; | 162 | cp0_perfcount_irq = -1; |
163 | 163 | ||
@@ -170,12 +170,6 @@ void __init plat_perf_setup(void) | |||
170 | if (cp0_perfcount_irq >= 0) { | 170 | if (cp0_perfcount_irq >= 0) { |
171 | if (cpu_has_vint) | 171 | if (cpu_has_vint) |
172 | set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); | 172 | set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); |
173 | #ifdef CONFIG_MIPS_MT_SMTC | ||
174 | setup_irq_smtc(cp0_perfcount_irq, irq, | ||
175 | 0x100 << cp0_perfcount_irq); | ||
176 | #else | ||
177 | setup_irq(cp0_perfcount_irq, irq); | ||
178 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
179 | #ifdef CONFIG_SMP | 173 | #ifdef CONFIG_SMP |
180 | set_irq_handler(cp0_perfcount_irq, handle_percpu_irq); | 174 | set_irq_handler(cp0_perfcount_irq, handle_percpu_irq); |
181 | #endif | 175 | #endif |
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c index 89891e984b3b..4681757460a1 100644 --- a/arch/mips/qemu/q-irq.c +++ b/arch/mips/qemu/q-irq.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/linkage.h> | 2 | #include <linux/linkage.h> |
3 | 3 | ||
4 | #include <asm/i8259.h> | 4 | #include <asm/i8259.h> |
5 | #include <asm/irq_cpu.h> | ||
5 | #include <asm/mipsregs.h> | 6 | #include <asm/mipsregs.h> |
6 | #include <asm/qemu.h> | 7 | #include <asm/qemu.h> |
7 | #include <asm/system.h> | 8 | #include <asm/system.h> |
@@ -12,7 +13,7 @@ asmlinkage void plat_irq_dispatch(void) | |||
12 | unsigned int pending = read_c0_status() & read_c0_cause(); | 13 | unsigned int pending = read_c0_status() & read_c0_cause(); |
13 | 14 | ||
14 | if (pending & 0x8000) { | 15 | if (pending & 0x8000) { |
15 | ll_timer_interrupt(Q_COUNT_COMPARE_IRQ); | 16 | do_IRQ(Q_COUNT_COMPARE_IRQ); |
16 | return; | 17 | return; |
17 | } | 18 | } |
18 | if (pending & 0x0400) { | 19 | if (pending & 0x0400) { |
@@ -29,6 +30,7 @@ void __init arch_init_irq(void) | |||
29 | { | 30 | { |
30 | mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */ | 31 | mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */ |
31 | 32 | ||
33 | mips_cpu_irq_init(); | ||
32 | init_i8259_irqs(); | 34 | init_i8259_irqs(); |
33 | set_c0_status(0x8400); | 35 | set_c0_status(0x8400); |
34 | } | 36 | } |
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c index 841394336f00..89a207650ce9 100644 --- a/arch/mips/qemu/q-setup.c +++ b/arch/mips/qemu/q-setup.c | |||
@@ -17,7 +17,6 @@ void __init plat_timer_setup(struct irqaction *irq) | |||
17 | outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ | 17 | outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ |
18 | outb_p(LATCH & 0xff , 0x40); /* LSB */ | 18 | outb_p(LATCH & 0xff , 0x40); /* LSB */ |
19 | outb(LATCH >> 8 , 0x40); /* MSB */ | 19 | outb(LATCH >> 8 , 0x40); /* MSB */ |
20 | setup_irq(0, irq); | ||
21 | } | 20 | } |
22 | 21 | ||
23 | void __init plat_mem_setup(void) | 22 | void __init plat_mem_setup(void) |
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index 338c0d706988..f199da7e49cf 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c | |||
@@ -242,7 +242,7 @@ asmlinkage void plat_irq_dispatch(void) | |||
242 | * First we check for r4k counter/timer IRQ. | 242 | * First we check for r4k counter/timer IRQ. |
243 | */ | 243 | */ |
244 | if (pending & CAUSEF_IP7) | 244 | if (pending & CAUSEF_IP7) |
245 | ll_timer_interrupt(SGI_TIMER_IRQ, NULL); | 245 | do_IRQ(SGI_TIMER_IRQ); |
246 | else if (pending & CAUSEF_IP2) | 246 | else if (pending & CAUSEF_IP2) |
247 | indy_local0_irqdispatch(); | 247 | indy_local0_irqdispatch(); |
248 | else if (pending & CAUSEF_IP3) | 248 | else if (pending & CAUSEF_IP3) |
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 5bad1b744d0f..002095b364a3 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c | |||
@@ -457,7 +457,7 @@ static void ip32_irq4(void) | |||
457 | 457 | ||
458 | static void ip32_irq5(void) | 458 | static void ip32_irq5(void) |
459 | { | 459 | { |
460 | ll_timer_interrupt(IP32_R4K_TIMER_IRQ); | 460 | do_IRQ(IP32_R4K_TIMER_IRQ); |
461 | } | 461 | } |
462 | 462 | ||
463 | asmlinkage void plat_irq_dispatch(void) | 463 | asmlinkage void plat_irq_dispatch(void) |
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index 841b301c99f0..e8fb880272bd 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SIBYTE_SB1250 | 1 | config SIBYTE_SB1250 |
2 | bool | 2 | bool |
3 | select HW_HAS_PCI | 3 | select HW_HAS_PCI |
4 | select IRQ_CPU | ||
4 | select SIBYTE_ENABLE_LDT_IF_PCI | 5 | select SIBYTE_ENABLE_LDT_IF_PCI |
5 | select SIBYTE_HAS_ZBUS_PROFILING | 6 | select SIBYTE_HAS_ZBUS_PROFILING |
6 | select SIBYTE_SB1xxx_SOC | 7 | select SIBYTE_SB1xxx_SOC |
@@ -8,6 +9,7 @@ config SIBYTE_SB1250 | |||
8 | 9 | ||
9 | config SIBYTE_BCM1120 | 10 | config SIBYTE_BCM1120 |
10 | bool | 11 | bool |
12 | select IRQ_CPU | ||
11 | select SIBYTE_BCM112X | 13 | select SIBYTE_BCM112X |
12 | select SIBYTE_HAS_ZBUS_PROFILING | 14 | select SIBYTE_HAS_ZBUS_PROFILING |
13 | select SIBYTE_SB1xxx_SOC | 15 | select SIBYTE_SB1xxx_SOC |
@@ -15,6 +17,7 @@ config SIBYTE_BCM1120 | |||
15 | config SIBYTE_BCM1125 | 17 | config SIBYTE_BCM1125 |
16 | bool | 18 | bool |
17 | select HW_HAS_PCI | 19 | select HW_HAS_PCI |
20 | select IRQ_CPU | ||
18 | select SIBYTE_BCM112X | 21 | select SIBYTE_BCM112X |
19 | select SIBYTE_HAS_ZBUS_PROFILING | 22 | select SIBYTE_HAS_ZBUS_PROFILING |
20 | select SIBYTE_SB1xxx_SOC | 23 | select SIBYTE_SB1xxx_SOC |
@@ -22,6 +25,7 @@ config SIBYTE_BCM1125 | |||
22 | config SIBYTE_BCM1125H | 25 | config SIBYTE_BCM1125H |
23 | bool | 26 | bool |
24 | select HW_HAS_PCI | 27 | select HW_HAS_PCI |
28 | select IRQ_CPU | ||
25 | select SIBYTE_BCM112X | 29 | select SIBYTE_BCM112X |
26 | select SIBYTE_ENABLE_LDT_IF_PCI | 30 | select SIBYTE_ENABLE_LDT_IF_PCI |
27 | select SIBYTE_HAS_ZBUS_PROFILING | 31 | select SIBYTE_HAS_ZBUS_PROFILING |
@@ -29,12 +33,14 @@ config SIBYTE_BCM1125H | |||
29 | 33 | ||
30 | config SIBYTE_BCM112X | 34 | config SIBYTE_BCM112X |
31 | bool | 35 | bool |
36 | select IRQ_CPU | ||
32 | select SIBYTE_SB1xxx_SOC | 37 | select SIBYTE_SB1xxx_SOC |
33 | select SIBYTE_HAS_ZBUS_PROFILING | 38 | select SIBYTE_HAS_ZBUS_PROFILING |
34 | 39 | ||
35 | config SIBYTE_BCM1x80 | 40 | config SIBYTE_BCM1x80 |
36 | bool | 41 | bool |
37 | select HW_HAS_PCI | 42 | select HW_HAS_PCI |
43 | select IRQ_CPU | ||
38 | select SIBYTE_HAS_ZBUS_PROFILING | 44 | select SIBYTE_HAS_ZBUS_PROFILING |
39 | select SIBYTE_SB1xxx_SOC | 45 | select SIBYTE_SB1xxx_SOC |
40 | select SYS_SUPPORTS_SMP | 46 | select SYS_SUPPORTS_SMP |
@@ -42,6 +48,7 @@ config SIBYTE_BCM1x80 | |||
42 | config SIBYTE_BCM1x55 | 48 | config SIBYTE_BCM1x55 |
43 | bool | 49 | bool |
44 | select HW_HAS_PCI | 50 | select HW_HAS_PCI |
51 | select IRQ_CPU | ||
45 | select SIBYTE_SB1xxx_SOC | 52 | select SIBYTE_SB1xxx_SOC |
46 | select SIBYTE_HAS_ZBUS_PROFILING | 53 | select SIBYTE_HAS_ZBUS_PROFILING |
47 | select SYS_SUPPORTS_SMP | 54 | select SYS_SUPPORTS_SMP |
@@ -49,6 +56,7 @@ config SIBYTE_BCM1x55 | |||
49 | config SIBYTE_SB1xxx_SOC | 56 | config SIBYTE_SB1xxx_SOC |
50 | bool | 57 | bool |
51 | select DMA_COHERENT | 58 | select DMA_COHERENT |
59 | select IRQ_CPU | ||
52 | select SIBYTE_CFE | 60 | select SIBYTE_CFE |
53 | select SWAP_IO_SPACE | 61 | select SWAP_IO_SPACE |
54 | select SYS_SUPPORTS_32BIT_KERNEL | 62 | select SYS_SUPPORTS_32BIT_KERNEL |
@@ -166,10 +174,6 @@ config SIBYTE_BW_TRACE | |||
166 | buffer activity. Raw buffer data is dumped to console, and | 174 | buffer activity. Raw buffer data is dumped to console, and |
167 | must be processed off-line. | 175 | must be processed off-line. |
168 | 176 | ||
169 | config SIBYTE_SB1250_PROF | ||
170 | bool "Support for SB1/SOC profiling - SB1/SCD perf counters" | ||
171 | depends on SIBYTE_SB1xxx_SOC | ||
172 | |||
173 | config SIBYTE_TBPROF | 177 | config SIBYTE_TBPROF |
174 | tristate "Support for ZBbus profiling" | 178 | tristate "Support for ZBbus profiling" |
175 | depends on SIBYTE_HAS_ZBUS_PROFILING | 179 | depends on SIBYTE_HAS_ZBUS_PROFILING |
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index e729b5f30264..cf979dbb282d 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c | |||
@@ -450,7 +450,6 @@ static void bcm1480_kgdb_interrupt(void) | |||
450 | 450 | ||
451 | #endif /* CONFIG_KGDB */ | 451 | #endif /* CONFIG_KGDB */ |
452 | 452 | ||
453 | extern void bcm1480_timer_interrupt(void); | ||
454 | extern void bcm1480_mailbox_interrupt(void); | 453 | extern void bcm1480_mailbox_interrupt(void); |
455 | 454 | ||
456 | asmlinkage void plat_irq_dispatch(void) | 455 | asmlinkage void plat_irq_dispatch(void) |
@@ -470,8 +469,16 @@ asmlinkage void plat_irq_dispatch(void) | |||
470 | else | 469 | else |
471 | #endif | 470 | #endif |
472 | 471 | ||
473 | if (pending & CAUSEF_IP4) | 472 | if (pending & CAUSEF_IP4) { |
474 | bcm1480_timer_interrupt(); | 473 | int cpu = smp_processor_id(); |
474 | int irq = K_BCM1480_INT_TIMER_0 + cpu; | ||
475 | |||
476 | /* Reset the timer */ | ||
477 | __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, | ||
478 | IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); | ||
479 | |||
480 | do_IRQ(irq); | ||
481 | } | ||
475 | 482 | ||
476 | #ifdef CONFIG_SMP | 483 | #ifdef CONFIG_SMP |
477 | else if (pending & CAUSEF_IP3) | 484 | else if (pending & CAUSEF_IP3) |
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index ad593a6c20be..6a4cc84194a9 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/errno.h> | 28 | #include <asm/errno.h> |
29 | #include <asm/signal.h> | 29 | #include <asm/signal.h> |
30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
31 | #include <asm/time.h> | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | 33 | ||
33 | #include <asm/sibyte/sb1250_regs.h> | 34 | #include <asm/sibyte/sb1250_regs.h> |
@@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void) | |||
399 | 400 | ||
400 | #endif /* CONFIG_KGDB */ | 401 | #endif /* CONFIG_KGDB */ |
401 | 402 | ||
402 | extern void sb1250_timer_interrupt(void); | 403 | static inline void sb1250_timer_interrupt(void) |
404 | { | ||
405 | int cpu = smp_processor_id(); | ||
406 | int irq = K_INT_TIMER_0 + cpu; | ||
407 | |||
408 | irq_enter(); | ||
409 | kstat_this_cpu.irqs[irq]++; | ||
410 | |||
411 | write_seqlock(&xtime_lock); | ||
412 | |||
413 | /* ACK interrupt */ | ||
414 | ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | ||
415 | IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); | ||
416 | |||
417 | /* | ||
418 | * call the generic timer interrupt handling | ||
419 | */ | ||
420 | do_timer(1); | ||
421 | |||
422 | write_sequnlock(&xtime_lock); | ||
423 | |||
424 | /* | ||
425 | * In UP mode, we call local_timer_interrupt() to do profiling | ||
426 | * and process accouting. | ||
427 | * | ||
428 | * In SMP mode, local_timer_interrupt() is invoked by appropriate | ||
429 | * low-level local timer interrupt handler. | ||
430 | */ | ||
431 | local_timer_interrupt(irq); | ||
432 | |||
433 | irq_exit(); | ||
434 | } | ||
435 | |||
403 | extern void sb1250_mailbox_interrupt(void); | 436 | extern void sb1250_mailbox_interrupt(void); |
404 | 437 | ||
405 | asmlinkage void plat_irq_dispatch(void) | 438 | asmlinkage void plat_irq_dispatch(void) |
406 | { | 439 | { |
407 | unsigned int pending; | 440 | unsigned int pending; |
408 | 441 | ||
409 | #ifdef CONFIG_SIBYTE_SB1250_PROF | ||
410 | /* Set compare to count to silence count/compare timer interrupts */ | ||
411 | write_c0_compare(read_c0_count()); | ||
412 | #endif | ||
413 | |||
414 | /* | 442 | /* |
415 | * What a pain. We have to be really careful saving the upper 32 bits | 443 | * What a pain. We have to be really careful saving the upper 32 bits |
416 | * of any * register across function calls if we don't want them | 444 | * of any * register across function calls if we don't want them |
@@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void) | |||
423 | 451 | ||
424 | pending = read_c0_cause() & read_c0_status() & ST0_IM; | 452 | pending = read_c0_cause() & read_c0_status() & ST0_IM; |
425 | 453 | ||
426 | #ifdef CONFIG_SIBYTE_SB1250_PROF | 454 | if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */ |
427 | if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ | 455 | do_IRQ(MIPS_CPU_IRQ_BASE + 7); |
428 | sbprof_cpu_intr(); | 456 | else if (pending & CAUSEF_IP4) |
429 | else | ||
430 | #endif | ||
431 | |||
432 | if (pending & CAUSEF_IP4) | ||
433 | sb1250_timer_interrupt(); | 457 | sb1250_timer_interrupt(); |
434 | 458 | ||
435 | #ifdef CONFIG_SMP | 459 | #ifdef CONFIG_SMP |
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index 5bb83cd4c113..eb177075e9c0 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c | |||
@@ -116,18 +116,6 @@ void sb1250_time_init(void) | |||
116 | */ | 116 | */ |
117 | } | 117 | } |
118 | 118 | ||
119 | void sb1250_timer_interrupt(void) | ||
120 | { | ||
121 | int cpu = smp_processor_id(); | ||
122 | int irq = K_INT_TIMER_0 + cpu; | ||
123 | |||
124 | /* ACK interrupt */ | ||
125 | ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, | ||
126 | IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); | ||
127 | |||
128 | ll_timer_interrupt(irq); | ||
129 | } | ||
130 | |||
131 | /* | 119 | /* |
132 | * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over | 120 | * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over |
133 | * again. | 121 | * again. |
diff --git a/include/asm-mips/mach-ip27/irq.h b/include/asm-mips/mach-ip27/irq.h index 25f0c3f39adf..cf4384bfa846 100644 --- a/include/asm-mips/mach-ip27/irq.h +++ b/include/asm-mips/mach-ip27/irq.h | |||
@@ -17,4 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | #define NR_IRQS 256 | 18 | #define NR_IRQS 256 |
19 | 19 | ||
20 | #include_next <irq.h> | ||
21 | |||
20 | #endif /* __ASM_MACH_IP27_IRQ_H */ | 22 | #endif /* __ASM_MACH_IP27_IRQ_H */ |
diff --git a/include/asm-mips/qemu.h b/include/asm-mips/qemu.h index 531caf44560c..487ced4a40de 100644 --- a/include/asm-mips/qemu.h +++ b/include/asm-mips/qemu.h | |||
@@ -12,7 +12,7 @@ | |||
12 | * Interrupt numbers | 12 | * Interrupt numbers |
13 | */ | 13 | */ |
14 | #define Q_PIC_IRQ_BASE 0 | 14 | #define Q_PIC_IRQ_BASE 0 |
15 | #define Q_COUNT_COMPARE_IRQ 16 | 15 | #define Q_COUNT_COMPARE_IRQ 23 |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * Qemu clock rate. Unlike on real MIPS this has no relation to the | 18 | * Qemu clock rate. Unlike on real MIPS this has no relation to the |
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 3516b32c9efb..35555bd5c52d 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h | |||
@@ -49,11 +49,6 @@ extern void (*mips_timer_ack)(void); | |||
49 | extern struct clocksource clocksource_mips; | 49 | extern struct clocksource clocksource_mips; |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * The low-level timer interrupt routine. | ||
53 | */ | ||
54 | extern void ll_timer_interrupt(int irq, void *dev_id); | ||
55 | |||
56 | /* | ||
57 | * profiling and process accouting is done separately in local_timer_interrupt | 52 | * profiling and process accouting is done separately in local_timer_interrupt |
58 | */ | 53 | */ |
59 | extern void local_timer_interrupt(int irq, void *dev_id); | 54 | extern void local_timer_interrupt(int irq, void *dev_id); |
@@ -78,4 +73,9 @@ extern unsigned int mips_hpt_frequency; | |||
78 | */ | 73 | */ |
79 | extern int (*perf_irq)(void); | 74 | extern int (*perf_irq)(void); |
80 | 75 | ||
76 | /* | ||
77 | * Initialize the calling CPU's compare interrupt as clockevent device | ||
78 | */ | ||
79 | extern void mips_clockevent_init(void); | ||
80 | |||
81 | #endif /* _ASM_TIME_H */ | 81 | #endif /* _ASM_TIME_H */ |