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