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