1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef __MU_IMX_H__
32 #define __MU_IMX_H__
33 
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <assert.h>
37 #include "device_imx.h"
38 
39 /*!
40  * @addtogroup mu_driver
41  * @{
42  */
43 
44 /******************************************************************************
45  * Definitions
46  *****************************************************************************/
47 
48 /*!@brief Bit mask for general purpose interrupt 0 pending. */
49 #define MU_SR_GIP0_MASK (1U<<31U)
50 /*!@brief Bit mask for RX full interrupt 0 pending. */
51 #define MU_SR_RF0_MASK (1U<<27U)
52 /*!@brief Bit mask for TX empty interrupt 0 pending. */
53 #define MU_SR_TE0_MASK (1U<<23U)
54 /*!@brief Bit mask for general purpose interrupt 0 enable. */
55 #define MU_CR_GIE0_MASK (1U<<31U)
56 /*!@brief Bit mask for RX full interrupt 0 enable. */
57 #define MU_CR_RIE0_MASK (1U<<27U)
58 /*!@brief Bit mask for TX empty interrupt 0 enable. */
59 #define MU_CR_TIE0_MASK (1U<<23U)
60 /*!@brief Bit mask to trigger general purpose interrupt 0. */
61 #define MU_CR_GIR0_MASK (1U<<19U)
62 
63 /*!@brief Number of general purpose interrupt. */
64 #define MU_GPn_COUNT (4U)
65 
66 /* Mask for MU_CR_GIRN. When read-modify-write to MU_CR, should
67    pay attention to these bits in case of trigger interrupts by mistake.*/
68 
69 /*! @brief MU status return codes. */
70 typedef enum _mu_status
71 {
72     kStatus_MU_Success      = 0U, /*!< Success.                              */
73     kStatus_MU_TxNotEmpty   = 1U, /*!< TX register is not empty.             */
74     kStatus_MU_RxNotFull    = 2U, /*!< RX register is not full.              */
75     kStatus_MU_FlagPending  = 3U, /*!< Previous flags update pending.        */
76     kStatus_MU_EventPending = 4U, /*!< MU event is pending.                  */
77     kStatus_MU_Initialized  = 5U, /*!< MU driver has initialized previously. */
78     kStatus_MU_IntPending   = 6U, /*!< Previous general interrupt still pending. */
79     kStatus_MU_Failed       = 7U  /*!< Execution failed.                     */
80 } mu_status_t;
81 
82 /*! @brief MU message status. */
83 typedef enum _mu_msg_status
84 {
85     kMuTxEmpty0 = MU_SR_TE0_MASK,        /*!< TX0 empty status.                          */
86     kMuTxEmpty1 = MU_SR_TE0_MASK >> 1U,  /*!< TX1 empty status.                          */
87     kMuTxEmpty2 = MU_SR_TE0_MASK >> 2U,  /*!< TX2 empty status.                          */
88     kMuTxEmpty3 = MU_SR_TE0_MASK >> 3U,  /*!< TX3 empty status.                          */
89     kMuTxEmpty  = kMuTxEmpty0  |
90                   kMuTxEmpty1  |
91                   kMuTxEmpty2  |
92                   kMuTxEmpty3,           /*!< TX empty status.                            */
93 
94     kMuRxFull0  = MU_SR_RF0_MASK,        /*!< RX0 full status.                            */
95     kMuRxFull1  = MU_SR_RF0_MASK >> 1U,  /*!< RX1 full status.                            */
96     kMuRxFull2  = MU_SR_RF0_MASK >> 2U,  /*!< RX2 full status.                            */
97     kMuRxFull3  = MU_SR_RF0_MASK >> 3U,  /*!< RX3 full status.                            */
98     kMuRxFull   = kMuRxFull0   |
99                   kMuRxFull1   |
100                   kMuRxFull2   |
101                   kMuRxFull3,            /*!< RX empty status.                            */
102 
103     kMuGenInt0  = MU_SR_GIP0_MASK,       /*!< General purpose interrupt 0 pending status. */
104     kMuGenInt1  = MU_SR_GIP0_MASK >> 1U, /*!< General purpose interrupt 2 pending status. */
105     kMuGenInt2  = MU_SR_GIP0_MASK >> 2U, /*!< General purpose interrupt 2 pending status. */
106     kMuGenInt3  = MU_SR_GIP0_MASK >> 3U, /*!< General purpose interrupt 3 pending status. */
107     kMuGenInt   = kMuGenInt0    |
108                   kMuGenInt1    |
109                   kMuGenInt2    |
110                   kMuGenInt3,      /*!< General purpose interrupt pending status.   */
111 
112     kMuStatusAll = kMuTxEmpty |
113                    kMuRxFull  |
114                    kMuGenInt,      /*!< All MU status.                              */
115 
116 } mu_msg_status_t;
117 
118 /*! @brief Power mode definition. */
119 typedef enum _mu_power_mode
120 {
121     kMuPowerModeRun  = 0x00U, /*!< Run mode.  */
122     kMuPowerModeWait = 0x01U, /*!< WAIT mode. */
123     kMuPowerModeStop = 0x02U, /*!< STOP mode. */
124     kMuPowerModeDsm  = 0x03U, /*!< DSM mode.  */
125 } mu_power_mode_t;
126 
127 /*******************************************************************************
128  * API
129  ******************************************************************************/
130 
131 #if defined(__cplusplus)
132 extern "C" {
133 #endif
134 
135 /*!
136  * @name Initialization.
137  * @{
138  */
139 /*!
140  * @brief Initializes the MU module to reset state.
141  *        This function sets the MU module control register to its default reset value.
142  *
143  * @param base Register base address for the module.
144  */
MU_Init(MU_Type * base)145 static inline void MU_Init(MU_Type * base)
146 {
147     // Clear GIEn, RIEn, TIEn, GIRn and ABFn.
148     base->CR &= ~(MU_CR_GIEn_MASK | MU_CR_RIEn_MASK | MU_CR_TIEn_MASK | MU_CR_GIRn_MASK | MU_CR_Fn_MASK);
149 }
150 
151 /* @} */
152 
153 /*!
154  * @name Send Messages.
155  * @{
156  */
157 
158 /*!
159  * @brief Try to send a message.
160  *
161  * This function tries to send a message, if the TX register is not empty,
162  * this function returns kStatus_MU_TxNotEmpty.
163  *
164  * @param base Register base address for the module.
165  * @param regIdex  Tx register index.
166  * @param msg      Message to send.
167  * @retval kStatus_MU_Success     Message send successfully.
168  * @retval kStatus_MU_TxNotEmpty  Message not send because TX is not empty.
169  */
170 mu_status_t MU_TrySendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);
171 
172 /*!
173  * @brief Block to send a message.
174  *
175  * This function waits until TX register is empty and send the message.
176  *
177  * @param base Register base address for the module.
178  * @param regIdex  Tx register index.
179  * @param msg      Message to send.
180  */
181 void MU_SendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);
182 
183 /*!
184  * @brief Check TX empty status.
185  *
186  * This function checks the specific transmit register empty status.
187  *
188  * @param base Register base address for the module.
189  * @param index TX register index to check.
190  * @retval true TX register is empty.
191  * @retval false TX register is not empty.
192  */
MU_IsTxEmpty(MU_Type * base,uint32_t index)193 static inline bool MU_IsTxEmpty(MU_Type * base, uint32_t index)
194 {
195     return (bool)(base->SR & (MU_SR_TE0_MASK >> index));
196 }
197 
198 /*!
199  * @brief Enable TX empty interrupt.
200  *
201  * This function enables specific TX empty interrupt.
202  *
203  * @param base Register base address for the module.
204  * @param index TX interrupt index to enable.
205  *
206  * Example:
207    @code
208    // To enable TX0 empty interrupts.
209    MU_EnableTxEmptyInt(MU0_BASE, 0U);
210    @endcode
211  */
MU_EnableTxEmptyInt(MU_Type * base,uint32_t index)212 static inline void MU_EnableTxEmptyInt(MU_Type * base, uint32_t index)
213 {
214     base->CR = (base->CR & ~ MU_CR_GIRn_MASK)   // Clear GIRn
215                          | (MU_CR_TIE0_MASK>>index); // Set TIEn
216 }
217 
218 /*!
219  * @brief Disable TX empty interrupt.
220  *
221  * This function disables specific TX empty interrupt.
222  *
223  * @param base Register base address for the module.
224  * @param disableMask Bitmap of the interrupts to disable.
225  *
226  * Example:
227    @code
228    // To disable TX0 empty interrupts.
229    MU_DisableTxEmptyInt(MU0_BASE, 0U);
230    @endcode
231  */
MU_DisableTxEmptyInt(MU_Type * base,uint32_t index)232 static inline void MU_DisableTxEmptyInt(MU_Type * base, uint32_t index)
233 {
234     base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_TIE0_MASK>>index)); // Clear GIRn , clear TIEn
235 }
236 
237 /* @} */
238 
239 /*!
240  * @name Receive Messages.
241  * @{
242  */
243 
244 /*!
245  * @brief Try to receive a message.
246  *
247  * This function tries to receive a message, if the RX register is not full,
248  * this function returns kStatus_MU_RxNotFull.
249  *
250  * @param base Register base address for the module.
251  * @param regIdex Rx register index.
252  * @param msg Message to receive.
253  * @retval kStatus_MU_Success    Message receive successfully.
254  * @retval kStatus_MU_RxNotFull  Message not received because RX is not full.
255  */
256 mu_status_t MU_TryReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);
257 
258 /*!
259  * @brief Block to receive a message.
260  *
261  * This function waits until RX register is full and receive the message.
262  *
263  * @param base Register base address for the module.
264  * @param regIdex Rx register index.
265  * @param msg Message to receive.
266  */
267 void MU_ReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);
268 
269 /*!
270  * @brief Check RX full status.
271  *
272  * This function checks the specific receive register full status.
273  *
274  * @param base Register base address for the module.
275  * @param index RX register index to check.
276  * @retval true RX register is full.
277  * @retval false RX register is not full.
278  */
MU_IsRxFull(MU_Type * base,uint32_t index)279 static inline bool MU_IsRxFull(MU_Type * base, uint32_t index)
280 {
281     return (bool)(base->SR & (MU_SR_RF0_MASK >> index));
282 }
283 
284 /*!
285  * @brief Enable RX full interrupt.
286  *
287  * This function enables specific RX full interrupt.
288  *
289  * @param base Register base address for the module.
290  * @param index RX interrupt index to enable.
291  *
292  * Example:
293    @code
294    // To enable RX0 full interrupts.
295    MU_EnableRxFullInt(MU0_BASE, 0U);
296    @endcode
297  */
MU_EnableRxFullInt(MU_Type * base,uint32_t index)298 static inline void MU_EnableRxFullInt(MU_Type * base, uint32_t index)
299 {
300     base->CR = (base->CR & ~MU_CR_GIRn_MASK)  // Clear GIRn
301                          | (MU_CR_RIE0_MASK>>index); // Set RIEn
302 }
303 
304 /*!
305  * @brief Disable RX full interrupt.
306  *
307  * This function disables specific RX full interrupt.
308  *
309  * @param base Register base address for the module.
310  * @param disableMask Bitmap of the interrupts to disable.
311  *
312  * Example:
313    @code
314    // To disable RX0 full interrupts.
315    MU_DisableRxFullInt(MU0_BASE, 0U);
316    @endcode
317  */
MU_DisableRxFullInt(MU_Type * base,uint32_t index)318 static inline void MU_DisableRxFullInt(MU_Type * base, uint32_t index)
319 {
320     base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_RIE0_MASK>>index)); // Clear GIRn, clear RIEn
321 }
322 
323 /* @} */
324 
325 /*!
326  * @name General Purpose Interrupt.
327  * @{
328  */
329 
330 /*!
331  * @brief Enable general purpose interrupt.
332  *
333  * This function enables specific general purpose interrupt.
334  *
335  * @param base Register base address for the module.
336  * @param index General purpose interrupt index to enable.
337  *
338  * Example:
339    @code
340    // To enable general purpose interrupts 0.
341    MU_EnableGeneralInt(MU0_BASE, 0U);
342    @endcode
343  */
MU_EnableGeneralInt(MU_Type * base,uint32_t index)344 static inline void MU_EnableGeneralInt(MU_Type * base, uint32_t index)
345 {
346     base->CR = (base->CR & ~MU_CR_GIRn_MASK)  // Clear GIRn
347                          | (MU_CR_GIE0_MASK>>index); // Set GIEn
348 }
349 
350 /*!
351  * @brief Disable general purpose interrupt.
352  *
353  * This function disables specific general purpose interrupt.
354  *
355  * @param base Register base address for the module.
356  * @param index General purpose interrupt index to disable.
357  *
358  * Example:
359    @code
360    // To disable general purpose interrupts 0.
361    MU_DisableGeneralInt(MU0_BASE, 0U);
362    @endcode
363  */
MU_DisableGeneralInt(MU_Type * base,uint32_t index)364 static inline void MU_DisableGeneralInt(MU_Type * base, uint32_t index)
365 {
366     base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_GIE0_MASK>>index));  // Clear GIRn, clear GIEn
367 }
368 
369 /*!
370  * @brief Check specific general purpose interrupt pending flag.
371  *
372  * This function checks the specific general purpose interrupt pending status.
373  *
374  * @param base Register base address for the module.
375  * @param index Index of the general purpose interrupt flag to check.
376  * @retval true General purpose interrupt is pending.
377  * @retval false General purpose interrupt is not pending.
378  */
MU_IsGeneralIntPending(MU_Type * base,uint32_t index)379 static inline bool MU_IsGeneralIntPending(MU_Type * base, uint32_t index)
380 {
381     return (bool)(base->SR & (MU_SR_GIP0_MASK >> index));
382 }
383 
384 /*!
385  * @brief Clear specific general purpose interrupt pending flag.
386  *
387  * This function clears the specific general purpose interrupt pending status.
388  *
389  * @param base Register base address for the module.
390  * @param index Index of the general purpose interrupt flag to clear.
391  */
MU_ClearGeneralIntPending(MU_Type * base,uint32_t index)392 static inline void MU_ClearGeneralIntPending(MU_Type * base, uint32_t index)
393 {
394     base->SR = (MU_SR_GIP0_MASK >> index);
395 }
396 
397 /*!
398  * @brief Trigger specific general purpose interrupt.
399  *
400  * This function triggers specific general purpose interrupt to other core.
401  *
402  * To ensure proper operations, make sure the correspond general purpose
403  * interrupt triggered previously has been accepted by the other core. The
404  * function MU_IsGeneralIntAccepted can be used for this check. If the
405  * previous general interrupt has not been accepted by the other core, this
406  * function does not trigger interrupt actually and returns an error.
407  *
408  * @param base Register base address for the module.
409  * @param index Index of general purpose interrupt to trigger.
410  * @retval kStatus_MU_Success    Interrupt has been triggered successfully.
411  * @retval kStatus_MU_IntPending Previous interrupt has not been accepted.
412  */
413 mu_status_t MU_TriggerGeneralInt(MU_Type * base, uint32_t index);
414 
415 /*!
416  * @brief Check specific general purpose interrupt is accepted or not.
417  *
418  * This function checks whether the specific general purpose interrupt has
419  * been accepted by the other core or not.
420  *
421  * @param base Register base address for the module.
422  * @param index Index of the general purpose interrupt to check.
423  * @retval true  General purpose interrupt is accepted.
424  * @retval false General purpose interrupt is not accepted.
425  */
MU_IsGeneralIntAccepted(MU_Type * base,uint32_t index)426 static inline bool MU_IsGeneralIntAccepted(MU_Type * base, uint32_t index)
427 {
428     return !(bool)(base->CR & (MU_CR_GIR0_MASK >> index));
429 }
430 
431 /* @} */
432 
433 /*!
434  * @name Flags
435  * @{
436  */
437 
438 /*!
439  * @brief Try to set some bits of the 3-bit flag reflect on the other MU side.
440  *
441  * This functions tries to set some bits of the 3-bit flag. If previous flags
442  * update is still pending, this function returns kStatus_MU_FlagPending.
443  *
444  * @param base Register base address for the module.
445  * @retval kStatus_MU_Success     Flag set successfully.
446  * @retval kStatus_MU_FlagPending Previous flag update is pending.
447  */
448 mu_status_t MU_TrySetFlags(MU_Type * base, uint32_t flags);
449 
450 /*!
451  * @brief Set some bits of the 3-bit flag reflect on the other MU side.
452  *
453  * This functions set some bits of the 3-bit flag. If previous flags update is
454  * still pending, this function  blocks and polls to set the flag.
455  *
456  * @param base Register base address for the module.
457  */
458 void MU_SetFlags(MU_Type * base, uint32_t flags);
459 
460 /*!
461  * @brief Checks whether the previous flag update is pending.
462  *
463  * After setting flags, the flags update request is pending until internally
464  * acknowledged. During the pending period, it is not allowed to set flags again.
465  * This function is used to check the pending status, it can be used together
466  * with function MU_TrySetFlags.
467  *
468  * @param base Register base address for the module.
469  * @return True if pending, false if not.
470  */
MU_IsFlagPending(MU_Type * base)471 static inline bool MU_IsFlagPending(MU_Type * base)
472 {
473     return (bool)(base->SR & MU_SR_FUP_MASK);
474 }
475 
476 /*!
477  * @brief Get the current value of the 3-bit flag set by other side.
478  *
479  * This functions gets the current value of the 3-bit flag.
480  *
481  * @param base Register base address for the module.
482  * @return flags Current value of the 3-bit flag.
483  */
MU_GetFlags(MU_Type * base)484 static inline uint32_t MU_GetFlags(MU_Type * base)
485 {
486     return base->SR & MU_SR_Fn_MASK;
487 }
488 
489 /* @} */
490 
491 /*!
492  * @name Misc.
493  * @{
494  */
495 
496 /*!
497  * @brief Get the power mode of the other core.
498  *
499  * This functions gets the power mode of the other core.
500  *
501  * @param base Register base address for the module.
502  * @return powermode Power mode of the other core.
503  */
MU_GetOtherCorePowerMode(MU_Type * base)504 static inline mu_power_mode_t MU_GetOtherCorePowerMode(MU_Type * base)
505 {
506     return (mu_power_mode_t)((base->SR & MU_SR_PM_MASK) >> MU_SR_PM_SHIFT);
507 }
508 
509 /*!
510  * @brief Get the event pending status.
511  *
512  * This functions gets the event pending status. To ensure events have been
513  * posted to the other side before entering STOP mode, verify the
514  * event pending status using this function.
515  *
516  * @param base Register base address for the module.
517  * @retval true  Event is pending.
518  * @retval false Event is not pending.
519  */
MU_IsEventPending(MU_Type * base)520 static inline bool MU_IsEventPending(MU_Type * base)
521 {
522     return (bool)(base->SR & MU_SR_EP_MASK);
523 }
524 
525 /*!
526  * @brief Get the the MU message status.
527  *
528  * This functions gets TX/RX and general purpose interrupt pending status. The
529  * parameter is passed in as bitmask of the status to check.
530  *
531  * @param base Register base address for the module.
532  * @param statusToCheck The status to check, see mu_msg_status_t.
533  * @return Status checked.
534  *
535  * Example:
536    @code
537    // To check TX0 empty status.
538    MU_GetMsgStatus(MU0_BASE, kMuTxEmpty0);
539 
540    // To check all RX full status.
541    MU_GetMsgStatus(MU0_BASE, kMuRxFull);
542 
543    // To check general purpose interrupt 0 and 3 pending status.
544    MU_GetMsgStatus(MU0_BASE, kMuGenInt0 | kMuGenInt3);
545 
546    // To check all status.
547    MU_GetMsgStatus(MU0_BASE, kMuStatusAll);
548 
549    @endcode
550  */
MU_GetMsgStatus(MU_Type * base,uint32_t statusToCheck)551 static inline uint32_t MU_GetMsgStatus(MU_Type * base, uint32_t statusToCheck)
552 {
553     return base->SR & statusToCheck;
554 }
555 
556 /* @} */
557 
558 #if defined(__cplusplus)
559 }
560 #endif
561 
562 /*!
563  * @}
564  */
565 
566 #endif /* __MU_IMX_H__ */
567 /******************************************************************************
568  * EOF
569  *****************************************************************************/
570