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
+               subunit TPDM.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[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 pattern for the DSB subunit TPDM.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[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 pattern for the DSB subunit TPDM.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/enable_ts
+Date:          March 2023
+KernelVersion  6.7
+Contact:       Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+               (Write) Set the pattern timestamp of DSB tpdm. Read
+               the pattern timestamp of DSB tpdm.
+
+               Accepts only one of the 2 values -  0 or 1.
+               0 : Disable DSB pattern timestamp.
+               1 : Enable DSB pattern timestamp.
+
+What:          /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/set_type
+Date:          March 2023
+KernelVersion  6.7
+Contact:       Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+               (Write) Set the pattern type of DSB tpdm. Read
+               the pattern type of DSB tpdm.
+
+               Accepts only one of the 2 values -  0 or 1.
+               0 : Set the DSB pattern type to value.
+               1 : Set the DSB pattern type to toggle.
 
                        return -EINVAL;
                return sysfs_emit(buf, "0x%x\n",
                        drvdata->dsb->trig_patt_mask[tpdm_attr->idx]);
+       case DSB_PATT:
+               if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
+                       return -EINVAL;
+               return sysfs_emit(buf, "0x%x\n",
+                       drvdata->dsb->patt_val[tpdm_attr->idx]);
+       case DSB_PATT_MASK:
+               if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
+                       return -EINVAL;
+               return sysfs_emit(buf, "0x%x\n",
+                       drvdata->dsb->patt_mask[tpdm_attr->idx]);
        }
        return -EINVAL;
 }
                else
                        ret = -EINVAL;
                break;
+       case DSB_PATT:
+               if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
+                       drvdata->dsb->patt_val[tpdm_attr->idx] = val;
+               else
+                       ret = -EINVAL;
+               break;
+       case DSB_PATT_MASK:
+               if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
+                       drvdata->dsb->patt_mask[tpdm_attr->idx] = val;
+               else
+                       ret = -EINVAL;
+               break;
        default:
                ret = -EINVAL;
        }
                *val &= ~TPDM_DSB_CR_MODE;
 }
 
+static void set_dsb_tier(struct tpdm_drvdata *drvdata)
+{
+       u32 val;
+
+       val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
+
+       /* Clear all relevant fields */
+       val &= ~(TPDM_DSB_TIER_PATT_TSENAB | TPDM_DSB_TIER_PATT_TYPE |
+                TPDM_DSB_TIER_XTRIG_TSENAB);
+
+       /* Set pattern timestamp type and enablement */
+       if (drvdata->dsb->patt_ts) {
+               val |= TPDM_DSB_TIER_PATT_TSENAB;
+               if (drvdata->dsb->patt_type)
+                       val |= TPDM_DSB_TIER_PATT_TYPE;
+               else
+                       val &= ~TPDM_DSB_TIER_PATT_TYPE;
+       } else {
+               val &= ~TPDM_DSB_TIER_PATT_TSENAB;
+       }
+
+       /* Set trigger timestamp */
+       if (drvdata->dsb->trig_ts)
+               val |= TPDM_DSB_TIER_XTRIG_TSENAB;
+       else
+               val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;
+
+       writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
+}
+
 static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
 {
        u32 val, 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->patt_val[i],
+                          drvdata->base + TPDM_DSB_TPR(i));
+               writel_relaxed(drvdata->dsb->patt_mask[i],
+                          drvdata->base + TPDM_DSB_TPMR(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)
-               val |= TPDM_DSB_TIER_XTRIG_TSENAB;
-       else
-               val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;
-       writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
+
+       set_dsb_tier(drvdata);
 
        val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
        /* Set the mode of DSB dataset */
 }
 static DEVICE_ATTR_WO(ctrl_mask);
 
+static ssize_t enable_ts_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       return sysfs_emit(buf, "%u\n",
+                        (unsigned int)drvdata->dsb->patt_ts);
+}
+
+/*
+ * value 1: Enable/Disable DSB pattern timestamp
+ */
+static ssize_t enable_ts_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 & ~1UL))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->dsb->patt_ts = !!val;
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(enable_ts);
+
+static ssize_t set_type_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       return sysfs_emit(buf, "%u\n",
+                        (unsigned int)drvdata->dsb->patt_type);
+}
+
+/*
+ * value 1: Set DSB pattern type
+ */
+static ssize_t set_type_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 & ~1UL))
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->dsb->patt_type = val;
+       spin_unlock(&drvdata->spinlock);
+       return size;
+}
+static DEVICE_ATTR_RW(set_type);
+
 static ssize_t dsb_trig_type_show(struct device *dev,
                                  struct device_attribute *attr, char *buf)
 {
        NULL,
 };
 
