Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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