2023-07-25 08:15:06

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 00/13] Add support to configure TPDM DSB subunit

Introduction of TPDM DSB subunit
DSB subunit is responsible for creating a dataset element, and is also
optionally responsible for packing it to fit multiple elements on a
single ATB transfer if possible in the configuration. The TPDM Core
Datapath requests timestamps be stored by the TPDA and then delivering
ATB sized data (depending on ATB width and element size, this could
be smaller or larger than a dataset element) to the ATB Mast FSM.

The DSB subunit must be configured prior to enablement. This series
adds support for TPDM to configure the configure DSB subunit.

Once this series patches are applied properly, the new tpdm nodes for
should be observed at the tpdm path /sys/bus/coresight/devices/tpdm*
which supports DSB subunit.
e.g.
/sys/devices/platform/soc@0/69d0000.tpdm/tpdm0#ls -l | grep dsb
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_edge_ctrl
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_edge_ctrl_mask
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_mode
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_mask
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_ts
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_type
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_val
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_patt_mask
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_patt_val
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_ts
-rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_type

We can use the commands are similar to the below to configure the
TPDMs which support DSB subunit. Enable coresight sink first.
echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink
echo 1 > /sys/bus/coresight/devices/tpdm0/reset
echo 0x3 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_idx
echo 0x1 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_mask
echo 0x0 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl
echo 1 > /sys/bus/coresight/devices/tpdm0/dsb_patt_ts
echo 1 > /sys/bus/coresight/devices/tpdm0/dsb_patt_type
echo 0 > /sys/bus/coresight/devices/tpdm0/dsb_trig_ts
echo 0x5 > /sys/bus/coresight/devices/tpdm0/dsb_patt_idx
echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_patt_mask
echo 0x2 > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_idx
echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_val

TPDM_DSB commit tree:
https://git.codelinaro.org/clo/linux-kernel/coresight/-/tree/tpdm-dsb-v7
https://git.codelinaro.org/clo/linux-kernel/coresight/-/commits/tpdm-dsb-v7

Changes in V7:
1. Since the "One value" limitation on SysFs file usage, add
the nodes to read/write the index number for configuring the
DSB TPDM. The following index number nodes are added.
"dsb_edge_ctrl_idx" in the patch #9
"dsb_trig_patt_idx" in the patch #10
"dsb_patt_idx" in the patch #11
"dsb_msr_idx" in the patch #13
-- Suzuki K Poulose

Changes in V6:
1. Align the code to fix the styling issue.
-- Suzuki K Poulose

Changes in V5:
1. Correct data type for DSB element size in dt-bindings patch.
2. Refine the recursive function "tpda_set_element_size".
-- Suzuki K Poulose
3. Get return value of the function "__tpda_enable" in
"tpda_enable".
-- Suzuki K Poulose
4. Refine the comments on "dsb_esize".
-- Suzuki K Poulose
5. Split the chage that introduce the subtype
"SUBTYPE_SOURCE_TPDM" to Coresight driver.
-- Suzuki K Poulose
6. Inline the trigger type setting to "tpdm_enable_dsb" simply.
-- Suzuki K Poulose
7. Split the change that remove the needless CS_{UN,}LOCK in
the function "tpdm_datasets_setup".
-- Suzuki K Poulose
8. Remove the disablement step in the reset node.
-- Suzuki K Poulose
9. Update the kernel version to 6.5 in the sysfs document.
-- Suzuki K Poulose
10. Remove the needless check in "tpdm_dsb_is_visible".
-- Suzuki K Poulose
11. Change the macro to mask the mode of DSB TPDM.
-- Suzuki K Poulose
12. Add a check to make sure "sysfs_emit_at" calling will not
cause overflow.
-- Suzuki K Poulose
13. Change the macro to get "edge_ctrl" value.
-- Suzuki K Poulose
14. Remove the needless comments in the sysfs document.
-- Suzuki K Poulose
15. Replace "TPDM_DSB_MAX_PATT" with "drvdata->dsb->msr_num" in
"dsb_msr_show".
-- Suzuki K Poulose
16. Update the check of MSR number in "dsb_msr_store".
-- Suzuki K Poulose
17. Write data to the MSR registers in the DSB TPDM enablement
function.
-- Suzuki K Poulose

Changes in V4:
1. Change the range of the property "qcom,dsb-element-size", and
change the type to enumeration.
-- Suzuki K Poulose, Krzysztof Kozlowski
2. Change dsb_esize from 32 bits to 8 bits.
-- Suzuki K Poulose
3. Update the function tpda_set_element_size since James has
updated the dependency series. Meanwhile, it will send out a
warning if it detects more than one TPDM from the same TPDA
input port.
-- Suzuki K Poulose
4. Add a source_sub_type for TPDM to distinguish TPDM from
the other coresight source.
-- Suzuki K Poulose
5. Return error if the element size is not configured on
devicetree in TPDA enablement.
-- Suzuki K Poulose
6. Move memory allocation from "tpdm_init_datasets" to
"tpdm_datasets_setup". Rename "tpdm_init_datasets" as
"tpdm_reset_datasets".
-- Suzuki K Poulose
7. Replace "coresight_disable" with "coresight_disable_source"
to disable the TPDM in resetting.
-- Suzuki K Poulose
8. Make sure "drvdata" is not NULL pointer before using it.
-- Suzuki K Poulose
9. Change "set_dsb_cycacc_mode" to "set_dsb_test_mode" since
cycle accurate mode is not supported on the current targets.
It is replaced by test mode.
10. Document the value of "dsb_mode".
-- Suzuki K Poulose
11. Macros are used to replace the formulas on dsb edge control
nodes.
-- Suzuki K Poulose
12. Document the values of "dsb_trig_patt_val" and
"dsb_trig_patt_mask".
-- Suzuki K Poulose
13. Combine two pattern related loops to one. And move DSB TIER
register configurations to the new function "set_dsb_tier".
-- Suzuki K Poulose
14. Rename the property "qcom,dsb_msr_num" to "qcom,dsb-msrs-num".
-- Suzuki K Poulose, Krzysztof Kozlowski

Changes in V3:
1. Move the property "qcom,dsb-element-size" to TPDM
devicetree and update the TPDM yaml file for this item.
-- Suzuki K Poulose
2. Add the error message when the DSB element size is not set to
32-bit or 64-bit. -- Suzuki K Poulose
3. Add more information to the comments of patch #3
-- Suzuki K Poulose
4. Combine the value updates to the TPDM_DSB_CR for TPDM.
-- Suzuki K Poulose
5. Remove the function "tpdm_datasets_alloc", and fold its code
to a new function "tpdm_init_datasets". It will complete the
initialization of TPDM. -- Suzuki K Poulose
6. Change the method of qualifying input values.
-- Suzuki K Poulose
7. Add the documentation of the new sysfs handles.
-- Suzuki K Poulose
8. Provide the separate handles for the "mode bits".
-- Suzuki K Poulose

Changes in V2:
1. Change the name of the property "qcom,dsb-elem-size" to
"qcom,dsb-element-size" -- Suzuki K Poulose
2. Update the TPDA yaml file for the item "qcom,dsb-elem-size".
-- Krzysztof Kozlowski
3. Add the full name of DSB in the description of the item
"qcom,dsb-elem-size". -- Rob Herring

Changes in V1:
1. Change the definition of the property "qcom,dsb-elem-size" from
"uint32-array" to "uint32-matrix". -- Krzysztof Kozlowski
2. Add the full name of DSB. -- Rob Herring
3. Deal with 2 entries in an iteration in TPDA driver. -- Suzuki K Poulose
4. Divide the function "tpdm_datasets_alloc" into two functions,
"tpdm_datasets_setup" and "tpdm_datasets_alloc".
5. Detecte the input string with the conventional semantics automatically,
and constrain the size of the input value. -- Suzuki K Poulose
6. Use the hook function "is_visible()" to hide the DSB related knobs if
the data sets are missing. -- Suzuki K Poulose
7. Use the macros "FIELD_GET" and "FIELD_PREP" to set the values.
-- Suzuki K Poulose
8. Update the definition of the macros in TPDM driver.
9. Update the comments of the values for the nodes which are for DSB
element creation and onfigure pattern match output. -- Suzuki K Poulose
10. Use API "sysfs_emit" to "replace scnprintf". -- Suzuki K Poulose

Tao Zhang (13):
coresight-tpdm: Remove the unnecessary lock
dt-bindings: arm: Add support for DSB element size
coresight-tpdm: Introduce TPDM subtype to TPDM driver
coresight-tpda: Add DSB dataset support
coresight-tpdm: Initialize DSB subunit configuration
coresight-tpdm: Add reset node to TPDM node
coresight-tpdm: Add nodes to set trigger timestamp and type
coresight-tpdm: Add node to set dsb programming mode
coresight-tpdm: Add nodes for dsb edge control
coresight-tpdm: Add nodes to configure pattern match output
coresight-tpdm: Add nodes for timestamp request
dt-bindings: arm: Add support for DSB MSR register
coresight-tpdm: Add nodes for dsb msr support

.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 192 +++++
.../bindings/arm/qcom,coresight-tpdm.yaml | 20 +
drivers/hwtracing/coresight/coresight-core.c | 1 +
drivers/hwtracing/coresight/coresight-tpda.c | 96 ++-
drivers/hwtracing/coresight/coresight-tpda.h | 4 +
drivers/hwtracing/coresight/coresight-tpdm.c | 806 ++++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 91 +++
include/linux/coresight.h | 1 +
8 files changed, 1193 insertions(+), 18 deletions(-)

--
2.7.4



2023-07-25 08:15:50

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 11/13] coresight-tpdm: Add nodes for timestamp request

Add nodes to configure the timestamp request based on input
pattern match. Each TPDM that support DSB subunit has maximum of
n(n<7) TPR registers to configure value for timestamp request
based on input pattern match. Eight 32 bit registers providing
DSB interface timestamp request pattern match comparison. And
each TPDM that support DSB subunit has maximum of m(m<7) TPMR
registers to configure pattern mask for timestamp request. Eight
32 bit registers providing DSB interface timestamp request
pattern match mask generation. Add nodes to enable/disable
pattern timestamp and set pattern timestamp type.

Signed-off-by: Tao Zhang <[email protected]>
---
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 57 +++++-
drivers/hwtracing/coresight/coresight-tpdm.c | 205 ++++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++
3 files changed, 272 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index 66f9582..74a0126 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -130,4 +130,59 @@ Description:
to the index number. Before writing data to this sysfs file,
"dsb_trig_patt_idx" should be written first to configure the
index number of the trigger pattern mask which needs to be
- configured.
\ No newline at end of file
+ configured.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_idx
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read/Write the index number of the DSB tpdm pattern. Since
+ there are at most 8 TPR and TPMR registers for the parttern,
+ this value ranges from 0 to 7.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the pattern values of the DSB TPDM. Write a data
+ to configure the pattern corresponding to the index number.
+ Before writing data to this sysfs file, "dsb_patt_idx" should be
+ written first to configure the index number of the pattern which
+ needs to be configured.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the pattern mask values of the DSB TPDM. Write a
+ data to configure the pattern mask corresponding to the index
+ number. Before writing data to this sysfs file, "dsb_patt_idx"
+ should be written first to configure the index number of the
+ pattern mask which needs to be configured.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+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_type
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+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.
\ No newline at end of file
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 1c32d27..f9e5a1d 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -69,6 +69,27 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
*val &= ~TPDM_DSB_CR_MODE;
}

+static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val)
+{
+ /* 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;
+
+}
+
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
{
u32 val, i;
@@ -81,6 +102,10 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
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],
@@ -88,11 +113,7 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
}

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;
+ set_dsb_tier(drvdata, &val);
writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);

val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
@@ -462,6 +483,175 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);

+static ssize_t dsb_patt_idx_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_idx);
+
+}
+
+static ssize_t dsb_patt_idx_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;
+
+ if ((kstrtoul(buf, 0, &index)) || (index >= TPDM_DSB_MAX_PATT))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->patt_idx = index;
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+
+}
+static DEVICE_ATTR_RW(dsb_patt_idx);
+
+static ssize_t dsb_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;
+ unsigned long bytes;
+ int i = 0;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Value: 0x%x\n", drvdata->dsb->patt_val[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t dsb_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 val;
+
+ if (kstrtoul(buf, 0, &val))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->patt_val[drvdata->dsb->patt_idx] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_val);
+
+static ssize_t dsb_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;
+ unsigned long bytes;
+ int i = 0;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Value: 0x%x\n", drvdata->dsb->patt_mask[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t dsb_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 val;
+
+ if (kstrtoul(buf, 0, &val))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->patt_mask[drvdata->dsb->patt_idx] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_patt_mask);
+
+static ssize_t dsb_patt_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 dsb_patt_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(dsb_patt_ts);
+
+static ssize_t dsb_patt_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 dsb_patt_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(dsb_patt_type);
+
static ssize_t dsb_trig_patt_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -645,6 +835,11 @@ static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_edge_ctrl_idx.attr,
&dev_attr_dsb_edge_ctrl_val.attr,
&dev_attr_dsb_edge_ctrl_mask.attr,
+ &dev_attr_dsb_patt_idx.attr,
+ &dev_attr_dsb_patt_val.attr,
+ &dev_attr_dsb_patt_mask.attr,
+ &dev_attr_dsb_patt_ts.attr,
+ &dev_attr_dsb_patt_type.attr,
&dev_attr_dsb_trig_patt_idx.attr,
&dev_attr_dsb_trig_patt_val.attr,
&dev_attr_dsb_trig_patt_mask.attr,
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 7f688b2..7c52cf4 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -12,6 +12,8 @@
/* 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))
@@ -24,8 +26,12 @@
/* Enable bit for DSB subunit trigger type */
#define TPDM_DSB_CR_TRIG_TYPE BIT(12)

+/* 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 */
/* Test mode control bit*/
@@ -86,22 +92,32 @@
* struct dsb_dataset - specifics associated to dsb dataset
* @mode: DSB programming mode
* @edge_ctrl_idx Index number of the edge control
+ * @patt_idx Index number of pattern
* @trig_patt_idx Index number of the trigger pattern
* @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.
*/
struct dsb_dataset {
u32 mode;
u32 edge_ctrl_idx;
+ u32 patt_idx;
u32 trig_patt_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;
};
--
2.7.4


2023-07-25 08:19:45

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 02/13] dt-bindings: arm: Add support for DSB element size

Add property "qcom,dsb-elem-size" to support DSB(Discrete Single
Bit) element for TPDM. The associated aggregator will read this
size before it is enabled. DSB element size currently only
supports 32-bit and 64-bit.

