Merge branch 'agp-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / arch / arm / mach-omap2 / omap_hwmod.c
index 633b216..d8c8545 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/mutex.h>
 #include <linux/bootmem.h>
 
+#include <plat/common.h>
 #include <plat/cpu.h>
 #include <plat/clockdomain.h>
 #include <plat/powerdomain.h>
@@ -209,6 +210,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v
+ * @oh: struct omap_hwmod *
+ * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
+ * @v: pointer to register contents to modify
+ *
+ * Update the module autoidle bit in @v to be @autoidle for the @oh
+ * hwmod.  The autoidle bit controls whether the module can gate
+ * internal clocks automatically when it isn't doing anything; the
+ * exact function of this bit varies on a per-module basis.  This
+ * function does not write to the hardware.  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
+                               u32 *v)
+{
+       if (!oh->sysconfig ||
+           !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
+               return -EINVAL;
+
+       *v &= ~SYSC_AUTOIDLE_MASK;
+       *v |= autoidle << SYSC_AUTOIDLE_SHIFT;
+
+       return 0;
+}
+
 /**
  * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
  * @oh: struct omap_hwmod *
@@ -326,6 +353,9 @@ static int _init_main_clk(struct omap_hwmod *oh)
                ret = -EINVAL;
        oh->_clk = c;
 
+       WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n",
+            oh->clkdev_con_id, c->name);
+
        return ret;
 }
 
@@ -557,8 +587,19 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_master_standbymode(oh, idlemode, &v);
        }
 
-       /* XXX OCP AUTOIDLE bit? */
+       if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) {
+               idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
+                       0 : 1;
+               _set_module_autoidle(oh, idlemode, &v);
+       }
+
+       /* XXX OCP ENAWAKEUP bit? */
 
+       /*
+        * XXX The clock framework should handle this, by
+        * calling into this code.  But this must wait until the
+        * clock structures are tagged with omap_hwmod entries
+        */
        if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT &&
            oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)
                _set_clockactivity(oh, oh->sysconfig->clockact, &v);
@@ -622,7 +663,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh)
        if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)
                _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
 
-       /* XXX clear OCP AUTOIDLE bit? */
+       if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)
+               _set_module_autoidle(oh, 1, &v);
 
        _write_sysconfig(v, oh);
 }
@@ -736,7 +778,7 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 static int _reset(struct omap_hwmod *oh)
 {
        u32 r, v;
-       int c;
+       int c = 0;
 
        if (!oh->sysconfig ||
            !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) ||
@@ -758,13 +800,9 @@ static int _reset(struct omap_hwmod *oh)
                return r;
        _write_sysconfig(v, oh);
 
-       c = 0;
-       while (c < MAX_MODULE_RESET_WAIT &&
-              !(omap_hwmod_readl(oh, oh->sysconfig->syss_offs) &
-                SYSS_RESETDONE_MASK)) {
-               udelay(1);
-               c++;
-       }
+       omap_test_timeout((omap_hwmod_readl(oh, oh->sysconfig->syss_offs) &
+                          SYSS_RESETDONE_MASK),
+                         MAX_MODULE_RESET_WAIT, c);
 
        if (c == MAX_MODULE_RESET_WAIT)
                WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
@@ -883,33 +921,6 @@ static int _shutdown(struct omap_hwmod *oh)
        return 0;
 }
 
