drivers/perf: fsl_imx8_ddr: Correct the CLEAR bit definition
authorJoakim Zhang <qiangqing.zhang@nxp.com>
Tue, 25 Feb 2020 12:56:43 +0000 (20:56 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 25 Mar 2020 07:25:47 +0000 (08:25 +0100)
[ Upstream commit 049d919168458ac54e7fad27cd156a958b042d2f ]

When disabling a counter from ddr_perf_event_stop(), the counter value
is reset to 0 at the same time.

Preserve the counter value by performing a read-modify-write of the
PMU register and clearing only the enable bit.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/perf/fsl_imx8_ddr_perf.c

index 0e51baa..6eef47d 100644 (file)
@@ -327,9 +327,10 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
 
        if (enable) {
                /*
-                * must disable first, then enable again
-                * otherwise, cycle counter will not work
-                * if previous state is enabled.
+                * cycle counter is special which should firstly write 0 then
+                * write 1 into CLEAR bit to clear it. Other counters only
+                * need write 0 into CLEAR bit and it turns out to be 1 by
+                * hardware. Below enable flow is harmless for all counters.
                 */
                writel(0, pmu->base + reg);
                val = CNTL_EN | CNTL_CLEAR;
@@ -337,7 +338,8 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
                writel(val, pmu->base + reg);
        } else {
                /* Disable counter */
-               writel(0, pmu->base + reg);
+               val = readl_relaxed(pmu->base + reg) & CNTL_EN_MASK;
+               writel(val, pmu->base + reg);
        }
 }