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: Paul Walmsley <paul@pwsan.com> Tested-by: Kevin Hilman <khilman@deeprootsystems.com>
This commit is contained in:
parent
b835d01421
commit
726072e5dd
@ -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)
|
|||||||
_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)
|
|||||||
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;
|
|||||||
#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 {
|
|||||||
* 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
|
||||||
|
Loading…
Reference in New Issue
Block a user