Introduction of TPDM DSB subunit DSB subunit is responsible for creating a dataset element, and is also optionally responsible for packing it to fit multiple elements on a single ATB transfer if possible in the configuration. The TPDM Core Datapath requests timestamps be stored by the TPDA and then delivering ATB sized data (depending on ATB width and element size, this could be smaller or larger than a dataset element) to the ATB Mast FSM.
The DSB subunit must be configured prior to enablement. This series adds support for TPDM to configure the configure DSB subunit.
Once this series patches are applied properly, the new tpdm nodes for should be observed at the tpdm path /sys/bus/coresight/devices/tpdm* which supports DSB subunit. e.g. /sys/devices/platform/soc@0/69d0000.tpdm/tpdm0#ls -l | grep dsb -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_edge_ctrl -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_edge_ctrl_mask -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_mode -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_mask -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_ts -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_type -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_patt_val -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_patt_mask -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_patt_val -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_ts -rw-r--r-- 1 root root 4096 Jan 1 00:01 dsb_trig_type
We can use the commands are similar to the below to configure the TPDMs which support DSB subunit. Enable coresight sink first. echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink echo 1 > /sys/bus/coresight/devices/tpdm0/reset echo 0x3 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_idx echo 0x1 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl_mask echo 0x0 > /sys/bus/coresight/devices/tpdm0/dsb_edge_ctrl echo 1 > /sys/bus/coresight/devices/tpdm0/dsb_patt_ts echo 1 > /sys/bus/coresight/devices/tpdm0/dsb_patt_type echo 0 > /sys/bus/coresight/devices/tpdm0/dsb_trig_ts echo 0x5 > /sys/bus/coresight/devices/tpdm0/dsb_patt_idx echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_patt_mask echo 0x2 > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_idx echo 0 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/dsb_trig_patt_val
TPDM_DSB commit tree: https://git.codelinaro.org/clo/linux-kernel/coresight/-/tree/tpdm-dsb-v7 https://git.codelinaro.org/clo/linux-kernel/coresight/-/commits/tpdm-dsb-v7
Changes in V7: 1. Since the "One value" limitation on SysFs file usage, add the nodes to read/write the index number for configuring the DSB TPDM. The following index number nodes are added. "dsb_edge_ctrl_idx" in the patch #9 "dsb_trig_patt_idx" in the patch #10 "dsb_patt_idx" in the patch #11 "dsb_msr_idx" in the patch #13 -- Suzuki K Poulose
Changes in V6: 1. Align the code to fix the styling issue. -- Suzuki K Poulose
Changes in V5: 1. Correct data type for DSB element size in dt-bindings patch. 2. Refine the recursive function "tpda_set_element_size". -- Suzuki K Poulose 3. Get return value of the function "__tpda_enable" in "tpda_enable". -- Suzuki K Poulose 4. Refine the comments on "dsb_esize". -- Suzuki K Poulose 5. Split the chage that introduce the subtype "SUBTYPE_SOURCE_TPDM" to Coresight driver. -- Suzuki K Poulose 6. Inline the trigger type setting to "tpdm_enable_dsb" simply. -- Suzuki K Poulose 7. Split the change that remove the needless CS_{UN,}LOCK in the function "tpdm_datasets_setup". -- Suzuki K Poulose 8. Remove the disablement step in the reset node. -- Suzuki K Poulose 9. Update the kernel version to 6.5 in the sysfs document. -- Suzuki K Poulose 10. Remove the needless check in "tpdm_dsb_is_visible". -- Suzuki K Poulose 11. Change the macro to mask the mode of DSB TPDM. -- Suzuki K Poulose 12. Add a check to make sure "sysfs_emit_at" calling will not cause overflow. -- Suzuki K Poulose 13. Change the macro to get "edge_ctrl" value. -- Suzuki K Poulose 14. Remove the needless comments in the sysfs document. -- Suzuki K Poulose 15. Replace "TPDM_DSB_MAX_PATT" with "drvdata->dsb->msr_num" in "dsb_msr_show". -- Suzuki K Poulose 16. Update the check of MSR number in "dsb_msr_store". -- Suzuki K Poulose 17. Write data to the MSR registers in the DSB TPDM enablement function. -- Suzuki K Poulose
Changes in V4: 1. Change the range of the property "qcom,dsb-element-size", and change the type to enumeration. -- Suzuki K Poulose, Krzysztof Kozlowski 2. Change dsb_esize from 32 bits to 8 bits. -- Suzuki K Poulose 3. Update the function tpda_set_element_size since James has updated the dependency series. Meanwhile, it will send out a warning if it detects more than one TPDM from the same TPDA input port. -- Suzuki K Poulose 4. Add a source_sub_type for TPDM to distinguish TPDM from the other coresight source. -- Suzuki K Poulose 5. Return error if the element size is not configured on devicetree in TPDA enablement. -- Suzuki K Poulose 6. Move memory allocation from "tpdm_init_datasets" to "tpdm_datasets_setup". Rename "tpdm_init_datasets" as "tpdm_reset_datasets". -- Suzuki K Poulose 7. Replace "coresight_disable" with "coresight_disable_source" to disable the TPDM in resetting. -- Suzuki K Poulose 8. Make sure "drvdata" is not NULL pointer before using it. -- Suzuki K Poulose 9. Change "set_dsb_cycacc_mode" to "set_dsb_test_mode" since cycle accurate mode is not supported on the current targets. It is replaced by test mode. 10. Document the value of "dsb_mode". -- Suzuki K Poulose 11. Macros are used to replace the formulas on dsb edge control nodes. -- Suzuki K Poulose 12. Document the values of "dsb_trig_patt_val" and "dsb_trig_patt_mask". -- Suzuki K Poulose 13. Combine two pattern related loops to one. And move DSB TIER register configurations to the new function "set_dsb_tier". -- Suzuki K Poulose 14. Rename the property "qcom,dsb_msr_num" to "qcom,dsb-msrs-num". -- Suzuki K Poulose, Krzysztof Kozlowski
Changes in V3: 1. Move the property "qcom,dsb-element-size" to TPDM devicetree and update the TPDM yaml file for this item. -- Suzuki K Poulose 2. Add the error message when the DSB element size is not set to 32-bit or 64-bit. -- Suzuki K Poulose 3. Add more information to the comments of patch #3 -- Suzuki K Poulose 4. Combine the value updates to the TPDM_DSB_CR for TPDM. -- Suzuki K Poulose 5. Remove the function "tpdm_datasets_alloc", and fold its code to a new function "tpdm_init_datasets". It will complete the initialization of TPDM. -- Suzuki K Poulose 6. Change the method of qualifying input values. -- Suzuki K Poulose 7. Add the documentation of the new sysfs handles. -- Suzuki K Poulose 8. Provide the separate handles for the "mode bits". -- Suzuki K Poulose
Changes in V2: 1. Change the name of the property "qcom,dsb-elem-size" to "qcom,dsb-element-size" -- Suzuki K Poulose 2. Update the TPDA yaml file for the item "qcom,dsb-elem-size". -- Krzysztof Kozlowski 3. Add the full name of DSB in the description of the item "qcom,dsb-elem-size". -- Rob Herring
Changes in V1: 1. Change the definition of the property "qcom,dsb-elem-size" from "uint32-array" to "uint32-matrix". -- Krzysztof Kozlowski 2. Add the full name of DSB. -- Rob Herring 3. Deal with 2 entries in an iteration in TPDA driver. -- Suzuki K Poulose 4. Divide the function "tpdm_datasets_alloc" into two functions, "tpdm_datasets_setup" and "tpdm_datasets_alloc". 5. Detecte the input string with the conventional semantics automatically, and constrain the size of the input value. -- Suzuki K Poulose 6. Use the hook function "is_visible()" to hide the DSB related knobs if the data sets are missing. -- Suzuki K Poulose 7. Use the macros "FIELD_GET" and "FIELD_PREP" to set the values. -- Suzuki K Poulose 8. Update the definition of the macros in TPDM driver. 9. Update the comments of the values for the nodes which are for DSB element creation and onfigure pattern match output. -- Suzuki K Poulose 10. Use API "sysfs_emit" to "replace scnprintf". -- Suzuki K Poulose
Tao Zhang (13): coresight-tpdm: Remove the unnecessary lock dt-bindings: arm: Add support for DSB element size coresight-tpdm: Introduce TPDM subtype to TPDM driver coresight-tpda: Add DSB dataset support coresight-tpdm: Initialize DSB subunit configuration coresight-tpdm: Add reset node to TPDM node coresight-tpdm: Add nodes to set trigger timestamp and type coresight-tpdm: Add node to set dsb programming mode coresight-tpdm: Add nodes for dsb edge control coresight-tpdm: Add nodes to configure pattern match output coresight-tpdm: Add nodes for timestamp request dt-bindings: arm: Add support for DSB MSR register coresight-tpdm: Add nodes for dsb msr support
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 192 +++++ .../bindings/arm/qcom,coresight-tpdm.yaml | 20 + drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpda.c | 96 ++- drivers/hwtracing/coresight/coresight-tpda.h | 4 + drivers/hwtracing/coresight/coresight-tpdm.c | 806 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 91 +++ include/linux/coresight.h | 1 + 8 files changed, 1193 insertions(+), 18 deletions(-)
Remove the unnecessary lock "CS_{UN,}LOCK" in TPDM driver. This lock is only needed while writing the data to Coresight registers.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- drivers/hwtracing/coresight/coresight-tpdm.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f4854af..b645612 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -114,11 +114,9 @@ static void tpdm_init_default_data(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); }
/*
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 Acked-by: Rob Herring robh@kernel.org --- Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml index 5c08342..931ee8f 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml @@ -44,6 +44,14 @@ properties: minItems: 1 maxItems: 2
+ qcom,dsb-element-size: + description: + Specifies the DSB(Discrete Single Bit) element size supported by + the monitor. The associated aggregator will read this size before it + is enabled. DSB element size currently only supports 32-bit and 64-bit. + $ref: /schemas/types.yaml#/definitions/uint8 + enum: [32, 64] + clocks: maxItems: 1
@@ -77,6 +85,8 @@ examples: compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0684c000 0x1000>;
+ qcom,dsb-element-size = /bits/ 8 <32>; + clocks = <&aoss_qmp>; clock-names = "apb_pclk";
Introduce the new subtype of "CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM" for TPDM components in driver.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- drivers/hwtracing/coresight/coresight-core.c | 1 + drivers/hwtracing/coresight/coresight-tpdm.c | 2 +- include/linux/coresight.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 118fcf2..a8c52aa 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1093,6 +1093,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-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index b645612..abaff0b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -203,7 +203,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 bf70987..dc19a44 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -62,6 +62,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, };
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-tpda.c | 96 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ 2 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..7c71342 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,58 @@
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
+/* Search and read element data size from the TPDM node in + * the devicetree. Each input port of TPDA is connected to + * a TPDM. Different TPDM supports different types of dataset, + * and some may support more than one type of dataset. + * Parameter "inport" is used to pass in the input port number + * of TPDA, and it is set to 0 in the recursize call. + * Parameter "parent" is used to pass in the original call. + */ +static int tpda_set_element_size(struct tpda_drvdata *drvdata, + struct coresight_device *csdev, int inport, bool match_inport) +{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev; + + if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL; + + if (match_inport) { + nr_inport = inport; + tpdm_found = false; + } + + for (i = 0; i < csdev->pdata->nr_inconns; i++) { + in_csdev = csdev->pdata->in_conns[i]->src_dev; + if (!in_csdev) + break; + + if (match_inport) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue; + + if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && + (in_csdev->subtype.source_subtype + == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) { + of_property_read_u8(in_csdev->dev.parent->of_node, + "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]); + if (!tpdm_found) + tpdm_found = true; + else + dev_warn(drvdata->dev, + "More than one TPDM is mapped to the TPDA input port %d.\n", + nr_inport); + continue; + } + tpda_set_element_size(drvdata, in_csdev, 0, false); + } + + return 0; +} + /* Settings pre enabling port control register */ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) { @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDA_CR); }
-static void tpda_enable_port(struct tpda_drvdata *drvdata, int port) +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) { u32 val;
val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); + /* + * Configure aggregator port n DSB data set element size + * Set the bit to 0 if the size is 32 + * Set the bit to 1 if the size is 64 + */ + if (drvdata->dsb_esize[port] == 32) + val &= ~TPDA_Pn_CR_DSBSIZE; + else if (drvdata->dsb_esize[port] == 64) + val |= TPDA_Pn_CR_DSBSIZE; + else + return -EINVAL; + /* Enable the port */ val |= TPDA_Pn_CR_ENA; writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port)); + + return 0; }
-static void __tpda_enable(struct tpda_drvdata *drvdata, int port) +static int __tpda_enable(struct tpda_drvdata *drvdata, int port) { + int ret; + CS_UNLOCK(drvdata->base);
if (!drvdata->csdev->enable) tpda_enable_pre_port(drvdata);
- tpda_enable_port(drvdata, port); - + ret = tpda_enable_port(drvdata, port); CS_LOCK(drvdata->base); + + return ret; }
static int tpda_enable(struct coresight_device *csdev, @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + int ret; + + ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true); + if (ret) + return ret;
spin_lock(&drvdata->spinlock); - if (atomic_read(&in->dest_refcnt) == 0) - __tpda_enable(drvdata, in->dest_port); + if (atomic_read(&in->dest_refcnt) == 0) { + ret = __tpda_enable(drvdata, in->dest_port); + if (!ret) { + atomic_inc(&in->dest_refcnt); + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); + } + }
- atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock); - - dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); - return 0; + return ret; }
static void __tpda_disable(struct tpda_drvdata *drvdata, int port) diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h index 0399678..12a1472 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.h +++ b/drivers/hwtracing/coresight/coresight-tpda.h @@ -10,6 +10,8 @@ #define TPDA_Pn_CR(n) (0x004 + (n * 4)) /* Aggregator port enable bit */ #define TPDA_Pn_CR_ENA BIT(0) +/* Aggregator port DSB data set element size bit */ +#define TPDA_Pn_CR_DSBSIZE BIT(8)
#define TPDA_MAX_INPORTS 32
@@ -23,6 +25,7 @@ * @csdev: component vitals needed by the framework. * @spinlock: lock for the drvdata value. * @enable: enable status of the component. + * @dsb_esize: DSB element size for each inport, it must be 32 or 64. */ struct tpda_drvdata { void __iomem *base; @@ -30,6 +33,7 @@ struct tpda_drvdata { struct coresight_device *csdev; spinlock_t spinlock; u8 atid; + u8 dsb_esize[TPDA_MAX_INPORTS]; };
#endif /* _CORESIGHT_CORESIGHT_TPDA_H */
On 25/07/2023 08:15, Tao Zhang wrote:
Read the DSB element size from the device tree. Set the register bit that controls the DSB element size of the corresponding port.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ 2 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..7c71342 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,58 @@ DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda"); +/* Search and read element data size from the TPDM node in
minor nit:
/* * Search ...
- the devicetree. Each input port of TPDA is connected to
- a TPDM. Different TPDM supports different types of dataset,
- and some may support more than one type of dataset.
- Parameter "inport" is used to pass in the input port number
- of TPDA, and it is set to 0 in the recursize call.
- Parameter "parent" is used to pass in the original call.
Please remove references to the past and describe "match_inport"
- */
+static int tpda_set_element_size(struct tpda_drvdata *drvdata,
struct coresight_device *csdev, int inport, bool match_inport)
May be we could switch the order of the parameters:
match_inport, int port
Or even inport < 0, implies, port wont be matched.
i.e.,
tpda_set_element_size(drvdata, child, inport)
+{
- static int nr_inport;
- int i;
- static bool tpdm_found;
- struct coresight_device *in_csdev;
- if (inport > (TPDA_MAX_INPORTS - 1))
return -EINVAL;
- if (match_inport) {
nr_inport = inport;
tpdm_found = false;
- }
Could we not avoid the static variables and this dance by making the function return the dsb_size ? See further down.
- for (i = 0; i < csdev->pdata->nr_inconns; i++) {
in_csdev = csdev->pdata->in_conns[i]->src_dev;
if (!in_csdev)
break;
continue ?
if (match_inport)
if (csdev->pdata->in_conns[i]->dest_port != inport)
continue;
if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
(in_csdev->subtype.source_subtype
== CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
Please provide a helper :
static bool coresight_device_is_tpdm(csdev) { return (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && (in_csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); }
of_property_read_u8(in_csdev->dev.parent->of_node,
"qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);
if (!tpdm_found)
tpdm_found = true;
else
dev_warn(drvdata->dev,
"More than one TPDM is mapped to the TPDA input port %d.\n",
nr_inport);
continue;
}
tpda_set_element_size(drvdata, in_csdev, 0, false);
- }
/* * Read the DSB element size from the TPDM device * Returns * the size read from the firmware if available. * 0 - Otherwise, with a Warning once. */ static int tpdm_read_dsb_element_size(struct coresight_device *csdev) { int rc, size = 0;
rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent), "qcom,dsb-element-size", &size); if (rc) dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size: %d\n", rc); return size; }
static int tpda_get_element_size(struct coresight_device *csdev, int inport) { int dsb_size = -ENOENT;
for (i = 0; i < csdev->pdata->nr_inconns; i++) { in = csdev->pdata->in_conns[i]->src_dev; if (!in) continue; if (coresight_device_is_tpdm(in)) { /* Ignore the TPDMs that do not match port */ if (inport > 0 && (csdev->pdata->in_conns[i]->dest_port != inport)) continue; size = tpdm_read_dsb_element_size(csdev); } else { /* Recurse down the path */ size = tpda_set_element_size(in, -1); }
if (size < 0) return size; /* We have found a size, save it. */ if (dsb_size < 0) { dsb_size = size; } else { /* We have duplicate TPDMs */ return -EEXIST; } } return dsb_size; }
- return 0;
+}
- /* Settings pre enabling port control register */ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) {
@@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDA_CR); } -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port) +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) { u32 val; val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
- /*
* Configure aggregator port n DSB data set element size
* Set the bit to 0 if the size is 32
* Set the bit to 1 if the size is 64
*/
- if (drvdata->dsb_esize[port] == 32)
val &= ~TPDA_Pn_CR_DSBSIZE;
- else if (drvdata->dsb_esize[port] == 64)
val |= TPDA_Pn_CR_DSBSIZE;
Couldn't this be detected via tpda_get_element_size()? see below.
- else
return -EINVAL;
- /* Enable the port */ val |= TPDA_Pn_CR_ENA; writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
- return 0; }
-static void __tpda_enable(struct tpda_drvdata *drvdata, int port) +static int __tpda_enable(struct tpda_drvdata *drvdata, int port) {
- int ret;
- CS_UNLOCK(drvdata->base);
if (!drvdata->csdev->enable) tpda_enable_pre_port(drvdata);
- tpda_enable_port(drvdata, port);
- ret = tpda_enable_port(drvdata, port); CS_LOCK(drvdata->base);
- return ret; }
static int tpda_enable(struct coresight_device *csdev, @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
- ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
size = tpda_get_element_size(csdev, in->dest_port); switch (size) { case 32: case 64: break; case -EEXIST: dev_warn_once("Detected multiple TPDMs on port %d", ..) fallthrough; default: return size; }
drvdata->dsb_esize[in->dest_port] = size;
Suzuki
- if (ret)
return ret;
spin_lock(&drvdata->spinlock);
- if (atomic_read(&in->dest_refcnt) == 0)
__tpda_enable(drvdata, in->dest_port);
- if (atomic_read(&in->dest_refcnt) == 0) {
ret = __tpda_enable(drvdata, in->dest_port);
if (!ret) {
atomic_inc(&in->dest_refcnt);
dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
}
- }
- atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
- return 0;
- return ret; }
static void __tpda_disable(struct tpda_drvdata *drvdata, int port) diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h index 0399678..12a1472 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.h +++ b/drivers/hwtracing/coresight/coresight-tpda.h @@ -10,6 +10,8 @@ #define TPDA_Pn_CR(n) (0x004 + (n * 4)) /* Aggregator port enable bit */ #define TPDA_Pn_CR_ENA BIT(0) +/* Aggregator port DSB data set element size bit */ +#define TPDA_Pn_CR_DSBSIZE BIT(8) #define TPDA_MAX_INPORTS 32 @@ -23,6 +25,7 @@
- @csdev: component vitals needed by the framework.
- @spinlock: lock for the drvdata value.
- @enable: enable status of the component.
*/ struct tpda_drvdata { void __iomem *base;
- @dsb_esize: DSB element size for each inport, it must be 32 or 64.
@@ -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 */
On 04/08/2023 16:02, Suzuki K Poulose wrote:
On 25/07/2023 08:15, Tao Zhang wrote:
Read the DSB element size from the device tree. Set the register bit that controls the DSB element size of the corresponding port.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ 2 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..7c71342 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,58 @@ DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda"); +/* Search and read element data size from the TPDM node in
minor nit:
/* * Search ...
- the devicetree. Each input port of TPDA is connected to
- a TPDM. Different TPDM supports different types of dataset,
- and some may support more than one type of dataset.
- Parameter "inport" is used to pass in the input port number
- of TPDA, and it is set to 0 in the recursize call.
- Parameter "parent" is used to pass in the original call.
Please remove references to the past and describe "match_inport"
- */
+static int tpda_set_element_size(struct tpda_drvdata *drvdata, + struct coresight_device *csdev, int inport, bool match_inport)
May be we could switch the order of the parameters:
match_inport, int port
Or even inport < 0, implies, port wont be matched.
i.e.,
tpda_set_element_size(drvdata, child, inport)
+{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (match_inport) { + nr_inport = inport; + tpdm_found = false; + }
Could we not avoid the static variables and this dance by making the function return the dsb_size ? See further down.
+ for (i = 0; i < csdev->pdata->nr_inconns; i++) { + in_csdev = csdev->pdata->in_conns[i]->src_dev; + if (!in_csdev) + break;
continue ?
+ if (match_inport) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && + (in_csdev->subtype.source_subtype + == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
Please provide a helper :
static bool coresight_device_is_tpdm(csdev) { return (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && (in_csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); }
+ of_property_read_u8(in_csdev->dev.parent->of_node, + "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);
+ if (!tpdm_found) + tpdm_found = true; + else + dev_warn(drvdata->dev, + "More than one TPDM is mapped to the TPDA input port %d.\n", + nr_inport); + continue; + } + tpda_set_element_size(drvdata, in_csdev, 0, false); + }
/* * Read the DSB element size from the TPDM device * Returns * the size read from the firmware if available. * 0 - Otherwise, with a Warning once. */ static int tpdm_read_dsb_element_size(struct coresight_device *csdev) { int rc, size = 0;
rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent), "qcom,dsb-element-size", &size); if (rc) dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size: %d\n", rc); return size; }
static int tpda_get_element_size(struct coresight_device *csdev, int inport) { int dsb_size = -ENOENT;
for (i = 0; i < csdev->pdata->nr_inconns; i++) { in = csdev->pdata->in_conns[i]->src_dev; if (!in) continue; if (coresight_device_is_tpdm(in)) { /* Ignore the TPDMs that do not match port */ if (inport > 0 && (csdev->pdata->in_conns[i]->dest_port != inport)) continue; size = tpdm_read_dsb_element_size(csdev); } else { /* Recurse down the path */ size = tpda_set_element_size(in, -1); }
if (size < 0) return size; /* We have found a size, save it. */ if (dsb_size < 0) { dsb_size = size; } else { /* We have duplicate TPDMs */ return -EEXIST; } } return dsb_size; }
+ return 0; +}
/* Settings pre enabling port control register */ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) { @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDA_CR); } -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port) +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) { u32 val; val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); + /* + * Configure aggregator port n DSB data set element size + * Set the bit to 0 if the size is 32 + * Set the bit to 1 if the size is 64 + */ + if (drvdata->dsb_esize[port] == 32) + val &= ~TPDA_Pn_CR_DSBSIZE; + else if (drvdata->dsb_esize[port] == 64) + val |= TPDA_Pn_CR_DSBSIZE;
Couldn't this be detected via tpda_get_element_size()? see below.
+ else + return -EINVAL;
/* Enable the port */ val |= TPDA_Pn_CR_ENA; writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
+ return 0; } -static void __tpda_enable(struct tpda_drvdata *drvdata, int port) +static int __tpda_enable(struct tpda_drvdata *drvdata, int port) { + int ret;
CS_UNLOCK(drvdata->base); if (!drvdata->csdev->enable) tpda_enable_pre_port(drvdata); - tpda_enable_port(drvdata, port);
+ ret = tpda_enable_port(drvdata, port); CS_LOCK(drvdata->base);
+ return ret; } static int tpda_enable(struct coresight_device *csdev, @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + int ret;
+ ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
size = tpda_get_element_size(csdev, in->dest_port); switch (size) { case 32: case 64: break;
We also need :
case 0: return -ENOENT;
Suzuki
case -EEXIST: dev_warn_once("Detected multiple TPDMs on port %d", ..) fallthrough; default: return size; }
drvdata->dsb_esize[in->dest_port] = size;
Suzuki
+ if (ret) + return ret; spin_lock(&drvdata->spinlock); - if (atomic_read(&in->dest_refcnt) == 0) - __tpda_enable(drvdata, in->dest_port); + if (atomic_read(&in->dest_refcnt) == 0) { + ret = __tpda_enable(drvdata, in->dest_port); + if (!ret) { + atomic_inc(&in->dest_refcnt); + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); + } + } - atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); - return 0; + return ret; } static void __tpda_disable(struct tpda_drvdata *drvdata, int port) diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h index 0399678..12a1472 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.h +++ b/drivers/hwtracing/coresight/coresight-tpda.h @@ -10,6 +10,8 @@ #define TPDA_Pn_CR(n) (0x004 + (n * 4)) /* Aggregator port enable bit */ #define TPDA_Pn_CR_ENA BIT(0) +/* Aggregator port DSB data set element size bit */ +#define TPDA_Pn_CR_DSBSIZE BIT(8) #define TPDA_MAX_INPORTS 32 @@ -23,6 +25,7 @@ * @csdev: component vitals needed by the framework. * @spinlock: lock for the drvdata value. * @enable: enable status of the component.
- @dsb_esize: DSB element size for each inport, it must be 32 or 64.
*/ struct tpda_drvdata { void __iomem *base; @@ -30,6 +33,7 @@ struct tpda_drvdata { struct coresight_device *csdev; spinlock_t spinlock; u8 atid; + u8 dsb_esize[TPDA_MAX_INPORTS]; }; #endif /* _CORESIGHT_CORESIGHT_TPDA_H */
On 8/7/2023 5:12 PM, Suzuki K Poulose wrote:
On 04/08/2023 16:02, Suzuki K Poulose wrote:
On 25/07/2023 08:15, Tao Zhang wrote:
Read the DSB element size from the device tree. Set the register bit that controls the DSB element size of the corresponding port.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ 2 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..7c71342 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,58 @@ DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda"); +/* Search and read element data size from the TPDM node in
minor nit:
/* * Search ...
- the devicetree. Each input port of TPDA is connected to
- a TPDM. Different TPDM supports different types of dataset,
- and some may support more than one type of dataset.
- Parameter "inport" is used to pass in the input port number
- of TPDA, and it is set to 0 in the recursize call.
- Parameter "parent" is used to pass in the original call.
Please remove references to the past and describe "match_inport"
- */
+static int tpda_set_element_size(struct tpda_drvdata *drvdata, + struct coresight_device *csdev, int inport, bool match_inport)
May be we could switch the order of the parameters:
match_inport, int port
Or even inport < 0, implies, port wont be matched.
i.e.,
tpda_set_element_size(drvdata, child, inport)
+{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (match_inport) { + nr_inport = inport; + tpdm_found = false; + }
Could we not avoid the static variables and this dance by making the function return the dsb_size ? See further down.
+ for (i = 0; i < csdev->pdata->nr_inconns; i++) { + in_csdev = csdev->pdata->in_conns[i]->src_dev; + if (!in_csdev) + break;
continue ?
+ if (match_inport) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && + (in_csdev->subtype.source_subtype + == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
Please provide a helper :
static bool coresight_device_is_tpdm(csdev) { return (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && (in_csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); }
- of_property_read_u8(in_csdev->dev.parent->of_node,
+ "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);
+ if (!tpdm_found) + tpdm_found = true; + else + dev_warn(drvdata->dev, + "More than one TPDM is mapped to the TPDA input port %d.\n", + nr_inport); + continue; + } + tpda_set_element_size(drvdata, in_csdev, 0, false); + }
/* * Read the DSB element size from the TPDM device * Returns * the size read from the firmware if available. * 0 - Otherwise, with a Warning once. */ static int tpdm_read_dsb_element_size(struct coresight_device *csdev) { int rc, size = 0;
rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent), "qcom,dsb-element-size", &size); if (rc) dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size: %d\n", rc); return size; }
static int tpda_get_element_size(struct coresight_device *csdev, int inport) { int dsb_size = -ENOENT;
for (i = 0; i < csdev->pdata->nr_inconns; i++) { in = csdev->pdata->in_conns[i]->src_dev; if (!in) continue; if (coresight_device_is_tpdm(in)) { /* Ignore the TPDMs that do not match port */ if (inport > 0 && (csdev->pdata->in_conns[i]->dest_port != inport)) continue; size = tpdm_read_dsb_element_size(csdev); } else { /* Recurse down the path */ size = tpda_set_element_size(in, -1); }
if (size < 0) return size; /* We have found a size, save it. */ if (dsb_size < 0) { dsb_size = size; } else { /* We have duplicate TPDMs */ return -EEXIST; } } return dsb_size; }
+ return 0; +}
/* Settings pre enabling port control register */ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) { @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDA_CR); } -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port) +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) { u32 val; val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); + /* + * Configure aggregator port n DSB data set element size + * Set the bit to 0 if the size is 32 + * Set the bit to 1 if the size is 64 + */ + if (drvdata->dsb_esize[port] == 32) + val &= ~TPDA_Pn_CR_DSBSIZE; + else if (drvdata->dsb_esize[port] == 64) + val |= TPDA_Pn_CR_DSBSIZE;
Couldn't this be detected via tpda_get_element_size()? see below.
+ else + return -EINVAL;
/* Enable the port */ val |= TPDA_Pn_CR_ENA; writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
+ return 0; } -static void __tpda_enable(struct tpda_drvdata *drvdata, int port) +static int __tpda_enable(struct tpda_drvdata *drvdata, int port) { + int ret;
CS_UNLOCK(drvdata->base); if (!drvdata->csdev->enable) tpda_enable_pre_port(drvdata); - tpda_enable_port(drvdata, port);
+ ret = tpda_enable_port(drvdata, port); CS_LOCK(drvdata->base);
+ return ret; } static int tpda_enable(struct coresight_device *csdev, @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + int ret;
+ ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
size = tpda_get_element_size(csdev, in->dest_port); switch (size) { case 32: case 64: break;
We also need :
case 0: return -ENOENT;
I will update this in the next patch series.
Best,
Tao
Suzuki
case -EEXIST: dev_warn_once("Detected multiple TPDMs on port %d", ..) fallthrough; default: return size; }
drvdata->dsb_esize[in->dest_port] = size;
Suzuki
+ if (ret) + return ret; spin_lock(&drvdata->spinlock); - if (atomic_read(&in->dest_refcnt) == 0) - __tpda_enable(drvdata, in->dest_port); + if (atomic_read(&in->dest_refcnt) == 0) { + ret = __tpda_enable(drvdata, in->dest_port); + if (!ret) { + atomic_inc(&in->dest_refcnt); + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); + } + } - atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); - return 0; + return ret; } static void __tpda_disable(struct tpda_drvdata *drvdata, int port) diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h index 0399678..12a1472 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.h +++ b/drivers/hwtracing/coresight/coresight-tpda.h @@ -10,6 +10,8 @@ #define TPDA_Pn_CR(n) (0x004 + (n * 4)) /* Aggregator port enable bit */ #define TPDA_Pn_CR_ENA BIT(0) +/* Aggregator port DSB data set element size bit */ +#define TPDA_Pn_CR_DSBSIZE BIT(8) #define TPDA_MAX_INPORTS 32 @@ -23,6 +25,7 @@ * @csdev: component vitals needed by the framework. * @spinlock: lock for the drvdata value. * @enable: enable status of the component.
- @dsb_esize: DSB element size for each inport, it must be 32 or 64.
*/ struct tpda_drvdata { void __iomem *base; @@ -30,6 +33,7 @@ struct tpda_drvdata { struct coresight_device *csdev; spinlock_t spinlock; u8 atid; + u8 dsb_esize[TPDA_MAX_INPORTS]; }; #endif /* _CORESIGHT_CORESIGHT_TPDA_H */
Hi Suzuki,
On 8/4/2023 11:02 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, Tao Zhang wrote:
Read the DSB element size from the device tree. Set the register bit that controls the DSB element size of the corresponding port.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
drivers/hwtracing/coresight/coresight-tpda.c | 96 +++++++++++++++++++++++++--- drivers/hwtracing/coresight/coresight-tpda.h | 4 ++ 2 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 8d2b9d2..7c71342 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -21,6 +21,58 @@ DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda"); +/* Search and read element data size from the TPDM node in
minor nit:
/* * Search ...
I will update this in the next patch series.
- the devicetree. Each input port of TPDA is connected to
- a TPDM. Different TPDM supports different types of dataset,
- and some may support more than one type of dataset.
- Parameter "inport" is used to pass in the input port number
- of TPDA, and it is set to 0 in the recursize call.
- Parameter "parent" is used to pass in the original call.
Please remove references to the past and describe "match_inport"
I will update this in the next patch series.
- */
+static int tpda_set_element_size(struct tpda_drvdata *drvdata, + struct coresight_device *csdev, int inport, bool match_inport)
May be we could switch the order of the parameters:
match_inport, int port
Or even inport < 0, implies, port wont be matched.
i.e.,
tpda_set_element_size(drvdata, child, inport)
I will update this in the next patch series.
+{ + static int nr_inport; + int i; + static bool tpdm_found; + struct coresight_device *in_csdev;
+ if (inport > (TPDA_MAX_INPORTS - 1)) + return -EINVAL;
+ if (match_inport) { + nr_inport = inport; + tpdm_found = false; + }
Could we not avoid the static variables and this dance by making the function return the dsb_size ? See further down.
I will update this in the next patch series.
+ for (i = 0; i < csdev->pdata->nr_inconns; i++) { + in_csdev = csdev->pdata->in_conns[i]->src_dev; + if (!in_csdev) + break;
continue ?
I will update this in the next patch series.
+ if (match_inport) + if (csdev->pdata->in_conns[i]->dest_port != inport) + continue;
+ if ((in_csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && + (in_csdev->subtype.source_subtype + == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM)) {
Please provide a helper :
static bool coresight_device_is_tpdm(csdev) { return (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) && (in_csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); }
I will update this in the next patch series.
- of_property_read_u8(in_csdev->dev.parent->of_node,
+ "qcom,dsb-element-size", &drvdata->dsb_esize[nr_inport]);
+ if (!tpdm_found) + tpdm_found = true; + else + dev_warn(drvdata->dev, + "More than one TPDM is mapped to the TPDA input port %d.\n", + nr_inport); + continue; + } + tpda_set_element_size(drvdata, in_csdev, 0, false); + }
/* * Read the DSB element size from the TPDM device * Returns * the size read from the firmware if available. * 0 - Otherwise, with a Warning once. */ static int tpdm_read_dsb_element_size(struct coresight_device *csdev) { int rc, size = 0;
rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent), "qcom,dsb-element-size", &size); if (rc) dev_warn_once(&in->dev, "Failed to read TPDM DSB Element size: %d\n", rc); return size; }
static int tpda_get_element_size(struct coresight_device *csdev, int inport) { int dsb_size = -ENOENT;
for (i = 0; i < csdev->pdata->nr_inconns; i++) { in = csdev->pdata->in_conns[i]->src_dev; if (!in) continue; if (coresight_device_is_tpdm(in)) { /* Ignore the TPDMs that do not match port */ if (inport > 0 && (csdev->pdata->in_conns[i]->dest_port != inport)) continue; size = tpdm_read_dsb_element_size(csdev); } else { /* Recurse down the path */ size = tpda_set_element_size(in, -1); }
if (size < 0) return size; /* We have found a size, save it. */ if (dsb_size < 0) { dsb_size = size; } else { /* We have duplicate TPDMs */ return -EEXIST; } } return dsb_size; }
I will update this in the next patch series.
+ return 0; +}
/* Settings pre enabling port control register */ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) { @@ -32,26 +84,43 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) writel_relaxed(val, drvdata->base + TPDA_CR); } -static void tpda_enable_port(struct tpda_drvdata *drvdata, int port) +static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) { u32 val; val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); + /* + * Configure aggregator port n DSB data set element size + * Set the bit to 0 if the size is 32 + * Set the bit to 1 if the size is 64 + */ + if (drvdata->dsb_esize[port] == 32) + val &= ~TPDA_Pn_CR_DSBSIZE; + else if (drvdata->dsb_esize[port] == 64) + val |= TPDA_Pn_CR_DSBSIZE;
Couldn't this be detected via tpda_get_element_size()? see below.
I will update this in the next patch series.
+ else + return -EINVAL;
/* Enable the port */ val |= TPDA_Pn_CR_ENA; writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
+ return 0; } -static void __tpda_enable(struct tpda_drvdata *drvdata, int port) +static int __tpda_enable(struct tpda_drvdata *drvdata, int port) { + int ret;
CS_UNLOCK(drvdata->base); if (!drvdata->csdev->enable) tpda_enable_pre_port(drvdata); - tpda_enable_port(drvdata, port);
+ ret = tpda_enable_port(drvdata, port); CS_LOCK(drvdata->base);
+ return ret; } static int tpda_enable(struct coresight_device *csdev, @@ -59,16 +128,23 @@ static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + int ret;
+ ret = tpda_set_element_size(drvdata, csdev, in->dest_port, true);
size = tpda_get_element_size(csdev, in->dest_port); switch (size) { case 32: case 64: break; case -EEXIST: dev_warn_once("Detected multiple TPDMs on port %d", ..) fallthrough; default: return size; }
drvdata->dsb_esize[in->dest_port] = size;
I will update this in the next patch series.
Best,
Tao
Suzuki
+ if (ret) + return ret; spin_lock(&drvdata->spinlock); - if (atomic_read(&in->dest_refcnt) == 0) - __tpda_enable(drvdata, in->dest_port); + if (atomic_read(&in->dest_refcnt) == 0) { + ret = __tpda_enable(drvdata, in->dest_port); + if (!ret) { + atomic_inc(&in->dest_refcnt); + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); + } + } - atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); - return 0; + return ret; } static void __tpda_disable(struct tpda_drvdata *drvdata, int port) diff --git a/drivers/hwtracing/coresight/coresight-tpda.h b/drivers/hwtracing/coresight/coresight-tpda.h index 0399678..12a1472 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.h +++ b/drivers/hwtracing/coresight/coresight-tpda.h @@ -10,6 +10,8 @@ #define TPDA_Pn_CR(n) (0x004 + (n * 4)) /* Aggregator port enable bit */ #define TPDA_Pn_CR_ENA BIT(0) +/* Aggregator port DSB data set element size bit */ +#define TPDA_Pn_CR_DSBSIZE BIT(8) #define TPDA_MAX_INPORTS 32 @@ -23,6 +25,7 @@ * @csdev: component vitals needed by the framework. * @spinlock: lock for the drvdata value. * @enable: enable status of the component.
- @dsb_esize: DSB element size for each inport, it must be 32 or 64.
*/ struct tpda_drvdata { void __iomem *base; @@ -30,6 +33,7 @@ struct tpda_drvdata { struct coresight_device *csdev; spinlock_t spinlock; u8 atid; + u8 dsb_esize[TPDA_MAX_INPORTS]; }; #endif /* _CORESIGHT_CORESIGHT_TPDA_H */
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 | 55 ++++++++++++++++++++++++++-- drivers/hwtracing/coresight/coresight-tpdm.h | 18 +++++++++ 2 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index abaff0b..52aa48a6 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,46 @@
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 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 */ + if (drvdata->dsb->trig_type) + val |= TPDM_DSB_CR_TRIG_TYPE; + else + val &= ~TPDM_DSB_CR_TRIG_TYPE; + /* 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 */ +/* 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,13 +139,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;
/* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); + + 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; }
/* @@ -179,6 +219,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)) @@ -198,6 +239,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) @@ -214,7 +261,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..92c34cd 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. @@ -48,6 +64,7 @@ * @spinlock: lock for the drvdata value. * @enable: enable status of the component. * @datasets: The datasets types present of the TPDM. + * @dsb Specifics associated to an TPDM component. */
struct tpdm_drvdata { @@ -57,6 +74,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets; + struct dsb_dataset *dsb; };
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
On 25/07/2023 08:15, 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 | 55 ++++++++++++++++++++++++++-- drivers/hwtracing/coresight/coresight-tpdm.h | 18 +++++++++ 2 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index abaff0b..52aa48a6 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,46 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) +{
- if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
Do we need a helper for this, we seem to be doing this more than once ?
tpdm_has_dsb_dataset(drvdata) ?
memset(drvdata->dsb, 0, sizeof(struct dsb_dataset));
drvdata->dsb->trig_ts = true;
drvdata->dsb->trig_type = false;
- }
+}
- 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 */
- if (drvdata->dsb->trig_type)
val |= TPDM_DSB_CR_TRIG_TYPE;
- else
val &= ~TPDM_DSB_CR_TRIG_TYPE;
- /* 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 */ +/* TPDM enable operations
minor nit:
/* * TPDM enable..
- 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,13 +139,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; /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0);
- if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
if (!drvdata->dsb) {
This could be :
if (tpdm_has_dsb_dataset(drvdata) && !drvdata->dsb) {
drvdata->dsb = devm_kzalloc(drvdata->dev,
sizeof(*drvdata->dsb), GFP_KERNEL);
if (!drvdata->dsb)
return -ENOMEM;
}
}
- }
Could we move the reset datasets here ? tpdm_reset_datasets(drvdata);
- return 0; }
/* @@ -179,6 +219,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)) @@ -198,6 +239,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);
^^ We could move this to datasets_setup(), see above.
- /* Set up coresight component description */ desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name)
@@ -214,7 +261,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..92c34cd 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.
@@ -48,6 +64,7 @@
- @spinlock: lock for the drvdata value.
- @enable: enable status of the component.
- @datasets: The datasets types present of the TPDM.
- @dsb Specifics associated to an TPDM component.
TPDM DSB related settings ?
Suzuki
*/ struct tpdm_drvdata { @@ -57,6 +74,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets;
- struct dsb_dataset *dsb; };
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
On 8/7/2023 5:28 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 55 ++++++++++++++++++++++++++-- drivers/hwtracing/coresight/coresight-tpdm.h | 18 +++++++++ 2 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index abaff0b..52aa48a6 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,17 +20,46 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) +{ + if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
Do we need a helper for this, we seem to be doing this more than once ?
tpdm_has_dsb_dataset(drvdata) ?
Sure, I will update this in the next patch series.
+ memset(drvdata->dsb, 0, sizeof(struct dsb_dataset));
+ drvdata->dsb->trig_ts = true; + drvdata->dsb->trig_type = false; + } +}
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 */ + if (drvdata->dsb->trig_type) + val |= TPDM_DSB_CR_TRIG_TYPE; + else + val &= ~TPDM_DSB_CR_TRIG_TYPE; + /* 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 */ +/* TPDM enable operations
minor nit:
/* * TPDM enable..
I will update this in the next patch series.
- 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,13 +139,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; /* Get the datasets present on the TPDM. */ pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0);
+ if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { + if (!drvdata->dsb) {
This could be :
if (tpdm_has_dsb_dataset(drvdata) && !drvdata->dsb) {
I will update this in the next patch series.
+ drvdata->dsb = devm_kzalloc(drvdata->dev, + sizeof(*drvdata->dsb), GFP_KERNEL); + if (!drvdata->dsb) + return -ENOMEM;
}
+ } + }
Could we move the reset datasets here ? tpdm_reset_datasets(drvdata);
I will update this in the next patch series.
+ return 0; } /* @@ -179,6 +219,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)) @@ -198,6 +239,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);
^^ We could move this to datasets_setup(), see above.
I will update this in the next patch series.
/* Set up coresight component description */ desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name) @@ -214,7 +261,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..92c34cd 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. @@ -48,6 +64,7 @@ * @spinlock: lock for the drvdata value. * @enable: enable status of the component. * @datasets: The datasets types present of the TPDM.
- @dsb Specifics associated to an TPDM component.
TPDM DSB related settings ?
I will update this in the next patch series.
Best,
Tao
Suzuki
*/ struct tpdm_drvdata { @@ -57,6 +74,7 @@ struct tpdm_drvdata { spinlock_t spinlock; bool enable; unsigned long datasets; + struct dsb_dataset *dsb; }; #endif /* _CORESIGHT_CORESIGHT_TPDM_H */
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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5 +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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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); + + return size; +} +static DEVICE_ATTR_WO(reset); + /* * value 1: 64 bits test data * value 2: 32 bits test data @@ -199,6 +220,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 25/07/2023 08:15, 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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5
+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.
Please fix this, we don't disable TPDM. If it only ever resets the datasets, please could we rename this as such ?
i.e., reset_dataset or reset_dsb_data ?
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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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)
Minor nit: alignment ? Could we have something like :
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);
- return size;
+} +static DEVICE_ATTR_WO(reset);
- /*
- value 1: 64 bits test data
- value 2: 32 bits test data
@@ -199,6 +220,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, };
Suzuki
On 8/7/2023 5:36 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5
+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.
Please fix this, we don't disable TPDM. If it only ever resets the datasets, please could we rename this as such ?
i.e., reset_dataset or reset_dsb_data ?
Sure, I will update this in the next patch series.
+ 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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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)
Minor nit: alignment ? Could we have something like :
static ssize_t reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
I will update this in the next patch series.
Best,
Tao
+{ + 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);
+ return size; +} +static DEVICE_ATTR_WO(reset);
/* * value 1: 64 bits test data * value 2: 32 bits test data @@ -199,6 +220,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, };
Suzuki
On 8/9/2023 2:35 PM, Tao Zhang wrote:
On 8/7/2023 5:36 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5
+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.
Please fix this, we don't disable TPDM. If it only ever resets the datasets, please could we rename this as such ?
i.e., reset_dataset or reset_dsb_data ?
Sure, I will update this in the next patch series.
+ 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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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)
Minor nit: alignment ? Could we have something like :
static ssize_t reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
I will update this in the next patch series.
Best,
Tao
Hi Suzuki,
With regards to the parameters alignment for the function, could you
kindly remind me the rule of alignment? I'm using the thunderbird
mail client and I'm not sure if the alignment I see is what you expect.
If the rule can be specified, I can align all the function parameters in
this patch series according to this rule.
Best,
Tao
+{ + 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);
+ return size; +} +static DEVICE_ATTR_WO(reset);
/* * value 1: 64 bits test data * value 2: 32 bits test data @@ -199,6 +220,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, };
Suzuki
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
On 8/13/2023 11:38 PM, Tao Zhang wrote:
On 8/9/2023 2:35 PM, Tao Zhang wrote:
On 8/7/2023 5:36 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5
+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.
Please fix this, we don't disable TPDM. If it only ever resets the datasets, please could we rename this as such ?
i.e., reset_dataset or reset_dsb_data ?
Sure, I will update this in the next patch series.
+ 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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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)
Minor nit: alignment ? Could we have something like :
static ssize_t reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
I will update this in the next patch series.
Best,
Tao
Hi Suzuki,
With regards to the parameters alignment for the function, could you
kindly remind me the rule of alignment? I'm using the thunderbird
mail client and I'm not sure if the alignment I see is what you expect.
If the rule can be specified, I can align all the function parameters in
this patch series according to this rule.
Best,
Tao
Hi Suzuki,
Can I follow the following rules to handle the similar case?
"Descendants are always substantially shorter than the parent and are placed substantially to the right.
A very commonly used style is to align descendants to a function open parenthesis."
Best,
Tao
+{ + 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);
+ return size; +} +static DEVICE_ATTR_WO(reset);
/* * value 1: 64 bits test data * value 2: 32 bits test data @@ -199,6 +220,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, };
Suzuki
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
On 14/08/2023 08:08, Tao Zhang wrote:
On 8/13/2023 11:38 PM, Tao Zhang wrote:
On 8/9/2023 2:35 PM, Tao Zhang wrote:
On 8/7/2023 5:36 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 4a58e64..dbc2fbd0 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.5
+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.
Please fix this, we don't disable TPDM. If it only ever resets the datasets, please could we rename this as such ?
i.e., reset_dataset or reset_dsb_data ?
Sure, I will update this in the next patch series.
+ 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 52aa48a6..acc3eea 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -159,6 +159,27 @@ 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)
Minor nit: alignment ? Could we have something like :
static ssize_t reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
I will update this in the next patch series.
Best,
Tao
Hi Suzuki,
With regards to the parameters alignment for the function, could you
kindly remind me the rule of alignment? I'm using the thunderbird
mail client and I'm not sure if the alignment I see is what you expect.
It is not about the mail client, I am looking at the code with this series applied to the code.
If the rule can be specified, I can align all the function parameters in
this patch series according to this rule.
Best,
Tao
Hi Suzuki,
Can I follow the following rules to handle the similar case?
"Descendants are always substantially shorter than the parent and are placed substantially to the right.
A very commonly used style is to align descendants to a function open parenthesis."
Yes, this is what I expect.
Suzuki
Best,
Tao
+{ + 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);
+ return size; +} +static DEVICE_ATTR_WO(reset);
/* * value 1: 64 bits test data * value 2: 32 bits test data @@ -199,6 +220,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, };
Suzuki
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
CoreSight mailing list -- coresight@lists.linaro.org To unsubscribe send an email to coresight-leave@lists.linaro.org
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 | 94 ++++++++++++++++++++++ 2 files changed, 118 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index dbc2fbd0..0b7b4ad 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.5 +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.5 +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 acc3eea..62efc18 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,18 @@
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 && (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) { @@ -229,8 +241,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 25/07/2023 08:15, 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 | 94 ++++++++++++++++++++++ 2 files changed, 118 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index dbc2fbd0..0b7b4ad 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.5 +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.
Please use: (RW) instead of (Write).
(RW) Set/Get the trigger type of the DSB for TPDM. Similarly for the items below.
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.5 +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 acc3eea..62efc18 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,18 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static umode_t tpdm_dsb_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
Please keep the alignment.
+{
- struct device *dev = kobj_to_dev(kobj);
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- if (drvdata && (drvdata->datasets & TPDM_PIDR0_DS_DSB))
As suggested earlier, add a wrapper for the above check.
return attr->mode;
- return 0;
+}
- static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) { if (drvdata->datasets & TPDM_PIDR0_DS_DSB) {
@@ -229,8 +241,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)
Please follow the above alignment for all functions throughout the series. There are unaligned parameter lists scattered around the series.
+{
- 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.
Suzuk
On 8/7/2023 5:42 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 94 ++++++++++++++++++++++ 2 files changed, 118 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index dbc2fbd0..0b7b4ad 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.5 +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.
Please use: (RW) instead of (Write).
(RW) Set/Get the trigger type of the DSB for TPDM. Similarly for the items below.
I will update this in the next patch series.
+ 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.5 +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 acc3eea..62efc18 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -20,6 +20,18 @@ DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); +static umode_t tpdm_dsb_is_visible(struct kobject *kobj, + struct attribute *attr, int n)
Please keep the alignment.
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 && (drvdata->datasets & TPDM_PIDR0_DS_DSB))
As suggested earlier, add a wrapper for the above check.
I will update this in the next patch series.
+ return attr->mode;
+ return 0; +}
static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) { if (drvdata->datasets & TPDM_PIDR0_DS_DSB) { @@ -229,8 +241,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)
Please follow the above alignment for all functions throughout the series. There are unaligned parameter lists scattered around the series.
I will update this in the next patch series.
Best,
Tao
+{ + 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.
Suzuk
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 0b7b4ad..2a82cd0 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.5 +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 62efc18..c38760b 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> @@ -42,6 +43,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 tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val; @@ -55,6 +82,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 */ if (drvdata->dsb->trig_type) val |= TPDM_DSB_CR_TRIG_TYPE; @@ -241,6 +274,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_DSB_MODE_MASK; + 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) { @@ -312,6 +373,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 92c34cd..49fffb1 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)) +/* Performance mode */ +#define TPDM_DSB_MODE_PERF BIT(3) +/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_DSB_MODE_MASK GENMASK(8, 0) +#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 25/07/2023 08:15, 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 0b7b4ad..2a82cd0 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.5 +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.
(RW) ...
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 62efc18..c38760b 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> @@ -42,6 +43,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 tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val;
@@ -55,6 +82,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);
Couldn't all of them be combined to a single function, as they operate on a single value to be written ?
set_dsb_mode(drvdata, &val);
/* Set trigger type */ if (drvdata->dsb->trig_type) val |= TPDM_DSB_CR_TRIG_TYPE; @@ -241,6 +274,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);
It is u32 anyways, hence why not :
(buf, "%x\n", 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;
Is it not an error : if (val & ~TPDM_DSB_MODE_MASK) ?
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK;
- 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) {
@@ -312,6 +373,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 92c34cd..49fffb1 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))
What is the difference between MODE_TEST ^ and the TEST_MODE ( below ). Please could we have clear naming conventions ?
+/* Performance mode */ +#define TPDM_DSB_MODE_PERF BIT(3)
+/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_DSB_MODE_MASK GENMASK(8, 0)
+#define TPDM_DSB_TEST_MODE GENMASK(10, 9) +#define TPDM_DSB_HPSEL GENMASK(6, 2)
Ah, I read it again and these two are really TPDM_DSB_CR_x and 1) Must be defined as such (to avoid any confusion as above) 2) And defined closer to the other value defintions for the registers ?
Suzuki
- /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) #define TPDM_ITCNTRL (0xF00)
@@ -48,10 +62,12 @@ /**
- struct dsb_dataset - specifics associated to dsb dataset
*/ struct dsb_dataset {
- @mode: DSB programming mode
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- u32 mode; bool trig_ts; bool trig_type; };
On 8/7/2023 6:00 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 0b7b4ad..2a82cd0 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.5 +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.
(RW) ...
Sure, I will update this to the next patch series.
+ 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 62efc18..c38760b 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> @@ -42,6 +43,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 tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val; @@ -55,6 +82,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);
Couldn't all of them be combined to a single function, as they operate on a single value to be written ?
set_dsb_mode(drvdata, &val);
Yes, I will update this to the next patch series.
/* Set trigger type */ if (drvdata->dsb->trig_type) val |= TPDM_DSB_CR_TRIG_TYPE; @@ -241,6 +274,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);
It is u32 anyways, hence why not :
(buf, "%x\n", drvdata->dsb->mode) ?
Sure, I will update this to the next patch series.
+}
+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;
Is it not an error : if (val & ~TPDM_DSB_MODE_MASK) ?
We don't need to care about the data bits besides TPDM_DSB_MODE_MASK.
Do you think it is necessary to add this check?
If so, I can add this check in the next patch series.
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK; + 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) { @@ -312,6 +373,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 92c34cd..49fffb1 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))
What is the difference between MODE_TEST ^ and the TEST_MODE ( below ). Please could we have clear naming conventions ?
"TPDM_DSB_MODE_TEST" is to collect the data of test mode from user space input.
"TPDM_DSB_TEST_MODE" is to set the data bits collected by "TPDM_DSB_MODE_TEST"
to "TPDM_DSB_CR" register.
I will prefix the macro which is related to "TPDM_DSB_CR" to identify.
+/* Performance mode */ +#define TPDM_DSB_MODE_PERF BIT(3)
+/* High performance mode */ +#define TPDM_DSB_MODE_HPBYTESEL(val) (val & GENMASK(8, 4)) +#define TPDM_DSB_MODE_MASK GENMASK(8, 0)
+#define TPDM_DSB_TEST_MODE GENMASK(10, 9) +#define TPDM_DSB_HPSEL GENMASK(6, 2)
Ah, I read it again and these two are really TPDM_DSB_CR_x and
- Must be defined as such (to avoid any confusion as above)
- And defined closer to the other value defintions for the registers ?
Sure, I will update this according to your advice in the next patch series.
Best,
Tao
Suzuki
/* 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; };
Add the nodes to set value for DSB edge control and DSB edge control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. DSB edge detection control 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask. Eight 32 bit registers providing DSB interface edge detection mask control.
Add the nodes to configure DSB edge control and DSB edge control mask. Each DSB subunit TPDM maximum of 256 edge detections can be configured. The index and value sysfs files need to be paired and written to order. The index sysfs file is to set the index number of the edge detection which needs to be configured. And the value sysfs file is to set the control or mask for the edge detection. DSB edge detection control should be set as the following values. 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And DSB edge mask should be set as 0 or 1. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com --- .../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++- 3 files changed, 223 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 2a82cd0..a4550c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,42 @@ Description: Bit[3] : Set to 0 for low performance mode. Set to 1 for high performance mode. Bit[4:8] : Select byte lane for high performance mode. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of the edge detection for the DSB + subunit TPDM. Since there are at most 256 edge detections, this + value ranges from 0 to 255. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control registers of the DSB in TPDM. + Write a data to control the edge detection corresponding to + the index number. Before writing data to this sysfs file, + "dsb_edge_ctrl_idx" should be written first to configure the + index number of the edge detection which needs to be controlled. + + Accepts only one of the following values. + 0 - Rising edge detection + 1 - Falling edge detection + 2 - Rising and falling edge detection (toggle detection) + + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control mask registers of the DSB in TPDM. + Write a data to mask the edge detection corresponding to the index + number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx" + should be written first to configure the index number of the edge + detection which needs to be masked. + + Accepts only one of the 2 values - 0 or 1. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index c38760b..98fd6ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val)
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { - u32 val; + u32 val, i; + + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl[i], + drvdata->base + TPDM_DSB_EDCR(i)); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], + drvdata->base + TPDM_DSB_EDCMR(i));
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode);
+static ssize_t dsb_edge_ctrl_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->edge_ctrl_idx); +} + +/* + * The EDCR registers can include up to 16 32-bit registers, and each + * one can be configured to control up to 16 edge detections(2 bits + * control one edge detection). So a total 256 edge detections can be + * configured. This function provides a way to set the index number of + * the edge detection which needs to be configured. + */ +static ssize_t dsb_edge_ctrl_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->edge_ctrl_idx = val; + spin_unlock(&drvdata->spinlock); + + return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx); + +static ssize_t dsb_edge_ctrl_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +/* + * This function is used to control the edge detection according + * to the index number that has been set. + * "edge_ctrl" should be one of the following values. + * 0 - Rising edge detection + * 1 - Falling edge detection + * 2 - Rising and falling edge detection (toggle detection) + */ +static ssize_t dsb_edge_ctrl_val_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val, mask, edge_ctrl; + int reg; + + if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val = drvdata->dsb->edge_ctrl[reg]; + val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx); + drvdata->dsb->edge_ctrl[reg] = val; + spin_unlock(&drvdata->spinlock); + + return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_val); + +static ssize_t dsb_edge_ctrl_mask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + u32 set; + int reg; + + if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + else + set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + drvdata->dsb->edge_ctrl_mask[reg] = set; + spin_unlock(&drvdata->spinlock); + + return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_mask); + static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts);
static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl_idx.attr, + &dev_attr_dsb_edge_ctrl_val.attr, + &dev_attr_dsb_edge_ctrl_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, NULL, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 49fffb1..4afdb29 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -12,6 +12,8 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) #define TPDM_DSB_TIER (0x784) +#define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) +#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
/* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -34,6 +36,16 @@ #define TPDM_DSB_TEST_MODE GENMASK(10, 9) #define TPDM_DSB_HPSEL GENMASK(6, 2)
+#define EDCRS_PER_WORD 16 +#define EDCR_TO_WORD_IDX(r) ((r) / EDCRS_PER_WORD) +#define EDCR_TO_WORD_SHIFT(r) ((r % EDCRS_PER_WORD) * 2) +#define EDCR_TO_WORD_VAL(val, r) (val << EDCR_TO_WORD_SHIFT(r)) +#define EDCR_TO_WORD_MASK(r) EDCR_TO_WORD_VAL(0x3, r) + +#define EDCMRS_PER_WORD 32 +#define EDCMR_TO_WORD_IDX(r) ((r) / EDCMRS_PER_WORD) +#define EDCMR_TO_WORD_SHIFT(r) ((r) % EDCMRS_PER_WORD) + /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) #define TPDM_ITCNTRL (0xF00) @@ -60,14 +72,26 @@ #define TPDM_PIDR0_DS_IMPDEF BIT(0) #define TPDM_PIDR0_DS_DSB BIT(1)
+#define TPDM_DSB_MAX_LINES 256 +/* MAX number of EDCR registers */ +#define TPDM_DSB_MAX_EDCR 16 +/* MAX number of EDCMR registers */ +#define TPDM_DSB_MAX_EDCMR 8 + /** * struct dsb_dataset - specifics associated to dsb dataset - * @mode: DSB programming mode - * @trig_ts: Enable/Disable trigger timestamp. - * @trig_type: Enable/Disable trigger type. + * @mode: DSB programming mode + * @edge_ctrl_idx Index number of the edge control + * @edge_ctrl: Save value for edge control + * @edge_ctrl_mask: Save value for edge control mask + * @trig_ts: Enable/Disable trigger timestamp. + * @trig_type: Enable/Disable trigger type. */ struct dsb_dataset { u32 mode; + u32 edge_ctrl_idx; + u32 edge_ctrl[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR]; bool trig_ts; bool trig_type; };
On 25/07/2023 08:15, Tao Zhang wrote:
Add the nodes to set value for DSB edge control and DSB edge control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. DSB edge detection control 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask. Eight 32 bit registers providing DSB interface edge detection mask control.
Add the nodes to configure DSB edge control and DSB edge control mask. Each DSB subunit TPDM maximum of 256 edge detections can be configured. The index and value sysfs files need to be paired and written to order. The index sysfs file is to set the index number of the edge detection which needs to be configured. And the value sysfs file is to set the control or mask for the edge detection. DSB edge detection control should be set as the following values. 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And DSB edge mask should be set as 0 or 1. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++- 3 files changed, 223 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 2a82cd0..a4550c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,42 @@ Description: Bit[3] : Set to 0 for low performance mode. Set to 1 for high performance mode. Bit[4:8] : Select byte lane for high performance mode.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write the index number of the edge detection for the DSB
subunit TPDM. Since there are at most 256 edge detections, this
value ranges from 0 to 255.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the edge control registers of the DSB in TPDM.
Write a data to control the edge detection corresponding to
the index number. Before writing data to this sysfs file,
"dsb_edge_ctrl_idx" should be written first to configure the
index number of the edge detection which needs to be controlled.
Accepts only one of the following values.
0 - Rising edge detection
1 - Falling edge detection
2 - Rising and falling edge detection (toggle detection)
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the edge control mask registers of the DSB in TPDM.
Write a data to mask the edge detection corresponding to the index
number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx"
should be written first to configure the index number of the edge
detection which needs to be masked.
Accepts only one of the 2 values - 0 or 1.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index c38760b..98fd6ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) {
- u32 val;
- u32 val, i;
- for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
writel_relaxed(drvdata->dsb->edge_ctrl[i],
drvdata->base + TPDM_DSB_EDCR(i));
- for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
drvdata->base + TPDM_DSB_EDCMR(i));
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%u\n",
(unsigned int)drvdata->dsb->edge_ctrl_idx);
+}
+/*
- The EDCR registers can include up to 16 32-bit registers, and each
- one can be configured to control up to 16 edge detections(2 bits
- control one edge detection). So a total 256 edge detections can be
- configured. This function provides a way to set the index number of
- the edge detection which needs to be configured.
- */
+static ssize_t dsb_edge_ctrl_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->edge_ctrl_idx = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
+static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
bytes = sysfs_emit_at(buf, size,
"Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- This function is used to control the edge detection according
- to the index number that has been set.
- "edge_ctrl" should be one of the following values.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_val_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val, mask, edge_ctrl;
- int reg;
- if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- /*
* There are 2 bit per DSB Edge Control line.
* Thus we have 16 lines in a 32bit word.
*/
- reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
- mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
- val = drvdata->dsb->edge_ctrl[reg];
- val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
- val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
- drvdata->dsb->edge_ctrl[reg] = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
bytes = sysfs_emit_at(buf, size,
"Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- u32 set;
- int reg;
- if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- /*
* There is 1 bit per DSB Edge Control Mark line.
* Thus we have 32 lines in a 32bit word.
*/
- reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
- set = drvdata->dsb->edge_ctrl_mask[reg];
- if (val)
set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
- else
set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
drvdata->dsb->edge_ctrl_mask[reg] = set;
drivers/hwtracing/coresight/coresight-tpdm.c: In function ‘dsb_edge_ctrl_mask_store’: drivers/hwtracing/coresight/coresight-tpdm.c:449:2: error: this ‘else’ clause does not guard... [-Werror=misleading-indentation] else ^~~~ drivers/hwtracing/coresight/coresight-tpdm.c:451:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘else’ drvdata->dsb->edge_ctrl_mask[reg] = set; ^~~~~~~ cc1: all warnings being treated as errors make[4]: *** [scripts/Makefile.build:243: drivers/hwtracing/coresight/coresight-tpdm.o] Error 1 make[3]: *** [scripts/Makefile.build:480: drivers/hwtracing/coresight] Error 2 make[2]: *** [scripts/Makefile.build:480: drivers] Error 2 make[1]: *** [/ssd/src/LINUX-CORESIGHT/Makefile:2032: .] Error 2 make: *** [Makefile:234: __sub-make] Error 2
Suzuki
On 8/7/2023 5:24 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, Tao Zhang wrote:
Add the nodes to set value for DSB edge control and DSB edge control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. DSB edge detection control 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask. Eight 32 bit registers providing DSB interface edge detection mask control.
Add the nodes to configure DSB edge control and DSB edge control mask. Each DSB subunit TPDM maximum of 256 edge detections can be configured. The index and value sysfs files need to be paired and written to order. The index sysfs file is to set the index number of the edge detection which needs to be configured. And the value sysfs file is to set the control or mask for the edge detection. DSB edge detection control should be set as the following values. 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And DSB edge mask should be set as 0 or 1. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++- 3 files changed, 223 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 2a82cd0..a4550c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,42 @@ Description: Bit[3] : Set to 0 for low performance mode. Set to 1 for high performance mode. Bit[4:8] : Select byte lane for high performance mode.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of the edge detection for the DSB + subunit TPDM. Since there are at most 256 edge detections, this + value ranges from 0 to 255.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control registers of the DSB in TPDM. + Write a data to control the edge detection corresponding to + the index number. Before writing data to this sysfs file, + "dsb_edge_ctrl_idx" should be written first to configure the + index number of the edge detection which needs to be controlled.
+ Accepts only one of the following values. + 0 - Rising edge detection + 1 - Falling edge detection + 2 - Rising and falling edge detection (toggle detection)
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control mask registers of the DSB in TPDM. + Write a data to mask the edge detection corresponding to the index + number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx" + should be written first to configure the index number of the edge + detection which needs to be masked.
+ Accepts only one of the 2 values - 0 or 1. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index c38760b..98fd6ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { - u32 val; + u32 val, i;
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl[i], + drvdata->base + TPDM_DSB_EDCR(i)); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], + drvdata->base + TPDM_DSB_EDCMR(i)); val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->edge_ctrl_idx); +}
+/*
- The EDCR registers can include up to 16 32-bit registers, and each
- one can be configured to control up to 16 edge detections(2 bits
- control one edge detection). So a total 256 edge detections can be
- configured. This function provides a way to set the index number of
- the edge detection which needs to be configured.
- */
+static ssize_t dsb_edge_ctrl_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->edge_ctrl_idx = val; + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
+static ssize_t dsb_edge_ctrl_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- This function is used to control the edge detection according
- to the index number that has been set.
- "edge_ctrl" should be one of the following values.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_val_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val, mask, edge_ctrl; + int reg;
+ if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val = drvdata->dsb->edge_ctrl[reg]; + val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx); + drvdata->dsb->edge_ctrl[reg] = val; + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +}
+static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + u32 set; + int reg;
+ if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + else + set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + drvdata->dsb->edge_ctrl_mask[reg] = set;
drivers/hwtracing/coresight/coresight-tpdm.c: In function ‘dsb_edge_ctrl_mask_store’: drivers/hwtracing/coresight/coresight-tpdm.c:449:2: error: this ‘else’ clause does not guard... [-Werror=misleading-indentation] else ^~~~ drivers/hwtracing/coresight/coresight-tpdm.c:451:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘else’ drvdata->dsb->edge_ctrl_mask[reg] = set; ^~~~~~~ cc1: all warnings being treated as errors make[4]: *** [scripts/Makefile.build:243: drivers/hwtracing/coresight/coresight-tpdm.o] Error 1 make[3]: *** [scripts/Makefile.build:480: drivers/hwtracing/coresight] Error 2 make[2]: *** [scripts/Makefile.build:480: drivers] Error 2 make[1]: *** [/ssd/src/LINUX-CORESIGHT/Makefile:2032: .] Error 2 make: *** [Makefile:234: __sub-make] Error 2
I will update this in the next patch series.
Best,
Tao
Suzuki
On 25/07/2023 08:15, Tao Zhang wrote:
Add the nodes to set value for DSB edge control and DSB edge control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. DSB edge detection control 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask. Eight 32 bit registers providing DSB interface edge detection mask control.
Add the nodes to configure DSB edge control and DSB edge control mask. Each DSB subunit TPDM maximum of 256 edge detections can be configured. The index and value sysfs files need to be paired and written to order. The index sysfs file is to set the index number of the edge detection which needs to be configured. And the value sysfs file is to set the control or mask for the edge detection. DSB edge detection control should be set as the following values. 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And DSB edge mask should be set as 0 or 1. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++- 3 files changed, 223 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 2a82cd0..a4550c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,42 @@ Description: Bit[3] : Set to 0 for low performance mode. Set to 1 for high performance mode. Bit[4:8] : Select byte lane for high performance mode.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write the index number of the edge detection for the DSB
subunit TPDM. Since there are at most 256 edge detections, this
value ranges from 0 to 255.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the edge control registers of the DSB in TPDM.
Write a data to control the edge detection corresponding to
the index number. Before writing data to this sysfs file,
"dsb_edge_ctrl_idx" should be written first to configure the
index number of the edge detection which needs to be controlled.
Accepts only one of the following values.
0 - Rising edge detection
1 - Falling edge detection
2 - Rising and falling edge detection (toggle detection)
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the edge control mask registers of the DSB in TPDM.
Write a data to mask the edge detection corresponding to the index
number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx"
should be written first to configure the index number of the edge
detection which needs to be masked.
Accepts only one of the 2 values - 0 or 1.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index c38760b..98fd6ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) {
- u32 val;
- u32 val, i;
- for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
writel_relaxed(drvdata->dsb->edge_ctrl[i],
drvdata->base + TPDM_DSB_EDCR(i));
- for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
drvdata->base + TPDM_DSB_EDCMR(i));
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%u\n",
(unsigned int)drvdata->dsb->edge_ctrl_idx);
+}
+/*
- The EDCR registers can include up to 16 32-bit registers, and each
- one can be configured to control up to 16 edge detections(2 bits
- control one edge detection). So a total 256 edge detections can be
- configured. This function provides a way to set the index number of
- the edge detection which needs to be configured.
- */
+static ssize_t dsb_edge_ctrl_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->edge_ctrl_idx = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
+static ssize_t dsb_edge_ctrl_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
bytes = sysfs_emit_at(buf, size,
"Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
This feels a bit odd. edget_ctrl_val allows storing one "edge ctrl" value, while "show"ing all EDCR values. We could split them to :
Read only sysfs files:
dsb_edcr0 ... dsb_edcr15
for each EDCR register (similarly for the mask)
and may be show the specific edge_ctrl_line for with the above function for selected index.
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+/*
- This function is used to control the edge detection according
- to the index number that has been set.
- "edge_ctrl" should be one of the following values.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_val_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val, mask, edge_ctrl;
- int reg;
- if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- /*
* There are 2 bit per DSB Edge Control line.
* Thus we have 16 lines in a 32bit word.
*/
- reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
- mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
- val = drvdata->dsb->edge_ctrl[reg];
- val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx);
- val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx);
- drvdata->dsb->edge_ctrl[reg] = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
This can be WO attribute to write to a given line.
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) {
bytes = sysfs_emit_at(buf, size,
"Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
As mentioned above, please don't do this. One value per file. Add
dsb_edcmr0..dsb_edcmr7
and print only the selected index mask for this function.
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_edge_ctrl_mask_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- u32 set;
- int reg;
- if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- /*
* There is 1 bit per DSB Edge Control Mark line.
* Thus we have 32 lines in a 32bit word.
*/
- reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx);
- set = drvdata->dsb->edge_ctrl_mask[reg];
- if (val)
set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
- else
set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx));
drvdata->dsb->edge_ctrl_mask[reg] = set;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
- static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) {
@@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr,
- &dev_attr_dsb_edge_ctrl_idx.attr,
- &dev_attr_dsb_edge_ctrl_val.attr,
- &dev_attr_dsb_edge_ctrl_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, NULL,
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 49fffb1..4afdb29 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -12,6 +12,8 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) #define TPDM_DSB_TIER (0x784) +#define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) +#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4)) /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -34,6 +36,16 @@ #define TPDM_DSB_TEST_MODE GENMASK(10, 9) #define TPDM_DSB_HPSEL GENMASK(6, 2) +#define EDCRS_PER_WORD 16 +#define EDCR_TO_WORD_IDX(r) ((r) / EDCRS_PER_WORD) +#define EDCR_TO_WORD_SHIFT(r) ((r % EDCRS_PER_WORD) * 2) +#define EDCR_TO_WORD_VAL(val, r) (val << EDCR_TO_WORD_SHIFT(r)) +#define EDCR_TO_WORD_MASK(r) EDCR_TO_WORD_VAL(0x3, r)
+#define EDCMRS_PER_WORD 32 +#define EDCMR_TO_WORD_IDX(r) ((r) / EDCMRS_PER_WORD) +#define EDCMR_TO_WORD_SHIFT(r) ((r) % EDCMRS_PER_WORD)
- /* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) #define TPDM_ITCNTRL (0xF00)
@@ -60,14 +72,26 @@ #define TPDM_PIDR0_DS_IMPDEF BIT(0) #define TPDM_PIDR0_DS_DSB BIT(1) +#define TPDM_DSB_MAX_LINES 256 +/* MAX number of EDCR registers */ +#define TPDM_DSB_MAX_EDCR 16 +/* MAX number of EDCMR registers */ +#define TPDM_DSB_MAX_EDCMR 8
- /**
- struct dsb_dataset - specifics associated to dsb dataset
- @mode: DSB programming mode
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- @mode: DSB programming mode
- @edge_ctrl_idx Index number of the edge control
- @edge_ctrl: Save value for edge control
- @edge_ctrl_mask: Save value for edge control mask
- @trig_ts: Enable/Disable trigger timestamp.
*/ struct dsb_dataset { u32 mode;
- @trig_type: Enable/Disable trigger type.
- u32 edge_ctrl_idx;
- u32 edge_ctrl[TPDM_DSB_MAX_EDCR];
- u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
Please keep them aligned with the rest of the fields.
bool trig_ts; bool trig_type;
Suzuki
};
On 8/7/2023 6:58 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, Tao Zhang wrote:
Add the nodes to set value for DSB edge control and DSB edge control mask. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. DSB edge detection control 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask. Eight 32 bit registers providing DSB interface edge detection mask control.
Add the nodes to configure DSB edge control and DSB edge control mask. Each DSB subunit TPDM maximum of 256 edge detections can be configured. The index and value sysfs files need to be paired and written to order. The index sysfs file is to set the index number of the edge detection which needs to be configured. And the value sysfs file is to set the control or mask for the edge detection. DSB edge detection control should be set as the following values. 00: Rising edge detection 01: Falling edge detection 10: Rising and falling edge detection (toggle detection) And DSB edge mask should be set as 0 or 1. Each DSB subunit TPDM has maximum of n(n<16) EDCR resgisters to configure edge control. And each DSB subunit TPDM has maximum of m(m<8) ECDMR registers to configure mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 39 +++++ drivers/hwtracing/coresight/coresight-tpdm.c | 158 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 30 +++- 3 files changed, 223 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 2a82cd0..a4550c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -60,3 +60,42 @@ Description: Bit[3] : Set to 0 for low performance mode. Set to 1 for high performance mode. Bit[4:8] : Select byte lane for high performance mode.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of the edge detection for the DSB + subunit TPDM. Since there are at most 256 edge detections, this + value ranges from 0 to 255.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control registers of the DSB in TPDM. + Write a data to control the edge detection corresponding to + the index number. Before writing data to this sysfs file, + "dsb_edge_ctrl_idx" should be written first to configure the + index number of the edge detection which needs to be controlled.
+ Accepts only one of the following values. + 0 - Rising edge detection + 1 - Falling edge detection + 2 - Rising and falling edge detection (toggle detection)
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge_ctrl_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the edge control mask registers of the DSB in TPDM. + Write a data to mask the edge detection corresponding to the index + number. Before writing data to this sysfs file, "dsb_edge_ctrl_idx" + should be written first to configure the index number of the edge + detection which needs to be masked.
+ Accepts only one of the 2 values - 0 or 1. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index c38760b..98fd6ab 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -71,7 +71,14 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { - u32 val; + u32 val, i;
+ for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl[i], + drvdata->base + TPDM_DSB_EDCR(i)); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) + writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], + drvdata->base + TPDM_DSB_EDCMR(i)); val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ @@ -302,6 +309,152 @@ static ssize_t dsb_mode_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_mode); +static ssize_t dsb_edge_ctrl_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->edge_ctrl_idx); +}
+/*
- The EDCR registers can include up to 16 32-bit registers, and each
- one can be configured to control up to 16 edge detections(2 bits
- control one edge detection). So a total 256 edge detections can be
- configured. This function provides a way to set the index number of
- the edge detection which needs to be configured.
- */
+static ssize_t dsb_edge_ctrl_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->edge_ctrl_idx = val; + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_idx);
+static ssize_t dsb_edge_ctrl_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl[i]);
This feels a bit odd. edget_ctrl_val allows storing one "edge ctrl" value, while "show"ing all EDCR values. We could split them to :
Read only sysfs files:
dsb_edcr0 ... dsb_edcr15
for each EDCR register (similarly for the mask)
and may be show the specific edge_ctrl_line for with the above function for selected index.
Sure, I will update this in the next patch series.
+ if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +}
+/*
- This function is used to control the edge detection according
- to the index number that has been set.
- "edge_ctrl" should be one of the following values.
- 0 - Rising edge detection
- 1 - Falling edge detection
- 2 - Rising and falling edge detection (toggle detection)
- */
+static ssize_t dsb_edge_ctrl_val_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val, mask, edge_ctrl; + int reg;
+ if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + /* + * There are 2 bit per DSB Edge Control line. + * Thus we have 16 lines in a 32bit word. + */ + reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + mask = EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val = drvdata->dsb->edge_ctrl[reg]; + val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); + val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx); + drvdata->dsb->edge_ctrl[reg] = val; + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_val);
This can be WO attribute to write to a given line.
I will update this in the next patch series.
+static ssize_t dsb_edge_ctrl_mask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) { + bytes = sysfs_emit_at(buf, size, + "Val:0x%x\n", drvdata->dsb->edge_ctrl_mask[i]);
As mentioned above, please don't do this. One value per file. Add
dsb_edcmr0..dsb_edcmr7
and print only the selected index mask for this function.
I will update this in the next patch series.
+ if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +}
+static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + u32 set; + int reg;
+ if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + /* + * There is 1 bit per DSB Edge Control Mark line. + * Thus we have 32 lines in a 32bit word. + */ + reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); + set = drvdata->dsb->edge_ctrl_mask[reg]; + if (val) + set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + else + set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); + drvdata->dsb->edge_ctrl_mask[reg] = set; + spin_unlock(&drvdata->spinlock);
+ return size; +} +static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -374,6 +527,9 @@ static DEVICE_ATTR_RW(dsb_trig_ts); static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_mode.attr, + &dev_attr_dsb_edge_ctrl_idx.attr, + &dev_attr_dsb_edge_ctrl_val.attr, + &dev_attr_dsb_edge_ctrl_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, NULL, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 49fffb1..4afdb29 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -12,6 +12,8 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) #define TPDM_DSB_TIER (0x784) +#define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) +#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4)) /* Enable bit for DSB subunit */ #define TPDM_DSB_CR_ENA BIT(0) @@ -34,6 +36,16 @@ #define TPDM_DSB_TEST_MODE GENMASK(10, 9) #define TPDM_DSB_HPSEL GENMASK(6, 2) +#define EDCRS_PER_WORD 16 +#define EDCR_TO_WORD_IDX(r) ((r) / EDCRS_PER_WORD) +#define EDCR_TO_WORD_SHIFT(r) ((r % EDCRS_PER_WORD) * 2) +#define EDCR_TO_WORD_VAL(val, r) (val << EDCR_TO_WORD_SHIFT(r)) +#define EDCR_TO_WORD_MASK(r) EDCR_TO_WORD_VAL(0x3, r)
+#define EDCMRS_PER_WORD 32 +#define EDCMR_TO_WORD_IDX(r) ((r) / EDCMRS_PER_WORD) +#define EDCMR_TO_WORD_SHIFT(r) ((r) % EDCMRS_PER_WORD)
/* TPDM integration test registers */ #define TPDM_ITATBCNTRL (0xEF0) #define TPDM_ITCNTRL (0xF00) @@ -60,14 +72,26 @@ #define TPDM_PIDR0_DS_IMPDEF BIT(0) #define TPDM_PIDR0_DS_DSB BIT(1) +#define TPDM_DSB_MAX_LINES 256 +/* MAX number of EDCR registers */ +#define TPDM_DSB_MAX_EDCR 16 +/* MAX number of EDCMR registers */ +#define TPDM_DSB_MAX_EDCMR 8
/** * struct dsb_dataset - specifics associated to dsb dataset
- @mode: DSB programming mode
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
- @mode: DSB programming mode
- @edge_ctrl_idx Index number of the edge control
- @edge_ctrl: Save value for edge control
- @edge_ctrl_mask: Save value for edge control mask
- @trig_ts: Enable/Disable trigger timestamp.
- @trig_type: Enable/Disable trigger type.
*/ struct dsb_dataset { u32 mode; + u32 edge_ctrl_idx; + u32 edge_ctrl[TPDM_DSB_MAX_EDCR]; + u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
Please keep them aligned with the rest of the fields.
I will update this in the next patch series.
Best,
Tao
bool trig_ts; bool trig_type;
Suzuki
};
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 | 34 +++++- drivers/hwtracing/coresight/coresight-tpdm.c | 118 +++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 10 ++ 3 files changed, 161 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a4550c5..66f9582 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -98,4 +98,36 @@ Description: should be written first to configure the index number of the edge detection which needs to be masked.
- Accepts only one of the 2 values - 0 or 1. \ No newline at end of file + Accepts only one of the 2 values - 0 or 1. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of the trigger pattern value of DSB + tpdm. Since there are at most 8 XPR and XPMR registers for the + trigger parttern, this value ranges from 0 to 7. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the trigger pattern values of the DSB TPDM. + Write a data to configure the trigger pattern corresponding to + the index number. Before writing data to this sysfs file, + "dsb_trig_patt_idx" should be written first to configure the + index number of the trigger pattern which needs to be configured. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the trigger pattern mask of the DSB TPDM. + Write a data to configure the trigger pattern mask corresponding + to the index number. Before writing data to this sysfs file, + "dsb_trig_patt_idx" should be written first to configure the + index number of the trigger pattern mask which needs to be + configured. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 98fd6ab..1c32d27 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,6 +80,13 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], drvdata->base + TPDM_DSB_EDCMR(i));
+ for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + writel_relaxed(drvdata->dsb->trig_patt[i], + drvdata->base + TPDM_DSB_XPR(i)); + writel_relaxed(drvdata->dsb->trig_patt_mask[i], + drvdata->base + TPDM_DSB_XPMR(i)); + } + val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ if (drvdata->dsb->trig_ts) @@ -455,6 +462,114 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+static ssize_t dsb_trig_patt_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->trig_patt_idx); +} + +static ssize_t dsb_trig_patt_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index; + + if (kstrtoul(buf, 0, &index)) + return -EINVAL; + if (index >= TPDM_DSB_MAX_PATT) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt_idx = index; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_patt_idx); + +static ssize_t dsb_trig_patt_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + bytes = sysfs_emit_at(buf, size, + "Value: 0x%x\n", drvdata->dsb->trig_patt[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t dsb_trig_patt_val_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt[drvdata->dsb->trig_patt_idx] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_patt_val); + +static ssize_t dsb_trig_patt_mask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + bytes = sysfs_emit_at(buf, size, + "Value: 0x%x\n", drvdata->dsb->trig_patt_mask[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t dsb_trig_patt_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->trig_patt_mask[drvdata->dsb->trig_patt_idx] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_trig_patt_mask); + static ssize_t dsb_trig_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -530,6 +645,9 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_edge_ctrl_idx.attr, &dev_attr_dsb_edge_ctrl_val.attr, &dev_attr_dsb_edge_ctrl_mask.attr, + &dev_attr_dsb_trig_patt_idx.attr, + &dev_attr_dsb_trig_patt_val.attr, + &dev_attr_dsb_trig_patt_mask.attr, &dev_attr_dsb_trig_ts.attr, &dev_attr_dsb_trig_type.attr, NULL, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 4afdb29..7f688b2 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -12,6 +12,8 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) #define TPDM_DSB_TIER (0x784) +#define TPDM_DSB_XPR(n) (0x7C8 + (n * 4)) +#define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4)) #define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) #define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
@@ -77,21 +79,29 @@ #define TPDM_DSB_MAX_EDCR 16 /* MAX number of EDCMR registers */ #define TPDM_DSB_MAX_EDCMR 8 +/* MAX number of DSB pattern */ +#define TPDM_DSB_MAX_PATT 8
/** * struct dsb_dataset - specifics associated to dsb dataset * @mode: DSB programming mode * @edge_ctrl_idx Index number of the edge control + * @trig_patt_idx Index number of the trigger pattern * @edge_ctrl: Save value for edge control * @edge_ctrl_mask: Save value for edge control mask + * @trig_patt: Save value for trigger pattern + * @trig_patt_mask: Save value for trigger pattern mask * @trig_ts: Enable/Disable trigger timestamp. * @trig_type: Enable/Disable trigger type. */ struct dsb_dataset { u32 mode; u32 edge_ctrl_idx; + u32 trig_patt_idx; u32 edge_ctrl[TPDM_DSB_MAX_EDCR]; u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR]; + u32 trig_patt[TPDM_DSB_MAX_PATT]; + u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; bool trig_ts; bool trig_type; };
On 25/07/2023 08:15, Tao Zhang wrote:
Add nodes to configure trigger pattern and trigger pattern mask. Each DSB subunit TPDM has maximum of n(n<7) XPR registers to configure trigger pattern match output. Eight 32 bit registers providing DSB interface trigger output pattern match comparison. And each DSB subunit TPDM has maximum of m(m<7) XPMR registers to configure trigger pattern mask match output. Eight 32 bit registers providing DSB interface trigger output pattern match mask.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 34 +++++- drivers/hwtracing/coresight/coresight-tpdm.c | 118 +++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 10 ++ 3 files changed, 161 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index a4550c5..66f9582 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -98,4 +98,36 @@ Description: should be written first to configure the index number of the edge detection which needs to be masked.
Accepts only one of the 2 values - 0 or 1.
\ No newline at end of file
Accepts only one of the 2 values - 0 or 1.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write the index number of the trigger pattern value of DSB
tpdm. Since there are at most 8 XPR and XPMR registers for the
trigger parttern, this value ranges from 0 to 7.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the trigger pattern values of the DSB TPDM.
Write a data to configure the trigger pattern corresponding to
the index number. Before writing data to this sysfs file,
"dsb_trig_patt_idx" should be written first to configure the
index number of the trigger pattern which needs to be configured.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the trigger pattern mask of the DSB TPDM.
Write a data to configure the trigger pattern mask corresponding
to the index number. Before writing data to this sysfs file,
"dsb_trig_patt_idx" should be written first to configure the
index number of the trigger pattern mask which needs to be
configured.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 98fd6ab..1c32d27 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -80,6 +80,13 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], drvdata->base + TPDM_DSB_EDCMR(i));
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
writel_relaxed(drvdata->dsb->trig_patt[i],
drvdata->base + TPDM_DSB_XPR(i));
writel_relaxed(drvdata->dsb->trig_patt_mask[i],
drvdata->base + TPDM_DSB_XPMR(i));
- }
- val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); /* Set trigger timestamp */ if (drvdata->dsb->trig_ts)
@@ -455,6 +462,114 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask); +static ssize_t dsb_trig_patt_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%u\n",
(unsigned int)drvdata->dsb->trig_patt_idx);
+}
+static ssize_t dsb_trig_patt_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long index;
- if (kstrtoul(buf, 0, &index))
return -EINVAL;
- if (index >= TPDM_DSB_MAX_PATT)
return -EPERM;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->trig_patt_idx = index;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_trig_patt_idx);
+static ssize_t dsb_trig_patt_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
bytes = sysfs_emit_at(buf, size,
"Value: 0x%x\n", drvdata->dsb->trig_patt[i]);
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_trig_patt_val_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->trig_patt[drvdata->dsb->trig_patt_idx] = val;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_trig_patt_val);
+static ssize_t dsb_trig_patt_mask_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
bytes = sysfs_emit_at(buf, size,
"Value: 0x%x\n", drvdata->dsb->trig_patt_mask[i]);
As mentioned above, please stick to single value. In this case, we could simply expose :
dsb_trig_patt_mask0..7 as RW and directly let the user set/get the values and get rid of the idx.
You may be able to use an device_ext_attribute to store the index and use a single function to support all registers.
Suzuki
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 | 57 +++++- drivers/hwtracing/coresight/coresight-tpdm.c | 205 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++ 3 files changed, 272 insertions(+), 6 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 66f9582..74a0126 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -130,4 +130,59 @@ Description: to the index number. Before writing data to this sysfs file, "dsb_trig_patt_idx" should be written first to configure the index number of the trigger pattern mask which needs to be - configured. \ No newline at end of file + configured. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of the DSB tpdm pattern. Since + there are at most 8 TPR and TPMR registers for the parttern, + this value ranges from 0 to 7. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the pattern values of the DSB TPDM. Write a data + to configure the pattern corresponding to the index number. + Before writing data to this sysfs file, "dsb_patt_idx" should be + written first to configure the index number of the pattern which + needs to be configured. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read a set of the pattern mask values of the DSB TPDM. Write a + data to configure the pattern mask corresponding to the index + number. Before writing data to this sysfs file, "dsb_patt_idx" + should be written first to configure the index number of the + pattern mask which needs to be configured. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) 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.5 +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. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1c32d27..f9e5a1d 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -69,6 +69,27 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) *val &= ~TPDM_DSB_CR_MODE; }
+static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) +{ + /* Set pattern timestamp type and enablement */ + if (drvdata->dsb->patt_ts) { + *val |= TPDM_DSB_TIER_PATT_TSENAB; + if (drvdata->dsb->patt_type) + *val |= TPDM_DSB_TIER_PATT_TYPE; + else + *val &= ~TPDM_DSB_TIER_PATT_TYPE; + } else { + *val &= ~TPDM_DSB_TIER_PATT_TSENAB; + } + + /* Set trigger timestamp */ + if (drvdata->dsb->trig_ts) + *val |= TPDM_DSB_TIER_XTRIG_TSENAB; + else + *val &= ~TPDM_DSB_TIER_XTRIG_TSENAB; + +} + static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i; @@ -81,6 +102,10 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) drvdata->base + TPDM_DSB_EDCMR(i));
for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + writel_relaxed(drvdata->dsb->patt_val[i], + drvdata->base + TPDM_DSB_TPR(i)); + writel_relaxed(drvdata->dsb->patt_mask[i], + drvdata->base + TPDM_DSB_TPMR(i)); writel_relaxed(drvdata->dsb->trig_patt[i], drvdata->base + TPDM_DSB_XPR(i)); writel_relaxed(drvdata->dsb->trig_patt_mask[i], @@ -88,11 +113,7 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) }
val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); - /* Set trigger timestamp */ - if (drvdata->dsb->trig_ts) - val |= TPDM_DSB_TIER_XTRIG_TSENAB; - else - val &= ~TPDM_DSB_TIER_XTRIG_TSENAB; + set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); @@ -462,6 +483,175 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask);
+static ssize_t dsb_patt_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->patt_idx); + +} + +static ssize_t dsb_patt_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index; + + if ((kstrtoul(buf, 0, &index)) || (index >= TPDM_DSB_MAX_PATT)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_idx = index; + spin_unlock(&drvdata->spinlock); + + return size; + +} +static DEVICE_ATTR_RW(dsb_patt_idx); + +static ssize_t dsb_patt_val_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + bytes = sysfs_emit_at(buf, size, + "Value: 0x%x\n", drvdata->dsb->patt_val[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t dsb_patt_val_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_val[drvdata->dsb->patt_idx] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_patt_val); + +static ssize_t dsb_patt_mask_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + unsigned long bytes; + int i = 0; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { + bytes = sysfs_emit_at(buf, size, + "Value: 0x%x\n", drvdata->dsb->patt_mask[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t dsb_patt_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_mask[drvdata->dsb->patt_idx] = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_patt_mask); + +static ssize_t dsb_patt_ts_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->patt_ts); +} + +/* + * value 1: Enable/Disable DSB pattern timestamp + */ +static ssize_t dsb_patt_ts_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_ts = !!val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_patt_ts); + +static ssize_t dsb_patt_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->patt_type); +} + +/* + * value 1: Set DSB pattern type + */ +static ssize_t dsb_patt_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->patt_type = val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_patt_type); + static ssize_t dsb_trig_patt_idx_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -645,6 +835,11 @@ static struct attribute *tpdm_dsb_attrs[] = { &dev_attr_dsb_edge_ctrl_idx.attr, &dev_attr_dsb_edge_ctrl_val.attr, &dev_attr_dsb_edge_ctrl_mask.attr, + &dev_attr_dsb_patt_idx.attr, + &dev_attr_dsb_patt_val.attr, + &dev_attr_dsb_patt_mask.attr, + &dev_attr_dsb_patt_ts.attr, + &dev_attr_dsb_patt_type.attr, &dev_attr_dsb_trig_patt_idx.attr, &dev_attr_dsb_trig_patt_val.attr, &dev_attr_dsb_trig_patt_mask.attr, diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7f688b2..7c52cf4 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.h +++ b/drivers/hwtracing/coresight/coresight-tpdm.h @@ -12,6 +12,8 @@ /* DSB Subunit Registers */ #define TPDM_DSB_CR (0x780) #define TPDM_DSB_TIER (0x784) +#define TPDM_DSB_TPR(n) (0x788 + (n * 4)) +#define TPDM_DSB_TPMR(n) (0x7A8 + (n * 4)) #define TPDM_DSB_XPR(n) (0x7C8 + (n * 4)) #define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4)) #define TPDM_DSB_EDCR(n) (0x808 + (n * 4)) @@ -24,8 +26,12 @@ /* Enable bit for DSB subunit trigger type */ #define TPDM_DSB_CR_TRIG_TYPE BIT(12)
+/* Enable bit for DSB subunit pattern timestamp */ +#define TPDM_DSB_TIER_PATT_TSENAB BIT(0) /* Enable bit for DSB subunit trigger timestamp */ #define TPDM_DSB_TIER_XTRIG_TSENAB BIT(1) +/* Bit for DSB subunit pattern type */ +#define TPDM_DSB_TIER_PATT_TYPE BIT(2)
/* DSB programming modes */ /* Test mode control bit*/ @@ -86,22 +92,32 @@ * struct dsb_dataset - specifics associated to dsb dataset * @mode: DSB programming mode * @edge_ctrl_idx Index number of the edge control + * @patt_idx Index number of pattern * @trig_patt_idx Index number of the trigger pattern * @edge_ctrl: Save value for edge control * @edge_ctrl_mask: Save value for edge control mask + * @patt_val: Save value for pattern + * @patt_mask: Save value for pattern mask * @trig_patt: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask + * @patt_ts: Enable/Disable pattern timestamp + * @patt_type: Set pattern type * @trig_ts: Enable/Disable trigger timestamp. * @trig_type: Enable/Disable trigger type. */ struct dsb_dataset { u32 mode; u32 edge_ctrl_idx; + u32 patt_idx; u32 trig_patt_idx; u32 edge_ctrl[TPDM_DSB_MAX_EDCR]; u32 edge_ctrl_mask[TPDM_DSB_MAX_EDCMR]; + u32 patt_val[TPDM_DSB_MAX_PATT]; + u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; + bool patt_ts; + bool patt_type; bool trig_ts; bool trig_type; };
On 25/07/2023 08:15, Tao Zhang wrote:
Add nodes to configure the timestamp request based on input pattern match. Each TPDM that support DSB subunit has maximum of n(n<7) TPR registers to configure value for timestamp request based on input pattern match. Eight 32 bit registers providing DSB interface timestamp request pattern match comparison. And each TPDM that support DSB subunit has maximum of m(m<7) TPMR registers to configure pattern mask for timestamp request. Eight 32 bit registers providing DSB interface timestamp request pattern match mask generation. Add nodes to enable/disable pattern timestamp and set pattern timestamp type.
Signed-off-by: Tao Zhang quic_taozha@quicinc.com
.../ABI/testing/sysfs-bus-coresight-devices-tpdm | 57 +++++- drivers/hwtracing/coresight/coresight-tpdm.c | 205 ++++++++++++++++++++- drivers/hwtracing/coresight/coresight-tpdm.h | 16 ++ 3 files changed, 272 insertions(+), 6 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 66f9582..74a0126 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -130,4 +130,59 @@ Description: to the index number. Before writing data to this sysfs file, "dsb_trig_patt_idx" should be written first to configure the index number of the trigger pattern mask which needs to be
configured.
\ No newline at end of file
configured.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write the index number of the DSB tpdm pattern. Since
there are at most 8 TPR and TPMR registers for the parttern,
this value ranges from 0 to 7.
If it is only 0-7 and we read/write full registers, why not expose individual registers as mentioned in the previous comments and avoid multi-line output for "show" routines. You may even group the registers under a directory structure to avoid confusion.
e.g, :
dsb_patt/ - mask0 ... mask7 - ts0 ... ts7 - type0 ... type7
dsb_edge/ - edcr0 ... edcr15 - edcmr0 ... edcmr7 - ctrl_idx - ctrl_idx_val ....
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_val +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the pattern values of the DSB TPDM. Write a data
to configure the pattern corresponding to the index number.
Before writing data to this sysfs file, "dsb_patt_idx" should be
written first to configure the index number of the pattern which
needs to be configured.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_mask +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read a set of the pattern mask values of the DSB TPDM. Write a
data to configure the pattern mask corresponding to the index
number. Before writing data to this sysfs file, "dsb_patt_idx"
should be written first to configure the index number of the
pattern mask which needs to be configured.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt_ts +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) 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.5 +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.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 1c32d27..f9e5a1d 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -69,6 +69,27 @@ static void set_dsb_perf_mode(struct tpdm_drvdata *drvdata, u32 *val) *val &= ~TPDM_DSB_CR_MODE; } +static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) +{
- /* Set pattern timestamp type and enablement */
- if (drvdata->dsb->patt_ts) {
*val |= TPDM_DSB_TIER_PATT_TSENAB;
if (drvdata->dsb->patt_type)
*val |= TPDM_DSB_TIER_PATT_TYPE;
else
*val &= ~TPDM_DSB_TIER_PATT_TYPE;
- } else {
*val &= ~TPDM_DSB_TIER_PATT_TSENAB;
- }
- /* Set trigger timestamp */
- if (drvdata->dsb->trig_ts)
*val |= TPDM_DSB_TIER_XTRIG_TSENAB;
- else
*val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;
+}
- static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i;
@@ -81,6 +102,10 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) drvdata->base + TPDM_DSB_EDCMR(i)); for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
writel_relaxed(drvdata->dsb->patt_val[i],
drvdata->base + TPDM_DSB_TPR(i));
writel_relaxed(drvdata->dsb->patt_mask[i],
writel_relaxed(drvdata->dsb->trig_patt[i], drvdata->base + TPDM_DSB_XPR(i)); writel_relaxed(drvdata->dsb->trig_patt_mask[i],drvdata->base + TPDM_DSB_TPMR(i));
@@ -88,11 +113,7 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) } val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
- /* Set trigger timestamp */
- if (drvdata->dsb->trig_ts)
val |= TPDM_DSB_TIER_XTRIG_TSENAB;
- else
val &= ~TPDM_DSB_TIER_XTRIG_TSENAB;
- set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); @@ -462,6 +483,175 @@ static ssize_t dsb_edge_ctrl_mask_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_edge_ctrl_mask); +static ssize_t dsb_patt_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%u\n",
(unsigned int)drvdata->dsb->patt_idx);
+}
+static ssize_t dsb_patt_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long index;
- if ((kstrtoul(buf, 0, &index)) || (index >= TPDM_DSB_MAX_PATT))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->patt_idx = index;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_patt_idx);
+static ssize_t dsb_patt_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ssize_t size = 0;
- unsigned long bytes;
- int i = 0;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
bytes = sysfs_emit_at(buf, size,
"Value: 0x%x\n", drvdata->dsb->patt_val[i]);
Please see my comment on the other patches.
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_patt_val_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if (kstrtoul(buf, 0, &val))
You have used the base for all such conversions inconsistently, throughout the series. You can always stick to 0.
$ git grep kstrtoul drivers/hwtracing/coresight/coresight-tpdm.c drivers/hwtracing/coresight/coresight-tpdm.c: ret = kstrtoul(buf, 10, &val); drivers/hwtracing/coresight/coresight-tpdm.c: ret = kstrtoul(buf, 10, &val); drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &val)) || val < 0) drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES)) drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2)) drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) drivers/hwtracing/coresight/coresight-tpdm.c: if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
Suzuki
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 | 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 931ee8f..d1d66bc 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/uint8 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
@@ -86,6 +95,7 @@ examples: reg = <0x0684c000 0x1000>;
qcom,dsb-element-size = /bits/ 8 <32>; + qcom,dsb-msrs-num = <16>;
clocks = <&aoss_qmp>; clock-names = "apb_pclk";
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 | 19 ++++- drivers/hwtracing/coresight/coresight-tpdm.c | 98 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 7 ++ 3 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 74a0126..ee41a14 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -185,4 +185,21 @@ 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. \ No newline at end of file + 1 : Set the DSB pattern type to toggle. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of MSR(mux select register) on DSB + TPDM. This index number should not be greater than the number + of MSR supported by this DSB TPDM. + +What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm. \ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f9e5a1d..be7776b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val)
}
+static void set_dsb_msr(struct tpdm_drvdata *drvdata) +{ + int i; + + if (drvdata->dsb->msr_num == 0) + return; + + for (i = 0; i < drvdata->dsb->msr_num; i++) + writel_relaxed(drvdata->dsb->msr[i], + drvdata->base + TPDM_DSB_MSR(i)); +} + static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i; @@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
+ set_dsb_msr(drvdata); + val = readl_relaxed(drvdata->base + TPDM_DSB_CR); /* Set the test accurate mode */ set_dsb_test_mode(drvdata, &val); @@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)), + GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } }
return 0; @@ -830,6 +852,80 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts);
+static ssize_t dsb_msr_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->msr_idx); + +} + +static ssize_t dsb_msr_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index; + + if (kstrtoul(buf, 0, &index)) + return -EINVAL; + if (index >= drvdata->dsb->msr_num) + return -EPERM; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->msr_idx = index; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr_idx); + +static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + unsigned long bytes; + ssize_t size = 0; + + if (drvdata->dsb->msr_num == 0) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + for (i = 0; i < drvdata->dsb->msr_num; i++) { + bytes = sysfs_emit_at(buf, size, + "0x%x\n", drvdata->dsb->msr[i]); + if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock); + + return size; +} + +static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[drvdata->dsb->msr_idx] = 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_idx.attr, @@ -845,6 +941,8 @@ 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_idx.attr, + &dev_attr_dsb_msr.attr, NULL, };
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7c52cf4..7b70db3 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) @@ -100,6 +101,9 @@ * @patt_mask: Save value for pattern mask * @trig_patt: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask + * @msr_num Number of MSR supported by DSB TPDM + * @msr_idx Index number of the MSR + * @msr Save value for MSR * @patt_ts: Enable/Disable pattern timestamp * @patt_type: Set pattern type * @trig_ts: Enable/Disable trigger timestamp. @@ -116,6 +120,9 @@ struct dsb_dataset { u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; + u32 msr_num; + u32 msr_idx; + u32 *msr; bool patt_ts; bool patt_type; bool trig_ts;
On 25/07/2023 08:15, 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 | 19 ++++- drivers/hwtracing/coresight/coresight-tpdm.c | 98 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 7 ++ 3 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 74a0126..ee41a14 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -185,4 +185,21 @@ 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.
\ No newline at end of file
1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
Read/Write the index number of MSR(mux select register) on DSB
TPDM. This index number should not be greater than the number
of MSR supported by this DSB TPDM.
How does a user find it ? Why don't we expose it ? Scratch all of that, you could create a register file per exising msr.
dsb_msrs/msr0 ... msrN
You may :
1. either dynamically add files as you find the number
OR
2. If there is a hard limit, create that many files and control visibility based on the dynamic number.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description:
(Write) Set the MSR(mux select register) of DSB tpdm. Read
the MSR(mux select register) of DSB tpdm.
(RW)
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f9e5a1d..be7776b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) } +static void set_dsb_msr(struct tpdm_drvdata *drvdata) +{
- int i;
- if (drvdata->dsb->msr_num == 0)
return;
- for (i = 0; i < drvdata->dsb->msr_num; i++)
writel_relaxed(drvdata->dsb->msr[i],
drvdata->base + TPDM_DSB_MSR(i));
+}
- static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i;
@@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER);
- set_dsb_msr(drvdata);
- val = readl_relaxed(drvdata->base + TPDM_DSB_CR); /* Set the test accurate mode */ set_dsb_test_mode(drvdata, &val);
@@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; }
if (!of_property_read_u32(drvdata->dev->of_node,
"qcom,dsb_msr_num", &drvdata->dsb->msr_num)) {
drvdata->dsb->msr = devm_kzalloc(drvdata->dev, > + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
devm_kcalloc() ?
GFP_KERNEL);
if (!drvdata->dsb->msr)
return -ENOMEM;
}}
return 0; @@ -830,6 +852,80 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_idx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- return sysfs_emit(buf, "%u\n",
(unsigned int)drvdata->dsb->msr_idx);
+}
+static ssize_t dsb_msr_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long index;
- if (kstrtoul(buf, 0, &index))
return -EINVAL;
- if (index >= drvdata->dsb->msr_num)
return -EPERM;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->msr_idx = index;
- spin_unlock(&drvdata->spinlock);
- return size;
+} +static DEVICE_ATTR_RW(dsb_msr_idx);
+static ssize_t dsb_msr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned int i;
- unsigned long bytes;
- ssize_t size = 0;
- if (drvdata->dsb->msr_num == 0)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < drvdata->dsb->msr_num; i++) {
bytes = sysfs_emit_at(buf, size,
"0x%x\n", drvdata->dsb->msr[i]);
Single value per single file.
Suzuki
if (bytes <= 0)
break;
size += bytes;
- }
- spin_unlock(&drvdata->spinlock);
- return size;
+}
+static ssize_t dsb_msr_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
+{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
- if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- drvdata->dsb->msr[drvdata->dsb->msr_idx] = 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_idx.attr,
@@ -845,6 +941,8 @@ 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_idx.attr,
- &dev_attr_dsb_msr.attr, NULL, };
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7c52cf4..7b70db3 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) @@ -100,6 +101,9 @@
- @patt_mask: Save value for pattern mask
- @trig_patt: Save value for trigger pattern
- @trig_patt_mask: Save value for trigger pattern mask
- @msr_num Number of MSR supported by DSB TPDM
- @msr_idx Index number of the MSR
- @msr Save value for MSR
- @patt_ts: Enable/Disable pattern timestamp
- @patt_type: Set pattern type
- @trig_ts: Enable/Disable trigger timestamp.
@@ -116,6 +120,9 @@ struct dsb_dataset { u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT];
- u32 msr_num;
- u32 msr_idx;
- u32 *msr; bool patt_ts; bool patt_type; bool trig_ts;
On 8/7/2023 7:35 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 19 ++++- drivers/hwtracing/coresight/coresight-tpdm.c | 98 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 7 ++ 3 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 74a0126..ee41a14 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -185,4 +185,21 @@ 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. \ No newline at end of file + 1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of MSR(mux select register) on DSB + TPDM. This index number should not be greater than the number + of MSR supported by this DSB TPDM.
How does a user find it ? Why don't we expose it ? Scratch all of that, you could create a register file per exising msr.
dsb_msrs/msr0 ... msrN
You may :
- either dynamically add files as you find the number
OR
- If there is a hard limit, create that many files and control
visibility based on the dynamic number.
Hi Suzuki,
With regards to your suggestions, would you mind if you provide some sample code for my reference?
1. How to dynamically add files to the sysfs as I find the number?
2. The hard limit of MSR should be 32. How can I control visibility based on the dynamic number?
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm.
(RW)
Sure, I will update this in the next patch series.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f9e5a1d..be7776b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) } +static void set_dsb_msr(struct tpdm_drvdata *drvdata) +{ + int i;
+ if (drvdata->dsb->msr_num == 0) + return;
+ for (i = 0; i < drvdata->dsb->msr_num; i++) + writel_relaxed(drvdata->dsb->msr[i], + drvdata->base + TPDM_DSB_MSR(i)); +}
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i; @@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); + set_dsb_msr(drvdata);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); /* Set the test accurate mode */ set_dsb_test_mode(drvdata, &val); @@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, > + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
devm_kcalloc() ?
Sure, I will update this in the next patch series.
+ GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } } return 0; @@ -830,6 +852,80 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->msr_idx);
+}
+static ssize_t dsb_msr_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index;
+ if (kstrtoul(buf, 0, &index)) + return -EINVAL; + if (index >= drvdata->dsb->msr_num) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr_idx = index; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr_idx);
+static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + unsigned long bytes; + ssize_t size = 0;
+ if (drvdata->dsb->msr_num == 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < drvdata->dsb->msr_num; i++) { + bytes = sysfs_emit_at(buf, size, + "0x%x\n", drvdata->dsb->msr[i]);
Single value per single file.
Sure, I will update this in the next patch series.
Best,
Tao
Suzuki
+ if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock);
+ return size; +}
+static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if (kstrtoul(buf, 0, &val)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[drvdata->dsb->msr_idx] = 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_idx.attr, @@ -845,6 +941,8 @@ 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_idx.attr, + &dev_attr_dsb_msr.attr, NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7c52cf4..7b70db3 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) @@ -100,6 +101,9 @@ * @patt_mask: Save value for pattern mask * @trig_patt: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask
- @msr_num Number of MSR supported by DSB TPDM
- @msr_idx Index number of the MSR
- @msr Save value for MSR
* @patt_ts: Enable/Disable pattern timestamp * @patt_type: Set pattern type * @trig_ts: Enable/Disable trigger timestamp. @@ -116,6 +120,9 @@ struct dsb_dataset { u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; + u32 msr_num; + u32 msr_idx; + u32 *msr; bool patt_ts; bool patt_type; bool trig_ts;
On 18/08/2023 16:44, Tao Zhang wrote:
On 8/7/2023 7:35 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 19 ++++- drivers/hwtracing/coresight/coresight-tpdm.c | 98 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 7 ++ 3 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 74a0126..ee41a14 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -185,4 +185,21 @@ 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. \ No newline at end of file + 1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of MSR(mux select register) on DSB + TPDM. This index number should not be greater than the number + of MSR supported by this DSB TPDM.
How does a user find it ? Why don't we expose it ? Scratch all of that, you could create a register file per exising msr.
dsb_msrs/msr0 ... msrN
You may :
- either dynamically add files as you find the number
OR
- If there is a hard limit, create that many files and control
visibility based on the dynamic number.
Hi Suzuki,
With regards to your suggestions, would you mind if you provide some sample code for my reference?
How to dynamically add files to the sysfs as I find the number?
The hard limit of MSR should be 32. How can I control visibility
based on the dynamic number?
You could add attributes via dev_ext_attribute, storing the "idx" as the data field for 0-31. And use the is_visible() hook for the attribute_group, just like you do for DSB related checks.
Some skeleton code, untested :
static ssize_t dsb_msr_read(struct device *dev, struct device_attribute *attr, char *buf) { struct dev_ext_attribute *eattr = container_of(attr, struct dev_ext_attribute, attr); int idx = (int)(unsigned long)eattr->var;
/* Read the MSR at IDX */ }
/* Similarly for dsb_msr_write() */
#define DSB_MSR_ATTR(idx) \ &((struct dev_ext_attribute[]) { \ { \ __ATTR("msr"#idx, <RW>, dsb_msr_read, dsb_msr_write), \ (void *)idx } \ })[0].attr.attr
#define DSB_MSR_ATTRS \ DSB_MSR_ATTR(0), \ DSB_MSR_ATTR(1), \ ... DSB_MSR_ATTR(31)
static struct attribute * dsb_msr_attrs[] = { DSB_MSR_ATTRS, NULL, };
static umode_t dsb_msr_is_visible(struct kobject *kobj, struct attribute *attr, int unuse) { struct device *dev = kobject_to_dev(kobj); /* From dev, get drvdata */ /* Then decide if it should be made visible, if yes R/W permissions */ }
static const struct attribute_group dsb_msr_group = { .is_visible = dsb_msr_is_visible, .attrs = dsb_msr_attrs, .name = "dsb_msr", };
See : drivers/.../coresight-etm4x-sysfs.c:
coresight_etmv4_mgmt_attrs & coresight_etmv4_mgmt_group for an example.
Suzuki
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm.
(RW)
Sure, I will update this in the next patch series.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f9e5a1d..be7776b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) } +static void set_dsb_msr(struct tpdm_drvdata *drvdata) +{ + int i;
+ if (drvdata->dsb->msr_num == 0) + return;
+ for (i = 0; i < drvdata->dsb->msr_num; i++) + writel_relaxed(drvdata->dsb->msr[i], + drvdata->base + TPDM_DSB_MSR(i)); +}
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i; @@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); + set_dsb_msr(drvdata);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); /* Set the test accurate mode */ set_dsb_test_mode(drvdata, &val); @@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, > + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
devm_kcalloc() ?
Sure, I will update this in the next patch series.
+ GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } } return 0; @@ -830,6 +852,80 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->msr_idx);
+}
+static ssize_t dsb_msr_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index;
+ if (kstrtoul(buf, 0, &index)) + return -EINVAL; + if (index >= drvdata->dsb->msr_num) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr_idx = index; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr_idx);
+static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + unsigned long bytes; + ssize_t size = 0;
+ if (drvdata->dsb->msr_num == 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < drvdata->dsb->msr_num; i++) { + bytes = sysfs_emit_at(buf, size, + "0x%x\n", drvdata->dsb->msr[i]);
Single value per single file.
Sure, I will update this in the next patch series.
Best,
Tao
Suzuki
+ if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock);
+ return size; +}
+static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if (kstrtoul(buf, 0, &val)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[drvdata->dsb->msr_idx] = 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_idx.attr, @@ -845,6 +941,8 @@ 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_idx.attr, + &dev_attr_dsb_msr.attr, NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7c52cf4..7b70db3 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) @@ -100,6 +101,9 @@ * @patt_mask: Save value for pattern mask * @trig_patt: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask
- @msr_num Number of MSR supported by DSB TPDM
- @msr_idx Index number of the MSR
- @msr Save value for MSR
* @patt_ts: Enable/Disable pattern timestamp * @patt_type: Set pattern type * @trig_ts: Enable/Disable trigger timestamp. @@ -116,6 +120,9 @@ struct dsb_dataset { u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; + u32 msr_num; + u32 msr_idx; + u32 *msr; bool patt_ts; bool patt_type; bool trig_ts;
On 8/19/2023 12:25 AM, Suzuki K Poulose wrote:
On 18/08/2023 16:44, Tao Zhang wrote:
On 8/7/2023 7:35 PM, Suzuki K Poulose wrote:
On 25/07/2023 08:15, 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 | 19 ++++- drivers/hwtracing/coresight/coresight-tpdm.c | 98 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tpdm.h | 7 ++ 3 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm index 74a0126..ee41a14 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm @@ -185,4 +185,21 @@ 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. \ No newline at end of file + 1 : Set the DSB pattern type to toggle.
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr_idx +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + Read/Write the index number of MSR(mux select register) on DSB + TPDM. This index number should not be greater than the number + of MSR supported by this DSB TPDM.
How does a user find it ? Why don't we expose it ? Scratch all of that, you could create a register file per exising msr.
dsb_msrs/msr0 ... msrN
You may :
- either dynamically add files as you find the number
OR
- If there is a hard limit, create that many files and control
visibility based on the dynamic number.
Hi Suzuki,
With regards to your suggestions, would you mind if you provide some sample code for my reference?
How to dynamically add files to the sysfs as I find the number?
The hard limit of MSR should be 32. How can I control visibility
based on the dynamic number?
You could add attributes via dev_ext_attribute, storing the "idx" as the data field for 0-31. And use the is_visible() hook for the attribute_group, just like you do for DSB related checks.
Some skeleton code, untested :
static ssize_t dsb_msr_read(struct device *dev, struct device_attribute *attr, char *buf) { struct dev_ext_attribute *eattr = container_of(attr, struct dev_ext_attribute, attr); int idx = (int)(unsigned long)eattr->var;
/* Read the MSR at IDX */ }
/* Similarly for dsb_msr_write() */
#define DSB_MSR_ATTR(idx) \ &((struct dev_ext_attribute[]) { \ { \ __ATTR("msr"#idx, <RW>, dsb_msr_read, dsb_msr_write), \ (void *)idx } \ })[0].attr.attr
#define DSB_MSR_ATTRS \ DSB_MSR_ATTR(0), \ DSB_MSR_ATTR(1), \ ... DSB_MSR_ATTR(31)
static struct attribute * dsb_msr_attrs[] = { DSB_MSR_ATTRS, NULL, };
static umode_t dsb_msr_is_visible(struct kobject *kobj, struct attribute *attr, int unuse) { struct device *dev = kobject_to_dev(kobj); /* From dev, get drvdata */ /* Then decide if it should be made visible, if yes R/W permissions */ }
static const struct attribute_group dsb_msr_group = { .is_visible = dsb_msr_is_visible, .attrs = dsb_msr_attrs, .name = "dsb_msr", };
See : drivers/.../coresight-etm4x-sysfs.c:
coresight_etmv4_mgmt_attrs & coresight_etmv4_mgmt_group for an example.
Suzuki
I only can control if we need to expose the MSR sysfs files, but cannot control how
much MSR sysfs files need to be exposed dynamically, right?
Best,
Tao
+What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr +Date: March 2023 +KernelVersion 6.5 +Contact: Jinlong Mao (QUIC) quic_jinlmao@quicinc.com, Tao Zhang (QUIC) quic_taozha@quicinc.com +Description: + (Write) Set the MSR(mux select register) of DSB tpdm. Read + the MSR(mux select register) of DSB tpdm.
(RW)
Sure, I will update this in the next patch series.
\ No newline at end of file diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index f9e5a1d..be7776b 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -90,6 +90,18 @@ static void set_dsb_tier(struct tpdm_drvdata *drvdata, u32 *val) } +static void set_dsb_msr(struct tpdm_drvdata *drvdata) +{ + int i;
+ if (drvdata->dsb->msr_num == 0) + return;
+ for (i = 0; i < drvdata->dsb->msr_num; i++) + writel_relaxed(drvdata->dsb->msr[i], + drvdata->base + TPDM_DSB_MSR(i)); +}
static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) { u32 val, i; @@ -116,6 +128,8 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) set_dsb_tier(drvdata, &val); writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); + set_dsb_msr(drvdata);
val = readl_relaxed(drvdata->base + TPDM_DSB_CR); /* Set the test accurate mode */ set_dsb_test_mode(drvdata, &val); @@ -234,6 +248,14 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) if (!drvdata->dsb) return -ENOMEM; } + if (!of_property_read_u32(drvdata->dev->of_node, + "qcom,dsb_msr_num", &drvdata->dsb->msr_num)) { + drvdata->dsb->msr = devm_kzalloc(drvdata->dev, > + (drvdata->dsb->msr_num * sizeof(*drvdata->dsb->msr)),
devm_kcalloc() ?
Sure, I will update this in the next patch series.
+ GFP_KERNEL); + if (!drvdata->dsb->msr) + return -ENOMEM; + } } return 0; @@ -830,6 +852,80 @@ static ssize_t dsb_trig_ts_store(struct device *dev, } static DEVICE_ATTR_RW(dsb_trig_ts); +static ssize_t dsb_msr_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->dsb->msr_idx);
+}
+static ssize_t dsb_msr_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long index;
+ if (kstrtoul(buf, 0, &index)) + return -EINVAL; + if (index >= drvdata->dsb->msr_num) + return -EPERM;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr_idx = index; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(dsb_msr_idx);
+static ssize_t dsb_msr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned int i; + unsigned long bytes; + ssize_t size = 0;
+ if (drvdata->dsb->msr_num == 0) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + for (i = 0; i < drvdata->dsb->msr_num; i++) { + bytes = sysfs_emit_at(buf, size, + "0x%x\n", drvdata->dsb->msr[i]);
Single value per single file.
Sure, I will update this in the next patch series.
Best,
Tao
Suzuki
+ if (bytes <= 0) + break; + size += bytes; + } + spin_unlock(&drvdata->spinlock);
+ return size; +}
+static ssize_t dsb_msr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val;
+ if (kstrtoul(buf, 0, &val)) + return -EINVAL;
+ spin_lock(&drvdata->spinlock); + drvdata->dsb->msr[drvdata->dsb->msr_idx] = 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_idx.attr, @@ -845,6 +941,8 @@ 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_idx.attr, + &dev_attr_dsb_msr.attr, NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h index 7c52cf4..7b70db3 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) @@ -100,6 +101,9 @@ * @patt_mask: Save value for pattern mask * @trig_patt: Save value for trigger pattern * @trig_patt_mask: Save value for trigger pattern mask
- @msr_num Number of MSR supported by DSB TPDM
- @msr_idx Index number of the MSR
- @msr Save value for MSR
* @patt_ts: Enable/Disable pattern timestamp * @patt_type: Set pattern type * @trig_ts: Enable/Disable trigger timestamp. @@ -116,6 +120,9 @@ struct dsb_dataset { u32 patt_mask[TPDM_DSB_MAX_PATT]; u32 trig_patt[TPDM_DSB_MAX_PATT]; u32 trig_patt_mask[TPDM_DSB_MAX_PATT]; + u32 msr_num; + u32 msr_idx; + u32 *msr; bool patt_ts; bool patt_type; bool trig_ts;