Signed-off-by: Tao Zhang <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/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 5c08342..931ee8f 100644
--- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
@@ -44,6 +44,14 @@ properties:
minItems: 1
maxItems: 2

+ qcom,dsb-element-size:
+ description:
+ Specifies the DSB(Discrete Single Bit) element size supported by
+ the monitor. The associated aggregator will read this size before it
+ is enabled. DSB element size currently only supports 32-bit and 64-bit.
+ $ref: /schemas/types.yaml#/definitions/uint8
+ enum: [32, 64]
+
clocks:
maxItems: 1

@@ -77,6 +85,8 @@ examples:
compatible = "qcom,coresight-tpdm", "arm,primecell";
reg = <0x0684c000 0x1000>;

+ qcom,dsb-element-size = /bits/ 8 <32>;
+
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";

--
2.7.4


2023-07-25 08:23:15

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 10/13] coresight-tpdm: Add nodes to configure pattern match output

Add nodes to configure trigger pattern and trigger pattern mask.
Each DSB subunit TPDM has maximum of n(n<7) XPR registers to
configure trigger pattern match output. Eight 32 bit registers
providing DSB interface trigger output pattern match comparison.
And each DSB subunit TPDM has maximum of m(m<7) XPMR registers to
configure trigger pattern mask match output. Eight 32 bit
registers providing DSB interface trigger output pattern match
mask.

Signed-off-by: Tao Zhang <[email protected]>
---
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 34 +++++-
drivers/hwtracing/coresight/coresight-tpdm.c | 118 +++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tpdm.h | 10 ++
3 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index a4550c5..66f9582 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -98,4 +98,36 @@ Description:
should be written first to configure the index number of the edge
detection which needs to be masked.

- Accepts only one of the 2 values - 0 or 1.
\ No newline at end of file
+ Accepts only one of the 2 values - 0 or 1.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_idx
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read/Write the index number of the trigger pattern value of DSB
+ tpdm. Since there are at most 8 XPR and XPMR registers for the
+ trigger parttern, this value ranges from 0 to 7.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the trigger pattern values of the DSB TPDM.
+ Write a data to configure the trigger pattern corresponding to
+ the index number. Before writing data to this sysfs file,
+ "dsb_trig_patt_idx" should be written first to configure the
+ index number of the trigger pattern which needs to be configured.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the trigger pattern mask of the DSB TPDM.
+ Write a data to configure the trigger pattern mask corresponding
+ to the index number. Before writing data to this sysfs file,
+ "dsb_trig_patt_idx" should be written first to configure the
+ index number of the trigger pattern mask which needs to be
+ configured.
\ No newline at end of file
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 98fd6ab..1c32d27 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -80,6 +80,13 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
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->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)
@@ -455,6 +462,114 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);

+static ssize_t dsb_trig_patt_idx_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->trig_patt_idx);
+}
+
+static ssize_t dsb_trig_patt_idx_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;
+
+ if (kstrtoul(buf, 0, &index))
+ return -EINVAL;
+ if (index >= TPDM_DSB_MAX_PATT)
+ return -EPERM;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->trig_patt_idx = index;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_patt_idx);
+
+static ssize_t dsb_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;
+ unsigned long bytes;
+ int i = 0;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Value: 0x%x\n", drvdata->dsb->trig_patt[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t dsb_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 val;
+
+ if (kstrtoul(buf, 0, &val))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->trig_patt[drvdata->dsb->trig_patt_idx] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_patt_val);
+
+static ssize_t dsb_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;
+ unsigned long bytes;
+ int i = 0;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Value: 0x%x\n", drvdata->dsb->trig_patt_mask[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t dsb_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 val;
+
+ if (kstrtoul(buf, 0, &val))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->trig_patt_mask[drvdata->dsb->trig_patt_idx] = val;
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_trig_patt_mask);
+
static ssize_t dsb_trig_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -530,6 +645,9 @@ static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_edge_ctrl_idx.attr,
&dev_attr_dsb_edge_ctrl_val.attr,
&dev_attr_dsb_edge_ctrl_mask.attr,
+ &dev_attr_dsb_trig_patt_idx.attr,
+ &dev_attr_dsb_trig_patt_val.attr,
+ &dev_attr_dsb_trig_patt_mask.attr,
&dev_attr_dsb_trig_ts.attr,
&dev_attr_dsb_trig_type.attr,
NULL,
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 4afdb29..7f688b2 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -12,6 +12,8 @@
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
#define TPDM_DSB_TIER (0x784)
+#define TPDM_DSB_XPR(n) (0x7C8 + (n * 4))
+#define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4))
#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))

@@ -77,21 +79,29 @@
#define TPDM_DSB_MAX_EDCR 16
/* MAX number of EDCMR registers */
#define TPDM_DSB_MAX_EDCMR 8
+/* MAX number of DSB pattern */
+#define TPDM_DSB_MAX_PATT 8

/**
* struct dsb_dataset - specifics associated to dsb dataset
* @mode: DSB programming mode
* @edge_ctrl_idx Index number of the edge control
+ * @trig_patt_idx Index number of the trigger pattern
* @edge_ctrl: Save value for edge control
* @edge_ctrl_mask: Save value for edge control mask
+ * @trig_patt: Save value for trigger pattern
+ * @trig_patt_mask: Save value for trigger pattern mask
* @trig_ts: Enable/Disable trigger timestamp.
* @trig_type: Enable/Disable trigger type.
*/
struct dsb_dataset {
u32 mode;
u32 edge_ctrl_idx;
+ u32 trig_patt_idx;
u32 edge_ctrl[TPDM_DSB_MAX_EDCR];
u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
+ u32 trig_patt[TPDM_DSB_MAX_PATT];
+ u32 trig_patt_mask[TPDM_DSB_MAX_PATT];
bool trig_ts;
bool trig_type;
};
--
2.7.4


2023-07-25 08:24:07

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 04/13] coresight-tpda: Add DSB dataset support

Read the DSB element size from the device tree. Set the register
bit that controls the DSB element size of the corresponding port.

Signed-off-by: Tao Zhang <[email protected]>
---
drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++---
drivers/hwtracing/coresight/coresight-tpda.h | 4 ++
2 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index 8d2b9d2..7c71342 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -21,6 +21,58 @@

DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");

+/* Search and read element data size from the TPDM node in
+ * the devicetree. Each input port of TPDA is connected to
+ * a TPDM. Different TPDM supports different types of dataset,
+ * and some may support more than one type of dataset.
+ * Parameter "inport" is used to pass in the input port number
+ * of TPDA, and it is set to 0 in the recursize call.
+ * Parameter "parent" is used to pass in the original call.
+ */
+static int tpda_set_element_size(struct tpda_drvdata *drvdata,
+ struct coresight_device *csdev, int inport, bool match_inport)
+{
+ static int nr_inport;
+ int i;
+ static bool tpdm_found;
+ struct coresight_device *in_csdev;
+
+ if (inport > (TPDA_MAX_INPORTS - 1))
+ return -EINVAL;
+
+ if (match_inport) {
+ nr_inport = inport;
+ tpdm_found = false;
+ }
+
+ for (i = 0; i < csdev->pdata->nr_inconns; i++) {
+ in_csdev = csdev->pdata->in_conns[i]->src_dev;
+ if (!in_csdev)
+ break;
+
+ if (match_inport)
+ if (csdev->pdata->in_conns[i]->dest_port != inport)
+ continue;
+
+ if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
+ (in_csdev->subtype.source_subtype
+ == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
+ of_property_read_u8(in_csdev->dev.parent->of_node,
+ "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);
+ if (!tpdm_found)
+ tpdm_found = true;
+ else
+ dev_warn(drvdata->dev,
+ "More than one TPDM is mapped to the TPDA input port %d.\n",
+ nr_inport);
+ continue;
+ }
+ tpda_set_element_size(drvdata, in_csdev, 0, false);
+ }
+
+ return 0;
+}
+
/* Settings pre enabling port control register */
static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
{
@@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
writel_relaxed(val, drvdata->base + TPDA_CR);
}

-static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
+static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
{
u32 val;

val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
+ /*
+ * Configure aggregator port n DSB data set element size
+ * Set the bit to 0 if the size is 32
+ * Set the bit to 1 if the size is 64
+ */
+ if (drvdata->dsb_esize[port] == 32)
+ val &= ~TPDA_Pn_CR_DSBSIZE;
+ else if (drvdata->dsb_esize[port] == 64)
+ val |= TPDA_Pn_CR_DSBSIZE;
+ else
+ return -EINVAL;
+
/* Enable the port */
val |= TPDA_Pn_CR_ENA;
writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
+
+ return 0;
}

-static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
+static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
{
+ int ret;
+
CS_UNLOCK(drvdata->base);

if (!drvdata->csdev->enable)
tpda_enable_pre_port(drvdata);

- tpda_enable_port(drvdata, port);
-
+ ret = tpda_enable_port(drvdata, port);
CS_LOCK(drvdata->base);
+
+ return ret;
}

static int tpda_enable(struct coresight_device *csdev,
@@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev,
struct coresight_connection *out)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
+
+ ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
+ if (ret)
+ return ret;

spin_lock(&drvdata->spinlock);
- if (atomic_read(&in->dest_refcnt) == 0)
- __tpda_enable(drvdata, in->dest_port);
+ if (atomic_read(&in->dest_refcnt) == 0) {
+ ret = __tpda_enable(drvdata, in->dest_port);
+ if (!ret) {
+ atomic_inc(&in->dest_refcnt);
+ dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
+ }
+ }

- atomic_inc(&in->dest_refcnt);
spin_unlock(&drvdata->spinlock);
-
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
- return 0;
+ return ret;
}

static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h
index 0399678..12a1472 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.h
+++ b/drivers/hwtracing/coresight/coresight-tpda.h
@@ -10,6 +10,8 @@
#define TPDA_Pn_CR(n) (0x004 + (n * 4))
/* Aggregator port enable bit */
#define TPDA_Pn_CR_ENA BIT(0)
+/* Aggregator port DSB data set element size bit */
+#define TPDA_Pn_CR_DSBSIZE BIT(8)

#define TPDA_MAX_INPORTS 32

@@ -23,6 +25,7 @@
* @csdev: component vitals needed by the framework.
* @spinlock: lock for the drvdata value.
* @enable: enable status of the component.
+ * @dsb_esize: DSB element size for each inport, it must be 32 or 64.
*/
struct tpda_drvdata {
void __iomem *base;
@@ -30,6 +33,7 @@ struct tpda_drvdata {
struct coresight_device *csdev;
spinlock_t spinlock;
u8 atid;
+ u8 dsb_esize[TPDA_MAX_INPORTS];
};

#endif /* _CORESIGHT_CORESIGHT_TPDA_H */
--
2.7.4


2023-07-25 09:23:45

by Tao Zhang

[permalink] [raw]
Subject: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control

Add the nodes to set value for DSB edge control and DSB edge
control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR
resgisters to configure edge control. DSB edge detection control
00: Rising edge detection
01: Falling edge detection
10: Rising and falling edge detection (toggle detection)
And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to
configure mask. Eight 32 bit registers providing DSB interface
edge detection mask control.

Add the nodes to configure DSB edge control and DSB edge control
mask. Each DSB subunit TPDM maximum of 256 edge detections can be
configured. The index and value sysfs files need to be paired and
written to order. The index sysfs file is to set the index number
of the edge detection which needs to be configured. And the value
sysfs file is to set the control or mask for the edge detection.
DSB edge detection control should be set as the following values.
00: Rising edge detection
01: Falling edge detection
10: Rising and falling edge detection (toggle detection)
And DSB edge mask should be set as 0 or 1.
Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to
configure edge control. And each DSB subunit TPDM has maximum of
m(m<8) ECDMR registers to configure mask.

Signed-off-by: Tao Zhang <[email protected]>
---
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++
drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++-
3 files changed, 223 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index 2a82cd0..a4550c5 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -60,3 +60,42 @@ Description:
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.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read/Write the index number of the edge detection for the DSB
+ subunit TPDM. Since there are at most 256 edge detections, this
+ value ranges from 0 to 255.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the edge control registers of the DSB in TPDM.
+ Write a data to control the edge detection corresponding to
+ the index number. Before writing data to this sysfs file,
+ "dsb_edge_ctrl_idx" should be written first to configure the
+ index number of the edge detection which needs to be controlled.
+
+ Accepts only one of the following values.
+ 0 - Rising edge detection
+ 1 - Falling edge detection
+ 2 - Rising and falling edge detection (toggle detection)
+
+
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask
+Date: March 2023
+KernelVersion 6.5
+Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
+Description:
+ Read a set of the edge control mask registers of the DSB in TPDM.
+ Write a data to mask the edge detection corresponding to the index
+ number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx"
+ should be written first to configure the index number of the edge
+ detection which needs to be masked.
+
+ Accepts only one of the 2 values - 0 or 1.
\ No newline at end of file
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index c38760b..98fd6ab 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)

static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
{
- u32 val;
+ u32 val, i;
+
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
+ writel_relaxed(drvdata->dsb->edge_ctrl[i],
+ drvdata->base + TPDM_DSB_EDCR(i));
+ for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
+ writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
+ drvdata->base + TPDM_DSB_EDCMR(i));

val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
/* Set trigger timestamp */
@@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_mode);

+static ssize_t dsb_edge_ctrl_idx_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->edge_ctrl_idx);
+}
+
+/*
+ * The EDCR registers can include up to 16 32-bit registers, and each
+ * one can be configured to control up to 16 edge detections(2 bits
+ * control one edge detection). So a total 256 edge detections can be
+ * configured. This function provides a way to set the index number of
+ * the edge detection which needs to be configured.
+ */
+static ssize_t dsb_edge_ctrl_idx_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 >= TPDM_DSB_MAX_LINES))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ drvdata->dsb->edge_ctrl_idx = val;
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
+
+static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ unsigned long bytes;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+/*
+ * This function is used to control the edge detection according
+ * to the index number that has been set.
+ * "edge_ctrl" should be one of the following values.
+ * 0 - Rising edge detection
+ * 1 - Falling edge detection
+ * 2 - Rising and falling edge detection (toggle detection)
+ */
+static ssize_t dsb_edge_ctrl_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 val, mask, edge_ctrl;
+ int reg;
+
+ if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ /*
+ * There are 2 bit per DSB Edge Control line.
+ * Thus we have 16 lines in a 32bit word.
+ */
+ reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
+ mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
+ val = drvdata->dsb->edge_ctrl[reg];
+ val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
+ val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
+ drvdata->dsb->edge_ctrl[reg] = val;
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
+
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ssize_t size = 0;
+ unsigned long bytes;
+ int i;
+
+ spin_lock(&drvdata->spinlock);
+ for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
+ bytes = sysfs_emit_at(buf, size,
+ "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
+ if (bytes <= 0)
+ break;
+ size += bytes;
+ }
+ spin_unlock(&drvdata->spinlock);
+ return size;
+}
+
+static ssize_t dsb_edge_ctrl_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 val;
+ u32 set;
+ int reg;
+
+ if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
+ return -EINVAL;
+
+ spin_lock(&drvdata->spinlock);
+ /*
+ * There is 1 bit per DSB Edge Control Mark line.
+ * Thus we have 32 lines in a 32bit word.
+ */
+ reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
+ set = drvdata->dsb->edge_ctrl_mask[reg];
+ if (val)
+ set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
+ else
+ set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
+ drvdata->dsb->edge_ctrl_mask[reg] = set;
+ spin_unlock(&drvdata->spinlock);
+
+ return size;
+}
+static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+
static ssize_t dsb_trig_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts);

