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 baseAddress and @ref endAddress,
92  * should be aligned to the region resolution, see rdc_mem_t
93  * definitions.
94  */
95 typedef struct _rdc_mem_access_config
96 {
97     rdc_mem_t mem; /*!< Memory region descriptor name. */
98 
99     bool lock;            /*!< Lock the configuration. */
100     uint64_t baseAddress; /*!< Start address of the memory region. */
101     uint64_t endAddress;  /*!< End address of the memory region.   */
102     uint16_t policy;      /*!< Access policy.                      */
103 } rdc_mem_access_config_t;
104 
105 /*!
106  * @brief Memory region access violation status.
107  */
108 typedef struct _rdc_mem_status
109 {
110     bool hasViolation; /*!< Violating happens or not. */
111     uint8_t domainID;  /*!< Violating Domain ID. */
112     uint64_t address;  /*!< Violating Address. */
113 } rdc_mem_status_t;
114 
115 /*******************************************************************************
116  * API
117  ******************************************************************************/
118 
119 #if defined(__cplusplus)
120 extern "C" {
121 #endif
122 
123 /*!
124  * @brief Initializes the RDC module.
125  *
126  * This function enables the RDC clock.
127  *
128  * @param base RDC peripheral base address.
129  */
130 void RDC_Init(RDC_Type *base);
131 
132 /*!
133  * @brief De-initializes the RDC module.
134  *
135  * This function disables the RDC clock.
136  *
137  * @param base RDC peripheral base address.
138  */
139 void RDC_Deinit(RDC_Type *base);
140 
141 /*!
142  * @brief Gets the RDC hardware configuration.
143  *
144  * This function gets the RDC hardware configurations, including number of bus
145  * masters, number of domains, number of memory regions and number of peripherals.
146  *
147  * @param base RDC peripheral base address.
148  * @param config Pointer to the structure to get the configuration.
149  */
150 void RDC_GetHardwareConfig(RDC_Type *base, rdc_hardware_config_t *config);
151 
152 /*!
153  * @brief Enable interrupts.
154  *
155  * @param base RDC peripheral base address.
156  * @param mask Interrupts to enable, it is OR'ed value of enum @ref _rdc_interrupts.
157  */
RDC_EnableInterrupts(RDC_Type * base,uint32_t mask)158 static inline void RDC_EnableInterrupts(RDC_Type *base, uint32_t mask)
159 {
160     base->INTCTRL |= mask;
161 }
162 
163 /*!
164  * @brief Disable interrupts.
165  *
166  * @param base RDC peripheral base address.
167  * @param mask Interrupts to disable, it is OR'ed value of enum @ref _rdc_interrupts.
168  */
RDC_DisableInterrupts(RDC_Type * base,uint32_t mask)169 static inline void RDC_DisableInterrupts(RDC_Type *base, uint32_t mask)
170 {
171     base->INTCTRL &= ~mask;
172 }
173 
174 /*!
175  * @brief Get the interrupt pending status.
176  *
177  * @param base RDC peripheral base address.
178  * @return Interrupts pending status, it is OR'ed value of enum @ref _rdc_interrupts.
179  */
RDC_GetInterruptStatus(RDC_Type * base)180 static inline uint32_t RDC_GetInterruptStatus(RDC_Type *base)
181 {
182     return base->INTSTAT;
183 }
184 
185 /*!
186  * @brief Clear interrupt pending status.
187  *
188  * @param base RDC peripheral base address.
189  * @param mask Status to clear, it is OR'ed value of enum @ref _rdc_interrupts.
190  */
RDC_ClearInterruptStatus(RDC_Type * base,uint32_t mask)191 static inline void RDC_ClearInterruptStatus(RDC_Type *base, uint32_t mask)
192 {
193     base->INTSTAT = mask;
194 }
195 
196 /*!
197  * @brief Get RDC status.
198  *
199  * @param base RDC peripheral base address.
200  * @return mask RDC status, it is OR'ed value of enum @ref _rdc_flags.
201  */
RDC_GetStatus(RDC_Type * base)202 static inline uint32_t RDC_GetStatus(RDC_Type *base)
203 {
204     return base->STAT;
205 }
206 
207 /*!
208  * @brief Clear RDC status.
209  *
210  * @param base RDC peripheral base address.
211  * @param mask RDC status to clear, it is OR'ed value of enum @ref _rdc_flags.
212  */
RDC_ClearStatus(RDC_Type * base,uint32_t mask)213 static inline void RDC_ClearStatus(RDC_Type *base, uint32_t mask)
214 {
215     base->STAT = mask;
216 }
217 
218 /*!
219  * @brief Set master domain assignment
220  *
221  * @param base RDC peripheral base address.
222  * @param master Which master to set.
223  * @param domainAssignment Pointer to the assignment.
224  */
225 void RDC_SetMasterDomainAssignment(RDC_Type *base,
226                                    rdc_master_t master,
227                                    const rdc_domain_assignment_t *domainAssignment);
228 
229 /*!
230  * @brief Get default master domain assignment
231  *
232  * The default configuration is:
233  * @code
234    assignment->domainId = 0U;
235    assignment->lock = 0U;
236    @endcode
237  *
238  * @param domainAssignment Pointer to the assignment.
239  */
240 void RDC_GetDefaultMasterDomainAssignment(rdc_domain_assignment_t *domainAssignment);
241 
242 /*!
243  * @brief Lock master domain assignment
244  *
245  * Once locked, it could not be unlocked until next reset.
246  *
247  * @param base RDC peripheral base address.
248  * @param master Which master to lock.
249  */
RDC_LockMasterDomainAssignment(RDC_Type * base,rdc_master_t master)250 static inline void RDC_LockMasterDomainAssignment(RDC_Type *base, rdc_master_t master)
251 {
252     assert((uint32_t)master < RDC_MDA_COUNT);
253 
254     base->MDA[master] |= RDC_MDA_LCK_MASK;
255     __DSB();
256 }
257 
258 /*!
259  * @brief Set peripheral access policy.
260  *
261  * @param base RDC peripheral base address.
262  * @param config Pointer to the policy configuration.
263  */
264 void RDC_SetPeriphAccessConfig(RDC_Type *base, const rdc_periph_access_config_t *config);
265 
266 /*!
267  * @brief Get default peripheral access policy.
268  *
269  * The default configuration is:
270  * @code
271     config->lock = false;
272     config->enableSema = false;
273     config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
274                      RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
275                      RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
276                      RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
277    @endcode
278  *
279  * @param config Pointer to the policy configuration.
280  */
281 void RDC_GetDefaultPeriphAccessConfig(rdc_periph_access_config_t *config);
282 
283 /*!
284  * @brief Lock peripheral access policy configuration.
285  *
286  * Once locked, it could not be unlocked until reset.
287  *
288  * @param base RDC peripheral base address.
289  * @param periph Which peripheral to lock.
290  */
RDC_LockPeriphAccessConfig(RDC_Type * base,rdc_periph_t periph)291 static inline void RDC_LockPeriphAccessConfig(RDC_Type *base, rdc_periph_t periph)
292 {
293     assert((uint32_t)periph < RDC_PDAP_COUNT);
294 
295     base->PDAP[periph] |= RDC_PDAP_LCK_MASK;
296     __DSB();
297 }
298 
299 /*!
300  * @brief Get the peripheral access policy for specific domain.
301  *
302  * @param base RDC peripheral base address.
303  * @param periph Which peripheral to get.
304  * @param domainId Get policy for which domain.
305  * @return Access policy, see @ref _rdc_access_policy.
306  */
RDC_GetPeriphAccessPolicy(RDC_Type * base,rdc_periph_t periph,uint8_t domainId)307 static inline uint8_t RDC_GetPeriphAccessPolicy(RDC_Type *base, rdc_periph_t periph, uint8_t domainId)
308 {
309     assert((uint32_t)periph < RDC_PDAP_COUNT);
310 
311     return (uint8_t)((base->PDAP[periph] >> (domainId * 2U)) & 0x03U);
312 }
313 
314 /*!
315  * @brief Set memory region access policy.
316  *
317  * Note that when setting the baseAddress and endAddress in @p config,
318  * should be aligned to the region resolution, see rdc_mem_t
319  * definitions.
320  *
321  * @param base RDC peripheral base address.
322  * @param config Pointer to the policy configuration.
323  */
324 void RDC_SetMemAccessConfig(RDC_Type *base, const rdc_mem_access_config_t *config);
325 
326 /*!
327  * @brief Get default memory region access policy.
328  *
329  * The default configuration is:
330  * @code
331     config->lock = false;
332     config->baseAddress = 0;
333     config->endAddress = 0;
334     config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
335                      RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
336                      RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
337                      RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
338    @endcode
339  *
340  * @param config Pointer to the policy configuration.
341  */
342 void RDC_GetDefaultMemAccessConfig(rdc_mem_access_config_t *config);
343 
344 /*!
345  * @brief Lock memory access policy configuration.
346  *
347  * Once locked, it could not be unlocked until reset. After locked, you can
348  * only call @ref RDC_SetMemAccessValid to enable the configuration, but can not
349  * disable it or change other settings.
350  *
351  * @param base RDC peripheral base address.
352  * @param mem Which memory region to lock.
353  */
RDC_LockMemAccessConfig(RDC_Type * base,rdc_mem_t mem)354 static inline void RDC_LockMemAccessConfig(RDC_Type *base, rdc_mem_t mem)
355 {
356     assert((uint32_t)mem < RDC_MRC_COUNT);
357 
358     base->MR[mem].MRC |= RDC_MRC_LCK_MASK;
359     __DSB();
360 }
361 
362 /*!
363  * @brief Enable or disable memory access policy configuration.
364  *
365  * @param base RDC peripheral base address.
366  * @param mem Which memory region to operate.
367  * @param valid Pass in true to valid, false to invalid.
368  */
RDC_SetMemAccessValid(RDC_Type * base,rdc_mem_t mem,bool valid)369 static inline void RDC_SetMemAccessValid(RDC_Type *base, rdc_mem_t mem, bool valid)
370 {
371     assert((uint32_t)mem < RDC_MRC_COUNT);
372 
373     if (valid)
374     {
375         base->MR[mem].MRC |= RDC_MRC_ENA_MASK;
376     }
377     else
378     {
379         base->MR[mem].MRC &= ~RDC_MRC_ENA_MASK;
380     }
381     __DSB();
382 }
383 
384 /*!
385  * @brief Get the memory region violation status.
386  *
387  * The first access violation is captured. Subsequent violations are ignored
388  * until the status register is cleared. Contents are cleared upon reading the
389  * register. Clearing of contents occurs only when the status is read by the
390  * memory region's associated domain ID(s).
391  *
392  * @param base RDC peripheral base address.
393  * @param mem Which memory region to get.
394  * @param status The returned status.
395  */
396 void RDC_GetMemViolationStatus(RDC_Type *base, rdc_mem_t mem, rdc_mem_status_t *status);
397 
398 /*!
399  * @brief Clear the memory region violation flag.
400  *
401  * @param base RDC peripheral base address.
402  * @param mem Which memory region to clear.
403  */
RDC_ClearMemViolationFlag(RDC_Type * base,rdc_mem_t mem)404 static inline void RDC_ClearMemViolationFlag(RDC_Type *base, rdc_mem_t mem)
405 {
406     assert((uint32_t)mem < RDC_MRC_COUNT);
407 
408     base->MR[mem].MRVS = RDC_MRVS_AD_MASK;
409 }
410 
411 /*!
412  * @brief Get the memory region access policy for specific domain.
413  *
414  * @param base RDC peripheral base address.
415  * @param mem Which memory region to get.
416  * @param domainId Get policy for which domain.
417  * @return Access policy, see @ref _rdc_access_policy.
418  */
RDC_GetMemAccessPolicy(RDC_Type * base,rdc_mem_t mem,uint8_t domainId)419 static inline uint8_t RDC_GetMemAccessPolicy(RDC_Type *base, rdc_mem_t mem, uint8_t domainId)
420 {
421     assert((uint32_t)mem < RDC_MRC_COUNT);
422 
423     return (uint8_t)((base->MR[mem].MRC >> (domainId * 2U)) & 0x03U);
424 }
425 
426 /*!
427  * @brief Gets the domain ID of the current bus master.
428  *
429  * This function returns the domain ID of the current bus master.
430  *
431  * @param base RDC peripheral base address.
432  * @return Domain ID of current bus master.
433  */
RDC_GetCurrentMasterDomainId(RDC_Type * base)434 static inline uint8_t RDC_GetCurrentMasterDomainId(RDC_Type *base)
435 {
436     return (uint8_t)((base->STAT & RDC_STAT_DID_MASK) >> RDC_STAT_DID_SHIFT);
437 }
438 
439 #if defined(__cplusplus)
440 }
441 #endif
442 
443 /*!
444  * @}
445  */
446 
447 #endif /* _FSL_RDC_H_ */
448