aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
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 /arch/arm/mach-omap2
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>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c37
1 files changed, 35 insertions, 2 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}