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