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)
committerWill Deacon <will@kernel.org>
Mon, 2 Mar 2020 12:07:19 +0000 (12:07 +0000)
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>
drivers/perf/fsl_imx8_ddr_perf.c

index 95dca2cb526500325dc56e9dd6a4f55e620a6eb2..90884d14f95faea01082bfd82c587ecedbd31667 100644 (file)
@@ -388,9 +388,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;
@@ -398,7 +399,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);
        }
 }