1 /* -------------------------------------------------------------------------- */
2 /*                           Copyright 2021-2024 NXP                          */
3 /*                            All rights reserved.                            */
4 /*                    SPDX-License-Identifier: BSD-3-Clause                   */
5 /* -------------------------------------------------------------------------- */
6 
7 /* -------------------------------------------------------------------------- */
8 /*                                  Includes                                  */
9 /* -------------------------------------------------------------------------- */
10 
11 #include "fsl_common.h"
12 #include "fsl_adapter_rpmsg.h"
13 #include "fwk_platform_ble.h"
14 #include "fwk_platform.h"
15 #include "fwk_platform_ics.h"
16 
17 #ifdef SERIAL_BTSNOOP
18 #include "sbtsnoop.h"
19 #endif
20 
21 /* -------------------------------------------------------------------------- */
22 /*                               Private macros                               */
23 /* -------------------------------------------------------------------------- */
24 
25 #ifndef PLATFORM_BLE_HCI_TIMEOUT_MS
26 #define PLATFORM_BLE_HCI_TIMEOUT_MS 500U
27 #endif
28 
29 #define HciCommand(opCodeGroup, opCodeCommand) \
30     (((uint16_t)(opCodeGroup) & (uint16_t)0x3FU) << (uint16_t)SHIFT10) | (uint16_t)((opCodeCommand)&0x3FFU)
31 
32 /* Check if __st is negative,  if true, apply 4 bits shift and add new __error_code,
33     assert in debug and break
34    Shall be called in a do while(0) bracket */
35 #define CHECK_AND_RAISE_ERROR(__st, __error_code)                                                  \
36     {                                                                                              \
37         if ((__st) < 0)                                                                            \
38         {                                                                                          \
39             assert(0);                                                                             \
40             (__st) = -(int)((uint32_t)(((uint32_t)(-(__st)) << 4) | (uint32_t)(-(__error_code)))); \
41             break;                                                                                 \
42         }                                                                                          \
43     }
44 
45 /* Raise error with status update , shift previous status by 4 bits and OR with new error code.
46  * the returned status will be negative */
47 #define RAISE_ERROR(__st, __error_code) -(int)((uint32_t)(((uint32_t)(__st) << 4) | (uint32_t)(__error_code)));
48 
49 /* -------------------------------------------------------------------------- */
50 /*                         Private memory declarations                        */
51 /* -------------------------------------------------------------------------- */
52 
53 /* RPMSG related variables */
54 
55 /* Define hci serial manager handle*/
56 static RPMSG_HANDLE_DEFINE(hciRpmsgHandle);
57 
58 /*hci rpmsg configuration*/
59 static const hal_rpmsg_config_t hciRpmsgConfig = {
60     .local_addr  = 40,
61     .remote_addr = 30,
62 };
63 
64 static void (*hci_rx_callback)(uint8_t packetType, uint8_t *data, uint16_t len);
65 
66 static bool is_initialized = false;
67 /* -------------------------------------------------------------------------- */
68 /*                         Public memory declarations                        */
69 /* -------------------------------------------------------------------------- */
70 extern PLATFORM_ErrorCallback_t pfPlatformErrorCallback;
71 
72 /* -------------------------------------------------------------------------- */
73 /*                             Private prototypes                             */
74 /* -------------------------------------------------------------------------- */
75 
76 /*!
77  * \brief Init HCI link with BLE controller
78  *
79  */
80 static int PLATFORM_InitHciLink(void);
81 
82 /*!
83  * \brief RPMSG Rx callback used to receive HCI messages from Controller
84  *
85  * \param[in] param Usually NULL
86  * \param[in] data pointer to data buffer
87  * \param[in] len size of the data
88  * \return hal_rpmsg_return_status_t tells RPMSG to free or hold the buffer
89  */
90 static hal_rpmsg_return_status_t PLATFORM_HciRpmsgRxCallback(void *param, uint8_t *data, uint32_t len);
91 
92 /* -------------------------------------------------------------------------- */
93 /*                              Public functions                              */
94 /* -------------------------------------------------------------------------- */
95 
PLATFORM_InitBle(void)96 int PLATFORM_InitBle(void)
97 {
98     int status = 0;
99 
100     do
101     {
102         if (is_initialized)
103         {
104             status = 1;
105             break;
106         }
107         /* When waking up from deep power down mode (following Deep power down reset), it is necessary to release IO
108          * isolations. this is usually done in Low power initialization but it is necessay also
109          * to be done if the Application does not support low power */
110         (void)PLATFORM_ClearIoIsolationFromLowPower();
111 
112         /* Init NBU domain and configure RFMC module
113          * CM3 is still in reset and will be released by MCMGR_StartCore during RPMSG init */
114         status = PLATFORM_InitNbu();
115         CHECK_AND_RAISE_ERROR(status, -2);
116 
117         /* Init of the multicore*/
118         status = PLATFORM_InitMulticore();
119         CHECK_AND_RAISE_ERROR(status, -3);
120 
121         /* Init HCI link with NBU */
122         status = PLATFORM_InitHciLink();
123         CHECK_AND_RAISE_ERROR(status, -4);
124 
125         /* Initialize PLatform Service intercore channel
126          *  Used to retrieve NBU version information but not retricted to this sole use.
127          */
128         status = PLATFORM_FwkSrvInit();
129         CHECK_AND_RAISE_ERROR(status, -5);
130 
131 #if !defined(FPGA_SUPPORT) || (FPGA_SUPPORT == 0)
132         /* Send chip revision (A0 or A1) to NBU */
133         status = PLATFORM_SendChipRevision();
134         CHECK_AND_RAISE_ERROR(status, -6);
135 #endif
136 
137     } while (false);
138 
139     /* Error callback set by PLATFORM_RegisterBleErrorCallback() */
140     if ((status < 0) && (pfPlatformErrorCallback != NULL))
141     {
142         pfPlatformErrorCallback(PLATFORM_INIT_BLE_ID, status);
143     }
144 
145     is_initialized = true;
146     return status;
147 }
148 
PLATFORM_SetHciRxCallback(void (* callback)(uint8_t packetType,uint8_t * data,uint16_t len))149 int PLATFORM_SetHciRxCallback(void (*callback)(uint8_t packetType, uint8_t *data, uint16_t len))
150 {
151     int ret = 0;
152 
153     hci_rx_callback = callback;
154 
155     return ret;
156 }
157 
PLATFORM_SendHciMessage(uint8_t * msg,uint32_t len)158 int PLATFORM_SendHciMessage(uint8_t *msg, uint32_t len)
159 {
160     int status = 0;
161     do
162     {
163         /* Wake up controller before sending the message */
164         PLATFORM_RemoteActiveReq();
165 
166         /* Send HCI Packet through RPMSG channel */
167         status = (int)HAL_RpmsgSendTimeout(hciRpmsgHandle, msg, len, PLATFORM_BLE_HCI_TIMEOUT_MS);
168         if (status != 0)
169         {
170             status = RAISE_ERROR(status, 1);
171             break;
172         }
173 
174 #ifdef SERIAL_BTSNOOP
175         uint16_t lg = (uint16_t)len - 1U;
176         if (lg > 0U)
177         {
178             sbtsnoop_write_hci_pkt(msg[0U], 0U, &msg[1], lg);
179         }
180 #endif
181 
182     } while (false);
183 
184     /* Release wake up request */
185     PLATFORM_RemoteActiveRel();
186 
187     /* Error callback set by PLATFORM_RegisterBleErrorCallback() */
188     if ((status != 0) && (pfPlatformErrorCallback != NULL))
189     {
190         pfPlatformErrorCallback(PLATFORM_SEND_HCI_MESSAGE_ID, status);
191     }
192 
193     return status;
194 }
195 
PLATFORM_TerminateBle(void)196 int PLATFORM_TerminateBle(void)
197 {
198     return 0;
199 }
200 
PLATFORM_StartHci(void)201 int PLATFORM_StartHci(void)
202 {
203     return 0;
204 }
205 
206 /* -------------------------------------------------------------------------- */
207 /*                              Private functions                             */
208 /* -------------------------------------------------------------------------- */
209 
PLATFORM_InitHciLink(void)210 static int PLATFORM_InitHciLink(void)
211 {
212     int                status = 0;
213     hal_rpmsg_config_t hci_rpmsg_config;
214     hal_rpmsg_status_t hci_rpmsg_status;
215 
216     hci_rpmsg_config = hciRpmsgConfig;
217 
218     hci_rpmsg_status = HAL_RpmsgInit((hal_rpmsg_handle_t)hciRpmsgHandle, &hci_rpmsg_config);
219     if (hci_rpmsg_status != kStatus_HAL_RpmsgSuccess)
220     {
221         assert(0);
222         status = RAISE_ERROR(hci_rpmsg_status, 1);
223     }
224     /* Set RX Callback */
225     else
226     {
227         hci_rpmsg_status =
228             HAL_RpmsgInstallRxCallback((hal_rpmsg_handle_t)hciRpmsgHandle, PLATFORM_HciRpmsgRxCallback, NULL);
229         if (hci_rpmsg_status != kStatus_HAL_RpmsgSuccess)
230         {
231             assert(0);
232             status = RAISE_ERROR(hci_rpmsg_status, 2);
233         }
234     }
235     return status;
236 }
237 
PLATFORM_HciRpmsgRxCallback(void * param,uint8_t * data,uint32_t len)238 static hal_rpmsg_return_status_t PLATFORM_HciRpmsgRxCallback(void *param, uint8_t *data, uint32_t len)
239 {
240     PLATFORM_RemoteActiveReq();
241 
242     if (hci_rx_callback != NULL)
243     {
244         hci_rx_callback(data[0], &data[1], len - 1U);
245     }
246 
247 #ifdef SERIAL_BTSNOOP
248     sbtsnoop_write_hci_pkt(data[0U], 1U, &data[1], len - 1U);
249 #endif
250 
251     PLATFORM_RemoteActiveRel();
252 
253     (void)param;
254 
255     return kStatus_HAL_RL_RELEASE;
256 }
257