Re: [PATCH v3 1/4] OMAP2+: PM: omap device: API's for handling mstandby mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 23, 2011 at 10:46:35PM -0600, Paul Walmsley wrote:
> Hi
> 
> comments below
> 
> 
> On Thu, 24 Mar 2011, G, Manjunath Kondaiah wrote:
> 
> > Certain errata in OMAP2+ processors will require forcing
> > master standby to "no standby" mode before completing on going
> > operation. Without this, the results will be unpredictable.
> > 
> > Since current implementation of PM run time framework does not support
> > changing sysconfig settings during middle of the on going operation,
> > these API's will support the same. One API will force the device's
> > sysconfig mstandby mode settings to "no standby" and other API will
> > release "no standby" mode and sets it to "smart standby" or "no
> > standby? depending on HWMOD_SWSUP_MSTANDBY value.
> > 
> > These API's should be used by device drivers only incase of
> > erratum applicable to their modules if there is no other methods
> > to resolve.
> > 
> > These API's are required for multiple DMA errata which require
> > putting DMA controller in no mstandby mode before stopping dma.
> > 
> > The applicable errata:
> > 1. Erratum ID: i557(Applicable for omap36xx all ES versions)
> > The channel hangs when the Pause bit (DMA4_CDPi [7] ) is cleared
> > through config port while in Standby.
> > 
> > 2. Erratum ID: i541
> > sDMA FIFO draining does not finish. Applicable to all omap2+ except
> > omap4.
> > 
> > 3. Erratum ID:i88
> > The sDMA to be put in no mstandby mode before disabling the channel
> > after completing the data transfer operation.
> > Applicable only for OMAP3430 ES1.0
> > 
> > Also fixes typo HWMOD_SWSUP_MSTDBY to HWMOD_SWSUP_MSTANDBY in
> > omap_hwmod.h
> > 
> > Signed-off-by: G, Manjunath Kondaiah <manjugk@xxxxxx>
> > ---
> >  arch/arm/mach-omap2/omap_hwmod.c              |   42 ++++++++++++++++
> >  arch/arm/plat-omap/include/plat/omap_device.h |    2 +
> >  arch/arm/plat-omap/include/plat/omap_hwmod.h  |    4 +-
> >  arch/arm/plat-omap/omap_device.c              |   64 +++++++++++++++++++++++++
> >  4 files changed, 111 insertions(+), 1 deletions(-)
> > 
> > diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> > index e034294..7966cc0 100644
> > --- a/arch/arm/mach-omap2/omap_hwmod.c
> > +++ b/arch/arm/mach-omap2/omap_hwmod.c
> > @@ -1594,6 +1594,48 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
> >  }
> >  
> >  /**
> > + * omap_hwmod_set_master_standbymode - set the hwmod's OCP mstandby mode
> > + * @oh: struct omap_hwmod *
> > + * @midlemode: flag to set mstandby to either "no standby" or "smart standby"
> > + *
> > + * Sets the IP block's OCP mstandby mode in hardware, and updates our
> > + * local copy.  Intended to be used by drivers that have some erratum
> > + * that requires direct manipulation of the MIDLEMODE bits.  Returns
> > + * -EINVAL if @oh is null, or passes along the return value from
> > + * _set_master_standbymode().
> > + *
> > + * Any users of this function should be scrutinized carefully.
> > + */
> > +int omap_hwmod_set_master_standbymode(struct omap_hwmod *oh, u8 idlemode)
> > +{
> > +	u32 v;
> > +	u8 sf;
> > +	int retval = 0;
> > +
> > +	if (!oh)
> > +		return -EINVAL;
> > +
> > +	if (!oh->class->sysc)
> > +		return -EINVAL;
> > +
> > +	v = oh->_sysc_cache;
> > +	sf = oh->class->sysc->sysc_flags;
> > +
> > +	if (sf & SYSC_HAS_MIDLEMODE) {
> > +		if (idlemode)
> > +			idlemode = HWMOD_IDLEMODE_NO;
> > +		else
> > +			idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
> > +				HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
> > +	}
> > +	retval = _set_master_standbymode(oh, idlemode, &v);
> > +	if (!retval)
> > +		_write_sysconfig(v, oh);
> > +
> > +	return retval;
> > +}
> > +
> > +/**
> >   * omap_hwmod_lookup - look up a registered omap_hwmod by name
> >   * @name: name of the omap_hwmod to look up
> >   *
> > diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
> > index e4c349f..42e0186 100644
> > --- a/arch/arm/plat-omap/include/plat/omap_device.h
> > +++ b/arch/arm/plat-omap/include/plat/omap_device.h
> > @@ -117,6 +117,8 @@ int omap_device_enable_hwmods(struct omap_device *od);
> >  int omap_device_disable_clocks(struct omap_device *od);
> >  int omap_device_enable_clocks(struct omap_device *od);
> >  
> > +int omap_device_require_no_mstandby(struct platform_device *pdev);
> > +int omap_device_release_no_mstandby(struct platform_device *pdev);
> >  
> >  /*
> >   * Entries should be kept in latency order ascending
> > diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> > index 1adea9c..2437f10 100644
> > --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
> > +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> > @@ -373,7 +373,7 @@ struct omap_hwmod_omap4_prcm {
> >   *
> >   * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
> >   *     of idle, rather than relying on module smart-idle
> > - * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
> > + * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and out
> >   *     of standby, rather than relying on module smart-standby
> >   * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
> >   *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
> > @@ -567,6 +567,8 @@ int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
> >  int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
> >  int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
> >  
> > +int omap_hwmod_set_master_standbymode(struct omap_hwmod *oh, u8 idlemode);
> > +
> >  int omap_hwmod_reset(struct omap_hwmod *oh);
> >  void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
> >  
> > diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
> > index 9bbda9a..b502098 100644
> > --- a/arch/arm/plat-omap/omap_device.c
> > +++ b/arch/arm/plat-omap/omap_device.c
> > @@ -628,6 +628,70 @@ int omap_device_idle(struct platform_device *pdev)
> >  }
> >  
> >  /**
> > + * omap_device_require_no_mstandby - set no mstandby mode of an omap_device
> > + * @od: struct omap_device * to idle
> > + *
> > + * Sets the IP block's OCP master standby to no mstandby mode in hardware.
> > + *
> > + * Intended to be used by drivers that have some erratum that requires direct
> > + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the
> > + * omap_device is not currently enabled or passes along the return value
> > + * of omap_hwmod_set_master_standbymode().
> > + */
> > +int omap_device_require_no_mstandby(struct platform_device *pdev)
> > +{
> > +	int ret  = 0, i;
> > +	struct omap_device *od;
> > +	struct omap_hwmod *oh;
> > +
> > +	od = _find_by_pdev(pdev);
> > +	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
> > +		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
> > +		     od->pdev.name, od->pdev.id, __func__, od->_state);
> > +		return -EINVAL;
> > +	}
> > +
> > +	oh = *od->hwmods;
> > +	for (i = 0; i < od->hwmods_cnt; i++)
> > +		ret = omap_hwmod_set_master_standbymode(oh, true);
> 
> You're still just operating on the same oh, over and over...

