xref: /linux/drivers/platform/x86/intel/telemetry/core.c (revision 9669b2499ea377764f8320dd562dd6cd4ea80a5d)
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