aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2009-12-08 18:34:15 -0500
committerpaul <paul@twilight.(none)>2009-12-11 19:00:43 -0500
commit726072e5dd459e3831d1dd4308ba469ff3ded419 (patch)
tree1e79dcd2e26bcb3eb3fd232d30e17a83f0e73c48
parentb835d0142196466c5ff3695b90cff1e3ea635c8e (diff)
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>
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c37
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h8
2 files changed, 42 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 65a8e0ae394f..b01da1ed822d 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -211,6 +211,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
211} 211}
212 212
213/** 213/**
214 * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v
215 * @oh: struct omap_hwmod *
216 * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
217 * @v: pointer to register contents to modify
218 *
219 * Update the module autoidle bit in @v to be @autoidle for the @oh
220 * hwmod. The autoidle bit controls whether the module can gate
221 * internal clocks automatically when it isn't doing anything; the
222 * exact function of this bit varies on a per-module basis. This
223 * function does not write to the hardware. Returns -EINVAL upon
224 * error or 0 upon success.
225 */
226static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
227 u32 *v)
228{
229 if (!oh->sysconfig ||
230 !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
231 return -EINVAL;
232
233 *v &= ~SYSC_AUTOIDLE_MASK;
234 *v |= autoidle << SYSC_AUTOIDLE_SHIFT;
235
236 return 0;
237}
238
239/**
214 * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware 240 * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
215 * @oh: struct omap_hwmod * 241 * @oh: struct omap_hwmod *
216 * 242 *
@@ -558,7 +584,13 @@ static void _sysc_enable(struct omap_hwmod *oh)
558 _set_master_standbymode(oh, idlemode, &v); 584 _set_master_standbymode(oh, idlemode, &v);
559 } 585 }
560 586
561 /* XXX OCP AUTOIDLE bit? */ 587 if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) {
588 idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
589 0 : 1;
590 _set_module_autoidle(oh, idlemode, &v);
591 }
592
593 /* XXX OCP ENAWAKEUP bit? */
562 594
563 if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT && 595 if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT &&
564 oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY) 596 oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)
@@ -623,7 +655,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh)
623 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) 655 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)
624 _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v); 656 _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
625 657
626 /* XXX clear OCP AUTOIDLE bit? */ 658 if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)
659 _set_module_autoidle(oh, 1, &v);
627 660
628 _write_sysconfig(v, oh); 661 _write_sysconfig(v, oh);
629} 662}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index dbdd123eca16..643a9727de35 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -50,6 +50,8 @@ struct omap_device;
50#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT) 50#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
51#define SYSC_SOFTRESET_SHIFT 1 51#define SYSC_SOFTRESET_SHIFT 1
52#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT) 52#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
53#define SYSC_AUTOIDLE_SHIFT 0
54#define SYSC_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT)
53 55
54/* OCP SYSSTATUS bit shifts/masks */ 56/* OCP SYSSTATUS bit shifts/masks */
55#define SYSS_RESETDONE_SHIFT 0 57#define SYSS_RESETDONE_SHIFT 0
@@ -294,13 +296,17 @@ struct omap_hwmod_omap4_prcm {
294 * SDRAM controller, etc. 296 * SDRAM controller, etc.
295 * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM 297 * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
296 * controller, etc. 298 * controller, etc.
299 * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
300 * when module is enabled, rather than the default, which is to
301 * enable autoidle
297 * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup 302 * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
298 */ 303 */
299#define HWMOD_SWSUP_SIDLE (1 << 0) 304#define HWMOD_SWSUP_SIDLE (1 << 0)
300#define HWMOD_SWSUP_MSTANDBY (1 << 1) 305#define HWMOD_SWSUP_MSTANDBY (1 << 1)
301#define HWMOD_INIT_NO_RESET (1 << 2) 306#define HWMOD_INIT_NO_RESET (1 << 2)
302#define HWMOD_INIT_NO_IDLE (1 << 3) 307#define HWMOD_INIT_NO_IDLE (1 << 3)
303#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 4) 308#define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
309#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
304 310
305/* 311/*
306 * omap_hwmod._int_flags definitions 312 * omap_hwmod._int_flags definitions