coresight-tpdm: Add nodes to configure pattern match output
authorTao Zhang <quic_taozha@quicinc.com>
Thu, 28 Sep 2023 06:29:43 +0000 (14:29 +0800)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Thu, 16 Nov 2023 11:35:33 +0000 (11:35 +0000)
Add nodes to configure trigger pattern and trigger pattern mask.
Each DSB subunit TPDM has maximum of n(n<7) XPR registers to
configure trigger pattern match output. Eight 32 bit registers
providing DSB interface trigger output pattern match comparison.
And each DSB subunit TPDM has maximum of m(m<7) XPMR registers to
configure trigger pattern mask match output. Eight 32 bit
registers providing DSB interface trigger output pattern match
mask.

Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/1695882586-10306-11-git-send-email-quic_taozha@quicinc.com
Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
drivers/hwtracing/coresight/coresight-tpdm.c
drivers/hwtracing/coresight/coresight-tpdm.h

index 6853bb1..2252e47 100644 (file)
@@ -107,4 +107,20 @@ Date:              March 2023
 KernelVersion  6.7
 Contact:       Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
 Description:
-               Read a set of the edge control mask of the DSB in TPDM.
\ No newline at end of file
+               Read a set of the edge control mask of the DSB in TPDM.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpr[0:7]
+Date:          March 2023
+KernelVersion  6.7
+Contact:       Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+               (RW) Set/Get the value of the trigger pattern for the DSB
+               subunit TPDM.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpmr[0:7]
+Date:          March 2023
+KernelVersion  6.7
+Contact:       Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+               (RW) Set/Get the mask of the trigger pattern for the DSB
+               subunit TPDM.
\ No newline at end of file
index 7175e70..e04c41f 100644 (file)
@@ -41,10 +41,58 @@ static ssize_t tpdm_simple_dataset_show(struct device *dev,
                        return -EINVAL;
                return sysfs_emit(buf, "0x%x\n",
                        drvdata->dsb->edge_ctrl_mask[tpdm_attr->idx]);
+       case DSB_TRIG_PATT:
+               if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
+                       return -EINVAL;
+               return sysfs_emit(buf, "0x%x\n",
+                       drvdata->dsb->trig_patt[tpdm_attr->idx]);
+       case DSB_TRIG_PATT_MASK:
+               if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
+                       return -EINVAL;
+               return sysfs_emit(buf, "0x%x\n",
+                       drvdata->dsb->trig_patt_mask[tpdm_attr->idx]);
        }
        return -EINVAL;
 }
 
+/* Write dataset array member with the index number */
+static ssize_t tpdm_simple_dataset_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t size)
+{
+       unsigned long val;
+       ssize_t ret = size;
+
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+       struct tpdm_dataset_attribute *tpdm_attr =
+               container_of(attr, struct tpdm_dataset_attribute, attr);
+
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       switch (tpdm_attr->mem) {
+       case DSB_TRIG_PATT:
+               if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
+                       drvdata->dsb->trig_patt[tpdm_attr->idx] = val;
+               else
+                       ret = -EINVAL;
+               break;
+       case DSB_TRIG_PATT_MASK:
+               if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
+                       drvdata->dsb->trig_patt_mask[tpdm_attr->idx] = val;
+               else
+                       ret = -EINVAL;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       spin_unlock(&drvdata->spinlock);
+
+       return ret;
+}
+
 static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
 {
        return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
@@ -103,7 +151,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
        for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
                writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
                           drvdata->base + TPDM_DSB_EDCMR(i));
-
+       for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+               writel_relaxed(drvdata->dsb->trig_patt[i],
+                          drvdata->base + TPDM_DSB_XPR(i));
+               writel_relaxed(drvdata->dsb->trig_patt_mask[i],
+                          drvdata->base + TPDM_DSB_XPMR(i));
+       }
        val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
        /* Set trigger timestamp */
        if (drvdata->dsb->trig_ts)
@@ -532,6 +585,26 @@ static struct attribute *tpdm_dsb_edge_attrs[] = {
        NULL,
 };
 
