coresight-etm4x: Controls pertaining to the sequencer functions

Adding sysfs entries to access the sequencers related registers,
more specifically the sequencer state, the sequencer state
transition and the sequencer reset control registers.

Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Pratik Patel 2015-05-13 10:34:15 -06:00 committed by Greg Kroah-Hartman
parent 35c9b29bc8
commit 5e5ff34406
2 changed files with 154 additions and 0 deletions

View file

@ -179,3 +179,28 @@ Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used to setup address range comparator values.
What: /sys/bus/coresight/devices/<memory_map>.etm/seq_idx
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Select which sequensor.
What: /sys/bus/coresight/devices/<memory_map>.etm/seq_state
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Use this to set, or read, the sequencer state.
What: /sys/bus/coresight/devices/<memory_map>.etm/seq_event
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Moves the sequencer state to a specific state.
What: /sys/bus/coresight/devices/<memory_map>.etm/seq_reset_event
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Moves the sequencer to state 0 when a programmed event
occurs.

View file

@ -1442,6 +1442,131 @@ static ssize_t addr_context_store(struct device *dev,
}
static DEVICE_ATTR_RW(addr_context);
static ssize_t seq_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->seq_idx;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t seq_idx_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;
if (val >= drvdata->nrseqstate - 1)
return -EINVAL;
/*
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
spin_lock(&drvdata->spinlock);
drvdata->seq_idx = val;
spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(seq_idx);
static ssize_t seq_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->seq_state;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t seq_state_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;
if (val >= drvdata->nrseqstate)
return -EINVAL;
drvdata->seq_state = val;
return size;
}
static DEVICE_ATTR_RW(seq_state);
static ssize_t seq_event_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
u8 idx;
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
spin_lock(&drvdata->spinlock);
idx = drvdata->seq_idx;
val = drvdata->seq_ctrl[idx];
spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t seq_event_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
u8 idx;
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
if (kstrtoul(buf, 16, &val))
return -EINVAL;
spin_lock(&drvdata->spinlock);
idx = drvdata->seq_idx;
/* RST, bits[7:0] */
drvdata->seq_ctrl[idx] = val & 0xFF;
spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(seq_event);
static ssize_t seq_reset_event_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->seq_rst;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t seq_reset_event_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;
if (!(drvdata->nrseqstate))
return -EINVAL;
drvdata->seq_rst = val & ETMv4_EVENT_MASK;
return size;
}
static DEVICE_ATTR_RW(seq_reset_event);
static ssize_t cpu_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -1484,6 +1609,10 @@ static struct attribute *coresight_etmv4_attrs[] = {
&dev_attr_addr_stop.attr,
&dev_attr_addr_ctxtype.attr,
&dev_attr_addr_context.attr,
&dev_attr_seq_idx.attr,
&dev_attr_seq_state.attr,
&dev_attr_seq_event.attr,
&dev_attr_seq_reset_event.attr,
&dev_attr_cpu.attr,
NULL,
};