Home | History | Annotate | Download | only in docs
      1 Guide to migrate to new Platform porting interface
      2 ==================================================
      3 
      4 
      5 .. section-numbering::
      6     :suffix: .
      7 
      8 .. contents::
      9 
     10 --------------
     11 
     12 Introduction
     13 ------------
     14 
     15 The PSCI implementation in Trusted Firmware has undergone a redesign because of
     16 three requirements that the PSCI 1.0 specification introduced :
     17 
     18 -  Removing the framework assumption about the structure of the MPIDR, and
     19    its relation to the power topology enables support for deeper and more
     20    complex hierarchies.
     21 
     22 -  Reworking the power state coordination implementation in the framework
     23    to support the more detailed PSCI 1.0 requirements and reduce platform
     24    port complexity
     25 
     26 -  Enable the use of the extended power\_state parameter and the larger StateID
     27    field
     28 
     29 The PSCI 1.0 implementation introduces new frameworks to fulfill the above
     30 requirements. These framework changes mean that the platform porting API must
     31 also be modified. This document is a guide to assist migration of the existing
     32 platform ports to the new platform API.
     33 
     34 This document describes the new platform API and compares it with the
     35 deprecated API. It also describes the compatibility layer that enables the
     36 existing platform ports to work with the PSCI 1.0 implementation. The
     37 deprecated platform API is documented for reference.
     38 
     39 Platform API modification due to PSCI framework changes
     40 -------------------------------------------------------
     41 
     42 This section describes changes to the platform APIs.
     43 
     44 Power domain topology framework platform API modifications
     45 ----------------------------------------------------------
     46 
     47 This removes the assumption in the PSCI implementation that MPIDR
     48 based affinity instances map directly to power domains. A power domain, as
     49 described in section 4.2 of `PSCI`_, could contain a core or a logical group
     50 of cores (a cluster) which share some state on which power management
     51 operations can be performed. The existing affinity instance based APIs
     52 ``plat_get_aff_count()`` and ``plat_get_aff_state()`` are deprecated. The new
     53 platform interfaces that are introduced for this framework are:
     54 
     55 -  ``plat_core_pos_by_mpidr()``
     56 -  ``plat_my_core_pos()``
     57 -  ``plat_get_power_domain_tree_desc()``
     58 
     59 ``plat_my_core_pos()`` and ``plat_core_pos_by_mpidr()`` are mandatory
     60 and are meant to replace the existing ``platform_get_core_pos()`` API.
     61 The description of these APIs can be found in the `Porting Guide`_.
     62 These are used by the power domain topology framework such that:
     63 
     64 #. The generic PSCI code does not generate MPIDRs or use them to query the
     65    platform about the number of power domains at a particular power level. The
     66    ``plat_get_power_domain_tree_desc()`` provides a description of the power
     67    domain tree on the SoC through a pointer to the byte array containing the
     68    power domain topology tree description data structure.
     69 
     70 #. The linear indices returned by ``plat_core_pos_by_mpidr()`` and
     71    ``plat_my_core_pos()`` are used to retrieve core power domain nodes from
     72    the power domain tree. These core indices are unique for a core and it is a
     73    number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The platform can choose
     74    to implement a static mapping between ``MPIDR`` and core index or implement
     75    a dynamic mapping, choosing to skip the unavailable/unused cores to compact
     76    the core indices.
     77 
     78 In addition, the platforms must define the macros ``PLAT_NUM_PWR_DOMAINS`` and
     79 ``PLAT_MAX_PWR_LVL`` which replace the macros ``PLAT_NUM_AFFS`` and
     80 ``PLATFORM_MAX_AFFLVL`` respectively. On platforms where the affinity instances
     81 correspond to power domains, the values of new macros remain the same as the
     82 old ones.
     83 
     84 More details on the power domain topology description and its platform
     85 interface can be found in `psci pd tree`_.
     86 
     87 Composite power state framework platform API modifications
     88 ----------------------------------------------------------
     89 
     90 The state-ID field in the power-state parameter of a CPU\_SUSPEND call can be
     91 used to describe the composite power states specific to a platform. The existing
     92 PSCI state coordination had the limitation that it operates on a run/off
     93 granularity of power states and it did not interpret the state-ID field. This
     94 was acceptable as the specification requirement in PSCI 0.2 and the framework's
     95 approach to coordination only required maintaining a reference
     96 count of the number of cores that have requested the cluster to remain powered.
     97 
     98 In the PSCI 1.0 specification, this approach is non optimal. If composite
     99 power states are used, the PSCI implementation cannot make global
    100 decisions about state coordination required because it does not understand the
    101 platform specific states.
    102 
    103 The PSCI 1.0 implementation now defines a generic representation of the
    104 power-state parameter :
    105 
    106 .. code:: c
    107 
    108     typedef struct psci_power_state {
    109         plat_local_state_t pwr_domain_state[PLAT_MAX_PWR_LVL + 1];
    110     } psci_power_state_t;
    111 
    112 ``pwr_domain_state`` is an array where each index corresponds to a power level.
    113 Each entry in the array contains the local power state the power domain at
    114 that power level could enter. The meaning of the local power state value is
    115 platform defined, and can vary between levels in a single platform. The PSCI
    116 implementation constraints the values only so that it can classify the state
    117 as RUN, RETENTION or OFF as required by the specification:
    118 
    119 #. Zero means RUN
    120 
    121 #. All OFF state values at all levels must be higher than all
    122    RETENTION state values at all levels
    123 
    124 The platform is required to define the macros ``PLAT_MAX_RET_STATE`` and
    125 ``PLAT_MAX_OFF_STATE`` to the framework. The requirement for these macros can
    126 be found in the `Porting Guide <porting-guide.rst>`__.
    127 
    128 The PSCI 1.0 implementation adds support to involve the platform in state
    129 coordination. This enables the platform to decide the final target state.
    130 During a request to place a power domain in a low power state, the platform
    131 is passed an array of requested ``plat_local_state_t`` for that power domain by
    132 each core within it through the ``plat_get_target_pwr_state()`` API. This API
    133 coordinates amongst these requested states to determine a target
    134 ``plat_local_state_t`` for that power domain. A default weak implementation of
    135 this API is provided in the platform layer which returns the minimum of the
    136 requested local states back to the PSCI state coordination. More details
    137 of ``plat_get_target_pwr_state()`` API can be found in the
    138 `Porting Guide <porting-guide.rst#user-content-function--plat_get_target_pwr_state-optional>`__.
    139 
    140 The PSCI Generic implementation expects platform ports to populate the handlers
    141 for the ``plat_psci_ops`` structure which is declared as :
    142 
    143 .. code:: c
    144 
    145     typedef struct plat_psci_ops {
    146         void (*cpu_standby)(plat_local_state_t cpu_state);
    147         int (*pwr_domain_on)(u_register_t mpidr);
    148         void (*pwr_domain_off)(const psci_power_state_t *target_state);
    149         void (*pwr_domain_suspend_early)(const psci_power_state_t *target_state);
    150         void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
    151         void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
    152         void (*pwr_domain_suspend_finish)(
    153                         const psci_power_state_t *target_state);
    154         void (*system_off)(void) __dead2;
    155         void (*system_reset)(void) __dead2;
    156         int (*validate_power_state)(unsigned int power_state,
    157                         psci_power_state_t *req_state);
    158         int (*validate_ns_entrypoint)(unsigned long ns_entrypoint);
    159         void (*get_sys_suspend_power_state)(
    160                         psci_power_state_t *req_state);
    161         int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state,
    162                                     int pwrlvl);
    163         int (*translate_power_state_by_mpidr)(u_register_t mpidr,
    164                                     unsigned int power_state,
    165                                     psci_power_state_t *output_state);
    166         int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level);
    167         int (*mem_protect_chk)(uintptr_t base, u_register_t length);
    168         int (*read_mem_protect)(int *val);
    169         int (*write_mem_protect)(int val);
    170         int (*system_reset2)(int is_vendor,
    171                                 int reset_type, u_register_t cookie);
    172     } plat_psci_ops_t;
    173 
    174 The description of these handlers can be found in the `Porting Guide <porting-guide.rst#user-content-function--plat_setup_psci_ops-mandatory>`__.
    175 The previous ``plat_pm_ops`` structure is deprecated. Compared with the previous
    176 handlers, the major differences are:
    177 
    178 -  Difference in parameters
    179 
    180 The PSCI 1.0 implementation depends on the ``validate_power_state`` handler to
    181 convert the power-state parameter (possibly encoding a composite power state)
    182 passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler
    183 is now mandatory for PSCI ``CPU_SUSPEND`` support.
    184 
    185 The ``plat_psci_ops`` handlers, ``pwr_domain_off``, ``pwr_domain_suspend_early``
    186 and ``pwr_domain_suspend``, are passed the target local state for each affected
    187 power domain. The platform must execute operations specific to these target
    188 states. Similarly, ``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish``
    189 are passed the local states of the affected power domains before wakeup. The
    190 platform must execute actions to restore these power domains from these specific
    191 local states.
    192 
    193 -  Difference in invocation
    194 
    195 Whereas the power management handlers in ``plat_pm_ops`` used to be invoked
    196 for each affinity level till the target affinity level, the new handlers
    197 are only invoked once. The ``target_state`` encodes the target low power
    198 state or the low power state woken up from for each affected power domain.
    199 
    200 -  Difference in semantics
    201 
    202 Although the previous ``suspend`` handlers could be used for power down as well
    203 as retention at different affinity levels, the new handlers make this support
    204 explicit. The ``pwr_domain_suspend`` can be used to specify powerdown and
    205 retention at various power domain levels subject to the conditions mentioned
    206 in section 4.2.1 of `PSCI`_
    207 
    208 Unlike the previous ``standby`` handler, the ``cpu_standby()`` handler is only used
    209 as a fast path for placing a core power domain into a standby or retention
    210 state.
    211 
    212 The below diagram shows the sequence of a PSCI SUSPEND call and the interaction
    213 with the platform layer depicting the exchange of data between PSCI Generic
    214 layer and the platform layer.
    215 
    216 |Image 1|
    217 
    218 Refer `plat/arm/board/fvp/fvp\_pm.c`_ for the implementation details of
    219 these handlers for the FVP. The commit `38dce70f51fb83b27958ba3e2ad15f5635cb1061`_
    220 demonstrates the migration of ARM reference platforms to the new platform API.
    221 
    222 Miscellaneous modifications
    223 ---------------------------
    224 
    225 In addition to the framework changes, unification of warm reset entry points on
    226 wakeup from low power modes has led to a change in the platform API. In the
    227 earlier implementation, the warm reset entry used to be programmed into the
    228 mailboxes by the 'ON' and 'SUSPEND' power management hooks. In the PSCI 1.0
    229 implementation, this information is not required, because it can figure that
    230 out by querying affinity info state whether to execute the 'suspend\_finisher\`
    231 or 'on\_finisher'.
    232 
    233 As a result, the warm reset entry point must be programmed only once. The
    234 ``plat_setup_psci_ops()`` API takes the secure entry point as an
    235 additional parameter to enable the platforms to configure their mailbox. The
    236 plat\_psci\_ops handlers ``pwr_domain_on`` and ``pwr_domain_suspend`` no longer take
    237 the warm reset entry point as a parameter.
    238 
    239 Also, some platform APIs which took ``MPIDR`` as an argument were only ever
    240 invoked to perform actions specific to the caller core which makes the argument
    241 redundant. Therefore the platform APIs ``plat_get_my_entrypoint()``,
    242 ``plat_is_my_cpu_primary()``, ``plat_set_my_stack()`` and
    243 ``plat_get_my_stack()`` are defined which are meant to be invoked only for
    244 operations on the current caller core instead of ``platform_get_entrypoint()``,
    245 ``platform_is_primary_cpu()``, ``platform_set_stack()`` and ``platform_get_stack()``.
    246 
    247 Compatibility layer
    248 -------------------
    249 
    250 To ease the migration of the platform ports to the new porting interface,
    251 a compatibility layer is introduced that essentially implements a glue layer
    252 between the old platform API and the new API. The build flag
    253 ``ENABLE_PLAT_COMPAT`` (enabled by default), specifies whether to enable this
    254 layer or not. A platform port which has migrated to the new API can disable
    255 this flag within the platform specific makefile.
    256 
    257 The compatibility layer works on the assumption that the onus of
    258 state coordination, in case multiple low power states are supported,
    259 is with the platform. The generic PSCI implementation only takes into
    260 account whether the suspend request is power down or not. This corresponds
    261 with the behavior of the PSCI implementation before the introduction of
    262 new frameworks. Also, it assumes that the affinity levels of the platform
    263 correspond directly to the power domain levels.
    264 
    265 The compatibility layer dynamically constructs the new topology
    266 description array by querying the platform using ``plat_get_aff_count()``
    267 and ``plat_get_aff_state()`` APIs. The linear index returned by
    268 ``platform_get_core_pos()`` is used as the core index for the cores. The
    269 higher level (non-core) power domain nodes must know the cores contained
    270 within its domain. It does so by storing the core index of first core
    271 within it and number of core indexes following it. This means that core
    272 indices returned by ``platform_get_core_pos()`` for cores within a particular
    273 power domain must be consecutive. We expect that this is the case for most
    274 platform ports including ARM reference platforms.
    275 
    276 The old PSCI helpers like ``psci_get_suspend_powerstate()``,
    277 ``psci_get_suspend_stateid()``, ``psci_get_suspend_stateid_by_mpidr()``,
    278 ``psci_get_max_phys_off_afflvl()`` and ``psci_get_suspend_afflvl()`` are also
    279 implemented for the compatibility layer. This allows the existing
    280 platform ports to work with the new PSCI frameworks without significant
    281 rework.
    282 
    283 Deprecated Platform API
    284 -----------------------
    285 
    286 This section documents the deprecated platform porting API.
    287 
    288 Common mandatory modifications
    289 ------------------------------
    290 
    291 The mandatory macros to be defined by the platform port in ``platform_def.h``
    292 
    293 -  **#define : PLATFORM\_NUM\_AFFS**
    294 
    295    Defines the total number of nodes in the affinity hierarchy at all affinity
    296    levels used by the platform.
    297 
    298 -  **#define : PLATFORM\_MAX\_AFFLVL**
    299 
    300    Defines the maximum affinity level that the power management operations
    301    should apply to. ARMv8-A has support for four affinity levels. It is likely
    302    that hardware will implement fewer affinity levels. This macro allows the
    303    PSCI implementation to consider only those affinity levels in the system
    304    that the platform implements. For example, the Base AEM FVP implements two
    305    clusters with a configurable number of cores. It reports the maximum
    306    affinity level as 1, resulting in PSCI power control up to the cluster
    307    level.
    308 
    309 The following functions must be implemented by the platform port to enable
    310 the reset vector code to perform the required tasks.
    311 
    312 Function : platform\_get\_entrypoint() [mandatory]
    313 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    314 
    315 ::
    316 
    317     Argument : unsigned long
    318     Return   : unsigned long
    319 
    320 This function is called with the ``SCTLR.M`` and ``SCTLR.C`` bits disabled. The core
    321 is identified by its ``MPIDR``, which is passed as the argument. The function is
    322 responsible for distinguishing between a warm and cold reset using platform-
    323 specific means. If it is a warm reset, it returns the entrypoint into the
    324 BL31 image that the core must jump to. If it is a cold reset, this function
    325 must return zero.
    326 
    327 This function is also responsible for implementing a platform-specific mechanism
    328 to handle the condition where the core has been warm reset but there is no
    329 entrypoint to jump to.
    330 
    331 This function does not follow the Procedure Call Standard used by the
    332 Application Binary Interface for the ARM 64-bit architecture. The caller should
    333 not assume that callee saved registers are preserved across a call to this
    334 function.
    335 
    336 Function : platform\_is\_primary\_cpu() [mandatory]
    337 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    338 
    339 ::
    340 
    341     Argument : unsigned long
    342     Return   : unsigned int
    343 
    344 This function identifies a core by its ``MPIDR``, which is passed as the argument,
    345 to determine whether this core is the primary core or a secondary core. A return
    346 value of zero indicates that the core is not the primary core, while a non-zero
    347 return value indicates that the core is the primary core.
    348 
    349 Common optional modifications
    350 -----------------------------
    351 
    352 Function : platform\_get\_core\_pos()
    353 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    354 
    355 ::
    356 
    357     Argument : unsigned long
    358     Return   : int
    359 
    360 A platform may need to convert the ``MPIDR`` of a core to an absolute number, which
    361 can be used as a core-specific linear index into blocks of memory (for example
    362 while allocating per-core stacks). This routine contains a simple mechanism
    363 to perform this conversion, using the assumption that each cluster contains a
    364 maximum of four cores:
    365 
    366 ::
    367 
    368     linear index = cpu_id + (cluster_id * 4)
    369 
    370     cpu_id = 8-bit value in MPIDR at affinity level 0
    371     cluster_id = 8-bit value in MPIDR at affinity level 1
    372 
    373 Function : platform\_set\_stack()
    374 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    375 
    376 ::
    377 
    378     Argument : unsigned long
    379     Return   : void
    380 
    381 This function sets the current stack pointer to the normal memory stack that
    382 has been allocated for the core specified by MPIDR. For BL images that only
    383 require a stack for the primary core the parameter is ignored. The size of
    384 the stack allocated to each core is specified by the platform defined constant
    385 ``PLATFORM_STACK_SIZE``.
    386 
    387 Common implementations of this function for the UP and MP BL images are
    388 provided in `plat/common/aarch64/platform\_up\_stack.S`_ and
    389 `plat/common/aarch64/platform\_mp\_stack.S`_
    390 
    391 Function : platform\_get\_stack()
    392 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    393 
    394 ::
    395 
    396     Argument : unsigned long
    397     Return   : unsigned long
    398 
    399 This function returns the base address of the normal memory stack that
    400 has been allocated for the core specificed by MPIDR. For BL images that only
    401 require a stack for the primary core the parameter is ignored. The size of
    402 the stack allocated to each core is specified by the platform defined constant
    403 ``PLATFORM_STACK_SIZE``.
    404 
    405 Common implementations of this function for the UP and MP BL images are
    406 provided in `plat/common/aarch64/platform\_up\_stack.S`_ and
    407 `plat/common/aarch64/platform\_mp\_stack.S`_
    408 
    409 Modifications for Power State Coordination Interface (in BL31)
    410 --------------------------------------------------------------
    411 
    412 The following functions must be implemented to initialize PSCI functionality in
    413 the ARM Trusted Firmware.
    414 
    415 Function : plat\_get\_aff\_count() [mandatory]
    416 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    417 
    418 ::
    419 
    420     Argument : unsigned int, unsigned long
    421     Return   : unsigned int
    422 
    423 This function may execute with the MMU and data caches enabled if the platform
    424 port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only
    425 called by the primary core.
    426 
    427 This function is called by the PSCI initialization code to detect the system
    428 topology. Its purpose is to return the number of affinity instances implemented
    429 at a given ``affinity level`` (specified by the first argument) and a given
    430 ``MPIDR`` (specified by the second argument). For example, on a dual-cluster
    431 system where first cluster implements two cores and the second cluster
    432 implements four cores, a call to this function with an ``MPIDR`` corresponding
    433 to the first cluster (``0x0``) and affinity level 0, would return 2. A call
    434 to this function with an ``MPIDR`` corresponding to the second cluster (``0x100``)
    435 and affinity level 0, would return 4.
    436 
    437 Function : plat\_get\_aff\_state() [mandatory]
    438 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    439 
    440 ::
    441 
    442     Argument : unsigned int, unsigned long
    443     Return   : unsigned int
    444 
    445 This function may execute with the MMU and data caches enabled if the platform
    446 port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only
    447 called by the primary core.
    448 
    449 This function is called by the PSCI initialization code. Its purpose is to
    450 return the state of an affinity instance. The affinity instance is determined by
    451 the affinity ID at a given ``affinity level`` (specified by the first argument)
    452 and an ``MPIDR`` (specified by the second argument). The state can be one of
    453 ``PSCI_AFF_PRESENT`` or ``PSCI_AFF_ABSENT``. The latter state is used to cater for
    454 system topologies where certain affinity instances are unimplemented. For
    455 example, consider a platform that implements a single cluster with four cores and
    456 another core implemented directly on the interconnect with the cluster. The
    457 ``MPIDR``\ s of the cluster would range from ``0x0-0x3``. The ``MPIDR`` of the single
    458 core is 0x100 to indicate that it does not belong to cluster 0. Cluster 1
    459 is missing but needs to be accounted for to reach this single core in the
    460 topology tree. Therefore it is marked as ``PSCI_AFF_ABSENT``.
    461 
    462 Function : platform\_setup\_pm() [mandatory]
    463 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    464 
    465 ::
    466 
    467     Argument : const plat_pm_ops **
    468     Return   : int
    469 
    470 This function may execute with the MMU and data caches enabled if the platform
    471 port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only
    472 called by the primary core.
    473 
    474 This function is called by PSCI initialization code. Its purpose is to export
    475 handler routines for platform-specific power management actions by populating
    476 the passed pointer with a pointer to the private ``plat_pm_ops`` structure of
    477 BL31.
    478 
    479 A description of each member of this structure is given below. A platform port
    480 is expected to implement these handlers if the corresponding PSCI operation
    481 is to be supported and these handlers are expected to succeed if the return
    482 type is ``void``.
    483 
    484 plat\_pm\_ops.affinst\_standby()
    485 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    486 
    487 Perform the platform-specific setup to enter the standby state indicated by the
    488 passed argument. The generic code expects the handler to succeed.
    489 
    490 plat\_pm\_ops.affinst\_on()
    491 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    492 
    493 Perform the platform specific setup to power on an affinity instance, specified
    494 by the ``MPIDR`` (first argument) and ``affinity level`` (third argument). The
    495 ``state`` (fourth argument) contains the current state of that affinity instance
    496 (ON or OFF). This is useful to determine whether any action must be taken. For
    497 example, while powering on a core, the cluster that contains this core might
    498 already be in the ON state. The platform decides what actions must be taken to
    499 transition from the current state to the target state (indicated by the power
    500 management operation). The generic code expects the platform to return
    501 E\_SUCCESS on success or E\_INTERN\_FAIL for any failure.
    502 
    503 plat\_pm\_ops.affinst\_off()
    504 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    505 
    506 Perform the platform specific setup to power off an affinity instance of the
    507 calling core. It is called by the PSCI ``CPU_OFF`` API implementation.
    508 
    509 The ``affinity level`` (first argument) and ``state`` (second argument) have
    510 a similar meaning as described in the ``affinst_on()`` operation. They
    511 identify the affinity instance on which the call is made and its
    512 current state. This gives the platform port an indication of the
    513 state transition it must make to perform the requested action. For example, if
    514 the calling core is the last powered on core in the cluster, after powering down
    515 affinity level 0 (the core), the platform port should power down affinity
    516 level 1 (the cluster) as well. The generic code expects the handler to succeed.
    517 
    518 plat\_pm\_ops.affinst\_suspend()
    519 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    520 
    521 Perform the platform specific setup to power off an affinity instance of the
    522 calling core. It is called by the PSCI ``CPU_SUSPEND`` API and ``SYSTEM_SUSPEND``
    523 API implementation
    524 
    525 The ``affinity level`` (second argument) and ``state`` (third argument) have a
    526 similar meaning as described in the ``affinst_on()`` operation. They are used to
    527 identify the affinity instance on which the call is made and its current state.
    528 This gives the platform port an indication of the state transition it must
    529 make to perform the requested action. For example, if the calling core is the
    530 last powered on core in the cluster, after powering down affinity level 0
    531 (the core), the platform port should power down affinity level 1 (the cluster)
    532 as well.
    533 
    534 The difference between turning an affinity instance off and suspending it
    535 is that in the former case, the affinity instance is expected to re-initialize
    536 its state when it is next powered on (see ``affinst_on_finish()``). In the latter
    537 case, the affinity instance is expected to save enough state so that it can
    538 resume execution by restoring this state when it is powered on (see
    539 ``affinst_suspend_finish()``).The generic code expects the handler to succeed.
    540 
    541 plat\_pm\_ops.affinst\_on\_finish()
    542 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    543 
    544 This function is called by the PSCI implementation after the calling core is
    545 powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call.
    546 It performs the platform-specific setup required to initialize enough state for
    547 this core to enter the Normal world and also provide secure runtime firmware
    548 services.
    549 
    550 The ``affinity level`` (first argument) and ``state`` (second argument) have a
    551 similar meaning as described in the previous operations. The generic code
    552 expects the handler to succeed.
    553 
    554 plat\_pm\_ops.affinst\_suspend\_finish()
    555 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    556 
    557 This function is called by the PSCI implementation after the calling core is
    558 powered on and released from reset in response to an asynchronous wakeup
    559 event, for example a timer interrupt that was programmed by the core during the
    560 ``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific
    561 setup required to restore the saved state for this core to resume execution
    562 in the Normal world and also provide secure runtime firmware services.
    563 
    564 The ``affinity level`` (first argument) and ``state`` (second argument) have a
    565 similar meaning as described in the previous operations. The generic code
    566 expects the platform to succeed.
    567 
    568 plat\_pm\_ops.validate\_power\_state()
    569 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    570 
    571 This function is called by the PSCI implementation during the ``CPU_SUSPEND``
    572 call to validate the ``power_state`` parameter of the PSCI API. If the
    573 ``power_state`` is known to be invalid, the platform must return
    574 PSCI\_E\_INVALID\_PARAMS as an error, which is propagated back to the Normal
    575 world PSCI client.
    576 
    577 plat\_pm\_ops.validate\_ns\_entrypoint()
    578 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    579 
    580 This function is called by the PSCI implementation during the ``CPU_SUSPEND``,
    581 ``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the Non-secure ``entry_point``
    582 parameter passed by the Normal world. If the ``entry_point`` is known to be
    583 invalid, the platform must return PSCI\_E\_INVALID\_PARAMS as an error, which is
    584 propagated back to the Normal world PSCI client.
    585 
    586 plat\_pm\_ops.get\_sys\_suspend\_power\_state()
    587 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    588 
    589 This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND``
    590 call to return the ``power_state`` parameter. This allows the platform to encode
    591 the appropriate State-ID field within the ``power_state`` parameter which can be
    592 utilized in ``affinst_suspend()`` to suspend to system affinity level. The
    593 ``power_state`` parameter should be in the same format as specified by the
    594 PSCI specification for the CPU\_SUSPEND API.
    595 
    596 --------------
    597 
    598 *Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.*
    599 
    600 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf
    601 .. _Porting Guide: porting-guide.rst#user-content-function--plat_my_core_pos
    602 .. _psci pd tree: psci-pd-tree.rst
    603 .. _plat/arm/board/fvp/fvp\_pm.c: ../plat/arm/board/fvp/fvp_pm.c
    604 .. _38dce70f51fb83b27958ba3e2ad15f5635cb1061: https://github.com/ARM-software/arm-trusted-firmware/commit/38dce70f51fb83b27958ba3e2ad15f5635cb1061
    605 .. _plat/common/aarch64/platform\_up\_stack.S: ../plat/common/aarch64/platform_up_stack.S
    606 .. _plat/common/aarch64/platform\_mp\_stack.S: ../plat/common/aarch64/platform_mp_stack.S
    607 
    608 .. |Image 1| image:: diagrams/psci-suspend-sequence.png?raw=true
    609