Re: [PATCH v5] OMAP2+: PM: omap device: API's for handling mstandby mode

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

 



On Wed, Nov 24, 2010 at 4:24 PM, G, Manjunath Kondaiah <manjugk@xxxxxx> 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>
> Cc: Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>
> Cc: Paul Walmsley <paul@xxxxxxxxx>
> Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
> ---
> Change summary:
> v3: Review comments incorporated for:
> https://patchwork.kernel.org/patch/282212/
> v4: added mutex changes
> v5: typo fixes for errata and erratum
>
> Âarch/arm/mach-omap2/omap_hwmod.c       Â|  43 ++++++++++++++++-
> Â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(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> index 5a30658..de78441 100644
> --- a/arch/arm/mach-omap2/omap_hwmod.c
> +++ b/arch/arm/mach-omap2/omap_hwmod.c
> @@ -1427,6 +1427,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_register - register a struct omap_hwmod
> Â* @oh: struct omap_hwmod *
> Â*
> @@ -2116,4 +2158,3 @@ int omap_hwmod_for_each_by_class(const char *classname,
>
> Â Â Â Âreturn ret;
> Â}
> -
> diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
> index 28e2d1a..4fbf7c1 100644
> --- a/arch/arm/plat-omap/include/plat/omap_device.h
> +++ b/arch/arm/plat-omap/include/plat/omap_device.h
> @@ -116,6 +116,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 7eaa8ed..c7ff65a 100644
> --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
> +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> @@ -354,7 +354,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.
> @@ -526,6 +526,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_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 abe933c..fa99551 100644
> --- a/arch/arm/plat-omap/omap_device.c
> +++ b/arch/arm/plat-omap/omap_device.c
> @@ -584,6 +584,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;

     I Guess you are missing oh++ in the following loop.
> + Â Â Â for (i = 0; i < od->hwmods_cnt; i++)
> + Â Â Â Â Â Â Â ret = omap_hwmod_set_master_standbymode(oh, true);
> +
> + Â Â Â 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;

     Same comment here.
> + Â Â Â for (i = 0; i < od->hwmods_cnt; i++)
> + Â Â Â Â Â Â Â ret = omap_hwmod_set_master_standbymode(oh, false);
> +
> + Â Â Â return ret;
> +}
> +
> +/**
> Â* omap_device_shutdown - shut down an omap_device
> Â* @od: struct omap_device * to shut down
> Â*
> --
> 1.7.1
>
> --
> 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
>
--
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