static struct attribute *tpdm_dsb_attrs[] = {
&dev_attr_dsb_mode.attr,
+ &dev_attr_dsb_edge_ctrl_idx.attr,
+ &dev_attr_dsb_edge_ctrl_val.attr,
+ &dev_attr_dsb_edge_ctrl_mask.attr,
&dev_attr_dsb_trig_ts.attr,
&dev_attr_dsb_trig_type.attr,
NULL,
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 49fffb1..4afdb29 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -12,6 +12,8 @@
/* DSB Subunit Registers */
#define TPDM_DSB_CR (0x780)
#define TPDM_DSB_TIER (0x784)
+#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
+#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))

/* Enable bit for DSB subunit */
#define TPDM_DSB_CR_ENA BIT(0)
@@ -34,6 +36,16 @@
#define TPDM_DSB_TEST_MODE GENMASK(10, 9)
#define TPDM_DSB_HPSEL GENMASK(6, 2)

+#define EDCRS_PER_WORD 16
+#define EDCR_TO_WORD_IDX(r) ((r) / EDCRS_PER_WORD)
+#define EDCR_TO_WORD_SHIFT(r) ((r % EDCRS_PER_WORD) * 2)
+#define EDCR_TO_WORD_VAL(val, r) (val << EDCR_TO_WORD_SHIFT(r))
+#define EDCR_TO_WORD_MASK(r) EDCR_TO_WORD_VAL(0x3, r)
+
+#define EDCMRS_PER_WORD 32
+#define EDCMR_TO_WORD_IDX(r) ((r) / EDCMRS_PER_WORD)
+#define EDCMR_TO_WORD_SHIFT(r) ((r) % EDCMRS_PER_WORD)
+
/* TPDM integration test registers */
#define TPDM_ITATBCNTRL (0xEF0)
#define TPDM_ITCNTRL (0xF00)
@@ -60,14 +72,26 @@
#define TPDM_PIDR0_DS_IMPDEF BIT(0)
#define TPDM_PIDR0_DS_DSB BIT(1)

+#define TPDM_DSB_MAX_LINES 256
+/* MAX number of EDCR registers */
+#define TPDM_DSB_MAX_EDCR 16
+/* MAX number of EDCMR registers */
+#define TPDM_DSB_MAX_EDCMR 8
+
/**
* struct dsb_dataset - specifics associated to dsb dataset
- * @mode: DSB programming mode
- * @trig_ts: Enable/Disable trigger timestamp.
- * @trig_type: Enable/Disable trigger type.
+ * @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
+ * @trig_ts: Enable/Disable trigger timestamp.
+ * @trig_type: Enable/Disable trigger type.
*/
struct dsb_dataset {
u32 mode;
+ u32 edge_ctrl_idx;
+ u32 edge_ctrl[TPDM_DSB_MAX_EDCR];
+ u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
bool trig_ts;
bool trig_type;
};
--
2.7.4


2023-07-25 13:37:09

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control

Hi Tao,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.5-rc3 next-20230725]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Tao-Zhang/coresight-tpdm-Remove-the-unnecessary-lock/20230725-152235
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/1690269353-10829-10-git-send-email-quic_taozha%40quicinc.com
patch subject: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control
config: arm-randconfig-r003-20230725 (https://download.01.org/0day-ci/archive/20230725/[email protected]/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230725/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/hwtracing/coresight/coresight-tpdm.c: In function 'dsb_edge_ctrl_val_store':
>> drivers/hwtracing/coresight/coresight-tpdm.c:383:28: warning: variable 'mask' set but not used [-Wunused-but-set-variable]
383 | unsigned long val, mask, edge_ctrl;
| ^~~~
drivers/hwtracing/coresight/coresight-tpdm.c: In function 'dsb_edge_ctrl_mask_store':
>> drivers/hwtracing/coresight/coresight-tpdm.c:449:9: warning: this 'else' clause does not guard... [-Wmisleading-indentation]
449 | else
| ^~~~
drivers/hwtracing/coresight/coresight-tpdm.c:451:17: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'else'
451 | drvdata->dsb->edge_ctrl_mask[reg] = set;
| ^~~~~~~


vim +/mask +383 drivers/hwtracing/coresight/coresight-tpdm.c

368
369 /*
370 * This function is used to control the edge detection according
371 * to the index number that has been set.
372 * "edge_ctrl" should be one of the following values.
373 * 0 - Rising edge detection
374 * 1 - Falling edge detection
375 * 2 - Rising and falling edge detection (toggle detection)
376 */
377 static ssize_t dsb_edge_ctrl_val_store(struct device *dev,
378 struct device_attribute *attr,
379 const char *buf,
380 size_t size)
381 {
382 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> 383 unsigned long val, mask, edge_ctrl;
384 int reg;
385
386 if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
387 return -EINVAL;
388
389 spin_lock(&drvdata->spinlock);
390 /*
391 * There are 2 bit per DSB Edge Control line.
392 * Thus we have 16 lines in a 32bit word.
393 */
394 reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
395 mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
396 val = drvdata->dsb->edge_ctrl[reg];
397 val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
398 val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
399 drvdata->dsb->edge_ctrl[reg] = val;
400 spin_unlock(&drvdata->spinlock);
401
402 return size;
403 }
404 static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
405
406 static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
407 struct device_attribute *attr,
408 char *buf)
409 {
410 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
411 ssize_t size = 0;
412 unsigned long bytes;
413 int i;
414
415 spin_lock(&drvdata->spinlock);
416 for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
417 bytes = sysfs_emit_at(buf, size,
418 "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
419 if (bytes <= 0)
420 break;
421 size += bytes;
422 }
423 spin_unlock(&drvdata->spinlock);
424 return size;
425 }
426
427 static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
428 struct device_attribute *attr,
429 const char *buf,
430 size_t size)
431 {
432 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
433 unsigned long val;
434 u32 set;
435 int reg;
436
437 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
438 return -EINVAL;
439
440 spin_lock(&drvdata->spinlock);
441 /*
442 * There is 1 bit per DSB Edge Control Mark line.
443 * Thus we have 32 lines in a 32bit word.
444 */
445 reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
446 set = drvdata->dsb->edge_ctrl_mask[reg];
447 if (val)
448 set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> 449 else
450 set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
451 drvdata->dsb->edge_ctrl_mask[reg] = set;
452 spin_unlock(&drvdata->spinlock);
453
454 return size;
455 }
456 static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
457

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-07-25 22:37:19

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control

Hi Tao,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.5-rc3 next-20230725]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Tao-Zhang/coresight-tpdm-Remove-the-unnecessary-lock/20230725-152235
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/1690269353-10829-10-git-send-email-quic_taozha%40quicinc.com
patch subject: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control
config: arm-randconfig-r013-20230725 (https://download.01.org/0day-ci/archive/20230726/[email protected]/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce: (https://download.01.org/0day-ci/archive/20230726/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/hwtracing/coresight/coresight-tpdm.c:383:21: warning: variable 'mask' set but not used [-Wunused-but-set-variable]
383 | unsigned long val, mask, edge_ctrl;
| ^
>> drivers/hwtracing/coresight/coresight-tpdm.c:451:3: warning: misleading indentation; statement is not part of the previous 'else' [-Wmisleading-indentation]
451 | drvdata->dsb->edge_ctrl_mask[reg] = set;
| ^
drivers/hwtracing/coresight/coresight-tpdm.c:449:2: note: previous statement is here
449 | else
| ^
2 warnings generated.


vim +/else +451 drivers/hwtracing/coresight/coresight-tpdm.c

426
427 static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
428 struct device_attribute *attr,
429 const char *buf,
430 size_t size)
431 {
432 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
433 unsigned long val;
434 u32 set;
435 int reg;
436
437 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
438 return -EINVAL;
439
440 spin_lock(&drvdata->spinlock);
441 /*
442 * There is 1 bit per DSB Edge Control Mark line.
443 * Thus we have 32 lines in a 32bit word.
444 */
445 reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
446 set = drvdata->dsb->edge_ctrl_mask[reg];
447 if (val)
448 set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
449 else
450 set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> 451 drvdata->dsb->edge_ctrl_mask[reg] = set;
452 spin_unlock(&drvdata->spinlock);
453
454 return size;
455 }
456 static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
457

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-08-04 15:31:02

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 04/13] coresight-tpda: Add DSB dataset support

On 25/07/2023 08:15, Tao Zhang wrote:
> Read the DSB element size from the device tree. Set the register
> bit that controls the DSB element size of the corresponding port.
>
> Signed-off-by: Tao Zhang <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++---
> drivers/hwtracing/coresight/coresight-tpda.h | 4 ++
> 2 files changed, 90 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> index 8d2b9d2..7c71342 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> @@ -21,6 +21,58 @@
>
> DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
>
> +/* Search and read element data size from the TPDM node in

minor nit:

/*
* Search ...

> + * the devicetree. Each input port of TPDA is connected to
> + * a TPDM. Different TPDM supports different types of dataset,
> + * and some may support more than one type of dataset.
> + * Parameter "inport" is used to pass in the input port number
> + * of TPDA, and it is set to 0 in the recursize call.

> + * Parameter "parent" is used to pass in the original call.

Please remove references to the past and describe "match_inport"

> + */
> +static int tpda_set_element_size(struct tpda_drvdata *drvdata,
> + struct coresight_device *csdev, int inport, bool match_inport)

May be we could switch the order of the parameters:

match_inport, int port

Or even inport < 0, implies, port wont be matched.

i.e.,

tpda_set_element_size(drvdata, child, inport)

> +{
> + static int nr_inport;
> + int i;
> + static bool tpdm_found;
> + struct coresight_device *in_csdev;
> +
> + if (inport > (TPDA_MAX_INPORTS - 1))
> + return -EINVAL;
> +
> + if (match_inport) {
> + nr_inport = inport;
> + tpdm_found = false;
> + }

Could we not avoid the static variables and this dance by making the
function return the dsb_size ? See further down.


> +
> + for (i = 0; i < csdev->pdata->nr_inconns; i++) {
> + in_csdev = csdev->pdata->in_conns[i]->src_dev;
> + if (!in_csdev)
> + break;
continue ?
> +
> + if (match_inport)
> + if (csdev->pdata->in_conns[i]->dest_port != inport)
> + continue;
> +
> + if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
> + (in_csdev->subtype.source_subtype
> + == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {

Please provide a helper :

static bool coresight_device_is_tpdm(csdev) {
return
(csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
(in_csdev->subtype.source_subtype ==
CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
}



> + of_property_read_u8(in_csdev->dev.parent->of_node,
> + "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);



> + if (!tpdm_found)
> + tpdm_found = true;
> + else
> + dev_warn(drvdata->dev,
> + "More than one TPDM is mapped to the TPDA input port %d.\n",
> + nr_inport);
> + continue;
> + }
> + tpda_set_element_size(drvdata, in_csdev, 0, false);
> + }
> +

/*
* Read the DSB element size from the TPDM device
* Returns
* the size read from the firmware if available.
* 0 - Otherwise, with a Warning once.
*/
static int tpdm_read_dsb_element_size(struct coresight_device *csdev)
{
int rc, size = 0;

rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent),
"qcom,dsb-element-size", &size);
if (rc)
dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size: %d\n",
rc);
return size;
}

static int tpda_get_element_size(struct coresight_device *csdev,
int inport)
{
int dsb_size = -ENOENT;

for (i = 0; i < csdev->pdata->nr_inconns; i++) {
in = csdev->pdata->in_conns[i]->src_dev;
if (!in)
continue;
if (coresight_device_is_tpdm(in)) {
/* Ignore the TPDMs that do not match port */
if (inport > 0 &&
(csdev->pdata->in_conns[i]->dest_port !=
inport))
continue;
size = tpdm_read_dsb_element_size(csdev);
} else {
/* Recurse down the path */
size = tpda_set_element_size(in, -1);
}

if (size < 0)
return size;
/* We have found a size, save it. */
if (dsb_size < 0) {
dsb_size = size;
} else {
/* We have duplicate TPDMs */
return -EEXIST;
}
}
return dsb_size;
}




> + return 0;
> +}
> +
> /* Settings pre enabling port control register */
> static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
> {
> @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
> writel_relaxed(val, drvdata->base + TPDA_CR);
> }
>
> -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
> +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
> {
> u32 val;
>
> val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
> + /*
> + * Configure aggregator port n DSB data set element size
> + * Set the bit to 0 if the size is 32
> + * Set the bit to 1 if the size is 64
> + */
> + if (drvdata->dsb_esize[port] == 32)
> + val &= ~TPDA_Pn_CR_DSBSIZE;
> + else if (drvdata->dsb_esize[port] == 64)
> + val |= TPDA_Pn_CR_DSBSIZE;

Couldn't this be detected via tpda_get_element_size()? see below.

> + else
> + return -EINVAL;
> +
> /* Enable the port */
> val |= TPDA_Pn_CR_ENA;
> writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
> +
> + return 0;
> }
>
> -static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
> +static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
> {
> + int ret;
> +
> CS_UNLOCK(drvdata->base);
>
> if (!drvdata->csdev->enable)
> tpda_enable_pre_port(drvdata);
>
> - tpda_enable_port(drvdata, port);
> -
> + ret = tpda_enable_port(drvdata, port);
> CS_LOCK(drvdata->base);
> +
> + return ret;
> }
>
> static int tpda_enable(struct coresight_device *csdev,
> @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev,
> struct coresight_connection *out)
> {
> struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> + int ret;
> +
> + ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);

size = tpda_get_element_size(csdev, in->dest_port);
switch (size) {
case 32:
case 64:
break;
case -EEXIST:
dev_warn_once("Detected multiple TPDMs on port %d", ..)
fallthrough;
default:
return size;
}

drvdata->dsb_esize[in->dest_port] = size;

Suzuki



> + if (ret)
> + return ret;
>
> spin_lock(&drvdata->spinlock);
> - if (atomic_read(&in->dest_refcnt) == 0)
> - __tpda_enable(drvdata, in->dest_port);
> + if (atomic_read(&in->dest_refcnt) == 0) {
> + ret = __tpda_enable(drvdata, in->dest_port);
> + if (!ret) {
> + atomic_inc(&in->dest_refcnt);
> + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
> + }
> + }
>
> - atomic_inc(&in->dest_refcnt);
> spin_unlock(&drvdata->spinlock);
> -
> - dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
> - return 0;
> + return ret;
> }
>
> static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h
> index 0399678..12a1472 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.h
> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
> @@ -10,6 +10,8 @@
> #define TPDA_Pn_CR(n) (0x004 + (n * 4))
> /* Aggregator port enable bit */
> #define TPDA_Pn_CR_ENA BIT(0)
> +/* Aggregator port DSB data set element size bit */
> +#define TPDA_Pn_CR_DSBSIZE BIT(8)
>
> #define TPDA_MAX_INPORTS 32
>
> @@ -23,6 +25,7 @@
> * @csdev: component vitals needed by the framework.
> * @spinlock: lock for the drvdata value.
> * @enable: enable status of the component.
> + * @dsb_esize: DSB element size for each inport, it must be 32 or 64.
> */
> struct tpda_drvdata {
> void __iomem *base;
> @@ -30,6 +33,7 @@ struct tpda_drvdata {
> struct coresight_device *csdev;
> spinlock_t spinlock;
> u8 atid;
> + u8 dsb_esize[TPDA_MAX_INPORTS];
> };
>
> #endif /* _CORESIGHT_CORESIGHT_TPDA_H */


2023-08-07 09:54:30

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 04/13] coresight-tpda: Add DSB dataset support

