|
@@ -1357,3 +1357,143 @@ static void _enable_sysc(struct omap_hwmod *oh)
|
|
|
if (sf & SYSC_HAS_SIDLEMODE) {
|
|
|
clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
|
|
|
if (clkdm_act && !(oh->class->sysc->idlemodes &
|
|
|
+ (SIDLE_SMART | SIDLE_SMART_WKUP)))
|
|
|
+ idlemode = HWMOD_IDLEMODE_FORCE;
|
|
|
+ else
|
|
|
+ idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
|
|
|
+ HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
|
|
|
+ _set_slave_idlemode(oh, idlemode, &v);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_MIDLEMODE) {
|
|
|
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
|
|
|
+ idlemode = HWMOD_IDLEMODE_NO;
|
|
|
+ } else {
|
|
|
+ if (sf & SYSC_HAS_ENAWAKEUP)
|
|
|
+ _enable_wakeup(oh, &v);
|
|
|
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
|
|
|
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
|
|
|
+ else
|
|
|
+ idlemode = HWMOD_IDLEMODE_SMART;
|
|
|
+ }
|
|
|
+ _set_master_standbymode(oh, idlemode, &v);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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) &&
|
|
|
+ (sf & SYSC_HAS_CLOCKACTIVITY))
|
|
|
+ _set_clockactivity(oh, oh->class->sysc->clockact, &v);
|
|
|
+
|
|
|
+ /* If slave is in SMARTIDLE, also enable wakeup */
|
|
|
+ if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
|
|
|
+ _enable_wakeup(oh, &v);
|
|
|
+
|
|
|
+ _write_sysconfig(v, oh);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set the autoidle bit only after setting the smartidle bit
|
|
|
+ * Setting this will not have any impact on the other modules.
|
|
|
+ */
|
|
|
+ if (sf & SYSC_HAS_AUTOIDLE) {
|
|
|
+ idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
|
|
|
+ 0 : 1;
|
|
|
+ _set_module_autoidle(oh, idlemode, &v);
|
|
|
+ _write_sysconfig(v, oh);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _idle_sysc - try to put a module into idle via OCP_SYSCONFIG
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * If module is marked as SWSUP_SIDLE, force the module into slave
|
|
|
+ * idle; otherwise, configure it for smart-idle. If module is marked
|
|
|
+ * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
|
|
|
+ * configure it for smart-standby. No return value.
|
|
|
+ */
|
|
|
+static void _idle_sysc(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ u8 idlemode, sf;
|
|
|
+ u32 v;
|
|
|
+
|
|
|
+ if (!oh->class->sysc)
|
|
|
+ return;
|
|
|
+
|
|
|
+ v = oh->_sysc_cache;
|
|
|
+ sf = oh->class->sysc->sysc_flags;
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_SIDLEMODE) {
|
|
|
+ /* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */
|
|
|
+ if (oh->flags & HWMOD_SWSUP_SIDLE ||
|
|
|
+ !(oh->class->sysc->idlemodes &
|
|
|
+ (SIDLE_SMART | SIDLE_SMART_WKUP)))
|
|
|
+ idlemode = HWMOD_IDLEMODE_FORCE;
|
|
|
+ else
|
|
|
+ idlemode = HWMOD_IDLEMODE_SMART;
|
|
|
+ _set_slave_idlemode(oh, idlemode, &v);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_MIDLEMODE) {
|
|
|
+ if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
|
|
|
+ idlemode = HWMOD_IDLEMODE_FORCE;
|
|
|
+ } else {
|
|
|
+ if (sf & SYSC_HAS_ENAWAKEUP)
|
|
|
+ _enable_wakeup(oh, &v);
|
|
|
+ if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
|
|
|
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
|
|
|
+ else
|
|
|
+ idlemode = HWMOD_IDLEMODE_SMART;
|
|
|
+ }
|
|
|
+ _set_master_standbymode(oh, idlemode, &v);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If slave is in SMARTIDLE, also enable wakeup */
|
|
|
+ if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
|
|
|
+ _enable_wakeup(oh, &v);
|
|
|
+
|
|
|
+ _write_sysconfig(v, oh);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _shutdown_sysc - force a module into idle via OCP_SYSCONFIG
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Force the module into slave idle and master suspend. No return
|
|
|
+ * value.
|
|
|
+ */
|
|
|
+static void _shutdown_sysc(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ u32 v;
|
|
|
+ u8 sf;
|
|
|
+
|
|
|
+ if (!oh->class->sysc)
|
|
|
+ return;
|
|
|
+
|
|
|
+ v = oh->_sysc_cache;
|
|
|
+ sf = oh->class->sysc->sysc_flags;
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_SIDLEMODE)
|
|
|
+ _set_slave_idlemode(oh, HWMOD_IDLEMODE_FORCE, &v);
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_MIDLEMODE)
|
|
|
+ _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
|
|
|
+
|
|
|
+ if (sf & SYSC_HAS_AUTOIDLE)
|
|
|
+ _set_module_autoidle(oh, 1, &v);
|
|
|
+
|
|
|
+ _write_sysconfig(v, oh);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _lookup - find an omap_hwmod by name
|
|
|
+ * @name: find an omap_hwmod by name
|
|
|
+ *
|
|
|
+ * Return a pointer to an omap_hwmod by name, or NULL if not found.
|
|
|
+ */
|
|
|
+static struct omap_hwmod *_lookup(const char *name)
|
|
|
+{
|
|
|
+ struct omap_hwmod *oh, *temp_oh;
|