Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -210,6 +210,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
	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
 * @oh: struct omap_hwmod *
@@ -558,7 +584,13 @@ static void _sysc_enable(struct omap_hwmod *oh)
		_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 &&
	    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)
		_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);
}
+7 −1
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ struct omap_device;
#define SYSC_ENAWAKEUP_MASK		(1 << SYSC_ENAWAKEUP_SHIFT)
#define SYSC_SOFTRESET_SHIFT		1
#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 */
#define SYSS_RESETDONE_SHIFT		0
@@ -294,13 +296,17 @@ struct omap_hwmod_omap4_prcm {
 *     SDRAM controller, etc.
 * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
 *     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
 */
#define HWMOD_SWSUP_SIDLE			(1 << 0)
#define HWMOD_SWSUP_MSTANDBY			(1 << 1)
#define HWMOD_INIT_NO_RESET			(1 << 2)
#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