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 | |
15 | struct dummy_drvdata { |
16 | struct device *dev; |
17 | struct coresight_device *csdev; |
18 | }; |
19 | |
20 | DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source" ); |
21 | DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink" ); |
22 | |
23 | static int dummy_source_enable(struct coresight_device *csdev, |
24 | struct perf_event *event, enum cs_mode mode) |
25 | { |
26 | dev_dbg(csdev->dev.parent, "Dummy source enabled\n" ); |
27 | |
28 | return 0; |
29 | } |
30 | |
31 | static void dummy_source_disable(struct coresight_device *csdev, |
32 | struct perf_event *event) |
33 | { |
34 | dev_dbg(csdev->dev.parent, "Dummy source disabled\n" ); |
35 | } |
36 | |
37 | static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode, |
38 | void *data) |
39 | { |
40 | dev_dbg(csdev->dev.parent, "Dummy sink enabled\n" ); |
41 | |
42 | return 0; |
43 | } |
44 | |
45 | static int dummy_sink_disable(struct coresight_device *csdev) |
46 | { |
47 | dev_dbg(csdev->dev.parent, "Dummy sink disabled\n" ); |
48 | |
49 | return 0; |
50 | } |
51 | |
52 | static const struct coresight_ops_source dummy_source_ops = { |
53 | .enable = dummy_source_enable, |
54 | .disable = dummy_source_disable, |
55 | }; |
56 | |
57 | static const struct coresight_ops dummy_source_cs_ops = { |
58 | .source_ops = &dummy_source_ops, |
59 | }; |
60 | |
61 | static const struct coresight_ops_sink dummy_sink_ops = { |
62 | .enable = dummy_sink_enable, |
63 | .disable = dummy_sink_disable, |
64 | }; |
65 | |
66 | static const struct coresight_ops dummy_sink_cs_ops = { |
67 | .sink_ops = &dummy_sink_ops, |
68 | }; |
69 | |
70 | static int dummy_probe(struct platform_device *pdev) |
71 | { |
72 | struct device *dev = &pdev->dev; |
73 | struct device_node *node = dev->of_node; |
74 | struct coresight_platform_data *pdata; |
75 | struct dummy_drvdata *drvdata; |
76 | struct coresight_desc desc = { 0 }; |
77 | |
78 | if (of_device_is_compatible(device: node, "arm,coresight-dummy-source" )) { |
79 | |
80 | desc.name = coresight_alloc_device_name(devs: &source_devs, dev); |
81 | if (!desc.name) |
82 | return -ENOMEM; |
83 | |
84 | desc.type = CORESIGHT_DEV_TYPE_SOURCE; |
85 | desc.subtype.source_subtype = |
86 | CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; |
87 | desc.ops = &dummy_source_cs_ops; |
88 | } else if (of_device_is_compatible(device: node, "arm,coresight-dummy-sink" )) { |
89 | desc.name = coresight_alloc_device_name(devs: &sink_devs, dev); |
90 | if (!desc.name) |
91 | return -ENOMEM; |
92 | |
93 | desc.type = CORESIGHT_DEV_TYPE_SINK; |
94 | desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_DUMMY; |
95 | desc.ops = &dummy_sink_cs_ops; |
96 | } else { |
97 | dev_err(dev, "Device type not set\n" ); |
98 | return -EINVAL; |
99 | } |
100 | |
101 | pdata = coresight_get_platform_data(dev); |
102 | if (IS_ERR(ptr: pdata)) |
103 | return PTR_ERR(ptr: pdata); |
104 | pdev->dev.platform_data = pdata; |
105 | |
106 | drvdata = devm_kzalloc(dev, size: sizeof(*drvdata), GFP_KERNEL); |
107 | if (!drvdata) |
108 | return -ENOMEM; |
109 | |
110 | drvdata->dev = &pdev->dev; |
111 | platform_set_drvdata(pdev, data: drvdata); |
112 | |
113 | desc.pdata = pdev->dev.platform_data; |
114 | desc.dev = &pdev->dev; |
115 | drvdata->csdev = coresight_register(desc: &desc); |
116 | if (IS_ERR(ptr: drvdata->csdev)) |
117 | return PTR_ERR(ptr: drvdata->csdev); |
118 | |
119 | pm_runtime_enable(dev); |
120 | dev_dbg(dev, "Dummy device initialized\n" ); |
121 | |
122 | return 0; |
123 | } |
124 | |
125 | static void dummy_remove(struct platform_device *pdev) |
126 | { |
127 | struct dummy_drvdata *drvdata = platform_get_drvdata(pdev); |
128 | struct device *dev = &pdev->dev; |
129 | |
130 | pm_runtime_disable(dev); |
131 | coresight_unregister(csdev: drvdata->csdev); |
132 | } |
133 | |
134 | static const struct of_device_id dummy_match[] = { |
135 | {.compatible = "arm,coresight-dummy-source" }, |
136 | {.compatible = "arm,coresight-dummy-sink" }, |
137 | {}, |
138 | }; |
139 | |
140 | static struct platform_driver dummy_driver = { |
141 | .probe = dummy_probe, |
142 | .remove_new = dummy_remove, |
143 | .driver = { |
144 | .name = "coresight-dummy" , |
145 | .of_match_table = dummy_match, |
146 | }, |
147 | }; |
148 | |
149 | module_platform_driver(dummy_driver); |
150 | |
151 | MODULE_LICENSE("GPL" ); |
152 | MODULE_DESCRIPTION("CoreSight dummy driver" ); |
153 | |