Skip to content

Commit c39e88d

Browse files
Mao Jinlongjiegan0107
authored andcommitted
FROMLIST: coresight: Add remote etm support
The system on chip (SoC) consists of main APSS(Applications processor subsytem) and additional processors like modem, lpass. Coresight remote etm(Embedded Trace Macrocell) driver is for enabling and disabling the etm trace of remote processors. It uses QMI interface to communicate with remote processors' software and uses coresight framework to configure the connection from remote etm source to TMC sinks. Link: https://lore.kernel.org/all/20250424115854.2328190-5-quic_jinlmao@quicinc.com/ Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
1 parent bf06daf commit c39e88d

3 files changed

Lines changed: 265 additions & 0 deletions

File tree

drivers/hwtracing/coresight/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,16 @@ config CORESIGHT_QMI
279279
To compile this driver as a module, choose M here: the module will be
280280
called coresight-qmi.
281281

282+
config CORESIGHT_REMOTE_ETM
283+
tristate "Remote processor ETM trace support"
284+
depends on QCOM_QMI_HELPERS
285+
help
286+
Enables support for ETM trace collection on remote processor using
287+
CoreSight framework. Enabling this will allow turning on ETM
288+
tracing on remote processor via sysfs by configuring the required
289+
CoreSight components.
290+
291+
To compile this driver as a module, choose M here: the module will be
292+
called coresight-remote-etm.
293+
282294
endif

