1Guide to migrate to new Platform porting interface 2================================================== 3 4 5.. section-numbering:: 6 :suffix: . 7 8.. contents:: 9 10-------------- 11 12Introduction 13------------ 14 15The PSCI implementation in Trusted Firmware has undergone a redesign because of 16three 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 29The PSCI 1.0 implementation introduces new frameworks to fulfill the above 30requirements. These framework changes mean that the platform porting API must 31also be modified. This document is a guide to assist migration of the existing 32platform ports to the new platform API. 33 34This document describes the new platform API and compares it with the 35deprecated API. It also describes the compatibility layer that enables the 36existing platform ports to work with the PSCI 1.0 implementation. The 37deprecated platform API is documented for reference. 38 39Platform API modification due to PSCI framework changes 40------------------------------------------------------- 41 42This section describes changes to the platform APIs. 43 44Power domain topology framework platform API modifications 45---------------------------------------------------------- 46 47This removes the assumption in the PSCI implementation that MPIDR 48based affinity instances map directly to power domains. A power domain, as 49described in section 4.2 of `PSCI`_, could contain a core or a logical group 50of cores (a cluster) which share some state on which power management 51operations can be performed. The existing affinity instance based APIs 52``plat_get_aff_count()`` and ``plat_get_aff_state()`` are deprecated. The new 53platform 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 60and are meant to replace the existing ``platform_get_core_pos()`` API. 61The description of these APIs can be found in the `Porting Guide`_. 62These 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 78In 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 81correspond to power domains, the values of new macros remain the same as the 82old ones. 83 84More details on the power domain topology description and its platform 85interface can be found in `psci pd tree`_. 86 87Composite power state framework platform API modifications 88---------------------------------------------------------- 89 90The state-ID field in the power-state parameter of a CPU\_SUSPEND call can be 91used to describe the composite power states specific to a platform. The existing 92PSCI state coordination had the limitation that it operates on a run/off 93granularity of power states and it did not interpret the state-ID field. This 94was acceptable as the specification requirement in PSCI 0.2 and the framework's 95approach to coordination only required maintaining a reference 96count of the number of cores that have requested the cluster to remain powered. 97 98In the PSCI 1.0 specification, this approach is non optimal. If composite 99power states are used, the PSCI implementation cannot make global 100decisions about state coordination required because it does not understand the 101platform specific states. 102 103The PSCI 1.0 implementation now defines a generic representation of the 104power-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. 113Each entry in the array contains the local power state the power domain at 114that power level could enter. The meaning of the local power state value is 115platform defined, and can vary between levels in a single platform. The PSCI 116implementation constraints the values only so that it can classify the state 117as 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 124The 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 126be found in the `Porting Guide <porting-guide.rst>`__. 127 128The PSCI 1.0 implementation adds support to involve the platform in state 129coordination. This enables the platform to decide the final target state. 130During a request to place a power domain in a low power state, the platform 131is passed an array of requested ``plat_local_state_t`` for that power domain by 132each core within it through the ``plat_get_target_pwr_state()`` API. This API 133coordinates amongst these requested states to determine a target 134``plat_local_state_t`` for that power domain. A default weak implementation of 135this API is provided in the platform layer which returns the minimum of the 136requested local states back to the PSCI state coordination. More details 137of ``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 140The PSCI Generic implementation expects platform ports to populate the handlers 141for 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 174The description of these handlers can be found in the `Porting Guide <porting-guide.rst#user-content-function--plat_setup_psci_ops-mandatory>`__. 175The previous ``plat_pm_ops`` structure is deprecated. Compared with the previous 176handlers, the major differences are: 177 178- Difference in parameters 179 180The PSCI 1.0 implementation depends on the ``validate_power_state`` handler to 181convert the power-state parameter (possibly encoding a composite power state) 182passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler 183is now mandatory for PSCI ``CPU_SUSPEND`` support. 184 185The ``plat_psci_ops`` handlers, ``pwr_domain_off``, ``pwr_domain_suspend_early`` 186and ``pwr_domain_suspend``, are passed the target local state for each affected 187power domain. The platform must execute operations specific to these target 188states. Similarly, ``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` 189are passed the local states of the affected power domains before wakeup. The 190platform must execute actions to restore these power domains from these specific 191local states. 192 193- Difference in invocation 194 195Whereas the power management handlers in ``plat_pm_ops`` used to be invoked 196for each affinity level till the target affinity level, the new handlers 197are only invoked once. The ``target_state`` encodes the target low power 198state or the low power state woken up from for each affected power domain. 199 200- Difference in semantics 201 202Although the previous ``suspend`` handlers could be used for power down as well 203as retention at different affinity levels, the new handlers make this support 204explicit. The ``pwr_domain_suspend`` can be used to specify powerdown and 205retention at various power domain levels subject to the conditions mentioned 206in section 4.2.1 of `PSCI`_ 207 208Unlike the previous ``standby`` handler, the ``cpu_standby()`` handler is only used 209as a fast path for placing a core power domain into a standby or retention 210state. 211 212The below diagram shows the sequence of a PSCI SUSPEND call and the interaction 213with the platform layer depicting the exchange of data between PSCI Generic 214layer and the platform layer. 215 216|Image 1| 217 218Refer `plat/arm/board/fvp/fvp\_pm.c`_ for the implementation details of 219these handlers for the FVP. The commit `38dce70f51fb83b27958ba3e2ad15f5635cb1061`_ 220demonstrates the migration of ARM reference platforms to the new platform API. 221 222Miscellaneous modifications 223--------------------------- 224 225In addition to the framework changes, unification of warm reset entry points on 226wakeup from low power modes has led to a change in the platform API. In the 227earlier implementation, the warm reset entry used to be programmed into the 228mailboxes by the 'ON' and 'SUSPEND' power management hooks. In the PSCI 1.0 229implementation, this information is not required, because it can figure that 230out by querying affinity info state whether to execute the 'suspend\_finisher\` 231or 'on\_finisher'. 232 233As 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 235additional parameter to enable the platforms to configure their mailbox. The 236plat\_psci\_ops handlers ``pwr_domain_on`` and ``pwr_domain_suspend`` no longer take 237the warm reset entry point as a parameter. 238 239Also, some platform APIs which took ``MPIDR`` as an argument were only ever 240invoked to perform actions specific to the caller core which makes the argument 241redundant. 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 244operations on the current caller core instead of ``platform_get_entrypoint()``, 245``platform_is_primary_cpu()``, ``platform_set_stack()`` and ``platform_get_stack()``. 246 247Compatibility layer 248------------------- 249 250To ease the migration of the platform ports to the new porting interface, 251a compatibility layer is introduced that essentially implements a glue layer 252between the old platform API and the new API. The build flag 253``ENABLE_PLAT_COMPAT`` (enabled by default), specifies whether to enable this 254layer or not. A platform port which has migrated to the new API can disable 255this flag within the platform specific makefile. 256 257The compatibility layer works on the assumption that the onus of 258state coordination, in case multiple low power states are supported, 259is with the platform. The generic PSCI implementation only takes into 260account whether the suspend request is power down or not. This corresponds 261with the behavior of the PSCI implementation before the introduction of 262new frameworks. Also, it assumes that the affinity levels of the platform 263correspond directly to the power domain levels. 264 265The compatibility layer dynamically constructs the new topology 266description array by querying the platform using ``plat_get_aff_count()`` 267and ``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 269higher level (non-core) power domain nodes must know the cores contained 270within its domain. It does so by storing the core index of first core 271within it and number of core indexes following it. This means that core 272indices returned by ``platform_get_core_pos()`` for cores within a particular 273power domain must be consecutive. We expect that this is the case for most 274platform ports including ARM reference platforms. 275 276The 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 279implemented for the compatibility layer. This allows the existing 280platform ports to work with the new PSCI frameworks without significant 281rework. 282 283Deprecated Platform API 284----------------------- 285 286This section documents the deprecated platform porting API. 287 288Common mandatory modifications 289------------------------------ 290 291The 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 309The following functions must be implemented by the platform port to enable 310the reset vector code to perform the required tasks. 311 312Function : platform\_get\_entrypoint() [mandatory] 313~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 314 315:: 316 317 Argument : unsigned long 318 Return : unsigned long 319 320This function is called with the ``SCTLR.M`` and ``SCTLR.C`` bits disabled. The core 321is identified by its ``MPIDR``, which is passed as the argument. The function is 322responsible for distinguishing between a warm and cold reset using platform- 323specific means. If it is a warm reset, it returns the entrypoint into the 324BL31 image that the core must jump to. If it is a cold reset, this function 325must return zero. 326 327This function is also responsible for implementing a platform-specific mechanism 328to handle the condition where the core has been warm reset but there is no 329entrypoint to jump to. 330 331This function does not follow the Procedure Call Standard used by the 332Application Binary Interface for the ARM 64-bit architecture. The caller should 333not assume that callee saved registers are preserved across a call to this 334function. 335 336Function : platform\_is\_primary\_cpu() [mandatory] 337~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 338 339:: 340 341 Argument : unsigned long 342 Return : unsigned int 343 344This function identifies a core by its ``MPIDR``, which is passed as the argument, 345to determine whether this core is the primary core or a secondary core. A return 346value of zero indicates that the core is not the primary core, while a non-zero 347return value indicates that the core is the primary core. 348 349Common optional modifications 350----------------------------- 351 352Function : platform\_get\_core\_pos() 353~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 354 355:: 356 357 Argument : unsigned long 358 Return : int 359 360A platform may need to convert the ``MPIDR`` of a core to an absolute number, which 361can be used as a core-specific linear index into blocks of memory (for example 362while allocating per-core stacks). This routine contains a simple mechanism 363to perform this conversion, using the assumption that each cluster contains a 364maximum 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 373Function : platform\_set\_stack() 374~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 375 376:: 377 378 Argument : unsigned long 379 Return : void 380 381This function sets the current stack pointer to the normal memory stack that 382has been allocated for the core specified by MPIDR. For BL images that only 383require a stack for the primary core the parameter is ignored. The size of 384the stack allocated to each core is specified by the platform defined constant 385``PLATFORM_STACK_SIZE``. 386 387Common implementations of this function for the UP and MP BL images are 388provided in `plat/common/aarch64/platform\_up\_stack.S`_ and 389`plat/common/aarch64/platform\_mp\_stack.S`_ 390 391Function : platform\_get\_stack() 392~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 393 394:: 395 396 Argument : unsigned long 397 Return : unsigned long 398 399This function returns the base address of the normal memory stack that 400has been allocated for the core specificed by MPIDR. For BL images that only 401require a stack for the primary core the parameter is ignored. The size of 402the stack allocated to each core is specified by the platform defined constant 403``PLATFORM_STACK_SIZE``. 404 405Common implementations of this function for the UP and MP BL images are 406provided in `plat/common/aarch64/platform\_up\_stack.S`_ and 407`plat/common/aarch64/platform\_mp\_stack.S`_ 408 409Modifications for Power State Coordination Interface (in BL31) 410-------------------------------------------------------------- 411 412The following functions must be implemented to initialize PSCI functionality in 413the ARM Trusted Firmware. 414 415Function : plat\_get\_aff\_count() [mandatory] 416~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 417 418:: 419 420 Argument : unsigned int, unsigned long 421 Return : unsigned int 422 423This function may execute with the MMU and data caches enabled if the platform 424port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only 425called by the primary core. 426 427This function is called by the PSCI initialization code to detect the system 428topology. Its purpose is to return the number of affinity instances implemented 429at 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 431system where first cluster implements two cores and the second cluster 432implements four cores, a call to this function with an ``MPIDR`` corresponding 433to the first cluster (``0x0``) and affinity level 0, would return 2. A call 434to this function with an ``MPIDR`` corresponding to the second cluster (``0x100``) 435and affinity level 0, would return 4. 436 437Function : plat\_get\_aff\_state() [mandatory] 438~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 439 440:: 441 442 Argument : unsigned int, unsigned long 443 Return : unsigned int 444 445This function may execute with the MMU and data caches enabled if the platform 446port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only 447called by the primary core. 448 449This function is called by the PSCI initialization code. Its purpose is to 450return the state of an affinity instance. The affinity instance is determined by 451the affinity ID at a given ``affinity level`` (specified by the first argument) 452and 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 454system topologies where certain affinity instances are unimplemented. For 455example, consider a platform that implements a single cluster with four cores and 456another 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 458core is 0x100 to indicate that it does not belong to cluster 0. Cluster 1 459is missing but needs to be accounted for to reach this single core in the 460topology tree. Therefore it is marked as ``PSCI_AFF_ABSENT``. 461 462Function : platform\_setup\_pm() [mandatory] 463~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 464 465:: 466 467 Argument : const plat_pm_ops ** 468 Return : int 469 470This function may execute with the MMU and data caches enabled if the platform 471port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only 472called by the primary core. 473 474This function is called by PSCI initialization code. Its purpose is to export 475handler routines for platform-specific power management actions by populating 476the passed pointer with a pointer to the private ``plat_pm_ops`` structure of 477BL31. 478 479A description of each member of this structure is given below. A platform port 480is expected to implement these handlers if the corresponding PSCI operation 481is to be supported and these handlers are expected to succeed if the return 482type is ``void``. 483 484plat\_pm\_ops.affinst\_standby() 485^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 486 487Perform the platform-specific setup to enter the standby state indicated by the 488passed argument. The generic code expects the handler to succeed. 489 490plat\_pm\_ops.affinst\_on() 491^^^^^^^^^^^^^^^^^^^^^^^^^^^ 492 493Perform the platform specific setup to power on an affinity instance, specified 494by 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 497example, while powering on a core, the cluster that contains this core might 498already be in the ON state. The platform decides what actions must be taken to 499transition from the current state to the target state (indicated by the power 500management operation). The generic code expects the platform to return 501E\_SUCCESS on success or E\_INTERN\_FAIL for any failure. 502 503plat\_pm\_ops.affinst\_off() 504^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 505 506Perform the platform specific setup to power off an affinity instance of the 507calling core. It is called by the PSCI ``CPU_OFF`` API implementation. 508 509The ``affinity level`` (first argument) and ``state`` (second argument) have 510a similar meaning as described in the ``affinst_on()`` operation. They 511identify the affinity instance on which the call is made and its 512current state. This gives the platform port an indication of the 513state transition it must make to perform the requested action. For example, if 514the calling core is the last powered on core in the cluster, after powering down 515affinity level 0 (the core), the platform port should power down affinity 516level 1 (the cluster) as well. The generic code expects the handler to succeed. 517 518plat\_pm\_ops.affinst\_suspend() 519^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 520 521Perform the platform specific setup to power off an affinity instance of the 522calling core. It is called by the PSCI ``CPU_SUSPEND`` API and ``SYSTEM_SUSPEND`` 523API implementation 524 525The ``affinity level`` (second argument) and ``state`` (third argument) have a 526similar meaning as described in the ``affinst_on()`` operation. They are used to 527identify the affinity instance on which the call is made and its current state. 528This gives the platform port an indication of the state transition it must 529make to perform the requested action. For example, if the calling core is the 530last 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) 532as well. 533 534The difference between turning an affinity instance off and suspending it 535is that in the former case, the affinity instance is expected to re-initialize 536its state when it is next powered on (see ``affinst_on_finish()``). In the latter 537case, the affinity instance is expected to save enough state so that it can 538resume execution by restoring this state when it is powered on (see 539``affinst_suspend_finish()``).The generic code expects the handler to succeed. 540 541plat\_pm\_ops.affinst\_on\_finish() 542^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 543 544This function is called by the PSCI implementation after the calling core is 545powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. 546It performs the platform-specific setup required to initialize enough state for 547this core to enter the Normal world and also provide secure runtime firmware 548services. 549 550The ``affinity level`` (first argument) and ``state`` (second argument) have a 551similar meaning as described in the previous operations. The generic code 552expects the handler to succeed. 553 554plat\_pm\_ops.affinst\_suspend\_finish() 555^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 556 557This function is called by the PSCI implementation after the calling core is 558powered on and released from reset in response to an asynchronous wakeup 559event, 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 561setup required to restore the saved state for this core to resume execution 562in the Normal world and also provide secure runtime firmware services. 563 564The ``affinity level`` (first argument) and ``state`` (second argument) have a 565similar meaning as described in the previous operations. The generic code 566expects the platform to succeed. 567 568plat\_pm\_ops.validate\_power\_state() 569^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 570 571This function is called by the PSCI implementation during the ``CPU_SUSPEND`` 572call to validate the ``power_state`` parameter of the PSCI API. If the 573``power_state`` is known to be invalid, the platform must return 574PSCI\_E\_INVALID\_PARAMS as an error, which is propagated back to the Normal 575world PSCI client. 576 577plat\_pm\_ops.validate\_ns\_entrypoint() 578^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 579 580This 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`` 582parameter passed by the Normal world. If the ``entry_point`` is known to be 583invalid, the platform must return PSCI\_E\_INVALID\_PARAMS as an error, which is 584propagated back to the Normal world PSCI client. 585 586plat\_pm\_ops.get\_sys\_suspend\_power\_state() 587^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 588 589This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` 590call to return the ``power_state`` parameter. This allows the platform to encode 591the appropriate State-ID field within the ``power_state`` parameter which can be 592utilized in ``affinst_suspend()`` to suspend to system affinity level. The 593``power_state`` parameter should be in the same format as specified by the 594PSCI 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