-/**
- * _write_clockact_lock - set the module's clockactivity bits
- * @oh: struct omap_hwmod *
- * @clockact: CLOCKACTIVITY field bits
- *
- * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
- * wrong state or returns 0.
- */
-static int _write_clockact_lock(struct omap_hwmod *oh, u8 clockact)
-{
-       u32 v;
-
-       if (!oh->sysconfig ||
-           !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
-               return -EINVAL;
-
-       mutex_lock(&omap_hwmod_mutex);
-       v = oh->_sysc_cache;
-       _set_clockactivity(oh, clockact, &v);
-       _write_sysconfig(v, oh);
-       mutex_unlock(&omap_hwmod_mutex);
-
-       return 0;
-}
-
-
 /**
  * _setup - do initial configuration of omap_hwmod
  * @oh: struct omap_hwmod *
@@ -948,11 +959,19 @@ static int _setup(struct omap_hwmod *oh)
 
        _enable(oh);
 
-       if (!(oh->flags & HWMOD_INIT_NO_RESET))
-               _reset(oh);
-
-       /* XXX OCP AUTOIDLE bit? */
-       /* XXX OCP ENAWAKEUP bit? */
+       if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+               /*
+                * XXX Do the OCP_SYSCONFIG bits need to be
+                * reprogrammed after a reset?  If not, then this can
+                * be removed.  If they do, then probably the
+                * _enable() function should be split to avoid the
+                * rewrite of the OCP_SYSCONFIG register.
+                */
+               if (oh->sysconfig) {
+                       _update_sysc_cache(oh);
+                       _sysc_enable(oh);
+               }
+       }
 
        if (!(oh->flags & HWMOD_INIT_NO_IDLE))
                _idle(oh);
@@ -1348,8 +1367,9 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
        /* For each IRQ, DMA, memory area, fill in array.*/
 
        for (i = 0; i < oh->mpu_irqs_cnt; i++) {
-               (res + r)->start = *(oh->mpu_irqs + i);
-               (res + r)->end = *(oh->mpu_irqs + i);
+               (res + r)->name = (oh->mpu_irqs + i)->name;
+               (res + r)->start = (oh->mpu_irqs + i)->irq;
+               (res + r)->end = (oh->mpu_irqs + i)->irq;
                (res + r)->flags = IORESOURCE_IRQ;
                r++;
        }
@@ -1453,62 +1473,6 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
        return _del_initiator_dep(oh, init_oh);
 }
 
-/**
- * omap_hwmod_set_clockact_none - set clockactivity test to BOTH
- * @oh: struct omap_hwmod *
- *
- * On some modules, this function can affect the wakeup latency vs.
- * power consumption balance.  Intended to be called by the
- * omap_device layer.  Passes along the return value from
- * _write_clockact_lock().
- */
-int omap_hwmod_set_clockact_both(struct omap_hwmod *oh)
-{
-       return _write_clockact_lock(oh, CLOCKACT_TEST_BOTH);
-}
-
-/**
- * omap_hwmod_set_clockact_none - set clockactivity test to MAIN
- * @oh: struct omap_hwmod *
- *
- * On some modules, this function can affect the wakeup latency vs.
- * power consumption balance.  Intended to be called by the
- * omap_device layer.  Passes along the return value from
- * _write_clockact_lock().
- */
-int omap_hwmod_set_clockact_main(struct omap_hwmod *oh)
-{
-       return _write_clockact_lock(oh, CLOCKACT_TEST_MAIN);
-}
-
-/**
- * omap_hwmod_set_clockact_none - set clockactivity test to ICLK
- * @oh: struct omap_hwmod *
- *
- * On some modules, this function can affect the wakeup latency vs.
- * power consumption balance.  Intended to be called by the
- * omap_device layer.  Passes along the return value from
- * _write_clockact_lock().
- */
-int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh)
-{
-       return _write_clockact_lock(oh, CLOCKACT_TEST_ICLK);
-}
-
-/**
- * omap_hwmod_set_clockact_none - set clockactivity test to NONE
- * @oh: struct omap_hwmod *
- *
- * On some modules, this function can affect the wakeup latency vs.
- * power consumption balance.  Intended to be called by the
- * omap_device layer.  Passes along the return value from
- * _write_clockact_lock().
- */
-int omap_hwmod_set_clockact_none(struct omap_hwmod *oh)
-{
-       return _write_clockact_lock(oh, CLOCKACT_TEST_NONE);
-}
-
 /**
  * omap_hwmod_enable_wakeup - allow device to wake up the system
  * @oh: struct omap_hwmod *