mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 06:04:44 +01:00
coresight: Updates for Linux v6.20/v7.0
This batch of CoreSight hwtracing updates contains :
- Fine grained control of Timestamp generation in ETM4 trace, retaining backward
compatibility
- Feature updates for Qualcomm TPDA driver
- Support Qualcomm Interconnect TNOC
- Miscellaneous fixes to TMC-ETR driver
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAml3Q8UACgkQxcXRZPKy
BqF8lg//UHXXwvZp2lKG8SwCPZoYBbwQSRwf7JMOXo/hEIF38qElWXm3zA7d0U4E
qY+cKVaSTXxz5hrjTzkzDsLI2cLsmZX1R8QEhP33voXWPdW/b4GFA84WwKss/F7J
2t4p/m/EbW/1305eIKkKqz5ev0J8vOe8FoPZ1oQ7h27Lw1EDw9wzpUCu9JZkljz3
/A7c6i78H5fkF9ulRM+11/xZnZXnIIjdv3JRY2qrGUyvLXKs5dC59p9R6ln+cRWU
1AOjCqMeCyjZPJAk/S6iH3Qi1R+NxN3tL4ojsmHnHojmql8mGKjCFbUkrw0eOgxg
/3qFVIeIEmOq66Azj28yKezICpQwn9MyWxp03dVYGxPoCEpZP8x39NoK47inZD4u
KXrKlLSQ6i0aehbjs0s2NsBsetHKHrkS16sXESvoPQSEb6KmgKk9PK9WSara3Plo
ueJtuJzlSgLuxLciX6rnzrZALzhQWIsIpzNOaInWZMjJpNrramxk5T64tRwA9xhG
eWErxaNLsJGCZzWA/4ozLgRUEBJygp6VpCNpU8ddjBMzMVaKyrk6W5vCfWlynwVy
UNepYiAHqGYeV7JgbxfqAJHk4AazEWYNbkHhxZXd0PsRhqHTilDpfPtk3KFh2BVM
k64vS0BnPWHvUYQSwghOkiHrSnqvtWWL9uqw/zZfSj+YMj6KP6E=
=7lsU
-----END PGP SIGNATURE-----
Merge tag 'coresight-next-v7.0' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next
Suzuki writes:
coresight: Updates for Linux v6.20/v7.0
This batch of CoreSight hwtracing updates contains :
- Fine grained control of Timestamp generation in ETM4 trace, retaining backward
compatibility
- Feature updates for Qualcomm TPDA driver
- Support Qualcomm Interconnect TNOC
- Miscellaneous fixes to TMC-ETR driver
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
* tag 'coresight-next-v7.0' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux: (27 commits)
coresight: tmc: Decouple the perf buffer allocation from sysfs mode
coresight: tmc-etr: Fix race condition between sysfs and perf mode
coresight: tmc: Add missing doc including reading and etr_mode of struct tmc_drvdata
coresight-tnoc: Add runtime PM support for Interconnect TNOC
coresight-tnoc: add platform driver to support Interconnect TNOC
dt-bindings: arm: qcom: Add Coresight Interconnect TNOC
coresight: etm3x: Fix cpulocked warning on cpuhp
coresight: tpda: Fix intendation for sysfs interface documentation
coresight: tpda: add sysfs node to flush specific port
coresight: tpda: add logic to configure TPDA_SYNCR register
coresight: tpda: add global_flush_req sysfs node
coresight: tpda: add sysfs nodes for tpda cross-trigger configuration
coresight: docs: Document etm4x timestamp interval option
coresight: Extend width of timestamp format attribute
coresight: Prepare to allow setting the timestamp interval
coresight: Remove misleading definitions
coresight: Interpret ETMv4 config with ATTR_CFG_GET_FLD()
coresight: Interpret perf config with ATTR_CFG_GET_FLD()
coresight: Don't reject unrecognized ETMv3 format attributes
coresight: Interpret ETMv3 config with ATTR_CFG_GET_FLD()
...
This commit is contained in:
commit
a8a6d9b4da
23 changed files with 996 additions and 263 deletions
|
|
@ -1,7 +1,7 @@
|
|||
What: /sys/bus/coresight/devices/dummy_source<N>/enable_source
|
||||
Date: Dec 2024
|
||||
KernelVersion: 6.14
|
||||
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
Contact: Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
Description: (RW) Enable/disable tracing of dummy source. A sink should be activated
|
||||
before enabling the source. The path of coresight components linking
|
||||
the source to the sink is configured and managed automatically by the
|
||||
|
|
@ -10,7 +10,7 @@ Description: (RW) Enable/disable tracing of dummy source. A sink should be activ
|
|||
What: /sys/bus/coresight/devices/dummy_source<N>/traceid
|
||||
Date: Dec 2024
|
||||
KernelVersion: 6.14
|
||||
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
Contact: Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
Description: (R) Show the trace ID that will appear in the trace stream
|
||||
coming from this trace entity.
|
||||
|
||||
|
|
|
|||
69
Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
Normal file
69
Documentation/ABI/testing/sysfs-bus-coresight-devices-tpda
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
What: /sys/bus/coresight/devices/<tpda-name>/trig_async_enable
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Enable/disable cross trigger synchronization sequence interface.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/trig_flag_ts_enable
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Enable/disable cross trigger FLAG packet request interface.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/trig_freq_enable
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Enable/disable cross trigger FREQ packet request interface.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/freq_ts_enable
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Enable/disable the timestamp for all FREQ packets.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/cmbchan_mode
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Configure the CMB/MCMB channel mode for all enabled ports.
|
||||
Value 0 means raw channel mapping mode. Value 1 means channel pair marking mode.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/global_flush_req
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set global (all ports) flush request bit. The bit remains set until a
|
||||
global flush request sequence completes.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/syncr_mode
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set mode the of the syncr counter.
|
||||
mode 0 - COUNT[11:0] value represents the approximate number of bytes moved between two ASYNC packet requests
|
||||
mode 1 - the bits COUNT[11:7] are used as a power of 2. for example, we could insert an async packet every 8K
|
||||
data by writing a value 13 to the COUNT[11:7] field.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/syncr_count
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set value the of the syncr counter.
|
||||
Range: 0-4095
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpda-name>/port_flush_req
|
||||
Date: December 2025
|
||||
KernelVersion: 6.20
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Configure the bit i to requests a flush operation of port i on the TPDA.
|
||||
The requested bit(s) remain set until the flush request completes.
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/integration_test
|
||||
Date: January 2023
|
||||
KernelVersion: 6.2
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(Write) Run integration test for tpdm. Integration test
|
||||
will generate test data for tpdm. It can help to make
|
||||
|
|
@ -15,7 +15,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/reset_dataset
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(Write) Reset the dataset of the tpdm.
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the trigger type of the DSB for tpdm.
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the trigger timestamp of the DSB for tpdm.
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the programming mode of the DSB for tpdm.
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_idx
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the index number of the edge detection for the DSB
|
||||
subunit TPDM. Since there are at most 256 edge detections, this
|
||||
|
|
@ -70,7 +70,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_val
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
Write a data to control the edge detection corresponding to
|
||||
the index number. Before writing data to this sysfs file,
|
||||
|
|
@ -86,7 +86,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_mask
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
Write a data to mask the edge detection corresponding to the index
|
||||
number. Before writing data to this sysfs file, "ctrl_idx" should
|
||||
|
|
@ -98,21 +98,21 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcr[0:15]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
Read a set of the edge control value of the DSB in TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcmr[0:7]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
Read a set of the edge control mask of the DSB in TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpr[0:7]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the value of the trigger pattern for the DSB
|
||||
subunit TPDM.
|
||||
|
|
@ -120,7 +120,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpmr[0:7]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the mask of the trigger pattern for the DSB
|
||||
subunit TPDM.
|
||||
|
|
@ -128,21 +128,21 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:7]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the value of the pattern for the DSB subunit TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:7]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the mask of the pattern for the DSB subunit TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/enable_ts
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(Write) Set the pattern timestamp of DSB tpdm. Read
|
||||
the pattern timestamp of DSB tpdm.
|
||||
|
|
@ -154,7 +154,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/set_type
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(Write) Set the pattern type of DSB tpdm. Read
|
||||
the pattern type of DSB tpdm.
|
||||
|
|
@ -166,7 +166,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr/msr[0:31]
|
||||
Date: March 2023
|
||||
KernelVersion: 6.7
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the MSR(mux select register) for the DSB subunit
|
||||
TPDM.
|
||||
|
|
@ -174,7 +174,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_mode
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description: (Write) Set the data collection mode of CMB tpdm. Continuous
|
||||
change creates CMB data set elements on every CMBCLK edge.
|
||||
Trace-on-change creates CMB data set elements only when a new
|
||||
|
|
@ -188,7 +188,7 @@ Description: (Write) Set the data collection mode of CMB tpdm. Continuous
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpr[0:1]
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the value of the trigger pattern for the CMB
|
||||
subunit TPDM.
|
||||
|
|
@ -196,7 +196,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpmr[0:1]
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the mask of the trigger pattern for the CMB
|
||||
subunit TPDM.
|
||||
|
|
@ -204,21 +204,21 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:1]
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the value of the pattern for the CMB subunit TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:1]
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the mask of the pattern for the CMB subunit TPDM.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt/enable_ts
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(Write) Set the pattern timestamp of CMB tpdm. Read
|
||||
the pattern timestamp of CMB tpdm.
|
||||
|
|
@ -230,7 +230,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_ts
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the trigger timestamp of the CMB for tpdm.
|
||||
|
||||
|
|
@ -241,7 +241,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_ts_all
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Read or write the status of timestamp upon all interface.
|
||||
Only value 0 and 1 can be written to this node. Set this node to 1 to request
|
||||
|
|
@ -253,7 +253,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_msr/msr[0:31]
|
||||
Date: January 2024
|
||||
KernelVersion: 6.9
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the MSR(mux select register) for the CMB subunit
|
||||
TPDM.
|
||||
|
|
@ -261,7 +261,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/mcmb_trig_lane
|
||||
Date: Feb 2025
|
||||
KernelVersion 6.15
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get which lane participates in the output pattern
|
||||
match cross trigger mechanism for the MCMB subunit TPDM.
|
||||
|
|
@ -269,7 +269,7 @@ Description:
|
|||
What: /sys/bus/coresight/devices/<tpdm-name>/mcmb_lanes_select
|
||||
Date: Feb 2025
|
||||
KernelVersion 6.15
|
||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
Description:
|
||||
(RW) Set/Get the enablement of the individual lane.
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ maintainers:
|
|||
- Mike Leach <mike.leach@linaro.org>
|
||||
- Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
- James Clark <james.clark@linaro.org>
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
- Hao Zhang <quic_hazha@quicinc.com>
|
||||
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ maintainers:
|
|||
- Mike Leach <mike.leach@linaro.org>
|
||||
- Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
- James Clark <james.clark@linaro.org>
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
- Hao Zhang <quic_hazha@quicinc.com>
|
||||
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: CoreSight TMC Control Unit
|
||||
|
||||
maintainers:
|
||||
- Yuanfang Zhang <quic_yuanfang@quicinc.com>
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Jie Gan <quic_jiegan@quicinc.com>
|
||||
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
|
||||
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
- Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
|
||||
description: |
|
||||
The Trace Memory Controller(TMC) is used for Embedded Trace Buffer(ETB),
|
||||
|
|
@ -26,8 +26,13 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-ctcu
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qcs8300-ctcu
|
||||
- const: qcom,sa8775p-ctcu
|
||||
- enum:
|
||||
- qcom,sa8775p-ctcu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/arm/qcom,coresight-itnoc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Interconnect Trace Network On Chip - ITNOC
|
||||
|
||||
maintainers:
|
||||
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
|
||||
|
||||
description:
|
||||
The Interconnect TNOC is a CoreSight graph link that forwards trace data
|
||||
from a subsystem to the Aggregator TNOC. Compared to Aggregator TNOC, it
|
||||
does not have aggregation and ATID functionality.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^itnoc(@[0-9a-f]+)?$"
|
||||
|
||||
compatible:
|
||||
const: qcom,coresight-itnoc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
patternProperties:
|
||||
'^port(@[0-9a-f]{1,2})?$':
|
||||
description: Input connections from CoreSight Trace Bus
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
out-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
port:
|
||||
description: out connections to aggregator TNOC
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- in-ports
|
||||
- out-ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
itnoc@109ac000 {
|
||||
compatible = "qcom,coresight-itnoc";
|
||||
reg = <0x109ac000 0x1000>;
|
||||
|
||||
clocks = <&aoss_qmp>;
|
||||
clock-names = "apb";
|
||||
|
||||
in-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
tn_ic_in_tpdm_dcc: endpoint {
|
||||
remote-endpoint = <&tpdm_dcc_out_tn_ic>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
out-ports {
|
||||
port {
|
||||
tn_ic_out_tnoc_aggr: endpoint {
|
||||
/* to Aggregator TNOC input */
|
||||
remote-endpoint = <&tn_ag_in_tn_ic>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Qualcomm Coresight Remote ETM(Embedded Trace Macrocell)
|
||||
|
||||
maintainers:
|
||||
- Jinlong Mao <quic_jinlmao@quicinc.com>
|
||||
- Tao Zhang <quic_taozha@quicinc.com>
|
||||
- Jinlong Mao <jinlong.mao@oss.qualcomm.com>
|
||||
- Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
|
||||
description:
|
||||
Support for ETM trace collection on remote processor using coresight
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Qualcomm Trace Network On Chip - TNOC
|
||||
|
||||
maintainers:
|
||||
- Yuanfang Zhang <quic_yuanfang@quicinc.com>
|
||||
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
|
||||
|
||||
description: >
|
||||
The Trace Network On Chip (TNOC) is an integration hierarchy hardware
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ description: |
|
|||
to sink.
|
||||
|
||||
maintainers:
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Tao Zhang <quic_taozha@quicinc.com>
|
||||
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
- Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
|
||||
# Need a custom select here or 'arm,primecell' will match on lots of nodes
|
||||
select:
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ description: |
|
|||
sources and send it to a TPDA for packetization, timestamping, and funneling.
|
||||
|
||||
maintainers:
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Tao Zhang <quic_taozha@quicinc.com>
|
||||
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
|
||||
- Tao Zhang <tao.zhang@oss.qualcomm.com>
|
||||
|
||||
# Need a custom select here or 'arm,primecell' will match on lots of nodes
|
||||
select:
|
||||
|
|
|
|||
|
|
@ -613,8 +613,20 @@ They are also listed in the folder /sys/bus/event_source/devices/cs_etm/format/
|
|||
- Session local version of the system wide setting: :ref:`ETM_MODE_RETURNSTACK
|
||||
<coresight-return-stack>`
|
||||
* - timestamp
|
||||
- Session local version of the system wide setting: :ref:`ETMv4_MODE_TIMESTAMP
|
||||
<coresight-timestamp>`
|
||||
- Controls generation and interval of timestamps.
|
||||
|
||||
0 = off, 1 = minimum interval .. 15 = maximum interval.
|
||||
|
||||
Values 1 - 14 use a counter that decrements every cycle to generate a
|
||||
timestamp on underflow. The reload value for the counter is 2 ^ (interval
|
||||
- 1). If the value is 1 then the reload value is 1, if the value is 11
|
||||
then the reload value is 1024 etc.
|
||||
|
||||
Setting the maximum interval (15) will disable the counter generated
|
||||
timestamps, freeing the counter resource, leaving only ones emitted when
|
||||
a SYNC packet is generated. The sync interval is controlled with
|
||||
TRCSYNCPR.PERIOD which is every 4096 bytes of trace by default.
|
||||
|
||||
* - cc_threshold
|
||||
- Cycle count threshold value. If nothing is provided here or the provided value is 0, then the
|
||||
default value i.e 0x100 will be used. If provided value is less than minimum cycles threshold
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/perf/arm_pmu.h>
|
||||
#include <linux/percpu-defs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stringhash.h>
|
||||
|
|
@ -50,26 +51,22 @@ struct etm_ctxt {
|
|||
static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt);
|
||||
static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
|
||||
|
||||
/*
|
||||
* The PMU formats were orignally for ETMv3.5/PTM's ETMCR 'config';
|
||||
* now take them as general formats and apply on all ETMs.
|
||||
*/
|
||||
PMU_FORMAT_ATTR(branch_broadcast, "config:"__stringify(ETM_OPT_BRANCH_BROADCAST));
|
||||
PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));
|
||||
/* contextid1 enables tracing CONTEXTIDR_EL1 for ETMv4 */
|
||||
PMU_FORMAT_ATTR(contextid1, "config:" __stringify(ETM_OPT_CTXTID));
|
||||
/* contextid2 enables tracing CONTEXTIDR_EL2 for ETMv4 */
|
||||
PMU_FORMAT_ATTR(contextid2, "config:" __stringify(ETM_OPT_CTXTID2));
|
||||
PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS));
|
||||
PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK));
|
||||
/* preset - if sink ID is used as a configuration selector */
|
||||
PMU_FORMAT_ATTR(preset, "config:0-3");
|
||||
/* Sink ID - same for all ETMs */
|
||||
PMU_FORMAT_ATTR(sinkid, "config2:0-31");
|
||||
/* config ID - set if a system configuration is selected */
|
||||
PMU_FORMAT_ATTR(configid, "config2:32-63");
|
||||
PMU_FORMAT_ATTR(cc_threshold, "config3:0-11");
|
||||
GEN_PMU_FORMAT_ATTR(cycacc);
|
||||
GEN_PMU_FORMAT_ATTR(timestamp);
|
||||
GEN_PMU_FORMAT_ATTR(retstack);
|
||||
GEN_PMU_FORMAT_ATTR(sinkid);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
|
||||
GEN_PMU_FORMAT_ATTR(branch_broadcast);
|
||||
/* contextid1 enables tracing CONTEXTIDR_EL1*/
|
||||
GEN_PMU_FORMAT_ATTR(contextid1);
|
||||
/* contextid2 enables tracing CONTEXTIDR_EL2*/
|
||||
GEN_PMU_FORMAT_ATTR(contextid2);
|
||||
/* preset - if sink ID is used as a configuration selector */
|
||||
GEN_PMU_FORMAT_ATTR(preset);
|
||||
/* config ID - set if a system configuration is selected */
|
||||
GEN_PMU_FORMAT_ATTR(configid);
|
||||
GEN_PMU_FORMAT_ATTR(cc_threshold);
|
||||
|
||||
/*
|
||||
* contextid always traces the "PID". The PID is in CONTEXTIDR_EL1
|
||||
|
|
@ -80,29 +77,35 @@ static ssize_t format_attr_contextid_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
int pid_fmt = ETM_OPT_CTXTID;
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
|
||||
pid_fmt = is_kernel_in_hyp_mode() ? ETM_OPT_CTXTID2 : ETM_OPT_CTXTID;
|
||||
#endif
|
||||
return sprintf(page, "config:%d\n", pid_fmt);
|
||||
if (is_kernel_in_hyp_mode())
|
||||
return contextid2_show(dev, attr, page);
|
||||
return contextid1_show(dev, attr, page);
|
||||
}
|
||||
|
||||
static struct device_attribute format_attr_contextid =
|
||||
__ATTR(contextid, 0444, format_attr_contextid_show, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ETMv3 only uses the first 3 attributes for programming itself (see
|
||||
* ETM3X_SUPPORTED_OPTIONS). Sink ID is also supported for selecting a
|
||||
* sink in both, but not used for configuring the ETM. The remaining
|
||||
* attributes are ETMv4 specific.
|
||||
*/
|
||||
static struct attribute *etm_config_formats_attr[] = {
|
||||
&format_attr_cycacc.attr,
|
||||
&format_attr_contextid.attr,
|
||||
&format_attr_contextid1.attr,
|
||||
&format_attr_contextid2.attr,
|
||||
&format_attr_timestamp.attr,
|
||||
&format_attr_retstack.attr,
|
||||
&format_attr_sinkid.attr,
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
|
||||
&format_attr_contextid.attr,
|
||||
&format_attr_contextid1.attr,
|
||||
&format_attr_contextid2.attr,
|
||||
&format_attr_preset.attr,
|
||||
&format_attr_configid.attr,
|
||||
&format_attr_branch_broadcast.attr,
|
||||
&format_attr_cc_threshold.attr,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -315,7 +318,7 @@ static bool sinks_compatible(struct coresight_device *a,
|
|||
static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||
int nr_pages, bool overwrite)
|
||||
{
|
||||
u32 id, cfg_hash;
|
||||
u32 sink_hash, cfg_hash;
|
||||
int cpu = event->cpu;
|
||||
cpumask_t *mask;
|
||||
struct coresight_device *sink = NULL;
|
||||
|
|
@ -328,13 +331,12 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
|||
INIT_WORK(&event_data->work, free_event_data);
|
||||
|
||||
/* First get the selected sink from user space. */
|
||||
if (event->attr.config2 & GENMASK_ULL(31, 0)) {
|
||||
id = (u32)event->attr.config2;
|
||||
sink = user_sink = coresight_get_sink_by_id(id);
|
||||
}
|
||||
sink_hash = ATTR_CFG_GET_FLD(&event->attr, sinkid);
|
||||
if (sink_hash)
|
||||
sink = user_sink = coresight_get_sink_by_id(sink_hash);
|
||||
|
||||
/* check if user wants a coresight configuration selected */
|
||||
cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
|
||||
cfg_hash = ATTR_CFG_GET_FLD(&event->attr, configid);
|
||||
if (cfg_hash) {
|
||||
if (cscfg_activate_config(cfg_hash))
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,44 @@ struct cscfg_config_desc;
|
|||
*/
|
||||
#define ETM_ADDR_CMP_MAX 8
|
||||
|
||||
#define ATTR_CFG_FLD_preset_CFG config
|
||||
#define ATTR_CFG_FLD_preset_LO 0
|
||||
#define ATTR_CFG_FLD_preset_HI 3
|
||||
#define ATTR_CFG_FLD_timestamp_CFG config
|
||||
#define ATTR_CFG_FLD_timestamp_LO 4
|
||||
#define ATTR_CFG_FLD_timestamp_HI 7
|
||||
#define ATTR_CFG_FLD_branch_broadcast_CFG config
|
||||
#define ATTR_CFG_FLD_branch_broadcast_LO 8
|
||||
#define ATTR_CFG_FLD_branch_broadcast_HI 8
|
||||
#define ATTR_CFG_FLD_cycacc_CFG config
|
||||
#define ATTR_CFG_FLD_cycacc_LO 12
|
||||
#define ATTR_CFG_FLD_cycacc_HI 12
|
||||
#define ATTR_CFG_FLD_contextid1_CFG config
|
||||
#define ATTR_CFG_FLD_contextid1_LO 14
|
||||
#define ATTR_CFG_FLD_contextid1_HI 14
|
||||
#define ATTR_CFG_FLD_contextid2_CFG config
|
||||
#define ATTR_CFG_FLD_contextid2_LO 15
|
||||
#define ATTR_CFG_FLD_contextid2_HI 15
|
||||
/*
|
||||
* Old position of 'timestamp' and not published in sysfs. Remove at a later
|
||||
* date if necessary.
|
||||
*/
|
||||
#define ATTR_CFG_FLD_deprecated_timestamp_CFG config
|
||||
#define ATTR_CFG_FLD_deprecated_timestamp_LO 28
|
||||
#define ATTR_CFG_FLD_deprecated_timestamp_HI 28
|
||||
#define ATTR_CFG_FLD_retstack_CFG config
|
||||
#define ATTR_CFG_FLD_retstack_LO 29
|
||||
#define ATTR_CFG_FLD_retstack_HI 29
|
||||
#define ATTR_CFG_FLD_sinkid_CFG config2
|
||||
#define ATTR_CFG_FLD_sinkid_LO 0
|
||||
#define ATTR_CFG_FLD_sinkid_HI 31
|
||||
#define ATTR_CFG_FLD_configid_CFG config2
|
||||
#define ATTR_CFG_FLD_configid_LO 32
|
||||
#define ATTR_CFG_FLD_configid_HI 63
|
||||
#define ATTR_CFG_FLD_cc_threshold_CFG config3
|
||||
#define ATTR_CFG_FLD_cc_threshold_LO 0
|
||||
#define ATTR_CFG_FLD_cc_threshold_HI 11
|
||||
|
||||
/**
|
||||
* struct etm_filter - single instruction range or start/stop configuration.
|
||||
* @start_addr: The address to start tracing on.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/perf/arm_pmu.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
#include "coresight-etm.h"
|
||||
|
|
@ -309,6 +310,7 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
|
|||
{
|
||||
struct etm_config *config = &drvdata->config;
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
u8 ts_level;
|
||||
|
||||
if (!attr)
|
||||
return -EINVAL;
|
||||
|
|
@ -332,28 +334,31 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
|
|||
if (config->mode)
|
||||
etm_config_trace_mode(config);
|
||||
|
||||
/*
|
||||
* At this time only cycle accurate, return stack and timestamp
|
||||
* options are available.
|
||||
*/
|
||||
if (attr->config & ~ETM3X_SUPPORTED_OPTIONS)
|
||||
config->ctrl = 0;
|
||||
|
||||
if (ATTR_CFG_GET_FLD(attr, cycacc))
|
||||
config->ctrl |= ETMCR_CYC_ACC;
|
||||
|
||||
ts_level = max(ATTR_CFG_GET_FLD(attr, timestamp),
|
||||
ATTR_CFG_GET_FLD(attr, deprecated_timestamp));
|
||||
|
||||
if (ts_level > 1) {
|
||||
dev_dbg(&drvdata->csdev->dev,
|
||||
"timestamp format attribute should be 0 (off) or 1 (on)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
config->ctrl = attr->config;
|
||||
|
||||
/* Don't trace contextID when runs in non-root PID namespace */
|
||||
if (!task_is_in_init_pid_ns(current))
|
||||
config->ctrl &= ~ETMCR_CTXID_SIZE;
|
||||
if (ts_level)
|
||||
config->ctrl |= ETMCR_TIMESTAMP_EN;
|
||||
|
||||
/*
|
||||
* Possible to have cores with PTM (supports ret stack) and ETM
|
||||
* (never has ret stack) on the same SoC. So if we have a request
|
||||
* for return stack that can't be honoured on this core then
|
||||
* clear the bit - trace will still continue normally
|
||||
* Possible to have cores with PTM (supports ret stack) and ETM (never
|
||||
* has ret stack) on the same SoC. So only enable when it can be honored
|
||||
* - trace will still continue normally otherwise.
|
||||
*/
|
||||
if ((config->ctrl & ETMCR_RETURN_STACK) &&
|
||||
!(drvdata->etmccer & ETMCCER_RETSTACK))
|
||||
config->ctrl &= ~ETMCR_RETURN_STACK;
|
||||
if (ATTR_CFG_GET_FLD(attr, retstack) &&
|
||||
(drvdata->etmccer & ETMCCER_RETSTACK))
|
||||
config->ctrl |= ETMCR_RETURN_STACK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -795,16 +800,16 @@ static int __init etm_hp_setup(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||
"arm/coresight:starting",
|
||||
etm_starting_cpu, etm_dying_cpu);
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||
"arm/coresight:starting",
|
||||
etm_starting_cpu, etm_dying_cpu);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
|
||||
"arm/coresight:online",
|
||||
etm_online_cpu, NULL);
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
|
||||
"arm/coresight:online",
|
||||
etm_online_cpu, NULL);
|
||||
|
||||
/* HP dyn state ID returned in ret on success */
|
||||
if (ret > 0) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/perf/arm_pmu.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
|
|
@ -642,18 +643,34 @@ static void etm4_enable_sysfs_smp_call(void *info)
|
|||
* TRCRSCTLR1 (always true) used to get the counter to decrement. From
|
||||
* there a resource selector is configured with the counter and the
|
||||
* timestamp control register to use the resource selector to trigger the
|
||||
* event that will insert a timestamp packet in the stream.
|
||||
* event that will insert a timestamp packet in the stream:
|
||||
*
|
||||
* +--------------+
|
||||
* | Resource 1 | fixed "always-true" resource
|
||||
* +--------------+
|
||||
* |
|
||||
* +------v-------+
|
||||
* | Counter x | (reload to 2 ^ (ts_level - 1) on underflow)
|
||||
* +--------------+
|
||||
* |
|
||||
* +------v--------------+
|
||||
* | Resource Selector y | (trigger on counter x == 0)
|
||||
* +---------------------+
|
||||
* |
|
||||
* +------v---------------+
|
||||
* | Timestamp Generator | (timestamp on resource y)
|
||||
* +----------------------+
|
||||
*/
|
||||
static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
|
||||
static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata,
|
||||
u8 ts_level)
|
||||
{
|
||||
int ctridx, ret = -EINVAL;
|
||||
int counter, rselector;
|
||||
u32 val = 0;
|
||||
int ctridx;
|
||||
int rselector;
|
||||
struct etmv4_config *config = &drvdata->config;
|
||||
|
||||
/* No point in trying if we don't have at least one counter */
|
||||
if (!drvdata->nr_cntr)
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
|
||||
/* Find a counter that hasn't been initialised */
|
||||
for (ctridx = 0; ctridx < drvdata->nr_cntr; ctridx++)
|
||||
|
|
@ -663,15 +680,19 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
|
|||
/* All the counters have been configured already, bail out */
|
||||
if (ctridx == drvdata->nr_cntr) {
|
||||
pr_debug("%s: no available counter found\n", __func__);
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Searching for an available resource selector to use, starting at
|
||||
* '2' since every implementation has at least 2 resource selector.
|
||||
* ETMIDR4 gives the number of resource selector _pairs_,
|
||||
* hence multiply by 2.
|
||||
* Searching for an available resource selector to use, starting at '2'
|
||||
* since resource 0 is the fixed 'always returns false' resource and 1
|
||||
* is the fixed 'always returns true' resource. See IHI0064H_b '7.3.64
|
||||
* TRCRSCTLRn, Resource Selection Control Registers, n=2-31'. If there
|
||||
* are no resources, there would also be no counters so wouldn't get
|
||||
* here.
|
||||
*
|
||||
* ETMIDR4 gives the number of resource selector _pairs_, hence multiply
|
||||
* by 2.
|
||||
*/
|
||||
for (rselector = 2; rselector < drvdata->nr_resource * 2; rselector++)
|
||||
if (!config->res_ctrl[rselector])
|
||||
|
|
@ -680,40 +701,47 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
|
|||
if (rselector == drvdata->nr_resource * 2) {
|
||||
pr_debug("%s: no available resource selector found\n",
|
||||
__func__);
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* Remember what counter we used */
|
||||
counter = 1 << ctridx;
|
||||
/* Initialise original and reload counter value. */
|
||||
config->cntr_val[ctridx] = config->cntrldvr[ctridx] = 1 << (ts_level - 1);
|
||||
|
||||
/*
|
||||
* Initialise original and reload counter value to the smallest
|
||||
* possible value in order to get as much precision as we can.
|
||||
* Trace Counter Control Register TRCCNTCTLRn
|
||||
*
|
||||
* CNTCHAIN = 0, don't reload on the previous counter
|
||||
* RLDSELF = true, reload counter automatically on underflow
|
||||
* RLDEVENT = RES_SEL_FALSE (0), reload on single false resource (never reload)
|
||||
* CNTEVENT = RES_SEL_TRUE (1), count single fixed 'always true' resource (always decrement)
|
||||
*/
|
||||
config->cntr_val[ctridx] = 1;
|
||||
config->cntrldvr[ctridx] = 1;
|
||||
config->cntr_ctrl[ctridx] = TRCCNTCTLRn_RLDSELF |
|
||||
FIELD_PREP(TRCCNTCTLRn_RLDEVENT_MASK,
|
||||
etm4_res_sel_single(ETM4_RES_SEL_FALSE)) |
|
||||
FIELD_PREP(TRCCNTCTLRn_CNTEVENT_MASK,
|
||||
etm4_res_sel_single(ETM4_RES_SEL_TRUE));
|
||||
|
||||
/* Set the trace counter control register */
|
||||
val = 0x1 << 16 | /* Bit 16, reload counter automatically */
|
||||
0x0 << 7 | /* Select single resource selector */
|
||||
0x1; /* Resource selector 1, i.e always true */
|
||||
/*
|
||||
* Resource Selection Control Register TRCRSCTLRn
|
||||
*
|
||||
* PAIRINV = 0, INV = 0, don't invert
|
||||
* GROUP = 2, SELECT = ctridx, trigger when counter 'ctridx' reaches 0
|
||||
*
|
||||
* Multiple counters can be selected, and each bit signifies a counter,
|
||||
* so set bit 'ctridx' to select our counter.
|
||||
*/
|
||||
config->res_ctrl[rselector] = FIELD_PREP(TRCRSCTLRn_GROUP_MASK, 2) |
|
||||
FIELD_PREP(TRCRSCTLRn_SELECT_MASK, 1 << ctridx);
|
||||
|
||||
config->cntr_ctrl[ctridx] = val;
|
||||
/*
|
||||
* Global Timestamp Control Register TRCTSCTLR
|
||||
*
|
||||
* EVENT = generate timestamp on single resource 'rselector'
|
||||
*/
|
||||
config->ts_ctrl = FIELD_PREP(TRCTSCTLR_EVENT_MASK,
|
||||
etm4_res_sel_single(rselector));
|
||||
|
||||
val = 0x2 << 16 | /* Group 0b0010 - Counter and sequencers */
|
||||
counter << 0; /* Counter to use */
|
||||
|
||||
config->res_ctrl[rselector] = val;
|
||||
|
||||
val = 0x0 << 7 | /* Select single resource selector */
|
||||
rselector; /* Resource selector */
|
||||
|
||||
config->ts_ctrl = val;
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_parse_event_config(struct coresight_device *csdev,
|
||||
|
|
@ -722,9 +750,13 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
|
|||
int ret = 0;
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
struct etmv4_config *config = &drvdata->config;
|
||||
struct perf_event_attr max_timestamp = {
|
||||
.ATTR_CFG_FLD_timestamp_CFG = U64_MAX,
|
||||
};
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
unsigned long cfg_hash;
|
||||
int preset, cc_threshold;
|
||||
u8 ts_level;
|
||||
|
||||
/* Clear configuration from previous run */
|
||||
memset(config, 0, sizeof(struct etmv4_config));
|
||||
|
|
@ -750,47 +782,51 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
|
|||
goto out;
|
||||
|
||||
/* Go from generic option to ETMv4 specifics */
|
||||
if (attr->config & BIT(ETM_OPT_CYCACC)) {
|
||||
if (ATTR_CFG_GET_FLD(attr, cycacc)) {
|
||||
config->cfg |= TRCCONFIGR_CCI;
|
||||
/* TRM: Must program this for cycacc to work */
|
||||
cc_threshold = attr->config3 & ETM_CYC_THRESHOLD_MASK;
|
||||
cc_threshold = ATTR_CFG_GET_FLD(attr, cc_threshold);
|
||||
if (!cc_threshold)
|
||||
cc_threshold = ETM_CYC_THRESHOLD_DEFAULT;
|
||||
if (cc_threshold < drvdata->ccitmin)
|
||||
cc_threshold = drvdata->ccitmin;
|
||||
config->ccctlr = cc_threshold;
|
||||
}
|
||||
if (attr->config & BIT(ETM_OPT_TS)) {
|
||||
/*
|
||||
* Configure timestamps to be emitted at regular intervals in
|
||||
* order to correlate instructions executed on different CPUs
|
||||
* (CPU-wide trace scenarios).
|
||||
*/
|
||||
ret = etm4_config_timestamp_event(drvdata);
|
||||
|
||||
ts_level = max(ATTR_CFG_GET_FLD(attr, timestamp),
|
||||
ATTR_CFG_GET_FLD(attr, deprecated_timestamp));
|
||||
if (ts_level) {
|
||||
/*
|
||||
* No need to go further if timestamp intervals can't
|
||||
* be configured.
|
||||
* Don't do counter generated timestamps when ts_level == MAX.
|
||||
* Leave only SYNC timestamps from TRCCONFIGR_TS.
|
||||
*/
|
||||
if (ret)
|
||||
goto out;
|
||||
if (ts_level != ATTR_CFG_GET_FLD(&max_timestamp, timestamp)) {
|
||||
ret = etm4_config_timestamp_event(drvdata, ts_level);
|
||||
|
||||
/*
|
||||
* Error if user asked for timestamps but there was no
|
||||
* free counter.
|
||||
*/
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* bit[11], Global timestamp tracing bit */
|
||||
config->cfg |= TRCCONFIGR_TS;
|
||||
}
|
||||
|
||||
/* Only trace contextID when runs in root PID namespace */
|
||||
if ((attr->config & BIT(ETM_OPT_CTXTID)) &&
|
||||
if (ATTR_CFG_GET_FLD(attr, contextid1) &&
|
||||
task_is_in_init_pid_ns(current))
|
||||
/* bit[6], Context ID tracing bit */
|
||||
config->cfg |= TRCCONFIGR_CID;
|
||||
|
||||
/*
|
||||
* If set bit ETM_OPT_CTXTID2 in perf config, this asks to trace VMID
|
||||
* for recording CONTEXTIDR_EL2. Do not enable VMID tracing if the
|
||||
* kernel is not running in EL2.
|
||||
* If set bit contextid2 in perf config, this asks to trace VMID for
|
||||
* recording CONTEXTIDR_EL2. Do not enable VMID tracing if the kernel
|
||||
* is not running in EL2.
|
||||
*/
|
||||
if (attr->config & BIT(ETM_OPT_CTXTID2)) {
|
||||
if (ATTR_CFG_GET_FLD(attr, contextid2)) {
|
||||
if (!is_kernel_in_hyp_mode()) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
|
@ -801,26 +837,22 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
|
|||
}
|
||||
|
||||
/* return stack - enable if selected and supported */
|
||||
if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack)
|
||||
if (ATTR_CFG_GET_FLD(attr, retstack) && drvdata->retstack)
|
||||
/* bit[12], Return stack enable bit */
|
||||
config->cfg |= TRCCONFIGR_RS;
|
||||
|
||||
/*
|
||||
* Set any selected configuration and preset.
|
||||
*
|
||||
* This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
|
||||
* in the perf attributes defined in coresight-etm-perf.c.
|
||||
* configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
|
||||
* A zero configid means no configuration active, preset = 0 means no preset selected.
|
||||
* Set any selected configuration and preset. A zero configid means no
|
||||
* configuration active, preset = 0 means no preset selected.
|
||||
*/
|
||||
if (attr->config2 & GENMASK_ULL(63, 32)) {
|
||||
cfg_hash = (u32)(attr->config2 >> 32);
|
||||
preset = attr->config & 0xF;
|
||||
cfg_hash = ATTR_CFG_GET_FLD(attr, configid);
|
||||
if (cfg_hash) {
|
||||
preset = ATTR_CFG_GET_FLD(attr, preset);
|
||||
ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
|
||||
}
|
||||
|
||||
/* branch broadcast - enable if selected and supported */
|
||||
if (attr->config & BIT(ETM_OPT_BRANCH_BROADCAST)) {
|
||||
if (ATTR_CFG_GET_FLD(attr, branch_broadcast)) {
|
||||
if (!drvdata->trcbb) {
|
||||
/*
|
||||
* Missing BB support could cause silent decode errors
|
||||
|
|
@ -829,7 +861,7 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
} else {
|
||||
config->cfg |= BIT(ETM4_CFG_BIT_BB);
|
||||
config->cfg |= TRCCONFIGR_BB;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1053,11 +1085,8 @@ static int etm4_disable_perf(struct coresight_device *csdev,
|
|||
return -EINVAL;
|
||||
|
||||
etm4_disable_hw(drvdata);
|
||||
/*
|
||||
* The config_id occupies bits 63:32 of the config2 perf event attr
|
||||
* field. If this is non-zero then we will have enabled a config.
|
||||
*/
|
||||
if (attr->config2 & GENMASK_ULL(63, 32))
|
||||
/* If configid is non-zero then we will have enabled a config. */
|
||||
if (ATTR_CFG_GET_FLD(attr, configid))
|
||||
cscfg_csdev_disable_active_config(csdev);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -225,6 +225,50 @@
|
|||
#define TRCRSCTLRn_GROUP_MASK GENMASK(19, 16)
|
||||
#define TRCRSCTLRn_SELECT_MASK GENMASK(15, 0)
|
||||
|
||||
#define TRCCNTCTLRn_CNTCHAIN BIT(17)
|
||||
#define TRCCNTCTLRn_RLDSELF BIT(16)
|
||||
#define TRCCNTCTLRn_RLDEVENT_MASK GENMASK(15, 8)
|
||||
#define TRCCNTCTLRn_CNTEVENT_MASK GENMASK(7, 0)
|
||||
|
||||
#define TRCTSCTLR_EVENT_MASK GENMASK(7, 0)
|
||||
|
||||
#define ETM4_RES_SEL_FALSE 0 /* Fixed function 'always false' resource selector */
|
||||
#define ETM4_RES_SEL_TRUE 1 /* Fixed function 'always true' resource selector */
|
||||
|
||||
#define ETM4_RES_SEL_SINGLE_MASK GENMASK(4, 0)
|
||||
#define ETM4_RES_SEL_PAIR_MASK GENMASK(3, 0)
|
||||
#define ETM4_RES_SEL_TYPE_PAIR BIT(7)
|
||||
|
||||
/*
|
||||
* Utilities for programming EVENT resource selectors, e.g. TRCCNTCTLRn_RLDEVENT.
|
||||
*
|
||||
* Resource selectors have a common format across registers:
|
||||
*
|
||||
* 7 6 5 4 0
|
||||
* +------+------+-------+
|
||||
* | TYPE | RES0 | SEL |
|
||||
* +------+------+-------+
|
||||
*
|
||||
* Where TYPE indicates whether the selector is for a single event or a pair.
|
||||
* When TYPE is pair, SEL is 4 bits wide and using pair 0 is UNPREDICTABLE.
|
||||
* Otherwise for single it's 5 bits wide.
|
||||
*/
|
||||
static inline u32 etm4_res_sel_single(u8 res_sel_idx)
|
||||
{
|
||||
WARN_ON_ONCE(!FIELD_FIT(ETM4_RES_SEL_SINGLE_MASK, res_sel_idx));
|
||||
return FIELD_PREP(ETM4_RES_SEL_SINGLE_MASK, res_sel_idx);
|
||||
}
|
||||
|
||||
static inline u32 etm4_res_sel_pair(u8 res_sel_idx)
|
||||
{
|
||||
if (__builtin_constant_p(res_sel_idx))
|
||||
BUILD_BUG_ON(res_sel_idx == 0);
|
||||
WARN_ON_ONCE(!FIELD_FIT(ETM4_RES_SEL_PAIR_MASK, res_sel_idx) ||
|
||||
(res_sel_idx == 0));
|
||||
return FIELD_PREP(ETM4_RES_SEL_PAIR_MASK, res_sel_idx) |
|
||||
ETM4_RES_SEL_TYPE_PAIR;
|
||||
}
|
||||
|
||||
/*
|
||||
* System instructions to access ETM registers.
|
||||
* See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
|
||||
|
|
@ -824,8 +868,7 @@ struct etmv4_config {
|
|||
u32 eventctrl0;
|
||||
u32 eventctrl1;
|
||||
u32 stall_ctrl;
|
||||
u32 ts_ctrl;
|
||||
u32 syncfreq;
|
||||
u32 ts_ctrl; /* TRCTSCTLR */
|
||||
u32 ccctlr;
|
||||
u32 bb_ctrl;
|
||||
u32 vinst_ctrl;
|
||||
|
|
@ -833,15 +876,16 @@ struct etmv4_config {
|
|||
u32 vissctlr;
|
||||
u32 vipcssctlr;
|
||||
u8 seq_idx;
|
||||
u8 syncfreq;
|
||||
u32 seq_ctrl[ETM_MAX_SEQ_STATES];
|
||||
u32 seq_rst;
|
||||
u32 seq_state;
|
||||
u8 cntr_idx;
|
||||
u32 cntrldvr[ETMv4_MAX_CNTR];
|
||||
u32 cntr_ctrl[ETMv4_MAX_CNTR];
|
||||
u32 cntr_val[ETMv4_MAX_CNTR];
|
||||
u32 cntrldvr[ETMv4_MAX_CNTR]; /* TRCCNTRLDVRn */
|
||||
u32 cntr_ctrl[ETMv4_MAX_CNTR]; /* TRCCNTCTLRn */
|
||||
u32 cntr_val[ETMv4_MAX_CNTR]; /* TRCCNTVRn */
|
||||
u8 res_idx;
|
||||
u32 res_ctrl[ETM_MAX_RES_SEL];
|
||||
u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */
|
||||
u8 ss_idx;
|
||||
u32 ss_ctrl[ETM_MAX_SS_CMP];
|
||||
u32 ss_status[ETM_MAX_SS_CMP];
|
||||
|
|
@ -1016,27 +1060,27 @@ struct etmv4_drvdata {
|
|||
u8 ns_ex_level;
|
||||
u8 q_support;
|
||||
u8 os_lock_model;
|
||||
bool sticky_enable;
|
||||
bool boot_enable;
|
||||
bool os_unlock;
|
||||
bool instrp0;
|
||||
bool q_filt;
|
||||
bool trcbb;
|
||||
bool trccond;
|
||||
bool retstack;
|
||||
bool trccci;
|
||||
bool trc_error;
|
||||
bool syncpr;
|
||||
bool stallctl;
|
||||
bool sysstall;
|
||||
bool nooverflow;
|
||||
bool atbtrig;
|
||||
bool lpoverride;
|
||||
bool sticky_enable : 1;
|
||||
bool boot_enable : 1;
|
||||
bool os_unlock : 1;
|
||||
bool instrp0 : 1;
|
||||
bool q_filt : 1;
|
||||
bool trcbb : 1;
|
||||
bool trccond : 1;
|
||||
bool retstack : 1;
|
||||
bool trccci : 1;
|
||||
bool trc_error : 1;
|
||||
bool syncpr : 1;
|
||||
bool stallctl : 1;
|
||||
bool sysstall : 1;
|
||||
bool nooverflow : 1;
|
||||
bool atbtrig : 1;
|
||||
bool lpoverride : 1;
|
||||
bool skip_power_up : 1;
|
||||
bool paused : 1;
|
||||
u64 trfcr;
|
||||
struct etmv4_config config;
|
||||
struct etmv4_save_state *save_state;
|
||||
bool skip_power_up;
|
||||
bool paused;
|
||||
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1306,6 +1306,19 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
|
|||
|
||||
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
|
||||
/*
|
||||
* Since the sysfs buffer allocation and the hardware enablement is not
|
||||
* in the same critical region, it's possible to race with the perf.
|
||||
*/
|
||||
if (coresight_get_mode(csdev) == CS_MODE_PERF) {
|
||||
drvdata->sysfs_buf = NULL;
|
||||
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
/* Free allocated memory out side of the spinlock */
|
||||
tmc_etr_free_sysfs_buf(sysfs_buf);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* In sysFS mode we can have multiple writers per sink. Since this
|
||||
* sink is already enabled no memory is needed and the HW need not be
|
||||
|
|
@ -1354,9 +1367,7 @@ EXPORT_SYMBOL_GPL(tmc_etr_get_buffer);
|
|||
|
||||
/*
|
||||
* alloc_etr_buf: Allocate ETR buffer for use by perf.
|
||||
* The size of the hardware buffer is dependent on the size configured
|
||||
* via sysfs and the perf ring buffer size. We prefer to allocate the
|
||||
* largest possible size, scaling down the size by half until it
|
||||
* Allocate the largest possible size, scaling down the size by half until it
|
||||
* reaches a minimum limit (1M), beyond which we give up.
|
||||
*/
|
||||
static struct etr_buf *
|
||||
|
|
@ -1365,36 +1376,26 @@ alloc_etr_buf(struct tmc_drvdata *drvdata, struct perf_event *event,
|
|||
{
|
||||
int node;
|
||||
struct etr_buf *etr_buf;
|
||||
unsigned long size;
|
||||
ssize_t size;
|
||||
|
||||
node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu);
|
||||
/*
|
||||
* Try to match the perf ring buffer size if it is larger
|
||||
* than the size requested via sysfs.
|
||||
*/
|
||||
if ((nr_pages << PAGE_SHIFT) > drvdata->size) {
|
||||
etr_buf = tmc_alloc_etr_buf(drvdata, ((ssize_t)nr_pages << PAGE_SHIFT),
|
||||
0, node, NULL);
|
||||
if (!IS_ERR(etr_buf))
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Use the minimum limit if the required size is smaller */
|
||||
size = nr_pages << PAGE_SHIFT;
|
||||
size = max_t(ssize_t, size, TMC_ETR_PERF_MIN_BUF_SIZE);
|
||||
|
||||
/*
|
||||
* Else switch to configured size for this ETR
|
||||
* and scale down until we hit the minimum limit.
|
||||
* Try to allocate the required size for this ETR, if failed scale
|
||||
* down until we hit the minimum limit.
|
||||
*/
|
||||
size = drvdata->size;
|
||||
do {
|
||||
etr_buf = tmc_alloc_etr_buf(drvdata, size, 0, node, NULL);
|
||||
if (!IS_ERR(etr_buf))
|
||||
goto done;
|
||||
return etr_buf;
|
||||
size /= 2;
|
||||
} while (size >= TMC_ETR_PERF_MIN_BUF_SIZE);
|
||||
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
done:
|
||||
return etr_buf;
|
||||
}
|
||||
|
||||
static struct etr_buf *
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ struct tmc_resrv_buf {
|
|||
* @pid: Process ID of the process that owns the session that is using
|
||||
* this component. For example this would be the pid of the Perf
|
||||
* process.
|
||||
* @reading: buffer's in the reading through "/dev/xyz.tmc" entry
|
||||
* @stop_on_flush: Stop on flush trigger user configuration.
|
||||
* @buf: Snapshot of the trace data for ETF/ETB.
|
||||
* @etr_buf: details of buffer used in TMC-ETR
|
||||
|
|
@ -233,6 +234,7 @@ struct tmc_resrv_buf {
|
|||
* @trigger_cntr: amount of words to store after a trigger.
|
||||
* @etr_caps: Bitmask of capabilities of the TMC ETR, inferred from the
|
||||
* device configuration register (DEVID)
|
||||
* @etr_mode: User preferred mode of the ETR device, default auto mode.
|
||||
* @idr: Holds etr_bufs allocated for this ETR.
|
||||
* @idr_mutex: Access serialisation for idr.
|
||||
* @sysfs_buf: SYSFS buffer for ETR.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
* @base: memory mapped base address for this component.
|
||||
* @dev: device node for trace_noc_drvdata.
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @spinlock: serialize enable/disable operation.
|
||||
* @atid: id for the trace packet.
|
||||
*/
|
||||
|
|
@ -41,8 +42,9 @@ struct trace_noc_drvdata {
|
|||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct clk *pclk;
|
||||
spinlock_t spinlock;
|
||||
u32 atid;
|
||||
int atid;
|
||||
};
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(trace_noc_devs, "traceNoc");
|
||||
|
|
@ -51,6 +53,12 @@ static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
|
|||
{
|
||||
u32 val;
|
||||
|
||||
/* No valid ATID, simply enable the unit */
|
||||
if (drvdata->atid == -EOPNOTSUPP) {
|
||||
writel(TRACE_NOC_CTRL_PORTEN, drvdata->base + TRACE_NOC_CTRL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set ATID */
|
||||
writel_relaxed(drvdata->atid, drvdata->base + TRACE_NOC_XLD);
|
||||
|
||||
|
|
@ -124,6 +132,11 @@ static int trace_noc_init_default_data(struct trace_noc_drvdata *drvdata)
|
|||
{
|
||||
int atid;
|
||||
|
||||
if (!dev_is_amba(drvdata->dev)) {
|
||||
drvdata->atid = -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
atid = coresight_trace_id_get_system_id();
|
||||
if (atid < 0)
|
||||
return atid;
|
||||
|
|
@ -149,8 +162,21 @@ static struct attribute *coresight_tnoc_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static umode_t trace_id_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (attr == &dev_attr_traceid.attr && drvdata->atid < 0)
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
static const struct attribute_group coresight_tnoc_group = {
|
||||
.attrs = coresight_tnoc_attrs,
|
||||
.is_visible = trace_id_is_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *coresight_tnoc_groups[] = {
|
||||
|
|
@ -158,9 +184,8 @@ static const struct attribute_group *coresight_tnoc_groups[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static int _tnoc_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata;
|
||||
struct trace_noc_drvdata *drvdata;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
|
@ -173,16 +198,20 @@ static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
pdata = coresight_get_platform_data(dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
adev->dev.platform_data = pdata;
|
||||
dev->platform_data = pdata;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->dev = &adev->dev;
|
||||
drvdata->dev = dev;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
drvdata->base = devm_ioremap_resource(dev, &adev->res);
|
||||
ret = coresight_get_enable_clocks(dev, &drvdata->pclk, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drvdata->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(drvdata->base))
|
||||
return PTR_ERR(drvdata->base);
|
||||
|
||||
|
|
@ -195,20 +224,31 @@ static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
desc.ops = &trace_noc_cs_ops;
|
||||
desc.type = CORESIGHT_DEV_TYPE_LINK;
|
||||
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
|
||||
desc.pdata = adev->dev.platform_data;
|
||||
desc.dev = &adev->dev;
|
||||
desc.pdata = pdata;
|
||||
desc.dev = dev;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(drvdata->base);
|
||||
desc.groups = coresight_tnoc_groups;
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
coresight_trace_id_put_system_id(drvdata->atid);
|
||||
if (drvdata->atid > 0)
|
||||
coresight_trace_id_put_system_id(drvdata->atid);
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
}
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trace_noc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _tnoc_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void trace_noc_remove(struct amba_device *adev)
|
||||
{
|
||||
struct trace_noc_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
|
|
@ -240,7 +280,81 @@ static struct amba_driver trace_noc_driver = {
|
|||
.id_table = trace_noc_ids,
|
||||
};
|
||||
|
||||
module_amba_driver(trace_noc_driver);
|
||||
static int itnoc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = _tnoc_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void itnoc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct trace_noc_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int itnoc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int itnoc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(drvdata->pclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops itnoc_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(itnoc_runtime_suspend, itnoc_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id itnoc_of_match[] = {
|
||||
{ .compatible = "qcom,coresight-itnoc" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, itnoc_of_match);
|
||||
|
||||
static struct platform_driver itnoc_driver = {
|
||||
.probe = itnoc_probe,
|
||||
.remove = itnoc_remove,
|
||||
.driver = {
|
||||
.name = "coresight-itnoc",
|
||||
.of_match_table = itnoc_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &itnoc_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tnoc_init(void)
|
||||
{
|
||||
return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver, THIS_MODULE);
|
||||
}
|
||||
|
||||
static void __exit tnoc_exit(void)
|
||||
{
|
||||
coresight_remove_driver(&trace_noc_driver, &itnoc_driver);
|
||||
}
|
||||
module_init(tnoc_init);
|
||||
module_exit(tnoc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Trace NOC driver");
|
||||
|
|
|
|||
|
|
@ -137,12 +137,46 @@ static int tpda_get_element_size(struct tpda_drvdata *drvdata,
|
|||
/* Settings pre enabling port control register */
|
||||
static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
|
||||
{
|
||||
u32 val;
|
||||
u32 val = 0;
|
||||
|
||||
val = readl_relaxed(drvdata->base + TPDA_CR);
|
||||
val &= ~TPDA_CR_ATID;
|
||||
val |= FIELD_PREP(TPDA_CR_ATID, drvdata->atid);
|
||||
if (drvdata->trig_async)
|
||||
val |= TPDA_CR_SRIE;
|
||||
|
||||
if (drvdata->trig_flag_ts)
|
||||
val |= TPDA_CR_FLRIE;
|
||||
|
||||
if (drvdata->trig_freq)
|
||||
val |= TPDA_CR_FRIE;
|
||||
|
||||
if (drvdata->freq_ts)
|
||||
val |= TPDA_CR_FREQTS;
|
||||
|
||||
if (drvdata->cmbchan_mode)
|
||||
val |= TPDA_CR_CMBCHANMODE;
|
||||
|
||||
writel_relaxed(val, drvdata->base + TPDA_CR);
|
||||
|
||||
/*
|
||||
* If FLRIE bit is set, set the master and channel
|
||||
* id as zero
|
||||
*/
|
||||
if (drvdata->trig_flag_ts)
|
||||
writel_relaxed(0x0, drvdata->base + TPDA_FPID_CR);
|
||||
|
||||
/* Initialize with a value of 0 */
|
||||
val = 0;
|
||||
if (drvdata->syncr_mode)
|
||||
val |= TPDA_SYNCR_MODE_CTRL_MASK;
|
||||
|
||||
if (drvdata->syncr_count > 0 &&
|
||||
drvdata->syncr_count < TPDA_SYNCR_COUNT_MASK)
|
||||
val |= drvdata->syncr_count;
|
||||
else
|
||||
/* Program the count to its MAX value by default */
|
||||
val |= TPDA_SYNCR_COUNT_MASK;
|
||||
|
||||
writel_relaxed(val, drvdata->base + TPDA_SYNCR);
|
||||
}
|
||||
|
||||
static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
|
||||
|
|
@ -258,6 +292,248 @@ static const struct coresight_ops tpda_cs_ops = {
|
|||
.link_ops = &tpda_link_ops,
|
||||
};
|
||||
|
||||
/* Read cross-trigger register member */
|
||||
static ssize_t tpda_trig_sysfs_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tpda_trig_sysfs_attribute *tpda_attr =
|
||||
container_of(attr, struct tpda_trig_sysfs_attribute, attr);
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
switch (tpda_attr->mem) {
|
||||
case FREQTS:
|
||||
return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->freq_ts);
|
||||
case FRIE:
|
||||
return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_freq);
|
||||
case FLRIE:
|
||||
return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_flag_ts);
|
||||
case SRIE:
|
||||
return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_async);
|
||||
case CMBCHANMODE:
|
||||
return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->cmbchan_mode);
|
||||
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t tpda_trig_sysfs_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct tpda_trig_sysfs_attribute *tpda_attr =
|
||||
container_of(attr, struct tpda_trig_sysfs_attribute, attr);
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
switch (tpda_attr->mem) {
|
||||
case FREQTS:
|
||||
drvdata->freq_ts = !!val;
|
||||
break;
|
||||
case FRIE:
|
||||
drvdata->trig_freq = !!val;
|
||||
break;
|
||||
case FLRIE:
|
||||
drvdata->trig_flag_ts = !!val;
|
||||
break;
|
||||
case SRIE:
|
||||
drvdata->trig_async = !!val;
|
||||
break;
|
||||
case CMBCHANMODE:
|
||||
drvdata->cmbchan_mode = !!val;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t global_flush_req_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (!drvdata->csdev->refcnt)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
val = readl_relaxed(drvdata->base + TPDA_CR);
|
||||
/* read global_flush_req bit */
|
||||
val &= TPDA_CR_FLREQ;
|
||||
|
||||
return sysfs_emit(buf, "%lu\n", val);
|
||||
}
|
||||
|
||||
static ssize_t global_flush_req_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (!drvdata->csdev->refcnt || !val)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
val = readl_relaxed(drvdata->base + TPDA_CR);
|
||||
/* set global_flush_req bit */
|
||||
val |= TPDA_CR_FLREQ;
|
||||
CS_UNLOCK(drvdata->base);
|
||||
writel_relaxed(val, drvdata->base + TPDA_CR);
|
||||
CS_LOCK(drvdata->base);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(global_flush_req);
|
||||
|
||||
static ssize_t syncr_mode_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val, syncr_val;
|
||||
|
||||
if (!drvdata->csdev->refcnt)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
syncr_val = readl_relaxed(drvdata->base + TPDA_SYNCR);
|
||||
val = FIELD_GET(TPDA_SYNCR_MODE_CTRL_MASK, syncr_val);
|
||||
|
||||
return sysfs_emit(buf, "%lu\n", val);
|
||||
}
|
||||
|
||||
static ssize_t syncr_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
/* set the mode when first enabling the device */
|
||||
drvdata->syncr_mode = !!val;
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(syncr_mode);
|
||||
|
||||
static ssize_t syncr_count_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (!drvdata->csdev->refcnt)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
val = readl_relaxed(drvdata->base + TPDA_SYNCR);
|
||||
val &= TPDA_SYNCR_COUNT_MASK;
|
||||
|
||||
return sysfs_emit(buf, "%lu\n", val);
|
||||
}
|
||||
|
||||
static ssize_t syncr_count_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val > TPDA_SYNCR_COUNT_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
drvdata->syncr_count = val;
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(syncr_count);
|
||||
|
||||
static ssize_t port_flush_req_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (!drvdata->csdev->refcnt)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
val = readl_relaxed(drvdata->base + TPDA_FLUSH_CR);
|
||||
|
||||
return sysfs_emit(buf, "0x%lx\n", val);
|
||||
}
|
||||
|
||||
static ssize_t port_flush_req_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
u32 val;
|
||||
|
||||
if (kstrtou32(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (!drvdata->csdev->refcnt || !val)
|
||||
return -EINVAL;
|
||||
|
||||
guard(spinlock)(&drvdata->spinlock);
|
||||
CS_UNLOCK(drvdata->base);
|
||||
writel_relaxed(val, drvdata->base + TPDA_FLUSH_CR);
|
||||
CS_LOCK(drvdata->base);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(port_flush_req);
|
||||
|
||||
static struct attribute *tpda_attrs[] = {
|
||||
&dev_attr_global_flush_req.attr,
|
||||
&dev_attr_syncr_mode.attr,
|
||||
&dev_attr_syncr_count.attr,
|
||||
&dev_attr_port_flush_req.attr,
|
||||
tpda_trig_sysfs_rw(freq_ts_enable, FREQTS),
|
||||
tpda_trig_sysfs_rw(trig_freq_enable, FRIE),
|
||||
tpda_trig_sysfs_rw(trig_flag_ts_enable, FLRIE),
|
||||
tpda_trig_sysfs_rw(trig_async_enable, SRIE),
|
||||
tpda_trig_sysfs_rw(cmbchan_mode, CMBCHANMODE),
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group tpda_attr_grp = {
|
||||
.attrs = tpda_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *tpda_attr_grps[] = {
|
||||
&tpda_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int tpda_init_default_data(struct tpda_drvdata *drvdata)
|
||||
{
|
||||
int atid;
|
||||
|
|
@ -273,6 +549,7 @@ static int tpda_init_default_data(struct tpda_drvdata *drvdata)
|
|||
return atid;
|
||||
|
||||
drvdata->atid = atid;
|
||||
drvdata->freq_ts = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +593,7 @@ static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
desc.ops = &tpda_cs_ops;
|
||||
desc.pdata = adev->dev.platform_data;
|
||||
desc.dev = &adev->dev;
|
||||
desc.groups = tpda_attr_grps;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2023,2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CORESIGHT_CORESIGHT_TPDA_H
|
||||
|
|
@ -8,6 +8,29 @@
|
|||
|
||||
#define TPDA_CR (0x000)
|
||||
#define TPDA_Pn_CR(n) (0x004 + (n * 4))
|
||||
#define TPDA_FPID_CR (0x084)
|
||||
#define TPDA_SYNCR (0x08C)
|
||||
#define TPDA_FLUSH_CR (0x090)
|
||||
|
||||
/* Cross trigger global (all ports) flush request bit */
|
||||
#define TPDA_CR_FLREQ BIT(0)
|
||||
/* Cross trigger FREQ packets timestamp bit */
|
||||
#define TPDA_CR_FREQTS BIT(2)
|
||||
/* Cross trigger FREQ packet request bit */
|
||||
#define TPDA_CR_FRIE BIT(3)
|
||||
/* Cross trigger FLAG packet request interface bit */
|
||||
#define TPDA_CR_FLRIE BIT(4)
|
||||
/* Cross trigger synchronization bit */
|
||||
#define TPDA_CR_SRIE BIT(5)
|
||||
/* Bits 6 ~ 12 is for atid value */
|
||||
#define TPDA_CR_ATID GENMASK(12, 6)
|
||||
/*
|
||||
* Channel mode bit of the packetization of CMB/MCB traffic
|
||||
* 0 - raw channel mapping mode
|
||||
* 1 - channel pair marking mode
|
||||
*/
|
||||
#define TPDA_CR_CMBCHANMODE BIT(20)
|
||||
|
||||
/* Aggregator port enable bit */
|
||||
#define TPDA_Pn_CR_ENA BIT(0)
|
||||
/* Aggregator port CMB data set element size bit */
|
||||
|
|
@ -15,10 +38,12 @@
|
|||
/* Aggregator port DSB data set element size bit */
|
||||
#define TPDA_Pn_CR_DSBSIZE BIT(8)
|
||||
|
||||
#define TPDA_MAX_INPORTS 32
|
||||
/* TPDA_SYNCR count mask */
|
||||
#define TPDA_SYNCR_COUNT_MASK GENMASK(11, 0)
|
||||
/* TPDA_SYNCR mode control bit */
|
||||
#define TPDA_SYNCR_MODE_CTRL_MASK GENMASK(12, 12)
|
||||
|
||||
/* Bits 6 ~ 12 is for atid value */
|
||||
#define TPDA_CR_ATID GENMASK(12, 6)
|
||||
#define TPDA_MAX_INPORTS 32
|
||||
|
||||
/**
|
||||
* struct tpda_drvdata - specifics associated to an TPDA component
|
||||
|
|
@ -29,6 +54,13 @@
|
|||
* @enable: enable status of the component.
|
||||
* @dsb_esize Record the DSB element size.
|
||||
* @cmb_esize Record the CMB element size.
|
||||
* @trig_async: Enable/disable cross trigger synchronization sequence interface.
|
||||
* @trig_flag_ts: Enable/disable cross trigger FLAG packet request interface.
|
||||
* @trig_freq: Enable/disable cross trigger FREQ packet request interface.
|
||||
* @freq_ts: Enable/disable the timestamp for all FREQ packets.
|
||||
* @cmbchan_mode: Configure the CMB/MCMB channel mode.
|
||||
* @syncr_mode: Setting the mode for counting packets.
|
||||
* @syncr_count: Setting the value of the count.
|
||||
*/
|
||||
struct tpda_drvdata {
|
||||
void __iomem *base;
|
||||
|
|
@ -38,6 +70,42 @@ struct tpda_drvdata {
|
|||
u8 atid;
|
||||
u32 dsb_esize;
|
||||
u32 cmb_esize;
|
||||
bool trig_async;
|
||||
bool trig_flag_ts;
|
||||
bool trig_freq;
|
||||
bool freq_ts;
|
||||
bool cmbchan_mode;
|
||||
bool syncr_mode;
|
||||
u32 syncr_count;
|
||||
};
|
||||
|
||||
/* Enumerate members of global control register(cr) */
|
||||
enum tpda_cr_mem {
|
||||
FREQTS,
|
||||
FRIE,
|
||||
FLRIE,
|
||||
SRIE,
|
||||
CMBCHANMODE
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tpda_trig_sysfs_attribute - Record the member variables of cross
|
||||
* trigger register that need to be operated by sysfs file
|
||||
* @attr: The device attribute
|
||||
* @mem: The member in the control register data structure
|
||||
*/
|
||||
struct tpda_trig_sysfs_attribute {
|
||||
struct device_attribute attr;
|
||||
enum tpda_cr_mem mem;
|
||||
};
|
||||
|
||||
#define tpda_trig_sysfs_rw(name, mem) \
|
||||
(&((struct tpda_trig_sysfs_attribute[]) { \
|
||||
{ \
|
||||
__ATTR(name, 0644, tpda_trig_sysfs_show, \
|
||||
tpda_trig_sysfs_store), \
|
||||
mem, \
|
||||
} \
|
||||
})[0].attr.attr)
|
||||
|
||||
#endif /* _CORESIGHT_CORESIGHT_TPDA_H */
|
||||
|
|
|
|||
|
|
@ -21,30 +21,6 @@
|
|||
*/
|
||||
#define CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) (0x10 + (cpu * 2))
|
||||
|
||||
/*
|
||||
* Below are the definition of bit offsets for perf option, and works as
|
||||
* arbitrary values for all ETM versions.
|
||||
*
|
||||
* Most of them are orignally from ETMv3.5/PTM's ETMCR config, therefore,
|
||||
* ETMv3.5/PTM doesn't define ETMCR config bits with prefix "ETM3_" and
|
||||
* directly use below macros as config bits.
|
||||
*/
|
||||
#define ETM_OPT_BRANCH_BROADCAST 8
|
||||
#define ETM_OPT_CYCACC 12
|
||||
#define ETM_OPT_CTXTID 14
|
||||
#define ETM_OPT_CTXTID2 15
|
||||
#define ETM_OPT_TS 28
|
||||
#define ETM_OPT_RETSTK 29
|
||||
|
||||
/* ETMv4 CONFIGR programming bits for the ETM OPTs */
|
||||
#define ETM4_CFG_BIT_BB 3
|
||||
#define ETM4_CFG_BIT_CYCACC 4
|
||||
#define ETM4_CFG_BIT_CTXTID 6
|
||||
#define ETM4_CFG_BIT_VMID 7
|
||||
#define ETM4_CFG_BIT_TS 11
|
||||
#define ETM4_CFG_BIT_RETSTK 12
|
||||
#define ETM4_CFG_BIT_VMID_OPT 15
|
||||
|
||||
/*
|
||||
* Interpretation of the PERF_RECORD_AUX_OUTPUT_HW_ID payload.
|
||||
* Used to associate a CPU with the CoreSight Trace ID.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue