1 /*
2  * Copyright 2020-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #ifndef FSL_IMU_H_
8 #define FSL_IMU_H_
9 
10 #include "fsl_common.h"
11 
12 /*!
13  * @addtogroup imu
14  * @{
15  */
16 
17 /******************************************************************************
18  * Definitions
19  *****************************************************************************/
20 
21 /*! @name Driver version */
22 /*! @{ */
23 /*! @brief IMU driver version. */
24 #define FSL_IMU_DRIVER_VERSION (MAKE_VERSION(2, 1, 1))
25 /*! @} */
26 
27 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK      (1UL)
28 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK (1UL << 1U)
29 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK        (1UL << 2U)
30 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK       (1UL << 3U)
31 #define IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK            (0x1FUL << 4U)
32 #define IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT           (4U)
33 #define IMU_MSG_FIFO_STATUS_WR_PTR_MASK               (0xFUL << 16U)
34 #define IMU_MSG_FIFO_STATUS_WR_PTR_SHIFT              (16U)
35 #define IMU_MSG_FIFO_STATUS_RD_PTR_MASK               (0xFUL << 20U)
36 #define IMU_MSG_FIFO_STATUS_RD_PTR_SHIFT              (20U)
37 
38 #define IMU_MSG_FIFO_CNTL_MSG_RDY_INT_CLR_MASK      (1UL << 0U)
39 #define IMU_MSG_FIFO_CNTL_SP_AV_INT_CLR_MASK        (1UL << 1U)
40 #define IMU_MSG_FIFO_CNTL_FIFO_FLUSH_MASK           (1UL << 16U)
41 #define IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK         (1UL << 17U)
42 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_MASK  (0x0FUL << 20U)
43 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_SHIFT (20U)
44 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK(x)    (((uint32_t)(x)) << 20U)
45 
46 /* Write message directly. */
47 #define IMU_WR_MSG(link, msg) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->WR_MSG = (msg))
48 
49 /* Read message directly. */
50 #define IMU_RD_MSG(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->RD_MSG)
51 
52 /* Check whether RX FIFO is locked. */
53 #define IMU_RX_FIFO_LOCKED(link) \
54     (0UL !=                      \
55      (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
56 
57 /* Check whether TX FIFO is locked. */
58 #define IMU_TX_FIFO_LOCKED(link) \
59     (0UL !=                      \
60      (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
61 
62 /* Check whether TX FIFO is almost full. */
63 #define IMU_TX_FIFO_ALMOST_FULL(link)                                           \
64     (0UL != (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & \
65              IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK))
66 
67 /*! @brief Get Rx FIFO empty status. */
68 #define IMU_RX_FIFO_EMPTY(link) \
69     (0UL !=                     \
70      (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK))
71 
72 /* Lock the TX FIFO. */
73 #define IMU_LOCK_TX_FIFO(link) \
74     (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK)
75 
76 /* Unlock the TX FIFO. */
77 #define IMU_UNLOCK_TX_FIFO(link) \
78     (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL &= ~IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK)
79 
80 /* Get message count in RX FIFO. */
81 #define IMU_RX_FIFO_MSG_COUNT(link)                                                                              \
82     ((((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> \
83      IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
84 
85 /* Get message count in TX FIFO. */
86 #define IMU_TX_FIFO_MSG_COUNT(link)                                                                             \
87     ((((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> \
88      IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
89 
90 /* Get message count from RX FIFO status register value. */
91 #define IMU_RX_FIFO_MSG_COUNT_FROM_STATUS(rxFifoStatus) \
92     (((rxFifoStatus)&IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
93 
94 /* Get RX FIFO lock status from RX FIFO status register value. */
95 #define IMU_RX_FIFO_LOCKED_FROM_STATUS(rxFifoStatus) (0UL != ((rxFifoStatus)&IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
96 
97 /* TX FIFO status register. */
98 #define IMU_TX_FIFO_STATUS(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS)
99 
100 /* RX FIFO status register. */
101 #define IMU_RX_FIFO_STATUS(link) (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS)
102 
103 /* RX FIFO control register. */
104 #define IMU_TX_FIFO_CNTL(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL)
105 
106 /*! @brief IMU driver returned error value. */
107 #define IMU_ERR_TX_FIFO_LOCKED (-1L)
108 
109 /*! @brief Maximum message numbers in FIFO. */
110 #define IMU_MSG_FIFO_MAX_COUNT 16U
111 
112 /*! @brief Maximum message FIFO warter mark. */
113 #define IMU_MAX_MSG_FIFO_WATER_MARK (IMU_MSG_FIFO_MAX_COUNT - 1U)
114 
115 /* IMP: ICC_MAX_MSG_CNT should be power of 2 */
116 #define IMU_FIFO_SW_WRAPAROUND(ptr) ((ptr) & (IMU_MSG_FIFO_MAX_COUNT - 1U))
117 
118 #define IMU_WR_PTR(link)                                                                   \
119     IMU_FIFO_SW_WRAPAROUND((IMU_TX_FIFO_STATUS(link) & IMU_MSG_FIFO_STATUS_WR_PTR_MASK) >> \
120                            IMU_MSG_FIFO_STATUS_WR_PTR_SHIFT)
121 
122 #define IMU_RD_PTR(link)                                                                   \
123     IMU_FIFO_SW_WRAPAROUND((IMU_RX_FIFO_STATUS(link) & IMU_MSG_FIFO_STATUS_RD_PTR_MASK) >> \
124                            IMU_MSG_FIFO_STATUS_RD_PTR_SHIFT)
125 
126 /*!
127  * @brief IMU status flags.
128  * @anchor _imu_status_flags
129  */
130 enum _imu_status_flags
131 {
132     kIMU_TxFifoEmpty      = IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK,
133     kIMU_TxFifoFull       = IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK,
134     kIMU_TxFifoAlmostFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK,
135     kIMU_TxFifoLocked     = IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK,
136     kIMU_RxFifoEmpty      = IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK << 8U,
137     kIMU_RxFifoFull       = IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK << 8U,
138     kIMU_RxFifoAlmostFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK << 8U,
139     kIMU_RxFifoLocked     = IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK << 8U,
140 };
141 
142 /*!
143  * @brief IMU interrupt.
144  * @anchor _imu_interrupts
145  */
146 enum _imu_interrupts
147 {
148     kIMU_RxMsgReadyInterrupt           = IMU_MSG_FIFO_CNTL_MSG_RDY_INT_CLR_MASK,
149     kIMU_TxFifoSpaceAvailableInterrupt = IMU_MSG_FIFO_CNTL_SP_AV_INT_CLR_MASK,
150 };
151 
152 /*! @brief IMU register structure. */
153 typedef struct
154 {
155     volatile uint32_t WR_MSG;
156     const volatile uint32_t RD_MSG;
157     const volatile uint32_t MSG_FIFO_STATUS;
158     volatile uint32_t MSG_FIFO_CNTL;
159     const volatile uint32_t RD_MSG_DBG;
160 } IMU_Type;
161 
162 /*******************************************************************************
163  * API
164  ******************************************************************************/
165 
166 #if defined(__cplusplus)
167 extern "C" {
168 #endif
169 
170 /*!
171  * @name IMU initialization.
172  * @{
173  */
174 
175 /*!
176  * @brief Initializes the IMU module.
177  *
178  * This function sets IMU to initialized state, including:
179  *
180  *   - Flush the send FIFO.
181  *   - Unlock the send FIFO.
182  *   - Set the water mark to (IMU_MAX_MSG_FIFO_WATER_MARK)
183  *   - Flush the read FIFO.
184  *
185  * @param link IMU link.
186  * @retval kStatus_InvalidArgument The link is invalid.
187  * @retval kStatus_Success Initialized successfully.
188  */
189 status_t IMU_Init(imu_link_t link);
190 
191 /*!
192  * @brief De-initializes the IMU module.
193  *
194  * @param link IMU link.
195  */
196 void IMU_Deinit(imu_link_t link);
197 
198 /*! @} */
199 
200 /*!
201  * @name IMU Message
202  * @{
203  */
204 
205 /*!
206  * @brief Write one message to TX FIFO.
207  *
208  * This function writes message to the TX FIFO, user need to make sure
209  * there is empty space in the TX FIFO, and TX FIFO not locked before
210  * calling this function.
211  *
212  * @param link IMU link.
213  * @param msg The message to send.
214  */
IMU_WriteMsg(imu_link_t link,uint32_t msg)215 static inline void IMU_WriteMsg(imu_link_t link, uint32_t msg)
216 {
217     IMU_WR_MSG(link, msg);
218 }
219 
220 /*!
221  * @brief Read one message from RX FIFO.
222  *
223  * User need to make sure there is available message in the RX FIFO.
224  *
225  * @param link IMU link.
226  * @return The message.
227  */
IMU_ReadMsg(imu_link_t link)228 static inline uint32_t IMU_ReadMsg(imu_link_t link)
229 {
230     return IMU_RD_MSG(link);
231 }
232 
233 /*!
234  * @brief Blocking to send messages.
235  *
236  * This function blocks until all messages have been filled to TX FIFO.
237  *
238  * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
239  * - If TX FIFO not locked, this function waits the available empty slot in TX FIFO,
240  *   and fills the message to TX FIFO.
241  * - To lock TX FIFO after filling all messages, set @p lockSendFifo to true.
242  *
243  * @param link IMU link.
244  * @param msgs The messages to send.
245  * @param msgCount Message count, one message is a 32-bit word.
246  * @param lockSendFifo If set to true, the TX FIFO is locked after all messages filled to TX FIFO.
247  * @return If TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED,
248  * otherwise, this function returns the actual message count sent out, it equals @p msgCount
249  * because this function is blocking function, it returns until all messages have been
250  * filled into TX FIFO.
251  */
252 int32_t IMU_SendMsgsBlocking(imu_link_t link, const uint32_t *msgs, int32_t msgCount, bool lockSendFifo);
253 
254 /*!
255  * @brief Try to send messages.
256  *
257  * This function is similar with @ref IMU_SendMsgsBlocking, the difference is,
258  * this function tries to send as many as possible, if there is not enough
259  * empty slot in TX FIFO, this function fills messages to available empty slots
260  * and returns how many messages have been filled.
261  *
262  * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
263  * - If TX FIFO not locked, this function fills messages to TX FIFO empty slot,
264  *   and returns how many messages have been filled.
265  * - If @p lockSendFifo is set to true, TX FIFO is locked after all messages have
266  *   been filled to TX FIFO. In other word, TX FIFO is locked if the function
267  *   return value equals @p msgCount, when @p lockSendFifo set to true.
268  *
269  * @param link IMU link.
270  * @param msgs The messages to send.
271  * @param msgCount Message count, one message is a 32-bit word.
272  * @param lockSendFifo If set to true, the TX FIFO is locked after all messages filled to TX FIFO.
273  * @return If TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED,
274  * otherwise, this function returns the actual message count sent out.
275  */
276 int32_t IMU_TrySendMsgs(imu_link_t link, const uint32_t *msgs, int32_t msgCount, bool lockSendFifo);
277 
278 /*!
279  * @brief Try to receive messages.
280  *
281  * This function tries to read messages from RX FIFO. It reads the messages already
282  * exists in RX FIFO and returns the actual read count.
283  *
284  * - If the RX FIFO has enough messages, this function reads the messages and returns.
285  * - If the RX FIFO does not have enough messages, this function the messages in RX FIFO
286  *   and returns the actual read count.
287  * - During message reading, if RX FIFO is empty and locked, in this case peer CPU will not
288  *   send message until current CPU send lock ack message. Then this function
289  *   returns the message count actually received, and sets @p needAckLock to true
290  *   to inform upper layer.
291  *
292  * @param link IMU link.
293  * @param msgs The buffer to read messages.
294  * @param desiredMsgCount Desired read count, one message is a 32-bit word.
295  * @param needAckLock Upper layer should always check this value. When this is
296  * set to true by this function, upper layer should send lock ack message to peer CPU.
297  * @return Count of messages actually received.
298  */
299 int32_t IMU_TryReceiveMsgs(imu_link_t link, uint32_t *msgs, int32_t desiredMsgCount, bool *needAckLock);
300 
301 /*!
302  * @brief Blocking to receive messages.
303  *
304  * This function blocks until all desired messages have been received or the RX FIFO
305  * is locked.
306  *
307  * - If the RX FIFO has enough messages, this function reads the messages and returns.
308  * - If the RX FIFO does not have enough messages, this function waits for the new
309  *   messages.
310  * - During message reading, if RX FIFO is empty and locked, in this case peer CPU will not
311  *   send message until current CPU send lock ack message. Then this function
312  *   returns the message count actually received, and sets @p needAckLock to true
313  *   to inform upper layer.
314  *
315  * @param link IMU link.
316  * @param msgs The buffer to read messages.
317  * @param desiredMsgCount Desired read count, one message is a 32-bit word.
318  * @param needAckLock Upper layer should always check this value. When this is
319  * set to true by this function, upper layer should send lock ack message to peer CPU.
320  * @return Count of messages actually received.
321  */
322 int32_t IMU_ReceiveMsgsBlocking(imu_link_t link, uint32_t *msgs, int32_t desiredMsgCount, bool *needAckLock);
323 
324 /*!
325  * @brief Blocking to send messages pointer.
326  *
327  * Compared with @ref IMU_SendMsgsBlocking, this function fills message pointer
328  * to TX FIFO, but not the message content.
329  *
330  * This function blocks until the message pointer is filled to TX FIFO.
331  *
332  * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
333  * - If TX FIFO not locked, this function waits the available empty slot in TX FIFO,
334  *   and fills the message pointer to TX FIFO.
335  * - To lock TX FIFO after filling the message pointer, set @p lockSendFifo to true.
336  *
337  * @param link IMU link.
338  * @param msgPtr The buffer pointer to message to send.
339  * @param needAckLock Upper layer should always check this value. When this is
340  * set to true by this function, upper layer should send lock ack message to peer CPU.
341  * @retval 0 The message pointer set successfully.
342  * @retval IMU_ERR_TX_FIFO_LOCKED The TX FIFO is locked, send failed.
343  */
344 int32_t IMU_SendMsgPtrBlocking(imu_link_t link, uint32_t msgPtr, bool lockSendFifo);
345 
346 /*!
347  * @brief Lock or unlock the TX FIFO.
348  *
349  * @param link IMU link.
350  * @param lock Use true to lock the FIFO, use false to unlock.
351  */
IMU_LockSendFifo(imu_link_t link,bool lock)352 static inline void IMU_LockSendFifo(imu_link_t link, bool lock)
353 {
354     if (lock)
355     {
356         ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK;
357     }
358     else
359     {
360         ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL &= ~IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK;
361     }
362 }
363 
364 /*!
365  * @brief Flush the send FIFO.
366  *
367  * Flush all messages in send FIFO.
368  *
369  * @param link IMU link.
370  */
371 void IMU_FlushSendFifo(imu_link_t link);
372 
373 /*!
374  * @brief Set send FIFO warter mark.
375  *
376  * The warter mark must be less than IMU_MAX_MSG_FIFO_WATER_MARK,
377  * i.e. 0 < waterMark <= IMU_MAX_MSG_FIFO_WATER_MARK.
378  *
379  * @param link IMU link.
380  * @param waterMark Send FIFO warter mark.
381  */
IMU_SetSendFifoWaterMark(imu_link_t link,uint8_t waterMark)382 static inline void IMU_SetSendFifoWaterMark(imu_link_t link, uint8_t waterMark)
383 {
384     uint32_t reg = ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL;
385 
386     reg &= ~IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_MASK;
387     reg |= IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK(waterMark);
388 
389     ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL = reg;
390 }
391 
392 /*!
393  * @brief Get the message count in receive FIFO.
394  *
395  * @param link IMU link.
396  * @return The message count in receive FIFO.
397  */
IMU_GetReceivedMsgCount(imu_link_t link)398 static inline uint32_t IMU_GetReceivedMsgCount(imu_link_t link)
399 {
400     return IMU_RX_FIFO_MSG_COUNT(link);
401 }
402 
403 /*!
404  * @brief Get the empty slot in send FIFO.
405  *
406  * @param link IMU link.
407  * @return The empty slot count in send FIFO.
408  */
IMU_GetSendFifoEmptySpace(imu_link_t link)409 static inline uint32_t IMU_GetSendFifoEmptySpace(imu_link_t link)
410 {
411     return IMU_MSG_FIFO_MAX_COUNT - IMU_TX_FIFO_MSG_COUNT(link) - 1U;
412 }
413 
414 /*! @} */
415 
416 /*!
417  * @name Status and Interrupt.
418  * @{
419  */
420 
421 /*!
422  * @brief Gets the IMU status flags.
423  *
424  * @param link IMU link.
425  * @return Bit mask of the IMU status flags, see @ref _imu_status_flags.
426  */
427 uint32_t IMU_GetStatusFlags(imu_link_t link);
428 
429 /*!
430  * @brief Clear the IMU IRQ
431  *
432  * @param link IMU link.
433  * @param mask Bit mask of the interrupts to clear, see @ref _imu_interrupts.
434  */
IMU_ClearPendingInterrupts(imu_link_t link,uint32_t mask)435 static inline void IMU_ClearPendingInterrupts(imu_link_t link, uint32_t mask)
436 {
437     ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= mask;
438 }
439 
440 /*! @} */
441 
442 #if defined(__cplusplus)
443 }
444 #endif /*_cplusplus*/
445 /*! @} */
446 
447 #endif /* FSL_IMU_H_*/
448