@@ -1261,6 +1261,9 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
*/
static int _shutdown(struct omap_hwmod *oh)
{
+ int ret;
+ u8 prev_state;
+
if (oh->_state != _HWMOD_STATE_IDLE &&
oh->_state != _HWMOD_STATE_ENABLED) {
WARN(1, "omap_hwmod: %s: disabled state can only be entered "
@@ -1270,6 +1273,18 @@ static int _shutdown(struct omap_hwmod *oh)
pr_debug("omap_hwmod: %s: disabling\n", oh->name);
+ if (oh->class->pre_shutdown) {
+ prev_state = oh->_state;
+ if (oh->_state == _HWMOD_STATE_IDLE)
+ _omap_hwmod_enable(oh);
+ ret = oh->class->pre_shutdown(oh);
+ if (ret) {
+ if (prev_state == _HWMOD_STATE_IDLE)
+ _omap_hwmod_idle(oh);
+ return ret;
+ }
+ }
+
if (oh->class->sysc)
_shutdown_sysc(oh);
@@ -415,14 +415,24 @@ struct omap_hwmod_omap4_prcm {
* @name: name of the hwmod_class
* @sysc: device SYSCONFIG/SYSSTATUS register data
* @rev: revision of the IP class
+ * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
*
* Represent the class of a OMAP hardware "modules" (e.g. timer,
* smartreflex, gpio, uart...)
+ *
+ * @pre_shutdown is a function that will be run immediately before
+ * hwmod clocks are disabled, etc. It is intended for use for hwmods
+ * like the MPU watchdog, which cannot be disabled with the standard
+ * omap_hwmod_shutdown(). The function should return 0 upon success,
+ * or some negative error upon failure. Returning an error will cause
+ * omap_hwmod_shutdown() to abort the device shutdown and return an
+ * error.
*/
struct omap_hwmod_class {
const char *name;
struct omap_hwmod_class_sysconfig *sysc;
u32 rev;
+ int (*pre_shutdown)(struct omap_hwmod *oh);
};
/**