Continuous multi-bit (CMB) is responsible for collection of CMB data sets.
It monitors a bus of related signals (eg, a counter value) and an associated valid signal.
This patch series adds support to config of CMB registers.
Element Creation:
CMB_CR.mode : Continuous mode or Trace on Change mode(cmb_mode)
Pattern Match Output (usually to CTI):
CMB_XPR : Trigger pattern register value(cmb_trig_patt_val)
CMB_XPMR : Trigger pattern mask register value(cmb_trig_patt_mask)
Timestamp Request Based on Input Pattern Match:
CMB_TPR : Timestamp pattern register value(cmb_patt_val)
CMB_TPMR : Timestamp pattern mask register value(cmb_patt_mask)
CMB_TIER.patt_tsenab : Timestamps are requested upon CMB interface pattern match via
setting this bit to 1(cmb_patt_ts)
Timestamp Request Based on Input (usually from CTI):
CMB_TIER.xtrig_tsenab : Timestamps are requested upon CMB cross trigger interface
timestamp request via setting this bit to 1(cmb_trig_ts)
Mux Select Registers:
CMB_MSR : Configure Mux select registers(cmb_msr)
Once this series patches are applied properly, the new tpdm nodes should be observed at the tpdm path.
e.g.
/sys/devices/platform/soc@0/10c29000.tpdm/tpdm1 # ls -l | grep cmb
-rw-r--r-- 1 root 0 4096 Jan 1 00:00 cmb_mode
-rw-r--r-- 1 root 0 4096 Jan 1 00:00 cmb_msr
-rw-r--r-- 1 root 0 4096 Jan 1 00:00 cmb_patt_mask
-rw-r--r-- 1 root 0 4096 Jan 1 00:00 cmb_patt_ts
-rw-r--r-- 1 root 0 4096 Jan 1 00:22 cmb_patt_val
-rw-r--r-- 1 root 0 4096 Jan 1 00:59 cmb_trig_patt_mask
-rw-r--r-- 1 root 0 4096 Jan 1 00:57 cmb_trig_patt_val
-rw-r--r-- 1 root 0 4096 Jan 1 00:00 cmb_trig_ts
-rw-r--r-- 1 root 0 4096 Jan 1 00:58 cmb_ts_all
This patch series depends on:
[v3,0/11] Add support to configure TPDM DSB subunit
https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/
Codelinaro link:
https://git.codelinaro.org/clo/linux-kernel/coresight/-/commits/tpdm-cmb-v1
Mao Jinlong (8):
coresight-tpdm: Add CMB dataset support
coresight-tpdm: Add support to configure CMB collection mode
coresight-tpdm: Add pattern registers support for CMB data set
coresight-tpdm: Add timestamp control register support for the CMB
coresight-tpdm: Add msr register support for CMB
dt-bindings: arm: Add support for TPDM CMB MSR register
coresight-tpda: Add support to configure CMB element size
dt-bindings: arm: Add support for TPDM CMB element size
.../testing/sysfs-bus-coresight-devices-tpdm | 63 +++
.../bindings/arm/qcom,coresight-tpdm.yaml | 26 +
drivers/hwtracing/coresight/coresight-tpda.c | 33 +-
drivers/hwtracing/coresight/coresight-tpda.h | 4 +
drivers/hwtracing/coresight/coresight-tpdm.c | 447 +++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 60 +++
6 files changed, 626 insertions(+), 7 deletions(-)
--
2.39.0
Add property "qcom,cmb_msr_num" to support CMB MSR(mux select register)
for TPDM. It specifies the number of CMB MSR registers supported by
the TDPM.
Signed-off-by: Mao Jinlong <[email protected]>
---
.../devicetree/bindings/arm/qcom,coresight-tpdm.yaml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
index 691c7ba365aa..283dfb39d46f 100644
--- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
@@ -62,6 +62,15 @@ properties:
minimum: 0
maximum: 32
+ qcom,cmb-msr-num:
+ description:
+ Specifies the number of CMB MSR(mux select register)
+ registers supported by the monitor. If this property is not configured
+ or set to 0, it means this TPDM doesn't support CMB MSR.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 128
+
clocks:
maxItems: 1
@@ -97,6 +106,7 @@ examples:
qcom,dsb-element-size = <32>;
qcom,dsb_msr_num = <16>;
+ qcom,cmb-msr-num = <6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
--
2.39.0
TPDM CMB subunits support two forms of CMB data set element creation:
continuous and trace-on-change collection mode. Continuous change
creates CMB data set elements on every CMBCLK edge. Trace-on-change
creates CMB data set elements only when a new data set element differs
in value from the previous element in a CMB data set. Set CMB_CR.MODE
to 0 for continuous CMB collection mode. Set CMB_CR.MODE to 1 for
trace-on-change CMB collection mode
Signed-off-by: Mao Jinlong <[email protected]>
---
.../testing/sysfs-bus-coresight-devices-tpdm | 8 ++
drivers/hwtracing/coresight/coresight-tpdm.c | 77 ++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 12 +++
3 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index 6bdba7d375c9..89051018dd70 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -155,3 +155,11 @@ Description:
Accepts the following two values.
value 1: Index number of MSR register
value 2: The value need to be written
+
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_mode
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <[email protected]>
+Description: (RW) Read or write CMB data collection mode. Only value 0 and 1 can be written to this node.
+ Set to 0 is for continuous CMB collection mode. Set to 1 is for trace-on-change CMB
+ collection mode.
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index d92432329c9c..68244abfc8b9 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -34,6 +34,21 @@ static umode_t tpdm_dsb_is_visible(struct kobject *kobj,
return 0;
}
+static umode_t tpdm_cmb_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (drvdata) {
+ if (drvdata->datasets & TPDM_PIDR0_DS_CMB)
+ return attr->mode;
+ }
+
+ return 0;
+}
+
+
static int tpdm_init_datasets(struct tpdm_drvdata *drvdata)
{
if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
@@ -50,6 +65,15 @@ static int tpdm_init_datasets(struct tpdm_drvdata *drvdata)
&drvdata->dsb->msr_num);
}
+ if (drvdata->datasets & TPDM_PIDR0_DS_CMB) {
+ if (!drvdata->cmb) {
+ drvdata->cmb = devm_kzalloc(drvdata->dev,
+ sizeof(*drvdata->cmb), GFP_KERNEL);
+ if (!drvdata->cmb)
+ return -ENOMEM;
+ }
+ }
+
return 0;
}
@@ -154,9 +178,18 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
u32 val;
val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
- val |= TPDM_CMB_CR_ENA;
+ /*
+ * Set to 0 for continuous CMB collection mode,
+ * 1 for trace-on-change CMB collection mode.
+ */
+ if (drvdata->cmb->trace_mode)
+ val |= TPDM_CMB_CR_MODE;
+ else
+ val &= ~TPDM_CMB_CR_MODE;
/* Set the enable bit of CMB control register to 1 */
+ val |= TPDM_CMB_CR_ENA;
+
writel_relaxed(val, drvdata->base + TPDM_CMB_CR);
}
@@ -819,6 +852,37 @@ static ssize_t dsb_msr_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_msr);
+static ssize_t cmb_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->cmb->trace_mode);
+
+}
+
+static ssize_t cmb_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 trace_mode;
+ int ret;
+
+ ret = kstrtoul(buf, 16, &trace_mode);
+ if (ret || (trace_mode & ~1UL))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->trace_mode = trace_mode;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_mode);
+
static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_mode.attr,
&dev_attr_dsb_edge_ctrl.attr,
@@ -835,14 +899,25 @@ static struct attribute *tpdm_dsb_attrs[] = {
NULL,
};
+static struct attribute *tpdm_cmb_attrs[] = {
+ &dev_attr_cmb_mode.attr,
+ NULL,
+};
+
static struct attribute_group tpdm_dsb_attr_grp = {
.attrs = tpdm_dsb_attrs,
.is_visible = tpdm_dsb_is_visible,
};
+static struct attribute_group tpdm_cmb_attr_grp = {
+ .attrs = tpdm_cmb_attrs,
+ .is_visible = tpdm_cmb_is_visible,
+};
+
static const struct attribute_group *tpdm_attr_grps[] = {
&tpdm_attr_grp,
&tpdm_dsb_attr_grp,
+ &tpdm_cmb_attr_grp,
NULL,
};
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 4c065a4b8a75..d716963bee10 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -15,6 +15,8 @@
/* Enable bit for CMB subunit */
#define TPDM_CMB_CR_ENA BIT(0)
+/* Trace collection mode for CMB subunit*/
+#define TPDM_CMB_CR_MODE BIT(1)
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
@@ -117,6 +119,14 @@ struct dsb_dataset {
u32 *msr;
};
+/*
+ * struct cmb_dataset
+ * @trace_mode: Dataset collection mode
+ */
+struct cmb_dataset {
+ u32 trace_mode;
+};
+
/**
* struct tpdm_drvdata - specifics associated to an TPDM component
* @base: memory mapped base address for this component.
@@ -125,6 +135,7 @@ struct dsb_dataset {
* @spinlock: lock for the drvdata value.
* @enable: enable status of the component.
* @datasets: The datasets types present of the TPDM.
+ * @cmb: cmb dataset struct data.
*/
struct tpdm_drvdata {
@@ -135,6 +146,7 @@ struct tpdm_drvdata {
bool enable;
unsigned long datasets;
struct dsb_dataset *dsb;
+ struct cmb_dataset *cmb;
};
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
--
2.39.0
Timestamps are requested if the monitor’s CMB data set unit input
data matches the value in the Monitor CMB timestamp pattern and mask
registers (M_CMB_TPR and M_CMB_TPMR) when CMB timestamp enabled
via the timestamp insertion enable register bit(CMB_TIER.PATT_TSENAB).
The pattern match trigger output is achieved via setting values into
the CMB trigger pattern and mask registers (CMB_XPR and CMB_XPMR).
After configuring a pattern through these registers, the TPDM subunit
will assert an output trigger every time it receives new input data
that matches the configured pattern value. Values in a given bit
number of the mask register correspond to the same bit number in
the corresponding pattern register.
Signed-off-by: Mao Jinlong <[email protected]>
---
.../testing/sysfs-bus-coresight-devices-tpdm | 25 +++
drivers/hwtracing/coresight/coresight-tpdm.c | 169 ++++++++++++++++++
drivers/hwtracing/coresight/coresight-tpdm.h | 19 ++
3 files changed, 213 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index 89051018dd70..4cc22ad5c485 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -163,3 +163,28 @@ Contact: Jinlong Mao <[email protected]>
Description: (RW) Read or write CMB data collection mode. Only value 0 and 1 can be written to this node.
Set to 0 is for continuous CMB collection mode. Set to 1 is for trace-on-change CMB
collection mode.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt_mask
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <[email protected]>
+Description: (RW) Read or write CMB timestamp pattern mask.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt_val
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <[email protected]>
+Description: (RW) Read or write CMB interface timestamp request pattern match control.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt_mask
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <[email protected]>
+Description: (RW) Read or write the value of CMB subunit trigger pattern mask.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt_val
+Date: March 2023
+KernelVersion 6.3
+Contact: Jinlong Mao <[email protected]>
+Description: (RW) Read or write the value of CMB subunit trigger pattern match.
+
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 68244abfc8b9..05341fa7a6b7 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -176,6 +176,19 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
{
u32 val;
+ int i;
+
+ /* Configure pattern registers*/
+ for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
+ writel_relaxed(drvdata->cmb->patt_val[i],
+ drvdata->base + TPDM_CMB_TPR(i));
+ writel_relaxed(drvdata->cmb->patt_mask[i],
+ drvdata->base + TPDM_CMB_TPMR(i));
+ writel_relaxed(drvdata->cmb->trig_patt_val[i],
+ drvdata->base + TPDM_CMB_XPR(i));
+ writel_relaxed(drvdata->cmb->trig_patt_mask[i],
+ drvdata->base + TPDM_CMB_XPMR(i));
+ }
val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
/*
@@ -883,6 +896,158 @@ static ssize_t cmb_mode_store(struct device *dev,
}
static DEVICE_ATTR_RW(cmb_mode);
+static ssize_t cmb_patt_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
+ size += sysfs_emit_at(buf, size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->patt_val[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t cmb_patt_val_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 index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_MAX_PATT)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->patt_val[index] = val;
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_patt_val);
+
+static ssize_t cmb_patt_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
+ size += sysfs_emit_at(buf, size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->patt_mask[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+
+}
+
+static ssize_t cmb_patt_mask_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 index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_MAX_PATT)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->patt_mask[index] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_patt_mask);
+
+static ssize_t cmb_trig_patt_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
+ size += sysfs_emit_at(buf, size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->trig_patt_val[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+
+static ssize_t cmb_trig_patt_val_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 index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_MAX_PATT)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->trig_patt_val[index] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_trig_patt_val);
+
+static ssize_t cmb_trig_patt_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
+ size += sysfs_emit_at(buf, size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->trig_patt_mask[i]);
+ }
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+
+static ssize_t cmb_trig_patt_mask_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 index, val;
+
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_MAX_PATT)
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->cmb->trig_patt_mask[index] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(cmb_trig_patt_mask);
+
static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_mode.attr,
&dev_attr_dsb_edge_ctrl.attr,
@@ -901,6 +1066,10 @@ static struct attribute *tpdm_dsb_attrs[] = {
static struct attribute *tpdm_cmb_attrs[] = {
&dev_attr_cmb_mode.attr,
+ &dev_attr_cmb_patt_val.attr,
+ &dev_attr_cmb_patt_mask.attr,
+ &dev_attr_cmb_trig_patt_val.attr,
+ &dev_attr_cmb_trig_patt_mask.attr,
NULL,
};
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index d716963bee10..616b6df41e00 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -12,12 +12,23 @@
/* CMB Subunit Registers*/
/*CMB subunit global control register*/
#define TPDM_CMB_CR (0xA00)
+/*CMB subunit timestamp pattern registers*/
+#define TPDM_CMB_TPR(n) (0xA08 + (n * 4))
+/*CMB subunit timestamp pattern mask registers*/
+#define TPDM_CMB_TPMR(n) (0xA10 + (n * 4))
+/*CMB subunit trigger pattern registers*/
+#define TPDM_CMB_XPR(n) (0xA18 + (n * 4))
+/*CMB subunit trigger pattern mask registers*/
+#define TPDM_CMB_XPMR(n) (0xA20 + (n * 4))
/* Enable bit for CMB subunit */
#define TPDM_CMB_CR_ENA BIT(0)
/* Trace collection mode for CMB subunit*/
#define TPDM_CMB_CR_MODE BIT(1)
+/*Patten register number*/
+#define TPDM_CMB_MAX_PATT 2
+
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
#define TPDM_DSB_TIER (0x784)
@@ -122,9 +133,17 @@ struct dsb_dataset {
/*
* struct cmb_dataset
* @trace_mode: Dataset collection mode
+ * @patt_val: Save value for pattern
+ * @patt_mask: Save value for pattern mask
+ * @trig_patt_val: Save value for trigger pattern
+ * @trig_patt_mask: Save value for trigger pattern mask
*/
struct cmb_dataset {
u32 trace_mode;
+ u32 patt_val[TPDM_CMB_MAX_PATT];
+ u32 patt_mask[TPDM_CMB_MAX_PATT];
+ u32 trig_patt_val[TPDM_CMB_MAX_PATT];
+ u32 trig_patt_mask[TPDM_CMB_MAX_PATT];
};
/**
--
2.39.0
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 <[email protected]>
---
.../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(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index aa357f463d03..403c45fcdcfe 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -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 <[email protected]>
+Description: (RW) Read or write the value of CMB msr.
+
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 88bb740cddd6..91b9ec80bf23 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -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,
};
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 88ade2f2ef6c..d783fc94252b 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -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;
--
2.39.0
CMB (continuous multi-bit) is one of TPDM's dataset type. CMB subunit
can be enabled for data collection by writing 1 to the first bit of
CMB_CR register. This change is to add enable/disable function for
CMB dataset by writing CMB_CR register.
Signed-off-by: Mao Jinlong <[email protected]>
---
drivers/hwtracing/coresight/coresight-tpdm.c | 30 ++++++++++++++++++--
drivers/hwtracing/coresight/coresight-tpdm.h | 9 ++++++
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 3240bc4a8b30..d92432329c9c 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -149,6 +149,17 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
}
+static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
+{
+ u32 val;
+
+ val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
+ val |= TPDM_CMB_CR_ENA;
+
+ /* Set the enable bit of CMB control register to 1 */
+ writel_relaxed(val, drvdata->base + TPDM_CMB_CR);
+}
+
/* TPDM enable operations */
/* The TPDM or Monitor serves as data collection component for various
* dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
@@ -160,9 +171,11 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
{
CS_UNLOCK(drvdata->base);
- /* Check if DSB datasets is present for TPDM. */
+ /* Enable dataset packets */
if (drvdata->datasets & TPDM_PIDR0_DS_DSB)
tpdm_enable_dsb(drvdata);
+ if (drvdata->datasets & TPDM_PIDR0_DS_CMB)
+ tpdm_enable_cmb(drvdata);
CS_LOCK(drvdata->base);
}
@@ -196,14 +209,27 @@ static void tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
}
+static void tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
+{
+ u32 val;
+
+ val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
+ val &= ~TPDM_CMB_CR_ENA;
+
+ /* Set the enable bit of CMB control register to 0 */
+ writel_relaxed(val, drvdata->base + TPDM_CMB_CR);
+}
+
/* TPDM disable operations */
static void __tpdm_disable(struct tpdm_drvdata *drvdata)
{
CS_UNLOCK(drvdata->base);
- /* Check if DSB datasets is present for TPDM. */
+ /* Disable dataset packet */
if (drvdata->datasets & TPDM_PIDR0_DS_DSB)
tpdm_disable_dsb(drvdata);
+ if (drvdata->datasets & TPDM_PIDR0_DS_CMB)
+ tpdm_disable_cmb(drvdata);
CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 355a499635c2..4c065a4b8a75 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -9,6 +9,13 @@
/* The max number of the datasets that TPDM supports */
#define TPDM_DATASETS 7
+/* CMB Subunit Registers*/
+/*CMB subunit global control register*/
+#define TPDM_CMB_CR (0xA00)
+
+/* Enable bit for CMB subunit */
+#define TPDM_CMB_CR_ENA BIT(0)
+
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
#define TPDM_DSB_TIER (0x784)
@@ -65,10 +72,12 @@
*
* PERIPHIDR0[0] : Fix to 1 if ImplDef subunit present, else 0
* PERIPHIDR0[1] : Fix to 1 if DSB subunit present, else 0
+ * PERIPHIDR0[2] : Fix to 1 if CMB subunit present, else 0
*/
#define TPDM_PIDR0_DS_IMPDEF BIT(0)
#define TPDM_PIDR0_DS_DSB BIT(1)
+#define TPDM_PIDR0_DS_CMB BIT(2)
#define TPDM_DSB_MAX_LINES 256
/* MAX number of EDCR registers */
--
2.39.0
Add property "qcom,cmb-elem-size" to support CMB element for TPDM.
The associated aggregator will read this size before it is enabled.
CMB element size currently only supports 8-bit, 32-bit and 64-bit.
Signed-off-by: Mao Jinlong <[email protected]>
---
.../bindings/arm/qcom,coresight-tpdm.yaml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
index 283dfb39d46f..c5169de81e58 100644
--- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
@@ -53,6 +53,14 @@ properties:
minimum: 32
maximum: 64
+ qcom,cmb-element-size:
+ description:
+ Specifies the CMB (Continuous multi-bit) element size supported by
+ the monitor. The associated aggregator will read this size before it
+ is enabled. CMB element size currently supports 8-bit, 32-bit, 64-bit.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [8, 32, 64]
+
qcom,dsb_msr_num:
description:
Specifies the number of DSB(Discrete Single Bit) MSR(mux select register)
@@ -95,6 +103,12 @@ required:
- clocks
- clock-names
+anyOf:
+ - required:
+ - qcom,dsb_msr_num
+ - required:
+ - qcom,cmb-msr-num
+
additionalProperties: false
examples:
@@ -105,6 +119,8 @@ examples:
reg = <0x0684c000 0x1000>;
qcom,dsb-element-size = <32>;
+ qcom,cmb-element-size = <32>;
+
qcom,dsb_msr_num = <16>;
qcom,cmb-msr-num = <6>;
--
2.39.0
On 29/03/2023 10:47, Mao Jinlong wrote:
> Add property "qcom,cmb_msr_num" to support CMB MSR(mux select register)
> for TPDM. It specifies the number of CMB MSR registers supported by
> the TDPM.
>
> Signed-off-by: Mao Jinlong <[email protected]>
Acked-by: Krzysztof Kozlowski <[email protected]>
Best regards,
Krzysztof
On 29/03/2023 10:47, Mao Jinlong wrote:
> Add property "qcom,cmb-elem-size" to support CMB element for TPDM.
> The associated aggregator will read this size before it is enabled.
> CMB element size currently only supports 8-bit, 32-bit and 64-bit.
>
> Signed-off-by: Mao Jinlong <[email protected]>
> ---
> .../bindings/arm/qcom,coresight-tpdm.yaml | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
> index 283dfb39d46f..c5169de81e58 100644
> --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
> +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
> @@ -53,6 +53,14 @@ properties:
> minimum: 32
> maximum: 64
>
> + qcom,cmb-element-size:
s/size/bits/
https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/property-units.yaml
> + description:
> + Specifies the CMB (Continuous multi-bit) element size supported by
> + the monitor. The associated aggregator will read this size before it
> + is enabled. CMB element size currently supports 8-bit, 32-bit, 64-bit.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + enum: [8, 32, 64]
> +
> qcom,dsb_msr_num:
> description:
> Specifies the number of DSB(Discrete Single Bit) MSR(mux select register)
> @@ -95,6 +103,12 @@ required:
> - clocks
> - clock-names
>
> +anyOf:
> + - required:
> + - qcom,dsb_msr_num
There is no such property.
> + - required:
> + - qcom,cmb-msr-num
Why this is part of this patch?
> +
> additionalProperties: false
>
> examples:
> @@ -105,6 +119,8 @@ examples:
> reg = <0x0684c000 0x1000>;
>
> qcom,dsb-element-size = <32>;
> + qcom,cmb-element-size = <32>;
> +
> qcom,dsb_msr_num = <16>;
> qcom,cmb-msr-num = <6>;
>
Best regards,
Krzysztof