diff options
author | Paul Walmsley <paul@pwsan.com> | 2009-12-08 18:34:15 -0500 |
---|---|---|
committer | paul <paul@twilight.(none)> | 2009-12-11 19:00:43 -0500 |
commit | 726072e5dd459e3831d1dd4308ba469ff3ded419 (patch) | |
tree | 1e79dcd2e26bcb3eb3fd232d30e17a83f0e73c48 /arch/arm/mach-omap2 | |
parent | b835d0142196466c5ff3695b90cff1e3ea635c8e (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.c | 37 |
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 | */ | ||
226 | static 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 | } |