1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3 *
4 * (C) COPYRIGHT 2022 ARM Limited. All rights reserved.
5 *
6 * This program is free software and is provided to you under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation, and any use by you of this program is subject to the terms
9 * of such GNU license.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can access it online at
18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 *
20 */
21
22 #include <linux/atomic.h>
23 #include <linux/coresight.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/types.h>
26 #include <linux/version.h>
27 #include <linux/vmalloc.h>
28 #include <linux/of_platform.h>
29
30 #include <linux/mali_kbase_debug_coresight_csf.h>
31 #include <coresight-priv.h>
32 #include "sources/coresight_mali_sources.h"
33
coresight_mali_source_trace_id(struct coresight_device * csdev)34 static int coresight_mali_source_trace_id(struct coresight_device *csdev)
35 {
36 struct coresight_mali_source_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
37
38 return drvdata->trcid;
39 }
40
coresight_mali_enable_source(struct coresight_device * csdev,struct perf_event * event,u32 mode)41 static int coresight_mali_enable_source(struct coresight_device *csdev, struct perf_event *event,
42 u32 mode)
43 {
44 return coresight_mali_enable_component(csdev, mode);
45 }
46
coresight_mali_disable_source(struct coresight_device * csdev,struct perf_event * event)47 static void coresight_mali_disable_source(struct coresight_device *csdev, struct perf_event *event)
48 {
49 coresight_mali_disable_component(csdev);
50 }
51
52 static const struct coresight_ops_source coresight_mali_source_ops = {
53 .trace_id = coresight_mali_source_trace_id,
54 .enable = coresight_mali_enable_source,
55 .disable = coresight_mali_disable_source
56 };
57
58 static const struct coresight_ops mali_cs_ops = {
59 .source_ops = &coresight_mali_source_ops,
60 };
61
coresight_mali_sources_probe(struct platform_device * pdev)62 int coresight_mali_sources_probe(struct platform_device *pdev)
63 {
64 int ret = 0;
65 struct coresight_platform_data *pdata = NULL;
66 struct coresight_mali_source_drvdata *drvdata = NULL;
67 struct coresight_desc desc = { 0 };
68 struct device *dev = &pdev->dev;
69 struct device_node *np = dev->of_node;
70 struct platform_device *gpu_pdev = NULL;
71 struct device_node *gpu_node = NULL;
72
73 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
74 if (!drvdata)
75 return -ENOMEM;
76
77 dev_set_drvdata(dev, drvdata);
78 drvdata->base.dev = dev;
79
80 #if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
81 pdata = coresight_get_platform_data(dev);
82 #else
83 if (np)
84 pdata = of_get_coresight_platform_data(dev, np);
85 #endif
86 if (IS_ERR(pdata)) {
87 dev_err(drvdata->base.dev, "Failed to get platform data\n");
88 ret = PTR_ERR(pdata);
89 goto devm_kfree_drvdata;
90 }
91
92 dev->platform_data = pdata;
93
94 gpu_node = of_parse_phandle(np, "gpu", 0);
95 if (!gpu_node) {
96 dev_err(drvdata->base.dev, "GPU node not available\n");
97 goto devm_kfree_drvdata;
98 }
99 gpu_pdev = of_find_device_by_node(gpu_node);
100 if (gpu_pdev == NULL) {
101 dev_err(drvdata->base.dev, "Couldn't find GPU device from node\n");
102 goto devm_kfree_drvdata;
103 }
104
105 drvdata->base.gpu_dev = platform_get_drvdata(gpu_pdev);
106 if (!drvdata->base.gpu_dev) {
107 dev_err(drvdata->base.dev, "GPU dev not available\n");
108 goto devm_kfree_drvdata;
109 }
110
111 ret = coresight_mali_sources_init_drvdata(drvdata);
112 if (ret) {
113 dev_err(drvdata->base.dev, "Failed to init source driver data\n");
114 goto kbase_client_unregister;
115 }
116
117 desc.type = CORESIGHT_DEV_TYPE_SOURCE;
118 desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
119 desc.ops = &mali_cs_ops;
120 desc.pdata = pdata;
121 desc.dev = dev;
122 desc.groups = coresight_mali_source_groups_get();
123
124 #if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
125 desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", drvdata->type_name);
126 if (!desc.name) {
127 ret = -ENOMEM;
128 goto devm_kfree_drvdata;
129 }
130 #endif
131 drvdata->base.csdev = coresight_register(&desc);
132 if (IS_ERR(drvdata->base.csdev)) {
133 dev_err(drvdata->base.dev, "Failed to register coresight device\n");
134 ret = PTR_ERR(drvdata->base.csdev);
135 goto devm_kfree_drvdata;
136 }
137
138 return ret;
139
140 kbase_client_unregister:
141 if (drvdata->base.csdev != NULL)
142 coresight_unregister(drvdata->base.csdev);
143
144 coresight_mali_sources_deinit_drvdata(drvdata);
145
146 devm_kfree_drvdata:
147 devm_kfree(dev, drvdata);
148
149 return ret;
150 }
151
coresight_mali_sources_remove(struct platform_device * pdev)152 int coresight_mali_sources_remove(struct platform_device *pdev)
153 {
154 struct coresight_mali_source_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
155
156 if (drvdata->base.csdev != NULL)
157 coresight_unregister(drvdata->base.csdev);
158
159 coresight_mali_sources_deinit_drvdata(drvdata);
160
161 devm_kfree(&pdev->dev, drvdata);
162
163 return 0;
164 }
165
166 MODULE_AUTHOR("ARM Ltd.");
167 MODULE_DESCRIPTION("Arm Coresight Mali source");
168 MODULE_LICENSE("GPL");
169