1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Intel SoC Core Telemetry Driver
4 * Copyright (C) 2015, Intel Corporation.
5 * All Rights Reserved.
6 *
7 * Telemetry Framework provides platform related PM and performance statistics.
8 * This file provides the core telemetry API implementation.
9 */
10 #include <linux/device.h>
11 #include <linux/module.h>
12
13 #include <asm/intel_telemetry.h>
14
15 #define DRIVER_NAME "intel_telemetry_core"
16
17 struct telemetry_core_config {
18 struct telemetry_plt_config *plt_config;
19 const struct telemetry_core_ops *telem_ops;
20 };
21
22 static struct telemetry_core_config telm_core_conf;
23
telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,u32 * verbosity)24 static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,
25 u32 *verbosity)
26 {
27 return 0;
28 }
29
30
telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,u32 verbosity)31 static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,
32 u32 verbosity)
33 {
34 return 0;
35 }
36
telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,struct telemetry_evtlog * evtlog,int len,int log_all_evts)37 static int telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,
38 struct telemetry_evtlog *evtlog,
39 int len, int log_all_evts)
40 {
41 return 0;
42 }
43
telemetry_def_read_eventlog(enum telemetry_unit telem_unit,struct telemetry_evtlog * evtlog,int len,int log_all_evts)44 static int telemetry_def_read_eventlog(enum telemetry_unit telem_unit,
45 struct telemetry_evtlog *evtlog,
46 int len, int log_all_evts)
47 {
48 return 0;
49 }
50
51 static const struct telemetry_core_ops telm_defpltops = {
52 .get_trace_verbosity = telemetry_def_get_trace_verbosity,
53 .set_trace_verbosity = telemetry_def_set_trace_verbosity,
54 .raw_read_eventlog = telemetry_def_raw_read_eventlog,
55 .read_eventlog = telemetry_def_read_eventlog,
56 };
57
58 /**
59 * telemetry_read_events() - Fetches samples as specified by evtlog.telem_evt_id
60 * @telem_unit: Specify whether IOSS or PSS Read
61 * @evtlog: Array of telemetry_evtlog structs to fill data
62 * evtlog.telem_evt_id specifies the ids to read
63 * @len: Length of array of evtlog
64 *
65 * Return: number of eventlogs read for success, < 0 for failure
66 */
telemetry_read_events(enum telemetry_unit telem_unit,struct telemetry_evtlog * evtlog,int len)67 int telemetry_read_events(enum telemetry_unit telem_unit,
68 struct telemetry_evtlog *evtlog, int len)
69 {
70 return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
71 len, 0);
72 }
73 EXPORT_SYMBOL_GPL(telemetry_read_events);
74
75 /**
76 * telemetry_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
77 * @telem_unit: Specify whether IOSS or PSS Read
78 * @evtlog: Array of telemetry_evtlog structs to fill data
79 * @len: Length of array of evtlog
80 *
81 * Return: number of eventlogs read for success, < 0 for failure
82 */
telemetry_read_eventlog(enum telemetry_unit telem_unit,struct telemetry_evtlog * evtlog,int len)83 int telemetry_read_eventlog(enum telemetry_unit telem_unit,
84 struct telemetry_evtlog *evtlog, int len)
85 {
86 return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
87 len, 1);
88 }
89 EXPORT_SYMBOL_GPL(telemetry_read_eventlog);
90
91 /**
92 * telemetry_raw_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
93 * @telem_unit: Specify whether IOSS or PSS Read
94 * @evtlog: Array of telemetry_evtlog structs to fill data
95 * @len: Length of array of evtlog
96 *
97 * The caller must take care of locking in this case.
98 *
99 * Return: number of eventlogs read for success, < 0 for failure
100 */
telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,struct telemetry_evtlog * evtlog,int len)101 int telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,
102 struct telemetry_evtlog *evtlog, int len)
103 {
104 return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
105 len, 1);
106 }
107 EXPORT_SYMBOL_GPL(telemetry_raw_read_eventlog);
108
109
110 /**
111 * telemetry_get_trace_verbosity() - Get the IOSS & PSS Trace verbosity
112 * @telem_unit: Specify whether IOSS or PSS Read
113 * @verbosity: Pointer to return Verbosity
114 *
115 * Return: 0 success, < 0 for failure
116 */
telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,u32 * verbosity)117 int telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,
118 u32 *verbosity)
119 {
120 return telm_core_conf.telem_ops->get_trace_verbosity(telem_unit,
121 verbosity);
122 }
123 EXPORT_SYMBOL_GPL(telemetry_get_trace_verbosity);
124
125
126 /**
127 * telemetry_set_trace_verbosity() - Update the IOSS & PSS Trace verbosity
128 * @telem_unit: Specify whether IOSS or PSS Read
129 * @verbosity: Verbosity to set
130 *
131 * Return: 0 success, < 0 for failure
132 */
telemetry_set_trace_verbosity(enum telemetry_unit telem_unit,u32 verbosity)133 int telemetry_set_trace_verbosity(enum telemetry_unit telem_unit, u32 verbosity)
134 {
135 return telm_core_conf.telem_ops->set_trace_verbosity(telem_unit,
136 verbosity);
137 }
138 EXPORT_SYMBOL_GPL(telemetry_set_trace_verbosity);
139
140 /**
141 * telemetry_set_pltdata() - Set the platform specific Data
142 * @ops: Pointer to ops structure
143 * @pltconfig: Platform config data
144 *
145 * Usage by other than telemetry pltdrv module is invalid
146 *
147 * Return: 0 success, < 0 for failure
148 */
telemetry_set_pltdata(const struct telemetry_core_ops * ops,struct telemetry_plt_config * pltconfig)149 int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
150 struct telemetry_plt_config *pltconfig)
151 {
152 if (ops)
153 telm_core_conf.telem_ops = ops;
154
155 if (pltconfig)
156 telm_core_conf.plt_config = pltconfig;
157
158 return 0;
159 }
160 EXPORT_SYMBOL_GPL(telemetry_set_pltdata);
161
162 /**
163 * telemetry_clear_pltdata() - Clear the platform specific Data
164 *
165 * Usage by other than telemetry pltdrv module is invalid
166 *
167 * Return: 0 success, < 0 for failure
168 */
telemetry_clear_pltdata(void)169 int telemetry_clear_pltdata(void)
170 {
171 telm_core_conf.telem_ops = &telm_defpltops;
172 telm_core_conf.plt_config = NULL;
173
174 return 0;
175 }
176 EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);
177
178 /**
179 * telemetry_get_pltdata() - Return telemetry platform config
180 *
181 * May be used by other telemetry modules to get platform specific
182 * configuration.
183 */
telemetry_get_pltdata(void)184 struct telemetry_plt_config *telemetry_get_pltdata(void)
185 {
186 return telm_core_conf.plt_config;
187 }
188 EXPORT_SYMBOL_GPL(telemetry_get_pltdata);
189
telemetry_get_pssevtname(enum telemetry_unit telem_unit,const char ** name,int len)190 static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,
191 const char **name, int len)
192 {
193 struct telemetry_unit_config psscfg;
194 int i;
195
196 if (!telm_core_conf.plt_config)
197 return -EINVAL;
198
199 psscfg = telm_core_conf.plt_config->pss_config;
200
201 if (len > psscfg.ssram_evts_used)
202 len = psscfg.ssram_evts_used;
203
204 for (i = 0; i < len; i++)
205 name[i] = psscfg.telem_evts[i].name;
206
207 return 0;
208 }
209
telemetry_get_iossevtname(enum telemetry_unit telem_unit,const char ** name,int len)210 static inline int telemetry_get_iossevtname(enum telemetry_unit telem_unit,
211 const char **name, int len)
212 {
213 struct telemetry_unit_config iosscfg;
214 int i;
215
216 if (!(telm_core_conf.plt_config))
217 return -EINVAL;
218
219 iosscfg = telm_core_conf.plt_config->ioss_config;
220
221 if (len > iosscfg.ssram_evts_used)
222 len = iosscfg.ssram_evts_used;
223
224 for (i = 0; i < len; i++)
225 name[i] = iosscfg.telem_evts[i].name;
226
227 return 0;
228
229 }
230
231 /**
232 * telemetry_get_evtname() - Checkif platform config is valid
233 * @telem_unit: Telemetry Unit to check
234 * @name: Array of character pointers to contain name
235 * @len: length of array name provided by user
236 *
237 * Usage by other than telemetry debugfs module is invalid
238 *
239 * Return: 0 success, < 0 for failure
240 */
telemetry_get_evtname(enum telemetry_unit telem_unit,const char ** name,int len)241 int telemetry_get_evtname(enum telemetry_unit telem_unit,
242 const char **name, int len)
243 {
244 int ret = -EINVAL;
245
246 if (telem_unit == TELEM_PSS)
247 ret = telemetry_get_pssevtname(telem_unit, name, len);
248
249 else if (telem_unit == TELEM_IOSS)
250 ret = telemetry_get_iossevtname(telem_unit, name, len);
251
252 return ret;
253 }
254 EXPORT_SYMBOL_GPL(telemetry_get_evtname);
255
telemetry_module_init(void)256 static int __init telemetry_module_init(void)
257 {
258 pr_info(pr_fmt(DRIVER_NAME) " Init\n");
259
260 telm_core_conf.telem_ops = &telm_defpltops;
261 return 0;
262 }
263
telemetry_module_exit(void)264 static void __exit telemetry_module_exit(void)
265 {
266 }
267
268 module_init(telemetry_module_init);
269 module_exit(telemetry_module_exit);
270
271 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
272 MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
273 MODULE_LICENSE("GPL v2");
274