xref: /OK3568_Linux_fs/kernel/drivers/hwtracing/coresight/mali/sources/coresight_mali_sources.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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