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 * Power domain management support. 9 */ 10 11 #ifndef MOD_POWER_DOMAIN_H 12 #define MOD_POWER_DOMAIN_H 13 14 #include <fwk_element.h> 15 #include <fwk_id.h> 16 #include <fwk_module_idx.h> 17 18 #include <limits.h> 19 #include <stdbool.h> 20 #include <stddef.h> 21 #include <stdint.h> 22 23 /*! 24 * \addtogroup GroupModules Modules 25 * \{ 26 */ 27 28 /*! 29 * \defgroup GroupPowerDomain Power Domains 30 * 31 * \details Support for querying and setting the power state of power domains 32 * such as CPU, cluster and GPU power domains. 33 * 34 * \{ 35 */ 36 37 /*! 38 * Maximum number of states for a power domain. 39 */ 40 #define MOD_PD_STATE_COUNT_MAX 16 41 42 /*! 43 * \brief Types of power domain. 44 */ 45 enum mod_pd_type { 46 /*! Processor. */ 47 MOD_PD_TYPE_CORE, 48 /*! Processor cluster. */ 49 MOD_PD_TYPE_CLUSTER, 50 /*! Generic device. */ 51 MOD_PD_TYPE_DEVICE, 52 /*! Debug device. */ 53 MOD_PD_TYPE_DEVICE_DEBUG, 54 /*! System. */ 55 MOD_PD_TYPE_SYSTEM, 56 /*! Number of power domain types. */ 57 MOD_PD_TYPE_COUNT 58 }; 59 60 /*! 61 * \brief Bit width of power domain type within attributes. 62 */ 63 #define MOD_PD_TYPE_BITS_WIDTH ((sizeof(unsigned int) * CHAR_BIT) - \ 64 __builtin_clz(MOD_PD_TYPE_COUNT - 1)) 65 66 /*! 67 * \brief Attributes of a power domain. 68 */ 69 struct mod_pd_attributes { 70 /*! Type of the power domain. */ 71 enum mod_pd_type pd_type : MOD_PD_TYPE_BITS_WIDTH; 72 73 /*! \internal */ 74 unsigned int not_used : ((sizeof(unsigned int) * CHAR_BIT) - 75 MOD_PD_TYPE_BITS_WIDTH); 76 }; 77 78 /*! 79 * \brief Identifiers for the power levels. 80 */ 81 enum mod_pd_level { 82 /*! Level 0. */ 83 MOD_PD_LEVEL_0, 84 /*! Level 1. */ 85 MOD_PD_LEVEL_1, 86 /*! Level 2. */ 87 MOD_PD_LEVEL_2, 88 /*! Level 3. */ 89 MOD_PD_LEVEL_3, 90 /*! Number of power domain levels. */ 91 MOD_PD_LEVEL_COUNT 92 }; 93 94 /*! 95 * \brief Power domain module configuration. 96 */ 97 struct mod_power_domain_config { 98 /*! 99 * Identifiers of the modules and elements which are granted access to the 100 * restricted interface of the module. 101 */ 102 fwk_id_t *authorized_id_table; 103 104 /*! Number of identifiers in the "authorized_id_table" table. */ 105 size_t authorized_id_table_size; 106 107 /* 108 * A flag to choose between sending notification when the last core going 109 * off or doing complete system suspend by the power domain 110 */ 111 bool enable_system_suspend_notification; 112 }; 113 114 /*! 115 * \brief Configuration data for a power domain. 116 * 117 * \details The configuration data of a power domain describes the power 118 * domain and its relationship with other power domains in the system. 119 * Assumptions about the organisation of the power domains, underlying the 120 * way in which power domains are described here, are: 121 * - Each power domain can be represented as a node in a power domain 122 * topology tree. 123 * - Sibling power domains are mutually exclusive. 124 * - Parent power domains are shared by the children. 125 * 126 * For more information, refer to the "Arm Power State Coordination 127 * Interface Platform Design Document", available here: 128 * http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_ 129 * Coordination_Interface_PDD_v1_1_DEN0022D.pdf 130 */ 131 struct mod_power_domain_element_config { 132 /*! 133 * brief Power domain parent index 134 */ 135 uint32_t parent_idx; 136 137 /*! 138 * Identifier of the module or element providing the driver for the power 139 * domain. 140 */ 141 fwk_id_t driver_id; 142 143 /*! Identifier of the driver API. */ 144 fwk_id_t api_id; 145 146 /*! Attributes of the power domain. */ 147 struct mod_pd_attributes attributes; 148 149 /*! 150 * Mask of the allowed power states for the power domain, for each possible 151 * power state of its parent. Table of allowed state masks. The bit 'i' of 152 * the entry 'j' is equal to one if and only if the state 'i' for the power 153 * domain is allowed when its parent is in state 'j'. The number of bits of 154 * each entry of this table has to be greater or equal than 155 * MOD_PD_STATE_COUNT_MAX. 156 */ 157 const uint32_t *allowed_state_mask_table; 158 159 /*! 160 * Power state names. The power state names are used only for debug 161 * purposes and this table is optional. If not provided then the default 162 * power state names (OFF, ON, SLEEP, 3, 4, ...) are used for the power 163 * domain states. 164 */ 165 const char **state_name_table; 166 167 /*! Composite state number of levels mask */ 168 const uint32_t composite_state_levels_mask; 169 170 /*! 171 * Composite state mask table. This table provides the mask for each level 172 */ 173 const uint32_t *composite_state_mask_table; 174 175 /*! Size of the composite state mask table */ 176 size_t composite_state_mask_table_size; 177 178 /*! Size of the table of allowed state masks */ 179 size_t allowed_state_mask_table_size; 180 181 /*! Size of the table of allowed state masks */ 182 size_t state_name_table_size; 183 184 /*! Disable power domain transition notifications */ 185 bool disable_state_transition_notifications; 186 187 /* ! Optional mapping for the enum_mod_pd_state to the driver state */ 188 const unsigned int *pd_state_mapping_table; 189 }; 190 191 /*! 192 * \brief Types of system shutdown 193 */ 194 enum mod_pd_system_shutdown { 195 /*! System shutdown */ 196 MOD_PD_SYSTEM_SHUTDOWN, 197 198 /*! System cold reset */ 199 MOD_PD_SYSTEM_COLD_RESET, 200 201 /*! System warm reset */ 202 MOD_PD_SYSTEM_WARM_RESET, 203 204 /*! Sub-system reset */ 205 MOD_PD_SYSTEM_SUB_SYSTEM_RESET, 206 207 /*! Forced system shutdown */ 208 MOD_PD_SYSTEM_FORCED_SHUTDOWN, 209 210 /*! Number of shutdown types */ 211 MOD_PD_SYSTEM_COUNT, 212 }; 213 214 /*! 215 * \brief Identifiers of the power domain states. The other states are defined 216 * by the platform code for more flexibility. The power states defined by 217 * the platform must be ordered from the shallowest to the deepest state. 218 */ 219 enum mod_pd_state { 220 /*! \c OFF power state */ 221 MOD_PD_STATE_OFF, 222 223 /*! \c ON power state */ 224 MOD_PD_STATE_ON, 225 226 /*! \c SLEEP power state */ 227 MOD_PD_STATE_SLEEP, 228 229 /*! \c OFF0 power state */ 230 MOD_PD_STATE_OFF_0, 231 232 /*! \c OFF1 power state */ 233 MOD_PD_STATE_OFF_1, 234 235 /*! \c OFF2 power state */ 236 MOD_PD_STATE_OFF_2, 237 238 /*! Number of power states */ 239 MOD_PD_STATE_COUNT 240 }; 241 242 /*! 243 * \brief Masks for the power domain states. 244 */ 245 enum mod_pd_state_mask { 246 MOD_PD_STATE_OFF_MASK = 1 << MOD_PD_STATE_OFF, 247 MOD_PD_STATE_ON_MASK = 1 << MOD_PD_STATE_ON, 248 MOD_PD_STATE_SLEEP_MASK = 1 << MOD_PD_STATE_SLEEP, 249 MOD_PD_STATE_OFF_0_MASK = 1 << MOD_PD_STATE_OFF_0, 250 MOD_PD_STATE_OFF_1_MASK = 1 << MOD_PD_STATE_OFF_1, 251 MOD_PD_STATE_OFF_2_MASK = 1 << MOD_PD_STATE_OFF_2, 252 }; 253 254 /*! 255 * \brief Number of bits for each level state in a composite power state. 256 */ 257 #define MOD_PD_CS_STATE_BITS_PER_LEVEL 4 258 259 /*! 260 * \brief Mask for a composite power state. 261 */ 262 #define MOD_PD_CS_STATE_MASK ((1U << MOD_PD_CS_STATE_BITS_PER_LEVEL) - 1U) 263 264 /*! 265 * \brief Shifts for the states and child policies fields in a composite 266 * power state. 267 */ 268 enum { 269 MOD_PD_CS_LEVEL_0_STATE_SHIFT = 270 MOD_PD_LEVEL_0 * MOD_PD_CS_STATE_BITS_PER_LEVEL, 271 MOD_PD_CS_LEVEL_1_STATE_SHIFT = 272 MOD_PD_LEVEL_1 * MOD_PD_CS_STATE_BITS_PER_LEVEL, 273 MOD_PD_CS_LEVEL_2_STATE_SHIFT = 274 MOD_PD_LEVEL_2 * MOD_PD_CS_STATE_BITS_PER_LEVEL, 275 MOD_PD_CS_LEVEL_3_STATE_SHIFT = 276 MOD_PD_LEVEL_3 * MOD_PD_CS_STATE_BITS_PER_LEVEL, 277 MOD_PD_CS_LEVEL_SHIFT = 278 MOD_PD_LEVEL_COUNT * MOD_PD_CS_STATE_BITS_PER_LEVEL, 279 }; 280 281 /*! 282 * \brief Compute a composite power domain state. 283 */ 284 #define MOD_PD_COMPOSITE_STATE(HIGHEST_LEVEL, LEVEL_3_STATE, LEVEL_2_STATE, \ 285 LEVEL_1_STATE, LEVEL_0_STATE) \ 286 (((HIGHEST_LEVEL) << MOD_PD_CS_LEVEL_SHIFT) | \ 287 ((LEVEL_3_STATE) << MOD_PD_CS_LEVEL_3_STATE_SHIFT) | \ 288 ((LEVEL_2_STATE) << MOD_PD_CS_LEVEL_2_STATE_SHIFT) | \ 289 ((LEVEL_1_STATE) << MOD_PD_CS_LEVEL_1_STATE_SHIFT) | \ 290 ((LEVEL_0_STATE) << MOD_PD_CS_LEVEL_0_STATE_SHIFT)) 291 292 /*! 293 * \brief Power domain driver interface. 294 * 295 * \details The interface the power domain module relies on to perform 296 * actions on a power domain. Examples include powering a domain on or off, 297 * resetting the domain and preparing for/reacting to a system shutdown or 298 * reset. 299 */ 300 struct mod_pd_driver_api { 301 /*! 302 * \brief Set the power domain identified by \p dev_id to the \p state power 303 * state. 304 * 305 * \details The power domain module calls this function when processing a 306 * <tt>set state</tt> request. The function is called once the module 307 * has checked that the power domain's children and parent are in a 308 * proper state for the power domain to be transitioned to the \p state 309 * power state. This function must not return until the transition has 310 * completed. 311 * 312 * \warning In the case of a <tt>shutdown</tt> request, if provided, 313 * ::mod_pd_driver_api::shutdown will be called instead. 314 * 315 * \param dev_id Driver identifier of the power domain. 316 * \param state Power state the power domain has to be put into. 317 * 318 * \retval ::FWK_SUCCESS The power state has been successfully set. 319 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 320 * call to the API. 321 * \return One of the other specific error codes described by the driver 322 * module. 323 */ 324 int (*set_state)(fwk_id_t dev_id, unsigned int state); 325 326 /*! 327 * \brief Get the current power state of the power domain identified by 328 * \p dev_id. 329 * 330 * \details The power domain module calls this function when processing a 331 * <tt>get state</tt> or <tt>get composite state</tt> request. 332 * 333 * \param dev_id Driver identifier of the power domain. 334 * \param[out] state Power state of the power domain. 335 * 336 * \retval ::FWK_SUCCESS The power state was successfully returned. 337 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 338 * call to the API. 339 */ 340 int (*get_state)(fwk_id_t dev_id, unsigned int *state); 341 342 /*! 343 * \brief Reset the power domain identified by \p dev_id. 344 * 345 * \details The power domain module calls this function when processing a 346 * <tt>reset</tt> request. The module will ensure that any children of 347 * the power domain are powered off before attempting a reset. 348 * 349 * \param dev_id Driver identifier of the power domain. 350 * 351 * \retval ::FWK_SUCCESS The power domain was successfully reset. 352 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 353 * call to the API. 354 * \return One of the other specific error codes described by the module. 355 */ 356 int (*reset)(fwk_id_t dev_id); 357 358 /*! 359 * \brief Check whether a state transition request should be denied. 360 * 361 * \note This function is optional (may be \c NULL) and it is expected that 362 * most drivers will not implement it. 363 * 364 * \details The power domain module calls this function when it wishes to 365 * know whether it should permit or deny a state transition request. 366 * It is intended to provide a device a denial mechanism that can make 367 * judgements based on information unavailable to the power domain 368 * module, such as dependencies between power domains beyond the power 369 * domain tree model. 370 * 371 * \param dev_id Driver identifier of the power domain. 372 * \param state Power state the power domain is intended to be put into. 373 * 374 * \retval true The transition should be denied. 375 * \retval false The power domain can transition to the power state \p 376 * state. 377 */ 378 bool (*deny)(fwk_id_t dev_id, unsigned int state); 379 380 /*! 381 * \brief Prepare the last standing core for a system suspend. 382 * 383 * \details The function prepares the last standing core for entering the 384 * ::MOD_PD_STATE_OFF state (powered off, no wake-up interrupt) when 385 * it will execute WFI. The function should also ensure that when the 386 * core is powered off a state transition report is sent by means of 387 * the ::mod_pd_driver_input_api::report_power_state_transition 388 * driver input interface function indicating that the core power 389 * domain state should be updated. This function is mandatory for core 390 * power domains, but is otherwise unused. 391 * 392 * \param dev_id Driver identifier of the power domain. 393 * 394 * \retval ::FWK_SUCCESS The core has been successfully prepared. 395 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 396 * call to the API. 397 */ 398 int (*prepare_core_for_system_suspend)(fwk_id_t dev_id); 399 400 /*! 401 * \brief Shutdown a power domain as part of a system shutdown. 402 * 403 * \note This function is optional (may be \c NULL). 404 * 405 * \details The power domain module calls this function when processing a 406 * <tt>shutdown</tt> request. 407 * 408 * \param dev_id Driver identifier of the power domain. 409 * \param system_shutdown Type of system shutdown. 410 * 411 * \retval ::FWK_SUCCESS The operation succeeded. 412 * \retval ::FWK_PENDING The operation was acknowledged. Please note that at 413 * present there is no dedicated driver input api for this case. 414 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 415 * call to the API. 416 */ 417 int (*shutdown)(fwk_id_t dev_id, 418 enum mod_pd_system_shutdown system_shutdown); 419 }; 420 421 /*! 422 * \brief Power domain module public interface. 423 * 424 * \details The interface the power domain module exposes to the other modules 425 * and their elements without any restriction. 426 */ 427 428 struct mod_pd_public_api { 429 /*! 430 * \brief Get the type of a power domain. 431 * 432 * \param pd_id Identifier of the power domain that the type is being 433 * queried for. 434 * \param[out] type Type of the power domain. 435 * 436 * \retval ::FWK_SUCCESS The type of the power domain was returned. 437 * \retval ::FWK_E_INIT The module has not been initialized. 438 * \retval ::FWK_E_STATE The power domain module is in an invalid state. 439 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 440 * - The `pd_id` parameter was not a valid system entity identifier. 441 * - The `type` parameter was a null pointer value. 442 */ 443 int (*get_domain_type)(fwk_id_t pd_id, enum mod_pd_type *type); 444 445 /*! 446 * \brief Get the identifier of the parent of a power domain. 447 * 448 * \note The function returns ::FWK_ID_NONE in the case of the root power 449 * domain which does not have any parent. 450 * 451 * \param pd_id Identifier of the power domain. 452 * \param[out] parent_pd_id Identifier of the parent power domain. 453 * 454 * \retval ::FWK_SUCCESS The identifier of the parent power domain was 455 * returned. 456 * \retval ::FWK_E_INIT The module has not been initialized. 457 * \retval ::FWK_E_STATE The power domain module is in an invalid state. 458 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 459 * - The `pd_id` parameter was not a valid system entity identifier. 460 * - The `parent_pd_id` parameter was a null pointer value. 461 */ 462 int (*get_domain_parent_id)(fwk_id_t pd_id, fwk_id_t *parent_pd_id); 463 }; 464 465 /*! 466 * \brief Power domain module restricted interface. 467 * 468 * \details The interface the power domain module exposes to a restricted set 469 * of modules and/or elements. The set of modules and/or elements that are 470 * allowed to access this interface is defined by the module configuration 471 * data. 472 */ 473 struct mod_pd_restricted_api { 474 /*! 475 * \brief Get the type of a power domain. 476 * 477 * \param pd_id Identifier of the power domain that the type is being 478 * queried for. 479 * \param[out] type Type of the power domain. 480 * 481 * \retval ::FWK_SUCCESS The type of the power domain was returned. 482 * \retval ::FWK_E_INIT The module has not been initialized. 483 * \retval ::FWK_E_STATE The power domain module is in an invalid state. 484 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 485 * - The `pd_id` parameter was not a valid system entity identifier. 486 * - The `type` parameter was a null pointer value. 487 */ 488 int (*get_domain_type)(fwk_id_t pd_id, enum mod_pd_type *type); 489 490 /*! 491 * \brief Get the identifier of the parent of a power domain. 492 * 493 * \note The function returns ::FWK_ID_NONE in the case of the root power 494 * domain which does not have any parent. 495 * 496 * \param pd_id Identifier of the power domain. 497 * \param[out] parent_pd_id The identifier of the parent power domain. 498 * 499 * \retval ::FWK_SUCCESS The identifier of the parent power domain was 500 * returned. 501 * \retval ::FWK_E_INIT The module has not been initialized. 502 * \retval ::FWK_E_STATE The power domain module is in an invalid state. 503 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 504 * - The `pd_id` parameter was not a valid system entity identifier. 505 * - The `parent_pd_id` parameter was a null pointer value. 506 */ 507 int (*get_domain_parent_id)(fwk_id_t pd_id, fwk_id_t *parent_pd_id); 508 509 /*! 510 * \brief Request an asynchronous power state transition. 511 * 512 * \warning Successful completion of this function does not indicate 513 * completion of a transition, but instead that a request has been 514 * submitted. 515 * 516 * \param pd_id Identifier of the power domain whose state has to be set. 517 * 518 * \param resp_requested True if the caller wants to be notified with an 519 * event response at the end of the request processing. 520 * 521 * \param composite State the power domain has to be put into and 522 * possibly the state(s) its ancestor(s) has(have) to be put into. The 523 * module will ensure that, for each power state transition, the parent 524 * and the children of the power domain involved are in a state where 525 * the transition can be completed. 526 * 527 * \retval ::FWK_SUCCESS The power state transition was submitted. 528 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 529 * call to the API. 530 * \retval ::FWK_E_PARAM One or more parameters were invalid. 531 */ 532 int (*set_state)(fwk_id_t pd_id, bool resp_requested, uint32_t state); 533 534 /*! 535 * \brief Get the state of a given power domain. 536 * 537 * \param pd_id Identifier of the power domain whose state has to be 538 * retrieved. 539 * \param[out] state The power domain state. 540 * 541 * \retval ::FWK_SUCCESS The power state was returned. 542 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 543 * - The `state` parameter was a null pointer value. 544 */ 545 int (*get_state)(fwk_id_t pd_id, unsigned int *state); 546 547 /*! 548 * \brief Request for a power domain to be reset. 549 * 550 * \note The function queues a reset request. When the function returns the 551 * power domain has not been reset, the reset has just been requested 552 * to the power domain module. 553 * 554 * \param pd_id Identifier of the power domain to reset. 555 * 556 * \param resp_requested True if the caller wants to be notified with an 557 * event response at the end of the reset request processing. 558 * 559 * \retval ::FWK_SUCCESS Reset request transmitted. 560 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 561 * call to the API. 562 * \retval ::FWK_E_HANDLER The function is not called from a thread. 563 * \retval ::FWK_E_NOMEM Failed to allocate a request descriptor. 564 * \retval ::FWK_E_PARAM The power domain identifier is unknown. 565 */ 566 int (*reset)(fwk_id_t pd_id, bool resp_requested); 567 568 /*! 569 * \brief Suspend the system. 570 * 571 * \note The function initiates the suspension of the system. On call, all 572 * but one core power domain must be in the MOD_PD_STATE_OFF state. 573 * When the function returns the power down of the last standing core 574 * is programmed to occur as soon as the core executes WFI. 575 * 576 * \param state State the system has to be suspended to. The definition 577 * of those states is platform specific. 578 * 579 * \retval ::FWK_SUCCESS The system suspension has been initiated 580 * successfully. 581 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 582 * call to the API. 583 * \retval ::FWK_E_HANDLER The function is not called from a thread. 584 * \retval ::FWK_E_NOMEM Failed to allocate a request descriptor. 585 * \retval ::FWK_E_PARAM Invalid state. 586 * \retval ::FWK_E_STATE The system is not in the proper state to be 587 * suspended. 588 */ 589 int (*system_suspend)(unsigned int state); 590 591 /*! 592 * \brief Shutdown the system. 593 * 594 * \note The function shutdowns the system whatever its current state. If 595 * the shutdown is successful, the function does not return. 596 * 597 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 598 * call to the API. 599 * \retval ::FWK_PENDING Request aknowledged. A response event will not be 600 * sent to the caller. 601 * \retval ::FWK_E_HANDLER The function is not called from a thread. 602 * \retval ::FWK_E_NOMEM Failed to allocate a request descriptor. 603 */ 604 int (*system_shutdown)(enum mod_pd_system_shutdown system_shutdown); 605 }; 606 607 /*! 608 * \brief Power domain module driver input API. 609 * 610 * \details The interface the power domain module exposes to its module drivers 611 * to be able to ask for power state transitions or report power state 612 * transitions following the occurrence of interrupts. 613 */ 614 struct mod_pd_driver_input_api { 615 /*! 616 * \brief Request an composite power state transition. 617 * 618 * \warning Successful completion of this function does not indicate 619 * completion of a transition, but instead that a request has been 620 * submitted. 621 * 622 * \param pd_id Identifier of the power domain whose state has to be set. 623 * 624 * \param resp_requested True if the caller wants to be notified with an 625 * event response at the end of the request processing. 626 * 627 * \param composite_state State the power domain has to be put into and 628 * possibly the state(s) its ancestor(s) has(have) to be put into. The 629 * module will ensure that, for each power state transition, the parent 630 * and the children of the power domain involved are in a state where 631 * the transition can be completed. 632 * 633 * \retval ::FWK_SUCCESS The composite power state transition was submitted. 634 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 635 * call to the API. 636 * \retval ::FWK_E_PARAM One or more parameters were invalid. 637 */ 638 int (*set_state)( 639 fwk_id_t pd_id, 640 bool resp_requested, 641 uint32_t composite_state); 642 643 /*! 644 * \brief Request for a power domain to be reset. 645 * 646 * \note The function queues a reset request. When the function returns the 647 * power domain has not been reset, the reset has just been requested 648 * to the power domain module. 649 * 650 * \param pd_id Identifier of the power domain to reset. 651 * 652 * \param resp_requested True if the caller wants to be notified with an 653 * event response at the end of the request processing. 654 * 655 * \retval ::FWK_SUCCESS Reset request transmitted. 656 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 657 * call to the API. 658 * \retval ::FWK_E_HANDLER The function is not called from a thread. 659 * \retval ::FWK_E_NOMEM Failed to allocate a request descriptor. 660 * \retval ::FWK_E_PARAM The power domain identifier is unknown. 661 */ 662 int (*reset)(fwk_id_t pd_id, bool resp_requested); 663 664 /*! 665 * \brief Report a power domain state transition. 666 * 667 * \warning Failure to call this function on a power state transition may 668 * leave the power domain module with an outdated power state for the 669 * power domain. 670 * 671 * \param pd_id Identifier of the power domain, a power state transition 672 * report is is sent to. 673 * 674 * \retval ::FWK_SUCCESS Report transmitted. 675 * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the 676 * call to the API. 677 * \retval ::FWK_E_NOMEM Failed to allocate a report event. 678 * \retval ::FWK_E_PARAM The power domain identifier is unknown. 679 */ 680 int (*report_power_state_transition)(fwk_id_t pd_id, unsigned int state); 681 682 /*! 683 * \brief Get the power domain identifier of the last core online before or 684 * during system suspend. 685 * 686 * \details When an agent calls for system suspend, the power domain module 687 * ensures that all cores are turned off except for one, which is the 688 * calling entity. Because any core can call system suspend, it may be 689 * necessary for a driver to know which core called system suspend. 690 * With this information the driver can, for example, safely resume the 691 * system from the same core which was turned off lastly. 692 * 693 * \note The power domain module does not perform any checks to ensure that 694 * this function is called during a system suspend sequence. 695 * 696 * \param[out] last_core_pd_id Identifier of the last core. 697 * 698 * \retval ::FWK_E_PARAM The pointer to the identifier is not valid. 699 * \retval ::FWK_SUCCESS The request was successful. 700 * \return One of the standard framework error codes. 701 */ 702 int (*get_last_core_pd_id)(fwk_id_t *last_core_pd_id); 703 }; 704 705 /*! 706 * \brief Parameters of a power state pre-transition notification. 707 */ 708 struct mod_pd_power_state_pre_transition_notification_params { 709 /*! Current power state */ 710 unsigned int current_state; 711 712 /*! Target power state */ 713 unsigned int target_state; 714 }; 715 716 /*! 717 * \brief Parameters of the response to a power state pre-transition 718 * notification. 719 */ 720 struct mod_pd_power_state_pre_transition_notification_resp_params { 721 /*! 722 * Status of the transition for the entity being notified. 723 */ 724 int status; 725 }; 726 727 /*! 728 * \brief Parameters of a power domain transition notification. 729 */ 730 struct mod_pd_power_state_transition_notification_params { 731 /*! Power state the power domain has transitioned to */ 732 unsigned int state; 733 }; 734 735 /*! 736 * \brief Parameters of a pre-shutdown transition notification. 737 */ 738 struct mod_pd_pre_shutdown_notif_params { 739 /*! System shutdown type the system is transitioning to */ 740 enum mod_pd_system_shutdown system_shutdown; 741 }; 742 743 /*! 744 * \brief Parameters of the response to a pre-shutdown transition notification. 745 */ 746 struct mod_pd_pre_shutdown_notif_resp_params { 747 /*! Status of the operation from the entity being notified */ 748 int status; 749 }; 750 751 /*! 752 * \defgroup GroupPowerDomainIds Identifiers 753 * \{ 754 */ 755 756 /*! 757 * \brief API indices 758 */ 759 enum mod_pd_api_idx { 760 MOD_PD_API_IDX_PUBLIC, 761 MOD_PD_API_IDX_RESTRICTED, 762 MOD_PD_API_IDX_DRIVER_INPUT, 763 MOD_PD_API_IDX_COUNT, 764 }; 765 766 #ifdef BUILD_HAS_MOD_POWER_DOMAIN 767 /*! Public API identifier */ 768 static const fwk_id_t mod_pd_api_id_public = 769 FWK_ID_API_INIT(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_PUBLIC); 770 771 /*! Restricted API identifier */ 772 static const fwk_id_t mod_pd_api_id_restricted = 773 FWK_ID_API_INIT(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_RESTRICTED); 774 775 /*! Driver input API identifier */ 776 static const fwk_id_t mod_pd_api_id_driver_input = 777 FWK_ID_API_INIT(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_DRIVER_INPUT); 778 #endif 779 780 #ifdef BUILD_HAS_NOTIFICATION 781 /*! 782 * \brief Notification indices. 783 */ 784 enum mod_pd_notification_idx { 785 /*! Power state transition */ 786 MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION, 787 788 /*! Power domain system suspend */ 789 MOD_PD_NOTIFICATION_IDX_POWER_DOMAIN_SYSTEM_SUSPEND, 790 791 /*! Power state pre-transition */ 792 MOD_PD_NOTIFICATION_IDX_POWER_STATE_PRE_TRANSITION, 793 794 /*! Broadcast notification before shutdown starts */ 795 MOD_PD_NOTIFICATION_IDX_PRE_SHUTDOWN, 796 797 /*! Broadcast warm reset notification */ 798 MOD_PD_NOTIFICATION_IDX_PRE_WARM_RESET, 799 800 /*! Number of notifications defined by the power domain module */ 801 MOD_PD_NOTIFICATION_COUNT, 802 }; 803 804 /*! 805 * \brief Notification identifiers. 806 */ 807 #ifdef BUILD_HAS_MOD_POWER_DOMAIN 808 /*! Identifier of the power state transition notification */ 809 static const fwk_id_t mod_pd_notification_id_power_state_transition = 810 FWK_ID_NOTIFICATION_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 811 MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION); 812 813 /*! Identifier of the power domain system suspend notification */ 814 static const fwk_id_t mod_pd_notification_id_system_suspend = 815 FWK_ID_NOTIFICATION_INIT( 816 FWK_MODULE_IDX_POWER_DOMAIN, 817 MOD_PD_NOTIFICATION_IDX_POWER_DOMAIN_SYSTEM_SUSPEND); 818 819 /*! Identifier of the power state pre-transition notification */ 820 static const fwk_id_t mod_pd_notification_id_power_state_pre_transition = 821 FWK_ID_NOTIFICATION_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 822 MOD_PD_NOTIFICATION_IDX_POWER_STATE_PRE_TRANSITION); 823 824 /*! 825 * Identifier of the pre-shutdown notification. 826 * 827 * \note This notification will be broadcast with module identifier only. 828 */ 829 static const fwk_id_t mod_pd_notification_id_pre_shutdown = 830 FWK_ID_NOTIFICATION_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 831 MOD_PD_NOTIFICATION_IDX_PRE_SHUTDOWN); 832 833 /*! 834 * Identifier of the pre-warm reboot notification. 835 * 836 * \note This notification will be broadcast with module identifier only. 837 */ 838 static const fwk_id_t mod_pd_notification_id_pre_warm_reset = 839 FWK_ID_NOTIFICATION_INIT( 840 FWK_MODULE_IDX_POWER_DOMAIN, 841 MOD_PD_NOTIFICATION_IDX_PRE_WARM_RESET); 842 843 # endif 844 #endif /* BUILD_HAS_NOTIFICATION */ 845 846 /*! 847 * \brief Power Domain public events indices 848 */ 849 enum mod_pd_public_event_idx { 850 /*! Set state request event */ 851 MOD_PD_PUBLIC_EVENT_IDX_SET_STATE, 852 853 /*! Number of public Power Domain events */ 854 MOD_PD_PUBLIC_EVENT_IDX_COUNT, 855 }; 856 857 /*! Set state requires a response */ 858 #define MOD_PD_SET_STATE_REQ_RESP true 859 860 /*! Set state does not require a response */ 861 #define MOD_PD_SET_STATE_NO_RESP false 862 863 /*! 864 * \brief Parameters of the set state response event 865 */ 866 struct pd_set_state_response { 867 /*! Status of the set state request event processing */ 868 int status; 869 870 /*! 871 * \brief Copy of the "composite_state" request parameter 872 * 873 * \details The composite state that defines the power state that the power 874 * domain, target of the request, had to be put into and possibly the 875 * power states the ancestors of the power domain had to be put into. 876 */ 877 uint32_t composite_state; 878 }; 879 880 /*! 881 * \brief Public Events identifiers. 882 */ 883 #ifdef BUILD_HAS_MOD_POWER_DOMAIN 884 /*! Identifier of the public event set_state identifier */ 885 static const fwk_id_t mod_pd_public_event_id_set_state = 886 FWK_ID_EVENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 887 MOD_PD_PUBLIC_EVENT_IDX_SET_STATE); 888 889 #endif 890 891 /*! 892 * \} 893 */ 894 895 /*! 896 * \} 897 */ 898 899 /*! 900 * \} 901 */ 902 903 #endif /* MOD_POWER_DOMAIN_H */ 904