]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/blobdiff - arch/arm/mach-omap2/omap_hwmod.c
arm: OMAP2+: hwmod: Extract enable-opt-clks-on-reset info from DT
[android-sdk/kernel-video.git] / arch / arm / mach-omap2 / omap_hwmod.c
index 1723f755fabd18a745916d4edfc331e5b923a3c6..2d5ea6b49f4a155a5e85d0eb622facf5c0d9f3b8 100644 (file)
@@ -2262,6 +2262,11 @@ static int _enable(struct omap_hwmod *oh)
  */
 static int _idle(struct omap_hwmod *oh)
 {
+       if (oh->flags & HWMOD_NO_IDLE) {
+               oh->_int_flags |= _HWMOD_SKIP_ENABLE;
+               return 0;
+       }
+
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -2477,6 +2482,9 @@ static int _setup_reidle(struct omap_hwmod *oh, void *data)
  * registers.  This address is needed early so the OCP registers that
  * are part of the device's address space can be ioremapped properly.
  *
+ * If SYSC access is not needed, the registers will not be remapped
+ * and non-availability of MPU access is not treated as an error.
+ *
  * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
  * -ENXIO on absent or invalid register target address space.
  */
@@ -2491,6 +2499,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
 
        _save_mpu_port_index(oh);
 
+       /* if we don't need sysc access we don't need to ioremap */
+       if (!oh->class->sysc)
+               return 0;
+
+       /* we can't continue without MPU PORT if we need sysc access */
        if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
                return -ENXIO;
 
@@ -2500,8 +2513,10 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
                         oh->name);
 
                /* Extract the IO space from device tree blob */
-               if (!np)
+               if (!np) {
+                       pr_err("omap_hwmod: %s: no dt node\n", oh->name);
                        return -ENXIO;
+               }
 
                va_start = of_iomap(np, index + oh->mpu_rt_idx);
        } else {
@@ -2560,13 +2575,11 @@ static int __init _init(struct omap_hwmod *oh, void *data)
                                oh->name, np->name);
        }
 
-       if (oh->class->sysc) {
-               r = _init_mpu_rt_base(oh, NULL, index, np);
-               if (r < 0) {
-                       WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
-                            oh->name);
-                       return 0;
-               }
+       r = _init_mpu_rt_base(oh, NULL, index, np);
+       if (r < 0) {
+               WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+                    oh->name);
+               return 0;
        }
 
        r = _init_clocks(oh, NULL);
@@ -2580,8 +2593,12 @@ static int __init _init(struct omap_hwmod *oh, void *data)
                        oh->flags |= HWMOD_INIT_NO_RESET;
                if (of_find_property(np, "ti,no-idle-on-init", NULL))
                        oh->flags |= HWMOD_INIT_NO_IDLE;
+               if (of_find_property(np, "ti,enable-opt-clks-on-reset", NULL))
+                       oh->flags |= HWMOD_CONTROL_OPT_CLKS_IN_RESET;
                if (of_find_property(np, "ti,no-init", NULL))
                        oh->flags |= HWMOD_NO_INIT;
+               if (of_find_property(np, "ti,no-idle", NULL))
+                       oh->flags |= HWMOD_NO_IDLE;
        }
        if (oh->flags & HWMOD_NO_INIT)
                oh->_state = _HWMOD_STATE_DISABLED;
@@ -2710,7 +2727,7 @@ static void __init _setup_postsetup(struct omap_hwmod *oh)
         * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
         * it should be set by the core code as a runtime flag during startup
         */
-       if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
+       if ((oh->flags & (HWMOD_INIT_NO_IDLE | HWMOD_NO_IDLE)) &&
            (postsetup_state == _HWMOD_STATE_IDLE)) {
                oh->_int_flags |= _HWMOD_SKIP_ENABLE;
                postsetup_state = _HWMOD_STATE_ENABLED;
@@ -3268,6 +3285,22 @@ static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
                                oh->prcm.omap4.rstctrl_offs);
 }
 
+/**
+ * _reidle - enable then idle a single hwmod
+ *
+ * enables and then immediately reidles an hwmod, as certain hwmods may
+ * not have their sysconfig registers programmed in an idle friendly state
+ * by default
+ */
+static void _reidle(struct omap_hwmod *oh)
+{
+       pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+       omap_hwmod_enable(oh);
+       omap_hwmod_softreset(oh);
+       omap_hwmod_idle(oh);
+}
+
 /**
  * _reidle_all - enable then idle all hwmods in oh_reidle_list
  *
@@ -3279,8 +3312,7 @@ static int _reidle_all(void)
        struct omap_hwmod_list *oh_list_item = NULL;
 
        list_for_each_entry(oh_list_item, &oh_reidle_list, oh_list) {
-               omap_hwmod_enable(oh_list_item->oh);
-               omap_hwmod_idle(oh_list_item->oh);
+               _reidle(oh_list_item->oh);
        }
 
        return 0;
@@ -4440,14 +4472,16 @@ static int omap_hwmod_restore_context(struct omap_hwmod *oh, void *unused)
        for (i = 0; i < oh->rst_lines_cnt; i++)
                if (oh->rst_lines[i].context)
                        _assert_hardreset(oh, oh->rst_lines[i].name);
-               else if (oh->_state == _HWMOD_STATE_ENABLED)
+               else
                        _deassert_hardreset(oh, oh->rst_lines[i].name);
 
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                if (soc_ops.enable_module)
                        soc_ops.enable_module(oh);
        } else {
-               if (soc_ops.disable_module)
+               if (oh->flags & HWMOD_NEEDS_REIDLE)
+                       _reidle(oh);
+               else if (soc_ops.disable_module)
                        soc_ops.disable_module(oh);
        }