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