coresight-tpdm: Add node to set dsb programming mode
authorTao Zhang <quic_taozha@quicinc.com>
Thu, 28 Sep 2023 06:29:41 +0000 (14:29 +0800)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Thu, 16 Nov 2023 11:35:29 +0000 (11:35 +0000)
Add node to set and show programming mode for TPDM DSB subunit.
Once the DSB programming mode is set, it will be written to the
register DSB_CR.

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-9-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 b15bf012a050a9335f38c7c2e161a939be7780d6..8ec7548070b7be97c502ef9c9e10ec2bb504a752 100644 (file)
@@ -43,3 +43,17 @@ Description:
                Accepts only one of the 2 values -  0 or 1.
                0 : Set the DSB trigger type to false
                1 : Set the DSB trigger type to true
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
+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 programming mode of the DSB for tpdm.
+
+               Accepts the value needs to be greater than 0. What data
+               bits do is listed below.
+               Bit[0:1] : Test mode control bit for choosing the inputs.
+               Bit[3] : Set to 0 for low performance mode.
+                                Set to 1 for high performance mode.
+               Bit[4:8] : Select byte lane for high performance mode.
index e9fc3482d480aa8af2d90ec75867b63cd27d851f..6201f12718ca60cd64585c479482ea35a48123fb 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/amba/bus.h>
+#include <linux/bitfield.h>
 #include <linux/bitmap.h>
 #include <linux/coresight.h>
 #include <linux/coresight-pmu.h>
@@ -47,6 +48,27 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)
        }
 }
 
+static void set_dsb_mode(struct tpdm_drvdata *drvdata, u32 *val)
+{
+       u32 mode;
+
+       /* Set the test accurate mode */
+       mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode);
+       *val &= ~TPDM_DSB_CR_TEST_MODE;
+       *val |= FIELD_PREP(TPDM_DSB_CR_TEST_MODE, mode);
+
+       /* Set the byte lane for high-performance mode */
+       mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
+       *val &= ~TPDM_DSB_CR_HPSEL;
+       *val |= FIELD_PREP(TPDM_DSB_CR_HPSEL, mode);
+
+       /* Set the performance mode */
+       if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
+               *val |= TPDM_DSB_CR_MODE;
+       else
+               *val &= ~TPDM_DSB_CR_MODE;
+}
+
 static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
 {
        u32 val;
@@ -60,6 +82,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
        writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
 
        val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
+       /* Set the mode of DSB dataset */
+       set_dsb_mode(drvdata, &val);
        /* Set trigger type */
        if (drvdata->dsb->trig_type)
                val |= TPDM_DSB_CR_TRIG_TYPE;
@@ -244,6 +268,34 @@ static struct attribute_group tpdm_attr_grp = {
        .attrs = tpdm_attrs,
 };
 
+static ssize_t dsb_mode_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       return sysfs_emit(buf, "%x\n", drvdata->dsb->mode);
+}
+
+static ssize_t dsb_mode_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 val;
+
+       if ((kstrtoul(buf, 0, &val)) || (val < 0) ||
+                       (val & ~TPDM_DSB_MODE_MASK))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK;
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(dsb_mode);
+
 static ssize_t dsb_trig_type_show(struct device *dev,
                                  struct device_attribute *attr, char *buf)
 {
@@ -316,6 +368,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
 static DEVICE_ATTR_RW(dsb_trig_ts);
 
 static struct attribute *tpdm_dsb_attrs[] = {
+       &dev_attr_dsb_mode.attr,
        &dev_attr_dsb_trig_ts.attr,
        &dev_attr_dsb_trig_type.attr,
        NULL,
index f59e751d358168450f7a6e2a92859eb4ad96eb7c..b55d6f5ce852002bf5069c72bb847a5fd3995a71 100644 (file)
 
 /* Enable bit for DSB subunit */
 #define TPDM_DSB_CR_ENA                BIT(0)
+/* Enable bit for DSB subunit perfmance mode */
+#define TPDM_DSB_CR_MODE               BIT(1)
 /* Enable bit for DSB subunit trigger type */
 #define TPDM_DSB_CR_TRIG_TYPE          BIT(12)
+/* Data bits for DSB high performace mode */
+#define TPDM_DSB_CR_HPSEL              GENMASK(6, 2)
+/* Data bits for DSB test mode */
+#define TPDM_DSB_CR_TEST_MODE          GENMASK(10, 9)
+
 /* Enable bit for DSB subunit trigger timestamp */
 #define TPDM_DSB_TIER_XTRIG_TSENAB             BIT(1)
 
+/* DSB programming modes */
+/* DSB mode bits mask */
+#define TPDM_DSB_MODE_MASK                     GENMASK(8, 0)
+/* Test mode control bit*/
+#define TPDM_DSB_MODE_TEST(val)        (val & GENMASK(1, 0))
+/* Performance mode */
+#define TPDM_DSB_MODE_PERF             BIT(3)
+/* High performance mode */
+#define TPDM_DSB_MODE_HPBYTESEL(val)   (val & GENMASK(8, 4))
+
 /* TPDM integration test registers */
 #define TPDM_ITATBCNTRL                (0xEF0)
 #define TPDM_ITCNTRL           (0xF00)
 
 /**
  * struct dsb_dataset - specifics associated to dsb dataset
+ * @mode:             DSB programming mode
  * @trig_ts:          Enable/Disable trigger timestamp.
  * @trig_type:        Enable/Disable trigger type.
  */
 struct dsb_dataset {
+       u32                     mode;
        bool                    trig_ts;
        bool                    trig_type;
 };