diff options
Diffstat (limited to 'arch/mn10300/kernel/time.c')
| -rw-r--r-- | arch/mn10300/kernel/time.c | 76 |
1 files changed, 20 insertions, 56 deletions
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 395caf01b90..67c6416a58f 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -17,29 +17,18 @@ #include <linux/smp.h> #include <linux/profile.h> #include <linux/cnt32_to_63.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> #include <asm/irq.h> #include <asm/div64.h> #include <asm/processor.h> #include <asm/intctl-regs.h> #include <asm/rtc.h> - -#ifdef CONFIG_MN10300_RTC -unsigned long mn10300_ioclk; /* system I/O clock frequency */ -unsigned long mn10300_iobclk; /* system I/O clock frequency */ -unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */ -#endif /* CONFIG_MN10300_RTC */ +#include "internal.h" static unsigned long mn10300_last_tsc; /* time-stamp counter at last time * interrupt occurred */ -static irqreturn_t timer_interrupt(int irq, void *dev_id); - -static struct irqaction timer_irq = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER, - .name = "timer", -}; - static unsigned long sched_clock_multiplier; /* @@ -51,18 +40,19 @@ unsigned long long sched_clock(void) unsigned long long ll; unsigned l[2]; } tsc64, result; - unsigned long tsc, tmp; + unsigned long tmp; unsigned product[3]; /* 96-bit intermediate value */ - /* read the TSC value - */ - tsc = 0 - get_cycles(); /* get_cycles() counts down */ + /* cnt32_to_63() is not safe with preemption */ + preempt_disable(); - /* expand to 64-bits. + /* expand the tsc to 64-bits. * - sched_clock() must be called once a minute or better or the * following will go horribly wrong - see cnt32_to_63() */ - tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; + tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL; + + preempt_enable(); /* scale the 64-bit TSC value to a nanosecond value via a 96-bit * intermediate @@ -90,34 +80,16 @@ static void __init mn10300_sched_clock_init(void) __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); } -/* - * advance the kernel's time keeping clocks (xtime and jiffies) - * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time - * there's a need to update +/** + * local_timer_interrupt - Local timer interrupt handler + * + * Handle local timer interrupts for this CPU. They may have been propagated + * to this CPU from the CPU that actually gets them by way of an IPI. */ -static irqreturn_t timer_interrupt(int irq, void *dev_id) +irqreturn_t local_timer_interrupt(void) { - unsigned tsc, elapse; - - write_seqlock(&xtime_lock); - - while (tsc = get_cycles(), - elapse = mn10300_last_tsc - tsc, /* time elapsed since last - * tick */ - elapse > MN10300_TSC_PER_HZ - ) { - mn10300_last_tsc -= MN10300_TSC_PER_HZ; - - /* advance the kernel's time tracking system */ - profile_tick(CPU_PROFILING); - do_timer(1); - check_rtc_time(); - } - - write_sequnlock(&xtime_lock); - + profile_tick(CPU_PROFILING); update_process_times(user_mode(get_irq_regs())); - return IRQ_HANDLED; } @@ -132,24 +104,16 @@ void __init time_init(void) */ TMPSCNT |= TMPSCNT_ENABLE; - startup_timestamp_counter(); + init_clocksource(); printk(KERN_INFO "timestamp counter I/O clock running at %lu.%02lu" " (calibrated against RTC)\n", MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); - xtime.tv_sec = get_initial_rtc_time(); - xtime.tv_nsec = 0; - - mn10300_last_tsc = TMTSCBC; - - /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */ - setup_irq(TMJCIRQ, &timer_irq); - - set_intr_level(TMJCIRQ, TMJCICR_LEVEL); + mn10300_last_tsc = read_timestamp_counter(); - startup_jiffies_counter(); + init_clockevents(); #ifdef CONFIG_MN10300_WD_TIMER /* start the watchdog timer */ |
