1 /*! *********************************************************************************
2 * Copyright 2021-2025 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 ********************************************************************************** */
8
9 #include "EmbeddedTypes.h"
10 #include "PhyInterface.h"
11 #include "Phy.h"
12
13 #include "fsl_adapter_rpmsg.h"
14 #include "fsl_os_abstraction.h"
15 #include "fwk_platform.h"
16 #if defined(HDI_MODE) && (HDI_MODE == 1)
17 #include "hdi.h"
18 #endif
19 #if (defined(HWINIT_DEBUG_DTEST) && (HWINIT_DEBUG_DTEST == 1L))
20 #include "dtest.h"
21 #endif
22
23 #ifdef MEM_USE_ZEPHYR
24 #include <zephyr/kernel.h>
25
26 #define PHY_MSG_Alloc(x) k_malloc(x)
27 #define PHY_MSG_Free(x) k_free(x)
28
29 #else /* MEM_USE_ZEPHYR */
30 #include "fsl_component_messaging.h"
31
32 #define PHY_MSG_Alloc(x) MSG_Alloc(x)
33 #define PHY_MSG_Free(x) MSG_Free(x)
34 #endif /* MEM_USE_ZEPHYR */
35
36 #undef CTX_NO
37 #define CTX_NO 2
38
39 static struct phy_local
40 {
41 uint32_t id;
42
43 PD_MAC_SapHandler_t PD_MAC_SapHandler;
44 PLME_MAC_SapHandler_t PLME_MAC_SapHandler;
45 } phyLocal[CTX_NO];
46
47 static RPMSG_HANDLE_DEFINE(phyRpmsgHandle);
48 static hal_rpmsg_config_t phyRpmsgConfig = {
49 .local_addr = 10,
50 .remote_addr = 20,
51 #if defined(RW610_SERIES)
52 .imuLink = kIMU_LinkCpu2Cpu3
53 #endif
54 };
55
56 static uint8_t wait_phy_rsp = FALSE;
57 static plmeGetReq_t phy_get_rsp;
58
59 static OSA_EVENT_HANDLE_DEFINE(get_event);
60
61 static bool_t phy_intf_init_done = FALSE;
62 static bool_t phy_intf_init_ongoing = FALSE;
63
64
wait_response()65 static void wait_response()
66 {
67 osa_event_flags_t flags;
68 uint32_t dt = osaWaitForever_c;
69
70 if (!OSA_TaskGetCurrentHandle())
71 {
72 /* Current task is valid in OSA_ProcessTasks().
73 There is no check in OSA_EventWait() that current task is valid.
74 For osaWaitNone_c, current task is not used */
75 dt = osaWaitNone_c;
76 }
77
78 /* Wait until NBU delivers result over RPMSG */
79 while (OSA_EventWait(get_event, 1, 1, dt, &flags) != KOSA_StatusSuccess)
80 {}
81
82 /* Clear event as auto clear is not enabled */
83 OSA_EventClear(get_event, 1);
84 }
85
86
PhyRpmsgRxCallback(void * param,uint8_t * data,uint32_t len)87 static hal_rpmsg_return_status_t PhyRpmsgRxCallback(void *param, uint8_t *data, uint32_t len)
88 {
89 (void)param;
90 phyMessageHeader_t *pMsg = (phyMessageHeader_t *)data;
91
92 if (pMsg->msgType == gPlmeGetReq_c)
93 {
94 if (wait_phy_rsp)
95 {
96 phy_get_rsp = ((macToPlmeMessage_t *)pMsg)->msgData.getReq;
97
98 OSA_EventSet(get_event, 1);
99 }
100 return kStatus_HAL_RL_RELEASE;
101 }
102
103 pMsg = (phyMessageHeader_t *)PHY_MSG_Alloc(len);
104 if (!pMsg)
105 {
106 return kStatus_HAL_RL_RELEASE;
107 }
108 memcpy(pMsg, data, len);
109
110 if (pMsg->ctx_id >= CTX_NO)
111 {
112 pMsg->ctx_id = 0;
113 }
114
115 switch(pMsg->msgType)
116 {
117 case gPdDataInd_c:
118 ((pdDataToMacMessage_t *)pMsg)->msgData.dataInd.pPsdu = (uint8_t *)pMsg + sizeof(pdDataToMacMessage_t);
119
120 phyLocal[pMsg->ctx_id].PD_MAC_SapHandler((pdDataToMacMessage_t *)pMsg, pMsg->ctx_id);
121 break;
122
123 case gPdDataCnf_c:
124 ((pdDataToMacMessage_t *)pMsg)->msgData.dataCnf.ackData = (uint8_t *)pMsg + sizeof(pdDataToMacMessage_t);
125
126 phyLocal[pMsg->ctx_id].PD_MAC_SapHandler((pdDataToMacMessage_t *)pMsg, pMsg->ctx_id);
127 break;
128
129 case gPlmeCcaCnf_c:
130 case gPlmeEdCnf_c:
131 case gPlmeSetTRxStateCnf_c:
132 case gPlmeSetCnf_c:
133 case gPlmeTimeoutInd_c:
134 case gPlmeAbortInd_c:
135 phyLocal[pMsg->ctx_id].PLME_MAC_SapHandler((plmeToMacMessage_t *)pMsg, pMsg->ctx_id);
136 break;
137
138 default:
139 PHY_MSG_Free(pMsg);
140 }
141
142 return kStatus_HAL_RL_RELEASE;
143 }
144
Phy_Init(void)145 void Phy_Init(void)
146 {
147 OSA_InterruptDisable();
148
149 if (phy_intf_init_done || phy_intf_init_ongoing)
150 {
151 OSA_InterruptEnable();
152 return;
153 }
154
155 phy_intf_init_ongoing = TRUE;
156
157 OSA_InterruptEnable();
158
159 if (HAL_RpmsgInit((hal_rpmsg_handle_t)phyRpmsgHandle, &phyRpmsgConfig) != kStatus_HAL_RpmsgSuccess)
160 {
161 assert(0);
162 return;
163 }
164
165 if (HAL_RpmsgInstallRxCallback((hal_rpmsg_handle_t)phyRpmsgHandle, PhyRpmsgRxCallback, NULL) != kStatus_HAL_RpmsgSuccess)
166 {
167 assert(0);
168 return;
169 }
170
171 /* plmeEventHandle with 0 auto clear to allow the task to run after flags have been set */
172 OSA_EventCreate((osa_event_handle_t)get_event, 0);
173
174 /* Configure DTEST signals for debug */
175 #if (defined(HWINIT_DEBUG_DTEST) && (HWINIT_DEBUG_DTEST == 1L))
176 dtest_init(DTEST0 | DTEST1 | DTEST2 | DTEST3 | DTEST4 | DTEST5 | DTEST6 | DTEST7 | DTEST8 | DTEST9 | DTEST10 | DTEST11 | DTEST12 | DTEST13 );
177 dtest_select(0x00); /* Place selftest waveform onto DTEST ports */
178 #endif
179
180 phy_intf_init_done = TRUE;
181 }
182
183 /*! *********************************************************************************
184 * \brief This function registers the MAC PD and PLME SAP handlers
185 *
186 * \param[in] pPD_MAC_SapHandler Pointer to the MAC PD handler function
187 * \param[in] pPLME_MAC_SapHandler Pointer to the MAC PLME handler function
188 * \param[in] instanceId The instance of the PHY
189 *
190 * \return The status of the operation.
191 *
192 ********************************************************************************** */
Phy_RegisterSapHandlers(PD_MAC_SapHandler_t pPD_MAC_SapHandler,PLME_MAC_SapHandler_t pPLME_MAC_SapHandler,instanceId_t instanceId)193 void Phy_RegisterSapHandlers(PD_MAC_SapHandler_t pPD_MAC_SapHandler,
194 PLME_MAC_SapHandler_t pPLME_MAC_SapHandler,
195 instanceId_t instanceId)
196 {
197 if (!phy_intf_init_done)
198 {
199 return;
200 }
201
202 if (instanceId >= CTX_NO)
203 {
204 instanceId = 0;
205 }
206
207 phyLocal[instanceId].PD_MAC_SapHandler = pPD_MAC_SapHandler;
208 phyLocal[instanceId].PLME_MAC_SapHandler = pPLME_MAC_SapHandler;
209 }
210
211 /*! *********************************************************************************
212 * \brief This is the PLME SAP message handler
213 *
214 * \param[in] pMsg Pointer to the PLME request message
215 * \param[in] instanceId The instance of the PHY
216 *
217 * \return phyStatus_t The status of the operation.
218 *
219 ********************************************************************************** */
MAC_PLME_SapHandler(macToPlmeMessage_t * pMsg,instanceId_t phyInstance)220 phyStatus_t MAC_PLME_SapHandler(macToPlmeMessage_t *pMsg, instanceId_t phyInstance)
221 {
222 phyStatus_t ret = gPhySuccess_c;
223 osa_event_flags_t flags;
224
225 if (!phy_intf_init_done)
226 {
227 return gPhyInvalidParameter_c;
228 }
229
230 PLATFORM_RemoteActiveReq();
231
232 do
233 {
234 if (phyInstance >= CTX_NO)
235 {
236 phyInstance = 0;
237 }
238
239 pMsg->ctx_id = phyInstance;
240
241 /* Bind Event with current task (main_task usually) in case RPMSG response is faster than
242 * OSA_EventWait in the loop below.
243 */
244 if (pMsg->msgType == gPlmeGetReq_c)
245 {
246 phy_get_rsp.PibAttributeValue = 0;
247
248 OSA_EventWait(get_event, 1, 1, osaWaitNone_c, &flags);
249 wait_phy_rsp = TRUE;
250 }
251
252 #if defined(HDI_MODE) && (HDI_MODE == 1)
253 if ((pMsg->msgType == gPlmeSetReq_c) && (pMsg->msgData.setReq.PibAttribute == gPhyPibCurrentChannel_c))
254 {
255 if (pMsg->msgData.setReq.PibAttribute == gPhyPibCurrentChannel_c)
256 {
257 HDI_SendChannelSwitchCmd((uint32_t)pMsg->msgData.setReq.PibAttributeValue);
258 }
259 }
260 #endif
261
262 if (HAL_RpmsgSend((hal_rpmsg_handle_t)phyRpmsgHandle, (uint8_t *)pMsg, sizeof(macToPlmeMessage_t)) != kStatus_HAL_RpmsgSuccess)
263 {
264 ret = gPhyBusy_c;
265 break;
266 }
267
268 if (pMsg->msgType == gPlmeGetReq_c)
269 {
270 wait_response();
271 wait_phy_rsp = FALSE;
272
273 pMsg->msgData.getReq.PibAttributeValue = phy_get_rsp.PibAttributeValue;
274 }
275 } while(0);
276
277 wait_phy_rsp = FALSE;
278 PLATFORM_RemoteActiveRel();
279
280 return ret;
281 }
282
283 /*! *********************************************************************************
284 * \brief This is the PD SAP message handler
285 *
286 * \param[in] pMsg Pointer to the PD request message
287 * \param[in] instanceId The instance of the PHY
288 *
289 * \return The status of the operation.
290 *
291 ********************************************************************************** */
MAC_PD_SapHandler(macToPdDataMessage_t * pMsg,instanceId_t phyInstance)292 phyStatus_t MAC_PD_SapHandler(macToPdDataMessage_t *pMsg, instanceId_t phyInstance)
293 {
294 uint32_t len = sizeof(macToPdDataMessage_t);
295 phyStatus_t ret = gPhySuccess_c;
296
297 if (!phy_intf_init_done)
298 {
299 return gPhyInvalidParameter_c;
300 }
301
302 PLATFORM_RemoteActiveReq();
303
304 do
305 {
306 if (phyInstance >= CTX_NO)
307 {
308 phyInstance = 0;
309 }
310
311 pMsg->ctx_id = phyInstance;
312
313 if (pMsg->msgType == gPdDataReq_c)
314 {
315 len += pMsg->msgData.dataReq.psduLength;
316 }
317
318 if (HAL_RpmsgSend((hal_rpmsg_handle_t)phyRpmsgHandle, (uint8_t *)pMsg, len) != kStatus_HAL_RpmsgSuccess)
319 {
320 ret = gPhyBusy_c;
321 break;
322 }
323 } while (0);
324
325 PLATFORM_RemoteActiveRel();
326
327 return ret;
328 }
329
PHY_get_ctx()330 uint8_t PHY_get_ctx()
331 {
332 macToPlmeMessage_t msg;
333
334 msg.msgType = gPlmeGetReq_c;
335 msg.msgData.getReq.PibAttribute = gPhyGetCtxId;
336 msg.msgData.getReq.PibAttributeValue = (uint64_t)(-1);
337
338 MAC_PLME_SapHandler(&msg, 0);
339
340 return (uint8_t)msg.msgData.getReq.PibAttributeValue;
341 }
342
343 /*! *********************************************************************************
344 * \brief This function returns the RSSI for the last received packet
345 *
346 * \return uint8_t RSSI value
347 *
348 ********************************************************************************** */
PhyGetLastRxRssiValue(void)349 uint8_t PhyGetLastRxRssiValue(void)
350 {
351 int32_t lqi_to_rssi = 0;
352
353 return (uint8_t)lqi_to_rssi;
354 }
355
PhyConvertLQIToRSSI(uint8_t lqi)356 int8_t PhyConvertLQIToRSSI(uint8_t lqi)
357 {
358 int32_t rssi = (36 * lqi - 9836) / 109;
359
360 return (int8_t)rssi;
361 }
362