1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017, 2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_xrdc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.xrdc"
18 #endif
19 
20 #define XRDC_DERR_W1_EST_VAL(w1)   (uint8_t)(((w1)&XRDC_DERR_W_EST_MASK) >> XRDC_DERR_W_EST_SHIFT)
21 #define XRDC_DERR_W1_EPORT_VAL(w1) (uint8_t)(((w1)&XRDC_DERR_W_EPORT_MASK) >> XRDC_DERR_W_EPORT_SHIFT)
22 #define XRDC_DERR_W1_ERW_VAL(w1)   (uint8_t)(((w1)&XRDC_DERR_W_ERW_MASK) >> XRDC_DERR_W_ERW_SHIFT)
23 #define XRDC_DERR_W1_EATR_VAL(w1)  (uint8_t)(((w1)&XRDC_DERR_W_EATR_MASK) >> XRDC_DERR_W_EATR_SHIFT)
24 #define XRDC_DERR_W1_EDID_VAL(w1)  (uint8_t)(((w1)&XRDC_DERR_W_EDID_MASK) >> XRDC_DERR_W_EDID_SHIFT)
25 
26 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
27 #define XRDC_MRGD_DXACP_WIDTH (3U) /* The width of XRDC_MRDG_DxACP. */
28 #elif (defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
29 #define XRDC_MRGD_DXSEL_WIDTH (3U) /* The width of XRDC_MRDG_DxSEL. */
30 #endif
31 #define XRDC_PDAC_DXACP_WIDTH (3U) /* The width of XRDC_PDAC_DxACP. */
32 
33 /* For the force exclusive accesss lock release procedure. */
34 #define XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1 (0x02000046U) /* The width of XRDC_MRDG_DxACP. */
35 #define XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2 (0x02000052U) /* The width of XRDC_PDAC_DxACP. */
36 
37 typedef union
38 {
39     xrdc_pid_config_t _pid;
40     uint32_t _u32;
41 } xrdc_pid_reg_t;
42 
43 typedef union
44 {
45     xrdc_processor_domain_assignment_t _mdaProc;
46     xrdc_non_processor_domain_assignment_t _mdaNonProc;
47     uint32_t _u32;
48 } xrdc_mda_reg_t;
49 
50 /*******************************************************************************
51  * Variables
52  ******************************************************************************/
53 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
54 /* Clock name of XRDC. */
55 #if (FSL_CLOCK_XRDC_GATE_COUNT > 1)
56 static const clock_ip_name_t s_xrdcClock[] = XRDC_CLOCKS;
57 #endif
58 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
59 
60 /*******************************************************************************
61  * Code
62  ******************************************************************************/
63 
64 #if ((__CORTEX_M == 0U) && (defined(__ICCARM__)))
65 /*!
66  * @brief Count the leading zeros.
67  *
68  * Count the leading zeros of an 32-bit data. This function is only defined
69  * for CM0 and CM0+ for IAR, because other cortex series have the clz instruction,
70  * KEIL and ARMGCC have toolchain build in function for this purpose.
71  *
72  * @param data The data to process.
73  * @return Count of the leading zeros.
74  */
XRDC_CountLeadingZeros(uint32_t data)75 static uint8_t XRDC_CountLeadingZeros(uint32_t data)
76 {
77     uint8_t count = 0U;
78     uint32_t mask = 0x80000000U;
79 
80     while ((data & mask) == 0U)
81     {
82         count++;
83         mask >>= 1U;
84     }
85 
86     return count;
87 }
88 #endif
89 
90 /*!
91  * brief Initializes the XRDC module.
92  *
93  * This function enables the XRDC clock.
94  *
95  * param base XRDC peripheral base address.
96  */
XRDC_Init(XRDC_Type * base)97 void XRDC_Init(XRDC_Type *base)
98 {
99 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
100 
101 #if (FSL_CLOCK_XRDC_GATE_COUNT > 0)
102 #if (FSL_CLOCK_XRDC_GATE_COUNT == 1)
103     CLOCK_EnableClock(kCLOCK_Xrdc0);
104 #else
105     uint8_t i;
106 
107     for (i = 0; i < ARRAY_SIZE(s_xrdcClock); i++)
108     {
109         CLOCK_EnableClock(s_xrdcClock[i]);
110     }
111 #endif
112 #endif
113 
114 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
115 }
116 
117 /*!
118  * brief De-initializes the XRDC module.
119  *
120  * This function disables the XRDC clock.
121  *
122  * param base XRDC peripheral base address.
123  */
XRDC_Deinit(XRDC_Type * base)124 void XRDC_Deinit(XRDC_Type *base)
125 {
126 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
127 
128 #if (FSL_CLOCK_XRDC_GATE_COUNT > 0)
129 #if (FSL_CLOCK_XRDC_GATE_COUNT == 1)
130     CLOCK_EnableClock(kCLOCK_Xrdc0);
131 #else
132     uint8_t i;
133 
134     for (i = 0; i < ARRAY_SIZE(s_xrdcClock); i++)
135     {
136         CLOCK_DisableClock(s_xrdcClock[i]);
137     }
138 #endif
139 #endif
140 
141 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
142 }
143 
144 /*!
145  * brief Gets the XRDC hardware configuration.
146  *
147  * This function gets the XRDC hardware configurations, including number of bus
148  * masters, number of domains, number of MRCs and number of PACs.
149  *
150  * param base XRDC peripheral base address.
151  * param config Pointer to the structure to get the configuration.
152  */
XRDC_GetHardwareConfig(XRDC_Type * base,xrdc_hardware_config_t * config)153 void XRDC_GetHardwareConfig(XRDC_Type *base, xrdc_hardware_config_t *config)
154 {
155     assert(NULL != config);
156 
157     config->masterNumber = (uint8_t)((base->HWCFG0 & XRDC_HWCFG0_NMSTR_MASK) >> XRDC_HWCFG0_NMSTR_SHIFT) + 1U;
158     config->domainNumber = (uint8_t)((base->HWCFG0 & XRDC_HWCFG0_NDID_MASK) >> XRDC_HWCFG0_NDID_SHIFT) + 1U;
159     config->pacNumber    = (uint8_t)((base->HWCFG0 & XRDC_HWCFG0_NPAC_MASK) >> XRDC_HWCFG0_NPAC_SHIFT) + 1U;
160     config->mrcNumber    = (uint8_t)((base->HWCFG0 & XRDC_HWCFG0_NMRC_MASK) >> XRDC_HWCFG0_NMRC_SHIFT) + 1U;
161 }
162 
163 /*!
164  * brief Gets and clears the first domain error of the current domain.
165  *
166  * This function gets the first access violation information for the current domain
167  * and clears the pending flag. There might be multiple access violations pending
168  * for the current domain. This function only processes the first error.
169  *
170  * param base XRDC peripheral base address.
171  * param error Pointer to the error information.
172  * return If the access violation is captured, this function returns the kStatus_Success.
173  *         The error information can be obtained from the parameter error. If no
174  *         access violation is captured, this function returns the kStatus_XRDC_NoError.
175  */
XRDC_GetAndClearFirstDomainError(XRDC_Type * base,xrdc_error_t * error)176 status_t XRDC_GetAndClearFirstDomainError(XRDC_Type *base, xrdc_error_t *error)
177 {
178     return XRDC_GetAndClearFirstSpecificDomainError(base, error, XRDC_GetCurrentMasterDomainId(base));
179 }
180 
181 /*!
182  * brief Gets and clears the first domain error of the specific domain.
183  *
184  * This function gets the first access violation information for the specific domain
185  * and clears the pending flag. There might be multiple access violations pending
186  * for the current domain. This function only processes the first error.
187  *
188  * param base XRDC peripheral base address.
189  * param error Pointer to the error information.
190  * param domainId The error of which domain to get and clear.
191  * return If the access violation is captured, this function returns the kStatus_Success.
192  *         The error information can be obtained from the parameter error. If no
193  *         access violation is captured, this function returns the kStatus_XRDC_NoError.
194  */
XRDC_GetAndClearFirstSpecificDomainError(XRDC_Type * base,xrdc_error_t * error,uint8_t domainId)195 status_t XRDC_GetAndClearFirstSpecificDomainError(XRDC_Type *base, xrdc_error_t *error, uint8_t domainId)
196 {
197     assert(NULL != error);
198 
199     status_t status;
200     uint8_t errorIndex;   /* The index of first domain error. */
201     uint32_t errorBitMap; /* Domain error location bit map.   */
202     uint32_t regW1;       /* To save XRDC_DERR_W1.            */
203 
204     if (domainId >= ARRAY_SIZE(base->DERRLOC))
205     {
206         return kStatus_InvalidArgument;
207     }
208 
209     /* Get the error bitmap. */
210     errorBitMap = base->DERRLOC[domainId];
211 
212     if (0U == errorBitMap) /* No error captured. */
213     {
214         status = kStatus_XRDC_NoError;
215     }
216     else
217     {
218         /* Get the first error controller index. */
219 #if ((__CORTEX_M == 0U) && (defined(__ICCARM__)))
220         errorIndex = 31U - XRDC_CountLeadingZeros(errorBitMap);
221 #else
222         errorIndex        = 31U - __CLZ(errorBitMap);
223 #endif
224 
225 #if (defined(FSL_FEATURE_XRDC_HAS_FDID) && FSL_FEATURE_XRDC_HAS_FDID)
226         /* Must write FDID[FDID] with the domain ID before reading the Domain Error registers. */
227         base->FDID = XRDC_FDID_FDID(domainId);
228 #endif /* FSL_FEATURE_XRDC_HAS_FDID */
229         /* Get the error information. */
230         regW1             = base->DERR_W[errorIndex][1];
231         error->controller = (xrdc_controller_t)errorIndex;
232         error->address    = base->DERR_W[errorIndex][0];
233         error->errorState = (xrdc_error_state_t)XRDC_DERR_W1_EST_VAL(regW1);
234         error->errorAttr  = (xrdc_error_attr_t)XRDC_DERR_W1_EATR_VAL(regW1);
235         error->errorType  = (xrdc_error_type_t)XRDC_DERR_W1_ERW_VAL(regW1);
236         error->errorPort  = XRDC_DERR_W1_EPORT_VAL(regW1);
237         error->domainId   = XRDC_DERR_W1_EDID_VAL(regW1);
238 
239         /* Clear error pending. */
240         base->DERR_W[errorIndex][3] = XRDC_DERR_W_RECR(0x01U);
241 
242         status = kStatus_Success;
243     }
244 
245     return status;
246 }
247 
248 /*!
249  * brief Gets the default PID configuration structure.
250  *
251  * This function initializes the configuration structure to default values. The default
252  * values are:
253  *
254  * code
255  * config->pid       = 0U;
256  * config->tsmEnable = 0U;
257  * config->sp4smEnable = 0U;
258  * config->lockMode  = kXRDC_PidLockSecurePrivilegeWritable;
259  * endcode
260  *
261  * param config Pointer to the configuration structure.
262  */
XRDC_GetPidDefaultConfig(xrdc_pid_config_t * config)263 void XRDC_GetPidDefaultConfig(xrdc_pid_config_t *config)
264 {
265     assert(NULL != config);
266 
267     xrdc_pid_reg_t pid;
268     pid._u32 = 0U;
269 
270     *config = pid._pid;
271 }
272 
273 /*!
274  * brief Configures the PID for a specific bus master.
275  *
276  * This function configures the PID for a specific bus master. Do not use this
277  * function for non-processor bus masters.
278  *
279  * param base XRDC peripheral base address.
280  * param master Which bus master to configure.
281  * param config Pointer to the configuration structure.
282  */
XRDC_SetPidConfig(XRDC_Type * base,xrdc_master_t master,const xrdc_pid_config_t * config)283 void XRDC_SetPidConfig(XRDC_Type *base, xrdc_master_t master, const xrdc_pid_config_t *config)
284 {
285     assert(NULL != config);
286 
287     xrdc_pid_reg_t pid;
288     pid._pid = *config;
289 
290     base->PID[master] = pid._u32;
291 }
292 
293 /*!
294  * brief Gets the default master domain assignment for non-processor bus master.
295  *
296  * This function gets the default master domain assignment for non-processor bus master.
297  * It should only be used for the non-processor bus masters, such as DMA. This function
298  * sets the assignment as follows:
299  *
300  * code
301  * assignment->domainId            = 0U;
302  * assignment->privilegeAttr       = kXRDC_ForceUser;
303  * assignment->privilegeAttr       = kXRDC_ForceSecure;
304  * assignment->bypassDomainId      = 0U;
305  * assignment->blogicPartId        = 0U;
306  * assignment->benableLogicPartId  = 0U;
307  * assignment->lock                = 0U;
308  * endcode
309  *
310  * param domainAssignment Pointer to the assignment structure.
311  */
XRDC_GetDefaultNonProcessorDomainAssignment(xrdc_non_processor_domain_assignment_t * domainAssignment)312 void XRDC_GetDefaultNonProcessorDomainAssignment(xrdc_non_processor_domain_assignment_t *domainAssignment)
313 {
314     assert(NULL != domainAssignment);
315 
316     xrdc_mda_reg_t mda;
317 
318     mda._u32 = 0U;
319 
320     *domainAssignment = mda._mdaNonProc;
321 }
322 
323 /*!
324  * brief Gets the default master domain assignment for the processor bus master.
325  *
326  * This function gets the default master domain assignment for the processor bus master.
327  * It should only be used for the processor bus masters, such as CORE0. This function
328  * sets the assignment as follows:
329  *
330  * code
331  * assignment->domainId           = 0U;
332  * assignment->domainIdSelect     = kXRDC_DidMda;
333  * assignment->dpidEnable         = kXRDC_PidDisable;
334  * assignment->pidMask            = 0U;
335  * assignment->pid                = 0U;
336  * assignment->logicPartId        = 0U;
337  * assignment->enableLogicPartId  = 0U;
338  * assignment->lock               = 0U;
339  * endcode
340  *
341  * param domainAssignment Pointer to the assignment structure.
342  */
XRDC_GetDefaultProcessorDomainAssignment(xrdc_processor_domain_assignment_t * domainAssignment)343 void XRDC_GetDefaultProcessorDomainAssignment(xrdc_processor_domain_assignment_t *domainAssignment)
344 {
345     assert(NULL != domainAssignment);
346 
347     xrdc_mda_reg_t mda;
348 
349     mda._u32 = 0U;
350 
351     *domainAssignment = mda._mdaProc;
352 }
353 
354 /*!
355  * brief Sets the non-processor bus master domain assignment.
356  *
357  * This function sets the non-processor master domain assignment as valid.
358  * One bus master might have multiple domain assignment registers. The parameter
359  * \p assignIndex specifies which assignment register to set.
360  *
361  * Example: Set domain assignment for DMA0.
362  * code
363  * xrdc_non_processor_domain_assignment_t nonProcessorAssignment;
364  *
365  * XRDC_GetDefaultNonProcessorDomainAssignment(&nonProcessorAssignment);
366  * nonProcessorAssignment.domainId = 1;
367  * nonProcessorAssignment.xxx      = xxx;
368  *
369  * XRDC_SetMasterDomainAssignment(XRDC, kXrdcMasterDma0, 0U, &nonProcessorAssignment);
370  * endcode
371  *
372  * param base XRDC peripheral base address.
373  * param master Which master to configure.
374  * param assignIndex Which assignment register to set.
375  * param domainAssignment Pointer to the assignment structure.
376  */
XRDC_SetNonProcessorDomainAssignment(XRDC_Type * base,xrdc_master_t master,uint8_t assignIndex,const xrdc_non_processor_domain_assignment_t * domainAssignment)377 void XRDC_SetNonProcessorDomainAssignment(XRDC_Type *base,
378                                           xrdc_master_t master,
379                                           uint8_t assignIndex,
380                                           const xrdc_non_processor_domain_assignment_t *domainAssignment)
381 {
382     /* Make sure the master is a non-CPU/non-processor master */
383     assert(0U != (base->MDACFG[master] & XRDC_MDACFG_NCM_MASK));
384     /* Make sure the master has the assignment register. */
385     assert(assignIndex < ((base->MDACFG[master] & XRDC_MDACFG_NMDAR_MASK) >> XRDC_MDACFG_NMDAR_SHIFT));
386     assert(NULL != domainAssignment);
387 
388     xrdc_mda_reg_t mda;
389 
390     mda._mdaNonProc = *domainAssignment;
391 
392     base->MDA[master].MDA_W[assignIndex] = (mda._u32 | XRDC_MDA_W_VLD_MASK);
393 }
394 
395 /*!
396  * brief Sets the processor bus master domain assignment.
397  *
398  * This function sets the processor master domain assignment as valid.
399  * One bus master might have multiple domain assignment registers. The parameter
400  * \p assignIndex specifies which assignment register to set.
401  *
402  * Example: Set domain assignment for core 0.
403  * In this example, there are 3 assignment registers for core 0.
404  *
405  * code
406  * xrdc_processor_domain_assignment_t processorAssignment;
407  *
408  * XRDC_GetDefaultProcessorDomainAssignment(&processorAssignment);
409  *
410  * processorAssignment.domainId = 1;
411  * processorAssignment.xxx      = xxx;
412  * XRDC_SetMasterDomainAssignment(XRDC, kXrdcMasterCpu0, 0U, &processorAssignment);
413  *
414  * processorAssignment.domainId = 2;
415  * processorAssignment.xxx      = xxx;
416  * XRDC_SetMasterDomainAssignment(XRDC, kXrdcMasterCpu0, 1U, &processorAssignment);
417  *
418  * processorAssignment.domainId = 0;
419  * processorAssignment.xxx      = xxx;
420  * XRDC_SetMasterDomainAssignment(XRDC, kXrdcMasterCpu0, 2U, &processorAssignment);
421  * endcode
422  *
423  * param base XRDC peripheral base address.
424  * param master Which master to configure.
425  * param assignIndex Which assignment register to set.
426  * param domainAssignment Pointer to the assignment structure.
427  */
XRDC_SetProcessorDomainAssignment(XRDC_Type * base,xrdc_master_t master,uint8_t assignIndex,const xrdc_processor_domain_assignment_t * domainAssignment)428 void XRDC_SetProcessorDomainAssignment(XRDC_Type *base,
429                                        xrdc_master_t master,
430                                        uint8_t assignIndex,
431                                        const xrdc_processor_domain_assignment_t *domainAssignment)
432 {
433     /* Make sure the master is a CPU/processor master */
434     assert(0U == (base->MDACFG[master] & XRDC_MDACFG_NCM_MASK));
435     /* Make sure the master has the assignment register. */
436     assert(assignIndex < ((base->MDACFG[master] & XRDC_MDACFG_NMDAR_MASK) >> XRDC_MDACFG_NMDAR_SHIFT));
437     assert(NULL != domainAssignment);
438 
439     xrdc_mda_reg_t mda;
440 
441     mda._mdaProc = *domainAssignment;
442 
443     base->MDA[master].MDA_W[assignIndex] = (mda._u32 | XRDC_MDA_W_VLD_MASK);
444 }
445 
446 /*!
447  * brief Gets the default memory region access policy.
448  *
449  * This function gets the default memory region access policy.
450  * It sets the policy as follows:
451  * code
452  * config->enableSema            = false;
453  * config->semaNum               = 0U;
454  * config->subRegionDisableMask  = 0U;
455  * config->size                  = kXrdcMemSizeNone;
456  * config->lockMode              = kXRDC_AccessConfigLockWritable;
457  * config->baseAddress           = 0U;
458  * config->policy[0]             = kXRDC_AccessPolicyNone;
459  * config->policy[1]             = kXRDC_AccessPolicyNone;
460  * ...
461  * config->policy[15]            = kXRDC_AccessPolicyNone;
462  * endcode
463  *
464  * param config Pointer to the configuration structure.
465  */
XRDC_GetMemAccessDefaultConfig(xrdc_mem_access_config_t * config)466 void XRDC_GetMemAccessDefaultConfig(xrdc_mem_access_config_t *config)
467 {
468     assert(NULL != config);
469 
470     /* Initializes the configure structure to zero. */
471     (void)memset(config, 0, sizeof(*config));
472 
473     uint8_t i;
474 
475 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
476     config->enableSema = false;
477     config->semaNum    = 0U;
478 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
479 
480 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
481     config->size = kXRDC_MemSizeNone;
482 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
483 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SRD) && FSL_FEATURE_XRDC_NO_MRGD_SRD)
484     config->subRegionDisableMask = 0U;
485 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SRD */
486 
487 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_CR) && FSL_FEATURE_XRDC_HAS_MRGD_CR)
488     config->codeRegion = kXRDC_MemCodeRegion0;
489 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_CR */
490 
491 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
492     config->enableAccset1Lock = false;
493     config->enableAccset2Lock = false;
494     config->accset1           = 0x000U;
495     config->accset2           = 0x000U;
496 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_ACCSET */
497 
498     config->lockMode = kXRDC_AccessConfigLockWritable;
499 
500     config->baseAddress = 0U;
501 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR) && FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR)
502     config->endAddress = 0U;
503 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR */
504 
505     for (i = 0U; i < (uint32_t)FSL_FEATURE_XRDC_DOMAIN_COUNT; i++)
506     {
507 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
508         config->policy[i] = kXRDC_AccessPolicyNone;
509 #elif (defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
510         config->policy[i] = kXRDC_AccessFlagsNone;
511 #endif
512     }
513 
514 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
515     config->exclAccessLockMode = kXRDC_ExclAccessLockDisabled;
516 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_EAL */
517 }
518 
519 /*!
520  * brief Sets the memory region access policy.
521  *
522  * This function sets the memory region access configuration as valid.
523  * There are two methods to use it:
524  *
525  * Example 1: Set one configuration run time.
526  * code
527  * xrdc_mem_access_config_t config =
528  * {
529  *     .mem         = kXRDC_MemMrc0_1,
530  *     .baseAddress = 0x20000000U,
531  *     .size        = kXRDC_MemSize1K,
532  *     .policy[0]   = kXRDC_AccessPolicyAll
533  * };
534  * XRDC_SetMemAccessConfig(XRDC, &config);
535  * endcode
536  *
537  * Example 2: Set multiple configurations during startup.
538  * code
539  * xrdc_mem_access_config_t configs[] =
540  * {
541  *     {
542  *         .mem         = kXRDC_MemMrc0_1,
543  *         .baseAddress = 0x20000000U,
544  *         .size        = kXRDC_MemSize1K,
545  *         .policy[0]   = kXRDC_AccessPolicyAll
546  *     },
547  *     {
548  *         .mem         = kXRDC_MemMrc0_2,
549  *         .baseAddress = 0x1FFF0000U,
550  *         .size        = kXRDC_MemSize2K,
551  *         .policy[0]   = kXRDC_AccessPolicyAll
552  *     }
553  * };
554  *
555  * for (i=0U; i<((sizeof(configs)/sizeof(configs[0]))); i++)
556  * {
557  *     XRDC_SetMemAccessConfig(XRDC, &configs[i]);
558  * }
559  * endcode
560  *
561  * param base XRDC peripheral base address.
562  * param config Pointer to the access policy configuration structure.
563  */
XRDC_SetMemAccessConfig(XRDC_Type * base,const xrdc_mem_access_config_t * config)564 void XRDC_SetMemAccessConfig(XRDC_Type *base, const xrdc_mem_access_config_t *config)
565 {
566     assert(NULL != config);
567 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
568     /* Not allowed to set sub-region disable mask for memory region smaller than 256-bytes. */
569     assert(!((config->size < kXRDC_MemSize256B) && (0U != config->subRegionDisableMask)));
570     /* Memory region minimum size = 32 bytes and base address must be aligned to 0-module-2**(SZ+1). */
571     assert(config->size >= kXRDC_MemSize32B);
572     assert(0U == (config->baseAddress & ((1UL << ((uint32_t)config->size + 1U)) - 1UL)));
573 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
574 
575     uint32_t i;
576     uint32_t regValue;
577     uint8_t index = (uint8_t)config->mem;
578 
579     /* Set MRGD_W0. */
580     base->MRGD[index].MRGD_W[0] = config->baseAddress;
581 
582 /* Set MRGD_W1. */
583 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
584     base->MRGD[index].MRGD_W[1] = XRDC_MRGD_W_SZ(config->size) | XRDC_MRGD_W_SRD(config->subRegionDisableMask);
585 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
586 
587 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR) && FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR)
588     base->MRGD[index].MRGD_W[1] = config->endAddress;
589 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR */
590 
591     /* Set MRGD_W2. */
592     regValue = 0U;
593 /* Set MRGD_W2[D0ACP ~ D7ACP] or MRGD_W2[D0SEL ~ D2SEL]. */
594 #if (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 8U)
595     i = FSL_FEATURE_XRDC_DOMAIN_COUNT;
596 #elif (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16U)
597     i = 8U;
598 #else
599 #error Does not support more than 16 domain.
600 #endif
601 
602     while (0U != (i--))
603     {
604 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
605         regValue <<= XRDC_MRGD_DXACP_WIDTH;
606 #elif (defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
607         regValue <<= XRDC_MRGD_DXSEL_WIDTH;
608 #endif
609         regValue |= (uint32_t)config->policy[i];
610     }
611 
612 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
613     regValue |= XRDC_MRGD_W_SE(config->enableSema) | XRDC_MRGD_W_SNUM(config->semaNum);
614 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
615 
616     base->MRGD[index].MRGD_W[2] = regValue;
617 
618     /* Set MRGD_W3. */
619     regValue = 0U;
620 
621 #if ((FSL_FEATURE_XRDC_DOMAIN_COUNT > 8U) && (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16))
622     /* Set MRGD_W3[D8ACP ~ D15ACP]. */
623     for (i = FSL_FEATURE_XRDC_DOMAIN_COUNT - 1U; i > 7U; i--)
624     {
625         regValue <<= XRDC_MRGD_DXACP_WIDTH;
626         regValue |= (uint32_t)config->policy[i];
627     }
628 #endif
629 
630 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_CR) && FSL_FEATURE_XRDC_HAS_MRGD_CR)
631     regValue |= XRDC_MRGD_W_CR(config->codeRegion);
632 #endif
633 
634 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_W3_VLD) && FSL_FEATURE_XRDC_NO_MRGD_W3_VLD)
635     regValue |= XRDC_MRGD_W_VLD_MASK | XRDC_MRGD_W_LK2(config->lockMode);
636 #endif
637 
638     base->MRGD[index].MRGD_W[3] = regValue;
639 
640 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
641     /*
642      * Set MRGD_W3[EAL].
643      * If write with a value of MRGD_W3[EAL]=0, then the other fields of MRGD_W3 are updated.
644      * If write with a value of MRGD_W3[EAL]!=0, then only the EAL is updated.
645      */
646     if (kXRDC_ExclAccessLockDisabled != config->exclAccessLockMode)
647     {
648         base->MRGD[index].MRGD_W[3] = XRDC_MRGD_W_EAL(config->exclAccessLockMode);
649     }
650 #endif
651 
652 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
653     /* Set MRGD_W4. */
654     base->MRGD[index].MRGD_W[4] = XRDC_MRGD_W_LKAS1(config->enableAccset1Lock) | XRDC_MRGD_W_ACCSET1(config->accset1) |
655                                   XRDC_MRGD_W_LKAS2(config->enableAccset2Lock) | XRDC_MRGD_W_ACCSET2(config->accset2) |
656                                   XRDC_MRGD_W_VLD_MASK | XRDC_MRGD_W_LK2(config->lockMode);
657 #endif
658 }
659 
660 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
661 /*!
662  * brief Sets the memory region exclusive access lock mode configuration.
663  *
664  * Note: Any write to MRGD_W[0-3]_n clears the MRGD_W4_n[VLD] indicator so a coherent register state can be supported.
665  *       It is indispensable to re-assert the valid bit when dynamically changing the EAL in the MRGD, which is done in
666  * this API.
667  *
668  * param base XRDC peripheral base address.
669  * param mem Which memory region's exclusive access lock mode to configure.
670  * param lockMode The exclusive access lock mode to set.
671  */
XRDC_SetMemExclAccessLockMode(XRDC_Type * base,xrdc_mem_t mem,xrdc_excl_access_lock_config_t lockMode)672 void XRDC_SetMemExclAccessLockMode(XRDC_Type *base, xrdc_mem_t mem, xrdc_excl_access_lock_config_t lockMode)
673 {
674     /* Write kXRDC_ExclAccessLockDisabled is not allowed. */
675     assert(kXRDC_ExclAccessLockDisabled != lockMode);
676 
677     uint32_t reg = base->MRGD[mem].MRGD_W[4];
678 
679     /* Step 1. Set the memory region exclusive access lock mode configuration. */
680     base->MRGD[mem].MRGD_W[3] = XRDC_MRGD_W_EAL(lockMode);
681 
682     /* Step 2. Set MRGD_W3 will clear the MRGD_W4[VLD]. So should re-assert it. */
683     base->MRGD[mem].MRGD_W[4] = reg;
684 }
685 
686 /*!
687  * brief Forces the release of the memory region exclusive access lock.
688  *
689  * A lock can be forced to the available state (EAL=10) by a domain that does not own the
690  * lock through the forced lock release procedure:
691  * The procedure to force a exclusive access lock release is as follows:
692  * 1. Write 0x02000046 to W1 register (PAC/MSC) or W3 register (MRC)
693  * 2. Write 0x02000052 to W1 register (PAC/MSC) or W3 register (MRC)
694  *
695  * Note: The two writes must be consecutive, any intervening write to the register resets the sequence.
696  *
697  * param base XRDC peripheral base address.
698  * param mem Which memory region's exclusive access lock to force release.
699  */
XRDC_ForceMemExclAccessLockRelease(XRDC_Type * base,xrdc_mem_t mem)700 void XRDC_ForceMemExclAccessLockRelease(XRDC_Type *base, xrdc_mem_t mem)
701 {
702     uint32_t primask;
703 
704     primask                   = DisableGlobalIRQ();
705     base->MRGD[mem].MRGD_W[3] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1;
706     base->MRGD[mem].MRGD_W[3] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2;
707     EnableGlobalIRQ(primask);
708 }
709 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_EAL */
710 
711 #if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
712 /*!
713  * brief Sets the memory region ACCSET (programmable access flags) lock.
714  *
715  * param base XRDC peripheral base address.
716  * param mem Which memory region descriptor to lock.
717  * param mem Which set/index of ACCSET to lock.
718  * param lock True to set lock, false to set unlock.
719  */
XRDC_SetMemAccsetLock(XRDC_Type * base,xrdc_mem_t mem,xrdc_mem_accset_t accset,bool lock)720 void XRDC_SetMemAccsetLock(XRDC_Type *base, xrdc_mem_t mem, xrdc_mem_accset_t accset, bool lock)
721 {
722     uint32_t lkasMask = 0U;
723 
724     if (kXRDC_MemAccset1 == accset)
725     {
726         lkasMask = XRDC_MRGD_W_LKAS1_MASK;
727     }
728     else
729     {
730         lkasMask = XRDC_MRGD_W_LKAS2_MASK;
731     }
732 
733     if (lock)
734     {
735         base->MRGD[mem].MRGD_W[4] |= lkasMask;
736     }
737     else
738     {
739         base->MRGD[mem].MRGD_W[4] &= ~lkasMask;
740     }
741 }
742 #endif /* FSL_FEATURE_XRDC_HAS_MRGD_ACCSET */
743 
744 /*!
745  * brief Gets the default peripheral access configuration.
746  *
747  * The default configuration is set as follows:
748  * code
749  * config->enableSema        = false;
750  * config->semaNum           = 0U;
751  * config->lockMode          = kXRDC_AccessConfigLockWritable;
752  * config->policy[0]         = kXRDC_AccessPolicyNone;
753  * config->policy[1]         = kXRDC_AccessPolicyNone;
754  * ...
755  * config->policy[15]        = kXRDC_AccessPolicyNone;
756  * endcode
757  *
758  * param config Pointer to the configuration structure.
759  */
XRDC_GetPeriphAccessDefaultConfig(xrdc_periph_access_config_t * config)760 void XRDC_GetPeriphAccessDefaultConfig(xrdc_periph_access_config_t *config)
761 {
762     assert(NULL != config);
763 
764     /* Initializes the configure structure to zero. */
765     (void)memset(config, 0, sizeof(*config));
766 
767     uint8_t i;
768 
769 #if !(defined(FSL_FEATURE_XRDC_NO_PDAC_SE) && FSL_FEATURE_XRDC_NO_PDAC_SE)
770     config->enableSema = false;
771     config->semaNum    = 0U;
772 #endif /* FSL_FEATURE_XRDC_NO_PDAC_SE */
773     config->lockMode = kXRDC_AccessConfigLockWritable;
774 #if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
775     config->exclAccessLockMode = kXRDC_ExclAccessLockDisabled;
776 #endif /* FSL_FEATURE_XRDC_HAS_PDAC_EAL */
777     for (i = 0U; i < (uint32_t)FSL_FEATURE_XRDC_DOMAIN_COUNT; i++)
778     {
779         config->policy[i] = kXRDC_AccessPolicyNone;
780     }
781 }
782 
783 /*!
784  * brief Sets the peripheral access configuration.
785  *
786  * This function sets the peripheral access configuration as valid. Two
787  * methods to use it:
788  * Method 1: Set for one peripheral, which is used for runtime settings.
789  * code
790  * xrdc_periph_access_config_t config;
791  *
792  * config.periph    = kXRDC_PeriphLptmr0;
793  * config.policy[0] = kXRDC_AccessPolicyAll;
794  * XRDC_SetPeriphAccessConfig(XRDC, &config);
795  * endcode
796  *
797  * Method 2: Set for multiple peripherals, which is used for initialization settings.
798  * code
799  * xrdc_periph_access_config_t configs[] =
800  * {
801  *     {
802  *         .periph    = kXRDC_PeriphLptmr0,
803  *         .policy[0] = kXRDC_AccessPolicyAll,
804  *         .policy[1] = kXRDC_AccessPolicyAll
805  *     },
806  *     {
807  *         .periph    = kXRDC_PeriphLpuart0,
808  *         .policy[0] = kXRDC_AccessPolicyAll,
809  *         .policy[1] = kXRDC_AccessPolicyAll
810  *     }
811  * };
812  *
813  * for (i=0U; i<(sizeof(configs)/sizeof(configs[0])), i++)
814  * {
815  *     XRDC_SetPeriphAccessConfig(XRDC, &config[i]);
816  * }
817  * endcode
818  *
819  * param base XRDC peripheral base address.
820  * param config Pointer to the configuration structure.
821  */
XRDC_SetPeriphAccessConfig(XRDC_Type * base,const xrdc_periph_access_config_t * config)822 void XRDC_SetPeriphAccessConfig(XRDC_Type *base, const xrdc_periph_access_config_t *config)
823 {
824     assert(NULL != config);
825 
826     uint32_t i;
827     uint32_t regValue;
828     uint8_t index = (uint8_t)config->periph;
829 
830     /* Set PDAC_W0[D0ACP ~ D7ACP]. */
831     regValue = 0U;
832 #if (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 8U)
833     i = FSL_FEATURE_XRDC_DOMAIN_COUNT;
834 #elif (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16U)
835     i = 8U;
836 #else
837 #error Does not support more than 16 domain.
838 #endif
839 
840     while (0U != (i--))
841     {
842         regValue <<= XRDC_PDAC_DXACP_WIDTH;
843         regValue |= (uint32_t)config->policy[i];
844     }
845 
846 #if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
847     regValue |= (XRDC_PDAC_W_SE(config->enableSema) | XRDC_PDAC_W_SNUM(config->semaNum));
848 #endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
849 
850     /* Set PDAC_W0. */
851     base->PDAC_W[index][0U] = regValue;
852 
853 #if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
854     /*
855      * If write with a value of PDAC_W1[EAL]=0, then the other fields of PDAC_W1 are updated.
856      * If write with a value of PDAC_W1[EAL]!=0, then only the EAL is updated.
857      */
858     base->PDAC_W[index][1U] = XRDC_PDAC_W_EAL(config->exclAccessLockMode);
859 #endif
860 
861     regValue = 0U;
862 #if ((FSL_FEATURE_XRDC_DOMAIN_COUNT > 8U) && (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16))
863     /* Set PDAC_W1[D8ACP ~ D15ACP]. */
864 
865     for (i = FSL_FEATURE_XRDC_DOMAIN_COUNT - 1U; i > 7U; i--)
866     {
867         regValue <<= XRDC_PDAC_DXACP_WIDTH;
868         regValue |= (uint32_t)config->policy[i];
869     }
870 #endif
871     /* Set PDAC_W1. */
872     base->PDAC_W[index][1] = regValue | XRDC_PDAC_W_VLD_MASK | XRDC_PDAC_W_LK2(config->lockMode);
873 }
874 
875 #if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
876 /*!
877  * brief Forces the release of the peripheral exclusive access lock.
878  *
879  * A lock can be forced to the available state (EAL=10) by a domain that does not own the
880  * lock through the forced lock release procedure:
881  * The procedure to force a exclusive access lock release is as follows:
882  * 1. Write 0x02000046 to W1 register (PAC/MSC) or W3 register (MRC)
883  * 2. Write 0x02000052 to W1 register (PAC/MSC) or W3 register (MRC)
884  *
885  * Note: The two writes must be consecutive, any intervening write to the register resets the sequence.
886  *
887  * param base XRDC peripheral base address.
888  * param periph Which peripheral's exclusive access lock to force release.
889  */
XRDC_ForcePeriphExclAccessLockRelease(XRDC_Type * base,xrdc_periph_t periph)890 void XRDC_ForcePeriphExclAccessLockRelease(XRDC_Type *base, xrdc_periph_t periph)
891 {
892     uint32_t primask;
893 
894     primask                 = DisableGlobalIRQ();
895     base->PDAC_W[periph][1] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1;
896     base->PDAC_W[periph][1] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2;
897     EnableGlobalIRQ(primask);
898 }
899 #endif /* FSL_FEATURE_XRDC_HAS_PDAC_EAL */
900