mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
coresight: resolve pcsave and etm tracing concurreny issue
Always clear ETMCR[pwrdwn] while enabling trace. This is used as a logic enable and is a pre-requisite while enabling trace. So switch to an implementation that does this and removes the save and restore for pwrdwn and pwrup. Change-Id: I8a14efe8fd76368ed1e177a701013a504aa1876f Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
This commit is contained in:
parent
72ae7be066
commit
807d04fd7d
1 changed files with 17 additions and 55 deletions
|
@ -195,6 +195,7 @@ struct etm_drvdata {
|
|||
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 @@ struct etm_drvdata {
|
|||
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 @@ struct etm_drvdata {
|
|||
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 @@ static void etm_clr_prog(struct etm_drvdata *drvdata)
|
|||
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 @@ static void etm_disable_pcsave(void *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_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 @@ static void __etm_enable(void *info)
|
|||
* 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 @@ static void __etm_enable(void *info)
|
|||
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 @@ static int etm_enable(struct coresight_device *csdev)
|
|||
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 @@ static void __etm_disable(void *info)
|
|||
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 @@ static void etm_disable(struct coresight_device *csdev)
|
|||
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 @@ static void __devinit etm_init_arch_data(void *info)
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue