1 /*
2 * Copyright 2022-2024 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_trdc.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.trdc1"
17 #endif
18
19 /* The memory increment definition in byte of MBC and MRC configuration registers */
20 #define TRDC_MRC_DOMAIN_INCREMENT 0x100UL
21 #define TRDC_MBC_DOMAIN_INCREMENT 0x200UL
22 /* In latest TRDC register definition this macro has been removed from device header file. Add this for backward
23 * compatability. */
24 #ifndef TRDC_MBC_NSE_BLK_CLR_ALL_DID_SEL
25 #define TRDC_MBC_NSE_BLK_CLR_ALL_DID_SEL(x) ((uint32_t)(((uint32_t)(x)) << TRDC_MBC_NSE_BLK_CLR_ALL_DID_SEL0_SHIFT))
26 #endif
27 /* Get the memory increment in for each slave inside MBC */
28 #define TRDC_MBC_SLAVE_INCREMENT(x) \
29 (((x) == 0U) ? (0U) : (((x) == 1U) ? (0x140UL) : (((x) == 2U) ? (0x168UL) : (0x190UL))))
30
31 typedef union
32 {
33 #if defined(FSL_FEATURE_TRDC_HAS_DOMAIN_ASSIGNMENT) && FSL_FEATURE_TRDC_HAS_DOMAIN_ASSIGNMENT
34 trdc_processor_domain_assignment_t _processor_domain_assignment;
35 trdc_non_processor_domain_assignment_t _non_processor_domain_assignment;
36 trdc_pid_config_t _pid_config;
37 #endif
38 #if defined(FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG) && FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG
39 trdc_idau_config_t _idau_config;
40 #endif
41 #if (defined(FSL_FEATURE_TRDC_HAS_MBC) && FSL_FEATURE_TRDC_HAS_MBC) || \
42 (defined(FSL_FEATURE_TRDC_HAS_MRC) && FSL_FEATURE_TRDC_HAS_MRC)
43 trdc_memory_access_control_config_t _memory_access_control;
44 #endif
45 #if defined(FSL_FEATURE_TRDC_HAS_MBC) && FSL_FEATURE_TRDC_HAS_MBC
46 trdc_mbc_memory_block_config_t _mbc_memory_blk;
47 trdc_mbc_nse_update_config_t _mbc_nse_update;
48 #endif
49 uint32_t _u32;
50 } trdc_reg32_convert_t;
51
52 /*******************************************************************************
53 * Variables
54 ******************************************************************************/
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
56 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
57
58 /*******************************************************************************
59 * Code
60 ******************************************************************************/
61 #if defined(FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG) && FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG
62 /*!
63 * brief Gets the TRDC hardware configuration.
64 *
65 * This function gets the TRDC hardware configurations, including number of bus
66 * masters, number of domains, number of MRCs and number of PACs.
67 *
68 * param base TRDC peripheral base address.
69 * param config Pointer to the structure to get the configuration.
70 */
TRDC_GetHardwareConfig(TRDC_Type * base,trdc_hardware_config_t * config)71 void TRDC_GetHardwareConfig(TRDC_Type *base, trdc_hardware_config_t *config)
72 {
73 assert(NULL != config);
74
75 config->masterNumber =
76 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMSTR_MASK) >> TRDC_TRDC_HWCFG0_NMSTR_SHIFT);
77 config->domainNumber =
78 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NDID_MASK) >> TRDC_TRDC_HWCFG0_NDID_SHIFT);
79 config->mbcNumber =
80 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMBC_MASK) >> TRDC_TRDC_HWCFG0_NMBC_SHIFT);
81 config->mrcNumber =
82 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMRC_MASK) >> TRDC_TRDC_HWCFG0_NMRC_SHIFT);
83 }
84 #endif
85
86 #if defined(FSL_FEATURE_TRDC_HAS_MBC) && FSL_FEATURE_TRDC_HAS_MBC
87 /*!
88 * brief Gets the hardware configuration of the one of two slave memories within each MBC(memory block checker).
89 *
90 * param base TRDC peripheral base address.
91 * param config Pointer to the structure to get the configuration.
92 * param mbcIdx MBC number.
93 * param slvIdx Slave number.
94 */
TRDC_GetMbcHardwareConfig(TRDC_Type * base,trdc_slave_memory_hardware_config_t * config,uint8_t mbcIdx,uint8_t slvIdx)95 void TRDC_GetMbcHardwareConfig(TRDC_Type *base,
96 trdc_slave_memory_hardware_config_t *config,
97 uint8_t mbcIdx,
98 uint8_t slvIdx)
99 {
100 assert(NULL != config);
101 #if defined(TRDC_MBC_COUNT) && TRDC_MBC_COUNT
102 assert(mbcIdx < (uint8_t)TRDC_MBC_COUNT);
103 #else
104 assert(mbcIdx < (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMBC_MASK) >>
105 TRDC_TRDC_HWCFG0_NMBC_SHIFT));
106 #endif
107 assert(slvIdx < 4U);
108
109 config->blockNum = TRDC_MBC_BASE(base, mbcIdx)->MBC_MEM_GLBCFG[slvIdx] & TRDC_MBC_MEM_GLBCFG_NBLKS_MASK;
110 config->blockSize = (TRDC_MBC_BASE(base, mbcIdx)->MBC_MEM_GLBCFG[slvIdx] & TRDC_MBC_MEM_GLBCFG_SIZE_LOG2_MASK) >>
111 TRDC_MBC_MEM_GLBCFG_SIZE_LOG2_SHIFT;
112 }
113 #endif
114
115 #if defined(FSL_FEATURE_TRDC_HAS_DOMAIN_ASSIGNMENT) && FSL_FEATURE_TRDC_HAS_DOMAIN_ASSIGNMENT
116 /*!
117 * brief Gets the default master domain assignment for the processor bus master.
118 *
119 * This function gets the default master domain assignment for the processor bus master.
120 * It should only be used for the processor bus masters, such as CORE0. This function
121 * sets the assignment as follows:
122 *
123 * code
124 * assignment->domainId = 0U;
125 * assignment->domainIdSelect = kTRDC_DidMda;
126 * assignment->lock = 0U;
127 * endcode
128 *
129 * param domainAssignment Pointer to the assignment structure.
130 */
TRDC_GetDefaultProcessorDomainAssignment(trdc_processor_domain_assignment_t * domainAssignment)131 void TRDC_GetDefaultProcessorDomainAssignment(trdc_processor_domain_assignment_t *domainAssignment)
132 {
133 assert(NULL != domainAssignment);
134
135 /* Initializes the configure structure to zero. */
136 (void)memset(domainAssignment, 0, sizeof(*domainAssignment));
137 }
138
139 /*!
140 * brief Gets the default master domain assignment for non-processor bus master.
141 *
142 * This function gets the default master domain assignment for non-processor bus master.
143 * It should only be used for the non-processor bus masters, such as DMA. This function
144 * sets the assignment as follows:
145 *
146 * code
147 * assignment->domainId = 0U;
148 * assignment->privilegeAttr = kTRDC_ForceUser;
149 * assignment->secureAttr = kTRDC_ForceSecure;
150 * assignment->bypassDomainId = 0U;
151 * assignment->lock = 0U;
152 * endcode
153 *
154 * param domainAssignment Pointer to the assignment structure.
155 */
TRDC_GetDefaultNonProcessorDomainAssignment(trdc_non_processor_domain_assignment_t * domainAssignment)156 void TRDC_GetDefaultNonProcessorDomainAssignment(trdc_non_processor_domain_assignment_t *domainAssignment)
157 {
158 assert(NULL != domainAssignment);
159
160 /* Initializes the configure structure to zero. */
161 (void)memset(domainAssignment, 0, sizeof(*domainAssignment));
162 }
163
164 /*!
165 * brief Sets the processor bus master domain assignment.
166 *
167 * This function sets the processor master domain assignment as valid.
168 * One bus master might have multiple domain assignment registers. The parameter
169 * \p assignIndex specifies which assignment register to set.
170 *
171 * Example: Set domain assignment for core 0.
172 *
173 * code
174 * trdc_processor_domain_assignment_t processorAssignment;
175 *
176 * TRDC_GetDefaultProcessorDomainAssignment(&processorAssignment);
177 *
178 * processorAssignment.domainId = 0;
179 * processorAssignment.xxx = xxx;
180 * TRDC_SetMasterDomainAssignment(TRDC, 1, &processorAssignment);
181 * endcode
182 *
183 * param base TRDC peripheral base address.
184 * param master Which master to configure, refer to trdcx_master_t in processor header file, x is trdc instance.
185 * param regNum Which register to configure, processor master can have more than one register for the MDAC
186 * configuration. param domainAssignment Pointer to the assignment structure.
187 */
TRDC_SetProcessorDomainAssignment(TRDC_Type * base,uint8_t master,uint8_t regNum,const trdc_processor_domain_assignment_t * domainAssignment)188 void TRDC_SetProcessorDomainAssignment(TRDC_Type *base,
189 uint8_t master,
190 uint8_t regNum,
191 const trdc_processor_domain_assignment_t *domainAssignment)
192 {
193 /* Make sure the master number does not exceed the max master count. */
194 assert(master <
195 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMSTR_MASK) >> TRDC_TRDC_HWCFG0_NMSTR_SHIFT));
196 /* Make sure the master is a processor master. */
197 assert(0U == (TRDC_GENERAL_BASE(base)->DACFG[master] & TRDC_DACFG_NCM_MASK));
198 assert(NULL != domainAssignment);
199 assert(domainAssignment->domainId <
200 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NDID_MASK) >> TRDC_TRDC_HWCFG0_NDID_SHIFT));
201
202 trdc_reg32_convert_t pid;
203 pid._processor_domain_assignment = *domainAssignment;
204 TRDC_DOMAIN_ASSIGNMENT_BASE(base)->MDA_DFMT0[master].MDA_W_DFMT0[regNum] = pid._u32 | TRDC_MDA_W_DFMT0_VLD_MASK;
205 }
206
207 /*!
208 * brief Sets the non-processor bus master domain assignment.
209 *
210 * This function sets the non-processor master domain assignment as valid.
211 * One bus master might have multiple domain assignment registers. The parameter
212 * \p assignIndex specifies which assignment register to set.
213 *
214 * Example: Set domain assignment for DMA0.
215 * code
216 * trdc_non_processor_domain_assignment_t nonProcessorAssignment;
217 *
218 * TRDC_GetDefaultNonProcessorDomainAssignment(&nonProcessorAssignment);
219 * nonProcessorAssignment.domainId = 1;
220 * nonProcessorAssignment.xxx = xxx;
221 *
222 * TRDC_SetMasterDomainAssignment(TRDC, kTrdcMasterDma0, 0U, &nonProcessorAssignment);
223 * endcode
224 *
225 * param base TRDC peripheral base address.
226 * param master Which master to configure, refer to trdc_master_t in processor header file.
227 * param domainAssignment Pointer to the assignment structure.
228 */
TRDC_SetNonProcessorDomainAssignment(TRDC_Type * base,uint8_t master,const trdc_non_processor_domain_assignment_t * domainAssignment)229 void TRDC_SetNonProcessorDomainAssignment(TRDC_Type *base,
230 uint8_t master,
231 const trdc_non_processor_domain_assignment_t *domainAssignment)
232 {
233 /* The master number should be less than the master count. */
234 assert(master <
235 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMSTR_MASK) >> TRDC_TRDC_HWCFG0_NMSTR_SHIFT));
236 /* Make sure the master is a non-CPU/non-processor master */
237 assert(0U != (TRDC_GENERAL_BASE(base)->DACFG[master] & TRDC_DACFG_NCM_MASK));
238 assert(NULL != domainAssignment);
239 assert(domainAssignment->domainId <
240 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NDID_MASK) >> TRDC_TRDC_HWCFG0_NDID_SHIFT));
241
242 trdc_reg32_convert_t pid;
243 pid._non_processor_domain_assignment = *domainAssignment;
244
245 TRDC_DOMAIN_ASSIGNMENT_BASE(base)->MDA_DFMT1[master].MDA_W_DFMT1[0] = pid._u32 | TRDC_MDA_W_DFMT1_VLD_MASK;
246 }
247
248 /*!
249 * brief Sets the current Process identifier(PID) for processor core.
250 *
251 * Each processor has a corresponding process identifier (PID) which can be used to group tasks into different domains.
252 * Secure privileged software saves and restores the PID as part of any context switch.
253 * This data structure defines an array of 32-bit values, one per MDA module, that define the PID. Since this register
254 * resource is only applicable to processor cores, the data structure is typically sparsely populated. The HWCFG[2-3]
255 * registers provide a bitmap of the implemented PIDn registers. This data structure is indexed using the corresponding
256 * MDA instance number. Depending on the operating clock domain of each DAC instance, there may be optional information
257 * stored in the corresponding PIDm register to properly implement the LK2 = 2 functionality.
258 *
259 * param base TRDC peripheral base address.
260 * param master Which processor master to configure, refer to trdc_master_t in processor header file.
261 * param pidConfig Pointer to the configuration structure.
262 */
TRDC_SetPid(TRDC_Type * base,uint8_t master,const trdc_pid_config_t * pidConfig)263 void TRDC_SetPid(TRDC_Type *base, uint8_t master, const trdc_pid_config_t *pidConfig)
264 {
265 assert(pidConfig != NULL);
266 /* The master number should be less than the master count. */
267 assert(master <
268 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMSTR_MASK) >> TRDC_TRDC_HWCFG0_NMSTR_SHIFT));
269 /* This master has to be a processor master. */
270 assert((TRDC_GENERAL_BASE(base)->DACFG[master] & TRDC_DACFG_NCM_MASK) == 0U);
271
272 trdc_reg32_convert_t pid;
273 pid._pid_config = *pidConfig;
274 TRDC_DOMAIN_ASSIGNMENT_BASE(base)->PID[master] = pid._u32;
275 }
276 #endif
277
278 #if defined(FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG) && FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG
279 /*!
280 * brief Gets the default IDAU(Implementation-Defined Attribution Unit) configuration.
281 *
282 * code
283 * config->lockSecureVTOR = false;
284 * config->lockNonsecureVTOR = false;
285 * config->lockSecureMPU = false;
286 * config->lockNonsecureMPU = false;
287 * config->lockSAU = false;
288 * endcode
289 *
290 * param domainAssignment Pointer to the configuration structure.
291 */
TRDC_GetDefaultIDAUConfig(trdc_idau_config_t * idauConfiguration)292 void TRDC_GetDefaultIDAUConfig(trdc_idau_config_t *idauConfiguration)
293 {
294 assert(NULL != idauConfiguration);
295
296 /* Initializes the configure structure to zero. */
297 (void)memset(idauConfiguration, 0, sizeof(*idauConfiguration));
298 }
299
300 /*!
301 * brief Sets the IDAU(Implementation-Defined Attribution Unit) control configuration.
302 *
303 * Example: Lock the secure and non-secure MPU registers.
304 *
305 * code
306 * trdc_idau_config_t idauConfiguration;
307 *
308 * TRDC_GetDefaultIDAUConfig(&idauConfiguration);
309 *
310 * idauConfiguration.lockSecureMPU = true;
311 * idauConfiguration.lockNonsecureMPU = true;
312 * TRDC_SetIDAU(TRDC, &idauConfiguration);
313 * endcode
314 *
315 * param base TRDC peripheral base address.
316 * param domainAssignment Pointer to the configuration structure.
317 */
TRDC_SetIDAU(TRDC_Type * base,const trdc_idau_config_t * idauConfiguration)318 void TRDC_SetIDAU(TRDC_Type *base, const trdc_idau_config_t *idauConfiguration)
319 {
320 assert(NULL != idauConfiguration);
321
322 trdc_reg32_convert_t pid;
323 pid._idau_config = *idauConfiguration;
324
325 TRDC_GENERAL_BASE(base)->TRDC_IDAU_CR = pid._u32 | TRDC_TRDC_IDAU_CR_VLD_MASK;
326 }
327 #endif
328
329 #if defined(FSL_FEATURE_TRDC_HAS_FLW) && FSL_FEATURE_TRDC_HAS_FLW
330 /*!
331 * brief Gets the default FLW(Flsh Logical Window) configuration.
332 *
333 * code
334 * config->blockCount = false;
335 * config->arrayBaseAddr = false;
336 * config->lock = false;
337 * config->enable = false;
338 * endcode
339 *
340 * param flwConfiguration Pointer to the configuration structure.
341 */
TRDC_GetDefaultFlashLogicalWindowConfig(trdc_flw_config_t * flwConfiguration)342 void TRDC_GetDefaultFlashLogicalWindowConfig(trdc_flw_config_t *flwConfiguration)
343 {
344 assert(NULL != flwConfiguration);
345
346 /* Initializes the configure structure to zero. */
347 (void)memset(flwConfiguration, 0, sizeof(*flwConfiguration));
348
349 flwConfiguration->enable = 0x1UL;
350 }
351
352 /*!
353 * brief Sets the FLW function's configuration.
354 *
355 * code
356 * trdc_flw_config_t flwConfiguration;
357 *
358 * TRDC_GetDefaultIDAUConfig(&flwConfiguration);
359 *
360 * flwConfiguration.blockCount = 32U;
361 * flwConfiguration.arrayBaseAddr = 0xXXXXXXXX;
362 * TRDC_SetIDAU(TRDC, &flwConfiguration);
363 * endcode
364 *
365 * param base TRDC peripheral base address.
366 * param flwConfiguration Pointer to the configuration structure.
367 */
TRDC_SetFlashLogicalWindow(TRDC_Type * base,const trdc_flw_config_t * flwConfiguration)368 void TRDC_SetFlashLogicalWindow(TRDC_Type *base, const trdc_flw_config_t *flwConfiguration)
369 {
370 assert(NULL != flwConfiguration);
371
372 TRDC_FLW_BASE(base)->TRDC_FLW_ABASE = flwConfiguration->arrayBaseAddr;
373 TRDC_FLW_BASE(base)->TRDC_FLW_BCNT = flwConfiguration->blockCount;
374 TRDC_FLW_BASE(base)->TRDC_FLW_CTL =
375 TRDC_TRDC_FLW_CTL_V(flwConfiguration->enable) | TRDC_TRDC_FLW_CTL_LK(flwConfiguration->lock);
376 }
377 #endif
378
379 #if defined(FSL_FEATURE_TRDC_HAS_DOMAIN_ERROR) && FSL_FEATURE_TRDC_HAS_DOMAIN_ERROR
380 #if (((__CORTEX_M == 0U) && (defined(__ICCARM__))) || (defined(__XTENSA__)))
381 /*!
382 * @brief Count the leading zeros.
383 *
384 * Count the leading zeros of an 32-bit data. This function is only defined
385 * for CM0 and CM0+ for IAR, because other cortex series have the clz instruction,
386 * KEIL and ARMGCC have toolchain build in function for this purpose.
387 *
388 * @param data The data to process.
389 * @return Count of the leading zeros.
390 */
TRDC_CountLeadingZeros(uint32_t data)391 static uint8_t TRDC_CountLeadingZeros(uint32_t data)
392 {
393 uint8_t count = 0U;
394 uint32_t mask = 0x80000000U;
395
396 while ((data & mask) == 0U)
397 {
398 count++;
399 mask >>= 1U;
400 }
401
402 return count;
403 }
404 #endif
405 #endif
406
407 /*!
408 * brief Initializes the TRDC module.
409 *
410 * This function enables the TRDC clock.
411 *
412 * param base TRDC peripheral base address.
413 */
TRDC_Init(TRDC_Type * base)414 void TRDC_Init(TRDC_Type *base)
415 {
416 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
417
418 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
419 }
420
421 /*!
422 * brief De-initializes the TRDC module.
423 *
424 * This function disables the TRDC clock.
425 *
426 * param base TRDC peripheral base address.
427 */
TRDC_Deinit(TRDC_Type * base)428 void TRDC_Deinit(TRDC_Type *base)
429 {
430 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
431
432 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
433 }
434
435 #if defined(FSL_FEATURE_TRDC_HAS_DOMAIN_ERROR) && FSL_FEATURE_TRDC_HAS_DOMAIN_ERROR
436 /*!
437 * brief Gets and clears the first domain error of the current domain.
438 *
439 * This function gets the first access violation information for the current domain
440 * and clears the pending flag. There might be multiple access violations pending
441 * for the current domain. This function only processes the first error.
442 *
443 * param base TRDC peripheral base address.
444 * param error Pointer to the error information.
445 * return If the access violation is captured, this function returns the kStatus_Success.
446 * The error information can be obtained from the parameter error. If no
447 * access violation is captured, this function returns the kStatus_NoData.
448 */
TRDC_GetAndClearFirstDomainError(TRDC_Type * base,trdc_domain_error_t * error)449 status_t TRDC_GetAndClearFirstDomainError(TRDC_Type *base, trdc_domain_error_t *error)
450 {
451 return TRDC_GetAndClearFirstSpecificDomainError(base, error, TRDC_GetCurrentMasterDomainId(base));
452 }
453
454 /*!
455 * brief Gets and clears the first domain error of the specific domain.
456 *
457 * This function gets the first access violation information for the specific domain
458 * and clears the pending flag. There might be multiple access violations pending
459 * for the current domain. This function only processes the first error.
460 *
461 * param base TRDC peripheral base address.
462 * param error Pointer to the error information.
463 * param domainId The error of which domain to get and clear.
464 * return If the access violation is captured, this function returns the kStatus_Success.
465 * The error information can be obtained from the parameter error. If no
466 * access violation is captured, this function returns the kStatus_NoData.
467 */
TRDC_GetAndClearFirstSpecificDomainError(TRDC_Type * base,trdc_domain_error_t * error,uint8_t domainId)468 status_t TRDC_GetAndClearFirstSpecificDomainError(TRDC_Type *base, trdc_domain_error_t *error, uint8_t domainId)
469 {
470 assert(NULL != error);
471
472 status_t status;
473 uint8_t errorIndex; /* The index of first domain error. */
474 uint32_t errorBitMap; /* Domain error location bit map. */
475 uint32_t regW1; /* To save TRDC_DERR_W1. */
476
477 /* Get the error bitmap. */
478 errorBitMap = TRDC_DOMAIN_ERROR_BASE(base)->TRDC_DERRLOC[domainId];
479
480 if (0U == errorBitMap) /* No error captured. */
481 {
482 status = kStatus_NoData;
483 }
484 else
485 {
486 /* Get the first error controller index. */
487 #if (((__CORTEX_M == 0U) && (defined(__ICCARM__))) || (defined(__XTENSA__)))
488 errorIndex = 31U - TRDC_CountLeadingZeros(errorBitMap);
489 #else
490 errorIndex = 31U - __CLZ(errorBitMap);
491 #endif
492
493 /* Must write TRDC_FDID[TRDC_FDID] with the domain ID before reading the Domain Error registers. */
494 TRDC_DOMAIN_ERROR_BASE(base)->TRDC_FDID = TRDC_TRDC_FDID_FDID(domainId);
495
496 /* Initializes the error structure to zero. */
497 (void)memset(error, 0, sizeof(*error));
498
499 if (errorIndex > 15U)
500 {
501 /* Error in Memory Region Checker (MRC) */
502 errorIndex -= 12U;
503 error->controller = (trdc_controller_t)errorIndex;
504 errorIndex -= 4U;
505
506 /* Get the error information. */
507 regW1 = TRDC_DOMAIN_ERROR_BASE(base)->MRC_DERR[errorIndex].W1;
508 error->address = TRDC_DOMAIN_ERROR_BASE(base)->MRC_DERR[errorIndex].W0;
509 /* Clear error pending. */
510 TRDC_DOMAIN_ERROR_BASE(base)->MRC_DERR[errorIndex].W3 = TRDC_W3_RECR(0x01U);
511 }
512 else
513 {
514 /* Error in Memory Block Controller (MBC) */
515 error->slaveMemoryIdx = errorIndex % 4U;
516 errorIndex /= 4U;
517 error->controller = (trdc_controller_t)errorIndex;
518
519 /* Check if the MBC error index exceeds the module's max MBC index to avoid overrun access. */
520 if (errorIndex >=
521 ((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NMBC_MASK) >> TRDC_TRDC_HWCFG0_NMBC_SHIFT))
522 {
523 return kStatus_Fail;
524 }
525
526 error->controller = (trdc_controller_t)errorIndex;
527
528 /* Get the error information. */
529 regW1 = TRDC_DOMAIN_ERROR_BASE(base)->MBC_DERR[errorIndex].W1;
530 error->address = TRDC_DOMAIN_ERROR_BASE(base)->MBC_DERR[errorIndex].W0;
531 /* Clear error pending. */
532 TRDC_DOMAIN_ERROR_BASE(base)->MBC_DERR[errorIndex].W3 = TRDC_W3_RECR(0x01U);
533 }
534
535 uint8_t tempVal = 0U;
536 error->domainId = (uint8_t)((regW1 & TRDC_W1_EDID_MASK) >> TRDC_W1_EDID_MASK);
537 tempVal = (uint8_t)((regW1 & TRDC_W1_EATR_MASK) >> TRDC_W1_EATR_SHIFT);
538 error->errorAttr = (trdc_error_attr_t)tempVal;
539 tempVal = (uint8_t)((regW1 & TRDC_W1_ERW_MASK) >> TRDC_W1_ERW_SHIFT);
540 error->errorType = (trdc_error_type_t)tempVal;
541 error->errorPort = (uint8_t)((regW1 & TRDC_W1_EPORT_MASK) >> TRDC_W1_EPORT_SHIFT);
542 tempVal = (uint8_t)((regW1 & TRDC_W1_EST_MASK) >> TRDC_W1_EST_SHIFT);
543 error->errorState = (trdc_error_state_t)tempVal;
544
545 status = kStatus_Success;
546 }
547
548 return status;
549 }
550 #endif
551
552 #if defined(FSL_FEATURE_TRDC_HAS_MRC) && FSL_FEATURE_TRDC_HAS_MRC
553 /*!
554 * brief Sets the memory access configuration for one of the access control register of one MRC.
555 *
556 * Example: Enable the secure operations and lock the configuration for MRC0 region 1.
557 *
558 * code
559 * trdc_memory_access_control_config_t config;
560 *
561 * config.securePrivX = true;
562 * config.securePrivW = true;
563 * config.securePrivR = true;
564 * config.lock = true;
565 * TRDC_SetMrcMemoryAccess(TRDC, &config, 0, 1);
566 * endcode
567 *
568 * param base TRDC peripheral base address.
569 * param config Pointer to the configuration structure.
570 * param mrcIdx MRC index.
571 * param regIdx Register number.
572 */
TRDC_MrcSetMemoryAccessConfig(TRDC_Type * base,const trdc_memory_access_control_config_t * config,uint8_t mrcIdx,uint8_t regIdx)573 void TRDC_MrcSetMemoryAccessConfig(TRDC_Type *base,
574 const trdc_memory_access_control_config_t *config,
575 uint8_t mrcIdx,
576 uint8_t regIdx)
577 {
578 assert(NULL != base);
579 assert(NULL != config);
580
581 trdc_reg32_convert_t pid;
582
583 pid._memory_access_control = *config;
584 TRDC_MRC_BASE(base, mrcIdx)->MRC_GLBAC[regIdx] = pid._u32;
585 }
586
587 /*!
588 * brief Enables the update of the selected domians.
589 *
590 * After the domians' update are enabled, their regions' NSE bits can be set or clear.
591 *
592 * param base TRDC peripheral base address.
593 * param mrcIdx MRC index.
594 * param domianMask Bit mask of the domains to be enabled.
595 * param enable True to enable, false to disable.
596 */
TRDC_MrcEnableDomainNseUpdate(TRDC_Type * base,uint8_t mrcIdx,uint16_t domianMask,bool enable)597 void TRDC_MrcEnableDomainNseUpdate(TRDC_Type *base, uint8_t mrcIdx, uint16_t domianMask, bool enable)
598 {
599 assert(NULL != base);
600
601 if (enable)
602 {
603 TRDC_MRC_BASE(base, mrcIdx)->MRC_NSE_RGN_INDIRECT |= ((uint32_t)domianMask << 16U);
604 }
605 else
606 {
607 TRDC_MRC_BASE(base, mrcIdx)->MRC_NSE_RGN_INDIRECT &= ~((uint32_t)domianMask << 16U);
608 }
609 }
610
611 /*!
612 * brief Sets the NSE bits of the selected regions for domains.
613 *
614 * This function sets the NSE bits for the selected regions for the domains whose update are enabled.
615 *
616 * param base TRDC peripheral base address.
617 * param mrcIdx MRC index.
618 * param regionMask Bit mask of the regions whose NSE bits to set.
619 */
TRDC_MrcRegionNseSet(TRDC_Type * base,uint8_t mrcIdx,uint16_t regionMask)620 void TRDC_MrcRegionNseSet(TRDC_Type *base, uint8_t mrcIdx, uint16_t regionMask)
621 {
622 assert(NULL != base);
623
624 TRDC_MRC_BASE(base, mrcIdx)->MRC_NSE_RGN_SET = ((uint32_t)regionMask);
625 }
626
627 /*!
628 * brief Clears the NSE bits of the selected regions for domains.
629 *
630 * This function clears the NSE bits for the selected regions for the domains whose update are enabled.
631 *
632 * param base TRDC peripheral base address.
633 * param mrcIdx MRC index.
634 * param regionMask Bit mask of the regions whose NSE bits to clear.
635 */
TRDC_MrcRegionNseClear(TRDC_Type * base,uint8_t mrcIdx,uint16_t regionMask)636 void TRDC_MrcRegionNseClear(TRDC_Type *base, uint8_t mrcIdx, uint16_t regionMask)
637 {
638 assert(NULL != base);
639
640 TRDC_MRC_BASE(base, mrcIdx)->MRC_NSE_RGN_CLR = ((uint32_t)regionMask);
641 }
642
643 /*!
644 * brief Clears the NSE bits for all the regions of the selected domains.
645 *
646 * This function clears the NSE bits for all regions of selected domains whose update are enabled.
647 *
648 * param base TRDC peripheral base address.
649 * param mrcIdx MRC index.
650 * param domainMask Bit mask of the domians whose NSE bits to clear.
651 */
TRDC_MrcDomainNseClear(TRDC_Type * base,uint8_t mrcIdx,uint16_t domainMask)652 void TRDC_MrcDomainNseClear(TRDC_Type *base, uint8_t mrcIdx, uint16_t domainMask)
653 {
654 assert(NULL != base);
655
656 uint8_t domainCount =
657 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NDID_MASK) >> TRDC_TRDC_HWCFG0_NDID_SHIFT);
658 uint8_t maxDomainId = 0U;
659 uint16_t tmpDomainMask = domainMask;
660
661 while (tmpDomainMask != 0U)
662 {
663 tmpDomainMask >>= 1U;
664 maxDomainId++;
665 }
666
667 /* Check whether the domain mask contains invalid domain. */
668 if (maxDomainId > domainCount)
669 {
670 assert(false);
671 }
672
673 TRDC_MRC_BASE(base, mrcIdx)->MRC_NSE_RGN_CLR_ALL = ((uint32_t)domainMask << 16U);
674 }
675
676 /*!
677 * brief Sets the configuration for one of the region descriptor per domain per MRC instnce.
678 *
679 * This function sets the configuration for one of the region descriptor, including the start
680 * and end address of the region, memory access control policy and valid.
681 *
682 * param base TRDC peripheral base address.
683 * param config Pointer to region descriptor configuration structure.
684 */
TRDC_MrcSetRegionDescriptorConfig(TRDC_Type * base,const trdc_mrc_region_descriptor_config_t * config)685 void TRDC_MrcSetRegionDescriptorConfig(TRDC_Type *base, const trdc_mrc_region_descriptor_config_t *config)
686 {
687 assert(NULL != base);
688
689 uint32_t regAddr = (uint32_t) & (TRDC_MRC_BASE(base, config->mrcIdx)->MRC_DOM0_RGD_W[config->regionIdx][0]);
690
691 regAddr += TRDC_MRC_DOMAIN_INCREMENT * config->domainIdx;
692
693 /* Set configuration for word 0 */
694 uint32_t data = TRDC_MRC_DOM0_RGD_W_MRACSEL(config->memoryAccessControlSelect) |
695 ((config->startAddr) & ~(TRDC_MRC_DOM0_RGD_W_MRACSEL_MASK));
696 *(uint32_t *)regAddr = data;
697
698 /* Set configuration for word 1 */
699 regAddr += 4U;
700 data = TRDC_MRC_DOM0_RGD_W_VLD(config->valid) | TRDC_MRC_DOM0_RGD_W_NSE(config->nseEnable) |
701 ((config->endAddr) & ~(TRDC_MRC_DOM0_RGD_W_VLD_MASK | TRDC_MRC_DOM0_RGD_W_NSE_MASK));
702 *(uint32_t *)regAddr = data;
703 }
704 #endif
705
706 #if defined(FSL_FEATURE_TRDC_HAS_MBC) && FSL_FEATURE_TRDC_HAS_MBC
707 /*!
708 * brief Sets the NSR update configuration for one of the MBC instance.
709 *
710 * After set the NSE configuration, the configured memory area can be updateby NSE set/clear.
711 *
712 * param base TRDC peripheral base address.
713 * param config Pointer to NSE update configuration structure.
714 * param mbcIdx MBC index.
715 */
TRDC_MbcSetNseUpdateConfig(TRDC_Type * base,const trdc_mbc_nse_update_config_t * config,uint8_t mbcIdx)716 void TRDC_MbcSetNseUpdateConfig(TRDC_Type *base, const trdc_mbc_nse_update_config_t *config, uint8_t mbcIdx)
717 {
718 assert(base != NULL);
719
720 trdc_reg32_convert_t pid;
721
722 pid._mbc_nse_update = *config;
723 TRDC_MBC_BASE(base, mbcIdx)->MBC_NSE_BLK_INDEX = pid._u32;
724 }
725
726 /*!
727 * brief Sets the NSE bits of the selected configuration words according to NSE update configuration.
728 *
729 * This function sets the NSE bits of the word for the configured regio, memory.
730 *
731 * param base TRDC peripheral base address.
732 * param mbcIdx MBC index.
733 * param bitMask Mask of the bits whose NSE bits to set.
734 */
TRDC_MbcWordNseSet(TRDC_Type * base,uint8_t mbcIdx,uint32_t bitMask)735 void TRDC_MbcWordNseSet(TRDC_Type *base, uint8_t mbcIdx, uint32_t bitMask)
736 {
737 assert(NULL != base);
738
739 TRDC_MBC_BASE(base, mbcIdx)->MBC_NSE_BLK_SET = ((uint32_t)bitMask);
740 }
741
742 /*!
743 * brief Clears the NSE bits of the selected configuration words according to NSE update configuration.
744 *
745 * This function sets the NSE bits of the word for the configured regio, memory.
746 *
747 * param base TRDC peripheral base address.
748 * param mbcIdx MBC index.
749 * param bitMask Mask of the bits whose NSE bits to clear.
750 */
TRDC_MbcWordNseClear(TRDC_Type * base,uint8_t mbcIdx,uint32_t bitMask)751 void TRDC_MbcWordNseClear(TRDC_Type *base, uint8_t mbcIdx, uint32_t bitMask)
752 {
753 assert(NULL != base);
754
755 TRDC_MBC_BASE(base, mbcIdx)->MBC_NSE_BLK_CLR = ((uint32_t)bitMask);
756 }
757
758 /*!
759 * brief Clears all configuration words' NSE bits of the selected domain and memory.
760 *
761 * param base TRDC peripheral base address.
762 * param mbcIdx MBC index.
763 * param domainMask Mask of the domains whose NSE bits to clear, 0b110 means clear domain 1&2.
764 * param slaveMask Mask of the slaves whose NSE bits to clear, 0x11 means clear all slave 0&1's NSE bits.
765 */
TRDC_MbcNseClearAll(TRDC_Type * base,uint8_t mbcIdx,uint16_t domainMask,uint8_t slave)766 void TRDC_MbcNseClearAll(TRDC_Type *base, uint8_t mbcIdx, uint16_t domainMask, uint8_t slave)
767 {
768 assert(NULL != base);
769
770 #if defined(FSL_FEATURE_TRDC_DOMAIN_COUNT) && FSL_FEATURE_TRDC_DOMAIN_COUNT
771 uint8_t dmainCount = FSL_FEATURE_TRDC_DOMAIN_COUNT;
772 #else
773 uint8_t dmainCount =
774 (uint8_t)((TRDC_GENERAL_BASE(base)->TRDC_HWCFG0 & TRDC_TRDC_HWCFG0_NDID_MASK) >> TRDC_TRDC_HWCFG0_NDID_SHIFT);
775 #endif
776 uint8_t maxDomainId = 0U;
777 uint16_t tmpDomainMask = domainMask;
778
779 while (tmpDomainMask != 0U)
780 {
781 tmpDomainMask >>= 1U;
782 maxDomainId++;
783 }
784
785 if (maxDomainId > dmainCount)
786 {
787 assert(false);
788 }
789
790 TRDC_MBC_BASE(base, mbcIdx)->MBC_NSE_BLK_CLR_ALL =
791 TRDC_MBC_NSE_BLK_CLR_ALL_DID_SEL(domainMask) | TRDC_MBC_NSE_BLK_CLR_ALL_MEMSEL(slave);
792 }
793
794 /*!
795 * brief Sets the memory access configuration for one of the region descriptor of one MBC.
796 *
797 * Example: Enable the secure operations and lock the configuration for MRC0 region 1.
798 *
799 * code
800 * trdc_memory_access_control_config_t config;
801 *
802 * config.securePrivX = true;
803 * config.securePrivW = true;
804 * config.securePrivR = true;
805 * config.lock = true;
806 * TRDC_SetMbcMemoryAccess(TRDC, &config, 0, 1);
807 * endcode
808 *
809 * param base TRDC peripheral base address.
810 * param config Pointer to the configuration structure.
811 * param mbcIdx MBC index.
812 * param rgdIdx Region descriptor number.
813 */
TRDC_MbcSetMemoryAccessConfig(TRDC_Type * base,const trdc_memory_access_control_config_t * config,uint8_t mbcIdx,uint8_t rgdIdx)814 void TRDC_MbcSetMemoryAccessConfig(TRDC_Type *base,
815 const trdc_memory_access_control_config_t *config,
816 uint8_t mbcIdx,
817 uint8_t rgdIdx)
818 {
819 assert(NULL != base);
820 assert(NULL != config);
821
822 trdc_reg32_convert_t pid;
823
824 pid._memory_access_control = *config;
825 TRDC_MBC_BASE(base, mbcIdx)->MBC_MEMN_GLBAC[rgdIdx] = pid._u32;
826 }
827
828 /*!
829 * brief Sets the configuration for one of the memory block per domain per MBC instnce.
830 *
831 * This function sets the configuration for one of the memory block, including the memory access
832 * control policy and nse enable.
833 *
834 * param base TRDC peripheral base address.
835 * param config Pointer to memory block configuration structure.
836 */
TRDC_MbcSetMemoryBlockConfig(TRDC_Type * base,const trdc_mbc_memory_block_config_t * config)837 void TRDC_MbcSetMemoryBlockConfig(TRDC_Type *base, const trdc_mbc_memory_block_config_t *config)
838 {
839 assert(NULL != base);
840
841 uint32_t shift = 4UL * (config->memoryBlockIdx % 8UL);
842 uint32_t regAddr = (uint32_t) & (TRDC_MBC_BASE(base, config->mbcIdx)->MBC_DOM0_MEM0_BLK_CFG_W[0]);
843 uint32_t configWord = 0U;
844 trdc_reg32_convert_t pid;
845
846 pid._mbc_memory_blk = *config;
847 configWord = (pid._u32 & 0xFU) << shift;
848
849 regAddr += (TRDC_MBC_DOMAIN_INCREMENT * config->domainIdx + TRDC_MBC_SLAVE_INCREMENT(config->slaveMemoryIdx)) +
850 ((uint32_t)config->memoryBlockIdx / 8U) * sizeof(uint32_t);
851 configWord = configWord | (*(uint32_t *)regAddr & ~(0xFUL << shift));
852 *(uint32_t *)regAddr = configWord;
853 }
854 #endif
855