1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef _FSL_NOTIFIER_H_
10 #define _FSL_NOTIFIER_H_
11 
12 #include "fsl_common.h"
13 /*!
14  * @addtogroup notifier
15  * @{
16  */
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*!
23  * @brief Notifier error codes.
24  *
25  * Used as return value of Notifier functions.
26  */
27 enum _notifier_status
28 {
29     kStatus_NOTIFIER_ErrorNotificationBefore =
30         MAKE_STATUS(kStatusGroup_NOTIFIER, 0), /*!< An error occurs during send "BEFORE" notification. */
31     kStatus_NOTIFIER_ErrorNotificationAfter =
32         MAKE_STATUS(kStatusGroup_NOTIFIER, 1), /*!< An error occurs during send "AFTER" notification. */
33 };
34 
35 /*!
36  * @brief Notifier policies.
37  *
38  * Defines whether the user function execution is forced or not.
39  * For kNOTIFIER_PolicyForcible, the user function is executed regardless of the callback results,
40  * while kNOTIFIER_PolicyAgreement policy is used to exit NOTIFIER_SwitchConfig()
41  * when any of the callbacks returns error code.
42  * See also NOTIFIER_SwitchConfig() description.
43  */
44 typedef enum _notifier_policy
45 {
46     kNOTIFIER_PolicyAgreement, /*!< NOTIFIER_SwitchConfig() method is exited when any of the callbacks returns error
47                                       code. */
48     kNOTIFIER_PolicyForcible,  /*!< The user function is executed regardless of the results. */
49 } notifier_policy_t;
50 
51 /*! @brief Notification type. Used to notify registered callbacks */
52 typedef enum _notifier_notification_type
53 {
54     kNOTIFIER_NotifyRecover = 0x00U, /*!< Notify IP to recover to previous work state. */
55     kNOTIFIER_NotifyBefore  = 0x01U, /*!< Notify IP that configuration setting is going to change. */
56     kNOTIFIER_NotifyAfter   = 0x02U, /*!< Notify IP that configuration setting has been changed. */
57 } notifier_notification_type_t;
58 
59 /*!
60  * @brief The callback type, which indicates kinds of notification the callback handles.
61  *
62  * Used in the callback configuration structure (notifier_callback_config_t)
63  * to specify when the registered callback is called during configuration switch initiated by the
64  * NOTIFIER_SwitchConfig().
65  * Callback can be invoked in following situations.
66  *  - Before the configuration switch (Callback return value can affect NOTIFIER_SwitchConfig()
67  *    execution. See the NOTIFIER_SwitchConfig() and notifier_policy_t documentation).
68  *  - After an unsuccessful attempt to switch configuration
69  *  - After a successful configuration switch
70  */
71 typedef enum _notifier_callback_type
72 {
73     kNOTIFIER_CallbackBefore      = 0x01U, /*!< Callback handles BEFORE notification. */
74     kNOTIFIER_CallbackAfter       = 0x02U, /*!< Callback handles AFTER notification. */
75     kNOTIFIER_CallbackBeforeAfter = 0x03U, /*!< Callback handles BEFORE and AFTER notification. */
76 } notifier_callback_type_t;
77 
78 /*! @brief Notifier user configuration type.
79  *
80  * Reference of the user defined configuration is stored in an array; the notifier switches between these configurations
81  * based on this array.
82  */
83 typedef void notifier_user_config_t;
84 
85 /*! @brief Notifier user function prototype
86  * Use this function to execute specific operations in configuration switch.
87  * Before and after this function execution, different notification is sent to registered callbacks.
88  * If this function returns any error code, NOTIFIER_SwitchConfig() exits.
89  *
90  * @param targetConfig target Configuration.
91  * @param userData Refers to other specific data passed to user function.
92  * @return An error code or kStatus_Success.
93  */
94 typedef status_t (*notifier_user_function_t)(notifier_user_config_t *targetConfig, void *userData);
95 
96 /*! @brief notification block passed to the registered callback function. */
97 typedef struct _notifier_notification_block
98 {
99     notifier_user_config_t *targetConfig;    /*!< Pointer to target configuration. */
100     notifier_policy_t policy;                /*!< Configure transition policy. */
101     notifier_notification_type_t notifyType; /*!< Configure notification type. */
102 } notifier_notification_block_t;
103 
104 /*!
105  * @brief Callback prototype.
106  *
107  * Declaration of a callback. It is common for registered callbacks.
108  * Reference to function of this type is part of the notifier_callback_config_t callback configuration structure.
109  * Depending on callback type, function of this prototype is called (see NOTIFIER_SwitchConfig())
110  * before configuration switch, after it or in both use cases to notify about
111  * the switch progress (see notifier_callback_type_t). When called, the type of the notification
112  * is passed as a parameter along with the reference to the target configuration structure (see
113  * notifier_notification_block_t) and any data passed during the callback registration. When notified before the
114  * configuration switch, depending on the configuration switch policy (see notifier_policy_t), the callback may deny the
115  * execution of the user function by returning an error code different than kStatus_Success (see
116  * NOTIFIER_SwitchConfig()).
117  *
118  * @param notify Notification block.
119  * @param data Callback data. Refers to the data passed during callback registration. Intended to
120  *  pass any driver or application data such as internal state information.
121  * @return An error code or kStatus_Success.
122  */
123 typedef status_t (*notifier_callback_t)(notifier_notification_block_t *notify, void *data);
124 
125 /*!
126  * @brief Callback configuration structure.
127  *
128  * This structure holds the configuration of callbacks.
129  * Callbacks of this type are expected to be statically allocated.
130  * This structure contains the following application-defined data.
131  *  callback - pointer to the callback function
132  *  callbackType - specifies when the callback is called
133  *  callbackData - pointer to the data passed to the callback.
134  */
135 typedef struct _notifier_callback_config
136 {
137     notifier_callback_t callback;          /*!< Pointer to the callback function. */
138     notifier_callback_type_t callbackType; /*!< Callback type. */
139     void *callbackData;                    /*!< Pointer to the data passed to the callback. */
140 } notifier_callback_config_t;
141 
142 /*!
143  * @brief Notifier handle structure.
144  *
145  * Notifier handle structure. Contains data necessary for the Notifier proper function.
146  * Stores references to registered configurations, callbacks, information about their numbers,
147  * user function, user data, and other internal data.
148  * NOTIFIER_CreateHandle() must be called to initialize this handle.
149  */
150 typedef struct _notifier_handle
151 {
152     notifier_user_config_t **configsTable;      /*!< Pointer to configure table. */
153     uint8_t configsNumber;                      /*!< Number of configurations. */
154     notifier_callback_config_t *callbacksTable; /*!< Pointer to callback table. */
155     uint8_t callbacksNumber;                    /*!< Maximum number of callback configurations. */
156     uint8_t errorCallbackIndex;                 /*!< Index of callback returns error. */
157     uint8_t currentConfigIndex;                 /*!< Index of current configuration.  */
158     notifier_user_function_t userFunction;      /*!< User function. */
159     void *userData;                             /*!< User data passed to user function. */
160 } notifier_handle_t;
161 
162 /*******************************************************************************
163  * API
164  ******************************************************************************/
165 
166 #if defined(__cplusplus)
167 extern "C" {
168 #endif
169 
170 /*!
171  * @brief Creates a Notifier handle.
172  *
173  * @param notifierHandle A pointer to the notifier handle.
174  * @param configs A pointer to an array with references to all configurations which is handled by the Notifier.
175  * @param configsNumber Number of configurations. Size of the configuration array.
176  * @param callbacks A pointer to an array of callback configurations.
177  *  If there are no callbacks to register during Notifier initialization, use NULL value.
178  * @param callbacksNumber Number of registered callbacks. Size of the callbacks array.
179  * @param userFunction User function.
180  * @param userData User data passed to user function.
181  * @return An error Code or kStatus_Success.
182  */
183 status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle,
184                                notifier_user_config_t **configs,
185                                uint8_t configsNumber,
186                                notifier_callback_config_t *callbacks,
187                                uint8_t callbacksNumber,
188                                notifier_user_function_t userFunction,
189                                void *userData);
190 
191 /*!
192  * @brief Switches the configuration according to a pre-defined structure.
193  *
194  * This function sets the system to the target configuration. Before transition,
195  * the Notifier sends notifications to all callbacks registered to the callback table.
196  * Callbacks are invoked in the following order: All registered callbacks are notified
197  * ordered by index in the callbacks array. The same order is used for before and after switch notifications.
198  * The notifications before the configuration switch can be used to obtain confirmation about
199  * the change from registered callbacks. If any registered callback denies the
200  * configuration change, further execution of this function depends on the notifier policy: the
201  * configuration change is either forced (kNOTIFIER_PolicyForcible) or exited (kNOTIFIER_PolicyAgreement).
202  * When configuration change is forced, the result of the before switch notifications are ignored. If an
203  * agreement is required, if any callback returns an error code, further notifications
204  * before switch notifications are cancelled and all already notified callbacks are re-invoked.
205  * The index of the callback which returned error code during pre-switch notifications is stored
206  * (any error codes during callbacks re-invocation are ignored) and NOTIFIER_GetErrorCallback() can be used to get it.
207  * Regardless of the policies, if any callback returns an error code, an error code indicating in which phase
208  * the error occurred is returned when NOTIFIER_SwitchConfig() exits.
209  * @param notifierHandle pointer to notifier handle
210  * @param configIndex Index of the target configuration.
211  * @param policy            Transaction policy, kNOTIFIER_PolicyAgreement or kNOTIFIER_PolicyForcible.
212  *
213  * @return An error code or kStatus_Success.
214  *
215  */
216 status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy);
217 
218 /*!
219  * @brief This function returns the last failed notification callback.
220  *
221  * This function returns an index of the last callback that failed during the configuration switch while
222  * the last NOTIFIER_SwitchConfig() was called. If the last NOTIFIER_SwitchConfig() call ended successfully
223  * value equal to callbacks number is returned. The returned value represents an index in the array of
224  * static call-backs.
225  *
226  * @param notifierHandle Pointer to the notifier handle
227  * @return Callback Index of the last failed callback or value equal to callbacks count.
228  */
229 uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle);
230 
231 #if defined(__cplusplus)
232 }
233 #endif /* __cplusplus */
234 
235 /*! @}*/
236 
237 #endif /* _FSL_NOTIFIER_H_ */
238