2020-02-14 16:06:59

by Sasha Levin

[permalink] [raw]
Subject: [PATCH AUTOSEL 5.4 191/459] ARM: OMAP2+: Add workaround for DRA7 DSP MStandby errata i879

From: Suman Anna <[email protected]>

[ Upstream commit 2f14101a1d760db72393910d481fbf7768c44530 ]

Errata Title:
i879: DSP MStandby requires CD_EMU in SW_WKUP

Description:
The DSP requires the internal emulation clock to be actively toggling
in order to successfully enter a low power mode via execution of the
IDLE instruction and PRCM MStandby/Idle handshake. This assumes that
other prerequisites and software sequence are followed.

Workaround:
The emulation clock to the DSP is free-running anytime CCS is connected
via JTAG debugger to the DSP subsystem or when the CD_EMU clock domain
is set in SW_WKUP mode. The CD_EMU domain can be set in SW_WKUP mode
via the CM_EMU_CLKSTCTRL [1:0]CLKTRCTRL field.

Implementation:
This patch implements this workaround by denying the HW_AUTO mode
for the EMU clockdomain during the power-up of any DSP processor
and re-enabling the HW_AUTO mode during the shutdown of the last
DSP processor (actually done during the enabling and disabling of
the respective DSP MDMA MMUs). Reference counting has to be used to
manage the independent sequencing between the multiple DSP processors.

This switching is done at runtime rather than a static clockdomain
flags value to meet the target power domain state for the EMU power
domain during suspend.

Note that the DSP MStandby behavior is not consistent across all
boards prior to this fix. Please see commit 45f871eec6c0 ("ARM:
OMAP2+: Extend DRA7 IPU1 MMU pdata quirks to DSP MDMA MMUs") for
details.

Signed-off-by: Suman Anna <[email protected]>
Signed-off-by: Tony Lindgren <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
arch/arm/mach-omap2/omap-iommu.c | 43 +++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index f1a6ece8108e4..78247e6f4a720 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -11,14 +11,43 @@

#include "omap_hwmod.h"
#include "omap_device.h"
+#include "clockdomain.h"
#include "powerdomain.h"

+static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev,
+ bool enable)
+{
+ static struct clockdomain *emu_clkdm;
+ static DEFINE_SPINLOCK(emu_lock);
+ static atomic_t count;
+ struct device_node *np = pdev->dev.of_node;
+
+ if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
+ return;
+
+ if (!emu_clkdm) {
+ emu_clkdm = clkdm_lookup("emu_clkdm");
+ if (WARN_ON_ONCE(!emu_clkdm))
+ return;
+ }
+
+ spin_lock(&emu_lock);
+
+ if (enable && (atomic_inc_return(&count) == 1))
+ clkdm_deny_idle(emu_clkdm);
+ else if (!enable && (atomic_dec_return(&count) == 0))
+ clkdm_allow_idle(emu_clkdm);
+
+ spin_unlock(&emu_lock);
+}
+
int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
u8 *pwrst)
{
struct powerdomain *pwrdm;
struct omap_device *od;
u8 next_pwrst;
+ int ret = 0;

od = to_omap_device(pdev);
if (!od)
@@ -31,13 +60,21 @@ int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
if (!pwrdm)
return -EINVAL;

- if (request)
+ if (request) {
*pwrst = pwrdm_read_next_pwrst(pwrdm);
+ omap_iommu_dra7_emu_swsup_config(pdev, true);
+ }

if (*pwrst > PWRDM_POWER_RET)
- return 0;
+ goto out;

next_pwrst = request ? PWRDM_POWER_ON : *pwrst;

- return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+ ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+
+out:
+ if (!request)
+ omap_iommu_dra7_emu_swsup_config(pdev, false);
+
+ return ret;
}
--
2.20.1


2020-02-14 18:33:50

by Suman Anna

[permalink] [raw]
Subject: Re: [PATCH AUTOSEL 5.4 191/459] ARM: OMAP2+: Add workaround for DRA7 DSP MStandby errata i879

Hi Sasha,