On 04/08/2023 16:02, Suzuki K Poulose wrote:
> On 25/07/2023 08:15, Tao Zhang wrote:
>> Read the DSB element size from the device tree. Set the register
>> bit that controls the DSB element size of the corresponding port.
>>
>> Signed-off-by: Tao Zhang <[email protected]>
>> ---
>>   drivers/hwtracing/coresight/coresight-tpda.c | 96
>> +++++++++++++++++++++++++---
>>   drivers/hwtracing/coresight/coresight-tpda.h |  4 ++
>>   2 files changed, 90 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c
>> b/drivers/hwtracing/coresight/coresight-tpda.c
>> index 8d2b9d2..7c71342 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>> @@ -21,6 +21,58 @@
>>   DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
>> +/* Search and read element data size from the TPDM node in
>
> minor nit:
>
> /*
>  * Search ...
>
>> + * the devicetree. Each input port of TPDA is connected to
>> + * a TPDM. Different TPDM supports different types of dataset,
>> + * and some may support more than one type of dataset.
>> + * Parameter "inport" is used to pass in the input port number
>> + * of TPDA, and it is set to 0 in the recursize call.
>
>> + * Parameter "parent" is used to pass in the original call.
>
> Please remove references to the past and describe "match_inport"
>
>> + */
>> +static int tpda_set_element_size(struct tpda_drvdata *drvdata,
>> +               struct coresight_device *csdev, int inport, bool
>> match_inport)
>
> May be we could switch the order of the parameters:
>
> match_inport, int port
>
> Or even inport < 0, implies, port wont be matched.
>
> i.e.,
>
> tpda_set_element_size(drvdata, child, inport)
>
>> +{
>> +    static int nr_inport;
>> +    int i;
>> +    static bool tpdm_found;
>> +    struct coresight_device *in_csdev;
>> +
>> +    if (inport > (TPDA_MAX_INPORTS - 1))
>> +        return -EINVAL;
>> +
>> +    if (match_inport) {
>> +        nr_inport = inport;
>> +        tpdm_found = false;
>> +    }
>
> Could we not avoid the static variables and this dance by making the
> function return the dsb_size ? See further down.
>
>
>> +
>> +    for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>> +        in_csdev = csdev->pdata->in_conns[i]->src_dev;
>> +        if (!in_csdev)
>> +            break;
>         continue ?
>> +
>> +        if (match_inport)
>> +            if (csdev->pdata->in_conns[i]->dest_port != inport)
>> +                continue;
>> +
>> +        if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>> +                (in_csdev->subtype.source_subtype
>> +                == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
>
> Please provide a helper :
>
> static bool coresight_device_is_tpdm(csdev) {
>     return
>      (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>      (in_csdev->subtype.source_subtype ==
>         CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
> }
>
>
>
>> +            of_property_read_u8(in_csdev->dev.parent->of_node,
>> +                    "qcom,dsb-element-size",
>> &drvdata->dsb_esize[nr_inport]);
>
>
>
>> +            if (!tpdm_found)
>> +                tpdm_found = true;
>> +            else
>> +                dev_warn(drvdata->dev,
>> +                    "More than one TPDM is mapped to the TPDA input
>> port %d.\n",
>> +                    nr_inport);
>> +            continue;
>> +        }
>> +        tpda_set_element_size(drvdata, in_csdev, 0, false);
>> +    }
>> +
>
> /*
>  * Read the DSB element size from the TPDM device
>  * Returns
>  *    the size read from the firmware if available.
>  *    0 - Otherwise, with a Warning once.
>  */
> static int tpdm_read_dsb_element_size(struct coresight_device *csdev)
> {
>     int rc, size = 0;
>
>     rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent),
>                      "qcom,dsb-element-size", &size);
>     if (rc)
>         dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size:
> %d\n",
>         rc);
>     return size;
> }
>
> static int tpda_get_element_size(struct coresight_device *csdev,
>                  int inport)
> {
>     int dsb_size = -ENOENT;
>
>     for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>         in = csdev->pdata->in_conns[i]->src_dev;
>         if (!in)
>             continue;
>         if (coresight_device_is_tpdm(in)) {
>             /* Ignore the TPDMs that do not match port */
>             if (inport > 0 &&
>                 (csdev->pdata->in_conns[i]->dest_port !=
>                 inport))
>                 continue;
>             size = tpdm_read_dsb_element_size(csdev);
>         } else {
>             /* Recurse down the path */
>             size = tpda_set_element_size(in, -1);
>         }
>
>         if (size < 0)
>             return size;
>         /* We have found a size, save it. */
>         if (dsb_size < 0) {
>             dsb_size = size;
>         } else {
>             /* We have duplicate TPDMs */
>             return -EEXIST;
>         }
>     }
>     return dsb_size;
> }
>
>
>
>
>> +    return 0;
>> +}
>> +
>>   /* Settings pre enabling port control register */
>>   static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
>>   {
>> @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct
>> tpda_drvdata *drvdata)
>>       writel_relaxed(val, drvdata->base + TPDA_CR);
>>   }
>> -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>> +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>>   {
>>       u32 val;
>>       val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
>> +    /*
>> +     * Configure aggregator port n DSB data set element size
>> +     * Set the bit to 0 if the size is 32
>> +     * Set the bit to 1 if the size is 64
>> +     */
>> +    if (drvdata->dsb_esize[port] == 32)
>> +        val &= ~TPDA_Pn_CR_DSBSIZE;
>> +    else if (drvdata->dsb_esize[port] == 64)
>> +        val |= TPDA_Pn_CR_DSBSIZE;
>
> Couldn't this be detected via tpda_get_element_size()? see below.
>
>> +    else
>> +        return -EINVAL;
>> +
>>       /* Enable the port */
>>       val |= TPDA_Pn_CR_ENA;
>>       writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
>> +
>> +    return 0;
>>   }
>> -static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
>> +static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
>>   {
>> +    int ret;
>> +
>>       CS_UNLOCK(drvdata->base);
>>       if (!drvdata->csdev->enable)
>>           tpda_enable_pre_port(drvdata);
>> -    tpda_enable_port(drvdata, port);
>> -
>> +    ret = tpda_enable_port(drvdata, port);
>>       CS_LOCK(drvdata->base);
>> +
>> +    return ret;
>>   }
>>   static int tpda_enable(struct coresight_device *csdev,
>> @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device
>> *csdev,
>>                  struct coresight_connection *out)
>>   {
>>       struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +    int ret;
>> +
>> +    ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
>
>     size  = tpda_get_element_size(csdev, in->dest_port);
>     switch (size) {
>     case 32:
>     case 64:
>         break;

We also need :

case 0:
return -ENOENT;

Suzuki


>     case -EEXIST:
>         dev_warn_once("Detected multiple TPDMs on port %d", ..)
>         fallthrough;
>     default:
>         return size;
>     }
>
>     drvdata->dsb_esize[in->dest_port] = size;
>
> Suzuki
>
>
>
>> +    if (ret)
>> +        return ret;
>>       spin_lock(&drvdata->spinlock);
>> -    if (atomic_read(&in->dest_refcnt) == 0)
>> -        __tpda_enable(drvdata, in->dest_port);
>> +    if (atomic_read(&in->dest_refcnt) == 0) {
>> +        ret = __tpda_enable(drvdata, in->dest_port);
>> +        if (!ret) {
>> +            atomic_inc(&in->dest_refcnt);
>> +            dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n",
>> in->dest_port);
>> +        }
>> +    }
>> -    atomic_inc(&in->dest_refcnt);
>>       spin_unlock(&drvdata->spinlock);
>> -
>> -    dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
>> -    return 0;
>> +    return ret;
>>   }
>>   static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h
>> b/drivers/hwtracing/coresight/coresight-tpda.h
>> index 0399678..12a1472 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpda.h
>> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
>> @@ -10,6 +10,8 @@
>>   #define TPDA_Pn_CR(n)        (0x004 + (n * 4))
>>   /* Aggregator port enable bit */
>>   #define TPDA_Pn_CR_ENA        BIT(0)
>> +/* Aggregator port DSB data set element size bit */
>> +#define TPDA_Pn_CR_DSBSIZE        BIT(8)
>>   #define TPDA_MAX_INPORTS    32
>> @@ -23,6 +25,7 @@
>>    * @csdev:      component vitals needed by the framework.
>>    * @spinlock:   lock for the drvdata value.
>>    * @enable:     enable status of the component.
>> + * @dsb_esize:  DSB element size for each inport, it must be 32 or 64.
>>    */
>>   struct tpda_drvdata {
>>       void __iomem        *base;
>> @@ -30,6 +33,7 @@ struct tpda_drvdata {
>>       struct coresight_device    *csdev;
>>       spinlock_t        spinlock;
>>       u8            atid;
>> +    u8            dsb_esize[TPDA_MAX_INPORTS];
>>   };
>>   #endif  /* _CORESIGHT_CORESIGHT_TPDA_H */
>


2023-08-07 10:24:39

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control

On 25/07/2023 08:15, Tao Zhang wrote:
> Add the nodes to set value for DSB edge control and DSB edge
> control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR
> resgisters to configure edge control. DSB edge detection control
> 00: Rising edge detection
> 01: Falling edge detection
> 10: Rising and falling edge detection (toggle detection)
> And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to
> configure mask. Eight 32 bit registers providing DSB interface
> edge detection mask control.
>
> Add the nodes to configure DSB edge control and DSB edge control
> mask. Each DSB subunit TPDM maximum of 256 edge detections can be
> configured. The index and value sysfs files need to be paired and
> written to order. The index sysfs file is to set the index number
> of the edge detection which needs to be configured. And the value
> sysfs file is to set the control or mask for the edge detection.
> DSB edge detection control should be set as the following values.
> 00: Rising edge detection
> 01: Falling edge detection
> 10: Rising and falling edge detection (toggle detection)
> And DSB edge mask should be set as 0 or 1.
> Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to
> configure edge control. And each DSB subunit TPDM has maximum of
> m(m<8) ECDMR registers to configure mask.
>
> Signed-off-by: Tao Zhang <[email protected]>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++
> drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++-
> drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++-
> 3 files changed, 223 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> index 2a82cd0..a4550c5 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> @@ -60,3 +60,42 @@ Description:
> 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.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read/Write the index number of the edge detection for the DSB
> + subunit TPDM. Since there are at most 256 edge detections, this
> + value ranges from 0 to 255.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the edge control registers of the DSB in TPDM.
> + Write a data to control the edge detection corresponding to
> + the index number. Before writing data to this sysfs file,
> + "dsb_edge_ctrl_idx" should be written first to configure the
> + index number of the edge detection which needs to be controlled.
> +
> + Accepts only one of the following values.
> + 0 - Rising edge detection
> + 1 - Falling edge detection
> + 2 - Rising and falling edge detection (toggle detection)
> +
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the edge control mask registers of the DSB in TPDM.
> + Write a data to mask the edge detection corresponding to the index
> + number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx"
> + should be written first to configure the index number of the edge
> + detection which needs to be masked.
> +
> + Accepts only one of the 2 values - 0 or 1.
> \ No newline at end of file
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
> index c38760b..98fd6ab 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
> @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
>
> static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> {
> - u32 val;
> + u32 val, i;
> +
> + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
> + writel_relaxed(drvdata->dsb->edge_ctrl[i],
> + drvdata->base + TPDM_DSB_EDCR(i));
> + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
> + writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
> + drvdata->base + TPDM_DSB_EDCMR(i));
>
> val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
> /* Set trigger timestamp */
> @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev,
> }
> static DEVICE_ATTR_RW(dsb_mode);
>
> +static ssize_t dsb_edge_ctrl_idx_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->edge_ctrl_idx);
> +}
> +
> +/*
> + * The EDCR registers can include up to 16 32-bit registers, and each
> + * one can be configured to control up to 16 edge detections(2 bits
> + * control one edge detection). So a total 256 edge detections can be
> + * configured. This function provides a way to set the index number of
> + * the edge detection which needs to be configured.
> + */
> +static ssize_t dsb_edge_ctrl_idx_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 >= TPDM_DSB_MAX_LINES))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->edge_ctrl_idx = val;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
> +
> +static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + ssize_t size = 0;
> + unsigned long bytes;
> + int i;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +/*
> + * This function is used to control the edge detection according
> + * to the index number that has been set.
> + * "edge_ctrl" should be one of the following values.
> + * 0 - Rising edge detection
> + * 1 - Falling edge detection
> + * 2 - Rising and falling edge detection (toggle detection)
> + */
> +static ssize_t dsb_edge_ctrl_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 val, mask, edge_ctrl;
> + int reg;
> +
> + if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + /*
> + * There are 2 bit per DSB Edge Control line.
> + * Thus we have 16 lines in a 32bit word.
> + */
> + reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
> + mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
> + val = drvdata->dsb->edge_ctrl[reg];
> + val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
> + val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
> + drvdata->dsb->edge_ctrl[reg] = val;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
> +
> +static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + ssize_t size = 0;
> + unsigned long bytes;
> + int i;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +static ssize_t dsb_edge_ctrl_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 val;
> + u32 set;
> + int reg;
> +
> + if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + /*
> + * There is 1 bit per DSB Edge Control Mark line.
> + * Thus we have 32 lines in a 32bit word.
> + */
> + reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
> + set = drvdata->dsb->edge_ctrl_mask[reg];
> + if (val)
> + set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> + else
> + set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> + drvdata->dsb->edge_ctrl_mask[reg] = set;


