• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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