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.c111
1 files changed, 98 insertions, 13 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 35988847c98a..369a5f9ad268 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -25,6 +25,7 @@
25#include <linux/spinlock.h> 25#include <linux/spinlock.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/kallsyms.h>
28 29
29#include <asm/bootinfo.h> 30#include <asm/bootinfo.h>
30#include <asm/cache.h> 31#include <asm/cache.h>
@@ -33,6 +34,7 @@
33#include <asm/cpu-features.h> 34#include <asm/cpu-features.h>
34#include <asm/div64.h> 35#include <asm/div64.h>
35#include <asm/sections.h> 36#include <asm/sections.h>
37#include <asm/smtc_ipi.h>
36#include <asm/time.h> 38#include <asm/time.h>
37 39
38#include <irq.h> 40#include <irq.h>
@@ -230,12 +232,24 @@ static int mips_next_event(unsigned long delta,
230 struct clock_event_device *evt) 232 struct clock_event_device *evt)
231{ 233{
232 unsigned int cnt; 234 unsigned int cnt;
235 int res;
233 236
237#ifdef CONFIG_MIPS_MT_SMTC
238 {
239 unsigned long flags, vpflags;
240 local_irq_save(flags);
241 vpflags = dvpe();
242#endif
234 cnt = read_c0_count(); 243 cnt = read_c0_count();
235 cnt += delta; 244 cnt += delta;
236 write_c0_compare(cnt); 245 write_c0_compare(cnt);
237 246 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0;
238 return ((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;
239} 253}
240 254
241static void mips_set_mode(enum clock_event_mode mode, 255static void mips_set_mode(enum clock_event_mode mode,
@@ -244,9 +258,7 @@ static void mips_set_mode(enum clock_event_mode mode,
244 /* Nothing to do ... */ 258 /* Nothing to do ... */
245} 259}
246 260
247struct clock_event_device mips_clockevent; 261static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
248
249static struct clock_event_device *global_cd[NR_CPUS];
250static int cp0_timer_irq_installed; 262static int cp0_timer_irq_installed;
251 263
252static irqreturn_t timer_interrupt(int irq, void *dev_id) 264static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -271,7 +283,12 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
271 */ 283 */
272 if (!r2 || (read_c0_cause() & (1 << 30))) { 284 if (!r2 || (read_c0_cause() & (1 << 30))) {
273 c0_timer_ack(); 285 c0_timer_ack();
274 cd = global_cd[cpu]; 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);
275 cd->event_handler(cd); 292 cd->event_handler(cd);
276 } 293 }
277 294
@@ -281,7 +298,11 @@ out:
281 298
282static struct irqaction timer_irqaction = { 299static struct irqaction timer_irqaction = {
283 .handler = timer_interrupt, 300 .handler = timer_interrupt,
301#ifdef CONFIG_MIPS_MT_SMTC
302 .flags = IRQF_DISABLED,
303#else
284 .flags = IRQF_DISABLED | IRQF_PERCPU, 304 .flags = IRQF_DISABLED | IRQF_PERCPU,
305#endif
285 .name = "timer", 306 .name = "timer",
286}; 307};
287 308
@@ -316,6 +337,60 @@ void __init __weak plat_timer_setup(struct irqaction *irq)
316{ 337{
317} 338}
318 339
340#ifdef CONFIG_MIPS_MT_SMTC
341DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
342
343static void smtc_set_mode(enum clock_event_mode mode,
344 struct clock_event_device *evt)
345{
346}
347
348int dummycnt[NR_CPUS];
349
350static void mips_broadcast(cpumask_t mask)
351{
352 unsigned int cpu;
353
354 for_each_cpu_mask(cpu, mask)
355 smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
356}
357
358static void setup_smtc_dummy_clockevent_device(void)
359{
360 //uint64_t mips_freq = mips_hpt_^frequency;
361 unsigned int cpu = smp_processor_id();
362 struct clock_event_device *cd;
363
364 cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
365
366 cd->name = "SMTC";
367 cd->features = CLOCK_EVT_FEAT_DUMMY;
368
369 /* Calculate the min / max delta */
370 cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
371 cd->shift = 0; //32;
372 cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
373 cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
374
375 cd->rating = 200;
376 cd->irq = 17; //-1;
377// if (cpu)
378// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
379// else
380 cd->cpumask = cpumask_of_cpu(cpu);
381
382 cd->set_mode = smtc_set_mode;
383
384 cd->broadcast = mips_broadcast;
385
386 clockevents_register_device(cd);
387}
388#endif
389
390static void mips_event_handler(struct clock_event_device *dev)
391{
392}
393
319void __cpuinit mips_clockevent_init(void) 394void __cpuinit mips_clockevent_init(void)
320{ 395{
321 uint64_t mips_freq = mips_hpt_frequency; 396 uint64_t mips_freq = mips_hpt_frequency;
@@ -326,12 +401,18 @@ void __cpuinit mips_clockevent_init(void)
326 if (!cpu_has_counter) 401 if (!cpu_has_counter)
327 return; 402 return;
328 403
329 if (cpu == 0) 404#ifdef CONFIG_MIPS_MT_SMTC
330 cd = &mips_clockevent; 405 setup_smtc_dummy_clockevent_device();
331 else 406
332 cd = kzalloc(sizeof(*cd), GFP_ATOMIC); 407 /*
333 if (!cd) 408 * On SMTC we only register VPE0's compare interrupt as clockevent
334 return; /* We're probably roadkill ... */ 409 * device.
410 */
411 if (cpu)
412 return;
413#endif
414
415 cd = &per_cpu(mips_clockevent_device, cpu);
335 416
336 cd->name = "MIPS"; 417 cd->name = "MIPS";
337 cd->features = CLOCK_EVT_FEAT_ONESHOT; 418 cd->features = CLOCK_EVT_FEAT_ONESHOT;
@@ -344,11 +425,15 @@ void __cpuinit mips_clockevent_init(void)
344 425
345 cd->rating = 300; 426 cd->rating = 300;
346 cd->irq = irq; 427 cd->irq = irq;
428#ifdef CONFIG_MIPS_MT_SMTC
429 cd->cpumask = CPU_MASK_ALL;
430#else
347 cd->cpumask = cpumask_of_cpu(cpu); 431 cd->cpumask = cpumask_of_cpu(cpu);
432#endif
348 cd->set_next_event = mips_next_event; 433 cd->set_next_event = mips_next_event;
349 cd->set_mode = mips_set_mode; 434 cd->set_mode = mips_set_mode;
435 cd->event_handler = mips_event_handler;
350 436
351 global_cd[cpu] = cd;
352 clockevents_register_device(cd); 437 clockevents_register_device(cd);
353 438
354 if (!cp0_timer_irq_installed) { 439 if (!cp0_timer_irq_installed) {