1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #ifndef MOD_STATISTICS_H 9 #define MOD_STATISTICS_H 10 11 #include <fwk_attributes.h> 12 #include <fwk_id.h> 13 #include <fwk_macros.h> 14 #include <fwk_module_idx.h> 15 16 #include <stdint.h> 17 18 /*! 19 * \ingroup GroupModules 20 * \defgroup GroupStatistics Statistics for Performance and Power domains 21 * of operating level changes 22 * \{ 23 */ 24 25 /*! 26 * \defgroup GroupStatisticsTypes Types 27 * \{ 28 */ 29 30 /*! 31 * \brief Statistics memory region information. 32 */ 33 struct FWK_PACKED mod_stats_config_info { 34 /*! AP physical address where statistics are located */ 35 uint64_t ap_stats_addr; 36 37 /*! SCP physical address where statistics are located */ 38 uintptr_t scp_stats_addr; 39 40 /*! Size in bytes of the shared memory region for statistics */ 41 uint32_t stats_region_size; 42 43 /*! Alarm used for period updates */ 44 fwk_id_t alarm_id; 45 }; 46 47 /*! 48 * \brief Domain statistics mapping structure. 49 */ 50 struct mod_stats_map { 51 /*! Array which contains values with levels that each domain has. 52 * We do not rely on domain_section->level_count in SCP address or 53 * offset calculation, since it can be modified by OSPM */ 54 int *se_level_count; 55 56 /*! Array which contains values with current level for each domain. 57 * We do not rely on domain_section->curr_level in SCP address or 58 * offset calculation, since it can be modified by OSPM */ 59 uint32_t *se_curr_level; 60 61 /*! An array of pointers to the domain statistics table. Every domain 62 * has its own table when statistics collection is set for it. */ 63 struct mod_stats_domain_stats_data *se_stats[]; 64 }; 65 66 /*! 67 * \brief Domain statistics management structure. 68 */ 69 struct mod_stats_context { 70 /*! Number of all stats entities of this type in the system (e.g. power 71 * domains, performance domains, etc) */ 72 int se_total_num; 73 74 /*! Number of stats entities of this type for which the statistics are 75 * collected */ 76 int se_used_num; 77 78 /*! Index used for mapping incremented after adding a new domain. */ 79 int last_stats_id; 80 81 /*! Array to map system entity id to index used in statistics memory 82 * allocator. It's needed because statistics are not enabled for all 83 * entities */ 84 int *se_index_map; 85 86 /*! Pointer to performance or power domain statistics mapping. Every 87 * domain has its own table when statistics collection is set for it. */ 88 struct mod_stats_map *se_stats_map; 89 }; 90 91 /*! 92 * \brief Statistics status and mode enum. 93 */ 94 enum mod_stats_mode { 95 STATS_NOT_INITIALIZED, /*!< Module not initialized */ 96 STATS_SETUP, /*!< Module in setup phase, not ready to use */ 97 STATS_INITIALIZED, /*!< Module ready to use */ 98 STATS_NOT_SUPPORTED, /*!< Statistics are not supported */ 99 STATS_INTERNAL_ERROR, /*!< Module reached an error */ 100 STATS_STOPPED, /*!< Statistics tracking stopped */ 101 }; 102 103 /*! 104 * \brief Statistics context. 105 */ 106 struct mod_stats_info { 107 /*! type_signature - private copy which should be the same as in shared 108 * memory description header describing type of statistics region. */ 109 uint32_t type_signature; 110 111 /*! Pointer to the shared memory header location */ 112 struct mod_stats_desc_header *desc_header; 113 114 /*! Size of the shared memory header */ 115 unsigned int desc_header_size; 116 117 /*! Size of unused shared memory region provided by the platform, which 118 * might be evaluated and adjusted to actual need */ 119 unsigned int used_mem_size; 120 121 /*! Offset inside the shared memory region to the header */ 122 uintptr_t desc_header_offset; 123 124 /*! Pointer to the structure maintaining internal data, allocations 125 * and sections of the entity (power domain, performance domain) 126 * statistics */ 127 struct mod_stats_context *context; 128 129 /*! Mode of operation for the statistics module */ 130 enum mod_stats_mode mode; 131 }; 132 133 /*! 134 * \brief Performance or power statistics memory region as defined in SCMIv2 135 * specification 136 */ 137 struct mod_stats_desc_header { 138 /*! Signature - 0x50455246 (‘PERF’) or 0x504F5752 ('POWR'). */ 139 uint32_t signature; 140 141 /*! The revision value aligned with the SCMI specification. */ 142 uint16_t revision; 143 144 /*! The attributes aligned with the SCMI specification. */ 145 uint16_t attributes; 146 147 /*! Total number of all performance or power domains in the system, which 148 * also corresponds to the size of 'domain_offset' array size. */ 149 uint16_t domain_count; 150 151 /*! Empty space just for memory alignment as per SCMI specification. */ 152 uint16_t reserved[3]; 153 154 /*! For each domain this array provides 4B offset from start addr of the 155 * statistics memory region to the particular performance or power domain 156 * statistics data section. If the value is 0 then statistics are not 157 * collected for this domain. */ 158 uint32_t domain_offset[]; 159 }; 160 161 /*! 162 * \brief Performance or power level statistics data 163 * 164 * \note In case of power domain. Here the reference to level means power state 165 */ 166 struct FWK_PACKED mod_stats_level_stats { 167 /*! The performance or power level ID. */ 168 uint32_t level_id; 169 170 /*! Reserved field as per SCMI specification. */ 171 uint32_t reserved; 172 173 /*! Maintains the number of how many time this level has been used. */ 174 uint64_t usage_count; 175 176 /*! Cumulative time of how long this level has been used. Value is in 177 * microseconds. */ 178 uint64_t total_residency_us; 179 }; 180 181 /*! 182 * \brief Performance or power domain statistics data 183 */ 184 struct FWK_PACKED mod_stats_domain_stats_data { 185 /*! Holds value of total number of performance or power levels available 186 * in the domain. */ 187 uint16_t level_count; 188 189 /*! Holds current Operating Performance Point or power level ID. */ 190 uint16_t curr_level_id; 191 192 /*! An offset to the extended statistics area if they are present. */ 193 uint32_t extended_stats_offset; 194 195 /*! Holds time stamp when the last performance or power level has been 196 * changed. Value is in microseconds.*/ 197 uint64_t ts_last_change_us; 198 199 /*! Beginning of the statistics region with information for each 200 * performance or power level. */ 201 struct mod_stats_level_stats level[]; 202 }; 203 204 /*! 205 * \} 206 */ 207 208 209 /*! 210 * \defgroup GroupStatsApis APIs 211 * \{ 212 */ 213 214 /*! 215 * \brief Stats API. 216 */ 217 struct mod_stats_api { 218 /*! 219 * \brief Initialize statistics for a given module. 220 * 221 * \param module_id Element identifier of the module. 222 * \param domain_count Total number of domains in this module. 223 * \param used_domains Total number of domains that have statistics. 224 */ 225 int (*init_stats)( 226 fwk_id_t module_id, 227 int domain_count, 228 int used_domains); 229 230 /*! 231 * \brief Start the statistics for the given module. 232 * 233 * \param module_id Element identifier of the module. 234 */ 235 int (*start_stats)(fwk_id_t module_id); 236 237 /*! 238 * \brief Add new domain to the statistics of the parent module. 239 * 240 * \param module_id Element identifier of the module. 241 * \param domain_id Element identifier of the domain. 242 * \param level_count Total number of levels in this domain. 243 */ 244 int (*add_domain)( 245 fwk_id_t module_id, 246 fwk_id_t domain_id, 247 int level_count); 248 249 /*! 250 * \brief Update the domain statistics with new level ID set. 251 * 252 * \param module_id Element identifier of the module. 253 * \param domain_id Element identifier of the domain. 254 * \param level_id Current operating level ID. 255 */ 256 int (*update_domain)( 257 fwk_id_t module_id, 258 fwk_id_t domain_id, 259 uint32_t level_id); 260 261 /*! 262 * \brief Get low and high addresses of statistics in AP address space 263 * with length of the memory region 264 * 265 * \param module_id Element identifier of the module. 266 * \param [out] addr_low lower 32 bits of the statistics address 267 * \param [out] addr_high higher 32 bits of the statistics address 268 * \param [out] length of the statistics memory region 269 */ 270 int (*get_statistics_desc)( 271 fwk_id_t module_id, 272 uint32_t *addr_low, 273 uint32_t *addr_high, 274 uint32_t *len); 275 }; 276 /*! 277 * \} 278 */ 279 /*! 280 * \defgroup GroupStatisticsIds Identifiers 281 * \{ 282 */ 283 284 /*! 285 * \brief API indices. 286 */ 287 enum mod_stats_api_idx { 288 MOD_STATS_API_IDX_STATS, /*!< API index for mod_stats_api_id_stats() */ 289 MOD_STATS_API_IDX_COUNT /*!< Number of defined APIs */ 290 }; 291 292 /*! Module API identifier */ 293 static const fwk_id_t mod_stats_api_id_stats = 294 FWK_ID_API_INIT(FWK_MODULE_IDX_STATISTICS, MOD_STATS_API_IDX_STATS); 295 296 /*! 297 * \} 298 */ 299 300 /*! 301 * \} 302 */ 303 304 #endif 305