123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /*
- * Intel SoC Core Telemetry Driver
- * Copyright (C) 2015, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * Telemetry Framework provides platform related PM and performance statistics.
- * This file provides the core telemetry API implementation.
- */
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/device.h>
- #include <asm/intel_telemetry.h>
- #define DRIVER_NAME "intel_telemetry_core"
- struct telemetry_core_config {
- struct telemetry_plt_config *plt_config;
- const struct telemetry_core_ops *telem_ops;
- };
- static struct telemetry_core_config telm_core_conf;
- static int telemetry_def_update_events(struct telemetry_evtconfig pss_evtconfig,
- struct telemetry_evtconfig ioss_evtconfig)
- {
- return 0;
- }
- static int telemetry_def_set_sampling_period(u8 pss_period, u8 ioss_period)
- {
- return 0;
- }
- static int telemetry_def_get_sampling_period(u8 *pss_min_period,
- u8 *pss_max_period,
- u8 *ioss_min_period,
- u8 *ioss_max_period)
- {
- return 0;
- }
- static int telemetry_def_get_eventconfig(
- struct telemetry_evtconfig *pss_evtconfig,
- struct telemetry_evtconfig *ioss_evtconfig,
- int pss_len, int ioss_len)
- {
- return 0;
- }
- static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,
- u32 *verbosity)
- {
- return 0;
- }
- static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,
- u32 verbosity)
- {
- return 0;
- }
- static int telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog,
- int len, int log_all_evts)
- {
- return 0;
- }
- static int telemetry_def_read_eventlog(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog,
- int len, int log_all_evts)
- {
- return 0;
- }
- static int telemetry_def_add_events(u8 num_pss_evts, u8 num_ioss_evts,
- u32 *pss_evtmap, u32 *ioss_evtmap)
- {
- return 0;
- }
- static int telemetry_def_reset_events(void)
- {
- return 0;
- }
- static const struct telemetry_core_ops telm_defpltops = {
- .set_sampling_period = telemetry_def_set_sampling_period,
- .get_sampling_period = telemetry_def_get_sampling_period,
- .get_trace_verbosity = telemetry_def_get_trace_verbosity,
- .set_trace_verbosity = telemetry_def_set_trace_verbosity,
- .raw_read_eventlog = telemetry_def_raw_read_eventlog,
- .get_eventconfig = telemetry_def_get_eventconfig,
- .read_eventlog = telemetry_def_read_eventlog,
- .update_events = telemetry_def_update_events,
- .reset_events = telemetry_def_reset_events,
- .add_events = telemetry_def_add_events,
- };
- /**
- * telemetry_update_events() - Update telemetry Configuration
- * @pss_evtconfig: PSS related config. No change if num_evts = 0.
- * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
- *
- * This API updates the IOSS & PSS Telemetry configuration. Old config
- * is overwritten. Call telemetry_reset_events when logging is over
- * All sample period values should be in the form of:
- * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_update_events(struct telemetry_evtconfig pss_evtconfig,
- struct telemetry_evtconfig ioss_evtconfig)
- {
- return telm_core_conf.telem_ops->update_events(pss_evtconfig,
- ioss_evtconfig);
- }
- EXPORT_SYMBOL_GPL(telemetry_update_events);
- /**
- * telemetry_set_sampling_period() - Sets the IOSS & PSS sampling period
- * @pss_period: placeholder for PSS Period to be set.
- * Set to 0 if not required to be updated
- * @ioss_period: placeholder for IOSS Period to be set
- * Set to 0 if not required to be updated
- *
- * All values should be in the form of:
- * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_set_sampling_period(u8 pss_period, u8 ioss_period)
- {
- return telm_core_conf.telem_ops->set_sampling_period(pss_period,
- ioss_period);
- }
- EXPORT_SYMBOL_GPL(telemetry_set_sampling_period);
- /**
- * telemetry_get_sampling_period() - Get IOSS & PSS min & max sampling period
- * @pss_min_period: placeholder for PSS Min Period supported
- * @pss_max_period: placeholder for PSS Max Period supported
- * @ioss_min_period: placeholder for IOSS Min Period supported
- * @ioss_max_period: placeholder for IOSS Max Period supported
- *
- * All values should be in the form of:
- * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_get_sampling_period(u8 *pss_min_period, u8 *pss_max_period,
- u8 *ioss_min_period, u8 *ioss_max_period)
- {
- return telm_core_conf.telem_ops->get_sampling_period(pss_min_period,
- pss_max_period,
- ioss_min_period,
- ioss_max_period);
- }
- EXPORT_SYMBOL_GPL(telemetry_get_sampling_period);
- /**
- * telemetry_reset_events() - Restore the IOSS & PSS configuration to default
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_reset_events(void)
- {
- return telm_core_conf.telem_ops->reset_events();
- }
- EXPORT_SYMBOL_GPL(telemetry_reset_events);
- /**
- * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
- * @pss_evtconfig: Pointer to PSS related configuration.
- * @pss_evtconfig: Pointer to IOSS related configuration.
- * @pss_len: Number of u32 elements allocated for pss_evtconfig array
- * @ioss_len: Number of u32 elements allocated for ioss_evtconfig array
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_get_eventconfig(struct telemetry_evtconfig *pss_evtconfig,
- struct telemetry_evtconfig *ioss_evtconfig,
- int pss_len, int ioss_len)
- {
- return telm_core_conf.telem_ops->get_eventconfig(pss_evtconfig,
- ioss_evtconfig,
- pss_len, ioss_len);
- }
- EXPORT_SYMBOL_GPL(telemetry_get_eventconfig);
- /**
- * telemetry_add_events() - Add IOSS & PSS configuration to existing settings.
- * @num_pss_evts: Number of PSS Events (<29) in pss_evtmap. Can be 0.
- * @num_ioss_evts: Number of IOSS Events (<29) in ioss_evtmap. Can be 0.
- * @pss_evtmap: Array of PSS Event-IDs to Enable
- * @ioss_evtmap: Array of PSS Event-IDs to Enable
- *
- * Events are appended to Old Configuration. In case of total events > 28, it
- * returns error. Call telemetry_reset_events to reset after eventlog done
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_add_events(u8 num_pss_evts, u8 num_ioss_evts,
- u32 *pss_evtmap, u32 *ioss_evtmap)
- {
- return telm_core_conf.telem_ops->add_events(num_pss_evts,
- num_ioss_evts, pss_evtmap,
- ioss_evtmap);
- }
- EXPORT_SYMBOL_GPL(telemetry_add_events);
- /**
- * telemetry_read_events() - Fetches samples as specified by evtlog.telem_evt_id
- * @telem_unit: Specify whether IOSS or PSS Read
- * @evtlog: Array of telemetry_evtlog structs to fill data
- * evtlog.telem_evt_id specifies the ids to read
- * @len: Length of array of evtlog
- *
- * Return: number of eventlogs read for success, < 0 for failure
- */
- int telemetry_read_events(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog, int len)
- {
- return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
- len, 0);
- }
- EXPORT_SYMBOL_GPL(telemetry_read_events);
- /**
- * telemetry_raw_read_events() - Fetch samples specified by evtlog.telem_evt_id
- * @telem_unit: Specify whether IOSS or PSS Read
- * @evtlog: Array of telemetry_evtlog structs to fill data
- * evtlog.telem_evt_id specifies the ids to read
- * @len: Length of array of evtlog
- *
- * The caller must take care of locking in this case.
- *
- * Return: number of eventlogs read for success, < 0 for failure
- */
- int telemetry_raw_read_events(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog, int len)
- {
- return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
- len, 0);
- }
- EXPORT_SYMBOL_GPL(telemetry_raw_read_events);
- /**
- * telemetry_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
- * @telem_unit: Specify whether IOSS or PSS Read
- * @evtlog: Array of telemetry_evtlog structs to fill data
- * @len: Length of array of evtlog
- *
- * Return: number of eventlogs read for success, < 0 for failure
- */
- int telemetry_read_eventlog(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog, int len)
- {
- return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
- len, 1);
- }
- EXPORT_SYMBOL_GPL(telemetry_read_eventlog);
- /**
- * telemetry_raw_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
- * @telem_unit: Specify whether IOSS or PSS Read
- * @evtlog: Array of telemetry_evtlog structs to fill data
- * @len: Length of array of evtlog
- *
- * The caller must take care of locking in this case.
- *
- * Return: number of eventlogs read for success, < 0 for failure
- */
- int telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,
- struct telemetry_evtlog *evtlog, int len)
- {
- return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
- len, 1);
- }
- EXPORT_SYMBOL_GPL(telemetry_raw_read_eventlog);
- /**
- * telemetry_get_trace_verbosity() - Get the IOSS & PSS Trace verbosity
- * @telem_unit: Specify whether IOSS or PSS Read
- * @verbosity: Pointer to return Verbosity
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,
- u32 *verbosity)
- {
- return telm_core_conf.telem_ops->get_trace_verbosity(telem_unit,
- verbosity);
- }
- EXPORT_SYMBOL_GPL(telemetry_get_trace_verbosity);
- /**
- * telemetry_set_trace_verbosity() - Update the IOSS & PSS Trace verbosity
- * @telem_unit: Specify whether IOSS or PSS Read
- * @verbosity: Verbosity to set
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_set_trace_verbosity(enum telemetry_unit telem_unit, u32 verbosity)
- {
- return telm_core_conf.telem_ops->set_trace_verbosity(telem_unit,
- verbosity);
- }
- EXPORT_SYMBOL_GPL(telemetry_set_trace_verbosity);
- /**
- * telemetry_set_pltdata() - Set the platform specific Data
- * @ops: Pointer to ops structure
- * @pltconfig: Platform config data
- *
- * Usage by other than telemetry pltdrv module is invalid
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
- struct telemetry_plt_config *pltconfig)
- {
- if (ops)
- telm_core_conf.telem_ops = ops;
- if (pltconfig)
- telm_core_conf.plt_config = pltconfig;
- return 0;
- }
- EXPORT_SYMBOL_GPL(telemetry_set_pltdata);
- /**
- * telemetry_clear_pltdata() - Clear the platform specific Data
- *
- * Usage by other than telemetry pltdrv module is invalid
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_clear_pltdata(void)
- {
- telm_core_conf.telem_ops = &telm_defpltops;
- telm_core_conf.plt_config = NULL;
- return 0;
- }
- EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);
- /**
- * telemetry_pltconfig_valid() - Checkif platform config is valid
- *
- * Usage by other than telemetry module is invalid
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_pltconfig_valid(void)
- {
- if (telm_core_conf.plt_config)
- return 0;
- else
- return -EINVAL;
- }
- EXPORT_SYMBOL_GPL(telemetry_pltconfig_valid);
- static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,
- const char **name, int len)
- {
- struct telemetry_unit_config psscfg;
- int i;
- if (!telm_core_conf.plt_config)
- return -EINVAL;
- psscfg = telm_core_conf.plt_config->pss_config;
- if (len > psscfg.ssram_evts_used)
- len = psscfg.ssram_evts_used;
- for (i = 0; i < len; i++)
- name[i] = psscfg.telem_evts[i].name;
- return 0;
- }
- static inline int telemetry_get_iossevtname(enum telemetry_unit telem_unit,
- const char **name, int len)
- {
- struct telemetry_unit_config iosscfg;
- int i;
- if (!(telm_core_conf.plt_config))
- return -EINVAL;
- iosscfg = telm_core_conf.plt_config->ioss_config;
- if (len > iosscfg.ssram_evts_used)
- len = iosscfg.ssram_evts_used;
- for (i = 0; i < len; i++)
- name[i] = iosscfg.telem_evts[i].name;
- return 0;
- }
- /**
- * telemetry_get_evtname() - Checkif platform config is valid
- * @telem_unit: Telemetry Unit to check
- * @name: Array of character pointers to contain name
- * @len: length of array name provided by user
- *
- * Usage by other than telemetry debugfs module is invalid
- *
- * Return: 0 success, < 0 for failure
- */
- int telemetry_get_evtname(enum telemetry_unit telem_unit,
- const char **name, int len)
- {
- int ret = -EINVAL;
- if (telem_unit == TELEM_PSS)
- ret = telemetry_get_pssevtname(telem_unit, name, len);
- else if (telem_unit == TELEM_IOSS)
- ret = telemetry_get_iossevtname(telem_unit, name, len);
- return ret;
- }
- EXPORT_SYMBOL_GPL(telemetry_get_evtname);
- static int __init telemetry_module_init(void)
- {
- pr_info(pr_fmt(DRIVER_NAME) " Init\n");
- telm_core_conf.telem_ops = &telm_defpltops;
- return 0;
- }
- static void __exit telemetry_module_exit(void)
- {
- }
- module_init(telemetry_module_init);
- module_exit(telemetry_module_exit);
- MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
- MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
- MODULE_LICENSE("GPL");
|