drivers/hwtracing/coresight/coresight-tpdm.c: In function
‘dsb_edge_ctrl_mask_store’:
drivers/hwtracing/coresight/coresight-tpdm.c:449:2: error: this ‘else’
clause does not guard... [-Werror=misleading-indentation]
else
^~~~
drivers/hwtracing/coresight/coresight-tpdm.c:451:3: note: ...this
statement, but the latter is misleadingly indented as if it were guarded
by the ‘else’
drvdata->dsb->edge_ctrl_mask[reg] = set;
^~~~~~~
cc1: all warnings being treated as errors
make[4]: *** [scripts/Makefile.build:243:
drivers/hwtracing/coresight/coresight-tpdm.o] Error 1
make[3]: *** [scripts/Makefile.build:480: drivers/hwtracing/coresight]
Error 2
make[2]: *** [scripts/Makefile.build:480: drivers] Error 2
make[1]: *** [/ssd/src/LINUX-CORESIGHT/Makefile:2032: .] Error 2
make: *** [Makefile:234: __sub-make] Error 2

Suzuki

2023-08-07 11:05:18

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control

On 25/07/2023 08:15, Tao Zhang wrote:
> Add the nodes to set value for DSB edge control and DSB edge
> control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR
> resgisters to configure edge control. DSB edge detection control
> 00: Rising edge detection
> 01: Falling edge detection
> 10: Rising and falling edge detection (toggle detection)
> And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to
> configure mask. Eight 32 bit registers providing DSB interface
> edge detection mask control.
>
> Add the nodes to configure DSB edge control and DSB edge control
> mask. Each DSB subunit TPDM maximum of 256 edge detections can be
> configured. The index and value sysfs files need to be paired and
> written to order. The index sysfs file is to set the index number
> of the edge detection which needs to be configured. And the value
> sysfs file is to set the control or mask for the edge detection.
> DSB edge detection control should be set as the following values.
> 00: Rising edge detection
> 01: Falling edge detection
> 10: Rising and falling edge detection (toggle detection)
> And DSB edge mask should be set as 0 or 1.
> Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to
> configure edge control. And each DSB subunit TPDM has maximum of
> m(m<8) ECDMR registers to configure mask.
>
> Signed-off-by: Tao Zhang <[email protected]>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++
> drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++-
> drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++-
> 3 files changed, 223 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> index 2a82cd0..a4550c5 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> @@ -60,3 +60,42 @@ Description:
> 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.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read/Write the index number of the edge detection for the DSB
> + subunit TPDM. Since there are at most 256 edge detections, this
> + value ranges from 0 to 255.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the edge control registers of the DSB in TPDM.
> + Write a data to control the edge detection corresponding to
> + the index number. Before writing data to this sysfs file,
> + "dsb_edge_ctrl_idx" should be written first to configure the
> + index number of the edge detection which needs to be controlled.
> +
> + Accepts only one of the following values.
> + 0 - Rising edge detection
> + 1 - Falling edge detection
> + 2 - Rising and falling edge detection (toggle detection)
> +
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the edge control mask registers of the DSB in TPDM.
> + Write a data to mask the edge detection corresponding to the index
> + number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx"
> + should be written first to configure the index number of the edge
> + detection which needs to be masked.
> +
> + Accepts only one of the 2 values - 0 or 1.
> \ No newline at end of file
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
> index c38760b..98fd6ab 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
> @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
>
> static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> {
> - u32 val;
> + u32 val, i;
> +
> + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
> + writel_relaxed(drvdata->dsb->edge_ctrl[i],
> + drvdata->base + TPDM_DSB_EDCR(i));
> + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
> + writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
> + drvdata->base + TPDM_DSB_EDCMR(i));
>
> val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
> /* Set trigger timestamp */
> @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev,
> }
> static DEVICE_ATTR_RW(dsb_mode);
>
> +static ssize_t dsb_edge_ctrl_idx_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->edge_ctrl_idx);
> +}
> +
> +/*
> + * The EDCR registers can include up to 16 32-bit registers, and each
> + * one can be configured to control up to 16 edge detections(2 bits
> + * control one edge detection). So a total 256 edge detections can be
> + * configured. This function provides a way to set the index number of
> + * the edge detection which needs to be configured.
> + */
> +static ssize_t dsb_edge_ctrl_idx_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 >= TPDM_DSB_MAX_LINES))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->edge_ctrl_idx = val;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
> +
> +static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + ssize_t size = 0;
> + unsigned long bytes;
> + int i;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);

This feels a bit odd. edget_ctrl_val allows storing one "edge ctrl"
value, while "show"ing all EDCR values. We could split them to :

Read only sysfs files:

dsb_edcr0 ... dsb_edcr15

for each EDCR register (similarly for the mask)

and may be show the specific edge_ctrl_line for with the above function
for selected index.

> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +/*
> + * This function is used to control the edge detection according
> + * to the index number that has been set.
> + * "edge_ctrl" should be one of the following values.
> + * 0 - Rising edge detection
> + * 1 - Falling edge detection
> + * 2 - Rising and falling edge detection (toggle detection)
> + */
> +static ssize_t dsb_edge_ctrl_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 val, mask, edge_ctrl;
> + int reg;
> +
> + if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + /*
> + * There are 2 bit per DSB Edge Control line.
> + * Thus we have 16 lines in a 32bit word.
> + */
> + reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
> + mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
> + val = drvdata->dsb->edge_ctrl[reg];
> + val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
> + val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
> + drvdata->dsb->edge_ctrl[reg] = val;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);

This can be WO attribute to write to a given line.

> +
> +static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + ssize_t size = 0;
> + unsigned long bytes;
> + int i;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);

As mentioned above, please don't do this. One value per file. Add

dsb_edcmr0..dsb_edcmr7

and print only the selected index mask for this function.

> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +static ssize_t dsb_edge_ctrl_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 val;
> + u32 set;
> + int reg;
> +
> + if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + /*
> + * There is 1 bit per DSB Edge Control Mark line.
> + * Thus we have 32 lines in a 32bit word.
> + */
> + reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
> + set = drvdata->dsb->edge_ctrl_mask[reg];
> + if (val)
> + set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> + else
> + set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
> + drvdata->dsb->edge_ctrl_mask[reg] = set;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
> +
> static ssize_t dsb_trig_type_show(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> @@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts);
>
> static struct attribute *tpdm_dsb_attrs[] = {
> &dev_attr_dsb_mode.attr,
> + &dev_attr_dsb_edge_ctrl_idx.attr,
> + &dev_attr_dsb_edge_ctrl_val.attr,
> + &dev_attr_dsb_edge_ctrl_mask.attr,
> &dev_attr_dsb_trig_ts.attr,
> &dev_attr_dsb_trig_type.attr,
> NULL,
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
> index 49fffb1..4afdb29 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.h
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.h
> @@ -12,6 +12,8 @@
> /* DSB Subunit Registers */
> #define TPDM_DSB_CR (0x780)
> #define TPDM_DSB_TIER (0x784)
> +#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
> +#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
>
> /* Enable bit for DSB subunit */
> #define TPDM_DSB_CR_ENA BIT(0)
> @@ -34,6 +36,16 @@
> #define TPDM_DSB_TEST_MODE GENMASK(10, 9)
> #define TPDM_DSB_HPSEL GENMASK(6, 2)
>
> +#define EDCRS_PER_WORD 16
> +#define EDCR_TO_WORD_IDX(r) ((r) / EDCRS_PER_WORD)
> +#define EDCR_TO_WORD_SHIFT(r) ((r % EDCRS_PER_WORD) * 2)
> +#define EDCR_TO_WORD_VAL(val, r) (val << EDCR_TO_WORD_SHIFT(r))
> +#define EDCR_TO_WORD_MASK(r) EDCR_TO_WORD_VAL(0x3, r)
> +
> +#define EDCMRS_PER_WORD 32
> +#define EDCMR_TO_WORD_IDX(r) ((r) / EDCMRS_PER_WORD)
> +#define EDCMR_TO_WORD_SHIFT(r) ((r) % EDCMRS_PER_WORD)
> +
> /* TPDM integration test registers */
> #define TPDM_ITATBCNTRL (0xEF0)
> #define TPDM_ITCNTRL (0xF00)
> @@ -60,14 +72,26 @@
> #define TPDM_PIDR0_DS_IMPDEF BIT(0)
> #define TPDM_PIDR0_DS_DSB BIT(1)
>
> +#define TPDM_DSB_MAX_LINES 256
> +/* MAX number of EDCR registers */
> +#define TPDM_DSB_MAX_EDCR 16
> +/* MAX number of EDCMR registers */
> +#define TPDM_DSB_MAX_EDCMR 8
> +
> /**
> * struct dsb_dataset - specifics associated to dsb dataset
> - * @mode: DSB programming mode
> - * @trig_ts: Enable/Disable trigger timestamp.
> - * @trig_type: Enable/Disable trigger type.
> + * @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
> + * @trig_ts: Enable/Disable trigger timestamp.
> + * @trig_type: Enable/Disable trigger type.
> */
> struct dsb_dataset {
> u32 mode;
> + u32 edge_ctrl_idx;
> + u32 edge_ctrl[TPDM_DSB_MAX_EDCR];
> + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];

Please keep them aligned with the rest of the fields.

> bool trig_ts;
> bool trig_type;

Suzuki


> };


2023-08-07 12:19:54

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 10/13] coresight-tpdm: Add nodes to configure pattern match output

On 25/07/2023 08:15, Tao Zhang wrote:
> Add nodes to configure trigger pattern and trigger pattern mask.
> Each DSB subunit TPDM has maximum of n(n<7) XPR registers to
> configure trigger pattern match output. Eight 32 bit registers
> providing DSB interface trigger output pattern match comparison.
> And each DSB subunit TPDM has maximum of m(m<7) XPMR registers to
> configure trigger pattern mask match output. Eight 32 bit
> registers providing DSB interface trigger output pattern match
> mask.
>
> Signed-off-by: Tao Zhang <[email protected]>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 34 +++++-
> drivers/hwtracing/coresight/coresight-tpdm.c | 118 +++++++++++++++++++++
> drivers/hwtracing/coresight/coresight-tpdm.h | 10 ++
> 3 files changed, 161 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> index a4550c5..66f9582 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> @@ -98,4 +98,36 @@ Description:
> should be written first to configure the index number of the edge
> detection which needs to be masked.
>
> - Accepts only one of the 2 values - 0 or 1.
> \ No newline at end of file
> + Accepts only one of the 2 values - 0 or 1.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_idx
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read/Write the index number of the trigger pattern value of DSB
> + tpdm. Since there are at most 8 XPR and XPMR registers for the
> + trigger parttern, this value ranges from 0 to 7.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the trigger pattern values of the DSB TPDM.
> + Write a data to configure the trigger pattern corresponding to
> + the index number. Before writing data to this sysfs file,
> + "dsb_trig_patt_idx" should be written first to configure the
> + index number of the trigger pattern which needs to be configured.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the trigger pattern mask of the DSB TPDM.
> + Write a data to configure the trigger pattern mask corresponding
> + to the index number. Before writing data to this sysfs file,
> + "dsb_trig_patt_idx" should be written first to configure the
> + index number of the trigger pattern mask which needs to be
> + configured.
> \ No newline at end of file
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
> index 98fd6ab..1c32d27 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
> @@ -80,6 +80,13 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> 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->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)
> @@ -455,6 +462,114 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
> }
> static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
>
> +static ssize_t dsb_trig_patt_idx_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->trig_patt_idx);
> +}
> +
> +static ssize_t dsb_trig_patt_idx_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;
> +
> + if (kstrtoul(buf, 0, &index))
> + return -EINVAL;
> + if (index >= TPDM_DSB_MAX_PATT)
> + return -EPERM;
> +
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->trig_patt_idx = index;
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_trig_patt_idx);
> +
> +static ssize_t dsb_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;
> + unsigned long bytes;
> + int i = 0;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Value: 0x%x\n", drvdata->dsb->trig_patt[i]);
> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +static ssize_t dsb_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 val;
> +
> + if (kstrtoul(buf, 0, &val))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->trig_patt[drvdata->dsb->trig_patt_idx] = val;
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +static DEVICE_ATTR_RW(dsb_trig_patt_val);
> +
> +static ssize_t dsb_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;
> + unsigned long bytes;
> + int i = 0;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Value: 0x%x\n", drvdata->dsb->trig_patt_mask[i]);

As mentioned above, please stick to single value. In this case, we could
simply expose :

dsb_trig_patt_mask0..7 as RW and directly let the user set/get the
values and get rid of the idx.

You may be able to use an device_ext_attribute to store the index and
use a single function to support all registers.

Suzuki


2023-08-07 12:27:53

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v7 11/13] coresight-tpdm: Add nodes for timestamp request

On 25/07/2023 08:15, Tao Zhang wrote:
> Add nodes to configure the timestamp request based on input
> pattern match. Each TPDM that support DSB subunit has maximum of
> n(n<7) TPR registers to configure value for timestamp request
> based on input pattern match. Eight 32 bit registers providing
> DSB interface timestamp request pattern match comparison. And
> each TPDM that support DSB subunit has maximum of m(m<7) TPMR
> registers to configure pattern mask for timestamp request. Eight
> 32 bit registers providing DSB interface timestamp request
> pattern match mask generation. Add nodes to enable/disable
> pattern timestamp and set pattern timestamp type.
>
> Signed-off-by: Tao Zhang <[email protected]>
> ---
> .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 57 +++++-
> drivers/hwtracing/coresight/coresight-tpdm.c | 205 ++++++++++++++++++++-
> drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++
> 3 files changed, 272 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> index 66f9582..74a0126 100644
> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
> @@ -130,4 +130,59 @@ Description:
> to the index number. Before writing data to this sysfs file,
> "dsb_trig_patt_idx" should be written first to configure the
> index number of the trigger pattern mask which needs to be
> - configured.
> \ No newline at end of file
> + configured.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_idx
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read/Write the index number of the DSB tpdm pattern. Since
> + there are at most 8 TPR and TPMR registers for the parttern,
> + this value ranges from 0 to 7.

