Merge "coresight: resolve pcsave and etm tracing concurreny issue"
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 50bae55..c961713 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -195,6 +195,7 @@
struct wake_lock wake_lock;
int cpu;
uint8_t arch;
+ bool enable;
uint8_t nr_addr_cmp;
uint8_t nr_cntr;
uint8_t nr_ext_inp;
@@ -203,7 +204,6 @@
uint8_t reset;
uint32_t mode;
uint32_t ctrl;
- uint8_t ctrl_pwrdwn;
uint32_t trigger_event;
uint32_t startstop_ctrl;
uint32_t enable_event;
@@ -230,7 +230,6 @@
uint32_t ctxid_mask;
uint32_t sync_freq;
uint32_t timestamp_event;
- uint8_t pdcr_pwrup;
bool pcsave_impl;
bool pcsave_enable;
};
@@ -339,48 +338,18 @@
etm_readl(drvdata, ETMSR));
}
-static void etm_save_pwrdwn(struct etm_drvdata *drvdata)
-{
- drvdata->ctrl_pwrdwn = BVAL(etm_readl(drvdata, ETMCR), 0);
-}
-
-static void etm_restore_pwrdwn(struct etm_drvdata *drvdata)
-{
- uint32_t etmcr;
-
- etmcr = etm_readl(drvdata, ETMCR);
- etmcr = (etmcr & ~BIT(0)) | drvdata->ctrl_pwrdwn;
- etm_writel(drvdata, etmcr, ETMCR);
-}
-
-static void etm_save_pwrup(struct etm_drvdata *drvdata)
-{
- drvdata->pdcr_pwrup = BVAL(etm_readl_mm(drvdata, ETMPDCR), 3);
-}
-
-static void etm_restore_pwrup(struct etm_drvdata *drvdata)
-{
- uint32_t etmpdcr;
-
- etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
- etmpdcr = (etmpdcr & ~BIT(3)) | (drvdata->pdcr_pwrup << 3);
- etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
-}
-
static void etm_enable_pcsave(void *info)
{
struct etm_drvdata *drvdata = info;
ETM_UNLOCK(drvdata);
- etm_save_pwrup(drvdata);
/*
* ETMPDCR is only accessible via memory mapped interface and so use
* it first to enable power/clock to allow subsequent cp14 accesses.
*/
etm_set_pwrup(drvdata);
etm_clr_pwrdwn(drvdata);
- etm_restore_pwrup(drvdata);
ETM_LOCK(drvdata);
}
@@ -391,14 +360,10 @@
ETM_UNLOCK(drvdata);
- etm_save_pwrup(drvdata);
- /*
- * ETMPDCR is only accessible via memory mapped interface and so use
- * it first to enable power/clock to allow subsequent cp14 accesses.
- */
- etm_set_pwrup(drvdata);
- etm_set_pwrdwn(drvdata);
- etm_restore_pwrup(drvdata);
+ if (!drvdata->enable) {
+ etm_set_pwrdwn(drvdata);
+ etm_clr_pwrup(drvdata);
+ }
ETM_LOCK(drvdata);
}
@@ -416,10 +381,10 @@
* to allow subsequent cp14 accesses.
*/
etm_set_pwrup(drvdata);
- etm_save_pwrdwn(drvdata);
/*
* Clear power down bit since when this bit is set writes to
- * certain registers might be ignored.
+ * certain registers might be ignored. This is also a pre-requisite
+ * for trace enable.
*/
etm_clr_pwrdwn(drvdata);
etm_set_prog(drvdata);
@@ -463,7 +428,6 @@
etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
etm_clr_prog(drvdata);
- etm_restore_pwrdwn(drvdata);
ETM_LOCK(drvdata);
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
@@ -481,10 +445,12 @@
goto err_clk;
mutex_lock(&drvdata->mutex);
- /* executing __etm_enable on the cpu whose ETM is being enabled
+ /*
+ * Executing __etm_enable on the cpu whose ETM is being enabled
* ensures that register writes occur when cpu is powered.
*/
smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
+ drvdata->enable = true;
mutex_unlock(&drvdata->mutex);
wake_unlock(&drvdata->wake_lock);
@@ -501,20 +467,15 @@
struct etm_drvdata *drvdata = info;
ETM_UNLOCK(drvdata);
- etm_save_pwrdwn(drvdata);
- /*
- * Clear power down bit since when this bit is set writes to
- * certain registers might be ignored.
- */
- etm_clr_pwrdwn(drvdata);
etm_set_prog(drvdata);
/* program trace enable to low by using always false event */
etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
- etm_restore_pwrdwn(drvdata);
- /* Vote for ETM power/clock disable */
- etm_clr_pwrup(drvdata);
+ if (!drvdata->pcsave_enable) {
+ etm_set_pwrdwn(drvdata);
+ etm_clr_pwrup(drvdata);
+ }
ETM_LOCK(drvdata);
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -527,10 +488,12 @@
wake_lock(&drvdata->wake_lock);
mutex_lock(&drvdata->mutex);
- /* executing __etm_disable on the cpu whose ETM is being disabled
+ /*
+ * Executing __etm_disable on the cpu whose ETM is being disabled
* ensures that register writes occur when cpu is powered.
*/
smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
+ drvdata->enable = false;
mutex_unlock(&drvdata->mutex);
clk_disable_unprepare(drvdata->clk);
@@ -1677,7 +1640,6 @@
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
etm_set_pwrdwn(drvdata);
- /* Vote for ETM power/clock disable */
etm_clr_pwrup(drvdata);
ETM_LOCK(drvdata);
}