X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-imx%2Ftime.c;h=40039b2a90b39079a7af6f5fcdd5856f6452280e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=ea805bfa5e5401f01455f47d586fde14ecfb5b2d;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index ea805bfa5..40039b2a9 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -8,12 +8,13 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include #include +#include #include +#include #include #include @@ -24,62 +25,45 @@ /* Use timer 1 as system timer */ #define TIMER_BASE IMX_TIM1_BASE -/* - * Returns number of us since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -static unsigned long imx_gettimeoffset(void) -{ - unsigned long ticks; - - /* - * Get the current number of ticks. Note that there is a race - * condition between us reading the timer and checking for - * an interrupt. We get around this by ensuring that the - * counter has not reloaded between our two reads. - */ - ticks = IMX_TCN(TIMER_BASE); - - /* - * Interrupt pending? If so, we've reloaded once already. - */ - if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP) - ticks += LATCH; - - /* - * Convert the ticks to usecs - */ - return (1000000 / CLK32) * ticks; -} +static unsigned long evt_diff; /* * IRQ handler for the timer */ static irqreturn_t -imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +imx_timer_interrupt(int irq, void *dev_id) { - write_seqlock(&xtime_lock); + uint32_t tstat; /* clear the interrupt */ - if (IMX_TSTAT(TIMER_BASE)) - IMX_TSTAT(TIMER_BASE) = 0; + tstat = IMX_TSTAT(TIMER_BASE); + IMX_TSTAT(TIMER_BASE) = 0; + + if (tstat & TSTAT_COMP) { + do { + + write_seqlock(&xtime_lock); + timer_tick(); + write_sequnlock(&xtime_lock); + IMX_TCMP(TIMER_BASE) += evt_diff; - timer_tick(regs); - write_sequnlock(&xtime_lock); + } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE) + - IMX_TCN(TIMER_BASE)) < 0)); + } return IRQ_HANDLED; } static struct irqaction imx_timer_irq = { .name = "i.MX Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = imx_timer_interrupt, }; /* - * Set up timer interrupt, and return the current time in seconds. + * Set up timer hardware into expected mode and state. */ -static void __init imx_timer_init(void) +static void __init imx_timer_hardware_init(void) { /* * Initialise to a known state (all timers off, and timing reset) @@ -87,7 +71,38 @@ static void __init imx_timer_init(void) IMX_TCTL(TIMER_BASE) = 0; IMX_TPRER(TIMER_BASE) = 0; IMX_TCMP(TIMER_BASE) = LATCH - 1; - IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN; + + IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN; + evt_diff = LATCH; +} + +cycle_t imx_get_cycles(void) +{ + return IMX_TCN(TIMER_BASE); +} + +static struct clocksource clocksource_imx = { + .name = "imx_timer1", + .rating = 200, + .read = imx_get_cycles, + .mask = 0xFFFFFFFF, + .shift = 20, + .is_continuous = 1, +}; + +static int __init imx_clocksource_init(void) +{ + clocksource_imx.mult = + clocksource_hz2mult(imx_get_perclk1(), clocksource_imx.shift); + clocksource_register(&clocksource_imx); + + return 0; +} + +static void __init imx_timer_init(void) +{ + imx_timer_hardware_init(); + imx_clocksource_init(); /* * Make irqs happen for the system timer @@ -97,5 +112,4 @@ static void __init imx_timer_init(void) struct sys_timer imx_timer = { .init = imx_timer_init, - .offset = imx_gettimeoffset, };