@@ -166,3 +166,17 @@ Description:
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.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
+Description:
+ (Write) Set the MSR(mux select register) of DSB tpdm. Read
+ the MSR(mux select register) of DSB tpdm.
+
+ Expected format is the following:
+ <integer1> <integer2>
+
+ Where:
+ <integer1> : Index number of MSR register, the range is 0 to 31
@@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val)
}
+static void set_dsb_msr(struct tpdm_drvdata *drvdata)
+{
+ int i;
+
+ if (drvdata->dsb->msr_num == 0)
+ return;
+
+ for (i = 0; i < drvdata->dsb->msr_num; i++)
+ writel_relaxed(drvdata->dsb->msr[i],
+ drvdata->base + TPDM_DSB_MSR(i));
+}
+
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
{
u32 val, i;
@@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
set_dsb_tier(drvdata, &val);
writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
+ set_dsb_msr(drvdata);
+
val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
/* Set the test accurate mode */
set_dsb_test_mode(drvdata, &val);
@@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata)
if (!drvdata->dsb)
return -ENOMEM;
}
+ if (!of_property_read_u32(drvdata->dev->of_node,
+ "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) {
+ drvdata->dsb->msr = devm_kzalloc(drvdata->dev,
+ (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
+ GFP_KERNEL);
+ if (!drvdata->dsb->msr)
+ return -ENOMEM;
+ }
}
return 0;
@@ -775,6 +797,54 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_trig_ts);
+static ssize_t dsb_msr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned int i;
+ unsigned long bytes;
+ ssize_t size = 0;
+
+ if (drvdata->dsb->msr_num == 0)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < drvdata->dsb->msr_num; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "%u 0x%x\n", i, drvdata->dsb->msr[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+
+static ssize_t dsb_msr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned int num, val;
+ int nval;
+
+ if (drvdata->dsb->msr_num == 0)
+ return -EINVAL;
+
+ nval = sscanf(buf, "%u %x", &num, &val);
+ if ((nval != 2) || (num >= drvdata->dsb->msr_num))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->msr[num] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_msr);
+
static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_mode.attr,
&dev_attr_dsb_edge_ctrl.attr,
@@ -787,6 +857,7 @@ static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_trig_patt_mask.attr,
&dev_attr_dsb_trig_ts.attr,
&dev_attr_dsb_trig_type.attr,
+ &dev_attr_dsb_msr.attr,
NULL,
};
@@ -18,6 +18,7 @@
#define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4))
#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
+#define TPDM_DSB_MSR(n) (0x980 + (n * 4))
/* Enable bit for DSB subunit */
#define TPDM_DSB_CR_ENA BIT(0)
@@ -97,6 +98,8 @@
* @patt_mask: Save value for pattern mask
* @trig_patt_val: Save value for trigger pattern
* @trig_patt_mask: Save value for trigger pattern mask
+ * @msr_num Number of MSR supported by DSB TPDM
+ * @msr Save value for MSR
* @patt_ts: Enable/Disable pattern timestamp
* @patt_type: Set pattern type
* @trig_ts: Enable/Disable trigger timestamp.
@@ -110,6 +113,8 @@ struct dsb_dataset {
u32 patt_mask[TPDM_DSB_MAX_PATT];
u32 trig_patt_val[TPDM_DSB_MAX_PATT];
u32 trig_patt_mask[TPDM_DSB_MAX_PATT];
+ u32 msr_num;
+ u32 *msr;
bool patt_ts;
bool patt_type;
bool trig_ts;