1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * SCMI performance domain management protocol support. 9 */ 10 11 #ifndef MOD_SCMI_PERF_H 12 #define MOD_SCMI_PERF_H 13 14 #include <fwk_id.h> 15 #include <fwk_macros.h> 16 17 #include <stddef.h> 18 #include <stdint.h> 19 20 /*! 21 * \addtogroup GroupModules Modules 22 * \{ 23 */ 24 25 /*! 26 * \defgroup GroupSCMI_PERF SCMI Performance Domain Management Protocol 27 * \{ 28 */ 29 30 /*! 31 * \brief Fast Channel Initialisation 32 */ 33 #define FCH_INIT(FCH_NUM) \ 34 { \ 35 .transport_id = \ 36 FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_TRANSPORT, FCH_NUM), \ 37 .transport_api_id = FWK_ID_API_INIT( \ 38 FWK_MODULE_IDX_TRANSPORT, MOD_TRANSPORT_API_IDX_FAST_CHANNELS), \ 39 } 40 41 /*! 42 * \brief Agent permissions. 43 */ 44 enum mod_scmi_perf_permissions { 45 /*! No permissions */ 46 MOD_SCMI_PERF_PERMS_NONE = 0, 47 48 /*! Permission to set performance level */ 49 MOD_SCMI_PERF_PERMS_SET_LEVEL = (1U << 0), 50 51 /*! Permission to set performance limits */ 52 MOD_SCMI_PERF_PERMS_SET_LIMITS = (1U << 1), 53 }; 54 55 /*! 56 * \brief Fast channels address index 57 */ 58 enum mod_scmi_perf_fast_channels_index { 59 MOD_SCMI_PERF_FAST_CHANNEL_LEVEL_SET = 0, 60 MOD_SCMI_PERF_FAST_CHANNEL_LIMIT_SET = 1, 61 MOD_SCMI_PERF_FAST_CHANNEL_LEVEL_GET = 2, 62 MOD_SCMI_PERF_FAST_CHANNEL_LIMIT_GET = 3, 63 MOD_SCMI_PERF_FAST_CHANNEL_COUNT = 4, 64 }; 65 /*! 66 *\brief Per-Domain Fast Channel Limit in shared memory. 67 */ 68 struct mod_scmi_perf_fast_channel_limit { 69 /*! Performance limit max. */ 70 uint32_t range_max; 71 /*! Performance limit min. */ 72 uint32_t range_min; 73 }; 74 75 /*! 76 *\brief Fast channels memory offset 77 */ 78 enum mod_scmi_perf_fast_channel_memory_offset { 79 MOD_SCMI_PERF_FAST_CHANNEL_OFFSET_LEVEL_SET = 0, 80 MOD_SCMI_PERF_FAST_CHANNEL_OFFSET_LIMIT_SET = sizeof(uint32_t), 81 MOD_SCMI_PERF_FAST_CHANNEL_OFFSET_LEVEL_GET = 82 sizeof(uint32_t) + sizeof(struct mod_scmi_perf_fast_channel_limit), 83 MOD_SCMI_PERF_FAST_CHANNEL_OFFSET_LIMIT_GET = 84 sizeof(uint32_t) * 2 + sizeof(struct mod_scmi_perf_fast_channel_limit), 85 MOD_SCMI_PERF_FAST_CHANNEL_OFFSET_TOTAL = sizeof(uint32_t) * 2 + 86 sizeof(struct mod_scmi_perf_fast_channel_limit) * 2 87 }; 88 89 /*! 90 * \brief Performance limits. 91 */ 92 struct mod_scmi_perf_level_limits { 93 uint32_t minimum; /*!< Minimum permitted level */ 94 uint32_t maximum; /*!< Maximum permitted level */ 95 }; 96 97 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS 98 /*! 99 * \brief Fast channel configuration 100 */ 101 struct scmi_perf_fch_config { 102 fwk_id_t transport_id; 103 fwk_id_t transport_api_id; 104 }; 105 106 #endif 107 /*! 108 * \brief Performance domain configuration data. 109 */ 110 struct mod_scmi_perf_domain_config { 111 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS 112 /* Pointer to the fast channel configuration */ 113 const struct scmi_perf_fch_config *fch_config; 114 115 /*! Flag indicates whether a particular domain supports fast channel */ 116 bool supports_fast_channels; 117 #endif 118 119 /*! Flag indicating that statistics are collected for this domain */ 120 bool stats_collected; 121 122 /*! 123 * \brief Performance group. 124 * 125 * \details When there's a mapping of n logical domains from SCMI to one 126 * physical DVFS domain, it is required to indicate the physical domain 127 * associated with each logical domain. See architecture documentation 128 * for further details. 129 * 130 * \note When not provided, the logical and physical domains are the same. 131 * It is also expected that either none of the domains or all of them 132 * are present. 133 */ 134 fwk_optional_id_t phy_group_id; 135 }; 136 137 /*! 138 * \brief Performance Plugins domain type 139 * 140 * \details The plugin's view on performance domains. See architecture 141 * documentation for further details. 142 */ 143 enum plugin_domain_type { 144 /*! 145 * \brief Plugin domain type physical 146 * 147 * \details A plugin which requires to have a physical domain' data should 148 * choose this option. Note that the plugin will receive `n` updates, 149 * where n is the number of physical domains. 150 */ 151 PERF_PLUGIN_DOM_TYPE_PHYSICAL, 152 153 /*! 154 * \brief Plugin domain type logical 155 * 156 * \details A plugin which requires to have all the logical domains' data 157 * that belong to a physical domain should choose this option. Note 158 * that the plugin will receive `n` updates where `n` is the number of 159 * physical domains. 160 */ 161 PERF_PLUGIN_DOM_TYPE_LOGICAL, 162 163 /*! 164 * \brief Plugin domain type full 165 * 166 * \details A plugin which requires to have all the physical domains' data 167 * in one go should choose this option. Note that the plugin will 168 * receive 1 updates at every iteration. See documentation for further 169 * details. 170 */ 171 PERF_PLUGIN_DOM_TYPE_FULL, 172 173 /*! The number of domain types available for plugins */ 174 PERF_PLUGIN_DOM_TYPE_COUNT, 175 }; 176 177 /*! 178 * \brief SCMI Performance Domain Management Protocol configuration data. 179 */ 180 struct mod_scmi_perf_config { 181 /*! Per-domain configuration data */ 182 const struct mod_scmi_perf_domain_config (*domains)[]; 183 184 /*! 185 * \brief Performance domain count 186 * 187 * \details This is the number of performance domains exposed via SCMI. 188 */ 189 size_t perf_doms_count; 190 191 /*! Fast Channel polling rate */ 192 uint32_t fast_channels_rate_limit; 193 194 /*! Flag indicating statistics in use */ 195 bool stats_enabled; 196 197 /*! 198 * \brief Whether approximate levels are allowed to be requested. 199 * 200 * \details When set to true, and no exact match with requested level is 201 * found, the next upper level will be used as performance level, as long as 202 * it is within current limits. 203 */ 204 bool approximate_level; 205 206 /*! Table of Performance Plugins */ 207 const struct mod_scmi_plugin_config *plugins; 208 209 /*! Number of Performance Plugins */ 210 size_t plugins_count; 211 }; 212 213 /*! 214 * \brief SCMI Performance APIs. 215 * 216 * \details APIs exported by SCMI Performance Protocol. 217 */ 218 enum scmi_perf_api_idx { 219 /*! Index for the SCMI protocol API */ 220 MOD_SCMI_PERF_PROTOCOL_API = 0, 221 222 /*! Index of the updates notification API */ 223 MOD_SCMI_PERF_DVFS_UPDATE_API = 1, 224 225 /*! Index of the Performance Plugin Handler API */ 226 MOD_SCMI_PERF_PLUGINS_API = 2, 227 228 /*! Number of APIs */ 229 MOD_SCMI_PERF_API_COUNT = 3 230 }; 231 232 /*! 233 * \brief Performance Plugins configuration data. 234 */ 235 struct mod_scmi_plugin_config { 236 /*! Performance Plugin identifier */ 237 fwk_id_t id; 238 239 /*! Performance Plugin domain type mode */ 240 enum plugin_domain_type dom_type; 241 }; 242 243 /*! 244 * \brief SCMI Perf updates notification API. 245 * 246 * \details API used by DVFS to notify the Perf layer when either the 247 * limits or level has been changed. 248 */ 249 struct mod_scmi_perf_updated_api { 250 /*! 251 * \brief Inform SCMI Perf that the domain limits have been updated. 252 * 253 * \param domain_id Domain identifier. 254 * \param cookie Context-specific value. 255 * \param range_min Min allowed performance level. 256 * \param range_max Max allowed performance level. 257 */ 258 void (*notify_limits_updated)( 259 fwk_id_t domain_id, 260 uintptr_t cookie, 261 uint32_t range_min, 262 uint32_t range_max); 263 264 /*! 265 * \brief Inform SCMI Perf that the domain level has been updated. 266 * 267 * \param domain_id Domain identifier. 268 * \param cookie Context-specific value. 269 * \param level The new performance level of the domain. 270 */ 271 void (*notify_level_updated)( 272 fwk_id_t domain_id, 273 uintptr_t cookie, 274 uint32_t level); 275 }; 276 277 /*! 278 * \defgroup GroupScmiPerformancePolicyHandlers Policy Handlers 279 * 280 * \brief SCMI Performance Policy Handlers. 281 * 282 * \details The SCMI policy handlers are weak definitions to allow a platform 283 * to implement a policy appropriate to that platform. The SCMI 284 * performance policy functions may be overridden in the 285 * `product/<platform>/src` directory. 286 * 287 * \note The `level`/`range` values may be changed by the policy handlers. 288 * \note See `product/juno/src/juno_scmi_clock.c` for an example policy 289 * handler. 290 * 291 * \{ 292 */ 293 294 /*! 295 * \brief Policy handler policies. 296 * 297 * \details These values are returned to the message handler by the policy 298 * handlers to determine whether the message handler should continue 299 * processing the message, or whether the request has been rejected. 300 */ 301 enum mod_scmi_perf_policy_status { 302 /*! Do not execute the message handler */ 303 MOD_SCMI_PERF_SKIP_MESSAGE_HANDLER = 0, 304 305 /*! Execute the message handler */ 306 MOD_SCMI_PERF_EXECUTE_MESSAGE_HANDLER = 1, 307 }; 308 309 /*! 310 * 311 * \brief SCMI Performance Set Level command policy. 312 * 313 * \details This function determines whether the SCMI message handler should 314 * allow or reject a given SCMI Performance Set Level command. 315 * 316 * The SCMI policy handler is executed before the message handler is 317 * called. The SCMI protocol message handler will only continue if the 318 * policy handler both returns ::FWK_SUCCESS and sets the policy status to 319 * ::MOD_SCMI_PERF_EXECUTE_MESSAGE_HANDLER. 320 * 321 * \param[out] policy_status Whether the command should be accepted or not. 322 * \param[in, out] level Level requested to be set. 323 * \param[in] agent_id Identifier of the agent requesting the service. 324 * \param[in] domain_id Identifier of the performance domain. 325 * 326 * \retval ::FWK_SUCCESS The operation succeeded. 327 * 328 * \return Status code representing the result of the operation. 329 */ 330 int scmi_perf_level_set_policy( 331 enum mod_scmi_perf_policy_status *policy_status, 332 uint32_t *level, 333 unsigned int agent_id, 334 fwk_id_t domain_id); 335 336 /*! 337 * \brief SCMI Performance Set Limits command policy. 338 * 339 * \details This function determines whether the SCMI message handler should 340 * allow or reject a given SCMI Performance Set Limits command. 341 * 342 * The SCMI policy handler is executed before the message handler is 343 * called. The SCMI protocol message handler will only continue if the 344 * policy handler both returns ::FWK_SUCCESS and sets the policy status to 345 * ::MOD_SCMI_PERF_EXECUTE_MESSAGE_HANDLER. 346 * 347 * \param[out] policy_status Whether the command should be accepted or not. 348 * \param[in, out] range_min Minimum level range. 349 * \param[in, out] range_max Maximum level range. 350 * \param[in] agent_id Identifier of the agent requesting the service. 351 * \param[in] domain_id Identifier of the performance domain. 352 * 353 * \retval ::FWK_SUCCESS The operation succeeded. 354 * 355 * \return Status code representing the result of the operation. 356 */ 357 int scmi_perf_limits_set_policy( 358 enum mod_scmi_perf_policy_status *policy_status, 359 uint32_t *range_min, 360 uint32_t *range_max, 361 unsigned int agent_id, 362 fwk_id_t domain_id); 363 364 /*! 365 * \} 366 */ 367 368 /*! 369 * \brief Performance Plugins performance data. 370 * 371 * \details This dataset is shared with the plugins. It contains the data 372 * collected from fast-channels and provides a way for the plugins to 373 * request an adjusted limit for the performance driver. 374 * Depending ond the plugin's domain view (physical or logical), levels and 375 * limits can be scalars or arrays. 376 */ 377 struct perf_plugins_perf_update { 378 /*! Performance domain identifier */ 379 fwk_id_t domain_id; 380 381 /*! Performance level(s) - This is an input for the plugin */ 382 uint32_t *level; 383 384 /*! Performance max limit(s) - This is an input for the plugin */ 385 uint32_t *max_limit; 386 387 /*! Performance min limit(s) - This is an input for the plugin */ 388 uint32_t *min_limit; 389 390 /*! 391 * \brief Adjusted performance max limit(s). 392 * 393 * \details This is an input/output for the plugin. 394 * This table contains the aggregated adjusted values set out by 395 * previous plugins. Plugins can use this info for their algorithms. 396 * A performance plugin should overwrite these values if wishes to 397 * affect the performance limit for targeted domains. 398 */ 399 uint32_t *adj_max_limit; 400 401 /*! 402 * \brief Adjusted performance min limit(s). 403 * 404 * \details This is an input/output for the plugin. 405 * This table contains the aggregated adjusted values set out by 406 * previous plugins. Plugins can use this info for their algorithms. 407 * A performance plugin should overwrite these values if wishes to 408 * affect the performance limit for targeted domains. 409 */ 410 uint32_t *adj_min_limit; 411 }; 412 413 /*! 414 * \brief Performance Report data. 415 * 416 * \details This dataset is shared with the plugins when the performance driver 417 * reports the final applied performance level/limit change. 418 */ 419 struct perf_plugins_perf_report { 420 /*! Physical (or dependency) domain identifier */ 421 const fwk_id_t dep_dom_id; 422 423 /*! Performance level */ 424 const uint32_t level; 425 426 /*! Performance max limit */ 427 const uint32_t max_limit; 428 429 /*! Performance min limit */ 430 const uint32_t min_limit; 431 }; 432 433 /*! 434 * \brief Performance Plugin APIs. 435 * 436 * \details APIs exported by the Performance Plugins. 437 */ 438 enum scmi_perf_plugin_api_idx { 439 /*! Index for SCMI Performance Plugin API */ 440 MOD_SCMI_PERF_PLUGIN_API = 0, 441 442 /*! Number of SCMI Performance Plugins APIs */ 443 444 /*! 445 * \brief Number of SCMI Performance Plugins APIs 446 * 447 * \details Other APIs implemented by a performance plugin will start from 448 * this index afterwards. 449 */ 450 MOD_SCMI_PERF_PLUGIN_API_COUNT = 1, 451 }; 452 453 /*! 454 * \brief Performance Plugins interface. 455 * 456 * \details The interface that performance plugins should implement to receive 457 * updates on performance. 458 */ 459 struct perf_plugins_api { 460 /*! 461 * \brief Update performance data. 462 * 463 * \details This function is called periodically to inform the plugin with 464 * the latest performance requests coming from SCMI. 465 * 466 * \details This callback serves the following purposes: 467 * - periodic tick: the plugins is called at determined time intervals 468 * that can be specified in the configuration and corresponds to the 469 * periodicity of the FastChannels sampling. 470 * - last performance level: the plugin has visibility of the last 471 * updated performance level that is taken from the FastChannels. 472 * - last performance limits: the plugin has visibility of the last 473 * updated performance limits that are taken from the FastChannels. 474 * - adjusted performance limits: the plugin has the opportunity to 475 * affect the final performance limits by writing a performance limit 476 * back to the SCMI Performance. 477 * All the above are put together along with an identifier of the 478 * performance domain being controlled. 479 * 480 * A typical scenario for a plugin would be that upon every callback, 481 * the plugin runs its own algorithm which can take advantage of the 482 * periodicity. In this algorithm the plugin can - if required - read 483 * the current performance level and limits for the given domain and, 484 * when necessary, can apply (write) new limits in the `adjusted` 485 * fields. This is expected to be done for each of the relevant 486 * performance domains that the plugin is concerned, unless its view 487 * is _FULL. In the latter case, the callback will execute once only in 488 * the tick period and the plugin will be provided with the entire blob 489 * of performance level/limits for all the domains. 490 * This is made available for plugins whose algorithm needs to take 491 * into account all the performance domains collectively in order to 492 * make a sane decision of the limits to be applied. 493 * 494 * \param data Performance data 495 * \retval ::FWK_SUCCESS or one of FWK_E_* error codes. 496 * 497 * \return Status code representing the result of the operation. 498 */ 499 int (*update)(struct perf_plugins_perf_update *data); 500 501 /*! 502 * \brief Report performance data. 503 * 504 * \details This function is called once a final performance level limit has 505 * been applied. 506 * 507 * \param data Performance data 508 * \retval ::FWK_SUCCESS or one of FWK_E_* error codes. 509 * 510 * \note This function is optional. Plugins that are not interested to 511 * receive a report of the last performance transition can omit this 512 * function. 513 * 514 * \return Status code representing the result of the operation. 515 */ 516 int (*report)(struct perf_plugins_perf_report *data); 517 }; 518 519 /*! 520 * \brief Performance Request Limits data. 521 * 522 * \details Data container for the plugin hanlder, contains the requested 523 * limits. 524 */ 525 struct plugin_limits_req { 526 /*! Performance domain identifier */ 527 const fwk_id_t domain_id; 528 529 /*! Performance max limit requested */ 530 const uint32_t max_limit; 531 532 /*! Performance min limit requested */ 533 const uint32_t min_limit; 534 }; 535 536 /*! 537 * \brief Plugin handler API - reserved for plugins only 538 * 539 * \details This interface can be used by any of the performance plugins to 540 * interact with the plugin handler to asyncronously request a performance 541 * level/limit. 542 * 543 * \warning This API should be used only in circumstances where waiting for the 544 * next update call would cause a significant loss of performance. 545 * Plugins should always try to use the update callback (see above) 546 * whenever possible. 547 */ 548 struct perf_plugins_handler_api { 549 /*! 550 * \brief Set limits 551 * 552 * \param data Limits request data. 553 * 554 * \retval ::FWK_E_PARAM Invalid parameter. 555 * \retval ::FWK_E_DEVICE The request to the performance driver failed. 556 * \retval ::FWK_SUCCESS The operation succeeded. Note that the operation 557 * may complete asyncronously depending on the performance driver. 558 * 559 * \return Status code representing the result of the operation. 560 */ 561 int (*plugin_set_limits)(struct plugin_limits_req *data); 562 }; 563 564 /*! 565 * \} 566 */ 567 568 /*! 569 * \} 570 */ 571 572 #endif /* MOD_SCMI_PERF_H */ 573