On 08/09/2022 09:45, Tao Zhang wrote:
Add nodes to configure the timestamp request based on input
pattern match. Each TPDM that support DSB subunit has n(0-7) TPR
registers to configure value for timestamp request based on input
pattern match, and has m(0-7) TPMR registers to configure pattern
mask for timestamp request.
Add nodes to enable/disable pattern timestamp and set pattern
timestamp type.
Signed-off-by: Tao Zhang <quic_taozha@xxxxxxxxxxx>
---
drivers/hwtracing/coresight/coresight-tpdm.c | 189 +++++++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tpdm.h | 14 ++
2 files changed, 203 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 648bbe6..4212ff4 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -32,6 +32,13 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
drvdata->base + TPDM_DSB_EDCMR(i));
for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ writel_relaxed(drvdata->dsb->patt_val[i],
+ drvdata->base + TPDM_DSB_TPR(i));
+ writel_relaxed(drvdata->dsb->patt_mask[i],
+ drvdata->base + TPDM_DSB_TPMR(i));
+ }
+
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
writel_relaxed(drvdata->dsb->trig_patt_val[i],
drvdata->base + TPDM_DSB_XPR(i));
writel_relaxed(drvdata->dsb->trig_patt_mask[i],
@@ -39,6 +46,16 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
}
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
+ /* Set pattern timestamp type and enablement */
+ if (drvdata->dsb->patt_ts) {
+ val |= TPDM_DSB_PATT_TSENAB;
+ if (drvdata->dsb->patt_type)
+ val |= TPDM_DSB_PATT_TYPE;
+ else
+ val &= ~TPDM_DSB_PATT_TYPE;
+ } else {
+ val &= ~TPDM_DSB_PATT_TSENAB;
+ }
/* Set trigger timestamp */
if (drvdata->dsb->trig_ts)
val |= TPDM_DSB_XTRIG_TSENAB;
@@ -411,6 +428,174 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+static ssize_t dsb_patt_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!(drvdata->datasets & TPDM_PIDR0_DS_DSB))
+ return -EPERM;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->patt_val[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+/*
+ * value 1: Index of TPR register
+ * value 2: Value need to be written
+ */
+static ssize_t dsb_patt_val_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!(drvdata->datasets & TPDM_PIDR0_DS_DSB) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->patt_val[index] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_val);
+
+static ssize_t dsb_patt_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i = 0;
+
+ if (!(drvdata->datasets & TPDM_PIDR0_DS_DSB))
+ return -EPERM;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->dsb->patt_mask[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+/*
+ * value 1: Index of TPMR register
+ * value 2: Value need to be written
+ */
+static ssize_t dsb_patt_mask_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (!(drvdata->datasets & TPDM_PIDR0_DS_DSB) ||
+ index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->patt_mask[index] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_mask);
+
+static ssize_t dsb_patt_ts_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (!(drvdata->datasets & TPDM_PIDR0_DS_DSB))
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (unsigned int)drvdata->dsb->patt_ts);
Please use sysfs_emit() everywhere (in the previous patches too)
for such operations.
I have finished reviewing this series.
Suzuki