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