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@xxxxxxxxx> Cc: BenoÃt Cousson <b-cousson@xxxxxx> --- arch/arm/mach-omap2/omap_hwmod.c | 15 +++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 10 ++++++++++ 2 files changed, 25 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5a30658..c051fa4 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -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); diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 7eaa8ed..d1f1265 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -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); }; /** -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html