As per the specification any update to the TRCPRGCTLR must be synchronized
by a context synchronization event (in our case an explicist ISB) before
the TRCSTATR is checked.

Cc: Mike Leach <mike.le...@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poir...@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poul...@arm.com>
---
 drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c 
b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 84af2c7b7f86..9b00720e7a02 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -284,6 +284,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
        /* Disable the trace unit before programming trace registers */
        etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
 
+       /*
+        * If we use system instructions, we need to synchronize the
+        * write to the TRCPRGCTLR, before accessing the TRCSTATR.
+        * See ARM IHI0064F, section
+        * "4.3.7 Synchronization of register updates"
+        */
+       if (!csa->io_mem)
+               isb();
+
        /* wait for TRCSTATR.IDLE to go up */
        if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
                dev_err(etm_dev,
@@ -362,6 +371,10 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
        /* Enable the trace unit */
        etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
 
+       /* Synchronize the register updates for sysreg access */
+       if (!csa->io_mem)
+               isb();
+
        /* wait for TRCSTATR.IDLE to go back down to '0' */
        if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
                dev_err(etm_dev,
-- 
2.24.1

Reply via email to