core.c (12937B)
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 17struct telemetry_core_config { 18 struct telemetry_plt_config *plt_config; 19 const struct telemetry_core_ops *telem_ops; 20}; 21 22static struct telemetry_core_config telm_core_conf; 23 24static int telemetry_def_update_events(struct telemetry_evtconfig pss_evtconfig, 25 struct telemetry_evtconfig ioss_evtconfig) 26{ 27 return 0; 28} 29 30static int telemetry_def_set_sampling_period(u8 pss_period, u8 ioss_period) 31{ 32 return 0; 33} 34 35static 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 43static 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 51static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit, 52 u32 *verbosity) 53{ 54 return 0; 55} 56 57 58static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit, 59 u32 verbosity) 60{ 61 return 0; 62} 63 64static 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 71static 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 78static 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 84static int telemetry_def_reset_events(void) 85{ 86 return 0; 87} 88 89static 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 */ 114int 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} 120EXPORT_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 */ 135int 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} 140EXPORT_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 */ 154int 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} 162EXPORT_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 */ 170int telemetry_reset_events(void) 171{ 172 return telm_core_conf.telem_ops->reset_events(); 173} 174EXPORT_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 */ 185int 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} 193EXPORT_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 */ 207int 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} 214EXPORT_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 */ 225int 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} 231EXPORT_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 */ 244int 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} 250EXPORT_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 */ 260int 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} 266EXPORT_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 */ 278int 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} 284EXPORT_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 */ 294int 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} 300EXPORT_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 */ 310int 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} 315EXPORT_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 */ 326int 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} 337EXPORT_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 */ 346int 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} 353EXPORT_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 */ 361struct telemetry_plt_config *telemetry_get_pltdata(void) 362{ 363 return telm_core_conf.plt_config; 364} 365EXPORT_SYMBOL_GPL(telemetry_get_pltdata); 366 367static 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 387static 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 */ 418int 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} 431EXPORT_SYMBOL_GPL(telemetry_get_evtname); 432 433static 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 441static void __exit telemetry_module_exit(void) 442{ 443} 444 445module_init(telemetry_module_init); 446module_exit(telemetry_module_exit); 447 448MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>"); 449MODULE_DESCRIPTION("Intel SoC Telemetry Interface"); 450MODULE_LICENSE("GPL v2");