If it is only 0-7 and we read/write full registers, why not expose
individual registers as mentioned in the previous comments and avoid
multi-line output for "show" routines. You may even group the registers
under a directory structure to avoid confusion.

e.g, :

dsb_patt/
\- mask0 ... mask7
\- ts0 ... ts7
\- type0 ... type7

dsb_edge/
\- edcr0 ... edcr15
\- edcmr0 ... edcmr7
\- ctrl_idx
\- ctrl_idx_val
....



> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the pattern values of the DSB TPDM. Write a data
> + to configure the pattern corresponding to the index number.
> + Before writing data to this sysfs file, "dsb_patt_idx" should be
> + written first to configure the index number of the pattern which
> + needs to be configured.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +Description:
> + Read a set of the pattern mask values of the DSB TPDM. Write a
> + data to configure the pattern mask corresponding to the index
> + number. Before writing data to this sysfs file, "dsb_patt_idx"
> + should be written first to configure the index number of the
> + pattern mask which needs to be configured.
> +
> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +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_type
> +Date: March 2023
> +KernelVersion 6.5
> +Contact: Jinlong Mao (QUIC) <[email protected]>, Tao Zhang (QUIC) <[email protected]>
> +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.
> \ No newline at end of file
> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
> index 1c32d27..f9e5a1d 100644
> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
> @@ -69,6 +69,27 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
> *val &= ~TPDM_DSB_CR_MODE;
> }
>
> +static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val)
> +{
> + /* 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;
> +
> +}
> +
> static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> {
> u32 val, i;
> @@ -81,6 +102,10 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> 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],
> @@ -88,11 +113,7 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
> }
>
> 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;
> + set_dsb_tier(drvdata, &val);
> writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
>
> val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
> @@ -462,6 +483,175 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
> }
> static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
>
> +static ssize_t dsb_patt_idx_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_idx);
> +
> +}
> +
> +static ssize_t dsb_patt_idx_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;
> +
> + if ((kstrtoul(buf, 0, &index)) || (index >= TPDM_DSB_MAX_PATT))
> + return -EINVAL;
> +
> + spin_lock(&drvdata->spinlock);
> + drvdata->dsb->patt_idx = index;
> + spin_unlock(&drvdata->spinlock);
> +
> + return size;
> +
> +}
> +static DEVICE_ATTR_RW(dsb_patt_idx);
> +
> +static ssize_t dsb_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;
> + unsigned long bytes;
> + int i = 0;
> +
> + spin_lock(&drvdata->spinlock);
> + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
> + bytes = sysfs_emit_at(buf, size,
> + "Value: 0x%x\n", drvdata->dsb->patt_val[i]);

Please see my comment on the other patches.

> + if (bytes <= 0)
> + break;
> + size += bytes;
> + }
> + spin_unlock(&drvdata->spinlock);
> + return size;
> +}
> +
> +static ssize_t dsb_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 val;
> +
> + if (kstrtoul(buf, 0, &val))

You have used the base for all such conversions inconsistently,
throughout the series. You can always stick to 0.

$ git grep kstrtoul drivers/hwtracing/coresight/coresight-tpdm.c
drivers/hwtracing/coresight/coresight-tpdm.c: ret = kstrtoul(buf, 10,
&val);
drivers/hwtracing/coresight/coresight-tpdm.c: ret = kstrtoul(buf, 10,
&val);
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&val)) || val < 0)
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&val)) || (val >= TPDM_DSB_MAX_LINES))
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&edge_ctrl)) || (edge_ctrl > 0x2))
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&val)) || (val & ~1UL))
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&val)) || (val & ~1UL))
drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0,
&val)) || (val & ~1UL))



Suzuki



2023-08-09 06:56:56

by Tao Zhang

[permalink] [raw]
Subject: Re: [PATCH v7 04/13] coresight-tpda: Add DSB dataset support

Hi Suzuki,

On 8/4/2023 11:02 PM, Suzuki K Poulose wrote:
> On 25/07/2023 08:15, Tao Zhang wrote:
>> Read the DSB element size from the device tree. Set the register
>> bit that controls the DSB element size of the corresponding port.
>>
>> Signed-off-by: Tao Zhang <[email protected]>
>> ---
>>   drivers/hwtracing/coresight/coresight-tpda.c | 96
>> +++++++++++++++++++++++++---
>>   drivers/hwtracing/coresight/coresight-tpda.h |  4 ++
>>   2 files changed, 90 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c
>> b/drivers/hwtracing/coresight/coresight-tpda.c
>> index 8d2b9d2..7c71342 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>> @@ -21,6 +21,58 @@
>>     DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
>>   +/* Search and read element data size from the TPDM node in
>
> minor nit:
>
> /*
>  * Search ...
I will update this in the next patch series.
>
>> + * the devicetree. Each input port of TPDA is connected to
>> + * a TPDM. Different TPDM supports different types of dataset,
>> + * and some may support more than one type of dataset.
>> + * Parameter "inport" is used to pass in the input port number
>> + * of TPDA, and it is set to 0 in the recursize call.
>
>> + * Parameter "parent" is used to pass in the original call.
>
> Please remove references to the past and describe "match_inport"
I will update this in the next patch series.
>
>> + */
>> +static int tpda_set_element_size(struct tpda_drvdata *drvdata,
>> +               struct coresight_device *csdev, int inport, bool
>> match_inport)
>
> May be we could switch the order of the parameters:
>
> match_inport, int port
>
> Or even inport < 0, implies, port wont be matched.
>
> i.e.,
>
> tpda_set_element_size(drvdata, child, inport)
I will update this in the next patch series.
>
>> +{
>> +    static int nr_inport;
>> +    int i;
>> +    static bool tpdm_found;
>> +    struct coresight_device *in_csdev;
>> +
>> +    if (inport > (TPDA_MAX_INPORTS - 1))
>> +        return -EINVAL;
>> +
>> +    if (match_inport) {
>> +        nr_inport = inport;
>> +        tpdm_found = false;
>> +    }
>
> Could we not avoid the static variables and this dance by making the
> function return the dsb_size ? See further down.
>
I will update this in the next patch series.
>
>> +
>> +    for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>> +        in_csdev = csdev->pdata->in_conns[i]->src_dev;
>> +        if (!in_csdev)
>> +            break;
>         continue ?
I will update this in the next patch series.
>> +
>> +        if (match_inport)
>> +            if (csdev->pdata->in_conns[i]->dest_port != inport)
>> +                continue;
>> +
>> +        if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>> +                (in_csdev->subtype.source_subtype
>> +                == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
>
> Please provide a helper :
>
> static bool coresight_device_is_tpdm(csdev) {
>     return
>      (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>      (in_csdev->subtype.source_subtype ==
>         CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
> }
>
I will update this in the next patch series.
>
>
>> + of_property_read_u8(in_csdev->dev.parent->of_node,
>> +                    "qcom,dsb-element-size",
>> &drvdata->dsb_esize[nr_inport]);
>
>
>
>> +            if (!tpdm_found)
>> +                tpdm_found = true;
>> +            else
>> +                dev_warn(drvdata->dev,
>> +                    "More than one TPDM is mapped to the TPDA input
>> port %d.\n",
>> +                    nr_inport);
>> +            continue;
>> +        }
>> +        tpda_set_element_size(drvdata, in_csdev, 0, false);
>> +    }
>> +
>
> /*
>  * Read the DSB element size from the TPDM device
>  * Returns
>  *    the size read from the firmware if available.
>  *    0 - Otherwise, with a Warning once.
>  */
> static int tpdm_read_dsb_element_size(struct coresight_device *csdev)
> {
>     int rc, size = 0;
>
>     rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent),
>                      "qcom,dsb-element-size", &size);
>     if (rc)
>         dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size:
> %d\n",
>         rc);
>     return size;
> }
>
> static int tpda_get_element_size(struct coresight_device *csdev,
>                  int inport)
> {
>     int dsb_size = -ENOENT;
>
>     for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>         in = csdev->pdata->in_conns[i]->src_dev;
>         if (!in)
>             continue;
>         if (coresight_device_is_tpdm(in)) {
>             /* Ignore the TPDMs that do not match port */
>             if (inport > 0 &&
>                 (csdev->pdata->in_conns[i]->dest_port !=
>                 inport))
>                 continue;
>             size = tpdm_read_dsb_element_size(csdev);
>         } else {
>             /* Recurse down the path */
>             size = tpda_set_element_size(in, -1);
>         }
>
>         if (size < 0)
>             return size;
>         /* We have found a size, save it. */
>         if (dsb_size < 0) {
>             dsb_size = size;
>         } else {
>             /* We have duplicate TPDMs */
>             return -EEXIST;
>         }
>     }
>     return dsb_size;
> }
>
I will update this in the next patch series.
>
>
>
>> +    return 0;
>> +}
>> +
>>   /* Settings pre enabling port control register */
>>   static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
>>   {
>> @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct
>> tpda_drvdata *drvdata)
>>       writel_relaxed(val, drvdata->base + TPDA_CR);
>>   }
>>   -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>> +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>>   {
>>       u32 val;
>>         val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
>> +    /*
>> +     * Configure aggregator port n DSB data set element size
>> +     * Set the bit to 0 if the size is 32
>> +     * Set the bit to 1 if the size is 64
>> +     */
>> +    if (drvdata->dsb_esize[port] == 32)
>> +        val &= ~TPDA_Pn_CR_DSBSIZE;
>> +    else if (drvdata->dsb_esize[port] == 64)
>> +        val |= TPDA_Pn_CR_DSBSIZE;
>
> Couldn't this be detected via tpda_get_element_size()? see below.
I will update this in the next patch series.
>
>> +    else
>> +        return -EINVAL;
>> +
>>       /* Enable the port */
>>       val |= TPDA_Pn_CR_ENA;
>>       writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
>> +
>> +    return 0;
>>   }
>>   -static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
>> +static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
>>   {
>> +    int ret;
>> +
>>       CS_UNLOCK(drvdata->base);
>>         if (!drvdata->csdev->enable)
>>           tpda_enable_pre_port(drvdata);
>>   -    tpda_enable_port(drvdata, port);
>> -
>> +    ret = tpda_enable_port(drvdata, port);
>>       CS_LOCK(drvdata->base);
>> +
>> +    return ret;
>>   }
>>     static int tpda_enable(struct coresight_device *csdev,
>> @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device
>> *csdev,
>>                  struct coresight_connection *out)
>>   {
>>       struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +    int ret;
>> +
>> +    ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
>
>     size  = tpda_get_element_size(csdev, in->dest_port);
>     switch (size) {
>     case 32:
>     case 64:
>         break;
>     case -EEXIST:
>         dev_warn_once("Detected multiple TPDMs on port %d", ..)
>         fallthrough;
>     default:
>         return size;
>     }
>
>     drvdata->dsb_esize[in->dest_port] = size;

I will update this in the next patch series.


Best,

Tao

>
> Suzuki
>
>
>
>> +    if (ret)
>> +        return ret;
>>         spin_lock(&drvdata->spinlock);
>> -    if (atomic_read(&in->dest_refcnt) == 0)
>> -        __tpda_enable(drvdata, in->dest_port);
>> +    if (atomic_read(&in->dest_refcnt) == 0) {
>> +        ret = __tpda_enable(drvdata, in->dest_port);
>> +        if (!ret) {
>> +            atomic_inc(&in->dest_refcnt);
>> +            dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n",
>> in->dest_port);
>> +        }
>> +    }
>>   -    atomic_inc(&in->dest_refcnt);
>>       spin_unlock(&drvdata->spinlock);
>> -
>> -    dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
>> -    return 0;
>> +    return ret;
>>   }
>>     static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h
>> b/drivers/hwtracing/coresight/coresight-tpda.h
>> index 0399678..12a1472 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpda.h
>> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
>> @@ -10,6 +10,8 @@
>>   #define TPDA_Pn_CR(n)        (0x004 + (n * 4))
>>   /* Aggregator port enable bit */
>>   #define TPDA_Pn_CR_ENA        BIT(0)
>> +/* Aggregator port DSB data set element size bit */
>> +#define TPDA_Pn_CR_DSBSIZE        BIT(8)
>>     #define TPDA_MAX_INPORTS    32
>>   @@ -23,6 +25,7 @@
>>    * @csdev:      component vitals needed by the framework.
>>    * @spinlock:   lock for the drvdata value.
>>    * @enable:     enable status of the component.
>> + * @dsb_esize:  DSB element size for each inport, it must be 32 or 64.
>>    */
>>   struct tpda_drvdata {
>>       void __iomem        *base;
>> @@ -30,6 +33,7 @@ struct tpda_drvdata {
>>       struct coresight_device    *csdev;
>>       spinlock_t        spinlock;
>>       u8            atid;
>> +    u8            dsb_esize[TPDA_MAX_INPORTS];
>>   };
>>     #endif  /* _CORESIGHT_CORESIGHT_TPDA_H */
>

2023-08-09 07:11:35

by Tao Zhang

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control


On 8/7/2023 6:58 PM, Suzuki K Poulose wrote:
> On 25/07/2023 08:15, Tao Zhang wrote:
>> Add the nodes to set value for DSB edge control and DSB edge
>> control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR
>> resgisters to configure edge control. DSB edge detection control
>> 00: Rising edge detection
>> 01: Falling edge detection
>> 10: Rising and falling edge detection (toggle detection)
>> And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to
>> configure mask. Eight 32 bit registers providing DSB interface
>> edge detection mask control.
>>
>> Add the nodes to configure DSB edge control and DSB edge control
>> mask. Each DSB subunit TPDM maximum of 256 edge detections can be
>> configured. The index and value sysfs files need to be paired and
>> written to order. The index sysfs file is to set the index number
>> of the edge detection which needs to be configured. And the value
>> sysfs file is to set the control or mask for the edge detection.
>> DSB edge detection control should be set as the following values.
>> 00: Rising edge detection
>> 01: Falling edge detection
>> 10: Rising and falling edge detection (toggle detection)
>> And DSB edge mask should be set as 0 or 1.
>> Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to
>> configure edge control. And each DSB subunit TPDM has maximum of
>> m(m<8) ECDMR registers to configure mask.
>>
>> Signed-off-by: Tao Zhang <[email protected]>
>> ---
>>   .../ABI/testing/sysfs-bus-coresight-devices-tpdm   |  39 +++++
>>   drivers/hwtracing/coresight/coresight-tpdm.c       | 158
>> ++++++++++++++++++++-
>>   drivers/hwtracing/coresight/coresight-tpdm.h       |  30 +++-
>>   3 files changed, 223 insertions(+), 4 deletions(-)
>>
>> diff --git
>> a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> index 2a82cd0..a4550c5 100644
>> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> @@ -60,3 +60,42 @@ Description:
>>           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.
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read/Write the index number of the edge detection for the DSB
>> +        subunit TPDM. Since there are at most 256 edge detections, this
>> +        value ranges from 0 to 255.
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read a set of the edge control registers of the DSB in TPDM.
>> +        Write a data to control the edge detection corresponding to
>> +        the index number. Before writing data to this sysfs file,
>> +        "dsb_edge_ctrl_idx" should be written first to configure the
>> +        index number of the edge detection which needs to be
>> controlled.
>> +
>> +        Accepts only one of the following values.
>> +        0 - Rising edge detection
>> +        1 - Falling edge detection
>> +        2 - Rising and falling edge detection (toggle detection)
>> +
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read a set of the edge control mask registers of the DSB in
>> TPDM.
>> +        Write a data to mask the edge detection corresponding to the
>> index
>> +        number. Before writing data to this sysfs file,
>> "dsb_edge_ctrl_idx"
>> +        should be written first to configure the index number of the
>> edge
>> +        detection which needs to be masked.
>> +
>> +        Accepts only one of the 2 values -  0 or 1.
>> \ No newline at end of file
>> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c
>> b/drivers/hwtracing/coresight/coresight-tpdm.c
>> index c38760b..98fd6ab 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
>> @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata
>> *drvdata, u32 *val)
>>     static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
>>   {
>> -    u32 val;
>> +    u32 val, i;
>> +
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
>> +        writel_relaxed(drvdata->dsb->edge_ctrl[i],
>> +               drvdata->base + TPDM_DSB_EDCR(i));
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
>> +        writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
>> +               drvdata->base + TPDM_DSB_EDCMR(i));
>>         val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
>>       /* Set trigger timestamp */
>> @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev,
>>   }
>>   static DEVICE_ATTR_RW(dsb_mode);
>>   +static ssize_t dsb_edge_ctrl_idx_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->edge_ctrl_idx);
>> +}
>> +
>> +/*
>> + * The EDCR registers can include up to 16 32-bit registers, and each
>> + * one can be configured to control up to 16 edge detections(2 bits
>> + * control one edge detection). So a total 256 edge detections can be
>> + * configured. This function provides a way to set the index number of
>> + * the edge detection which needs to be configured.
>> + */
>> +static ssize_t dsb_edge_ctrl_idx_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 >= TPDM_DSB_MAX_LINES))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    drvdata->dsb->edge_ctrl_idx = val;
>> +    spin_unlock(&drvdata->spinlock);
>> +
>> +    return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
>> +
>> +static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
>> +                       struct device_attribute *attr,
>> +                       char *buf)
>> +{
>> +    struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +    ssize_t size = 0;
>> +    unsigned long bytes;
>> +    int i;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
>> +        bytes = sysfs_emit_at(buf, size,
>> +                  "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
>
> This feels a bit odd. edget_ctrl_val allows storing one "edge ctrl"
> value, while "show"ing all EDCR values. We could split them to :
>
> Read only sysfs files:
>
> dsb_edcr0 ... dsb_edcr15
>
> for each EDCR register (similarly for the mask)
>
> and may be show the specific edge_ctrl_line for with the above
> function for selected index.
Sure, I will update this in the next patch series.
>
>> +        if (bytes <= 0)
>> +            break;
>> +        size += bytes;
>> +    }
>> +    spin_unlock(&drvdata->spinlock);
>> +    return size;
>> +}
>> +
>> +/*
>> + * This function is used to control the edge detection according
>> + * to the index number that has been set.
>> + * "edge_ctrl" should be one of the following values.
>> + * 0 - Rising edge detection
>> + * 1 - Falling edge detection
>> + * 2 - Rising and falling edge detection (toggle detection)
>> + */
>> +static ssize_t dsb_edge_ctrl_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 val, mask, edge_ctrl;
>> +    int reg;
>> +
>> +    if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    /*
>> +     * There are 2 bit per DSB Edge Control line.
>> +     * Thus we have 16 lines in a 32bit word.
>> +     */
>> +    reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
>> +    mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
>> +    val = drvdata->dsb->edge_ctrl[reg];
>> +    val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
>> +    val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
>> +    drvdata->dsb->edge_ctrl[reg] = val;
>> +    spin_unlock(&drvdata->spinlock);
>> +
>> +    return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
>
> This can be WO attribute to write to a given line.
I will update this in the next patch series.
>
>> +
>> +static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
>> +                        struct device_attribute *attr,
>> +                        char *buf)
>> +{
>> +    struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +    ssize_t size = 0;
>> +    unsigned long bytes;
>> +    int i;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
>> +        bytes = sysfs_emit_at(buf, size,
>> +                  "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
>
> As mentioned above, please don't do this. One value per file. Add
>
> dsb_edcmr0..dsb_edcmr7
>
> and print only the selected index mask for this function.
I will update this in the next patch series.
>
>> +        if (bytes <= 0)
>> +            break;
>> +        size += bytes;
>> +    }
>> +    spin_unlock(&drvdata->spinlock);
>> +    return size;
>> +}
>> +
>> +static ssize_t dsb_edge_ctrl_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 val;
>> +    u32 set;
>> +    int reg;
>> +
>> +    if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    /*
>> +     * There is 1 bit per DSB Edge Control Mark line.
>> +     * Thus we have 32 lines in a 32bit word.
>> +     */
>> +    reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
>> +    set = drvdata->dsb->edge_ctrl_mask[reg];
>> +    if (val)
>> +        set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
>> +    else
>> +        set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
>> +        drvdata->dsb->edge_ctrl_mask[reg] = set;
>> +    spin_unlock(&drvdata->spinlock);
>> +
>> +    return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
>> +
>>   static ssize_t dsb_trig_type_show(struct device *dev,
>>                        struct device_attribute *attr, char *buf)
>>   {
>> @@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts);
>>     static struct attribute *tpdm_dsb_attrs[] = {
>>       &dev_attr_dsb_mode.attr,
>> +    &dev_attr_dsb_edge_ctrl_idx.attr,
>> +    &dev_attr_dsb_edge_ctrl_val.attr,
>> +    &dev_attr_dsb_edge_ctrl_mask.attr,
>>       &dev_attr_dsb_trig_ts.attr,
>>       &dev_attr_dsb_trig_type.attr,
>>       NULL,
>> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h
>> b/drivers/hwtracing/coresight/coresight-tpdm.h
>> index 49fffb1..4afdb29 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpdm.h
>> +++ b/drivers/hwtracing/coresight/coresight-tpdm.h
>> @@ -12,6 +12,8 @@
>>   /* DSB Subunit Registers */
>>   #define TPDM_DSB_CR        (0x780)
>>   #define TPDM_DSB_TIER        (0x784)
>> +#define TPDM_DSB_EDCR(n)    (0x808 + (n * 4))
>> +#define TPDM_DSB_EDCMR(n)    (0x848 + (n * 4))
>>     /* Enable bit for DSB subunit */
>>   #define TPDM_DSB_CR_ENA        BIT(0)
>> @@ -34,6 +36,16 @@
>>   #define TPDM_DSB_TEST_MODE        GENMASK(10, 9)
>>   #define TPDM_DSB_HPSEL        GENMASK(6, 2)
>>   +#define EDCRS_PER_WORD                16
>> +#define EDCR_TO_WORD_IDX(r)            ((r) / EDCRS_PER_WORD)
>> +#define EDCR_TO_WORD_SHIFT(r)        ((r % EDCRS_PER_WORD) * 2)
>> +#define EDCR_TO_WORD_VAL(val, r)    (val << EDCR_TO_WORD_SHIFT(r))
>> +#define EDCR_TO_WORD_MASK(r)        EDCR_TO_WORD_VAL(0x3, r)
>> +
>> +#define EDCMRS_PER_WORD                32
>> +#define EDCMR_TO_WORD_IDX(r)        ((r) / EDCMRS_PER_WORD)
>> +#define EDCMR_TO_WORD_SHIFT(r)        ((r) % EDCMRS_PER_WORD)
>> +
>>   /* TPDM integration test registers */
>>   #define TPDM_ITATBCNTRL        (0xEF0)
>>   #define TPDM_ITCNTRL        (0xF00)
>> @@ -60,14 +72,26 @@
>>   #define TPDM_PIDR0_DS_IMPDEF    BIT(0)
>>   #define TPDM_PIDR0_DS_DSB    BIT(1)
>>   +#define TPDM_DSB_MAX_LINES    256
>> +/* MAX number of EDCR registers */
>> +#define TPDM_DSB_MAX_EDCR    16
>> +/* MAX number of EDCMR registers */
>> +#define TPDM_DSB_MAX_EDCMR    8
>> +
>>   /**
>>    * struct dsb_dataset - specifics associated to dsb dataset
>> - * @mode:             DSB programming mode
>> - * @trig_ts:          Enable/Disable trigger timestamp.
>> - * @trig_type:        Enable/Disable trigger type.
>> + * @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
>> + * @trig_ts:            Enable/Disable trigger timestamp.
>> + * @trig_type:          Enable/Disable trigger type.
>>    */
>>   struct dsb_dataset {
>>       u32                mode;
>> +    u32                edge_ctrl_idx;
>> +    u32                edge_ctrl[TPDM_DSB_MAX_EDCR];
>> +    u32                edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
>
> Please keep them aligned with the rest of the fields.

I will update this in the next patch series.


Best,

Tao

>
>>       bool            trig_ts;
>>       bool            trig_type;
>
> Suzuki
>
>
>>   };
>

2023-08-09 07:44:51

by Tao Zhang

[permalink] [raw]
Subject: Re: [PATCH v7 09/13] coresight-tpdm: Add nodes for dsb edge control


On 8/7/2023 5:24 PM, Suzuki K Poulose wrote:
> On 25/07/2023 08:15, Tao Zhang wrote:
>> Add the nodes to set value for DSB edge control and DSB edge
>> control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR
>> resgisters to configure edge control. DSB edge detection control
>> 00: Rising edge detection
>> 01: Falling edge detection
>> 10: Rising and falling edge detection (toggle detection)
>> And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to
>> configure mask. Eight 32 bit registers providing DSB interface
>> edge detection mask control.
>>
>> Add the nodes to configure DSB edge control and DSB edge control
>> mask. Each DSB subunit TPDM maximum of 256 edge detections can be
>> configured. The index and value sysfs files need to be paired and
>> written to order. The index sysfs file is to set the index number
>> of the edge detection which needs to be configured. And the value
>> sysfs file is to set the control or mask for the edge detection.
>> DSB edge detection control should be set as the following values.
>> 00: Rising edge detection
>> 01: Falling edge detection
>> 10: Rising and falling edge detection (toggle detection)
>> And DSB edge mask should be set as 0 or 1.
>> Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to
>> configure edge control. And each DSB subunit TPDM has maximum of
>> m(m<8) ECDMR registers to configure mask.
>>
>> Signed-off-by: Tao Zhang <[email protected]>
>> ---
>>   .../ABI/testing/sysfs-bus-coresight-devices-tpdm   |  39 +++++
>>   drivers/hwtracing/coresight/coresight-tpdm.c       | 158
>> ++++++++++++++++++++-
>>   drivers/hwtracing/coresight/coresight-tpdm.h       |  30 +++-
>>   3 files changed, 223 insertions(+), 4 deletions(-)
>>
>> diff --git
>> a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> index 2a82cd0..a4550c5 100644
>> --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
>> @@ -60,3 +60,42 @@ Description:
>>           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.
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read/Write the index number of the edge detection for the DSB
>> +        subunit TPDM. Since there are at most 256 edge detections, this
>> +        value ranges from 0 to 255.
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read a set of the edge control registers of the DSB in TPDM.
>> +        Write a data to control the edge detection corresponding to
>> +        the index number. Before writing data to this sysfs file,
>> +        "dsb_edge_ctrl_idx" should be written first to configure the
>> +        index number of the edge detection which needs to be
>> controlled.
>> +
>> +        Accepts only one of the following values.
>> +        0 - Rising edge detection
>> +        1 - Falling edge detection
>> +        2 - Rising and falling edge detection (toggle detection)
>> +
>> +
>> +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask
>> +Date:        March 2023
>> +KernelVersion    6.5
>> +Contact:    Jinlong Mao (QUIC) <[email protected]>, Tao Zhang
>> (QUIC) <[email protected]>
>> +Description:
>> +        Read a set of the edge control mask registers of the DSB in
>> TPDM.
>> +        Write a data to mask the edge detection corresponding to the
>> index
>> +        number. Before writing data to this sysfs file,
>> "dsb_edge_ctrl_idx"
>> +        should be written first to configure the index number of the
>> edge
>> +        detection which needs to be masked.
>> +
>> +        Accepts only one of the 2 values -  0 or 1.
>> \ No newline at end of file
>> diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c
>> b/drivers/hwtracing/coresight/coresight-tpdm.c
>> index c38760b..98fd6ab 100644
>> --- a/drivers/hwtracing/coresight/coresight-tpdm.c
>> +++ b/drivers/hwtracing/coresight/coresight-tpdm.c
>> @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata
>> *drvdata, u32 *val)
>>     static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
>>   {
>> -    u32 val;
>> +    u32 val, i;
>> +
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
>> +        writel_relaxed(drvdata->dsb->edge_ctrl[i],
>> +               drvdata->base + TPDM_DSB_EDCR(i));
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
>> +        writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
>> +               drvdata->base + TPDM_DSB_EDCMR(i));
>>         val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
>>       /* Set trigger timestamp */
>> @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev,
>>   }
>>   static DEVICE_ATTR_RW(dsb_mode);
>>   +static ssize_t dsb_edge_ctrl_idx_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->edge_ctrl_idx);
>> +}
>> +
>> +/*
>> + * The EDCR registers can include up to 16 32-bit registers, and each
>> + * one can be configured to control up to 16 edge detections(2 bits
>> + * control one edge detection). So a total 256 edge detections can be
>> + * configured. This function provides a way to set the index number of
>> + * the edge detection which needs to be configured.
>> + */
>> +static ssize_t dsb_edge_ctrl_idx_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 >= TPDM_DSB_MAX_LINES))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    drvdata->dsb->edge_ctrl_idx = val;
>> +    spin_unlock(&drvdata->spinlock);
>> +
>> +    return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
>> +
>> +static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
>> +                       struct device_attribute *attr,
>> +                       char *buf)
>> +{
>> +    struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +    ssize_t size = 0;
>> +    unsigned long bytes;
>> +    int i;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
>> +        bytes = sysfs_emit_at(buf, size,
>> +                  "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
>> +        if (bytes <= 0)
>> +            break;
>> +        size += bytes;
>> +    }
>> +    spin_unlock(&drvdata->spinlock);
>> +    return size;
>> +}
>> +
>> +/*
>> + * This function is used to control the edge detection according
>> + * to the index number that has been set.
>> + * "edge_ctrl" should be one of the following values.
>> + * 0 - Rising edge detection
>> + * 1 - Falling edge detection
>> + * 2 - Rising and falling edge detection (toggle detection)
>> + */
>> +static ssize_t dsb_edge_ctrl_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 val, mask, edge_ctrl;
>> +    int reg;
>> +
>> +    if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    /*
>> +     * There are 2 bit per DSB Edge Control line.
>> +     * Thus we have 16 lines in a 32bit word.
>> +     */
>> +    reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
>> +    mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
>> +    val = drvdata->dsb->edge_ctrl[reg];
>> +    val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
>> +    val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
>> +    drvdata->dsb->edge_ctrl[reg] = val;
>> +    spin_unlock(&drvdata->spinlock);
>> +
>> +    return size;
>> +}
>> +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
>> +
>> +static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
>> +                        struct device_attribute *attr,
>> +                        char *buf)
>> +{
>> +    struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
>> +    ssize_t size = 0;
>> +    unsigned long bytes;
>> +    int i;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
>> +        bytes = sysfs_emit_at(buf, size,
>> +                  "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
>> +        if (bytes <= 0)
>> +            break;
>> +        size += bytes;
>> +    }
>> +    spin_unlock(&drvdata->spinlock);
>> +    return size;
>> +}
>> +
>> +static ssize_t dsb_edge_ctrl_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 val;
>> +    u32 set;
>> +    int reg;
>> +
>> +    if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
>> +        return -EINVAL;
>> +
>> +    spin_lock(&drvdata->spinlock);
>> +    /*
>> +     * There is 1 bit per DSB Edge Control Mark line.
>> +     * Thus we have 32 lines in a 32bit word.
>> +     */
>> +    reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
>> +    set = drvdata->dsb->edge_ctrl_mask[reg];
>> +    if (val)
>> +        set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
>> +    else
>> +        set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
>> +        drvdata->dsb->edge_ctrl_mask[reg] = set;
>
>
> drivers/hwtracing/coresight/coresight-tpdm.c: In function
> ‘dsb_edge_ctrl_mask_store’:
> drivers/hwtracing/coresight/coresight-tpdm.c:449:2: error: this ‘else’
> clause does not guard... [-Werror=misleading-indentation]
>   else
>   ^~~~
> drivers/hwtracing/coresight/coresight-tpdm.c:451:3: note: ...this
> statement, but the latter is misleadingly indented as if it were
> guarded by the ‘else’
>    drvdata->dsb->edge_ctrl_mask[reg] = set;
>    ^~~~~~~
> cc1: all warnings being treated as errors
> make[4]: *** [scripts/Makefile.build:243:
> drivers/hwtracing/coresight/coresight-tpdm.o] Error 1
> make[3]: *** [scripts/Makefile.build:480: drivers/hwtracing/coresight]
> Error 2
> make[2]: *** [scripts/Makefile.build:480: drivers] Error 2
> make[1]: *** [/ssd/src/LINUX-CORESIGHT/Makefile:2032: .] Error 2
> make: *** [Makefile:234: __sub-make] Error 2
>
I will update this in the next patch series.


