diff options
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/generic.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-imx/irq.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-imx/time.c | 86 |
3 files changed, 65 insertions, 44 deletions
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index 12ea58a3b84f..b5aa49d00ca3 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c @@ -104,6 +104,9 @@ EXPORT_SYMBOL(imx_gpio_mode); */ static unsigned int imx_decode_pll(unsigned int pll) { + unsigned long long ll; + unsigned long quot; + u32 mfi = (pll >> 10) & 0xf; u32 mfn = pll & 0x3ff; u32 mfd = (pll >> 16) & 0x3ff; @@ -112,7 +115,11 @@ static unsigned int imx_decode_pll(unsigned int pll) mfi = mfi <= 5 ? 5 : mfi; - return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1); + ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) ); + quot = (pd+1) * (1<<16); + ll += quot / 2; + do_div(ll, quot); + return (unsigned int) ll; } unsigned int imx_get_system_clk(void) diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c index 368b13b058ab..0791b56caecc 100644 --- a/arch/arm/mach-imx/irq.c +++ b/arch/arm/mach-imx/irq.c @@ -146,7 +146,7 @@ imx_gpio_unmask_irq(unsigned int irq) static void imx_gpio_handler(unsigned int mask, unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { desc = irq_desc + irq; while (mask) { @@ -161,7 +161,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq, } static void -imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -171,7 +171,7 @@ imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -181,7 +181,7 @@ imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -191,7 +191,7 @@ imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -230,13 +230,13 @@ imx_init_irq(void) for (irq = 0; irq < IMX_IRQS; irq++) { set_irq_chip(irq, &imx_internal_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) { set_irq_chip(irq, &imx_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 8ae4a2c5066f..40039b2a90b3 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -14,6 +14,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/time.h> +#include <linux/clocksource.h> #include <asm/hardware.h> #include <asm/io.h> @@ -24,33 +25,7 @@ /* 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 @@ -58,14 +33,23 @@ static unsigned long imx_gettimeoffset(void) static irqreturn_t 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(); - write_sequnlock(&xtime_lock); + } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE) + - IMX_TCN(TIMER_BASE)) < 0)); + } return IRQ_HANDLED; } @@ -77,9 +61,9 @@ static struct irqaction imx_timer_irq = { }; /* - * 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, }; |