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