summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index a135d28e202..63229c5287e 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)
}
}
+/**
+ * omap_dm_timer_get_errata - get errata flags for a timer
+ *
+ * Get the timer errata flags that are specific to the OMAP device being used.
+ */
+u32 __init omap_dm_timer_get_errata(void)
+{
+ if (cpu_is_omap24xx())
+ return 0;
+
+ return OMAP_TIMER_ERRATA_I103_I767;
+}
+
static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
int gptimer_id,
const char *fck_source,
- const char *property)
+ const char *property,
+ int posted)
{
char name[10]; /* 10 = sizeof("gptXX_Xck0") */
const char *oh_name;
@@ -311,10 +325,15 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
}
__omap_dm_timer_init_regs(timer);
__omap_dm_timer_reset(timer, 1, 1);
- timer->posted = 1;
- timer->rate = clk_get_rate(timer->fclk);
+ if (posted)
+ __omap_dm_timer_enable_posted(timer);
+
+ /* Check that the intended posted configuration matches the actual */
+ if (posted != timer->posted)
+ return -EINVAL;
+ timer->rate = clk_get_rate(timer->fclk);
timer->reserved = 1;
return res;
@@ -326,7 +345,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
{
int res;
- res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property);
+ clkev.errata = omap_dm_timer_get_errata();
+
+ /*
+ * For clock-event timers we never read the timer counter and
+ * so we are not impacted by errata i103 and i767. Therefore,
+ * we can safely ignore this errata for clock-event timers.
+ */
+ __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
+
+ res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
+ OMAP_TIMER_POSTED);
BUG_ON(res);
omap2_gp_timer_irq.dev_id = &clkev;
@@ -360,7 +389,7 @@ static bool use_gptimer_clksrc;
static cycle_t clocksource_read_cycles(struct clocksource *cs)
{
return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
- OMAP_TIMER_POSTED);
+ OMAP_TIMER_NONPOSTED);
}
static struct clocksource clocksource_gpt = {
@@ -375,7 +404,7 @@ static u32 notrace dmtimer_read_sched_clock(void)
{
if (clksrc.reserved)
return __omap_dm_timer_read_counter(&clksrc,
- OMAP_TIMER_POSTED);
+ OMAP_TIMER_NONPOSTED);
return 0;
}
@@ -453,12 +482,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
{
int res;
- res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL);
+ clksrc.errata = omap_dm_timer_get_errata();
+
+ res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
+ OMAP_TIMER_NONPOSTED);
BUG_ON(res);
__omap_dm_timer_load_start(&clksrc,
OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
- OMAP_TIMER_POSTED);
+ OMAP_TIMER_NONPOSTED);
setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
@@ -696,6 +728,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
if (timer_dev_attr)
pdata->timer_capability = timer_dev_attr->timer_capability;
+ pdata->timer_errata = omap_dm_timer_get_errata();
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),