OMAP2+: hwmod: allow custom pre-shutdown functions
authorPaul Walmsley <paul@pwsan.com>
Tue, 14 Dec 2010 19:42:34 +0000 (12:42 -0700)
committerPaul Walmsley <paul@pwsan.com>
Wed, 22 Dec 2010 02:55:11 +0000 (19:55 -0700)
Some OMAP IP blocks, such as the watchdog timers, cannot be completely
shut down via the standard hwmod shutdown mechanism.  This patch
enables the hwmod data files to supply a pointer to a custom
pre-shutdown function via the struct omap_hwmod_class.pre_shutdown
function pointer.  If the struct omap_hwmod_class.pre_shutdown
function pointer is non-null, the function will be executed before the
existing hwmod shutdown code runs.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: BenoƮt Cousson <b-cousson@ti.com>
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/plat-omap/include/plat/omap_hwmod.h

index 5a30658444d0f84d8a8c8bbb7553ee9db07a5959..c051fa49359479ef8a58b472d1ab531b1e5d72de 100644 (file)
@@ -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);
 
index 7eaa8edf3b142eb3779385df916df80d1e055bf8..d1f1265fc4a627e786cab97553b3f04dd8c2f322 100644 (file)
@@ -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);
 };
 
 /**