It's my bad. This was captured at:
https://patchwork.kernel.org/patch/352481/
and same was fixed in:
https://patchwork.kernel.org/patch/374731/

While reusing old patches into this series, it got messed up. Apologies for the
mess.

> 
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * omap_device_release_no_mstandby - releases no mstandby mode of an omap_device
> > + * @od: struct omap_device * to idle
> > + *
> > + * Release no mstandby mode and sets the master standby to either no standby or
> > + * smart standby in IP block's OCP in hardware depending on status of the flag
> > + * HWMOD_SWSUP_MSTANDBY.
> > + *
> > + * Intended to be used by drivers that have some erratum that requires direct
> > + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the
> > + * omap_device is not currently enabled or passes along the return value
> > + * of omap_hwmod_set_master_standbymode().
> > + */
> > +int omap_device_release_no_mstandby(struct platform_device *pdev)
> > +{
> > +	int ret  = 0, i;
> > +	struct omap_device *od;
> > +	struct omap_hwmod *oh;
> > +
> > +	od = _find_by_pdev(pdev);
> > +	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
> > +		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
> > +		     od->pdev.name, od->pdev.id, __func__, od->_state);
> > +		return -EINVAL;
> > +	}
> > +
> > +	oh = *od->hwmods;
> > +	for (i = 0; i < od->hwmods_cnt; i++)
> > +		ret = omap_hwmod_set_master_standbymode(oh, false);
> 
> and same here.
ok. Here are the changes on top of this series, I will fold these changes into the
patch.

Let me see if there are any other comments before posting updated version.

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index b502098..257c835 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -651,9 +651,8 @@ int omap_device_require_no_mstandby(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	oh = *od->hwmods;
 	for (i = 0; i < od->hwmods_cnt; i++)
-		ret = omap_hwmod_set_master_standbymode(oh, true);
+		ret = omap_hwmod_set_master_standbymode(od->hwmods[i], true);
 
 	return ret;
 }
@@ -684,9 +683,8 @@ int omap_device_release_no_mstandby(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	oh = *od->hwmods;
 	for (i = 0; i < od->hwmods_cnt; i++)
-		ret = omap_hwmod_set_master_standbymode(oh, false);
+		ret = omap_hwmod_set_master_standbymode(od->hwmods[i], false);
 
 	return ret;
 }

-Manjunath
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux