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