Add the nodes for CMB subunit MSR(mux select register) support.
CMB MSRs(mux select registers) is to separate mux,arbitration,
,interleaving,data packing control from stream filtering control.
Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
---
.../testing/sysfs-bus-coresight-devices-tpdm | 6 ++
drivers/hwtracing/coresight/coresight-tpdm.c | 59 +++++++++++++++++++
drivers/hwtracing/coresight/coresight-tpdm.h | 6 ++
3 files changed, 71 insertions(+)
@@ -212,3 +212,9 @@ Description: (RW) Read or write the status of timestamp upon all interface.
Only value 0 and 1 can be written to this node. Set this node to 1 to requeset
timestamp to all trace packet.
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_msr
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <quic_jinlmao@quicinc.com>
+Description: (RW) Read or write the value of CMB msr.
+
@@ -72,6 +72,14 @@ static int tpdm_init_datasets(struct tpdm_drvdata *drvdata)
if (!drvdata->cmb)
return -ENOMEM;
}
+
+ /* Get cmb msr number*/
+ of_property_read_u32(drvdata->dev->of_node, "qcom,cmb-msr-num",
+ &drvdata->cmb->msr_num);
+ drvdata->cmb->msr = devm_kzalloc(drvdata->dev,
+ (drvdata->cmb->msr_num * sizeof(u32)), GFP_KERNEL);
+ if (!drvdata->cmb->msr)
+ return -ENOMEM;
}
return 0;
@@ -206,6 +214,12 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
val = val & ~TPDM_CMB_TIER_TS_ALL;
writel_relaxed(val, drvdata->base + TPDM_CMB_TIER);
+ /* Configure MSR registers */
+ if (drvdata->cmb->msr_num != 0)
+ for (i = 0; i < drvdata->cmb->msr_num; i++)
+ writel_relaxed(drvdata->cmb->msr[i],
+ drvdata->base + TPDM_CMB_MSR(i));
+
val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
/*
* Set to 0 for continuous CMB collection mode,
@@ -1159,6 +1173,50 @@ static ssize_t cmb_trig_ts_store(struct device *dev,
}
static DEVICE_ATTR_RW(cmb_trig_ts);
+static ssize_t cmb_msr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned int i;
+ ssize_t size = 0;
+
+ if (drvdata->cmb->msr_num == 0)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < drvdata->cmb->msr_num; i++) {
+ size += sysfs_emit_at(buf, size,
+ "%u 0x%x\n", i, drvdata->cmb->msr[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+
+static ssize_t cmb_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->cmb->msr_num == 0)
+ return -EINVAL;
+
+ nval = sscanf(buf, "%u %x", &num, &val);
+ if ((nval != 2) || (num >= (drvdata->cmb->msr_num - 1)))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->msr[num] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_msr);
+
static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_mode.attr,
&dev_attr_dsb_edge_ctrl.attr,
@@ -1184,6 +1242,7 @@ static struct attribute *tpdm_cmb_attrs[] = {
&dev_attr_cmb_patt_ts.attr,
&dev_attr_cmb_ts_all.attr,
&dev_attr_cmb_trig_ts.attr,
+ &dev_attr_cmb_msr.attr,
NULL,
};
@@ -22,6 +22,8 @@
#define TPDM_CMB_XPR(n) (0xA18 + (n * 4))
/*CMB subunit trigger pattern mask registers*/
#define TPDM_CMB_XPMR(n) (0xA20 + (n * 4))
+/* CMB MSR register */
+#define TPDM_CMB_MSR(n) (0xA80 + (n * 4))
/* Enable bit for CMB subunit */
#define TPDM_CMB_CR_ENA BIT(0)
@@ -145,6 +147,8 @@ struct dsb_dataset {
* @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: The number of msr register
+ * @msr: Save value for msr registers
* @patt_ts: Indicates if pattern match for timestamp is enabled.
* @trig_ts: Indicates if CTI trigger for timestamp is enabled.
* @ts_all: Indicates if timestamp is enabled for all packets.
@@ -155,6 +159,8 @@ struct cmb_dataset {
u32 patt_mask[TPDM_CMB_MAX_PATT];
u32 trig_patt_val[TPDM_CMB_MAX_PATT];
u32 trig_patt_mask[TPDM_CMB_MAX_PATT];
+ u32 msr_num;
+ u32 *msr;
bool patt_ts;
bool trig_ts;
bool ts_all;