diff options
author | Arve Hjønnevåg <arve@android.com> | 2012-03-28 21:03:13 -0700 |
---|---|---|
committer | Frank Li <Frank.Li@freescale.com> | 2012-09-26 13:24:30 +0800 |
commit | ac58d07866bea0dfab35a7520388b46d81e92340 (patch) | |
tree | d7c07d282eeaaf1c3a23c730aae8cfab5a17d90f | |
parent | 08aee79345937b04382511abb641f817864e20f5 (diff) |
ARM: etm: Wait for etm/ptm(s) to stop before requesting PowerDown
When PowerDown was requested at the same time as ProgBit, the
formatter flush command that follows could get stuck.
Change-Id: Iafb665f61f055819e64ca1dcb60398c656f593e4
Signed-off-by: Arve Hjønnevåg <arve@android.com>
-rw-r--r-- | arch/arm/kernel/etm.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 496b8b84e455..845287bd4ba2 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -199,11 +199,13 @@ static int trace_stop_etm(struct tracectx *t, int id) etm_unlock(t, id); - etm_writel(t, id, 0x441, ETMR_CTRL); + etm_writel(t, id, 0x440, ETMR_CTRL); while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) ; if (!timeout) { - dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); + dev_err(t->dev, + "etm%d: Waiting for progbit to assert timed out\n", + id); etm_lock(t, id); return -EFAULT; } @@ -212,18 +214,36 @@ static int trace_stop_etm(struct tracectx *t, int id) return 0; } +static int trace_power_down_etm(struct tracectx *t, int id) +{ + unsigned long timeout = TRACER_TIMEOUT; + etm_unlock(t, id); + while (!(etm_readl(t, id, ETMR_STATUS) & ETMST_PROGBIT) && --timeout) + ; + if (!timeout) { + dev_err(t->dev, "etm%d: Waiting for status progbit to assert timed out\n", + id); + etm_lock(t, id); + return -EFAULT; + } + + etm_writel(t, id, 0x441, ETMR_CTRL); + + etm_lock(t, id); + return 0; +} + static int trace_stop(struct tracectx *t) { int id; - int ret; unsigned long timeout = TRACER_TIMEOUT; u32 etb_fc = t->etb_fc; - for (id = 0; id < t->etm_regs_count; id++) { - ret = trace_stop_etm(t, id); - if (ret) - return ret; - } + for (id = 0; id < t->etm_regs_count; id++) + trace_stop_etm(t, id); + + for (id = 0; id < t->etm_regs_count; id++) + trace_power_down_etm(t, id); etb_unlock(t); if (etb_fc) { |