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