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 0x3 0x1 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_mask echo 0x6d 0x6d 0 > /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 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_patt_mask echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_val
This patch series depends on patch series "[PATCH v2 0/9] coresight: Fix CTI module refcount leak by making it a helper device" https://patchwork.kernel.org/project/linux-arm-kernel/patch/20230425143542.2...
TPDM_DSB commit tree: https://git.codelinaro.org/clo/linux-kernel/coresight/-/tree/tpdm-dsb-v4 https://git.codelinaro.org/clo/linux-kernel/coresight/-/commits/tpdm-dsb-v4
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 (11): dt-bindings: arm: Add support for DSB element size 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 | 174 ++++++ .../bindings/arm/qcom,coresight-tpdm.yaml | 19 + drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 ++- drivers/hwtracing/coresight/coresight-tpda.h | 4 + drivers/hwtracing/coresight/coresight-tpdm.c | 691 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 79 +++ include/linux/coresight.h | 1 + 8 files changed, 1045 insertions(+), 16 deletions(-)
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 quic_taozha@quicinc.com --- 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..932c55b 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/uint32 + 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";
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 quic_taozha@quicinc.com --- drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev,
if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL; diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@
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 parent) +{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev; + + if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL; + + if (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue; + + if (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); + } + 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 +82,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 +126,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) + if (atomic_read(&in->dest_refcnt) == 0) { __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..7332e9c 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, 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 */ diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f4854af..ba1867f 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -205,7 +205,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) if (!desc.name) return -ENOMEM; desc.type = CORESIGHT_DEV_TYPE_SOURCE; - desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; + desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM; desc.ops = &tpdm_cs_ops; desc.pdata = adev->dev.platform_data; desc.dev = &adev->dev; diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 225a5fa..6563896 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -60,6 +60,7 @@ enum coresight_dev_subtype_source { CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, CORESIGHT_DEV_SUBTYPE_SOURCE_BUS, CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE, + CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM, CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS, };
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE &&
subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM &&
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent)
+{
- static int nr_inport;
- int i;
- static bool tpdm_found;
- struct coresight_device *in_csdev;
- if (inport > (TPDA_MAX_INPORTS - 1))
return -EINVAL;
- if (parent) {
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 (parent)
if (csdev->pdata->in_conns[i]->dest_port != inport)
continue;
if (in_csdev->subtype.source_subtype
We must match the in_csdev->type to be SOURCE && the 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);
When we know, we have found a source device, we don't need to recurse down and could simply 'continue' to the next one in the list and skip the call below.
}
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 +82,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 +126,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)
- if (atomic_read(&in->dest_refcnt) == 0) { __tpda_enable(drvdata, in->dest_port);
ret = ... ?
if (!ret) {
atomic_inc(&in->dest_refcnt);
dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
}
- }
- atomic_inc(&in->dest_refcnt);
This seems wrong, as we may fail to hold additional refcounts for the additional sessions ?
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..7332e9c 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, it must be 32 or 64.
minor nit:
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 */ diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f4854af..ba1867f 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -205,7 +205,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) if (!desc.name) return -ENOMEM; desc.type = CORESIGHT_DEV_TYPE_SOURCE;
- desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS;
- desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM; desc.ops = &tpdm_cs_ops; desc.pdata = adev->dev.platform_data; desc.dev = &adev->dev;
Please could you split this change, i.e., introduction of SUBTYPE_SOURCE_TPDM and using this in TPDM driver, in a separate patch before this change.
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 225a5fa..6563896 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -60,6 +60,7 @@ enum coresight_dev_subtype_source { CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, CORESIGHT_DEV_SUBTYPE_SOURCE_BUS, CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE,
- CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM, CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS, };
On 23/05/2023 11:07, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent)
The name parent is a bit confusing. It could imply parent device ? That is kind of inverse ? because, parent = true, indicates the parent device of tpda, which is not true. Could we simply say
bool match_inport => When true, the dest_port of the connection from the csdev must match the inport ? And ...
+{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
The above can become :
if (match_inport && csdev->pdata->in_conns[i]->dest_port != inport) continue;
Suzuki
On 5/23/2023 10:48 PM, Suzuki K Poulose wrote:
On 23/05/2023 11:07, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent)
The name parent is a bit confusing. It could imply parent device ? That is kind of inverse ? because, parent = true, indicates the parent device of tpda, which is not true. Could we simply say
bool match_inport => When true, the dest_port of the connection from the csdev must match the inport ? And ...
Sure, 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 (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
The above can become :
if (match_inport && csdev->pdata->in_conns[i]->dest_port != inport) continue;
Sure, I will update this in the next patch series.
Best,
Tao
Suzuki
On 5/23/2023 6:07 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent) +{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if (in_csdev->subtype.source_subtype
We must match the in_csdev->type to be SOURCE && the subtype.
Sure, I will update it in the next patch series.
+ == 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);
When we know, we have found a source device, we don't need to recurse down and could simply 'continue' to the next one in the list and skip the call below.
Actually, one input port on TPDA only can connect to one TPDM. In the current design, it will
find out all the TPDMs on one input port and warn the users all the TPDMs it found. If we
replace 'recurse down' as 'continue' here, it may not find some TPDMs that might be connected
incorrectly.
+ } + 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 +82,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 +126,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) + if (atomic_read(&in->dest_refcnt) == 0) { __tpda_enable(drvdata, in->dest_port);
ret = ... ?
Sure, I will update it in the next patch series.
+ if (!ret) {
- atomic_inc(&in->dest_refcnt);
+ dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); + } + }
- atomic_inc(&in->dest_refcnt);
This seems wrong, as we may fail to hold additional refcounts for the additional sessions ?
In the current design, if the TPDA is enabled successfully, it will run "atomic_inc(&in->dest_refcnt);"
Otherwise, it will not run "atomic_inc(&in->dest_refcnt);" to avoid additional refcounts. Is it right?
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..7332e9c 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, it must be 32 or 64.
minor nit:
DSB element size for each inport, it must be 32 or 64
Sure, I will update it in the next patch series.
*/ 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 */ diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f4854af..ba1867f 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -205,7 +205,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) if (!desc.name) return -ENOMEM; desc.type = CORESIGHT_DEV_TYPE_SOURCE; - desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; + desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM; desc.ops = &tpdm_cs_ops; desc.pdata = adev->dev.platform_data; desc.dev = &adev->dev;
Please could you split this change, i.e., introduction of SUBTYPE_SOURCE_TPDM and using this in TPDM driver, in a separate patch before this change.
Sure, I will update it in the next patch series.
Best,
Tao
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 225a5fa..6563896 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -60,6 +60,7 @@ enum coresight_dev_subtype_source { CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, CORESIGHT_DEV_SUBTYPE_SOURCE_BUS, CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE, + CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM, CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS, };
On 25/05/2023 08:16, Tao Zhang wrote:
On 5/23/2023 6:07 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent) +{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if (in_csdev->subtype.source_subtype
We must match the in_csdev->type to be SOURCE && the subtype.
Sure, I will update it in the next patch series.
+ == 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);
When we know, we have found a source device, we don't need to recurse down and could simply 'continue' to the next one in the list and skip the call below.
Actually, one input port on TPDA only can connect to one TPDM. In the current design, it will
find out all the TPDMs on one input port and warn the users all the TPDMs it found. If we
replace 'recurse down' as 'continue' here, it may not find some TPDMs that might be connected
incorrectly.
What do you mean ? When you enter the if () above, the in_csdev is a source and it is TPDM. There must be no input connections TPDM, i.e. in_csdev, so no need to go further up the connection chain looking at the in_csdev. The loop will continue to analyse this device (where we found one TPDM already) and detect any further duplicate TPDMs connected.
Suzuki
On 5/25/2023 5:08 PM, Suzuki K Poulose wrote:
On 25/05/2023 08:16, Tao Zhang wrote:
On 5/23/2023 6:07 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 92 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 2af416b..f1eacbb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1092,6 +1092,7 @@ static int coresight_validate_source(struct coresight_device *csdev, if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE && + subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM && subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) { dev_err(&csdev->dev, "wrong device subtype in %s\n", function); return -EINVAL;
Please see the comment at the bottom.
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..af9c72f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,56 @@ 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 parent) +{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (parent) { + 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 (parent) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if (in_csdev->subtype.source_subtype
We must match the in_csdev->type to be SOURCE && the subtype.
Sure, I will update it in the next patch series.
+ == 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);
When we know, we have found a source device, we don't need to recurse down and could simply 'continue' to the next one in the list and skip the call below.
Actually, one input port on TPDA only can connect to one TPDM. In the current design, it will
find out all the TPDMs on one input port and warn the users all the TPDMs it found. If we
replace 'recurse down' as 'continue' here, it may not find some TPDMs that might be connected
incorrectly.
What do you mean ? When you enter the if () above, the in_csdev is a source and it is TPDM. There must be no input connections TPDM, i.e. in_csdev, so no need to go further up the connection chain looking at the in_csdev. The loop will continue to analyse this device (where we found one TPDM already) and detect any further duplicate TPDMs connected.
Got it. You're right.
I will update this in the next patch series as well.
Suzuki
DSB is used for monitoring “events”. Events are something that occurs at some point in time. It could be a state decode, the act of writing/reading a particular address, a FIFO being empty, etc. This decoding of the event desired is done outside TPDM. DSB subunit need to be configured in enablement and disablement. A struct that specifics associated to dsb dataset is needed. It saves the configuration and parameters of the dsb datasets. This change is to add this struct and initialize the configuration of DSB subunit.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- drivers/hwtracing/coresight/coresight-tpdm.c | 60 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpdm.h | 17 ++++++++ 2 files changed, 72 insertions(+), 5 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index ba1867f..6f8a8ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,51 @@
DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm");
+static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) +{ + if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { + memset(drvdata->dsb, 0, sizeof(struct dsb_dataset)); + + drvdata->dsb->trig_ts = true; + drvdata->dsb->trig_type = false; + } +} + +static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->trig_type) + *val |= TPDM_DSB_CR_TRIG_TYPE; + else + *val &= ~TPDM_DSB_CR_TRIG_TYPE; +} + static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val;
- /* Set the enable bit of DSB control register to 1 */ + val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); + /* Set trigger timestamp */ + if (drvdata->dsb->trig_ts) + val |= TPDM_DSB_TIER_XTRIG_TSENAB; + else + val &= ~TPDM_DSB_TIER_XTRIG_TSENAB; + writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); + val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set trigger type */ + set_trigger_type(drvdata, &val); + /* Set the enable bit of DSB control register to 1 */ val |= TPDM_DSB_CR_ENA; writel_relaxed(val, drvdata->base + TPDM_DSB_CR); }
/* TPDM enable operations */ +/* The TPDM or Monitor serves as data collection component for various + * dataset types. It covers Basic Counts(BC), Tenure Counts(TC), + * Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single + * Bit(DSB). This function will initialize the configuration according + * to the dataset type supported by the TPDM. + */ static void __tpdm_enable(struct tpdm_drvdata *drvdata) { CS_UNLOCK(drvdata->base); @@ -110,15 +144,24 @@ static const struct coresight_ops tpdm_cs_ops = { .source_ops = &tpdm_source_ops, };
-static void tpdm_init_default_data(struct tpdm_drvdata *drvdata) +static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) { u32 pidr;
- CS_UNLOCK(drvdata->base); /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); - CS_LOCK(drvdata->base); + + if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { + if (!drvdata->dsb) { + drvdata->dsb = devm_kzalloc(drvdata->dev, + sizeof(*drvdata->dsb), GFP_KERNEL); + if (!drvdata->dsb) + return -ENOMEM; + } + } + + return 0; }
/* @@ -181,6 +224,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_platform_data *pdata; struct tpdm_drvdata *drvdata; struct coresight_desc desc = { 0 }; + int ret;
pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) @@ -200,6 +244,12 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->base = base;
+ ret = tpdm_datasets_setup(drvdata); + if (ret) + return ret; + + tpdm_reset_datasets(drvdata); + /* Set up coresight component description */ desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name) @@ -216,7 +266,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(drvdata->csdev);
spin_lock_init(&drvdata->spinlock); - tpdm_init_default_data(drvdata); + /* Decrease pm refcount when probe is done.*/ pm_runtime_put(&adev->dev);
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 5438540..68f33bd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -11,8 +11,14 @@
/* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) +#define TPDM_DSB_TIER (0x784) + /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit trigger type */ +#define TPDM_DSB_CR_TRIG_TYPE BIT(12) +/* Enable bit for DSB subunit trigger timestamp */ +#define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
/* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) @@ -41,6 +47,16 @@ #define TPDM_PIDR0_DS_DSB BIT(1)
/** + * struct dsb_dataset - specifics associated to dsb dataset + * @trig_ts: Enable/Disable trigger timestamp. + * @trig_type: Enable/Disable trigger type. + */ +struct dsb_dataset { + bool trig_ts; + bool trig_type; +}; + +/** * struct tpdm_drvdata - specifics associated to an TPDM component * @base: memory mapped base address for this component. * @dev: The device entity associated to this component. @@ -57,6 +73,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets; + struct dsb_dataset *dsb; };
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
On 27/04/2023 10:00, Tao Zhang wrote:
DSB is used for monitoring “events”. Events are something that occurs at some point in time. It could be a state decode, the act of writing/reading a particular address, a FIFO being empty, etc. This decoding of the event desired is done outside TPDM. DSB subunit need to be configured in enablement and disablement. A struct that specifics associated to dsb dataset is needed. It saves the configuration and parameters of the dsb datasets. This change is to add this struct and initialize the configuration of DSB subunit.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpdm.c | 60 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpdm.h | 17 ++++++++ 2 files changed, 72 insertions(+), 5 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index ba1867f..6f8a8ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,51 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) +{
- if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
memset(drvdata->dsb, 0, sizeof(struct dsb_dataset));
drvdata->dsb->trig_ts = true;
drvdata->dsb->trig_type = false;
- }
+}
+static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) +{
- if (drvdata->dsb->trig_type)
*val |= TPDM_DSB_CR_TRIG_TYPE;
- else
*val &= ~TPDM_DSB_CR_TRIG_TYPE;
+}
Given this is not reused, we could simply inline it in the caller to avoid creating a confusion, like other operations ?
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val;
- /* Set the enable bit of DSB control register to 1 */
- val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
- /* Set trigger timestamp */
- if (drvdata->dsb->trig_ts)
val |= TPDM_DSB_TIER_XTRIG_TSENAB;
- else
val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;,
- writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
- val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
- /* Set trigger type */
- set_trigger_type(drvdata, &val);
- /* Set the enable bit of DSB control register to 1 */ val |= TPDM_DSB_CR_ENA; writel_relaxed(val, drvdata->base + TPDM_DSB_CR); }
/* TPDM enable operations */ +/* The TPDM or Monitor serves as data collection component for various
minor nit: Please could you extend the existing comment than adding a new multi-line comment ?
- dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
- Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single
- Bit(DSB). This function will initialize the configuration according
- to the dataset type supported by the TPDM.
- */ static void __tpdm_enable(struct tpdm_drvdata *drvdata) { CS_UNLOCK(drvdata->base);
@@ -110,15 +144,24 @@ static const struct coresight_ops tpdm_cs_ops = { .source_ops = &tpdm_source_ops, }; -static void tpdm_init_default_data(struct tpdm_drvdata *drvdata) +static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) { u32 pidr;
- CS_UNLOCK(drvdata->base); /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0);
- CS_LOCK(drvdata->base);
Why are we removing the CS_{UN,}LOCK here ?
Rest looks OK to me.
Suzuki
- if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
if (!drvdata->dsb) {
drvdata->dsb = devm_kzalloc(drvdata->dev,
sizeof(*drvdata->dsb), GFP_KERNEL);
if (!drvdata->dsb)
return -ENOMEM;
}
- }
- return 0; }
/* @@ -181,6 +224,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_platform_data *pdata; struct tpdm_drvdata *drvdata; struct coresight_desc desc = { 0 };
- int ret;
pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) @@ -200,6 +244,12 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) drvdata->base = base;
- ret = tpdm_datasets_setup(drvdata);
- if (ret)
return ret;
- tpdm_reset_datasets(drvdata);
- /* Set up coresight component description */ desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name)
@@ -216,7 +266,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(drvdata->csdev); spin_lock_init(&drvdata->spinlock);
- tpdm_init_default_data(drvdata);
- /* Decrease pm refcount when probe is done.*/ pm_runtime_put(&adev->dev);
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 5438540..68f33bd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -11,8 +11,14 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) +#define TPDM_DSB_TIER (0x784)
- /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0)
+/* Enable bit for DSB subunit trigger type */ +#define TPDM_DSB_CR_TRIG_TYPE BIT(12) +/* Enable bit for DSB subunit trigger timestamp */ +#define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) @@ -41,6 +47,16 @@ #define TPDM_PIDR0_DS_DSB BIT(1) /**
- struct dsb_dataset - specifics associated to dsb dataset
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- */
+struct dsb_dataset {
- bool trig_ts;
- bool trig_type;
+};
+/**
- struct tpdm_drvdata - specifics associated to an TPDM component
- @base: memory mapped base address for this component.
- @dev: The device entity associated to this component.
@@ -57,6 +73,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets;
- struct dsb_dataset *dsb; };
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
On 5/23/2023 9:42 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
DSB is used for monitoring “events”. Events are something that occurs at some point in time. It could be a state decode, the act of writing/reading a particular address, a FIFO being empty, etc. This decoding of the event desired is done outside TPDM. DSB subunit need to be configured in enablement and disablement. A struct that specifics associated to dsb dataset is needed. It saves the configuration and parameters of the dsb datasets. This change is to add this struct and initialize the configuration of DSB subunit.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpdm.c | 60 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpdm.h | 17 ++++++++ 2 files changed, 72 insertions(+), 5 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index ba1867f..6f8a8ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,51 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) +{ + if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { + memset(drvdata->dsb, 0, sizeof(struct dsb_dataset));
+ drvdata->dsb->trig_ts = true; + drvdata->dsb->trig_type = false; + } +}
+static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->trig_type) + *val |= TPDM_DSB_CR_TRIG_TYPE; + else + *val &= ~TPDM_DSB_CR_TRIG_TYPE; +}
Given this is not reused, we could simply inline it in the caller to avoid creating a confusion, like other operations ?
Sure, I will update it in the next patch series.
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val; - /* Set the enable bit of DSB control register to 1 */ + val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); + /* Set trigger timestamp */ + if (drvdata->dsb->trig_ts) + val |= TPDM_DSB_TIER_XTRIG_TSENAB; + else + val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;, + writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set trigger type */ + set_trigger_type(drvdata, &val); + /* Set the enable bit of DSB control register to 1 */ val |= TPDM_DSB_CR_ENA; writel_relaxed(val, drvdata->base + TPDM_DSB_CR); } /* TPDM enable operations */ +/* The TPDM or Monitor serves as data collection component for various
minor nit: Please could you extend the existing comment than adding a new multi-line comment ?
Sure, I will update it in the next patch series.
- dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
- Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single
- Bit(DSB). This function will initialize the configuration according
- to the dataset type supported by the TPDM.
- */
static void __tpdm_enable(struct tpdm_drvdata *drvdata) { CS_UNLOCK(drvdata->base); @@ -110,15 +144,24 @@ static const struct coresight_ops tpdm_cs_ops = { .source_ops = &tpdm_source_ops, }; -static void tpdm_init_default_data(struct tpdm_drvdata *drvdata) +static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) { u32 pidr; - CS_UNLOCK(drvdata->base); /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); - CS_LOCK(drvdata->base);
Why are we removing the CS_{UN,}LOCK here ?
CS_UNLOCK is used before writing data to Coresight registers. Here this function
doesn't need to write data to any registers, so I remove the CS_{UN,}LOCK here.
Best,
Tao
Rest looks OK to me.
Suzuki
+ if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { + if (!drvdata->dsb) { + drvdata->dsb = devm_kzalloc(drvdata->dev, + sizeof(*drvdata->dsb), GFP_KERNEL); + if (!drvdata->dsb) + return -ENOMEM; + } + }
+ return 0; } /* @@ -181,6 +224,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_platform_data *pdata; struct tpdm_drvdata *drvdata; struct coresight_desc desc = { 0 }; + int ret; pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) @@ -200,6 +244,12 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) drvdata->base = base; + ret = tpdm_datasets_setup(drvdata); + if (ret) + return ret;
+ tpdm_reset_datasets(drvdata);
/* Set up coresight component description */ desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name) @@ -216,7 +266,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(drvdata->csdev); spin_lock_init(&drvdata->spinlock); - tpdm_init_default_data(drvdata);
/* Decrease pm refcount when probe is done.*/ pm_runtime_put(&adev->dev); diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 5438540..68f33bd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -11,8 +11,14 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) +#define TPDM_DSB_TIER (0x784)
/* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit trigger type */ +#define TPDM_DSB_CR_TRIG_TYPE BIT(12) +/* Enable bit for DSB subunit trigger timestamp */ +#define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) @@ -41,6 +47,16 @@ #define TPDM_PIDR0_DS_DSB BIT(1) /**
- struct dsb_dataset - specifics associated to dsb dataset
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- */
+struct dsb_dataset { + bool trig_ts; + bool trig_type; +};
+/** * struct tpdm_drvdata - specifics associated to an TPDM component * @base: memory mapped base address for this component. * @dev: The device entity associated to this component. @@ -57,6 +73,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets; + struct dsb_dataset *dsb; }; #endif /* _CORESIGHT_CORESIGHT_TPDM_H */
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
On 25/05/2023 09:12, Tao Zhang wrote:
On 5/23/2023 9:42 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
DSB is used for monitoring “events”. Events are something that occurs at some point in time. It could be a state decode, the act of writing/reading a particular address, a FIFO being empty, etc. This decoding of the event desired is done outside TPDM. DSB subunit need to be configured in enablement and disablement. A struct that specifics associated to dsb dataset is needed. It saves the configuration and parameters of the dsb datasets. This change is to add this struct and initialize the configuration of DSB subunit.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
...
- dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
- Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single
- Bit(DSB). This function will initialize the configuration according
- to the dataset type supported by the TPDM.
- */
static void __tpdm_enable(struct tpdm_drvdata *drvdata) { CS_UNLOCK(drvdata->base); @@ -110,15 +144,24 @@ static const struct coresight_ops tpdm_cs_ops = { .source_ops = &tpdm_source_ops, }; -static void tpdm_init_default_data(struct tpdm_drvdata *drvdata) +static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) { u32 pidr; - CS_UNLOCK(drvdata->base); /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); - CS_LOCK(drvdata->base);
Why are we removing the CS_{UN,}LOCK here ?
CS_UNLOCK is used before writing data to Coresight registers. Here this function
doesn't need to write data to any registers, so I remove the CS_{UN,}LOCK here.
Please make this a separate patch to avoid confusing and keep it at the beginning of the series.
Suzuki
On 5/25/2023 5:09 PM, Suzuki K Poulose wrote:
On 25/05/2023 09:12, Tao Zhang wrote:
On 5/23/2023 9:42 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
DSB is used for monitoring “events”. Events are something that occurs at some point in time. It could be a state decode, the act of writing/reading a particular address, a FIFO being empty, etc. This decoding of the event desired is done outside TPDM. DSB subunit need to be configured in enablement and disablement. A struct that specifics associated to dsb dataset is needed. It saves the configuration and parameters of the dsb datasets. This change is to add this struct and initialize the configuration of DSB subunit.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
...
- dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
- Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete
Single
- Bit(DSB). This function will initialize the configuration
according
- to the dataset type supported by the TPDM.
- */
static void __tpdm_enable(struct tpdm_drvdata *drvdata) { CS_UNLOCK(drvdata->base); @@ -110,15 +144,24 @@ static const struct coresight_ops tpdm_cs_ops = { .source_ops = &tpdm_source_ops, }; -static void tpdm_init_default_data(struct tpdm_drvdata *drvdata) +static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) { u32 pidr; - CS_UNLOCK(drvdata->base); /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); - CS_LOCK(drvdata->base);
Why are we removing the CS_{UN,}LOCK here ?
CS_UNLOCK is used before writing data to Coresight registers. Here this function
doesn't need to write data to any registers, so I remove the CS_{UN,}LOCK here.
Please make this a separate patch to avoid confusing and keep it at the beginning of the series.
Sure, I will update this in the next patch series.
Suzuki
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
TPDM device need a node to reset the configurations and status of it. This change provides a node to reset the configurations and disable the TPDM if it has been enabled.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 10 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 27 ++++++++++++++++++++++ 2 files changed, 37 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..686bdde 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -11,3 +11,13 @@ Description: Accepts only one of the 2 values - 1 or 2. 1 : Generate 64 bits data 2 : Generate 32 bits data + +What: /sys/bus/coresight/devices/<tpdm-name>/reset +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Reset the dataset of the tpdm, and disable the tpdm. + + Accepts only one value - 1. + 1 : Reset the dataset of the tpdm diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 6f8a8ab..2e64cfd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -164,6 +164,32 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) return 0; }
+static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + int ret = 0; + unsigned long val; + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + ret = kstrtoul(buf, 10, &val); + if (ret || val != 1) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + tpdm_reset_datasets(drvdata); + + spin_unlock(&drvdata->spinlock); + + /* Disable tpdm if enabled */ + if (drvdata->enable) + coresight_disable_source(drvdata->csdev, NULL); + + return size; +} +static DEVICE_ATTR_WO(reset); + /* * value 1: 64 bits test data * value 2: 32 bits test data @@ -204,6 +230,7 @@ static ssize_t integration_test_store(struct device *dev, static DEVICE_ATTR_WO(integration_test);
static struct attribute *tpdm_attrs[] = { + &dev_attr_reset.attr, &dev_attr_integration_test.attr, NULL, };
On 27/04/2023 10:00, Tao Zhang wrote:
TPDM device need a node to reset the configurations and status of it. This change provides a node to reset the configurations and disable the TPDM if it has been enabled.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 10 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 27 ++++++++++++++++++++++ 2 files changed, 37 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..686bdde 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -11,3 +11,13 @@ Description: Accepts only one of the 2 values - 1 or 2. 1 : Generate 64 bits data 2 : Generate 32 bits data
+What: /sys/bus/coresight/devices/<tpdm-name>/reset +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Reset the dataset of the tpdm, and disable the tpdm.
Accepts only one value - 1.
1 : Reset the dataset of the tpdm
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 6f8a8ab..2e64cfd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -164,6 +164,32 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) return 0; } +static ssize_t reset_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- int ret = 0;
- unsigned long val;
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = kstrtoul(buf, 10, &val);
- if (ret || val != 1)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- tpdm_reset_datasets(drvdata);
- spin_unlock(&drvdata->spinlock);
- /* Disable tpdm if enabled */
- if (drvdata->enable)
coresight_disable_source(drvdata->csdev, NULL);
I am not really keen on doing this behind the back. What about the path of components ? We could simply reject the request when the TPDA is enabled and let the user alway follow : 1) Disable the TPDM manually via sysfs 2) Reset the TPDM.
So, please remove the disable step here.
Suzuki
- return size;
+} +static DEVICE_ATTR_WO(reset);
- /*
- value 1: 64 bits test data
- value 2: 32 bits test data
@@ -204,6 +230,7 @@ static ssize_t integration_test_store(struct device *dev, static DEVICE_ATTR_WO(integration_test); static struct attribute *tpdm_attrs[] = {
- &dev_attr_reset.attr, &dev_attr_integration_test.attr, NULL, };
On 5/23/2023 10:53 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
TPDM device need a node to reset the configurations and status of it. This change provides a node to reset the configurations and disable the TPDM if it has been enabled.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 10 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 27 ++++++++++++++++++++++ 2 files changed, 37 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..686bdde 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -11,3 +11,13 @@ Description: Accepts only one of the 2 values - 1 or 2. 1 : Generate 64 bits data 2 : Generate 32 bits data
+What: /sys/bus/coresight/devices/<tpdm-name>/reset +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Reset the dataset of the tpdm, and disable the tpdm.
+ Accepts only one value - 1. + 1 : Reset the dataset of the tpdm diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 6f8a8ab..2e64cfd 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -164,6 +164,32 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) return 0; } +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + int ret = 0; + unsigned long val; + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ ret = kstrtoul(buf, 10, &val); + if (ret || val != 1) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + tpdm_reset_datasets(drvdata);
+ spin_unlock(&drvdata->spinlock);
+ /* Disable tpdm if enabled */ + if (drvdata->enable) + coresight_disable_source(drvdata->csdev, NULL);
I am not really keen on doing this behind the back. What about the path of components ? We could simply reject the request when the TPDA is enabled and let the user alway follow : 1) Disable the TPDM manually via sysfs 2) Reset the TPDM.
So, please remove the disable step here.
I will update this in the next patch series.
Best,
Tao
Suzuki
+ return size; +} +static DEVICE_ATTR_WO(reset);
/* * value 1: 64 bits test data * value 2: 32 bits test data @@ -204,6 +230,7 @@ static ssize_t integration_test_store(struct device *dev, static DEVICE_ATTR_WO(integration_test); static struct attribute *tpdm_attrs[] = { + &dev_attr_reset.attr, &dev_attr_integration_test.attr, NULL, };
The nodes are needed to set or show the trigger timestamp and trigger type. This change is to add these nodes to achieve these function.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 24 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 95 ++++++++++++++++++++++ 2 files changed, 119 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 686bdde..77e67f2 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -21,3 +21,27 @@ Description:
Accepts only one value - 1. 1 : Reset the dataset of the tpdm + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger type of DSB tpdm. Read the trigger + type of DSB tpdm. + + Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB trigger type to false + 1 : Set the DSB trigger type to true + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger timestamp of DSB tpdm. Read the + trigger timestamp of DSB tpdm. + + Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB trigger type to false + 1 : Set the DSB trigger type to true diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 2e64cfd..14f4352 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,19 @@
DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm");
+static umode_t tpdm_dsb_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + if (drvdata) + if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB)) + return attr->mode; + + return 0; +} + static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) { if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { @@ -239,8 +252,90 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, };
+static ssize_t dsb_trig_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->trig_type); +} + +/* + * Trigger type (boolean): + * false - Disable trigger type. + * true - Enable trigger type. + */ +static ssize_t dsb_trig_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); + if (val) + drvdata->dsb->trig_type = true; + else + drvdata->dsb->trig_type = false; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_type); + +static ssize_t dsb_trig_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->trig_ts); +} + +/* + * Trigger timestamp (boolean): + * false - Disable trigger timestamp. + * true - Enable trigger timestamp. + */ +static ssize_t dsb_trig_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); + if (val) + drvdata->dsb->trig_ts = true; + else + drvdata->dsb->trig_ts = false; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_ts); + +static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_trig_ts.attr, + &dev_attr_dsb_trig_type.attr, + NULL, +}; + +static struct attribute_group tpdm_dsb_attr_grp = { + .attrs = tpdm_dsb_attrs, + .is_visible = tpdm_dsb_is_visible, +}; + static const struct attribute_group *tpdm_attr_grps[] = { &tpdm_attr_grp, + &tpdm_dsb_attr_grp, NULL, };
On 27/04/2023 10:00, Tao Zhang wrote:
The nodes are needed to set or show the trigger timestamp and trigger type. This change is to add these nodes to achieve these function.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 24 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 95 ++++++++++++++++++++++ 2 files changed, 119 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 686bdde..77e67f2 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -21,3 +21,27 @@ Description: Accepts only one value - 1. 1 : Reset the dataset of the tpdm
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type +Date: March 2023 +KernelVersion 6.3
This would need updating. We are not sure if this can make it to 6.5, with dependency on James' series. Fix this with 6.5 here and we can take a shot.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the trigger type of DSB tpdm. Read the trigger
type of DSB tpdm.
Accepts only one of the 2 values - 0 or 1.
0 : Set the DSB trigger type to false
1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts +Date: March 2023 +KernelVersion 6.3
Same here
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the trigger timestamp of DSB tpdm. Read the
trigger timestamp of DSB tpdm.
Accepts only one of the 2 values - 0 or 1.
0 : Set the DSB trigger type to false
1 : Set the DSB trigger type to true
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 2e64cfd..14f4352 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,19 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static umode_t tpdm_dsb_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
minor nit: alignment ?
+{
- struct device *dev = kobj_to_dev(kobj);
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- if (drvdata)
if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB))
return attr->mode;
Duplicate check for drvdata ?
if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB)) return attr->mode;
- return 0;
+}
- static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) { if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
@@ -239,8 +252,90 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_trig_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->trig_type);
+}
+/*
- Trigger type (boolean):
- false - Disable trigger type.
- true - Enable trigger type.
- */
+static ssize_t dsb_trig_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);
- if (val)
drvdata->dsb->trig_type = true;
- else
drvdata->dsb->trig_type = false;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_trig_type);
+static ssize_t dsb_trig_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->trig_ts);
+}
+/*
- Trigger timestamp (boolean):
- false - Disable trigger timestamp.
- true - Enable trigger timestamp.
- */
+static ssize_t dsb_trig_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);
- if (val)
drvdata->dsb->trig_ts = true;
- else
drvdata->dsb->trig_ts = false;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_trig_ts);
+static struct attribute *tpdm_dsb_attrs[] = {
- &dev_attr_dsb_trig_ts.attr,
- &dev_attr_dsb_trig_type.attr,
- NULL,
+};
+static struct attribute_group tpdm_dsb_attr_grp = {
- .attrs = tpdm_dsb_attrs,
- .is_visible = tpdm_dsb_is_visible,
+};
- static const struct attribute_group *tpdm_attr_grps[] = { &tpdm_attr_grp,
- &tpdm_dsb_attr_grp, NULL, };
Rest looks fine to me
Suzuki
On 6/1/2023 5:05 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
The nodes are needed to set or show the trigger timestamp and trigger type. This change is to add these nodes to achieve these function.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 24 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 95 ++++++++++++++++++++++ 2 files changed, 119 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 686bdde..77e67f2 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -21,3 +21,27 @@ Description: Accepts only one value - 1. 1 : Reset the dataset of the tpdm
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type +Date: March 2023 +KernelVersion 6.3
This would need updating. We are not sure if this can make it to 6.5, with dependency on James' series. Fix this with 6.5 here and we can take a shot.
Sure, I will update this in the next patch series.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger type of DSB tpdm. Read the trigger + type of DSB tpdm.
+ Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB trigger type to false + 1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts +Date: March 2023 +KernelVersion 6.3
Same here
Sure, I will update this in the next patch series.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger timestamp of DSB tpdm. Read the + trigger timestamp of DSB tpdm.
+ Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB trigger type to false + 1 : Set the DSB trigger type to true diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 2e64cfd..14f4352 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,19 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static umode_t tpdm_dsb_is_visible(struct kobject *kobj, + struct attribute *attr, int n)
minor nit: alignment ?
Sure, I will update this in the next patch series.
+{ + struct device *dev = kobj_to_dev(kobj); + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ if (drvdata) + if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB)) + return attr->mode;
Duplicate check for drvdata ?
if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB)) return attr->mode;
Don't need double check here, I will change this in the next patch series.
Best,
Tao
+ return 0; +}
static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) { if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { @@ -239,8 +252,90 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_trig_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->trig_type); +}
+/*
- Trigger type (boolean):
- false - Disable trigger type.
- true - Enable trigger type.
- */
+static ssize_t dsb_trig_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); + if (val) + drvdata->dsb->trig_type = true; + else + drvdata->dsb->trig_type = false; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_type);
+static ssize_t dsb_trig_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->trig_ts); +}
+/*
- Trigger timestamp (boolean):
- false - Disable trigger timestamp.
- true - Enable trigger timestamp.
- */
+static ssize_t dsb_trig_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); + if (val) + drvdata->dsb->trig_ts = true; + else + drvdata->dsb->trig_ts = false; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_ts);
+static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_trig_ts.attr, + &dev_attr_dsb_trig_type.attr, + NULL, +};
+static struct attribute_group tpdm_dsb_attr_grp = { + .attrs = tpdm_dsb_attrs, + .is_visible = tpdm_dsb_is_visible, +};
static const struct attribute_group *tpdm_attr_grps[] = { &tpdm_attr_grp, + &tpdm_dsb_attr_grp, NULL, };
Rest looks fine to me
Suzuki
Add node to set and show programming mode for TPDM DSB subunit. Once the DSB programming mode is set, it will be written to the register DSB_CR.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++ 3 files changed, 93 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 77e67f2..348e167 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -45,3 +45,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB trigger type to false 1 : Set the DSB trigger type to true + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the mode of DSB tpdm. Read the mode of DSB + tpdm. + + Accepts the value needs to be greater than 0. What data + bits do is listed below. + Bit[0:1] : Test mode control bit for choosing the inputs. + 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. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 14f4352..1bacaa5 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4,6 +4,7 @@ */
#include <linux/amba/bus.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/coresight.h> #include <linux/coresight-pmu.h> @@ -43,6 +44,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) } }
+static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode; + + mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode); + *val &= ~TPDM_DSB_TEST_MODE; + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode); +} + +static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode; + + mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode); + *val &= ~TPDM_DSB_HPSEL; + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode); +} + +static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF) + *val |= TPDM_DSB_CR_MODE; + else + *val &= ~TPDM_DSB_CR_MODE; +} + static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) { if (drvdata->dsb->trig_type) @@ -64,6 +91,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set the test accurate mode */ + set_dsb_test_mode(drvdata, &val); + /* Set the byte lane for high-performance mode */ + set_dsb_hpsel_mode(drvdata, &val); + /* Set the performance mode */ + set_dsb_perf_mode(drvdata, &val); /* Set trigger type */ set_trigger_type(drvdata, &val); /* Set the enable bit of DSB control register to 1 */ @@ -252,6 +285,34 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, };
+static ssize_t dsb_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%lx\n", + (unsigned long)drvdata->dsb->mode); +} + +static ssize_t dsb_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if ((kstrtoul(buf, 0, &val)) || val < 0) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->mode = val & TPDM_MODE_ALL; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_mode); + static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -323,6 +384,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev, static DEVICE_ATTR_RW(dsb_trig_ts);
static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_mode.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 68f33bd..79df07e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -15,11 +15,25 @@
/* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit perfmance mode */ +#define TPDM_DSB_CR_MODE BIT(1) /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12) + /* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
+/* DSB programming modes */ +/* Test mode control bit*/ +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0)) +/* Perforceman mode */ +#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_MODE_ALL (0xFFFFFFF) +#define TPDM_DSB_TEST_MODE GENMASK(10, 9) +#define TPDM_DSB_HPSEL GENMASK(6, 2) + /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) #define TPDM_ITCNTRL (0xF00) @@ -48,10 +62,12 @@
/** * struct dsb_dataset - specifics associated to dsb dataset + * @mode: DSB programming mode * @trig_ts: Enable/Disable trigger timestamp. * @trig_type: Enable/Disable trigger type. */ struct dsb_dataset { + u32 mode; bool trig_ts; bool trig_type; };
On 27/04/2023 10:00, Tao Zhang wrote:
Add node to set and show programming mode for TPDM DSB subunit. Once the DSB programming mode is set, it will be written to the register DSB_CR.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++ 3 files changed, 93 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 77e67f2..348e167 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -45,3 +45,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB trigger type to false 1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the mode of DSB tpdm. Read the mode of DSB
tpdm.
Accepts the value needs to be greater than 0. What data
bits do is listed below.
Bit[0:1] : Test mode control bit for choosing the inputs.
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.
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 14f4352..1bacaa5 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4,6 +4,7 @@ */ #include <linux/amba/bus.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/coresight.h> #include <linux/coresight-pmu.h> @@ -43,6 +44,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) } } +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val) +{
- u32 mode;
- mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode);
- *val &= ~TPDM_DSB_TEST_MODE;
- *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode);
+}
+static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val) +{
- u32 mode;
- mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
- *val &= ~TPDM_DSB_HPSEL;
- *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode);
+}
+static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) +{
- if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
*val |= TPDM_DSB_CR_MODE;
- else
*val &= ~TPDM_DSB_CR_MODE;
+}
- static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) { if (drvdata->dsb->trig_type)
@@ -64,6 +91,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
- /* Set the test accurate mode */
- set_dsb_test_mode(drvdata, &val);
- /* Set the byte lane for high-performance mode */
- set_dsb_hpsel_mode(drvdata, &val);
- /* Set the performance mode */
- set_dsb_perf_mode(drvdata, &val); /* Set trigger type */ set_trigger_type(drvdata, &val); /* Set the enable bit of DSB control register to 1 */
@@ -252,6 +285,34 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%lx\n",
(unsigned long)drvdata->dsb->mode);
+}
+static ssize_t dsb_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if ((kstrtoul(buf, 0, &val)) || val < 0)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->mode = val & TPDM_MODE_ALL;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_mode);
- static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) {
@@ -323,6 +384,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev, static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = {
- &dev_attr_dsb_mode.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 68f33bd..79df07e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -15,11 +15,25 @@ /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit perfmance mode */ +#define TPDM_DSB_CR_MODE BIT(1) /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
- /* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1)
+/* DSB programming modes */ +/* Test mode control bit*/ +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0)) +/* Perforceman mode */
minor nit: typo ^^
+#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_MODE_ALL (0xFFFFFFF)
GENMASK(27, 0) ?
Also, why do we cover bits 27-0 ?
Suzuki
On 6/1/2023 5:23 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
Add node to set and show programming mode for TPDM DSB subunit. Once the DSB programming mode is set, it will be written to the register DSB_CR.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++ 3 files changed, 93 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 77e67f2..348e167 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -45,3 +45,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB trigger type to false 1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the mode of DSB tpdm. Read the mode of DSB + tpdm.
+ Accepts the value needs to be greater than 0. What data + bits do is listed below. + Bit[0:1] : Test mode control bit for choosing the inputs. + 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. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 14f4352..1bacaa5 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4,6 +4,7 @@ */ #include <linux/amba/bus.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/coresight.h> #include <linux/coresight-pmu.h> @@ -43,6 +44,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) } } +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode); + *val &= ~TPDM_DSB_TEST_MODE; + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode); +}
+static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode); + *val &= ~TPDM_DSB_HPSEL; + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode); +}
+static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF) + *val |= TPDM_DSB_CR_MODE; + else + *val &= ~TPDM_DSB_CR_MODE; +}
static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) { if (drvdata->dsb->trig_type) @@ -64,6 +91,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set the test accurate mode */ + set_dsb_test_mode(drvdata, &val); + /* Set the byte lane for high-performance mode */ + set_dsb_hpsel_mode(drvdata, &val); + /* Set the performance mode */ + set_dsb_perf_mode(drvdata, &val); /* Set trigger type */ set_trigger_type(drvdata, &val); /* Set the enable bit of DSB control register to 1 */ @@ -252,6 +285,34 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%lx\n", + (unsigned long)drvdata->dsb->mode); +}
+static ssize_t dsb_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if ((kstrtoul(buf, 0, &val)) || val < 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->mode = val & TPDM_MODE_ALL; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_mode);
static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -323,6 +384,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev, static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_mode.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 68f33bd..79df07e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -15,11 +15,25 @@ /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit perfmance mode */ +#define TPDM_DSB_CR_MODE BIT(1) /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
/* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) +/* DSB programming modes */ +/* Test mode control bit*/ +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0)) +/* Perforceman mode */
minor nit: typo ^^
I will update this in the next patch series.
+#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_MODE_ALL (0xFFFFFFF)
GENMASK(27, 0) ?
Also, why do we cover bits 27-0 ?
The TPDM mode is only represented by [0:8]bits.
Can I replace it with "#define TPDM_DSB_MODE(val) (VAL & GENMASK(8, 0))"?
Best,
Tao
Suzuki
On 02/06/2023 03:58, Tao Zhang wrote:
On 6/1/2023 5:23 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
Add node to set and show programming mode for TPDM DSB subunit. Once the DSB programming mode is set, it will be written to the register DSB_CR.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++ 3 files changed, 93 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 77e67f2..348e167 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -45,3 +45,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB trigger type to false 1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the mode of DSB tpdm. Read the mode of DSB + tpdm.
+ Accepts the value needs to be greater than 0. What data + bits do is listed below. + Bit[0:1] : Test mode control bit for choosing the inputs. + 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. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 14f4352..1bacaa5 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4,6 +4,7 @@ */ #include <linux/amba/bus.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/coresight.h> #include <linux/coresight-pmu.h> @@ -43,6 +44,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) } } +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode); + *val &= ~TPDM_DSB_TEST_MODE; + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode); +}
+static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode); + *val &= ~TPDM_DSB_HPSEL; + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode); +}
+static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF) + *val |= TPDM_DSB_CR_MODE; + else + *val &= ~TPDM_DSB_CR_MODE; +}
static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) { if (drvdata->dsb->trig_type) @@ -64,6 +91,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set the test accurate mode */ + set_dsb_test_mode(drvdata, &val); + /* Set the byte lane for high-performance mode */ + set_dsb_hpsel_mode(drvdata, &val); + /* Set the performance mode */ + set_dsb_perf_mode(drvdata, &val); /* Set trigger type */ set_trigger_type(drvdata, &val); /* Set the enable bit of DSB control register to 1 */ @@ -252,6 +285,34 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%lx\n", + (unsigned long)drvdata->dsb->mode); +}
+static ssize_t dsb_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if ((kstrtoul(buf, 0, &val)) || val < 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->mode = val & TPDM_MODE_ALL; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_mode);
static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -323,6 +384,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev, static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_mode.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 68f33bd..79df07e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -15,11 +15,25 @@ /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit perfmance mode */ +#define TPDM_DSB_CR_MODE BIT(1) /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
/* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) +/* DSB programming modes */ +/* Test mode control bit*/ +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0)) +/* Perforceman mode */
minor nit: typo ^^
I will update this in the next patch series.
+#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_MODE_ALL (0xFFFFFFF)
GENMASK(27, 0) ?
Also, why do we cover bits 27-0 ?
The TPDM mode is only represented by [0:8]bits.
Can I replace it with "#define TPDM_DSB_MODE(val) (VAL & GENMASK(8, 0))"?
#define TPDM_DSB_MODE_MASK GENMASK(8, 0) ?
Suzuki
On 6/2/2023 4:25 PM, Suzuki K Poulose wrote:
On 02/06/2023 03:58, Tao Zhang wrote:
On 6/1/2023 5:23 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
Add node to set and show programming mode for TPDM DSB subunit. Once the DSB programming mode is set, it will be written to the register DSB_CR.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 62 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++++++ 3 files changed, 93 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 77e67f2..348e167 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -45,3 +45,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB trigger type to false 1 : Set the DSB trigger type to true
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the mode of DSB tpdm. Read the mode of DSB + tpdm.
+ Accepts the value needs to be greater than 0. What data + bits do is listed below. + Bit[0:1] : Test mode control bit for choosing the inputs. + 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. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 14f4352..1bacaa5 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -4,6 +4,7 @@ */ #include <linux/amba/bus.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/coresight.h> #include <linux/coresight-pmu.h> @@ -43,6 +44,32 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) } } +static void set_dsb_test_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode); + *val &= ~TPDM_DSB_TEST_MODE; + *val |= FIELD_PREP(TPDM_DSB_TEST_MODE, mode); +}
+static void set_dsb_hpsel_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + u32 mode;
+ mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode); + *val &= ~TPDM_DSB_HPSEL; + *val |= FIELD_PREP(TPDM_DSB_HPSEL, mode); +}
+static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) +{ + if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF) + *val |= TPDM_DSB_CR_MODE; + else + *val &= ~TPDM_DSB_CR_MODE; +}
static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) { if (drvdata->dsb->trig_type) @@ -64,6 +91,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); val = readl_relaxed(drvdata->base + TPDM_DSB_CR); + /* Set the test accurate mode */ + set_dsb_test_mode(drvdata, &val); + /* Set the byte lane for high-performance mode */ + set_dsb_hpsel_mode(drvdata, &val); + /* Set the performance mode */ + set_dsb_perf_mode(drvdata, &val); /* Set trigger type */ set_trigger_type(drvdata, &val); /* Set the enable bit of DSB control register to 1 */ @@ -252,6 +285,34 @@ static struct attribute_group tpdm_attr_grp = { .attrs = tpdm_attrs, }; +static ssize_t dsb_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%lx\n", + (unsigned long)drvdata->dsb->mode); +}
+static ssize_t dsb_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if ((kstrtoul(buf, 0, &val)) || val < 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->mode = val & TPDM_MODE_ALL; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_mode);
static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -323,6 +384,7 @@ static ssize_t dsb_trig_ts_store(struct device *dev, static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { + &dev_attr_dsb_mode.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 68f33bd..79df07e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -15,11 +15,25 @@ /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) +/* Enable bit for DSB subunit perfmance mode */ +#define TPDM_DSB_CR_MODE BIT(1) /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
/* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) +/* DSB programming modes */ +/* Test mode control bit*/ +#define TPDM_DSB_MODE_TEST(val) (val & GENMASK(1, 0)) +/* Perforceman mode */
minor nit: typo ^^
I will update this in the next patch series.
+#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_MODE_ALL (0xFFFFFFF)
GENMASK(27, 0) ?
Also, why do we cover bits 27-0 ?
The TPDM mode is only represented by [0:8]bits.
Can I replace it with "#define TPDM_DSB_MODE(val) (VAL & GENMASK(8, 0))"?
#define TPDM_DSB_MODE_MASK GENMASK(8, 0) ?
Sure, I will change it in the next patch series.
Best,
Tao
Suzuki _______________________________________________ CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM. + + Expected format is the following: + <integer1> <integer2> <integer3> + + Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM. + + Expected format is the following: + <integer1> <integer2> <integer3> + + Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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 */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode);
+static ssize_t dsb_edge_ctrl_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +} + +/* + * value 1: Start EDCR register number + * value 2: End EDCR register number + * value 3: The value need to be written + * 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. So the starting number(value 1) and ending number(value 2) + * cannot be greater than 256, and value 1 should be less than value 2. + * The following values are the rage of value 3. + * 0 - Rising edge detection + * 1 - Falling edge detection + * 2 - Rising and falling edge detection (toggle detection) + */ +static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift; + int i, reg; + + if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) || + (start > end) || (edge_ctrl > 0x2)) + return -EPERM; + + spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(i); + mask = EDCR_TO_WORD_MASK(i); + val = drvdata->dsb->edge_ctrl[reg]; + edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i); + bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32); + drvdata->dsb->edge_ctrl[reg] = val; + } + spin_unlock(&drvdata->spinlock); + + return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl); + +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; + int i; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +} + +/* + * value 1: Start EDCMR register number + * value 2: End EDCMR register number + * value 3: The value need to be written + */ +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 start, end, val; + u32 set; + int i, reg; + + if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) + || (start > end) || (val & ~1UL)) + return -EPERM; + + spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(i); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCR_TO_WORD_SHIFT(i)); + else + set &= ~BIT(EDCR_TO_WORD_SHIFT(i)); + 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) { @@ -385,6 +516,8 @@ static DEVICE_ATTR_RW(dsb_trig_ts);
static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl.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 79df07e..f25dcdec 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,15 @@ #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 +71,24 @@ #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 + * @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[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR]; bool trig_ts; bool trig_type; };
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write a set of the edge control registers of the DSB
in TPDM.
Expected format is the following:
<integer1> <integer2> <integer3>
Where:
<integer1> : Start EDCR register number
<integer2> : End EDCR register number
<integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write a set of the edge control mask registers of the
DSB in TPDM.
Expected format is the following:
<integer1> <integer2> <integer3>
Where:
<integer1> : Start EDCMR register number
<integer2> : End EDCMR register number
<integer3> : The value need to be written
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
size += sysfs_emit_at(buf, size,
"Index:0x%x Val:0x%x\n", i,
drvdata->dsb->edge_ctrl[i]);
It may be safe, but please add a check to make sure that we don't overflow. At least bail out when we hit a return of 0, indicating reached the end of buffer.
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- value 1: Start EDCR register number
- value 2: End EDCR register number
- value 3: The value need to be written
- 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. So the starting number(value 1) and ending number(value 2)
- cannot be greater than 256, and value 1 should be less than value 2.
- The following values are the rage of value 3.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift;
- int i, reg;
- if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
return -EINVAL;
- if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
(start > end) || (edge_ctrl > 0x2))
return -EPERM;
- spin_lock(&drvdata->spinlock);
- for (i = start; i <= end; i++) {
/*
* There are 2 bit per DSB Edge Control line.
* Thus we have 16 lines in a 32bit word.
*/
reg = EDCR_TO_WORD_IDX(i);
mask = EDCR_TO_WORD_MASK(i);
val = drvdata->dsb->edge_ctrl[reg];
edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i);
bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32);
Could we simply do :
reg &= ~mask; reg |= FIELD_PREP(mask, edge_ctrl);
drvdata->dsb->edge_ctrl[reg] = val;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl);
+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;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
size += sysfs_emit_at(buf, size,
"Index:0x%x Val:0x%x\n", i,
drvdata->dsb->edge_ctrl_mask[i]);
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- value 1: Start EDCMR register number
- value 2: End EDCMR register number
- value 3: The value need to be written
- */
+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 start, end, val;
- u32 set;
- int i, reg;
- if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
return -EINVAL;
- if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES)
|| (start > end) || (val & ~1UL))
return -EPERM;
- spin_lock(&drvdata->spinlock);
- for (i = start; i <= end; i++) {
/*
* There is 1 bit per DSB Edge Control Mark line.
* Thus we have 32 lines in a 32bit word.
*/
reg = EDCMR_TO_WORD_IDX(i);
set = drvdata->dsb->edge_ctrl_mask[reg];
if (val)
set |= BIT(EDCR_TO_WORD_SHIFT(i));
else
set &= ~BIT(EDCR_TO_WORD_SHIFT(i));
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) {
@@ -385,6 +516,8 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr,
- &dev_attr_dsb_edge_ctrl.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 79df07e..f25dcdec 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,15 @@ #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)
minor nit: add a new line here please
+#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 +71,24 @@ #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
- @edge_ctrl: Save value for edge control
*/ struct dsb_dataset { u32 mode;
- @edge_ctrl_mask: Save value for edge control mask
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- u32 edge_ctrl[TPDM_DSB_MAX_EDCR];
- u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
minor nit: Please align it with the fields below.
bool trig_ts; bool trig_type; };
Suzuki
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Currently we don't have a good way to know the quantity of EDCR/EDCMR registers for DSB TPDMs.
The only way we can think of is to set it in device tree manually.
Do you have other suggestion for this?
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl[i]);
It may be safe, but please add a check to make sure that we don't overflow. At least bail out when we hit a return of 0, indicating reached the end of buffer.
Can I add the following check to replace the current code??
int ret = 0;
for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
ret = sysfs_emit_at(buf, size, "Index:0x%x Val:0x%x\n", i, drvdata->dsb->edge_ctrl[i]);
if (!ret) {
dev_warn(drvdata->dev, "The buffer has been overflowed\n");
spin_unlock(&drvdata->spinlock);
return size;
} else
size += ret;
}
+ } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCR register number
- value 2: End EDCR register number
- value 3: The value need to be written
- 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. So the starting number(value 1) and ending
number(value 2)
- cannot be greater than 256, and value 1 should be less than value 2.
- The following values are the rage of value 3.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) || + (start > end) || (edge_ctrl > 0x2)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(i); + mask = EDCR_TO_WORD_MASK(i); + val = drvdata->dsb->edge_ctrl[reg];
+ edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i); + bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32);
Could we simply do :
reg &= ~mask; reg |= FIELD_PREP(mask, edge_ctrl);
Perhaps "FIELD_PREP" cannot be used here since "mask" must be constant in this macro.
But in our code, the variable "mask" is not constant.
- drvdata->dsb->edge_ctrl[reg] = val;
+ } + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl);
+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; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCMR register number
- value 2: End EDCMR register number
- value 3: The value need to be written
- */
+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 start, end, val; + u32 set; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) + || (start > end) || (val & ~1UL)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(i); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCR_TO_WORD_SHIFT(i)); + else + set &= ~BIT(EDCR_TO_WORD_SHIFT(i)); + 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) { @@ -385,6 +516,8 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl.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 79df07e..f25dcdec 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,15 @@ #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)
minor nit: add a new line here please
Sure, I will update this in the next patch series.
+#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 +71,24 @@ #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
- @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[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
minor nit: Please align it with the fields below.
Sure, I will update this in the next patch series.
Best,
Tao
bool trig_ts; bool trig_type; };
Suzuki
On 02/06/2023 09:21, Tao Zhang wrote:
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Currently we don't have a good way to know the quantity of EDCR/EDCMR registers for DSB TPDMs.
The only way we can think of is to set it in device tree manually.
Do you have other suggestion for this?
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl[i]);
It may be safe, but please add a check to make sure that we don't overflow. At least bail out when we hit a return of 0, indicating reached the end of buffer.
Can I add the following check to replace the current code??
int ret = 0;
for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
ret = sysfs_emit_at(buf, size, "Index:0x%x Val:0x%x\n", i, drvdata->dsb->edge_ctrl[i]);
if (!ret) {
dev_warn(drvdata->dev, "The buffer has been overflowed\n");
You don't need this, it already triggers a WARN() in sysfs_emit_at(). So you could do:
for (....) { unsigned long bytes = sysfs_emit_at(buf, size, ....); if (bytes <= 0) break; size += bytes; }
spin_unlock(&drvdata->spinlock);
return size;
} else
size += ret;
}
+ } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCR register number
- value 2: End EDCR register number
- value 3: The value need to be written
- 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. So the starting number(value 1) and ending
number(value 2)
- cannot be greater than 256, and value 1 should be less than value 2.
- The following values are the rage of value 3.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) || + (start > end) || (edge_ctrl > 0x2)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(i); + mask = EDCR_TO_WORD_MASK(i); + val = drvdata->dsb->edge_ctrl[reg];
+ edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i); + bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32);
Could we simply do :
reg &= ~mask; reg |= FIELD_PREP(mask, edge_ctrl);
Perhaps "FIELD_PREP" cannot be used here since "mask" must be constant in this macro.
Ah, you are right. Sorry about that.
But in our code, the variable "mask" is not constant.
Still I think using the bitmap_replace is an overkill. We could simply do: val &= ~mask; val |= EDCR_TO_WORD_VAL(edge_ctrl, i);
Suzuki
- drvdata->dsb->edge_ctrl[reg] = val;
+ } + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl);
+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; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCMR register number
- value 2: End EDCMR register number
- value 3: The value need to be written
- */
+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 start, end, val; + u32 set; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) + || (start > end) || (val & ~1UL)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(i); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCR_TO_WORD_SHIFT(i)); + else + set &= ~BIT(EDCR_TO_WORD_SHIFT(i)); + 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) { @@ -385,6 +516,8 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl.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 79df07e..f25dcdec 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,15 @@ #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)
minor nit: add a new line here please
Sure, I will update this in the next patch series.
+#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 +71,24 @@ #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
- @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[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
minor nit: Please align it with the fields below.
Sure, I will update this in the next patch series.
Best,
Tao
bool trig_ts; bool trig_type; };
Suzuki
On 02/06/2023 09:45, Suzuki K Poulose wrote:
On 02/06/2023 09:21, Tao Zhang wrote:
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Does the TRM for the component say so ? Or is it by luck ? If the spec says it is RAZ/WriteIgnore, then we could keep the code as it is, with a comment. Otherwise, we could add a DT property. So please get this clarified with the H/W designers.
Suzuki
On 6/2/2023 5:00 PM, Suzuki K Poulose wrote:
On 02/06/2023 09:45, Suzuki K Poulose wrote:
On 02/06/2023 09:21, Tao Zhang wrote:
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Does the TRM for the component say so ? Or is it by luck ? If the spec says it is RAZ/WriteIgnore, then we could keep the code as it is, with a comment. Otherwise, we could add a DT property. So please get this clarified with the H/W designers.
Confirmed with H/W designers, these addresses are reserved for the maximum
quantity of EDCR/EDCMR registers. It is safe to write data to them and it will not
impact anything.
Best,
Tao
Suzuki
On 6/2/2023 4:45 PM, Suzuki K Poulose wrote:
On 02/06/2023 09:21, Tao Zhang wrote:
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Currently we don't have a good way to know the quantity of EDCR/EDCMR registers for DSB TPDMs.
The only way we can think of is to set it in device tree manually.
Do you have other suggestion for this?
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl[i]);
It may be safe, but please add a check to make sure that we don't overflow. At least bail out when we hit a return of 0, indicating reached the end of buffer.
Can I add the following check to replace the current code??
int ret = 0;
for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
ret = sysfs_emit_at(buf, size, "Index:0x%x Val:0x%x\n", i, drvdata->dsb->edge_ctrl[i]);
if (!ret) {
dev_warn(drvdata->dev, "The buffer has been overflowed\n");
You don't need this, it already triggers a WARN() in sysfs_emit_at(). So you could do:
for (....) { unsigned long bytes = sysfs_emit_at(buf, size, ....);
if (bytes <= 0) break; size += bytes; }
Sure, I will update in the next patch series.
spin_unlock(&drvdata->spinlock);
return size;
} else
size += ret;
}
+ } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCR register number
- value 2: End EDCR register number
- value 3: The value need to be written
- 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. So the starting number(value 1) and ending
number(value 2)
- cannot be greater than 256, and value 1 should be less than
value 2.
- The following values are the rage of value 3.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) || + (start > end) || (edge_ctrl > 0x2)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(i); + mask = EDCR_TO_WORD_MASK(i); + val = drvdata->dsb->edge_ctrl[reg];
+ edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i); + bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32);
Could we simply do :
reg &= ~mask; reg |= FIELD_PREP(mask, edge_ctrl);
Perhaps "FIELD_PREP" cannot be used here since "mask" must be constant in this macro.
Ah, you are right. Sorry about that.
But in our code, the variable "mask" is not constant.
Still I think using the bitmap_replace is an overkill. We could simply do: val &= ~mask; val |= EDCR_TO_WORD_VAL(edge_ctrl, i);
Sure, I will update in the next patch series.
Best,
Tao
Suzuki
- drvdata->dsb->edge_ctrl[reg] = val;
+ } + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl);
+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; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCMR register number
- value 2: End EDCMR register number
- value 3: The value need to be written
- */
+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 start, end, val; + u32 set; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) + || (start > end) || (val & ~1UL)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(i); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCR_TO_WORD_SHIFT(i)); + else + set &= ~BIT(EDCR_TO_WORD_SHIFT(i)); + 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) { @@ -385,6 +516,8 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl.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 79df07e..f25dcdec 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,15 @@ #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)
minor nit: add a new line here please
Sure, I will update this in the next patch series.
+#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 +71,24 @@ #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
- @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[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
minor nit: Please align it with the fields below.
Sure, I will update this in the next patch series.
Best,
Tao
bool trig_ts; bool trig_type; };
Suzuki
On 02/06/2023 15:38, Tao Zhang wrote:
On 6/2/2023 4:45 PM, Suzuki K Poulose wrote:
On 02/06/2023 09:21, Tao Zhang wrote:
On 6/1/2023 8:14 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 32 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 135 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 21 ++++ 3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 348e167..a57f000 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,35 @@ 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 +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control registers of the DSB + in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCR register number + <integer2> : End EDCR register number + <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write a set of the edge control mask registers of the + DSB in TPDM.
+ Expected format is the following: + <integer1> <integer2> <integer3>
+ Where: + <integer1> : Start EDCMR register number + <integer2> : End EDCMR register number + <integer3> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1bacaa5..a40e458 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,7 +80,14 @@ static void set_trigger_type(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));
Do all TPDM DSBs have MAX_EDCR registers ? Or some have less than that ? If it is latter, do we need special care to avoid writing to inexistent registers ?
You are right, not all DSB TPDMs have MAX_EDCR registers. In our design, the inexistent register addresses
are not occupied and safe for accessing.
Currently we don't have a good way to know the quantity of EDCR/EDCMR registers for DSB TPDMs.
The only way we can think of is to set it in device tree manually.
Do you have other suggestion for this?
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -313,6 +320,130 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + size += sysfs_emit_at(buf, size, + "Index:0x%x Val:0x%x\n", i, + drvdata->dsb->edge_ctrl[i]);
It may be safe, but please add a check to make sure that we don't overflow. At least bail out when we hit a return of 0, indicating reached the end of buffer.
Can I add the following check to replace the current code??
int ret = 0;
for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
ret = sysfs_emit_at(buf, size, "Index:0x%x Val:0x%x\n", i, drvdata->dsb->edge_ctrl[i]);
if (!ret) {
dev_warn(drvdata->dev, "The buffer has been overflowed\n");
You don't need this, it already triggers a WARN() in sysfs_emit_at(). So you could do:
for (....) { unsigned long bytes = sysfs_emit_at(buf, size, ....);
if (bytes <= 0) break; size += bytes; }
Sure, I will update in the next patch series.
spin_unlock(&drvdata->spinlock);
return size;
} else
size += ret;
}
+ } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Start EDCR register number
- value 2: End EDCR register number
- value 3: The value need to be written
- 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. So the starting number(value 1) and ending
number(value 2)
- cannot be greater than 256, and value 1 should be less than
value 2.
- The following values are the rage of value 3.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_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, start, end, edge_ctrl, edge_ctrl_shift; + int i, reg;
+ if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3) + return -EINVAL; + if ((start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) || + (start > end) || (edge_ctrl > 0x2)) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + for (i = start; i <= end; i++) { + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(i); + mask = EDCR_TO_WORD_MASK(i); + val = drvdata->dsb->edge_ctrl[reg];
+ edge_ctrl_shift = EDCR_TO_WORD_VAL(edge_ctrl, i); + bitmap_replace(&val, &val, &edge_ctrl_shift, &mask, 32);
Could we simply do :
reg &= ~mask; reg |= FIELD_PREP(mask, edge_ctrl);
Perhaps "FIELD_PREP" cannot be used here since "mask" must be constant in this macro.
Ah, you are right. Sorry about that.
But in our code, the variable "mask" is not constant.
Still I think using the bitmap_replace is an overkill. We could simply do: val &= ~mask; val |= EDCR_TO_WORD_VAL(edge_ctrl, i);
Since we don't need mask any longer we could even do :
val &= ~EDCR_TO_WORD_MASK(i); val |= EDCR_TO_WORD_VAL(edge_ctrl, i);
Suzuki
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 quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 30 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 85 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 8 ++ 3 files changed, 123 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a57f000..c04c735 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -92,3 +92,33 @@ Description: <integer1> : Start EDCMR register number <integer2> : End EDCMR register number <integer3> : The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger pattern value of DSB tpdm. + Read the trigger pattern value of DSB tpdm. + + Expected format is the following: + <integer1> <integer2> + + Where: + <integer1> : Index number of XPR register, the range is 0 to 7 + <integer2> : The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger pattern mask of DSB tpdm. + Read the trigger pattern mask of DSB tpdm. + + Expected format is the following: + <integer1> <integer2> + + Where: + <integer1> : Index number of XPMR register, the range is 0 to 7 + <integer2> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index a40e458..9387bdf 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -89,6 +89,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_val[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) @@ -444,6 +451,82 @@ 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_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->trig_patt_val[i]); + } + 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 index, val; + + if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt_val[index] = 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; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->trig_patt_mask[i]); + } + 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 index, val; + + if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt_mask[index] = 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) { @@ -518,6 +601,8 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, &dev_attr_dsb_edge_ctrl_mask.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 f25dcdec..55c620f 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))
@@ -76,12 +78,16 @@ #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: Save value for edge control * @edge_ctrl_mask: Save value for edge control mask + * @trig_patt_val: 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. */ @@ -89,6 +95,8 @@ struct dsb_dataset { u32 mode; u32 edge_ctrl[TPDM_DSB_MAX_EDCR]; u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR]; + u32 trig_patt_val[TPDM_DSB_MAX_PATT]; + u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts; bool trig_type; };
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 30 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 85 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 8 ++ 3 files changed, 123 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a57f000..c04c735 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -92,3 +92,33 @@ Description: <integer1> : Start EDCMR register number <integer2> : End EDCMR register number <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the trigger pattern value of DSB tpdm.
Read the trigger pattern value of DSB tpdm.
Expected format is the following:
<integer1> <integer2>
Where:
<integer1> : Index number of XPR register, the range is 0 to 7
<integer2> : The value need to be written
I assume the values written to the registers are not special and doesn't have meaning and thus need not be documented ?
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask +Date: March 2023 +KernelVersion 6.3
Same as the previous one, 6.5 please
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the trigger pattern mask of DSB tpdm.
Read the trigger pattern mask of DSB tpdm.
Expected format is the following:
<integer1> <integer2>
Where:
<integer1> : Index number of XPMR register, the range is 0 to 7
<integer2> : The value need to be written
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index a40e458..9387bdf 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -89,6 +89,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++) {
Same as the previous, can we safely assume that write to these registers won't trigger an Error if not impelemented ?
writel_relaxed(drvdata->dsb->trig_patt_val[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)
@@ -444,6 +451,82 @@ 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_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
size += sysfs_emit_at(buf, size,
"Index: 0x%x Value: 0x%x\n", i,
drvdata->dsb->trig_patt_val[i]);
Please detect the return of 0 and break. Same below.
- }
- 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 index, val;
- if (sscanf(buf, "%lx %lx", &index, &val) != 2)
return -EINVAL;
- if (index >= TPDM_DSB_MAX_PATT)
return -EPERM;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->trig_patt_val[index] = 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;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
size += sysfs_emit_at(buf, size,
"Index: 0x%x Value: 0x%x\n", i,
drvdata->dsb->trig_patt_mask[i]);
- }
- spin_unlock(&drvdata->spinlock);
- return size;
Suzuki
On 6/1/2023 9:28 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 30 ++++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 85 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 8 ++ 3 files changed, 123 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a57f000..c04c735 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -92,3 +92,33 @@ Description: <integer1> : Start EDCMR register number <integer2> : End EDCMR register number <integer3> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger pattern value of DSB tpdm. + Read the trigger pattern value of DSB tpdm.
+ Expected format is the following: + <integer1> <integer2>
+ Where: + <integer1> : Index number of XPR register, the range is 0 to 7 + <integer2> : The value need to be written
I assume the values written to the registers are not special and doesn't have meaning and thus need not be documented ?
Sure, I will update this in the next patch series.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask +Date: March 2023 +KernelVersion 6.3
Same as the previous one, 6.5 please
Sure, I will update this in the next patch series.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the trigger pattern mask of DSB tpdm. + Read the trigger pattern mask of DSB tpdm.
+ Expected format is the following: + <integer1> <integer2>
+ Where: + <integer1> : Index number of XPMR register, the range is 0 to 7 + <integer2> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index a40e458..9387bdf 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -89,6 +89,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++) {
Same as the previous, can we safely assume that write to these registers won't trigger an Error if not impelemented ?
Yes, it won't trigger an error since these inexistent register's addresses are not occupied and safe
for being accessed.
- writel_relaxed(drvdata->dsb->trig_patt_val[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) @@ -444,6 +451,82 @@ 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_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + int i = 0;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->trig_patt_val[i]);
Please detect the return of 0 and break. Same below.
See my comments in patch #7 mail.
Best,
Tao
+ } + 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 index, val;
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt_val[index] = 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; + int i = 0;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->trig_patt_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size;
Suzuki
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 quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 48 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 182 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 14 ++ 3 files changed, 239 insertions(+), 5 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index c04c735..639b6fb8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -122,3 +122,51 @@ Description: Where: <integer1> : Index number of XPMR register, the range is 0 to 7 <integer2> : The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern value of DSB tpdm. Read + the pattern value of DSB tpdm. + + Accepts the following two values. + value 1: Index number of TPR register + value 2: The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern mask of DSB tpdm. Read + the pattern mask of DSB tpdm. + + Accepts the following two values. + value 1: Index number of TPMR register + value 2: The value need to be written + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern timestamp of DSB tpdm. Read + the pattern timestamp of DSB tpdm. + + Accepts only one of the 2 values - 0 or 1. + 0 : Disable DSB pattern timestamp. + 1 : Enable DSB pattern timestamp. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_type +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern type of DSB tpdm. Read + the pattern type of DSB tpdm. + + Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB pattern type to value. + 1 : Set the DSB pattern type to toggle. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 9387bdf..627de36 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -78,6 +78,27 @@ static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) *val &= ~TPDM_DSB_CR_TRIG_TYPE; }
+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; @@ -90,6 +111,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_val[i], drvdata->base + TPDM_DSB_XPR(i)); writel_relaxed(drvdata->dsb->trig_patt_mask[i], @@ -97,11 +122,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); @@ -451,6 +472,153 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+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; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->patt_val[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +} + +/* + * value 1: Index of TPR register + * value 2: Value need to be written + */ +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 index, val; + + if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_val[index] = 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; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->patt_mask[i]); + } + spin_unlock(&drvdata->spinlock); + return size; +} + +/* + * value 1: Index of TPMR register + * value 2: Value need to be written + */ +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 index, val; + + if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_mask[index] = 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); + if (val) + drvdata->dsb->patt_ts = true; + else + drvdata->dsb->patt_ts = false; + 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_val_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -601,6 +769,10 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, &dev_attr_dsb_edge_ctrl_mask.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_val.attr, &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 55c620f..9ad32a6 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,6 +92,10 @@ * @mode: DSB programming mode * @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 + * @patt_ts: Enable/Disable pattern timestamp + * @patt_type: Set pattern type * @trig_patt_val: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask * @trig_ts: Enable/Disable trigger timestamp. @@ -95,6 +105,10 @@ struct dsb_dataset { u32 mode; 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]; + bool patt_ts; + bool patt_type; u32 trig_patt_val[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts;
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 48 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 182 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 14 ++ 3 files changed, 239 insertions(+), 5 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index c04c735..639b6fb8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -122,3 +122,51 @@ Description: Where: <integer1> : Index number of XPMR register, the range is 0 to 7 <integer2> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val +Date: March 2023 +KernelVersion 6.3
Similar to the previous comments, please update this.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the pattern value of DSB tpdm. Read
the pattern value of DSB tpdm.
Accepts the following two values.
value 1: Index number of TPR register
value 2: The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the pattern mask of DSB tpdm. Read
the pattern mask of DSB tpdm.
Accepts the following two values.
value 1: Index number of TPMR register
value 2: The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the pattern timestamp of DSB tpdm. Read
the pattern timestamp of DSB tpdm.
Accepts only one of the 2 values - 0 or 1.
0 : Disable DSB pattern timestamp.
1 : Enable DSB pattern timestamp.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_type +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the pattern type of DSB tpdm. Read
the pattern type of DSB tpdm.
Accepts only one of the 2 values - 0 or 1.
0 : Set the DSB pattern type to value.
1 : Set the DSB pattern type to toggle.
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 9387bdf..627de36 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -78,6 +78,27 @@ static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) *val &= ~TPDM_DSB_CR_TRIG_TYPE; } +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;
@@ -90,6 +111,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],
writel_relaxed(drvdata->dsb->trig_patt_val[i], drvdata->base + TPDM_DSB_XPR(i)); writel_relaxed(drvdata->dsb->trig_patt_mask[i],drvdata->base + TPDM_DSB_TPMR(i));
@@ -97,11 +122,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); @@ -451,6 +472,153 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask); +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;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
size += sysfs_emit_at(buf, size,
"Index: 0x%x Value: 0x%x\n", i,
drvdata->dsb->patt_val[i]);
- }
Similarly here, please check for overflows and stop in case.
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- value 1: Index of TPR register
- value 2: Value need to be written
- */
+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 index, val;
- if (sscanf(buf, "%lx %lx", &index, &val) != 2)
return -EINVAL;
- if (index >= TPDM_DSB_MAX_PATT)
return -EPERM;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->patt_val[index] = 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;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
size += sysfs_emit_at(buf, size,
"Index: 0x%x Value: 0x%x\n", i,
drvdata->dsb->patt_mask[i]);
Same here
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- value 1: Index of TPMR register
- value 2: Value need to be written
- */
+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 index, val;
- if (sscanf(buf, "%lx %lx", &index, &val) != 2)
return -EINVAL;
- if (index >= TPDM_DSB_MAX_PATT)
return -EPERM;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->patt_mask[index] = 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)
minor nit: alignment ?
+{
- 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)
minor nit: Alignmnet
+{
- 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);
- if (val)
drvdata->dsb->patt_ts = true;
- else
drvdata->dsb->patt_ts = false;
ultra minor nit:
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_val_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -601,6 +769,10 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, &dev_attr_dsb_edge_ctrl_mask.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_val.attr, &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr,
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 55c620f..9ad32a6 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,6 +92,10 @@
- @mode: DSB programming mode
- @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
- @patt_ts: Enable/Disable pattern timestamp
- @patt_type: Set pattern type
- @trig_patt_val: Save value for trigger pattern
- @trig_patt_mask: Save value for trigger pattern mask
- @trig_ts: Enable/Disable trigger timestamp.
@@ -95,6 +105,10 @@ struct dsb_dataset { u32 mode; 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];
- bool patt_ts;
- bool patt_type;
minor nit: Alignment of the bool fields ?
Also, it may be good to move the bool fields together, for better packing of the structure.
u32 trig_patt_val[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts;
Suzuki
On 6/5/2023 6:19 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, 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 quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 48 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 182 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 14 ++ 3 files changed, 239 insertions(+), 5 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index c04c735..639b6fb8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -122,3 +122,51 @@ Description: Where: <integer1> : Index number of XPMR register, the range is 0 to 7 <integer2> : The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val +Date: March 2023 +KernelVersion 6.3
Similar to the previous comments, please update this.
Sure, I will update this in the next patch series.
+Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern value of DSB tpdm. Read + the pattern value of DSB tpdm.
+ Accepts the following two values. + value 1: Index number of TPR register + value 2: The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern mask of DSB tpdm. Read + the pattern mask of DSB tpdm.
+ Accepts the following two values. + value 1: Index number of TPMR register + value 2: The value need to be written
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern timestamp of DSB tpdm. Read + the pattern timestamp of DSB tpdm.
+ Accepts only one of the 2 values - 0 or 1. + 0 : Disable DSB pattern timestamp. + 1 : Enable DSB pattern timestamp.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_type +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the pattern type of DSB tpdm. Read + the pattern type of DSB tpdm.
+ Accepts only one of the 2 values - 0 or 1. + 0 : Set the DSB pattern type to value. + 1 : Set the DSB pattern type to toggle. diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 9387bdf..627de36 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -78,6 +78,27 @@ static void set_trigger_type(struct tpdm_drvdata *drvdata, u32 *val) *val &= ~TPDM_DSB_CR_TRIG_TYPE; } +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; @@ -90,6 +111,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_val[i], drvdata->base + TPDM_DSB_XPR(i)); writel_relaxed(drvdata->dsb->trig_patt_mask[i], @@ -97,11 +122,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); @@ -451,6 +472,153 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask); +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; + int i = 0;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->patt_val[i]); + }
Similarly here, please check for overflows and stop in case.
Sure, I will update this in the next patch series.
- spin_unlock(&drvdata->spinlock);
+ return size; +}
+/*
- value 1: Index of TPR register
- value 2: Value need to be written
- */
+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 index, val;
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_val[index] = 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; + int i = 0;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "Index: 0x%x Value: 0x%x\n", i, + drvdata->dsb->patt_mask[i]);
Same here
Sure, I will update this in the next patch series.
+ } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- value 1: Index of TPMR register
- value 2: Value need to be written
- */
+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 index, val;
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_mask[index] = 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)
minor nit: alignment ?
Is there a criteria for the alignment?
I edit the file by Notepad++, and seems like these lines have been aligned.
+{ + 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)
minor nit: Alignmnet
Same as my previous comment.
+{ + 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); + if (val) + drvdata->dsb->patt_ts = true; + else + drvdata->dsb->patt_ts = false;
ultra minor nit:
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_val_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -601,6 +769,10 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, &dev_attr_dsb_edge_ctrl_mask.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_val.attr, &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 55c620f..9ad32a6 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,6 +92,10 @@ * @mode: DSB programming mode * @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
- @patt_ts: Enable/Disable pattern timestamp
- @patt_type: Set pattern type
* @trig_patt_val: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask * @trig_ts: Enable/Disable trigger timestamp. @@ -95,6 +105,10 @@ struct dsb_dataset { u32 mode; 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]; + bool patt_ts; + bool patt_type;
minor nit: Alignment of the bool fields ?
Also, it may be good to move the bool fields together, for better packing of the structure.
Sure, I will update in the next patch series.
u32 trig_patt_val[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts;
Suzuki
Add property "qcom,dsb-msrs-num" to support DSB(Discrete Single Bit) MSR(mux select register) for TPDM. It specifies the number of MSR registers supported by the DSB TDPM.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml index 932c55b..cbd746d 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml @@ -52,6 +52,15 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 enum: [32, 64]
+ qcom,dsb-msrs-num: + description: + Specifies the number of DSB(Discrete Single Bit) MSR(mux select register) + registers supported by the monitor. If this property is not configured + or set to 0, it means this DSB TPDM doesn't support MSR. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 32 + clocks: maxItems: 1
Add the nodes for DSB subunit MSR(mux select register) support. The TPDM MSR (mux select register) interface is an optional interface and associated bank of registers per TPDM subunit. The intent of mux select registers is to control muxing structures driving the TPDM’s’ various subunit interfaces.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 53 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 3 ++ 3 files changed, 71 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 639b6fb8..f746f25 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -170,3 +170,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB pattern type to value. 1 : Set the DSB pattern type to toggle. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm. + + Expected format is the following: + <integer1> <integer2> + + Where: + <integer1> : Index number of MSR register + <integer2> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 627de36..5fe0bd5c 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -240,6 +240,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)), + GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } }
return 0; @@ -765,6 +773,50 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts);
+static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + ssize_t size = 0; + + if (drvdata->dsb->msr_num == 0) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + size += sysfs_emit_at(buf, size, + "%u 0x%x\n", i, drvdata->dsb->msr[i]); + } + spin_unlock(&drvdata->spinlock); + + return size; +} + +static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int num, val; + int nval; + + if (drvdata->dsb->msr_num == 0) + return -EINVAL; + + nval = sscanf(buf, "%u %x", &num, &val); + if ((nval != 2) || (num >= (drvdata->dsb->msr_num - 1))) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[num] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr); + static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, @@ -777,6 +829,7 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, + &dev_attr_dsb_msr.attr, NULL, };
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 9ad32a6..05e9f8e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -18,6 +18,7 @@ #define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4)) #define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) #define TPDM_DSB_EDCMR(n) (0x848 + (n * 4)) +#define TPDM_DSB_MSR(n) (0x980 + (n * 4))
/* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -113,6 +114,8 @@ struct dsb_dataset { u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts; bool trig_type; + u32 msr_num; + u32 *msr; };
/**
On 27/04/2023 10:00, Tao Zhang wrote:
Add the nodes for DSB subunit MSR(mux select register) support. The TPDM MSR (mux select register) interface is an optional interface and associated bank of registers per TPDM subunit. The intent of mux select registers is to control muxing structures driving the TPDM’s’ various subunit interfaces.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 53 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 3 ++ 3 files changed, 71 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 639b6fb8..f746f25 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -170,3 +170,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB pattern type to value. 1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the MSR(mux select register) of DSB tpdm. Read
the MSR(mux select register) of DSB tpdm.
Expected format is the following:
<integer1> <integer2>
Where:
<integer1> : Index number of MSR register
<integer2> : The value need to be written
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 627de36..5fe0bd5c 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -240,6 +240,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; }
if (!of_property_read_u32(drvdata->dev->of_node,
"qcom,dsb_msr_num", &drvdata->dsb->msr_num)) {
drvdata->dsb->msr = devm_kzalloc(drvdata->dev,
(drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
GFP_KERNEL);
if (!drvdata->dsb->msr)
return -ENOMEM;
}}
return 0; @@ -765,6 +773,50 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned int i;
- ssize_t size = 0;
- if (drvdata->dsb->msr_num == 0)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
Shouldn't this be "i < drvdata->dsb->msr_num" ?
size += sysfs_emit_at(buf, size,
"%u 0x%x\n", i, drvdata->dsb->msr[i]);
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_msr_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned int num, val;
- int nval;
- if (drvdata->dsb->msr_num == 0)
return -EINVAL;
- nval = sscanf(buf, "%u %x", &num, &val);
- if ((nval != 2) || (num >= (drvdata->dsb->msr_num - 1)))
(num >= drvdata->dsb->msr_num) ?
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->msr[num] = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_msr);
- static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr,
@@ -777,6 +829,7 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr,
- &dev_attr_dsb_msr.attr, NULL, };
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 9ad32a6..05e9f8e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -18,6 +18,7 @@ #define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4)) #define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) #define TPDM_DSB_EDCMR(n) (0x848 + (n * 4)) +#define TPDM_DSB_MSR(n) (0x980 + (n * 4)) /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -113,6 +114,8 @@ struct dsb_dataset { u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts; bool trig_type;
- u32 msr_num;
- u32 *msr; };
/**
Where/when do we write to these registers in the DSB ?
Suzuki
On 6/5/2023 6:24 PM, Suzuki K Poulose wrote:
On 27/04/2023 10:00, Tao Zhang wrote:
Add the nodes for DSB subunit MSR(mux select register) support. The TPDM MSR (mux select register) interface is an optional interface and associated bank of registers per TPDM subunit. The intent of mux select registers is to control muxing structures driving the TPDM’s’ various subunit interfaces.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 15 ++++++ drivers/hwtracing/coresight/coresight-tpdm.c | 53 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 3 ++ 3 files changed, 71 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 639b6fb8..f746f25 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -170,3 +170,18 @@ Description: Accepts only one of the 2 values - 0 or 1. 0 : Set the DSB pattern type to value. 1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.3 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm.
+ Expected format is the following: + <integer1> <integer2>
+ Where: + <integer1> : Index number of MSR register + <integer2> : The value need to be written diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 627de36..5fe0bd5c 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -240,6 +240,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)), + GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } } return 0; @@ -765,6 +773,50 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + ssize_t size = 0;
+ if (drvdata->dsb->msr_num == 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
Shouldn't this be "i < drvdata->dsb->msr_num" ?
Yes, I will update it to the next patch series.
+ size += sysfs_emit_at(buf, size, + "%u 0x%x\n", i, drvdata->dsb->msr[i]); + } + spin_unlock(&drvdata->spinlock);
+ return size; +}
+static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int num, val; + int nval;
+ if (drvdata->dsb->msr_num == 0) + return -EINVAL;
+ nval = sscanf(buf, "%u %x", &num, &val); + if ((nval != 2) || (num >= (drvdata->dsb->msr_num - 1)))
(num >= drvdata->dsb->msr_num) ?
Yes, I will update it to the next patch series.
+ return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[num] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr);
static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, &dev_attr_dsb_edge_ctrl.attr, @@ -777,6 +829,7 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, + &dev_attr_dsb_msr.attr, NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 9ad32a6..05e9f8e 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -18,6 +18,7 @@ #define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4)) #define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) #define TPDM_DSB_EDCMR(n) (0x848 + (n * 4)) +#define TPDM_DSB_MSR(n) (0x980 + (n * 4)) /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -113,6 +114,8 @@ struct dsb_dataset { u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts; bool trig_type; + u32 msr_num; + u32 *msr; }; /**
Where/when do we write to these registers in the DSB ?
DSB MSR registers should be written in the DSB TPDM enablement function.
I will update this to the next patch series.
Best
Tao
Suzuki
On 27/04/2023 10:00, Tao Zhang wrote:
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 0x3 0x1 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_mask echo 0x6d 0x6d 0 > /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 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_patt_mask echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_val
This patch series depends on patch series "[PATCH v2 0/9] coresight: Fix CTI module refcount leak by making it a helper device" https://patchwork.kernel.org/project/linux-arm-kernel/patch/20230425143542.2...
There is v6 available for the above and there may be changes in the data structures. But the series is stable now, and may be you could cordinate with James and repost the series at rc1 ?
Suzuki