+static struct attribute *tpdm_dsb_trig_patt_attrs[] = {
+       DSB_TRIG_PATT_ATTR(0),
+       DSB_TRIG_PATT_ATTR(1),
+       DSB_TRIG_PATT_ATTR(2),
+       DSB_TRIG_PATT_ATTR(3),
+       DSB_TRIG_PATT_ATTR(4),
+       DSB_TRIG_PATT_ATTR(5),
+       DSB_TRIG_PATT_ATTR(6),
+       DSB_TRIG_PATT_ATTR(7),
+       DSB_TRIG_PATT_MASK_ATTR(0),
+       DSB_TRIG_PATT_MASK_ATTR(1),
+       DSB_TRIG_PATT_MASK_ATTR(2),
+       DSB_TRIG_PATT_MASK_ATTR(3),
+       DSB_TRIG_PATT_MASK_ATTR(4),
+       DSB_TRIG_PATT_MASK_ATTR(5),
+       DSB_TRIG_PATT_MASK_ATTR(6),
+       DSB_TRIG_PATT_MASK_ATTR(7),
+       NULL,
+};
+
 static struct attribute *tpdm_dsb_attrs[] = {
        &dev_attr_dsb_mode.attr,
        &dev_attr_dsb_trig_ts.attr,
@@ -550,10 +623,17 @@ static struct attribute_group tpdm_dsb_edge_grp = {
        .name = "dsb_edge",
 };
 
+static struct attribute_group tpdm_dsb_trig_patt_grp = {
+       .attrs = tpdm_dsb_trig_patt_attrs,
+       .is_visible = tpdm_dsb_is_visible,
+       .name = "dsb_trig_patt",
+};
+
 static const struct attribute_group *tpdm_attr_grps[] = {
        &tpdm_attr_grp,
        &tpdm_dsb_attr_grp,
        &tpdm_dsb_edge_grp,
+       &tpdm_dsb_trig_patt_grp,
        NULL,
 };
 
index a9c65d9..2cf7bdb 100644 (file)
@@ -12,6 +12,8 @@
 /* DSB Subunit Registers */
 #define TPDM_DSB_CR            (0x780)
 #define TPDM_DSB_TIER          (0x784)
+#define TPDM_DSB_XPR(n)                (0x7C8 + (n * 4))
+#define TPDM_DSB_XPMR(n)       (0x7E8 + (n * 4))
 #define TPDM_DSB_EDCR(n)       (0x808 + (n * 4))
 #define TPDM_DSB_EDCMR(n)      (0x848 + (n * 4))
 
@@ -80,6 +82,8 @@
 #define TPDM_DSB_MAX_EDCR      16
 /* MAX number of EDCMR registers */
 #define TPDM_DSB_MAX_EDCMR     8
+/* MAX number of DSB pattern */
+#define TPDM_DSB_MAX_PATT      8
 
 #define tpdm_simple_dataset_ro(name, mem, idx)                 \
        (&((struct tpdm_dataset_attribute[]) {                  \
           }                                                            \
        })[0].attr.attr)
 
+#define tpdm_simple_dataset_rw(name, mem, idx)                 \
+       (&((struct tpdm_dataset_attribute[]) {                  \
+          {                                                            \
+               __ATTR(name, 0644, tpdm_simple_dataset_show,            \
+               tpdm_simple_dataset_store),             \
+               mem,                                                    \
+               idx,                                                    \
+          }                                                            \
+       })[0].attr.attr)
+
 #define DSB_EDGE_CTRL_ATTR(nr)                                 \
                tpdm_simple_dataset_ro(edcr##nr,                \
                DSB_EDGE_CTRL, nr)
                tpdm_simple_dataset_ro(edcmr##nr,               \
                DSB_EDGE_CTRL_MASK, nr)
 
+#define DSB_TRIG_PATT_ATTR(nr)                                 \
+               tpdm_simple_dataset_rw(xpr##nr,                 \
+               DSB_TRIG_PATT, nr)
+
+#define DSB_TRIG_PATT_MASK_ATTR(nr)                            \
+               tpdm_simple_dataset_rw(xpmr##nr,                \
+               DSB_TRIG_PATT_MASK, nr)
+
 /**
  * struct dsb_dataset - specifics associated to dsb dataset
  * @mode:             DSB programming mode
  * @edge_ctrl_idx     Index number of the edge control
  * @edge_ctrl:        Save value for edge control
  * @edge_ctrl_mask:   Save value for edge control mask
+ * @trig_patt:        Save value for trigger pattern
+ * @trig_patt_mask:   Save value for trigger pattern mask
  * @trig_ts:          Enable/Disable trigger timestamp.
  * @trig_type:        Enable/Disable trigger type.
  */
@@ -112,6 +136,8 @@ struct dsb_dataset {
        u32                     edge_ctrl_idx;
        u32                     edge_ctrl[TPDM_DSB_MAX_EDCR];
        u32                     edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
+       u32                     trig_patt[TPDM_DSB_MAX_PATT];
+       u32                     trig_patt_mask[TPDM_DSB_MAX_PATT];
        bool                    trig_ts;
        bool                    trig_type;
 };
@@ -141,6 +167,8 @@ struct tpdm_drvdata {
 enum dataset_mem {
        DSB_EDGE_CTRL,
        DSB_EDGE_CTRL_MASK,
+       DSB_TRIG_PATT,
+       DSB_TRIG_PATT_MASK,
 };
 
 /**