Commit 5e815baf authored by Robert Walker's avatar Robert Walker Committed by Mike Leach
Browse files

etm4x: Enable strobing of ETM

Controlled by sysfs parameters:
  strobe_window: How many cycles to sample for
  strobe_period: How many windows between sampled windows

To sample 1000 cycles every 20000 cycles:
  strobe_window: 1000
  strobe_period: 20
parent d5226fa6
......@@ -2258,6 +2258,64 @@ static ssize_t cpu_show(struct device *dev,
}
static DEVICE_ATTR_RO(cpu);
static ssize_t strobe_period_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->strobe_period;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t strobe_period_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
if (kstrtoul(buf, 16, &val))
return -EINVAL;
spin_lock(&drvdata->spinlock);
drvdata->strobe_period = val;
drvdata->strobe_period_last = val;
spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(strobe_period);
static ssize_t strobe_window_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->strobe_window;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t strobe_window_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
if (kstrtoul(buf, 16, &val))
return -EINVAL;
spin_lock(&drvdata->spinlock);
drvdata->strobe_window = val;
drvdata->strobe_window_last = val;
spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(strobe_window);
static struct attribute *coresight_etmv4_attrs[] = {
&dev_attr_nr_pe_cmp.attr,
&dev_attr_nr_addr_cmp.attr,
......@@ -2312,6 +2370,8 @@ static struct attribute *coresight_etmv4_attrs[] = {
&dev_attr_vmid_val.attr,
&dev_attr_vmid_masks.attr,
&dev_attr_cpu.attr,
&dev_attr_strobe_period.attr,
&dev_attr_strobe_window.attr,
NULL,
};
......
......@@ -54,6 +54,7 @@ static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
static void etm4_set_default_config(struct etmv4_config *config);
static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
struct perf_event *event);
static int etm4_set_strobing(struct etmv4_drvdata *drvdata);
static enum cpuhp_state hp_online;
......@@ -349,6 +350,10 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
if (ret)
goto out;
ret = etm4_set_strobing(drvdata);
if (ret)
goto out;
/* Go from generic option to ETMv4 specifics */
if (attr->config & BIT(ETM_OPT_CYCACC)) {
config->cfg |= BIT(4);
......@@ -507,6 +512,11 @@ static void etm4_disable_hw(void *info)
readl_relaxed(drvdata->base + TRCSSCSRn(i));
}
if (drvdata->strobe_period != 0 &&
drvdata->strobe_window != 0) {
drvdata->strobe_window_last = readl_relaxed(drvdata->base + TRCCNTVRn(0));
drvdata->strobe_period_last = readl_relaxed(drvdata->base + TRCCNTVRn(1));
}
coresight_disclaim_device_unlocked(drvdata->base);
CS_LOCK(drvdata->base);
......@@ -1065,6 +1075,46 @@ out:
return ret;
}
static int etm4_set_strobing(struct etmv4_drvdata *drvdata)
{
int ret = 0;
struct etmv4_config *config = &drvdata->config;
if (drvdata->strobe_period != 0 &&
drvdata->strobe_window != 0) {
/* Resource selector 2 is on when counter 0 is at zero */
config->res_ctrl[2] = 0x20001;
/* Resource selector 3 is on when counter 1 is at zero */
config->res_ctrl[3] = 0x20002;
/* This means resource selector pair 1 is on when both counters
0 and 1 are at zero */
/* Counter 0 counts cycles for one window */
config->cntrldvr[0] = drvdata->strobe_window - 1;
config->cntr_val[0] = drvdata->strobe_window_last;
/* reloads on zero, always count, never reload from other events */
config->cntr_ctrl[0] = 0x10001;
/* Counter 1 counts windows in one period */
config->cntrldvr[1] = drvdata->strobe_period - 1;
config->cntr_val[1] = drvdata->strobe_period_last;
/* config->cntr_val[1] = drvdata->strobe_period - 1; */
/* reloads when both counters are at zero, count when counter 0 is zero */
config->cntr_ctrl[1] = 0x8102;
/* Move state to 1 on counter 1 */
config->seq_ctrl[0] = 0x0081;
config->seq_ctrl[1] = 0x0000;
/* activate ViewInst while counter 1 is zero (lasts one window) */
config->vinst_ctrl |= 3;
}
return ret;
}
void etm4_config_trace_mode(struct etmv4_config *config)
{
u32 addr_acc, mode;
......@@ -1489,6 +1539,10 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
etm4_init_trace_id(drvdata);
etm4_set_default(&drvdata->config);
drvdata->strobe_period = 0;
drvdata->strobe_period_last = 0;
drvdata->strobe_window = 0;
drvdata->strobe_window_last = 0;
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata)) {
......
......@@ -451,6 +451,10 @@ struct etmv4_drvdata {
bool nooverflow;
bool atbtrig;
bool lpoverride;
u32 strobe_window;
u32 strobe_period;
u32 strobe_window_last;
u32 strobe_period_last;
struct etmv4_config config;
struct etmv4_save_state *save_state;
bool state_needs_restore;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment