Commit 726072e5 authored by Paul Walmsley's avatar Paul Walmsley Committed by paul

OMAP3 hwmod: Add automatic OCP_SYSCONFIG AUTOIDLE handling

This patch fills in the OCP_SYSCONFIG.AUTOIDLE handling in the OMAP
hwmod code.

After this patch, the hwmod code will set the module AUTOIDLE bit
(generally <module>.OCP_SYSCONFIG.AUTOIDLE) to 1 by default upon
enable.  If the hwmod flag HWMOD_NO_OCP_AUTOIDLE is set, AUTOIDLE will
be set to 0 upon enable.  Upon module disable, AUTOIDLE will be set to
1.

Enabling module autoidle should save some power.  The only reason to
not set the OCP_SYSCONFIG.AUTOIDLE bit is if there is a bug in the
module RTL, e.g., the MPUINTC block on OMAP3.

Comments from Kevin Hilman <khilman@deeprootsystems.com> inspired this patch,
and Kevin tested an earlier version of this patch.
Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
Tested-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent b835d014
...@@ -210,6 +210,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) ...@@ -210,6 +210,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
return 0; return 0;
} }
/**
* _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v
* @oh: struct omap_hwmod *
* @autoidle: desired AUTOIDLE bitfield value (0 or 1)
* @v: pointer to register contents to modify
*
* Update the module autoidle bit in @v to be @autoidle for the @oh
* hwmod. The autoidle bit controls whether the module can gate
* internal clocks automatically when it isn't doing anything; the
* exact function of this bit varies on a per-module basis. This
* function does not write to the hardware. Returns -EINVAL upon
* error or 0 upon success.
*/
static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
u32 *v)
{
if (!oh->sysconfig ||
!(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
return -EINVAL;
*v &= ~SYSC_AUTOIDLE_MASK;
*v |= autoidle << SYSC_AUTOIDLE_SHIFT;
return 0;
}
/** /**
* _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
* @oh: struct omap_hwmod * * @oh: struct omap_hwmod *
...@@ -558,7 +584,13 @@ static void _sysc_enable(struct omap_hwmod *oh) ...@@ -558,7 +584,13 @@ static void _sysc_enable(struct omap_hwmod *oh)
_set_master_standbymode(oh, idlemode, &v); _set_master_standbymode(oh, idlemode, &v);
} }
/* XXX OCP AUTOIDLE bit? */ if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) {
idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
0 : 1;
_set_module_autoidle(oh, idlemode, &v);
}
/* XXX OCP ENAWAKEUP bit? */
if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT && if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT &&
oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY) oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)
...@@ -623,7 +655,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh) ...@@ -623,7 +655,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh)
if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)
_set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v); _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
/* XXX clear OCP AUTOIDLE bit? */ if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)
_set_module_autoidle(oh, 1, &v);
_write_sysconfig(v, oh); _write_sysconfig(v, oh);
} }
......
...@@ -50,6 +50,8 @@ struct omap_device; ...@@ -50,6 +50,8 @@ struct omap_device;
#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT) #define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
#define SYSC_SOFTRESET_SHIFT 1 #define SYSC_SOFTRESET_SHIFT 1
#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT) #define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
#define SYSC_AUTOIDLE_SHIFT 0
#define SYSC_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT)
/* OCP SYSSTATUS bit shifts/masks */ /* OCP SYSSTATUS bit shifts/masks */
#define SYSS_RESETDONE_SHIFT 0 #define SYSS_RESETDONE_SHIFT 0
...@@ -294,13 +296,17 @@ struct omap_hwmod_omap4_prcm { ...@@ -294,13 +296,17 @@ struct omap_hwmod_omap4_prcm {
* SDRAM controller, etc. * SDRAM controller, etc.
* HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
* controller, etc. * controller, etc.
* HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
* when module is enabled, rather than the default, which is to
* enable autoidle
* HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
*/ */
#define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_SIDLE (1 << 0)
#define HWMOD_SWSUP_MSTANDBY (1 << 1) #define HWMOD_SWSUP_MSTANDBY (1 << 1)
#define HWMOD_INIT_NO_RESET (1 << 2) #define HWMOD_INIT_NO_RESET (1 << 2)
#define HWMOD_INIT_NO_IDLE (1 << 3) #define HWMOD_INIT_NO_IDLE (1 << 3)
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 4) #define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
/* /*
* omap_hwmod._int_flags definitions * omap_hwmod._int_flags definitions
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment