]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/platform/x86/intel_telemetry_core.c
Merge branch 'for-4.8/hid-led' into for-linus
[mirror_ubuntu-zesty-kernel.git] / drivers / platform / x86 / intel_telemetry_core.c
1 /*
2 * Intel SoC Core Telemetry Driver
3 * Copyright (C) 2015, Intel Corporation.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * Telemetry Framework provides platform related PM and performance statistics.
16 * This file provides the core telemetry API implementation.
17 */
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/device.h>
21
22 #include <asm/intel_telemetry.h>
23
24 #define DRIVER_NAME "intel_telemetry_core"
25
26 struct telemetry_core_config {
27 struct telemetry_plt_config *plt_config;
28 const struct telemetry_core_ops *telem_ops;
29 };
30
31 static struct telemetry_core_config telm_core_conf;
32
33 static int telemetry_def_update_events(struct telemetry_evtconfig pss_evtconfig,
34 struct telemetry_evtconfig ioss_evtconfig)
35 {
36 return 0;
37 }
38
39 static int telemetry_def_set_sampling_period(u8 pss_period, u8 ioss_period)
40 {
41 return 0;
42 }
43
44 static int telemetry_def_get_sampling_period(u8 *pss_min_period,
45 u8 *pss_max_period,
46 u8 *ioss_min_period,
47 u8 *ioss_max_period)
48 {
49 return 0;
50 }
51
52 static int telemetry_def_get_eventconfig(
53 struct telemetry_evtconfig *pss_evtconfig,
54 struct telemetry_evtconfig *ioss_evtconfig,
55 int pss_len, int ioss_len)
56 {
57 return 0;
58 }
59
60 static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,
61 u32 *verbosity)
62 {
63 return 0;
64 }
65
66
67 static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,
68 u32 verbosity)
69 {
70 return 0;
71 }
72
73 static int telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,
74 struct telemetry_evtlog *evtlog,
75 int len, int log_all_evts)
76 {
77 return 0;
78 }
79
80 static int telemetry_def_read_eventlog(enum telemetry_unit telem_unit,
81 struct telemetry_evtlog *evtlog,
82 int len, int log_all_evts)
83 {
84 return 0;
85 }
86
87 static int telemetry_def_add_events(u8 num_pss_evts, u8 num_ioss_evts,
88 u32 *pss_evtmap, u32 *ioss_evtmap)
89 {
90 return 0;
91 }
92
93 static int telemetry_def_reset_events(void)
94 {
95 return 0;
96 }
97
98 static const struct telemetry_core_ops telm_defpltops = {
99 .set_sampling_period = telemetry_def_set_sampling_period,
100 .get_sampling_period = telemetry_def_get_sampling_period,
101 .get_trace_verbosity = telemetry_def_get_trace_verbosity,
102 .set_trace_verbosity = telemetry_def_set_trace_verbosity,
103 .raw_read_eventlog = telemetry_def_raw_read_eventlog,
104 .get_eventconfig = telemetry_def_get_eventconfig,
105 .read_eventlog = telemetry_def_read_eventlog,
106 .update_events = telemetry_def_update_events,
107 .reset_events = telemetry_def_reset_events,
108 .add_events = telemetry_def_add_events,
109 };
110
111 /**
112 * telemetry_update_events() - Update telemetry Configuration
113 * @pss_evtconfig: PSS related config. No change if num_evts = 0.
114 * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
115 *
116 * This API updates the IOSS & PSS Telemetry configuration. Old config
117 * is overwritten. Call telemetry_reset_events when logging is over
118 * All sample period values should be in the form of:
119 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
120 *
121 * Return: 0 success, < 0 for failure
122 */
123 int telemetry_update_events(struct telemetry_evtconfig pss_evtconfig,
124 struct telemetry_evtconfig ioss_evtconfig)
125 {
126 return telm_core_conf.telem_ops->update_events(pss_evtconfig,
127 ioss_evtconfig);
128 }
129 EXPORT_SYMBOL_GPL(telemetry_update_events);
130
131
132 /**
133 * telemetry_set_sampling_period() - Sets the IOSS & PSS sampling period
134 * @pss_period: placeholder for PSS Period to be set.
135 * Set to 0 if not required to be updated
136 * @ioss_period: placeholder for IOSS Period to be set
137 * Set to 0 if not required to be updated
138 *
139 * All values should be in the form of:
140 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
141 *
142 * Return: 0 success, < 0 for failure
143 */
144 int telemetry_set_sampling_period(u8 pss_period, u8 ioss_period)
145 {
146 return telm_core_conf.telem_ops->set_sampling_period(pss_period,
147 ioss_period);
148 }
149 EXPORT_SYMBOL_GPL(telemetry_set_sampling_period);
150
151 /**
152 * telemetry_get_sampling_period() - Get IOSS & PSS min & max sampling period
153 * @pss_min_period: placeholder for PSS Min Period supported
154 * @pss_max_period: placeholder for PSS Max Period supported
155 * @ioss_min_period: placeholder for IOSS Min Period supported
156 * @ioss_max_period: placeholder for IOSS Max Period supported
157 *
158 * All values should be in the form of:
159 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
160 *
161 * Return: 0 success, < 0 for failure
162 */
163 int telemetry_get_sampling_period(u8 *pss_min_period, u8 *pss_max_period,
164 u8 *ioss_min_period, u8 *ioss_max_period)
165 {
166 return telm_core_conf.telem_ops->get_sampling_period(pss_min_period,
167 pss_max_period,
168 ioss_min_period,
169 ioss_max_period);
170 }
171 EXPORT_SYMBOL_GPL(telemetry_get_sampling_period);
172
173
174 /**
175 * telemetry_reset_events() - Restore the IOSS & PSS configuration to default
176 *
177 * Return: 0 success, < 0 for failure
178 */
179 int telemetry_reset_events(void)
180 {
181 return telm_core_conf.telem_ops->reset_events();
182 }
183 EXPORT_SYMBOL_GPL(telemetry_reset_events);
184
185 /**
186 * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
187 * @pss_evtconfig: Pointer to PSS related configuration.
188 * @pss_evtconfig: Pointer to IOSS related configuration.
189 * @pss_len: Number of u32 elements allocated for pss_evtconfig array
190 * @ioss_len: Number of u32 elements allocated for ioss_evtconfig array
191 *
192 * Return: 0 success, < 0 for failure
193 */
194 int telemetry_get_eventconfig(struct telemetry_evtconfig *pss_evtconfig,
195 struct telemetry_evtconfig *ioss_evtconfig,
196 int pss_len, int ioss_len)
197 {
198 return telm_core_conf.telem_ops->get_eventconfig(pss_evtconfig,
199 ioss_evtconfig,
200 pss_len, ioss_len);
201 }
202 EXPORT_SYMBOL_GPL(telemetry_get_eventconfig);
203
204 /**
205 * telemetry_add_events() - Add IOSS & PSS configuration to existing settings.
206 * @num_pss_evts: Number of PSS Events (<29) in pss_evtmap. Can be 0.
207 * @num_ioss_evts: Number of IOSS Events (<29) in ioss_evtmap. Can be 0.
208 * @pss_evtmap: Array of PSS Event-IDs to Enable
209 * @ioss_evtmap: Array of PSS Event-IDs to Enable
210 *
211 * Events are appended to Old Configuration. In case of total events > 28, it
212 * returns error. Call telemetry_reset_events to reset after eventlog done
213 *
214 * Return: 0 success, < 0 for failure
215 */
216 int telemetry_add_events(u8 num_pss_evts, u8 num_ioss_evts,
217 u32 *pss_evtmap, u32 *ioss_evtmap)
218 {
219 return telm_core_conf.telem_ops->add_events(num_pss_evts,
220 num_ioss_evts, pss_evtmap,
221 ioss_evtmap);
222 }
223 EXPORT_SYMBOL_GPL(telemetry_add_events);
224
225 /**
226 * telemetry_read_events() - Fetches samples as specified by evtlog.telem_evt_id
227 * @telem_unit: Specify whether IOSS or PSS Read
228 * @evtlog: Array of telemetry_evtlog structs to fill data
229 * evtlog.telem_evt_id specifies the ids to read
230 * @len: Length of array of evtlog
231 *
232 * Return: number of eventlogs read for success, < 0 for failure
233 */
234 int telemetry_read_events(enum telemetry_unit telem_unit,
235 struct telemetry_evtlog *evtlog, int len)
236 {
237 return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
238 len, 0);
239 }
240 EXPORT_SYMBOL_GPL(telemetry_read_events);
241
242 /**
243 * telemetry_raw_read_events() - Fetch samples specified by evtlog.telem_evt_id
244 * @telem_unit: Specify whether IOSS or PSS Read
245 * @evtlog: Array of telemetry_evtlog structs to fill data
246 * evtlog.telem_evt_id specifies the ids to read
247 * @len: Length of array of evtlog
248 *
249 * The caller must take care of locking in this case.
250 *
251 * Return: number of eventlogs read for success, < 0 for failure
252 */
253 int telemetry_raw_read_events(enum telemetry_unit telem_unit,
254 struct telemetry_evtlog *evtlog, int len)
255 {
256 return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
257 len, 0);
258 }
259 EXPORT_SYMBOL_GPL(telemetry_raw_read_events);
260
261 /**
262 * telemetry_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
263 * @telem_unit: Specify whether IOSS or PSS Read
264 * @evtlog: Array of telemetry_evtlog structs to fill data
265 * @len: Length of array of evtlog
266 *
267 * Return: number of eventlogs read for success, < 0 for failure
268 */
269 int telemetry_read_eventlog(enum telemetry_unit telem_unit,
270 struct telemetry_evtlog *evtlog, int len)
271 {
272 return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
273 len, 1);
274 }
275 EXPORT_SYMBOL_GPL(telemetry_read_eventlog);
276
277 /**
278 * telemetry_raw_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
279 * @telem_unit: Specify whether IOSS or PSS Read
280 * @evtlog: Array of telemetry_evtlog structs to fill data
281 * @len: Length of array of evtlog
282 *
283 * The caller must take care of locking in this case.
284 *
285 * Return: number of eventlogs read for success, < 0 for failure
286 */
287 int telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,
288 struct telemetry_evtlog *evtlog, int len)
289 {
290 return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
291 len, 1);
292 }
293 EXPORT_SYMBOL_GPL(telemetry_raw_read_eventlog);
294
295
296 /**
297 * telemetry_get_trace_verbosity() - Get the IOSS & PSS Trace verbosity
298 * @telem_unit: Specify whether IOSS or PSS Read
299 * @verbosity: Pointer to return Verbosity
300 *
301 * Return: 0 success, < 0 for failure
302 */
303 int telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,
304 u32 *verbosity)
305 {
306 return telm_core_conf.telem_ops->get_trace_verbosity(telem_unit,
307 verbosity);
308 }
309 EXPORT_SYMBOL_GPL(telemetry_get_trace_verbosity);
310
311
312 /**
313 * telemetry_set_trace_verbosity() - Update the IOSS & PSS Trace verbosity
314 * @telem_unit: Specify whether IOSS or PSS Read
315 * @verbosity: Verbosity to set
316 *
317 * Return: 0 success, < 0 for failure
318 */
319 int telemetry_set_trace_verbosity(enum telemetry_unit telem_unit, u32 verbosity)
320 {
321 return telm_core_conf.telem_ops->set_trace_verbosity(telem_unit,
322 verbosity);
323 }
324 EXPORT_SYMBOL_GPL(telemetry_set_trace_verbosity);
325
326 /**
327 * telemetry_set_pltdata() - Set the platform specific Data
328 * @ops: Pointer to ops structure
329 * @pltconfig: Platform config data
330 *
331 * Usage by other than telemetry pltdrv module is invalid
332 *
333 * Return: 0 success, < 0 for failure
334 */
335 int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
336 struct telemetry_plt_config *pltconfig)
337 {
338 if (ops)
339 telm_core_conf.telem_ops = ops;
340
341 if (pltconfig)
342 telm_core_conf.plt_config = pltconfig;
343
344 return 0;
345 }
346 EXPORT_SYMBOL_GPL(telemetry_set_pltdata);
347
348 /**
349 * telemetry_clear_pltdata() - Clear the platform specific Data
350 *
351 * Usage by other than telemetry pltdrv module is invalid
352 *
353 * Return: 0 success, < 0 for failure
354 */
355 int telemetry_clear_pltdata(void)
356 {
357 telm_core_conf.telem_ops = &telm_defpltops;
358 telm_core_conf.plt_config = NULL;
359
360 return 0;
361 }
362 EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);
363
364 /**
365 * telemetry_pltconfig_valid() - Checkif platform config is valid
366 *
367 * Usage by other than telemetry module is invalid
368 *
369 * Return: 0 success, < 0 for failure
370 */
371 int telemetry_pltconfig_valid(void)
372 {
373 if (telm_core_conf.plt_config)
374 return 0;
375
376 else
377 return -EINVAL;
378 }
379 EXPORT_SYMBOL_GPL(telemetry_pltconfig_valid);
380
381 static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,
382 const char **name, int len)
383 {
384 struct telemetry_unit_config psscfg;
385 int i;
386
387 if (!telm_core_conf.plt_config)
388 return -EINVAL;
389
390 psscfg = telm_core_conf.plt_config->pss_config;
391
392 if (len > psscfg.ssram_evts_used)
393 len = psscfg.ssram_evts_used;
394
395 for (i = 0; i < len; i++)
396 name[i] = psscfg.telem_evts[i].name;
397
398 return 0;
399 }
400
401 static inline int telemetry_get_iossevtname(enum telemetry_unit telem_unit,
402 const char **name, int len)
403 {
404 struct telemetry_unit_config iosscfg;
405 int i;
406
407 if (!(telm_core_conf.plt_config))
408 return -EINVAL;
409
410 iosscfg = telm_core_conf.plt_config->ioss_config;
411
412 if (len > iosscfg.ssram_evts_used)
413 len = iosscfg.ssram_evts_used;
414
415 for (i = 0; i < len; i++)
416 name[i] = iosscfg.telem_evts[i].name;
417
418 return 0;
419
420 }
421
422 /**
423 * telemetry_get_evtname() - Checkif platform config is valid
424 * @telem_unit: Telemetry Unit to check
425 * @name: Array of character pointers to contain name
426 * @len: length of array name provided by user
427 *
428 * Usage by other than telemetry debugfs module is invalid
429 *
430 * Return: 0 success, < 0 for failure
431 */
432 int telemetry_get_evtname(enum telemetry_unit telem_unit,
433 const char **name, int len)
434 {
435 int ret = -EINVAL;
436
437 if (telem_unit == TELEM_PSS)
438 ret = telemetry_get_pssevtname(telem_unit, name, len);
439
440 else if (telem_unit == TELEM_IOSS)
441 ret = telemetry_get_iossevtname(telem_unit, name, len);
442
443 return ret;
444 }
445 EXPORT_SYMBOL_GPL(telemetry_get_evtname);
446
447 static int __init telemetry_module_init(void)
448 {
449 pr_info(pr_fmt(DRIVER_NAME) " Init\n");
450
451 telm_core_conf.telem_ops = &telm_defpltops;
452 return 0;
453 }
454
455 static void __exit telemetry_module_exit(void)
456 {
457 }
458
459 module_init(telemetry_module_init);
460 module_exit(telemetry_module_exit);
461
462 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
463 MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
464 MODULE_LICENSE("GPL");