aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-davinci/time.c')
-rw-r--r--arch/arm/mach-davinci/time.c247
1 files changed, 150 insertions, 97 deletions
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 494e01bff5c3..0884ca57bfb0 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -19,6 +19,7 @@
19#include <linux/clk.h> 19#include <linux/clk.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/platform_device.h>
22 23
23#include <mach/hardware.h> 24#include <mach/hardware.h>
24#include <asm/system.h> 25#include <asm/system.h>
@@ -28,52 +29,41 @@
28#include <asm/errno.h> 29#include <asm/errno.h>
29#include <mach/io.h> 30#include <mach/io.h>
30#include <mach/cputype.h> 31#include <mach/cputype.h>
32#include <mach/time.h>
31#include "clock.h" 33#include "clock.h"
32 34
33static struct clock_event_device clockevent_davinci; 35static struct clock_event_device clockevent_davinci;
34static unsigned int davinci_clock_tick_rate; 36static unsigned int davinci_clock_tick_rate;
35 37
36#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
37#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
38#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
39
40enum {
41 T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
42};
43
44#define IS_TIMER1(id) (id & 0x2)
45#define IS_TIMER0(id) (!IS_TIMER1(id))
46#define IS_TIMER_TOP(id) ((id & 0x1))
47#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
48
49static int timer_irqs[NUM_TIMERS] = {
50 IRQ_TINT0_TINT12,
51 IRQ_TINT0_TINT34,
52 IRQ_TINT1_TINT12,
53 IRQ_TINT1_TINT34,
54};
55
56/* 38/*
57 * This driver configures the 2 64-bit count-up timers as 4 independent 39 * This driver configures the 2 64-bit count-up timers as 4 independent
58 * 32-bit count-up timers used as follows: 40 * 32-bit count-up timers used as follows:
59 *
60 * T0_BOT: Timer 0, bottom: clockevent source for hrtimers
61 * T0_TOP: Timer 0, top : clocksource for generic timekeeping
62 * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
63 * T1_TOP: Timer 1, top : <unused>
64 */ 41 */
65#define TID_CLOCKEVENT T0_BOT 42
66#define TID_CLOCKSOURCE T0_TOP 43enum {
44 TID_CLOCKEVENT,
45 TID_CLOCKSOURCE,
46};
67 47
68/* Timer register offsets */ 48/* Timer register offsets */
69#define PID12 0x0 49#define PID12 0x0
70#define TIM12 0x10 50#define TIM12 0x10
71#define TIM34 0x14 51#define TIM34 0x14
72#define PRD12 0x18 52#define PRD12 0x18
73#define PRD34 0x1c 53#define PRD34 0x1c
74#define TCR 0x20 54#define TCR 0x20
75#define TGCR 0x24 55#define TGCR 0x24
76#define WDTCR 0x28 56#define WDTCR 0x28
57
58/* Offsets of the 8 compare registers */
59#define CMP12_0 0x60
60#define CMP12_1 0x64
61#define CMP12_2 0x68
62#define CMP12_3 0x6c
63#define CMP12_4 0x70
64#define CMP12_5 0x74
65#define CMP12_6 0x78
66#define CMP12_7 0x7c
77 67
78/* Timer register bitfields */ 68/* Timer register bitfields */
79#define TCR_ENAMODE_DISABLE 0x0 69#define TCR_ENAMODE_DISABLE 0x0
@@ -105,6 +95,7 @@ struct timer_s {
105 unsigned int id; 95 unsigned int id;
106 unsigned long period; 96 unsigned long period;
107 unsigned long opts; 97 unsigned long opts;
98 unsigned long flags;
108 void __iomem *base; 99 void __iomem *base;
109 unsigned long tim_off; 100 unsigned long tim_off;
110 unsigned long prd_off; 101 unsigned long prd_off;
@@ -114,30 +105,58 @@ struct timer_s {
114static struct timer_s timers[]; 105static struct timer_s timers[];
115 106
116/* values for 'opts' field of struct timer_s */ 107/* values for 'opts' field of struct timer_s */
117#define TIMER_OPTS_DISABLED 0x00 108#define TIMER_OPTS_DISABLED 0x01
118#define TIMER_OPTS_ONESHOT 0x01 109#define TIMER_OPTS_ONESHOT 0x02
119#define TIMER_OPTS_PERIODIC 0x02 110#define TIMER_OPTS_PERIODIC 0x04
111#define TIMER_OPTS_STATE_MASK 0x07
112
113#define TIMER_OPTS_USE_COMPARE 0x80000000
114#define USING_COMPARE(t) ((t)->opts & TIMER_OPTS_USE_COMPARE)
115
116static char *id_to_name[] = {
117 [T0_BOT] = "timer0_0",
118 [T0_TOP] = "timer0_1",
119 [T1_BOT] = "timer1_0",
120 [T1_TOP] = "timer1_1",
121};
120 122
121static int timer32_config(struct timer_s *t) 123static int timer32_config(struct timer_s *t)
122{ 124{
123 u32 tcr = __raw_readl(t->base + TCR); 125 u32 tcr;
124 126 struct davinci_soc_info *soc_info = &davinci_soc_info;
125 /* disable timer */ 127
126 tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); 128 if (USING_COMPARE(t)) {
127 __raw_writel(tcr, t->base + TCR); 129 struct davinci_timer_instance *dtip =
128 130 soc_info->timer_info->timers;
129 /* reset counter to zero, set new period */ 131 int event_timer = ID_TO_TIMER(timers[TID_CLOCKEVENT].id);
130 __raw_writel(0, t->base + t->tim_off); 132
131 __raw_writel(t->period, t->base + t->prd_off); 133 /*
132 134 * Next interrupt should be the current time reg value plus
133 /* Set enable mode */ 135 * the new period (using 32-bit unsigned addition/wrapping
134 if (t->opts & TIMER_OPTS_ONESHOT) { 136 * to 0 on overflow). This assumes that the clocksource
135 tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift; 137 * is setup to count to 2^32-1 before wrapping around to 0.
136 } else if (t->opts & TIMER_OPTS_PERIODIC) { 138 */
137 tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; 139 __raw_writel(__raw_readl(t->base + t->tim_off) + t->period,
140 t->base + dtip[event_timer].cmp_off);
141 } else {
142 tcr = __raw_readl(t->base + TCR);
143
144 /* disable timer */
145 tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
146 __raw_writel(tcr, t->base + TCR);
147
148 /* reset counter to zero, set new period */
149 __raw_writel(0, t->base + t->tim_off);
150 __raw_writel(t->period, t->base + t->prd_off);
151
152 /* Set enable mode */
153 if (t->opts & TIMER_OPTS_ONESHOT)
154 tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
155 else if (t->opts & TIMER_OPTS_PERIODIC)
156 tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
157
158 __raw_writel(tcr, t->base + TCR);
138 } 159 }
139
140 __raw_writel(tcr, t->base + TCR);
141 return 0; 160 return 0;
142} 161}
143 162
@@ -182,13 +201,14 @@ static struct timer_s timers[] = {
182 201
183static void __init timer_init(void) 202static void __init timer_init(void)
184{ 203{
185 u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; 204 struct davinci_soc_info *soc_info = &davinci_soc_info;
205 struct davinci_timer_instance *dtip = soc_info->timer_info->timers;
186 int i; 206 int i;
187 207
188 /* Global init of each 64-bit timer as a whole */ 208 /* Global init of each 64-bit timer as a whole */
189 for(i=0; i<2; i++) { 209 for(i=0; i<2; i++) {
190 u32 tgcr; 210 u32 tgcr;
191 void __iomem *base = IO_ADDRESS(phys_bases[i]); 211 void __iomem *base = dtip[i].base;
192 212
193 /* Disabled, Internal clock source */ 213 /* Disabled, Internal clock source */
194 __raw_writel(0, base + TCR); 214 __raw_writel(0, base + TCR);
@@ -214,33 +234,33 @@ static void __init timer_init(void)
214 /* Init of each timer as a 32-bit timer */ 234 /* Init of each timer as a 32-bit timer */
215 for (i=0; i< ARRAY_SIZE(timers); i++) { 235 for (i=0; i< ARRAY_SIZE(timers); i++) {
216 struct timer_s *t = &timers[i]; 236 struct timer_s *t = &timers[i];
217 u32 phys_base; 237 int timer = ID_TO_TIMER(t->id);
218 238 u32 irq;
219 if (t->name) { 239
220 t->id = i; 240 t->base = dtip[timer].base;
221 phys_base = (IS_TIMER1(t->id) ? 241
222 DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); 242 if (IS_TIMER_BOT(t->id)) {
223 t->base = IO_ADDRESS(phys_base); 243 t->enamode_shift = 6;
224 244 t->tim_off = TIM12;
225 if (IS_TIMER_BOT(t->id)) { 245 t->prd_off = PRD12;
226 t->enamode_shift = 6; 246 irq = dtip[timer].bottom_irq;
227 t->tim_off = TIM12; 247 } else {
228 t->prd_off = PRD12; 248 t->enamode_shift = 22;
229 } else { 249 t->tim_off = TIM34;
230 t->enamode_shift = 22; 250 t->prd_off = PRD34;
231 t->tim_off = TIM34; 251 irq = dtip[timer].top_irq;
232 t->prd_off = PRD34; 252 }
233 } 253
234 254 /* Register interrupt */
235 /* Register interrupt */ 255 t->irqaction.name = t->name;
236 t->irqaction.name = t->name; 256 t->irqaction.dev_id = (void *)t;
237 t->irqaction.dev_id = (void *)t; 257
238 if (t->irqaction.handler != NULL) { 258 if (t->irqaction.handler != NULL) {
239 setup_irq(timer_irqs[t->id], &t->irqaction); 259 irq = USING_COMPARE(t) ? dtip[i].cmp_irq : irq;
240 } 260 setup_irq(irq, &t->irqaction);
241
242 timer32_config(&timers[i]);
243 } 261 }
262
263 timer32_config(&timers[i]);
244 } 264 }
245} 265}
246 266
@@ -255,7 +275,6 @@ static cycle_t read_cycles(struct clocksource *cs)
255} 275}
256 276
257static struct clocksource clocksource_davinci = { 277static struct clocksource clocksource_davinci = {
258 .name = "timer0_1",
259 .rating = 300, 278 .rating = 300,
260 .read = read_cycles, 279 .read = read_cycles,
261 .mask = CLOCKSOURCE_MASK(32), 280 .mask = CLOCKSOURCE_MASK(32),
@@ -284,15 +303,18 @@ static void davinci_set_mode(enum clock_event_mode mode,
284 switch (mode) { 303 switch (mode) {
285 case CLOCK_EVT_MODE_PERIODIC: 304 case CLOCK_EVT_MODE_PERIODIC:
286 t->period = davinci_clock_tick_rate / (HZ); 305 t->period = davinci_clock_tick_rate / (HZ);
287 t->opts = TIMER_OPTS_PERIODIC; 306 t->opts &= ~TIMER_OPTS_STATE_MASK;
307 t->opts |= TIMER_OPTS_PERIODIC;
288 timer32_config(t); 308 timer32_config(t);
289 break; 309 break;
290 case CLOCK_EVT_MODE_ONESHOT: 310 case CLOCK_EVT_MODE_ONESHOT:
291 t->opts = TIMER_OPTS_ONESHOT; 311 t->opts &= ~TIMER_OPTS_STATE_MASK;
312 t->opts |= TIMER_OPTS_ONESHOT;
292 break; 313 break;
293 case CLOCK_EVT_MODE_UNUSED: 314 case CLOCK_EVT_MODE_UNUSED:
294 case CLOCK_EVT_MODE_SHUTDOWN: 315 case CLOCK_EVT_MODE_SHUTDOWN:
295 t->opts = TIMER_OPTS_DISABLED; 316 t->opts &= ~TIMER_OPTS_STATE_MASK;
317 t->opts |= TIMER_OPTS_DISABLED;
296 break; 318 break;
297 case CLOCK_EVT_MODE_RESUME: 319 case CLOCK_EVT_MODE_RESUME:
298 break; 320 break;
@@ -300,7 +322,6 @@ static void davinci_set_mode(enum clock_event_mode mode,
300} 322}
301 323
302static struct clock_event_device clockevent_davinci = { 324static struct clock_event_device clockevent_davinci = {
303 .name = "timer0_0",
304 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 325 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
305 .shift = 32, 326 .shift = 32,
306 .set_next_event = davinci_set_next_event, 327 .set_next_event = davinci_set_next_event,
@@ -311,10 +332,42 @@ static struct clock_event_device clockevent_davinci = {
311static void __init davinci_timer_init(void) 332static void __init davinci_timer_init(void)
312{ 333{
313 struct clk *timer_clk; 334 struct clk *timer_clk;
314 335 struct davinci_soc_info *soc_info = &davinci_soc_info;
336 unsigned int clockevent_id;
337 unsigned int clocksource_id;
315 static char err[] __initdata = KERN_ERR 338 static char err[] __initdata = KERN_ERR
316 "%s: can't register clocksource!\n"; 339 "%s: can't register clocksource!\n";
317 340
341 clockevent_id = soc_info->timer_info->clockevent_id;
342 clocksource_id = soc_info->timer_info->clocksource_id;
343
344 timers[TID_CLOCKEVENT].id = clockevent_id;
345 timers[TID_CLOCKSOURCE].id = clocksource_id;
346
347 /*
348 * If using same timer for both clock events & clocksource,
349 * a compare register must be used to generate an event interrupt.
350 * This is equivalent to a oneshot timer only (not periodic).
351 */
352 if (clockevent_id == clocksource_id) {
353 struct davinci_timer_instance *dtip =
354 soc_info->timer_info->timers;
355 int event_timer = ID_TO_TIMER(clockevent_id);
356
357 /* Only bottom timers can use compare regs */
358 if (IS_TIMER_TOP(clockevent_id))
359 pr_warning("davinci_timer_init: Invalid use"
360 " of system timers. Results unpredictable.\n");
361 else if ((dtip[event_timer].cmp_off == 0)
362 || (dtip[event_timer].cmp_irq == 0))
363 pr_warning("davinci_timer_init: Invalid timer instance"
364 " setup. Results unpredictable.\n");
365 else {
366 timers[TID_CLOCKEVENT].opts |= TIMER_OPTS_USE_COMPARE;
367 clockevent_davinci.features = CLOCK_EVT_FEAT_ONESHOT;
368 }
369 }
370
318 /* init timer hw */ 371 /* init timer hw */
319 timer_init(); 372 timer_init();
320 373
@@ -325,6 +378,7 @@ static void __init davinci_timer_init(void)
325 davinci_clock_tick_rate = clk_get_rate(timer_clk); 378 davinci_clock_tick_rate = clk_get_rate(timer_clk);
326 379
327 /* setup clocksource */ 380 /* setup clocksource */
381 clocksource_davinci.name = id_to_name[clocksource_id];
328 clocksource_davinci.mult = 382 clocksource_davinci.mult =
329 clocksource_khz2mult(davinci_clock_tick_rate/1000, 383 clocksource_khz2mult(davinci_clock_tick_rate/1000,
330 clocksource_davinci.shift); 384 clocksource_davinci.shift);
@@ -332,12 +386,12 @@ static void __init davinci_timer_init(void)
332 printk(err, clocksource_davinci.name); 386 printk(err, clocksource_davinci.name);
333 387
334 /* setup clockevent */ 388 /* setup clockevent */
389 clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
335 clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, 390 clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
336 clockevent_davinci.shift); 391 clockevent_davinci.shift);
337 clockevent_davinci.max_delta_ns = 392 clockevent_davinci.max_delta_ns =
338 clockevent_delta2ns(0xfffffffe, &clockevent_davinci); 393 clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
339 clockevent_davinci.min_delta_ns = 394 clockevent_davinci.min_delta_ns = 50000; /* 50 usec */
340 clockevent_delta2ns(1, &clockevent_davinci);
341 395
342 clockevent_davinci.cpumask = cpumask_of(0); 396 clockevent_davinci.cpumask = cpumask_of(0);
343 clockevents_register_device(&clockevent_davinci); 397 clockevents_register_device(&clockevent_davinci);
@@ -349,15 +403,14 @@ struct sys_timer davinci_timer = {
349 403
350 404
351/* reset board using watchdog timer */ 405/* reset board using watchdog timer */
352void davinci_watchdog_reset(void) { 406void davinci_watchdog_reset(void)
407{
353 u32 tgcr, wdtcr; 408 u32 tgcr, wdtcr;
354 void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE); 409 struct davinci_soc_info *soc_info = &davinci_soc_info;
355 struct device dev; 410 void __iomem *base = soc_info->wdt_base;
356 struct clk *wd_clk; 411 struct clk *wd_clk;
357 char *name = "watchdog";
358 412
359 dev_set_name(&dev, name); 413 wd_clk = clk_get(&davinci_wdt_device.dev, NULL);
360 wd_clk = clk_get(&dev, NULL);
361 if (WARN_ON(IS_ERR(wd_clk))) 414 if (WARN_ON(IS_ERR(wd_clk)))
362 return; 415 return;
363 clk_enable(wd_clk); 416 clk_enable(wd_clk);