On 2/14/20 9:57 AM, Sasha Levin wrote:
> From: Suman Anna <[email protected]>
>
> [ Upstream commit 2f14101a1d760db72393910d481fbf7768c44530 ]
>
> Errata Title:
> i879: DSP MStandby requires CD_EMU in SW_WKUP
>
> Description:
> The DSP requires the internal emulation clock to be actively toggling
> in order to successfully enter a low power mode via execution of the
> IDLE instruction and PRCM MStandby/Idle handshake. This assumes that
> other prerequisites and software sequence are followed.
>
> Workaround:
> The emulation clock to the DSP is free-running anytime CCS is connected
> via JTAG debugger to the DSP subsystem or when the CD_EMU clock domain
> is set in SW_WKUP mode. The CD_EMU domain can be set in SW_WKUP mode
> via the CM_EMU_CLKSTCTRL [1:0]CLKTRCTRL field.
>
> Implementation:
> This patch implements this workaround by denying the HW_AUTO mode
> for the EMU clockdomain during the power-up of any DSP processor
> and re-enabling the HW_AUTO mode during the shutdown of the last
> DSP processor (actually done during the enabling and disabling of
> the respective DSP MDMA MMUs). Reference counting has to be used to
> manage the independent sequencing between the multiple DSP processors.
>
> This switching is done at runtime rather than a static clockdomain
> flags value to meet the target power domain state for the EMU power
> domain during suspend.
>
> Note that the DSP MStandby behavior is not consistent across all
> boards prior to this fix. Please see commit 45f871eec6c0 ("ARM:
> OMAP2+: Extend DRA7 IPU1 MMU pdata quirks to DSP MDMA MMUs") for
> details.
>
> Signed-off-by: Suman Anna <[email protected]>
> Signed-off-by: Tony Lindgren <[email protected]>
> Signed-off-by: Sasha Levin <[email protected]>

You can drop this from the 5.4-stable queue. Mainline doesn't yet boot
the processors, so this is not needed for stable queue.

regards
Suman

> ---
> arch/arm/mach-omap2/omap-iommu.c | 43 +++++++++++++++++++++++++++++---
> 1 file changed, 40 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
> index f1a6ece8108e4..78247e6f4a720 100644
> --- a/arch/arm/mach-omap2/omap-iommu.c
> +++ b/arch/arm/mach-omap2/omap-iommu.c
> @@ -11,14 +11,43 @@
>
> #include "omap_hwmod.h"
> #include "omap_device.h"
> +#include "clockdomain.h"
> #include "powerdomain.h"
>
> +static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev,
> + bool enable)
> +{
> + static struct clockdomain *emu_clkdm;
> + static DEFINE_SPINLOCK(emu_lock);
> + static atomic_t count;
> + struct device_node *np = pdev->dev.of_node;
> +
> + if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
> + return;
> +
> + if (!emu_clkdm) {
> + emu_clkdm = clkdm_lookup("emu_clkdm");
> + if (WARN_ON_ONCE(!emu_clkdm))
> + return;
> + }
> +
> + spin_lock(&emu_lock);
> +
> + if (enable && (atomic_inc_return(&count) == 1))
> + clkdm_deny_idle(emu_clkdm);
> + else if (!enable && (atomic_dec_return(&count) == 0))
> + clkdm_allow_idle(emu_clkdm);
> +
> + spin_unlock(&emu_lock);
> +}
> +
> int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
> u8 *pwrst)
> {
> struct powerdomain *pwrdm;
> struct omap_device *od;
> u8 next_pwrst;
> + int ret = 0;
>
> od = to_omap_device(pdev);
> if (!od)
> @@ -31,13 +60,21 @@ int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
> if (!pwrdm)
> return -EINVAL;
>
> - if (request)
> + if (request) {
> *pwrst = pwrdm_read_next_pwrst(pwrdm);
> + omap_iommu_dra7_emu_swsup_config(pdev, true);
> + }
>
> if (*pwrst > PWRDM_POWER_RET)
> - return 0;
> + goto out;
>
> next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
>
> - return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
> + ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst);
> +
> +out:
> + if (!request)
> + omap_iommu_dra7_emu_swsup_config(pdev, false);
> +
> + return ret;
> }
>