coresight-tpdm: add mux select register support

Add support to configure mux select registers for all subunits.

These registers can be used to select different trace events supported
by a subunit.

Change-Id: I5d5236e4c0cb94e401dfe82eeb91e8fe7e3c566b
Signed-off-by: Shashank Mittal <mittals@codeaurora.org>
This commit is contained in:
Shashank Mittal 2016-03-04 16:13:54 -08:00 committed by David Keitel
parent 8b9b492260
commit 8c962a959b

View file

@ -60,6 +60,7 @@ do { \
#define TPDM_BC_SHADOW_LO(n) (0x3D0 + (n * 4))
#define TPDM_BC_SHADOW_HI(n) (0x450 + (n * 4))
#define TPDM_BC_SWINC (0x4D0)
#define TPDM_BC_MSR(n) (0x4F0 + (n * 4))
/* TC Subunit Registers */
#define TPDM_TC_CR (0x500)
@ -78,6 +79,7 @@ do { \
#define TPDM_TC_SHADOW_LO(n) (0x594 + (n * 4))
#define TPDM_TC_SHADOW_HI(n) (0x644 + (n * 4))
#define TPDM_TC_SWINC (0x700)
#define TPDM_TC_MSR(n) (0x768 + (n * 4))
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
@ -89,6 +91,7 @@ do { \
#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
#define TPDM_DSB_CA_SELECT(n) (0x86c + (n * 4))
#define TPDM_DSB_MSR(n) (0x980 + (n * 4))
/* CMB Subunit Registers */
#define TPDM_CMB_CR (0xA00)
@ -97,6 +100,7 @@ do { \
#define TPDM_CMB_TPMR(n) (0xA10 + (n * 4))
#define TPDM_CMB_XPR(n) (0xA18 + (n * 4))
#define TPDM_CMB_XPMR(n) (0xA20 + (n * 4))
#define TPDM_CMB_MSR(n) (0xA80 + (n * 4))
/* TPDM Specific Registers */
#define TPDM_ITATBCNTRL (0xEF0)
@ -105,13 +109,17 @@ do { \
#define TPDM_DATASETS 32
#define TPDM_BC_MAX_COUNTERS 32
#define TPDM_BC_MAX_OVERFLOW 6
#define TPDM_BC_MAX_MSR 4
#define TPDM_TC_MAX_COUNTERS 44
#define TPDM_TC_MAX_TRIG 8
#define TPDM_TC_MAX_MSR 6
#define TPDM_DSB_MAX_PATT 8
#define TPDM_DSB_MAX_SELECT 8
#define TPDM_DSB_MAX_MSR 32
#define TPDM_DSB_MAX_EDCR 16
#define TPDM_DSB_MAX_LINES 256
#define TPDM_CMB_PATT_CMP 2
#define TPDM_CMB_MAX_MSR 128
/* DSB programming modes */
#define TPDM_DSB_MODE_CYCACC(val) BMVAL(val, 0, 2)
@ -124,6 +132,9 @@ do { \
#define TPDM_TRACE_ID_START 128
#define TPDM_REVISION_A 0
#define TPDM_REVISION_B 1
enum tpdm_dataset {
TPDM_DS_IMPLDEF,
TPDM_DS_DSB,
@ -181,6 +192,7 @@ struct bc_dataset {
uint32_t trig_val_hi[TPDM_BC_MAX_COUNTERS];
uint32_t enable_ganging;
uint32_t overflow_val[TPDM_BC_MAX_OVERFLOW];
uint32_t msr[TPDM_BC_MAX_MSR];
};
struct tc_dataset {
@ -194,6 +206,7 @@ struct tc_dataset {
uint32_t trig_sel[TPDM_TC_MAX_TRIG];
uint32_t trig_val_lo[TPDM_TC_MAX_TRIG];
uint32_t trig_val_hi[TPDM_TC_MAX_TRIG];
uint32_t msr[TPDM_TC_MAX_MSR];
};
struct dsb_dataset {
@ -207,6 +220,7 @@ struct dsb_dataset {
uint32_t trig_patt_mask[TPDM_DSB_MAX_PATT];
bool trig_ts;
uint32_t select_val[TPDM_DSB_MAX_SELECT];
uint32_t msr[TPDM_DSB_MAX_MSR];
};
struct cmb_dataset {
@ -217,6 +231,7 @@ struct cmb_dataset {
uint32_t trig_patt_val[TPDM_CMB_PATT_CMP];
uint32_t trig_patt_mask[TPDM_CMB_PATT_CMP];
bool trig_ts;
uint32_t msr[TPDM_CMB_MAX_MSR];
};
struct tpdm_drvdata {
@ -240,6 +255,8 @@ struct tpdm_drvdata {
struct dsb_dataset *dsb;
struct cmb_dataset *cmb;
int traceid;
uint32_t version;
bool msr_support;
};
static void __tpdm_enable_gpr(struct tpdm_drvdata *drvdata)
@ -253,6 +270,50 @@ static void __tpdm_enable_gpr(struct tpdm_drvdata *drvdata)
}
}
static void __tpdm_config_bc_msr(struct tpdm_drvdata *drvdata)
{
int i;
if (!drvdata->msr_support)
return;
for (i = 0; i < TPDM_BC_MAX_MSR; i++)
tpdm_writel(drvdata, drvdata->bc->msr[i], TPDM_BC_MSR(i));
}
static void __tpdm_config_tc_msr(struct tpdm_drvdata *drvdata)
{
int i;
if (!drvdata->msr_support)
return;
for (i = 0; i < TPDM_TC_MAX_MSR; i++)
tpdm_writel(drvdata, drvdata->tc->msr[i], TPDM_TC_MSR(i));
}
static void __tpdm_config_dsb_msr(struct tpdm_drvdata *drvdata)
{
int i;
if (!drvdata->msr_support)
return;
for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
tpdm_writel(drvdata, drvdata->dsb->msr[i], TPDM_DSB_MSR(i));
}
static void __tpdm_config_cmb_msr(struct tpdm_drvdata *drvdata)
{
int i;
if (!drvdata->msr_support)
return;
for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
tpdm_writel(drvdata, drvdata->cmb->msr[i], TPDM_CMB_MSR(i));
}
static void __tpdm_enable_bc(struct tpdm_drvdata *drvdata)
{
int i;
@ -303,6 +364,8 @@ static void __tpdm_enable_bc(struct tpdm_drvdata *drvdata)
tpdm_writel(drvdata, drvdata->bc->overflow_val[i],
TPDM_BC_OVERFLOW(i));
__tpdm_config_bc_msr(drvdata);
val = tpdm_readl(drvdata, TPDM_BC_CR);
if (drvdata->bc->retrieval_mode == TPDM_MODE_APB)
val = val | BIT(2);
@ -357,6 +420,8 @@ static void __tpdm_enable_tc(struct tpdm_drvdata *drvdata)
TPDM_TC_TRIG_HI(0));
}
__tpdm_config_tc_msr(drvdata);
val = tpdm_readl(drvdata, TPDM_TC_CR);
if (drvdata->tc->sat_mode)
val = val | BIT(4);
@ -414,6 +479,8 @@ static void __tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
val = val & ~BIT(1);
tpdm_writel(drvdata, val, TPDM_DSB_TIER);
__tpdm_config_dsb_msr(drvdata);
val = tpdm_readl(drvdata, TPDM_DSB_CR);
/* Set the cycle accurate mode */
mode = TPDM_DSB_MODE_CYCACC(drvdata->dsb->mode);
@ -469,6 +536,8 @@ static void __tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
val = val & ~BIT(1);
tpdm_writel(drvdata, val, TPDM_CMB_TIER);
__tpdm_config_cmb_msr(drvdata);
val = tpdm_readl(drvdata, TPDM_CMB_CR);
/* Set the flow control bit */
val = val & ~BIT(2);
@ -1550,6 +1619,35 @@ static ssize_t tpdm_store_bc_sw_inc(struct device *dev,
static DEVICE_ATTR(bc_sw_inc, S_IRUGO | S_IWUSR,
tpdm_show_bc_sw_inc, tpdm_store_bc_sw_inc);
static ssize_t tpdm_store_bc_msr(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned num, val;
int nval;
if (!drvdata->msr_support)
return -EINVAL;
if (!test_bit(TPDM_DS_BC, drvdata->datasets))
return -EPERM;
nval = sscanf(buf, "%u %x", &num, &val);
if (nval != 2)
return -EINVAL;
if (num >= TPDM_BC_MAX_MSR)
return -EINVAL;
mutex_lock(&drvdata->lock);
drvdata->bc->msr[num] = val;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR(bc_msr, S_IWUSR, NULL, tpdm_store_bc_msr);
static ssize_t tpdm_show_tc_capture_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -2395,6 +2493,35 @@ static ssize_t tpdm_store_tc_sw_inc(struct device *dev,
static DEVICE_ATTR(tc_sw_inc, S_IRUGO | S_IWUSR,
tpdm_show_tc_sw_inc, tpdm_store_tc_sw_inc);
static ssize_t tpdm_store_tc_msr(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned num, val;
int nval;
if (!drvdata->msr_support)
return -EINVAL;
if (!test_bit(TPDM_DS_TC, drvdata->datasets))
return -EPERM;
nval = sscanf(buf, "%u %x", &num, &val);
if (nval != 2)
return -EINVAL;
if (num >= TPDM_TC_MAX_MSR)
return -EINVAL;
mutex_lock(&drvdata->lock);
drvdata->tc->msr[num] = val;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR(tc_msr, S_IWUSR, NULL, tpdm_store_tc_msr);
static ssize_t tpdm_show_dsb_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -2836,6 +2963,35 @@ static ssize_t tpdm_store_dsb_select_val(struct device *dev,
static DEVICE_ATTR(dsb_select_val, S_IRUGO | S_IWUSR,
tpdm_show_dsb_select_val, tpdm_store_dsb_select_val);
static ssize_t tpdm_store_dsb_msr(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned num, val;
int nval;
if (!drvdata->msr_support)
return -EINVAL;
if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
return -EPERM;
nval = sscanf(buf, "%u %x", &num, &val);
if (nval != 2)
return -EINVAL;
if (num >= TPDM_DSB_MAX_MSR)
return -EINVAL;
mutex_lock(&drvdata->lock);
drvdata->dsb->msr[num] = val;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR(dsb_msr, S_IWUSR, NULL, tpdm_store_dsb_msr);
static ssize_t tpdm_show_cmb_available_modes(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -3249,6 +3405,35 @@ static ssize_t tpdm_store_cmb_trig_ts(struct device *dev,
static DEVICE_ATTR(cmb_trig_ts, S_IRUGO | S_IWUSR,
tpdm_show_cmb_trig_ts, tpdm_store_cmb_trig_ts);
static ssize_t tpdm_store_cmb_msr(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned num, val;
int nval;
if (!drvdata->msr_support)
return -EINVAL;
if (!test_bit(TPDM_DS_CMB, drvdata->datasets))
return -EPERM;
nval = sscanf(buf, "%u %x", &num, &val);
if (nval != 2)
return -EINVAL;
if (num >= TPDM_CMB_MAX_MSR)
return -EINVAL;
mutex_lock(&drvdata->lock);
drvdata->cmb->msr[num] = val;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR(cmb_msr, S_IWUSR, NULL, tpdm_store_cmb_msr);
static struct attribute *tpdm_bc_attrs[] = {
&dev_attr_bc_capture_mode.attr,
&dev_attr_bc_retrieval_mode.attr,
@ -3269,6 +3454,7 @@ static struct attribute *tpdm_bc_attrs[] = {
&dev_attr_bc_shadow_val_lo.attr,
&dev_attr_bc_shadow_val_hi.attr,
&dev_attr_bc_sw_inc.attr,
&dev_attr_bc_msr.attr,
NULL,
};
@ -3292,6 +3478,7 @@ static struct attribute *tpdm_tc_attrs[] = {
&dev_attr_tc_shadow_val_lo.attr,
&dev_attr_tc_shadow_val_hi.attr,
&dev_attr_tc_sw_inc.attr,
&dev_attr_tc_msr.attr,
NULL,
};
@ -3306,6 +3493,7 @@ static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_trig_patt_mask.attr,
&dev_attr_dsb_trig_ts.attr,
&dev_attr_dsb_select_val.attr,
&dev_attr_dsb_msr.attr,
NULL,
};
@ -3322,6 +3510,7 @@ static struct attribute *tpdm_cmb_attrs[] = {
&dev_attr_cmb_trig_patt_val_msb.attr,
&dev_attr_cmb_trig_patt_mask_msb.attr,
&dev_attr_cmb_trig_ts.attr,
&dev_attr_cmb_msr.attr,
NULL,
};
@ -3420,6 +3609,7 @@ static int tpdm_probe(struct platform_device *pdev)
struct resource *res;
struct coresight_desc *desc;
static int traceid = TPDM_TRACE_ID_START;
uint32_t version;
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
@ -3457,6 +3647,12 @@ static int tpdm_probe(struct platform_device *pdev)
if (ret)
return ret;
version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
drvdata->version = BMVAL(version, 4, 7);
if (drvdata->version)
drvdata->msr_support = true;
pidr = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR0);
for (i = 0; i < TPDM_DATASETS; i++) {
if (pidr & BIT(i)) {