Merge branch 'next/driver' of git://git.linaro.org/people/arnd/arm-soc
[pandora-kernel.git] / arch / arm / mach-omap2 / timer.c
1 /*
2  * linux/arch/arm/mach-omap2/timer.c
3  *
4  * OMAP2 GP timer support.
5  *
6  * Copyright (C) 2009 Nokia Corporation
7  *
8  * Update to use new clocksource/clockevent layers
9  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
10  * Copyright (C) 2007 MontaVista Software, Inc.
11  *
12  * Original driver:
13  * Copyright (C) 2005 Nokia Corporation
14  * Author: Paul Mundt <paul.mundt@nokia.com>
15  *         Juha Yrjölä <juha.yrjola@nokia.com>
16  * OMAP Dual-mode timer framework support by Timo Teras
17  *
18  * Some parts based off of TI's 24xx code:
19  *
20  * Copyright (C) 2004-2009 Texas Instruments, Inc.
21  *
22  * Roughly modelled after the OMAP1 MPU timer code.
23  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
24  *
25  * This file is subject to the terms and conditions of the GNU General Public
26  * License. See the file "COPYING" in the main directory of this archive
27  * for more details.
28  */
29 #include <linux/init.h>
30 #include <linux/time.h>
31 #include <linux/interrupt.h>
32 #include <linux/err.h>
33 #include <linux/clk.h>
34 #include <linux/delay.h>
35 #include <linux/irq.h>
36 #include <linux/clocksource.h>
37 #include <linux/clockchips.h>
38
39 #include <asm/mach/time.h>
40 #include <plat/dmtimer.h>
41 #include <asm/localtimer.h>
42 #include <asm/sched_clock.h>
43 #include <plat/common.h>
44 #include <plat/omap_hwmod.h>
45
46 /* Parent clocks, eventually these will come from the clock framework */
47
48 #define OMAP2_MPU_SOURCE        "sys_ck"
49 #define OMAP3_MPU_SOURCE        OMAP2_MPU_SOURCE
50 #define OMAP4_MPU_SOURCE        "sys_clkin_ck"
51 #define OMAP2_32K_SOURCE        "func_32k_ck"
52 #define OMAP3_32K_SOURCE        "omap_32k_fck"
53 #define OMAP4_32K_SOURCE        "sys_32k_ck"
54
55 #ifdef CONFIG_OMAP_32K_TIMER
56 #define OMAP2_CLKEV_SOURCE      OMAP2_32K_SOURCE
57 #define OMAP3_CLKEV_SOURCE      OMAP3_32K_SOURCE
58 #define OMAP4_CLKEV_SOURCE      OMAP4_32K_SOURCE
59 #define OMAP3_SECURE_TIMER      12
60 #else
61 #define OMAP2_CLKEV_SOURCE      OMAP2_MPU_SOURCE
62 #define OMAP3_CLKEV_SOURCE      OMAP3_MPU_SOURCE
63 #define OMAP4_CLKEV_SOURCE      OMAP4_MPU_SOURCE
64 #define OMAP3_SECURE_TIMER      1
65 #endif
66
67 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
68 #define MAX_GPTIMER_ID          12
69
70 u32 sys_timer_reserved;
71
72 /* Clockevent code */
73
74 static struct omap_dm_timer clkev;
75 static struct clock_event_device clockevent_gpt;
76
77 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
78 {
79         struct clock_event_device *evt = &clockevent_gpt;
80
81         __omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
82
83         evt->event_handler(evt);
84         return IRQ_HANDLED;
85 }
86
87 static struct irqaction omap2_gp_timer_irq = {
88         .name           = "gp timer",
89         .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
90         .handler        = omap2_gp_timer_interrupt,
91 };
92
93 static int omap2_gp_timer_set_next_event(unsigned long cycles,
94                                          struct clock_event_device *evt)
95 {
96         __omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
97                                                 0xffffffff - cycles, 1);
98
99         return 0;
100 }
101
102 static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
103                                     struct clock_event_device *evt)
104 {
105         u32 period;
106
107         __omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
108
109         switch (mode) {
110         case CLOCK_EVT_MODE_PERIODIC:
111                 period = clkev.rate / HZ;
112                 period -= 1;
113                 /* Looks like we need to first set the load value separately */
114                 __omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
115                                         0xffffffff - period, 1);
116                 __omap_dm_timer_load_start(clkev.io_base,
117                                         OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
118                                                 0xffffffff - period, 1);
119                 break;
120         case CLOCK_EVT_MODE_ONESHOT:
121                 break;
122         case CLOCK_EVT_MODE_UNUSED:
123         case CLOCK_EVT_MODE_SHUTDOWN:
124         case CLOCK_EVT_MODE_RESUME:
125                 break;
126         }
127 }
128
129 static struct clock_event_device clockevent_gpt = {
130         .name           = "gp timer",
131         .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
132         .shift          = 32,
133         .set_next_event = omap2_gp_timer_set_next_event,
134         .set_mode       = omap2_gp_timer_set_mode,
135 };
136
137 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
138                                                 int gptimer_id,
139                                                 const char *fck_source)
140 {
141         char name[10]; /* 10 = sizeof("gptXX_Xck0") */
142         struct omap_hwmod *oh;
143         size_t size;
144         int res = 0;
145
146         sprintf(name, "timer%d", gptimer_id);
147         omap_hwmod_setup_one(name);
148         oh = omap_hwmod_lookup(name);
149         if (!oh)
150                 return -ENODEV;
151
152         timer->irq = oh->mpu_irqs[0].irq;
153         timer->phys_base = oh->slaves[0]->addr->pa_start;
154         size = oh->slaves[0]->addr->pa_end - timer->phys_base;
155
156         /* Static mapping, never released */
157         timer->io_base = ioremap(timer->phys_base, size);
158         if (!timer->io_base)
159                 return -ENXIO;
160
161         /* After the dmtimer is using hwmod these clocks won't be needed */
162         sprintf(name, "gpt%d_fck", gptimer_id);
163         timer->fclk = clk_get(NULL, name);
164         if (IS_ERR(timer->fclk))
165                 return -ENODEV;
166
167         sprintf(name, "gpt%d_ick", gptimer_id);
168         timer->iclk = clk_get(NULL, name);
169         if (IS_ERR(timer->iclk)) {
170                 clk_put(timer->fclk);
171                 return -ENODEV;
172         }
173
174         omap_hwmod_enable(oh);
175
176         sys_timer_reserved |= (1 << (gptimer_id - 1));
177
178         if (gptimer_id != 12) {
179                 struct clk *src;
180
181                 src = clk_get(NULL, fck_source);
182                 if (IS_ERR(src)) {
183                         res = -EINVAL;
184                 } else {
185                         res = __omap_dm_timer_set_source(timer->fclk, src);
186                         if (IS_ERR_VALUE(res))
187                                 pr_warning("%s: timer%i cannot set source\n",
188                                                 __func__, gptimer_id);
189                         clk_put(src);
190                 }
191         }
192         __omap_dm_timer_reset(timer->io_base, 1, 1);
193         timer->posted = 1;
194
195         timer->rate = clk_get_rate(timer->fclk);
196
197         timer->reserved = 1;
198
199         return res;
200 }
201
202 static void __init omap2_gp_clockevent_init(int gptimer_id,
203                                                 const char *fck_source)
204 {
205         int res;
206
207         res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
208         BUG_ON(res);
209
210         omap2_gp_timer_irq.dev_id = (void *)&clkev;
211         setup_irq(clkev.irq, &omap2_gp_timer_irq);
212
213         __omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
214
215         clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
216                                      clockevent_gpt.shift);
217         clockevent_gpt.max_delta_ns =
218                 clockevent_delta2ns(0xffffffff, &clockevent_gpt);
219         clockevent_gpt.min_delta_ns =
220                 clockevent_delta2ns(3, &clockevent_gpt);
221                 /* Timer internal resynch latency. */
222
223         clockevent_gpt.cpumask = cpumask_of(0);
224         clockevents_register_device(&clockevent_gpt);
225
226         pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
227                 gptimer_id, clkev.rate);
228 }
229
230 /* Clocksource code */
231
232 #ifdef CONFIG_OMAP_32K_TIMER
233 /*
234  * When 32k-timer is enabled, don't use GPTimer for clocksource
235  * instead, just leave default clocksource which uses the 32k
236  * sync counter.  See clocksource setup in plat-omap/counter_32k.c
237  */
238
239 static void __init omap2_gp_clocksource_init(int unused, const char *dummy)
240 {
241         omap_init_clocksource_32k();
242 }
243
244 #else
245
246 static struct omap_dm_timer clksrc;
247
248 /*
249  * clocksource
250  */
251 static DEFINE_CLOCK_DATA(cd);
252 static cycle_t clocksource_read_cycles(struct clocksource *cs)
253 {
254         return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
255 }
256
257 static struct clocksource clocksource_gpt = {
258         .name           = "gp timer",
259         .rating         = 300,
260         .read           = clocksource_read_cycles,
261         .mask           = CLOCKSOURCE_MASK(32),
262         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
263 };
264
265 static void notrace dmtimer_update_sched_clock(void)
266 {
267         u32 cyc;
268
269         cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
270
271         update_sched_clock(&cd, cyc, (u32)~0);
272 }
273
274 unsigned long long notrace sched_clock(void)
275 {
276         u32 cyc = 0;
277
278         if (clksrc.reserved)
279                 cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
280
281         return cyc_to_sched_clock(&cd, cyc, (u32)~0);
282 }
283
284 /* Setup free-running counter for clocksource */
285 static void __init omap2_gp_clocksource_init(int gptimer_id,
286                                                 const char *fck_source)
287 {
288         int res;
289
290         res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
291         BUG_ON(res);
292
293         pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
294                 gptimer_id, clksrc.rate);
295
296         __omap_dm_timer_load_start(clksrc.io_base,
297                         OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
298         init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
299
300         if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
301                 pr_err("Could not register clocksource %s\n",
302                         clocksource_gpt.name);
303 }
304 #endif
305
306 #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src,                  \
307                                 clksrc_nr, clksrc_src)                  \
308 static void __init omap##name##_timer_init(void)                        \
309 {                                                                       \
310         omap2_gp_clockevent_init((clkev_nr), clkev_src);                \
311         omap2_gp_clocksource_init((clksrc_nr), clksrc_src);             \
312 }
313
314 #define OMAP_SYS_TIMER(name)                                            \
315 struct sys_timer omap##name##_timer = {                                 \
316         .init   = omap##name##_timer_init,                              \
317 };
318
319 #ifdef CONFIG_ARCH_OMAP2
320 OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
321 OMAP_SYS_TIMER(2)
322 #endif
323
324 #ifdef CONFIG_ARCH_OMAP3
325 OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
326 OMAP_SYS_TIMER(3)
327 OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
328                         2, OMAP3_MPU_SOURCE)
329 OMAP_SYS_TIMER(3_secure)
330 #endif
331
332 #ifdef CONFIG_ARCH_OMAP4
333 static void __init omap4_timer_init(void)
334 {
335 #ifdef CONFIG_LOCAL_TIMERS
336         twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
337         BUG_ON(!twd_base);
338 #endif
339         omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
340         omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
341 }
342 OMAP_SYS_TIMER(4)
343 #endif