drivers/hwtracing/coresight/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \
5353
coresight-cti-sysfs.o
5454
obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
5555
obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o
56+
obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o
5657
obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
5758
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
5859
coresight-ctcu-y := coresight-ctcu-core.o
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
4+
*/
5+
6+
#include <linux/module.h>
7+
#include <linux/init.h>
8+
#include <linux/device.h>
9+
#include <linux/platform_device.h>
10+
#include <linux/mutex.h>
11+
#include <linux/of.h>
12+
#include <linux/coresight.h>
13+
14+
#include "coresight-qmi.h"
15+
16+
#define CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN (7)
17+
18+
DEFINE_CORESIGHT_DEVLIST(remote_etm_devs, "remote-etm");
19+
20+
/**
21+
* struct remote_etm_drvdata - specifics associated to remote etm device
22+
* @dev: the device entity associated to this component
23+
* @csdev: component vitals needed by the framework
24+
* @mutex: lock for seting etm
25+
* @inst_id: the instance id of the remote connection
26+
*/
27+
struct remote_etm_drvdata {
28+
struct device *dev;
29+
struct coresight_device *csdev;
30+
struct mutex mutex;
31+
u32 inst_id;
32+
};
33+
34+
/*
35+
* Element info to descrbe the coresight_set_etm_req_msg_v01 struct
36+
* which is used to encode the request.
37+
*/
38+
static struct qmi_elem_info coresight_set_etm_req_msg_v01_ei[] = {
39+
{
40+
.data_type = QMI_UNSIGNED_4_BYTE,
41+
.elem_len = 1,
42+
.elem_size = sizeof(enum coresight_etm_state_enum_type_v01),
43+
.array_type = NO_ARRAY,
44+
.tlv_type = 0x01,
45+
.offset = offsetof(struct coresight_set_etm_req_msg_v01,
46+
state),
47+
.ei_array = NULL,
48+
},
49+
{
50+
.data_type = QMI_EOTI,
51+
.elem_len = 0,
52+
.elem_size = 0,
53+
.array_type = NO_ARRAY,
54+
.tlv_type = 0,
55+
.offset = 0,
56+
.ei_array = NULL,
57+
},
58+
};
59+
60+
/*
61+
* Element info to describe the coresight_set_etm_resp_msg_v01 struct
62+
* which is used to decode the response.
63+
*/
64+
static struct qmi_elem_info coresight_set_etm_resp_msg_v01_ei[] = {
65+
{
66+
.data_type = QMI_STRUCT,
67+
.elem_len = 1,
68+
.elem_size = sizeof(struct qmi_response_type_v01),
69+
.array_type = NO_ARRAY,
70+
.tlv_type = 0x02,
71+
.offset = offsetof(struct coresight_set_etm_resp_msg_v01,
72+
resp),
73+
.ei_array = qmi_response_type_v01_ei,
74+
},
75+
{
76+
.data_type = QMI_EOTI,
77+
.elem_len = 0,
78+
.elem_size = 0,
79+
.array_type = NO_ARRAY,
80+
.tlv_type = 0,
81+
.offset = 0,
82+
.ei_array = NULL,
83+
},
84+
};
85+
86+
static int remote_etm_enable(struct coresight_device *csdev,
87+
struct perf_event *event, enum cs_mode mode,
88+
__maybe_unused struct coresight_path *path)
89+
{
90+
struct remote_etm_drvdata *drvdata =
91+
dev_get_drvdata(csdev->dev.parent);
92+
struct coresight_set_etm_req_msg_v01 req;
93+
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
94+
int ret = 0;
95+
96+
mutex_lock(&drvdata->mutex);
97+
98+
if (mode != CS_MODE_SYSFS) {
99+
ret = -EINVAL;
100+
goto err;
101+
}
102+
103+
if (!coresight_take_mode(csdev, mode)) {
104+
ret = -EBUSY;
105+
goto err;
106+
}
107+
108+
req.state = CORESIGHT_ETM_STATE_ENABLED_V01;
109+
110+
ret = coresight_send_qmi_request(drvdata->inst_id, CORESIGHT_QMI_SET_ETM_REQ_V01,
111+
coresight_set_etm_resp_msg_v01_ei,
112+
coresight_set_etm_req_msg_v01_ei,
113+
&resp, &req, CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN);
114+
115+
if (ret)
116+
goto err;
117+
118+
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
119+
dev_err(drvdata->dev, "QMI request failed 0x%x\n", resp.resp.error);
120+
ret = -EINVAL;
121+
goto err;
122+
}
123+
124+
mutex_unlock(&drvdata->mutex);
125+
return 0;
126+
err:
127+
coresight_set_mode(csdev, CS_MODE_DISABLED);
128+
mutex_unlock(&drvdata->mutex);
129+
return ret;
130+
131+
}
132+
133+
static void remote_etm_disable(struct coresight_device *csdev,
134+
struct perf_event *event)
135+
{
136+
struct remote_etm_drvdata *drvdata =
137+
dev_get_drvdata(csdev->dev.parent);
138+
struct coresight_set_etm_req_msg_v01 req;
139+
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
140+
int ret = 0;
141+
142+
mutex_lock(&drvdata->mutex);
143+
144+
req.state = CORESIGHT_ETM_STATE_DISABLED_V01;
145+
146+
ret = coresight_send_qmi_request(drvdata->inst_id, CORESIGHT_QMI_SET_ETM_REQ_V01,
147+
coresight_set_etm_resp_msg_v01_ei,
148+
coresight_set_etm_req_msg_v01_ei,
149+
&resp, &req, CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN);
150+
if (ret)
151+
dev_err(drvdata->dev, "Send qmi request failed %d\n", ret);
152+
153+
if (resp.resp.result != QMI_RESULT_SUCCESS_V01)
154+
dev_err(drvdata->dev, "QMI request failed %d\n", resp.resp.error);
155+
156+
coresight_set_mode(csdev, CS_MODE_DISABLED);
157+
mutex_unlock(&drvdata->mutex);
158+
}
159+
160+
static const struct coresight_ops_source remote_etm_source_ops = {
161+
.enable = remote_etm_enable,
162+
.disable = remote_etm_disable,
163+
};
164+
165+
static const struct coresight_ops remote_cs_ops = {
166+
.source_ops = &remote_etm_source_ops,
167+
};
168+
169+
static int remote_etm_probe(struct platform_device *pdev)
170+
{
171+
struct device *dev = &pdev->dev;
172+
struct coresight_platform_data *pdata;
173+
struct remote_etm_drvdata *drvdata;
174+
struct coresight_desc desc = {0 };
175+
int ret;
176+
177+
desc.name = coresight_alloc_device_name(&remote_etm_devs, dev);
178+
if (!desc.name)
179+
return -ENOMEM;
180+
pdata = coresight_get_platform_data(dev);
181+
if (IS_ERR(pdata))
182+
return PTR_ERR(pdata);
183+
pdev->dev.platform_data = pdata;
184+
185+
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
186+
if (!drvdata)
187+
return -ENOMEM;
188+
189+
drvdata->dev = dev;
190+
platform_set_drvdata(pdev, drvdata);
191+
192+
ret = of_property_read_u32(dev->of_node, "qcom,qmi-id",
193+
&drvdata->inst_id);
194+
if (ret)
195+
return ret;
196+
197+
mutex_init(&drvdata->mutex);
198+
199+
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
200+
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS;
201+
desc.ops = &remote_cs_ops;
202+
desc.pdata = pdev->dev.platform_data;
203+
desc.dev = &pdev->dev;
204+
drvdata->csdev = coresight_register(&desc);
205+
if (IS_ERR(drvdata->csdev)) {
206+
ret = PTR_ERR(drvdata->csdev);
207+
goto err;
208+
}
209+
210+
dev_dbg(dev, "Remote ETM initialized\n");
211+
212+
return 0;
213+
214+
err:
215+
return ret;
216+
}
217+
218+
static void remote_etm_remove(struct platform_device *pdev)
219+
{
220+
struct remote_etm_drvdata *drvdata = platform_get_drvdata(pdev);
221+
222+
coresight_unregister(drvdata->csdev);
223+
}
224+
225+
static const struct of_device_id remote_etm_match[] = {
226+
{.compatible = "qcom,coresight-remote-etm"},
227+
{}
228+
};
229+
230+
static struct platform_driver remote_etm_driver = {
231+
.probe = remote_etm_probe,
232+
.remove = remote_etm_remove,
233+
.driver = {
234+
.name = "coresight-remote-etm",
235+
.of_match_table = remote_etm_match,
236+
},
237+
};
238+
239+
static int __init remote_etm_init(void)
240+
{
241+
return platform_driver_register(&remote_etm_driver);
242+
}
243+
module_init(remote_etm_init);
244+
245+
static void __exit remote_etm_exit(void)
246+
{
247+
platform_driver_unregister(&remote_etm_driver);
248+
}
249+
module_exit(remote_etm_exit);
250+
251+
MODULE_LICENSE("GPL");
252+
MODULE_DESCRIPTION("CoreSight Remote ETM driver");

0 commit comments

Comments
 (0)