aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/time.c')
-rw-r--r--arch/mips/kernel/time.c262
1 files changed, 0 insertions, 262 deletions
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}