|
@@ -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),
|