Best,

Tao

> Suzuki

2023-08-09 08:03:32

by Tao Zhang

[permalink] [raw]
Subject: Re: [PATCH v7 04/13] coresight-tpda: Add DSB dataset support


On 8/7/2023 5:12 PM, Suzuki K Poulose wrote:
> On 04/08/2023 16:02, Suzuki K Poulose wrote:
>> On 25/07/2023 08:15, Tao Zhang wrote:
>>> Read the DSB element size from the device tree. Set the register
>>> bit that controls the DSB element size of the corresponding port.
>>>
>>> Signed-off-by: Tao Zhang <[email protected]>
>>> ---
>>>   drivers/hwtracing/coresight/coresight-tpda.c | 96
>>> +++++++++++++++++++++++++---
>>>   drivers/hwtracing/coresight/coresight-tpda.h |  4 ++
>>>   2 files changed, 90 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c
>>> b/drivers/hwtracing/coresight/coresight-tpda.c
>>> index 8d2b9d2..7c71342 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tpda.c
>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
>>> @@ -21,6 +21,58 @@
>>>   DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
>>> +/* Search and read element data size from the TPDM node in
>>
>> minor nit:
>>
>> /*
>>   * Search ...
>>
>>> + * the devicetree. Each input port of TPDA is connected to
>>> + * a TPDM. Different TPDM supports different types of dataset,
>>> + * and some may support more than one type of dataset.
>>> + * Parameter "inport" is used to pass in the input port number
>>> + * of TPDA, and it is set to 0 in the recursize call.
>>
>>> + * Parameter "parent" is used to pass in the original call.
>>
>> Please remove references to the past and describe "match_inport"
>>
>>> + */
>>> +static int tpda_set_element_size(struct tpda_drvdata *drvdata,
>>> +               struct coresight_device *csdev, int inport, bool
>>> match_inport)
>>
>> May be we could switch the order of the parameters:
>>
>> match_inport, int port
>>
>> Or even inport < 0, implies, port wont be matched.
>>
>> i.e.,
>>
>> tpda_set_element_size(drvdata, child, inport)
>>
>>> +{
>>> +    static int nr_inport;
>>> +    int i;
>>> +    static bool tpdm_found;
>>> +    struct coresight_device *in_csdev;
>>> +
>>> +    if (inport > (TPDA_MAX_INPORTS - 1))
>>> +        return -EINVAL;
>>> +
>>> +    if (match_inport) {
>>> +        nr_inport = inport;
>>> +        tpdm_found = false;
>>> +    }
>>
>> Could we not avoid the static variables and this dance by making the
>> function return the dsb_size ? See further down.
>>
>>
>>> +
>>> +    for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>>> +        in_csdev = csdev->pdata->in_conns[i]->src_dev;
>>> +        if (!in_csdev)
>>> +            break;
>>          continue ?
>>> +
>>> +        if (match_inport)
>>> +            if (csdev->pdata->in_conns[i]->dest_port != inport)
>>> +                continue;
>>> +
>>> +        if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>>> +                (in_csdev->subtype.source_subtype
>>> +                == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
>>
>> Please provide a helper :
>>
>> static bool coresight_device_is_tpdm(csdev) {
>>      return
>>       (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
>>       (in_csdev->subtype.source_subtype ==
>>          CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
>> }
>>
>>
>>
>>> + of_property_read_u8(in_csdev->dev.parent->of_node,
>>> +                    "qcom,dsb-element-size",
>>> &drvdata->dsb_esize[nr_inport]);
>>
>>
>>
>>> +            if (!tpdm_found)
>>> +                tpdm_found = true;
>>> +            else
>>> +                dev_warn(drvdata->dev,
>>> +                    "More than one TPDM is mapped to the TPDA input
>>> port %d.\n",
>>> +                    nr_inport);
>>> +            continue;
>>> +        }
>>> +        tpda_set_element_size(drvdata, in_csdev, 0, false);
>>> +    }
>>> +
>>
>> /*
>>   * Read the DSB element size from the TPDM device
>>   * Returns
>>   *    the size read from the firmware if available.
>>   *    0 - Otherwise, with a Warning once.
>>   */
>> static int tpdm_read_dsb_element_size(struct coresight_device *csdev)
>> {
>>      int rc, size = 0;
>>
>>      rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent),
>>                       "qcom,dsb-element-size", &size);
>>      if (rc)
>>          dev_warn_once(&in->dev, "Failed to read TPDM DSB Element
>> size: %d\n",
>>          rc);
>>      return size;
>> }
>>
>> static int tpda_get_element_size(struct coresight_device *csdev,
>>                   int inport)
>> {
>>      int dsb_size = -ENOENT;
>>
>>      for (i = 0; i < csdev->pdata->nr_inconns; i++) {
>>          in = csdev->pdata->in_conns[i]->src_dev;
>>          if (!in)
>>              continue;
>>          if (coresight_device_is_tpdm(in)) {
>>              /* Ignore the TPDMs that do not match port */
>>              if (inport > 0 &&
>>                  (csdev->pdata->in_conns[i]->dest_port !=
>>                  inport))
>>                  continue;
>>              size = tpdm_read_dsb_element_size(csdev);
>>          } else {
>>              /* Recurse down the path */
>>              size = tpda_set_element_size(in, -1);
>>          }
>>
>>          if (size < 0)
>>              return size;
>>          /* We have found a size, save it. */
>>          if (dsb_size < 0) {
>>              dsb_size = size;
>>          } else {
>>              /* We have duplicate TPDMs */
>>              return -EEXIST;
>>          }
>>      }
>>      return dsb_size;
>> }
>>
>>
>>
>>
>>> +    return 0;
>>> +}
>>> +
>>>   /* Settings pre enabling port control register */
>>>   static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
>>>   {
>>> @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct
>>> tpda_drvdata *drvdata)
>>>       writel_relaxed(val, drvdata->base + TPDA_CR);
>>>   }
>>> -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>>> +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
>>>   {
>>>       u32 val;
>>>       val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
>>> +    /*
>>> +     * Configure aggregator port n DSB data set element size
>>> +     * Set the bit to 0 if the size is 32
>>> +     * Set the bit to 1 if the size is 64
>>> +     */
>>> +    if (drvdata->dsb_esize[port] == 32)
>>> +        val &= ~TPDA_Pn_CR_DSBSIZE;
>>> +    else if (drvdata->dsb_esize[port] == 64)
>>> +        val |= TPDA_Pn_CR_DSBSIZE;
>>
>> Couldn't this be detected via tpda_get_element_size()? see below.
>>
>>> +    else
>>> +        return -EINVAL;
>>> +
>>>       /* Enable the port */
>>>       val |= TPDA_Pn_CR_ENA;
>>>       writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
>>> +
>>> +    return 0;
>>>   }
>>> -static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
>>> +static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
>>>   {
>>> +    int ret;
>>> +
>>>       CS_UNLOCK(drvdata->base);
>>>       if (!drvdata->csdev->enable)
>>>           tpda_enable_pre_port(drvdata);
>>> -    tpda_enable_port(drvdata, port);
>>> -
>>> +    ret = tpda_enable_port(drvdata, port);
>>>       CS_LOCK(drvdata->base);
>>> +
>>> +    return ret;
>>>   }
>>>   static int tpda_enable(struct coresight_device *csdev,
>>> @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device
>>> *csdev,
>>>                  struct coresight_connection *out)
>>>   {
>>>       struct tpda_drvdata *drvdata =
>>> dev_get_drvdata(csdev->dev.parent);
>>> +    int ret;
>>> +
>>> +    ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
>>
>>      size  = tpda_get_element_size(csdev, in->dest_port);
>>      switch (size) {
>>      case 32:
>>      case 64:
>>          break;
>
> We also need :
>
>     case 0:
>         return -ENOENT;

I will update this in the next patch series.


Best,

Tao

>
> Suzuki
>
>
>>      case -EEXIST:
>>          dev_warn_once("Detected multiple TPDMs on port %d", ..)
>>          fallthrough;
>>      default:
>>          return size;
>>      }
>>
>>      drvdata->dsb_esize[in->dest_port] = size;
>>
>> Suzuki
>>
>>
>>
>>> +    if (ret)
>>> +        return ret;
>>>       spin_lock(&drvdata->spinlock);
>>> -    if (atomic_read(&in->dest_refcnt) == 0)
>>> -        __tpda_enable(drvdata, in->dest_port);
>>> +    if (atomic_read(&in->dest_refcnt) == 0) {
>>> +        ret = __tpda_enable(drvdata, in->dest_port);
>>> +        if (!ret) {
>>> +            atomic_inc(&in->dest_refcnt);
>>> +            dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n",
>>> in->dest_port);
>>> +        }
>>> +    }
>>> -    atomic_inc(&in->dest_refcnt);
>>>       spin_unlock(&drvdata->spinlock);
>>> -
>>> -    dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
>>> -    return 0;
>>> +    return ret;
>>>   }
>>>   static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
>>> diff --git a/drivers/hwtracing/coresight/coresight-tpda.h
>>> b/drivers/hwtracing/coresight/coresight-tpda.h
>>> index 0399678..12a1472 100644
>>> --- a/drivers/hwtracing/coresight/coresight-tpda.h
>>> +++ b/drivers/hwtracing/coresight/coresight-tpda.h
>>> @@ -10,6 +10,8 @@
>>>   #define TPDA_Pn_CR(n)        (0x004 + (n * 4))
>>>   /* Aggregator port enable bit */
>>>   #define TPDA_Pn_CR_ENA        BIT(0)
>>> +/* Aggregator port DSB data set element size bit */
>>> +#define TPDA_Pn_CR_DSBSIZE        BIT(8)
>>>   #define TPDA_MAX_INPORTS    32
>>> @@ -23,6 +25,7 @@
>>>    * @csdev:      component vitals needed by the framework.
>>>    * @spinlock:   lock for the drvdata value.
>>>    * @enable:     enable status of the component.
>>> + * @dsb_esize:  DSB element size for each inport, it must be 32 or 64.
>>>    */
>>>   struct tpda_drvdata {
>>>       void __iomem        *base;
>>> @@ -30,6 +33,7 @@ struct tpda_drvdata {
>>>       struct coresight_device    *csdev;
>>>       spinlock_t        spinlock;
>>>       u8            atid;
>>> +    u8            dsb_esize[TPDA_MAX_INPORTS];
>>>   };
>>>   #endif  /* _CORESIGHT_CORESIGHT_TPDA_H */
>>
>