1 /*
2 * Copyright 2019-2025 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_elemu.h"
9
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.elemu"
13 #endif
14
15 #define ELEMU_READY_WAIT_TIME 0xFFFFFFFFU
16 #define ELEMU_RESET_COMPLETED (0x1B00803Cu)
17 #define ELEMU_RESET_STARTED (0x1700D03Cu)
18
19 static status_t ELEMU_StartupWait(ELEMU_Type *mu);
20
21 #if (defined(ELEMU_HAS_LOADABLE_FW) && ELEMU_HAS_LOADABLE_FW)
22 #include "fsl_sss_mgmt.h"
23 #include "fsl_sss_sscp.h"
24 #include "fsl_sscp_mu.h"
25
26 #endif
27 /* ELEMU driver */
28
29 /* undef BIT in case of redefinition
30 * error: "BIT" redefined
31 */
32 #ifdef BIT
33 #undef BIT
34 #endif
35 #define BIT(x) (((uint32_t)1u << (x)))
36 #define MU_READ_HEADER (0x01u)
37 #define READ_RETRIES (0x5u)
38
39 #define MU_SEMA4_RESERVED_BY_OTHER (0xFFFFFFAAu)
40 #define MU_SEMA4_LOCKED_TO_CURRENT (0x00000055u)
41 #define MU_SEMA4_FREE (0x0u)
42
43 typedef struct mu_message
44 {
45 mu_hdr_t header;
46 uint32_t payload[ELEMU_TR_COUNT - MU_MSG_HEADER_SIZE];
47 } mu_message_t;
48
ELEMU_mu_hal_send_data(ELEMU_Type * mu,uint8_t regid,uint32_t * data)49 void ELEMU_mu_hal_send_data(ELEMU_Type *mu, uint8_t regid, uint32_t *data)
50 {
51 uint32_t mask = (BIT(regid));
52 while ((mu->TSR & mask) == 0u)
53 {
54 }
55 mu->TR[regid] = *data;
56 }
57
ELEMU_mu_hal_receive_data(ELEMU_Type * mu,uint8_t regid,uint32_t * data)58 void ELEMU_mu_hal_receive_data(ELEMU_Type *mu, uint8_t regid, uint32_t *data)
59 {
60 uint32_t mask = BIT(regid);
61 uint8_t read_retries = READ_RETRIES;
62 while ((mu->RSR & mask) == 0u)
63 {
64 }
65 *data = mu->RR[regid];
66 while (((mu->RSR & mask) != 0u) && (read_retries != 0u))
67 {
68 *data = mu->RR[regid];
69 read_retries--;
70 }
71 }
72
ELEMU_mu_hal_receive_data_wait(ELEMU_Type * mu,uint8_t regid,uint32_t * data,uint32_t wait)73 status_t ELEMU_mu_hal_receive_data_wait(ELEMU_Type *mu, uint8_t regid, uint32_t *data, uint32_t wait)
74 {
75 uint32_t mask = BIT(regid);
76 uint8_t read_retries = READ_RETRIES;
77 status_t ret = 0;
78 while ((mu->RSR & mask) == 0u)
79 {
80 if (--wait == 0u)
81 {
82 ret = kStatus_ELEMU_RequestTimeout;
83 break;
84 }
85 }
86 if (ret != kStatus_ELEMU_RequestTimeout)
87 {
88 *data = mu->RR[regid];
89 while (((mu->RSR & mask) != 0u) && (read_retries != 0u))
90 {
91 *data = mu->RR[regid];
92 read_retries--;
93 }
94 ret = kStatus_Success;
95 }
96 return ret;
97 }
98
ELEMU_mu_send_message(ELEMU_Type * mu,uint32_t buf[],size_t wordCount)99 status_t ELEMU_mu_send_message(ELEMU_Type *mu, uint32_t buf[], size_t wordCount)
100 {
101 uint8_t tx_reg_idx = 0u;
102 uint8_t counter = 0u;
103 status_t ret = kStatus_Fail;
104 if (buf == NULL)
105 {
106 ret = kStatus_ELEMU_InvalidArgument;
107 }
108 else if (wordCount > ELEMU_TR_COUNT)
109 {
110 ret = kStatus_ELEMU_AgumentOutOfRange;
111 }
112 else
113 {
114 while (wordCount > 0u)
115 {
116 tx_reg_idx = tx_reg_idx % ELEMU_TR_COUNT;
117 ELEMU_mu_hal_send_data(mu, tx_reg_idx, &buf[counter]);
118 tx_reg_idx++;
119 counter++;
120 wordCount--;
121 }
122 ret = kStatus_Success;
123 }
124 return ret;
125 }
126
ELEMU_mu_wait_for_ready(ELEMU_Type * mu,uint32_t wait)127 status_t ELEMU_mu_wait_for_ready(ELEMU_Type *mu, uint32_t wait)
128 {
129 if (kStatus_Success != ELEMU_LP_WakeupPathInit(mu))
130 {
131 return kStatus_ELEMU_RequestTimeout;
132 }
133
134 #if (defined(FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER) && FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER)
135 status_t ret = kStatus_ELEMU_RequestTimeout;
136 if (wait == 0u)
137 {
138 if ((ELEMUA->SEMA4_SR & (ELEMU_SEMA4_SR_MISC_BSY(0x30) | ELEMU_SEMA4_SR_SSS_CIP1_MASK)) == 0u)
139 {
140 ret = kStatus_Success;
141 }
142 }
143 else
144 {
145 do
146 {
147 if ((ELEMUA->SEMA4_SR & (ELEMU_SEMA4_SR_MISC_BSY(0x30) | ELEMU_SEMA4_SR_SSS_CIP1_MASK)) == 0u)
148 {
149 ret = kStatus_Success;
150 break;
151 }
152 wait--;
153 } while (wait != 0u);
154 }
155 return ret;
156 #else /* FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER */
157 return kStatus_Success;
158 #endif
159 }
160 #if (defined(FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER) && FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER)
ELEMU_mu_get_ownership_status(ELEMU_Type * mu)161 elemu_ownership_status_t ELEMU_mu_get_ownership_status(ELEMU_Type *mu)
162 {
163 elemu_ownership_status_t ret = kStatus_ELEMU_Unknown;
164 uint32_t result = mu->SEMA4_OWNR;
165 if (result == MU_SEMA4_LOCKED_TO_CURRENT)
166 {
167 ret = kStatus_ELEMU_LockedByMe;
168 }
169 else if (result == MU_SEMA4_RESERVED_BY_OTHER)
170 {
171 ret = kStatus_ELEMU_LockedByOther;
172 }
173 else if (result == MU_SEMA4_FREE)
174 {
175 ret = kStatus_ELEMU_Free;
176 }
177 else
178 {
179 ret = kStatus_ELEMU_Unknown;
180 }
181 return ret;
182 }
183
ELEMU_mu_get_ownership(ELEMU_Type * mu)184 status_t ELEMU_mu_get_ownership(ELEMU_Type *mu)
185 {
186 status_t ret = kStatus_Fail;
187 uint32_t result = mu->SEMA4_ACQ;
188 if (result == MU_SEMA4_LOCKED_TO_CURRENT)
189 {
190 ret = kStatus_Success;
191 }
192 else if (result == MU_SEMA4_RESERVED_BY_OTHER)
193 {
194 ret = kStatus_ELEMU_Busy;
195 }
196 else
197 {
198 ret = kStatus_Fail;
199 }
200 return ret;
201 }
202
ELEMU_mu_release_ownership(ELEMU_Type * mu)203 status_t ELEMU_mu_release_ownership(ELEMU_Type *mu)
204 {
205 status_t ret = kStatus_Fail;
206 uint32_t result = mu->SEMA4_REL;
207 if (result == MU_SEMA4_FREE)
208 {
209 ret = kStatus_Success;
210 }
211 else if (result == MU_SEMA4_RESERVED_BY_OTHER)
212 {
213 ret = kStatus_ELEMU_Busy;
214 }
215 else
216 {
217 ret = kStatus_Fail;
218 }
219 return ret;
220 }
221
ELEMU_mu_release_ownership_force(ELEMU_Type * mu)222 status_t ELEMU_mu_release_ownership_force(ELEMU_Type *mu)
223 {
224 status_t ret = kStatus_Fail;
225 uint32_t result = mu->SEMA4_FREL;
226 if (result == MU_SEMA4_FREE)
227 {
228 ret = kStatus_Success;
229 }
230 else if (result == MU_SEMA4_RESERVED_BY_OTHER)
231 {
232 ret = kStatus_ELEMU_Busy;
233 }
234 else
235 {
236 ret = kStatus_Fail;
237 }
238 return ret;
239 }
240 #endif /* FSL_FEATURE_ELEMU_HAS_SEMA4_STATUS_REGISTER */
241
ELEMU_mu_read_message(ELEMU_Type * mu,uint32_t * buf,uint8_t * size,uint8_t read_header)242 status_t ELEMU_mu_read_message(ELEMU_Type *mu, uint32_t *buf, uint8_t *size, uint8_t read_header)
243 {
244 uint8_t msg_size = 0u;
245 uint8_t rx_reg_idx = 0u;
246 mu_message_t *msg = (mu_message_t *)(uintptr_t)buf;
247 uint32_t counter = 0u;
248 status_t ret = kStatus_Fail;
249
250 if ((buf == NULL) || (size == NULL))
251 {
252 ret = kStatus_ELEMU_InvalidArgument;
253 }
254 else
255 {
256 if (read_header == MU_READ_HEADER)
257 {
258 ELEMU_mu_hal_receive_data(mu, rx_reg_idx, (uint32_t *)(uintptr_t)&msg->header);
259 msg_size = msg->header.size;
260 rx_reg_idx++;
261 *size = msg_size + 1u;
262 }
263 else
264 {
265 msg_size = *size;
266 }
267
268 while (msg_size > 0u)
269 {
270 rx_reg_idx = rx_reg_idx % ELEMU_RR_COUNT;
271 ELEMU_mu_hal_receive_data(mu, rx_reg_idx, &msg->payload[counter]);
272 rx_reg_idx++;
273 counter++;
274 msg_size--;
275 }
276 ret = kStatus_Success;
277 }
278 return ret;
279 }
280
ELEMU_mu_read_data_wait(ELEMU_Type * mu,uint32_t buf[],uint8_t * size,uint32_t wait)281 status_t ELEMU_mu_read_data_wait(ELEMU_Type *mu, uint32_t buf[], uint8_t *size, uint32_t wait)
282 {
283 uint8_t msg_size = 0u;
284 uint8_t counter = 0u;
285 uint8_t rx_reg_idx = 0u;
286 status_t ret = kStatus_Success;
287
288 if ((buf == NULL) || (size == NULL))
289 {
290 ret = kStatus_ELEMU_InvalidArgument;
291 }
292 else
293 {
294 msg_size = *size;
295 while (msg_size > 0u)
296 {
297 rx_reg_idx = rx_reg_idx % ELEMU_RR_COUNT;
298 if (wait > 0u)
299 {
300 if ((ret = ELEMU_mu_hal_receive_data_wait(mu, rx_reg_idx, &buf[counter], wait)) != kStatus_Success)
301 {
302 break;
303 }
304 }
305 else
306 {
307 ELEMU_mu_hal_receive_data(mu, rx_reg_idx, &buf[counter]);
308 }
309 rx_reg_idx++;
310 counter++;
311 msg_size--;
312 }
313 }
314 return ret;
315 }
316
ELEMU_mu_get_response(ELEMU_Type * mu,uint32_t * buf,size_t wordCount)317 status_t ELEMU_mu_get_response(ELEMU_Type *mu, uint32_t *buf, size_t wordCount)
318 {
319 uint8_t size = (uint8_t)wordCount;
320 status_t ret;
321 if (buf == NULL)
322 {
323 ret = kStatus_ELEMU_InvalidArgument;
324 }
325 else if (wordCount > ELEMU_RR_COUNT)
326 {
327 ret = kStatus_ELEMU_AgumentOutOfRange;
328 }
329 else
330 {
331 ret = ELEMU_mu_read_message(mu, buf, &size, MU_READ_HEADER);
332 }
333 return ret;
334 }
335
ELEMU_mu_wait_for_data(ELEMU_Type * mu,uint32_t * buf,size_t wordCount,uint32_t wait)336 status_t ELEMU_mu_wait_for_data(ELEMU_Type *mu, uint32_t *buf, size_t wordCount, uint32_t wait)
337 {
338 uint8_t size = (uint8_t)wordCount;
339 status_t ret;
340 if (buf == NULL)
341 {
342 ret = kStatus_ELEMU_InvalidArgument;
343 }
344 else if (wordCount > ELEMU_RR_COUNT)
345 {
346 ret = kStatus_ELEMU_AgumentOutOfRange;
347 }
348 else
349 {
350 ret = ELEMU_mu_read_data_wait(mu, buf, &size, wait);
351 }
352 return ret;
353 }
354
ELEMU_mu_init(ELEMU_Type * mu)355 void ELEMU_mu_init(ELEMU_Type *mu)
356 {
357 /* nothing to do for initialization */
358 }
359
ELEMU_StartupWait(ELEMU_Type * mu)360 static status_t ELEMU_StartupWait(ELEMU_Type *mu)
361 {
362 uint32_t msg[2] = {0};
363 status_t status = kStatus_Fail;
364
365 if (kStatus_Success != ELEMU_mu_wait_for_data(mu, msg, 2u, ELEMU_READY_WAIT_TIME))
366 {
367 }
368 else if (msg[0] != ELEMU_RESET_STARTED)
369 {
370 status = kStatus_Fail;
371 }
372 else if (msg[1] != ELEMU_RESET_COMPLETED)
373 {
374 status = kStatus_Fail;
375 }
376 else
377 {
378 status = kStatus_Success;
379 }
380
381 return status;
382 }
383
ELEMU_LP_WakeupPathInit(ELEMU_Type * mu)384 status_t ELEMU_LP_WakeupPathInit(ELEMU_Type *mu)
385 {
386 status_t status = kStatus_Fail;
387
388 do
389 {
390 /* read current value of the MRCC_SECSUBSYS register */
391 uint32_t mrcc_secsubsys = CLOCK_REG(kCLOCK_Secsubsys);
392
393 /* test if the module is released from reset and clocks are enabled */
394 if (((mrcc_secsubsys & MRCC_RSTB_MASK) == MRCC_RSTB_MASK) && ((mrcc_secsubsys & MRCC_CC_MASK) != 0x0u))
395 {
396 status = kStatus_Success;
397 }
398
399 /* apply the requested MRCC_SECSUBSYS[CC] (control) */
400 /* the actual non-zero CC value might be different from the setting configured by ROM bootloader */
401 /* the MRCC_SECSUBSYS[CC] is set to 2'b11 */
402 CLOCK_EnableClockLPMode(kCLOCK_Secsubsys, kCLOCK_IpClkControl_fun3);
403
404 /* the module is running and the CC is configured, return */
405 if (kStatus_Success == status)
406 {
407 break;
408 }
409
410 /* the module is NOT running at the time when this function is entered. */
411 /* therefore, wait for its startup sequence to complete */
412 status = ELEMU_StartupWait(mu);
413 } while (false);
414
415 return status;
416 }
417
418 #if (defined(ELEMU_HAS_LOADABLE_FW) && ELEMU_HAS_LOADABLE_FW)
419
420 /* Tunnel type is EdgeLock Firmware upload */
421 #define TUNNEL_TYPE_SB3_ELE_FW 0x22u
422 #define SB3_BLOCK0_SIZE_IN_BYTES 0x60u
423
ELEMU_loadFw(ELEMU_Type * mu,uint32_t image[])424 status_t ELEMU_loadFw(ELEMU_Type *mu, uint32_t image[])
425 {
426 uint32_t resultState = 0u;
427 sss_sscp_tunnel_t tunnelCtx;
428 sss_sscp_session_t sssSession;
429 sscp_context_t sscpContext;
430 status_t status = kStatus_Fail;
431 do
432 {
433 if (sscp_mu_init(&(sscpContext), (ELEMU_Type *)mu) != kStatus_SSCP_Success)
434 {
435 break;
436 }
437 /* OPEN SESSION */
438 if (sss_sscp_open_session(&sssSession, 0u, kType_SSS_Ele200, &sscpContext) != kStatus_SSS_Success)
439 {
440 break;
441 }
442
443 /* OPEN TUNNEL */
444 if (sss_sscp_tunnel_context_init(&tunnelCtx, &sssSession, TUNNEL_TYPE_SB3_ELE_FW) != kStatus_SSS_Success)
445 {
446 break;
447 }
448
449 /* Pass loadable ELE FW */
450 if (sss_sscp_tunnel(&tunnelCtx, (uint8_t *)image, SB3_BLOCK0_SIZE_IN_BYTES, &resultState) !=
451 kStatus_SSS_Success)
452 {
453 break;
454 }
455
456 /* If all steps before passes without break, then consider it as success*/
457 status = kStatus_Success;
458
459 } while (false);
460 /* FREE TUNNEL CONTEXT */
461 sss_sscp_tunnel_context_free(&tunnelCtx);
462 /* CLOSE SESSION */
463 sss_sscp_close_session(&sssSession);
464
465 return status;
466 }
467
468 #endif /* ELEMU_HAS_LOADABLE_FW */
469