diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index a135d28e202c..63229c5287e6 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -222,10 +222,24 @@ void __init omap_dmtimer_init(void) | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | /** | ||
226 | * omap_dm_timer_get_errata - get errata flags for a timer | ||
227 | * | ||
228 | * Get the timer errata flags that are specific to the OMAP device being used. | ||
229 | */ | ||
230 | u32 __init omap_dm_timer_get_errata(void) | ||
231 | { | ||
232 | if (cpu_is_omap24xx()) | ||
233 | return 0; | ||
234 | |||
235 | return OMAP_TIMER_ERRATA_I103_I767; | ||
236 | } | ||
237 | |||
225 | static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, | 238 | static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, |
226 | int gptimer_id, | 239 | int gptimer_id, |
227 | const char *fck_source, | 240 | const char *fck_source, |
228 | const char *property) | 241 | const char *property, |
242 | int posted) | ||
229 | { | 243 | { |
230 | char name[10]; /* 10 = sizeof("gptXX_Xck0") */ | 244 | char name[10]; /* 10 = sizeof("gptXX_Xck0") */ |
231 | const char *oh_name; | 245 | const char *oh_name; |
@@ -311,10 +325,15 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, | |||
311 | } | 325 | } |
312 | __omap_dm_timer_init_regs(timer); | 326 | __omap_dm_timer_init_regs(timer); |
313 | __omap_dm_timer_reset(timer, 1, 1); | 327 | __omap_dm_timer_reset(timer, 1, 1); |
314 | timer->posted = 1; | ||
315 | 328 | ||
316 | timer->rate = clk_get_rate(timer->fclk); | 329 | if (posted) |
330 | __omap_dm_timer_enable_posted(timer); | ||
331 | |||
332 | /* Check that the intended posted configuration matches the actual */ | ||
333 | if (posted != timer->posted) | ||
334 | return -EINVAL; | ||
317 | 335 | ||
336 | timer->rate = clk_get_rate(timer->fclk); | ||
318 | timer->reserved = 1; | 337 | timer->reserved = 1; |
319 | 338 | ||
320 | return res; | 339 | return res; |
@@ -326,7 +345,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, | |||
326 | { | 345 | { |
327 | int res; | 346 | int res; |
328 | 347 | ||
329 | res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property); | 348 | clkev.errata = omap_dm_timer_get_errata(); |
349 | |||
350 | /* | ||
351 | * For clock-event timers we never read the timer counter and | ||
352 | * so we are not impacted by errata i103 and i767. Therefore, | ||
353 | * we can safely ignore this errata for clock-event timers. | ||
354 | */ | ||
355 | __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767); | ||
356 | |||
357 | res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property, | ||
358 | OMAP_TIMER_POSTED); | ||
330 | BUG_ON(res); | 359 | BUG_ON(res); |
331 | 360 | ||
332 | omap2_gp_timer_irq.dev_id = &clkev; | 361 | omap2_gp_timer_irq.dev_id = &clkev; |
@@ -360,7 +389,7 @@ static bool use_gptimer_clksrc; | |||
360 | static cycle_t clocksource_read_cycles(struct clocksource *cs) | 389 | static cycle_t clocksource_read_cycles(struct clocksource *cs) |
361 | { | 390 | { |
362 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, | 391 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, |
363 | OMAP_TIMER_POSTED); | 392 | OMAP_TIMER_NONPOSTED); |
364 | } | 393 | } |
365 | 394 | ||
366 | static struct clocksource clocksource_gpt = { | 395 | static struct clocksource clocksource_gpt = { |
@@ -375,7 +404,7 @@ static u32 notrace dmtimer_read_sched_clock(void) | |||
375 | { | 404 | { |
376 | if (clksrc.reserved) | 405 | if (clksrc.reserved) |
377 | return __omap_dm_timer_read_counter(&clksrc, | 406 | return __omap_dm_timer_read_counter(&clksrc, |
378 | OMAP_TIMER_POSTED); | 407 | OMAP_TIMER_NONPOSTED); |
379 | 408 | ||
380 | return 0; | 409 | return 0; |
381 | } | 410 | } |
@@ -453,12 +482,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id, | |||
453 | { | 482 | { |
454 | int res; | 483 | int res; |
455 | 484 | ||
456 | res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL); | 485 | clksrc.errata = omap_dm_timer_get_errata(); |
486 | |||
487 | res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL, | ||
488 | OMAP_TIMER_NONPOSTED); | ||
457 | BUG_ON(res); | 489 | BUG_ON(res); |
458 | 490 | ||
459 | __omap_dm_timer_load_start(&clksrc, | 491 | __omap_dm_timer_load_start(&clksrc, |
460 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, | 492 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, |
461 | OMAP_TIMER_POSTED); | 493 | OMAP_TIMER_NONPOSTED); |
462 | setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate); | 494 | setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate); |
463 | 495 | ||
464 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) | 496 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) |
@@ -696,6 +728,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) | |||
696 | if (timer_dev_attr) | 728 | if (timer_dev_attr) |
697 | pdata->timer_capability = timer_dev_attr->timer_capability; | 729 | pdata->timer_capability = timer_dev_attr->timer_capability; |
698 | 730 | ||
731 | pdata->timer_errata = omap_dm_timer_get_errata(); | ||
699 | pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; | 732 | pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; |
700 | 733 | ||
701 | pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata), | 734 | pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata), |