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