ARM: OMAP3: PM: remove access to PRM_VOLTCTRL register
[pandora-kernel.git] / arch / arm / mach-omap2 / timer.c
index e49fc7b..ad273b7 100644 (file)
@@ -90,7 +90,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 }
 
 static struct irqaction omap2_gp_timer_irq = {
-       .name           = "gp timer",
+       .name           = "gp_timer",
        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = omap2_gp_timer_interrupt,
 };
@@ -99,7 +99,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
                                         struct clock_event_device *evt)
 {
        __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
-                                               0xffffffff - cycles, 1);
+                                  0xffffffff - cycles, OMAP_TIMER_POSTED);
 
        return 0;
 }
@@ -109,7 +109,7 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 {
        u32 period;
 
-       __omap_dm_timer_stop(&clkev, 1, clkev.rate);
+       __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
@@ -117,10 +117,10 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
                period -= 1;
                /* Looks like we need to first set the load value separately */
                __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
-                                       0xffffffff - period, 1);
+                                     0xffffffff - period, OMAP_TIMER_POSTED);
                __omap_dm_timer_load_start(&clkev,
                                        OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
-                                               0xffffffff - period, 1);
+                                       0xffffffff - period, OMAP_TIMER_POSTED);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                break;
@@ -132,16 +132,30 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 }
 
 static struct clock_event_device clockevent_gpt = {
-       .name           = "gp timer",
+       .name           = "gp_timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .shift          = 32,
        .set_next_event = omap2_gp_timer_set_next_event,
        .set_mode       = omap2_gp_timer_set_mode,
 };
 
+/**
+ * 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 *fck_source,
+                                               int posted)
 {
        char name[10]; /* 10 = sizeof("gptXX_Xck0") */
        struct omap_hwmod *oh;
@@ -169,13 +183,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
        if (IS_ERR(timer->fclk))
                return -ENODEV;
 
-       sprintf(name, "gpt%d_ick", gptimer_id);
-       timer->iclk = clk_get(NULL, name);
-       if (IS_ERR(timer->iclk)) {
-               clk_put(timer->fclk);
-               return -ENODEV;
-       }
-
        omap_hwmod_enable(oh);
 
        sys_timer_reserved |= (1 << (gptimer_id - 1));
@@ -196,10 +203,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;
@@ -210,7 +222,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 {
        int res;
 
-       res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
+       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,
+                                    OMAP_TIMER_POSTED);
        BUG_ON(res);
 
        omap2_gp_timer_irq.dev_id = (void *)&clkev;
@@ -254,37 +276,27 @@ static struct omap_dm_timer clksrc;
 /*
  * clocksource
  */
-static DEFINE_CLOCK_DATA(cd);
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-       return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
+       return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
+                                                    OMAP_TIMER_NONPOSTED);
 }
 
 static struct clocksource clocksource_gpt = {
-       .name           = "gp timer",
+       .name           = "gp_timer",
        .rating         = 300,
        .read           = clocksource_read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static void notrace dmtimer_update_sched_clock(void)
-{
-       u32 cyc;
-
-       cyc = __omap_dm_timer_read_counter(&clksrc, 1);
-
-       update_sched_clock(&cd, cyc, (u32)~0);
-}
-
-unsigned long long notrace sched_clock(void)
+static u32 notrace dmtimer_read_sched_clock(void)
 {
-       u32 cyc = 0;
-
        if (clksrc.reserved)
-               cyc = __omap_dm_timer_read_counter(&clksrc, 1);
+               return __omap_dm_timer_read_counter(&clksrc,
+                                                   OMAP_TIMER_NONPOSTED);
 
-       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+       return 0;
 }
 
 /* Setup free-running counter for clocksource */
@@ -293,15 +305,19 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
 {
        int res;
 
-       res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
+       clksrc.errata = omap_dm_timer_get_errata();
+
+       res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source,
+                                    OMAP_TIMER_NONPOSTED);
        BUG_ON(res);
 
        pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
                gptimer_id, clksrc.rate);
 
        __omap_dm_timer_load_start(&clksrc,
-                       OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
-       init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
+                                  OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
+                                  OMAP_TIMER_NONPOSTED);
+       setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
 
        if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
                pr_err("Could not register clocksource %s\n",
@@ -408,14 +424,6 @@ static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
        return ret;
 }
 
-struct omap_device_pm_latency omap2_dmtimer_latency[] = {
-       {
-               .deactivate_func = omap_device_idle_hwmods,
-               .activate_func   = omap_device_enable_hwmods,
-               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-       },
-};
-
 /**
  * omap_timer_init - build and register timer device with an
  * associated timer hwmod
@@ -471,15 +479,14 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
        if ((sys_timer_reserved >> (id - 1)) & 0x1)
                pdata->reserved = 1;
 
+       pdata->timer_errata = omap_dm_timer_get_errata();
        pwrdm = omap_hwmod_get_pwrdm(oh);
        pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
 #ifdef CONFIG_PM
        pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 #endif
        pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
-                       omap2_dmtimer_latency,
-                       ARRAY_SIZE(omap2_dmtimer_latency),
-                       0);
+                                NULL, 0, 0);
 
        if (IS_ERR(pdev)) {
                pr_err("%s: Can't build omap_device for %s: %s.\n",