[PATCH v4 07/13] coresight-etm4x: Controls pertaining to the sequencer functions
From: Mathieu Poirier
Date: Wed May 13 2015 - 12:36:59 EST
From: Pratik Patel <pratikp@xxxxxxxxxxxxxx>
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@xxxxxxxxxxxxxx>
Signed-off-by: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
---
.../ABI/testing/sysfs-bus-coresight-devices-etm4x | 25 ++++
drivers/hwtracing/coresight/coresight-etm4x.c | 129 +++++++++++++++++++++
2 files changed, 154 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
index 6a4d2b57bc39..6fb43e4c5939 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
@@ -179,3 +179,28 @@ Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
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@xxxxxxxxxx>
+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@xxxxxxxxxx>
+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@xxxxxxxxxx>
+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@xxxxxxxxxx>
+Description: (RW) Moves the sequencer to state 0 when a programmed event
+ occurs.
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 4c3d919b0ed3..aa9009fd2377 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -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,
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/