diff options
Diffstat (limited to 'arch/arm/mach-imx/time.c')
-rw-r--r-- | arch/arm/mach-imx/time.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c new file mode 100644 index 000000000000..11f1e56c36bc --- /dev/null +++ b/arch/arm/mach-imx/time.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-imx/time.c | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Deep Blue Solutions | ||
5 | * Copyright (C) 2002 Shane Nay (shane@minirl.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/time.h> | ||
17 | |||
18 | #include <asm/hardware.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/leds.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/mach/time.h> | ||
23 | |||
24 | /* Use timer 1 as system timer */ | ||
25 | #define TIMER_BASE IMX_TIM1_BASE | ||
26 | |||
27 | /* | ||
28 | * Returns number of us since last clock interrupt. Note that interrupts | ||
29 | * will have been disabled by do_gettimeoffset() | ||
30 | */ | ||
31 | static unsigned long imx_gettimeoffset(void) | ||
32 | { | ||
33 | unsigned long ticks; | ||
34 | |||
35 | /* | ||
36 | * Get the current number of ticks. Note that there is a race | ||
37 | * condition between us reading the timer and checking for | ||
38 | * an interrupt. We get around this by ensuring that the | ||
39 | * counter has not reloaded between our two reads. | ||
40 | */ | ||
41 | ticks = IMX_TCN(TIMER_BASE); | ||
42 | |||
43 | /* | ||
44 | * Interrupt pending? If so, we've reloaded once already. | ||
45 | */ | ||
46 | if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP) | ||
47 | ticks += LATCH; | ||
48 | |||
49 | /* | ||
50 | * Convert the ticks to usecs | ||
51 | */ | ||
52 | return (1000000 / CLK32) * ticks; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * IRQ handler for the timer | ||
57 | */ | ||
58 | static irqreturn_t | ||
59 | imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
60 | { | ||
61 | write_seqlock(&xtime_lock); | ||
62 | |||
63 | /* clear the interrupt */ | ||
64 | if (IMX_TSTAT(TIMER_BASE)) | ||
65 | IMX_TSTAT(TIMER_BASE) = 0; | ||
66 | |||
67 | timer_tick(regs); | ||
68 | write_sequnlock(&xtime_lock); | ||
69 | |||
70 | return IRQ_HANDLED; | ||
71 | } | ||
72 | |||
73 | static struct irqaction imx_timer_irq = { | ||
74 | .name = "i.MX Timer Tick", | ||
75 | .flags = SA_INTERRUPT, | ||
76 | .handler = imx_timer_interrupt | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * Set up timer interrupt, and return the current time in seconds. | ||
81 | */ | ||
82 | static void __init imx_timer_init(void) | ||
83 | { | ||
84 | /* | ||
85 | * Initialise to a known state (all timers off, and timing reset) | ||
86 | */ | ||
87 | IMX_TCTL(TIMER_BASE) = 0; | ||
88 | IMX_TPRER(TIMER_BASE) = 0; | ||
89 | IMX_TCMP(TIMER_BASE) = LATCH - 1; | ||
90 | IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN; | ||
91 | |||
92 | /* | ||
93 | * Make irqs happen for the system timer | ||
94 | */ | ||
95 | setup_irq(TIM1_INT, &imx_timer_irq); | ||
96 | } | ||
97 | |||
98 | struct sys_timer imx_timer = { | ||
99 | .init = imx_timer_init, | ||
100 | .offset = imx_gettimeoffset, | ||
101 | }; | ||