FILE
coresight-dummy.c
File preview with syntax highlighting.
linux-6.19.14/drivers/hwtracing/coresight/coresight-dummy.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6#include <linux/coresight.h> 7#include <linux/kernel.h> 8#include <linux/module.h> 9#include <linux/of.h> 10#include <linux/platform_device.h> 11#include <linux/pm_runtime.h> 12 13#include "coresight-priv.h" 14#include "coresight-trace-id.h" 15 16struct dummy_drvdata { 17 struct device *dev; 18 struct coresight_device *csdev; 19 u8 traceid; 20}; 21 22DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source"); 23DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink"); 24 25static int dummy_source_enable(struct coresight_device *csdev, 26 struct perf_event *event, enum cs_mode mode, 27 __maybe_unused struct coresight_path *path) 28{ 29 if (!coresight_take_mode(csdev, mode)) 30 return -EBUSY; 31 32 dev_dbg(csdev->dev.parent, "Dummy source enabled\n"); 33 34 return 0; 35} 36 37static void dummy_source_disable(struct coresight_device *csdev, 38 struct perf_event *event) 39{ 40 coresight_set_mode(csdev, CS_MODE_DISABLED); 41 dev_dbg(csdev->dev.parent, "Dummy source disabled\n"); 42} 43 44static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode, 45 __maybe_unused struct coresight_device *sink) 46{ 47 struct dummy_drvdata *drvdata; 48 49 drvdata = dev_get_drvdata(csdev->dev.parent); 50 51 return drvdata->traceid; 52} 53 54static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode, 55 struct coresight_path *path) 56{ 57 dev_dbg(csdev->dev.parent, "Dummy sink enabled\n"); 58 59 return 0; 60} 61 62static int dummy_sink_disable(struct coresight_device *csdev) 63{ 64 dev_dbg(csdev->dev.parent, "Dummy sink disabled\n"); 65 66 return 0; 67} 68 69static const struct coresight_ops_source dummy_source_ops = { 70 .enable = dummy_source_enable, 71 .disable = dummy_source_disable, 72}; 73 74static const struct coresight_ops dummy_source_cs_ops = { 75 .trace_id = dummy_source_trace_id, 76 .source_ops = &dummy_source_ops, 77}; 78 79static const struct coresight_ops_sink dummy_sink_ops = { 80 .enable = dummy_sink_enable, 81 .disable = dummy_sink_disable, 82}; 83 84static const struct coresight_ops dummy_sink_cs_ops = { 85 .sink_ops = &dummy_sink_ops, 86}; 87 88/* User can get the trace id of dummy source from this node. */ 89static ssize_t traceid_show(struct device *dev, 90 struct device_attribute *attr, char *buf) 91{ 92 unsigned long val; 93 struct dummy_drvdata *drvdata = dev_get_drvdata(dev->parent); 94 95 val = drvdata->traceid; 96 return sysfs_emit(buf, "%#lx\n", val); 97} 98static DEVICE_ATTR_RO(traceid); 99 100static struct attribute *coresight_dummy_attrs[] = { 101 &dev_attr_traceid.attr, 102 NULL, 103}; 104 105static const struct attribute_group coresight_dummy_group = { 106 .attrs = coresight_dummy_attrs, 107}; 108 109static const struct attribute_group *coresight_dummy_groups[] = { 110 &coresight_dummy_group, 111 NULL, 112}; 113 114static int dummy_probe(struct platform_device *pdev) 115{ 116 struct device *dev = &pdev->dev; 117 struct device_node *node = dev->of_node; 118 struct coresight_platform_data *pdata; 119 struct dummy_drvdata *drvdata; 120 struct coresight_desc desc = { 0 }; 121 int ret = 0, trace_id = 0; 122 123 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 124 if (!drvdata) 125 return -ENOMEM; 126 127 if (of_device_is_compatible(node, "arm,coresight-dummy-source")) { 128 129 desc.name = coresight_alloc_device_name(&source_devs, dev); 130 if (!desc.name) 131 return -ENOMEM; 132 133 desc.type = CORESIGHT_DEV_TYPE_SOURCE; 134 desc.subtype.source_subtype = 135 CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; 136 desc.ops = &dummy_source_cs_ops; 137 desc.groups = coresight_dummy_groups; 138 139 ret = coresight_get_static_trace_id(dev, &trace_id); 140 if (!ret) { 141 /* Get the static id if id is set in device tree. */ 142 ret = coresight_trace_id_get_static_system_id(trace_id); 143 if (ret < 0) { 144 dev_err(dev, "Fail to get static id.\n"); 145 return ret; 146 } 147 } else { 148 /* Get next available id if id is not set in device tree. */ 149 trace_id = coresight_trace_id_get_system_id(); 150 if (trace_id < 0) { 151 ret = trace_id; 152 return ret; 153 } 154 } 155 drvdata->traceid = (u8)trace_id; 156 157 } else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) { 158 desc.name = coresight_alloc_device_name(&sink_devs, dev); 159 if (!desc.name) 160 return -ENOMEM; 161 162 desc.type = CORESIGHT_DEV_TYPE_SINK; 163 desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_DUMMY; 164 desc.ops = &dummy_sink_cs_ops; 165 } else { 166 dev_err(dev, "Device type not set\n"); 167 return -EINVAL; 168 } 169 170 pdata = coresight_get_platform_data(dev); 171 if (IS_ERR(pdata)) { 172 ret = PTR_ERR(pdata); 173 goto free_id; 174 } 175 pdev->dev.platform_data = pdata; 176 177 drvdata->dev = &pdev->dev; 178 platform_set_drvdata(pdev, drvdata); 179 180 desc.pdata = pdev->dev.platform_data; 181 desc.dev = &pdev->dev; 182 drvdata->csdev = coresight_register(&desc); 183 if (IS_ERR(drvdata->csdev)) { 184 ret = PTR_ERR(drvdata->csdev); 185 goto free_id; 186 } 187 188 pm_runtime_enable(dev); 189 dev_dbg(dev, "Dummy device initialized\n"); 190 191 ret = 0; 192 goto out; 193 194free_id: 195 if (IS_VALID_CS_TRACE_ID(drvdata->traceid)) 196 coresight_trace_id_put_system_id(drvdata->traceid); 197 198out: 199 return ret; 200} 201 202static void dummy_remove(struct platform_device *pdev) 203{ 204 struct dummy_drvdata *drvdata = platform_get_drvdata(pdev); 205 struct device *dev = &pdev->dev; 206 207 if (IS_VALID_CS_TRACE_ID(drvdata->traceid)) 208 coresight_trace_id_put_system_id(drvdata->traceid); 209 pm_runtime_disable(dev); 210 coresight_unregister(drvdata->csdev); 211} 212 213static const struct of_device_id dummy_match[] = { 214 {.compatible = "arm,coresight-dummy-source"}, 215 {.compatible = "arm,coresight-dummy-sink"}, 216 {}, 217}; 218 219static struct platform_driver dummy_driver = { 220 .probe = dummy_probe, 221 .remove = dummy_remove, 222 .driver = { 223 .name = "coresight-dummy", 224 .of_match_table = dummy_match, 225 }, 226}; 227 228module_platform_driver(dummy_driver); 229 230MODULE_LICENSE("GPL"); 231MODULE_DESCRIPTION("CoreSight dummy driver");
~/
Read-only file preview.