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