1 /*
2 * Copyright 2017-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #ifndef FSL_RDC_H_
9 #define FSL_RDC_H_
10
11 #include "fsl_common.h"
12
13 /*!
14 * @addtogroup rdc
15 * @{
16 */
17
18 /******************************************************************************
19 * Definitions
20 *****************************************************************************/
21 #define FSL_RDC_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
22
23 #define RDC_ACCESS_POLICY(domainID, policy) (uint16_t)((uint16_t)(policy) << ((domainID)*2U))
24
25 /*!
26 * @brief RDC hardware configuration.
27 */
28 typedef struct _rdc_hardware_config
29 {
30 uint32_t domainNumber : 4; /*!< Number of domains. */
31 uint32_t masterNumber : 8; /*!< Number of bus masters. */
32 uint32_t periphNumber : 8; /*!< Number of peripherals. */
33 uint32_t memNumber : 8; /*!< Number of memory regions. */
34 uint32_t : 4;
35 } rdc_hardware_config_t;
36
37 /*!
38 * @brief RDC interrupts
39 */
40 enum _rdc_interrupts
41 {
42 kRDC_RestoreCompleteInterrupt = RDC_INTCTRL_RCI_EN_MASK,
43 /*!< Interrupt generated when the RDC has completed restoring state to a recently re-powered memory regions. */
44 };
45
46 /*!
47 * @brief RDC status
48 */
49 enum _rdc_flags
50 {
51 kRDC_PowerDownDomainOn = RDC_STAT_PDS_MASK, /*!< Power down domain is ON. */
52 };
53
54 /*!
55 * @brief Master domain assignment.
56 */
57 typedef struct _rdc_domain_assignment
58 {
59 uint32_t domainId : 2U; /*!< Domain ID. */
60 uint32_t : 29U; /*!< Reserved. */
61 uint32_t lock : 1U; /*!< Lock the domain assignment. */
62 } rdc_domain_assignment_t;
63
64 /*!
65 * @brief Access permission policy.
66 */
67 enum _rdc_access_policy
68 {
69 kRDC_NoAccess = 0, /*!< Could not read or write. */
70 kRDC_WriteOnly = 1, /*!< Write only. */
71 kRDC_ReadOnly = 2, /*!< Read only. */
72 kRDC_ReadWrite = 3, /*!< Read and write. */
73 };
74
75 /*!
76 * @brief Peripheral domain access permission configuration.
77 */
78 typedef struct _rdc_periph_access_config
79 {
80 rdc_periph_t periph; /*!< Peripheral name. */
81 bool lock; /*!< Lock the permission until reset. */
82 bool enableSema; /*!< Enable semaphore or not, when enabled, master should
83 call @ref RDC_SEMA42_Lock to lock the semaphore gate
84 accordingly before access the peripheral. */
85 uint16_t policy; /*!< Access policy. */
86 } rdc_periph_access_config_t;
87
88 /*!
89 * @brief Memory region domain access control configuration.
90 *
91 * Note that when setting the @ref rdc_mem_access_config_t::baseAddress
92 * and @ref rdc_mem_access_config_t::endAddress,
93 * should be aligned to the region resolution, see rdc_mem_t
94 * definitions.
95 */
96 typedef struct _rdc_mem_access_config
97 {
98 rdc_mem_t mem; /*!< Memory region descriptor name. */
99
100 bool lock; /*!< Lock the configuration. */
101 uint64_t baseAddress; /*!< Start address of the memory region. */
102 uint64_t endAddress; /*!< End address of the memory region. */
103 uint16_t policy; /*!< Access policy. */
104 } rdc_mem_access_config_t;
105
106 /*!
107 * @brief Memory region access violation status.
108 */
109 typedef struct _rdc_mem_status
110 {
111 bool hasViolation; /*!< Violating happens or not. */
112 uint8_t domainID; /*!< Violating Domain ID. */
113 uint64_t address; /*!< Violating Address. */
114 } rdc_mem_status_t;
115
116 /*******************************************************************************
117 * API
118 ******************************************************************************/
119
120 #if defined(__cplusplus)
121 extern "C" {
122 #endif
123
124 /*!
125 * @brief Initializes the RDC module.
126 *
127 * This function enables the RDC clock.
128 *
129 * @param base RDC peripheral base address.
130 */
131 void RDC_Init(RDC_Type *base);
132
133 /*!
134 * @brief De-initializes the RDC module.
135 *
136 * This function disables the RDC clock.
137 *
138 * @param base RDC peripheral base address.
139 */
140 void RDC_Deinit(RDC_Type *base);
141
142 /*!
143 * @brief Gets the RDC hardware configuration.
144 *
145 * This function gets the RDC hardware configurations, including number of bus
146 * masters, number of domains, number of memory regions and number of peripherals.
147 *
148 * @param base RDC peripheral base address.
149 * @param config Pointer to the structure to get the configuration.
150 */
151 void RDC_GetHardwareConfig(RDC_Type *base, rdc_hardware_config_t *config);
152
153 /*!
154 * @brief Enable interrupts.
155 *
156 * @param base RDC peripheral base address.
157 * @param mask Interrupts to enable, it is OR'ed value of enum @ref _rdc_interrupts.
158 */
RDC_EnableInterrupts(RDC_Type * base,uint32_t mask)159 static inline void RDC_EnableInterrupts(RDC_Type *base, uint32_t mask)
160 {
161 base->INTCTRL |= mask;
162 }
163
164 /*!
165 * @brief Disable interrupts.
166 *
167 * @param base RDC peripheral base address.
168 * @param mask Interrupts to disable, it is OR'ed value of enum @ref _rdc_interrupts.
169 */
RDC_DisableInterrupts(RDC_Type * base,uint32_t mask)170 static inline void RDC_DisableInterrupts(RDC_Type *base, uint32_t mask)
171 {
172 base->INTCTRL &= ~mask;
173 }
174
175 /*!
176 * @brief Get the interrupt pending status.
177 *
178 * @param base RDC peripheral base address.
179 * @return Interrupts pending status, it is OR'ed value of enum @ref _rdc_interrupts.
180 */
RDC_GetInterruptStatus(RDC_Type * base)181 static inline uint32_t RDC_GetInterruptStatus(RDC_Type *base)
182 {
183 return base->INTSTAT;
184 }
185
186 /*!
187 * @brief Clear interrupt pending status.
188 *
189 * @param base RDC peripheral base address.
190 * @param mask Status to clear, it is OR'ed value of enum @ref _rdc_interrupts.
191 */
RDC_ClearInterruptStatus(RDC_Type * base,uint32_t mask)192 static inline void RDC_ClearInterruptStatus(RDC_Type *base, uint32_t mask)
193 {
194 base->INTSTAT = mask;
195 }
196
197 /*!
198 * @brief Get RDC status.
199 *
200 * @param base RDC peripheral base address.
201 * @return mask RDC status, it is OR'ed value of enum @ref _rdc_flags.
202 */
RDC_GetStatus(RDC_Type * base)203 static inline uint32_t RDC_GetStatus(RDC_Type *base)
204 {
205 return base->STAT;
206 }
207
208 /*!
209 * @brief Clear RDC status.
210 *
211 * @param base RDC peripheral base address.
212 * @param mask RDC status to clear, it is OR'ed value of enum @ref _rdc_flags.
213 */
RDC_ClearStatus(RDC_Type * base,uint32_t mask)214 static inline void RDC_ClearStatus(RDC_Type *base, uint32_t mask)
215 {
216 base->STAT = mask;
217 }
218
219 /*!
220 * @brief Set master domain assignment
221 *
222 * @param base RDC peripheral base address.
223 * @param master Which master to set.
224 * @param domainAssignment Pointer to the assignment.
225 */
226 void RDC_SetMasterDomainAssignment(RDC_Type *base,
227 rdc_master_t master,
228 const rdc_domain_assignment_t *domainAssignment);
229
230 /*!
231 * @brief Get default master domain assignment
232 *
233 * The default configuration is:
234 * @code
235 assignment->domainId = 0U;
236 assignment->lock = 0U;
237 @endcode
238 *
239 * @param domainAssignment Pointer to the assignment.
240 */
241 void RDC_GetDefaultMasterDomainAssignment(rdc_domain_assignment_t *domainAssignment);
242
243 /*!
244 * @brief Lock master domain assignment
245 *
246 * Once locked, it could not be unlocked until next reset.
247 *
248 * @param base RDC peripheral base address.
249 * @param master Which master to lock.
250 */
RDC_LockMasterDomainAssignment(RDC_Type * base,rdc_master_t master)251 static inline void RDC_LockMasterDomainAssignment(RDC_Type *base, rdc_master_t master)
252 {
253 assert((uint32_t)master < RDC_MDA_COUNT);
254
255 base->MDA[master] |= RDC_MDA_LCK_MASK;
256 __DSB();
257 }
258
259 /*!
260 * @brief Set peripheral access policy.
261 *
262 * @param base RDC peripheral base address.
263 * @param config Pointer to the policy configuration.
264 */
265 void RDC_SetPeriphAccessConfig(RDC_Type *base, const rdc_periph_access_config_t *config);
266
267 /*!
268 * @brief Get default peripheral access policy.
269 *
270 * The default configuration is:
271 * @code
272 config->lock = false;
273 config->enableSema = false;
274 config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
275 RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
276 RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
277 RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
278 @endcode
279 *
280 * @param config Pointer to the policy configuration.
281 */
282 void RDC_GetDefaultPeriphAccessConfig(rdc_periph_access_config_t *config);
283
284 /*!
285 * @brief Lock peripheral access policy configuration.
286 *
287 * Once locked, it could not be unlocked until reset.
288 *
289 * @param base RDC peripheral base address.
290 * @param periph Which peripheral to lock.
291 */
RDC_LockPeriphAccessConfig(RDC_Type * base,rdc_periph_t periph)292 static inline void RDC_LockPeriphAccessConfig(RDC_Type *base, rdc_periph_t periph)
293 {
294 assert((uint32_t)periph < RDC_PDAP_COUNT);
295
296 base->PDAP[periph] |= RDC_PDAP_LCK_MASK;
297 __DSB();
298 }
299
300 /*!
301 * @brief Get the peripheral access policy for specific domain.
302 *
303 * @param base RDC peripheral base address.
304 * @param periph Which peripheral to get.
305 * @param domainId Get policy for which domain.
306 * @return Access policy, see @ref _rdc_access_policy.
307 */
RDC_GetPeriphAccessPolicy(RDC_Type * base,rdc_periph_t periph,uint8_t domainId)308 static inline uint8_t RDC_GetPeriphAccessPolicy(RDC_Type *base, rdc_periph_t periph, uint8_t domainId)
309 {
310 assert((uint32_t)periph < RDC_PDAP_COUNT);
311
312 return (uint8_t)((base->PDAP[periph] >> (domainId * 2U)) & 0x03U);
313 }
314
315 /*!
316 * @brief Set memory region access policy.
317 *
318 * Note that when setting the baseAddress and endAddress in @p config,
319 * should be aligned to the region resolution, see rdc_mem_t
320 * definitions.
321 *
322 * @param base RDC peripheral base address.
323 * @param config Pointer to the policy configuration.
324 */
325 void RDC_SetMemAccessConfig(RDC_Type *base, const rdc_mem_access_config_t *config);
326
327 /*!
328 * @brief Get default memory region access policy.
329 *
330 * The default configuration is:
331 * @code
332 config->lock = false;
333 config->baseAddress = 0;
334 config->endAddress = 0;
335 config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
336 RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
337 RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
338 RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
339 @endcode
340 *
341 * @param config Pointer to the policy configuration.
342 */
343 void RDC_GetDefaultMemAccessConfig(rdc_mem_access_config_t *config);
344
345 /*!
346 * @brief Lock memory access policy configuration.
347 *
348 * Once locked, it could not be unlocked until reset. After locked, you can
349 * only call @ref RDC_SetMemAccessValid to enable the configuration, but can not
350 * disable it or change other settings.
351 *
352 * @param base RDC peripheral base address.
353 * @param mem Which memory region to lock.
354 */
RDC_LockMemAccessConfig(RDC_Type * base,rdc_mem_t mem)355 static inline void RDC_LockMemAccessConfig(RDC_Type *base, rdc_mem_t mem)
356 {
357 assert((uint32_t)mem < RDC_MRC_COUNT);
358
359 base->MR[mem].MRC |= RDC_MRC_LCK_MASK;
360 __DSB();
361 }
362
363 /*!
364 * @brief Enable or disable memory access policy configuration.
365 *
366 * @param base RDC peripheral base address.
367 * @param mem Which memory region to operate.
368 * @param valid Pass in true to valid, false to invalid.
369 */
RDC_SetMemAccessValid(RDC_Type * base,rdc_mem_t mem,bool valid)370 static inline void RDC_SetMemAccessValid(RDC_Type *base, rdc_mem_t mem, bool valid)
371 {
372 assert((uint32_t)mem < RDC_MRC_COUNT);
373
374 if (valid)
375 {
376 base->MR[mem].MRC |= RDC_MRC_ENA_MASK;
377 }
378 else
379 {
380 base->MR[mem].MRC &= ~RDC_MRC_ENA_MASK;
381 }
382 __DSB();
383 }
384
385 /*!
386 * @brief Get the memory region violation status.
387 *
388 * The first access violation is captured. Subsequent violations are ignored
389 * until the status register is cleared. Contents are cleared upon reading the
390 * register. Clearing of contents occurs only when the status is read by the
391 * memory region's associated domain ID(s).
392 *
393 * @param base RDC peripheral base address.
394 * @param mem Which memory region to get.
395 * @param status The returned status.
396 */
397 void RDC_GetMemViolationStatus(RDC_Type *base, rdc_mem_t mem, rdc_mem_status_t *status);
398
399 /*!
400 * @brief Clear the memory region violation flag.
401 *
402 * @param base RDC peripheral base address.
403 * @param mem Which memory region to clear.
404 */
RDC_ClearMemViolationFlag(RDC_Type * base,rdc_mem_t mem)405 static inline void RDC_ClearMemViolationFlag(RDC_Type *base, rdc_mem_t mem)
406 {
407 assert((uint32_t)mem < RDC_MRC_COUNT);
408
409 base->MR[mem].MRVS = RDC_MRVS_AD_MASK;
410 }
411
412 /*!
413 * @brief Get the memory region access policy for specific domain.
414 *
415 * @param base RDC peripheral base address.
416 * @param mem Which memory region to get.
417 * @param domainId Get policy for which domain.
418 * @return Access policy, see @ref _rdc_access_policy.
419 */
RDC_GetMemAccessPolicy(RDC_Type * base,rdc_mem_t mem,uint8_t domainId)420 static inline uint8_t RDC_GetMemAccessPolicy(RDC_Type *base, rdc_mem_t mem, uint8_t domainId)
421 {
422 assert((uint32_t)mem < RDC_MRC_COUNT);
423
424 return (uint8_t)((base->MR[mem].MRC >> (domainId * 2U)) & 0x03U);
425 }
426
427 /*!
428 * @brief Gets the domain ID of the current bus master.
429 *
430 * This function returns the domain ID of the current bus master.
431 *
432 * @param base RDC peripheral base address.
433 * @return Domain ID of current bus master.
434 */
RDC_GetCurrentMasterDomainId(RDC_Type * base)435 static inline uint8_t RDC_GetCurrentMasterDomainId(RDC_Type *base)
436 {
437 return (uint8_t)((base->STAT & RDC_STAT_DID_MASK) >> RDC_STAT_DID_SHIFT);
438 }
439
440 #if defined(__cplusplus)
441 }
442 #endif
443
444 /*!
445 * @}
446 */
447
448 #endif /* FSL_RDC_H_ */
449