+static struct attribute *tpdm_dsb_patt_attrs[] = {
+       DSB_PATT_ATTR(0),
+       DSB_PATT_ATTR(1),
+       DSB_PATT_ATTR(2),
+       DSB_PATT_ATTR(3),
+       DSB_PATT_ATTR(4),
+       DSB_PATT_ATTR(5),
+       DSB_PATT_ATTR(6),
+       DSB_PATT_ATTR(7),
+       DSB_PATT_MASK_ATTR(0),
+       DSB_PATT_MASK_ATTR(1),
+       DSB_PATT_MASK_ATTR(2),
+       DSB_PATT_MASK_ATTR(3),
+       DSB_PATT_MASK_ATTR(4),
+       DSB_PATT_MASK_ATTR(5),
+       DSB_PATT_MASK_ATTR(6),
+       DSB_PATT_MASK_ATTR(7),
+       &dev_attr_enable_ts.attr,
+       &dev_attr_set_type.attr,
+       NULL,
+};
+
 static struct attribute *tpdm_dsb_attrs[] = {
        &dev_attr_dsb_mode.attr,
        &dev_attr_dsb_trig_ts.attr,
        .name = "dsb_trig_patt",
 };
 
+static struct attribute_group tpdm_dsb_patt_grp = {
+       .attrs = tpdm_dsb_patt_attrs,
+       .is_visible = tpdm_dsb_is_visible,
+       .name = "dsb_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,
+       &tpdm_dsb_patt_grp,
        NULL,
 };
 
 
 /* DSB Subunit Registers */
 #define TPDM_DSB_CR            (0x780)
 #define TPDM_DSB_TIER          (0x784)
+#define TPDM_DSB_TPR(n)                (0x788 + (n * 4))
+#define TPDM_DSB_TPMR(n)       (0x7A8 + (n * 4))
 #define TPDM_DSB_XPR(n)                (0x7C8 + (n * 4))
 #define TPDM_DSB_XPMR(n)       (0x7E8 + (n * 4))
 #define TPDM_DSB_EDCR(n)       (0x808 + (n * 4))
 /* Data bits for DSB test mode */
 #define TPDM_DSB_CR_TEST_MODE          GENMASK(10, 9)
 
+/* Enable bit for DSB subunit pattern timestamp */
+#define TPDM_DSB_TIER_PATT_TSENAB              BIT(0)
 /* Enable bit for DSB subunit trigger timestamp */
 #define TPDM_DSB_TIER_XTRIG_TSENAB             BIT(1)
+/* Bit for DSB subunit pattern type */
+#define TPDM_DSB_TIER_PATT_TYPE                        BIT(2)
 
 /* DSB programming modes */
 /* DSB mode bits mask */
                tpdm_simple_dataset_rw(xpmr##nr,                \
                DSB_TRIG_PATT_MASK, nr)
 
+#define DSB_PATT_ATTR(nr)                                      \
+               tpdm_simple_dataset_rw(tpr##nr,                 \
+               DSB_PATT, nr)
+
+#define DSB_PATT_MASK_ATTR(nr)                                 \
+               tpdm_simple_dataset_rw(tpmr##nr,                \
+               DSB_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
+ * @patt_val:         Save value for pattern
+ * @patt_mask:        Save value for pattern mask
  * @trig_patt:        Save value for trigger pattern
  * @trig_patt_mask:   Save value for trigger pattern mask
+ * @patt_ts:          Enable/Disable pattern timestamp
+ * @patt_type:        Set pattern type
  * @trig_ts:          Enable/Disable trigger timestamp.
  * @trig_type:        Enable/Disable trigger type.
  */
        u32                     edge_ctrl_idx;
        u32                     edge_ctrl[TPDM_DSB_MAX_EDCR];
        u32                     edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
+       u32                     patt_val[TPDM_DSB_MAX_PATT];
+       u32                     patt_mask[TPDM_DSB_MAX_PATT];
        u32                     trig_patt[TPDM_DSB_MAX_PATT];
        u32                     trig_patt_mask[TPDM_DSB_MAX_PATT];
+       bool                    patt_ts;
+       bool                    patt_type;
        bool                    trig_ts;
        bool                    trig_type;
 };
        DSB_EDGE_CTRL_MASK,
        DSB_TRIG_PATT,
        DSB_TRIG_PATT_MASK,
+       DSB_PATT,
+       DSB_PATT_MASK,
 };
 
 /**