1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_rdc.h"
9 
10 /******************************************************************************
11  * Definitions
12  *****************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.rdc"
17 #endif
18 
19 typedef union
20 {
21     rdc_domain_assignment_t _mda;
22     uint32_t _u32;
23 } rdc_mda_reg_t;
24 
25 typedef union
26 {
27     rdc_hardware_config_t _vir;
28     uint32_t _u32;
29 } rdc_vir_reg_t;
30 
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 
35 /*!
36  * @brief Get instance number for RDC module.
37  *
38  * @param base RDC peripheral base address.
39  */
40 uint32_t RDC_GetInstance(RDC_Type *base);
41 
42 /*******************************************************************************
43  * Variables
44  ******************************************************************************/
45 
46 /*! @brief Pointers to rdc bases for each instance. */
47 static RDC_Type *const s_rdcBases[] = RDC_BASE_PTRS;
48 
49 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
50 /*! @brief Pointers to rdc clocks for each instance. */
51 static const clock_ip_name_t s_rdcClocks[] = RDC_CLOCKS;
52 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
53 
54 /******************************************************************************
55  * CODE
56  *****************************************************************************/
57 
RDC_GetInstance(RDC_Type * base)58 uint32_t RDC_GetInstance(RDC_Type *base)
59 {
60     uint32_t instance;
61 
62     /* Find the instance index from base address mappings. */
63     for (instance = 0; instance < ARRAY_SIZE(s_rdcBases); instance++)
64     {
65         if (s_rdcBases[instance] == base)
66         {
67             break;
68         }
69     }
70 
71     assert(instance < ARRAY_SIZE(s_rdcBases));
72 
73     return instance;
74 }
75 
76 /*!
77  * brief Initializes the RDC module.
78  *
79  * This function enables the RDC clock.
80  *
81  * param base RDC peripheral base address.
82  */
RDC_Init(RDC_Type * base)83 void RDC_Init(RDC_Type *base)
84 {
85 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
86     CLOCK_EnableClock(s_rdcClocks[RDC_GetInstance(base)]);
87 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
88 }
89 
90 /*!
91  * brief De-initializes the RDC module.
92  *
93  * This function disables the RDC clock.
94  *
95  * param base RDC peripheral base address.
96  */
RDC_Deinit(RDC_Type * base)97 void RDC_Deinit(RDC_Type *base)
98 {
99 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
100     CLOCK_DisableClock(s_rdcClocks[RDC_GetInstance(base)]);
101 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
102 }
103 
104 /*!
105  * brief Gets the RDC hardware configuration.
106  *
107  * This function gets the RDC hardware configurations, including number of bus
108  * masters, number of domains, number of memory regions and number of peripherals.
109  *
110  * param base RDC peripheral base address.
111  * param config Pointer to the structure to get the configuration.
112  */
RDC_GetHardwareConfig(RDC_Type * base,rdc_hardware_config_t * config)113 void RDC_GetHardwareConfig(RDC_Type *base, rdc_hardware_config_t *config)
114 {
115     assert(NULL != config);
116 
117     rdc_vir_reg_t vir;
118     vir._u32 = base->VIR;
119 
120     *config = vir._vir;
121 }
122 
123 /*!
124  * brief Set master domain assignment
125  *
126  * param base RDC peripheral base address.
127  * param master Which master to set.
128  * param domainAssignment Pointer to the assignment.
129  */
RDC_SetMasterDomainAssignment(RDC_Type * base,rdc_master_t master,const rdc_domain_assignment_t * domainAssignment)130 void RDC_SetMasterDomainAssignment(RDC_Type *base, rdc_master_t master, const rdc_domain_assignment_t *domainAssignment)
131 {
132     assert((uint32_t)master < RDC_MDA_COUNT);
133 
134     rdc_mda_reg_t mda;
135 
136     mda._mda = *domainAssignment;
137 
138     base->MDA[master] = mda._u32;
139 }
140 
141 /*!
142  * brief Get default master domain assignment
143  *
144  * The default configuration is:
145  * code
146    assignment->domainId = 0U;
147    assignment->lock = 0U;
148    endcode
149  *
150  * param domainAssignment Pointer to the assignment.
151  */
RDC_GetDefaultMasterDomainAssignment(rdc_domain_assignment_t * domainAssignment)152 void RDC_GetDefaultMasterDomainAssignment(rdc_domain_assignment_t *domainAssignment)
153 {
154     assert(NULL != domainAssignment);
155 
156     rdc_mda_reg_t mda;
157     mda._u32 = 0U;
158 
159     *domainAssignment = mda._mda;
160 }
161 
162 /*!
163  * brief Set peripheral access policy.
164  *
165  * param base RDC peripheral base address.
166  * param config Pointer to the policy configuration.
167  */
RDC_SetPeriphAccessConfig(RDC_Type * base,const rdc_periph_access_config_t * config)168 void RDC_SetPeriphAccessConfig(RDC_Type *base, const rdc_periph_access_config_t *config)
169 {
170     assert((uint32_t)config->periph < RDC_PDAP_COUNT);
171 
172     uint32_t periph  = (uint32_t)config->periph;
173     uint32_t regPDAP = config->policy;
174 
175     if (config->lock)
176     {
177         regPDAP |= RDC_PDAP_LCK_MASK;
178     }
179 
180     if (config->enableSema)
181     {
182         regPDAP |= RDC_PDAP_SREQ_MASK;
183     }
184 
185     base->PDAP[periph] = regPDAP;
186 
187     __DSB();
188 }
189 
190 /*!
191  * brief Get default peripheral access policy.
192  *
193  * The default configuration is:
194  * code
195     config->lock = false;
196     config->enableSema = false;
197     config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
198                      RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
199                      RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
200                      RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
201    endcode
202  *
203  * param config Pointer to the policy configuration.
204  */
RDC_GetDefaultPeriphAccessConfig(rdc_periph_access_config_t * config)205 void RDC_GetDefaultPeriphAccessConfig(rdc_periph_access_config_t *config)
206 {
207     assert(NULL != config);
208 
209     /* Initializes the configure structure to zero. */
210     (void)memset(config, 0, sizeof(*config));
211 
212     config->lock       = false;
213     config->enableSema = false;
214     config->policy     = RDC_ACCESS_POLICY(0U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(1U, kRDC_ReadWrite) |
215                      RDC_ACCESS_POLICY(2U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(3U, kRDC_ReadWrite);
216 }
217 
218 /*!
219  * brief Set memory region access policy.
220  *
221  * Note that when setting the baseAddress and endAddress in p config,
222  * should be aligned to the region resolution, see rdc_mem_t
223  * definitions.
224  *
225  * param base RDC peripheral base address.
226  * param config Pointer to the policy configuration.
227  */
RDC_SetMemAccessConfig(RDC_Type * base,const rdc_mem_access_config_t * config)228 void RDC_SetMemAccessConfig(RDC_Type *base, const rdc_mem_access_config_t *config)
229 {
230     assert((uint32_t)config->mem < RDC_MRC_COUNT);
231 
232     uint32_t mem = (uint32_t)config->mem;
233     /* The configuration is enabled by default. */
234     uint32_t regMRC = config->policy | RDC_MRC_ENA_MASK;
235 
236     if (config->lock)
237     {
238         regMRC |= RDC_MRC_LCK_MASK;
239     }
240 
241 #if (defined(FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) && FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT)
242     base->MR[mem].MRSA = (uint32_t)(config->baseAddress >> (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT);
243     base->MR[mem].MREA = (uint32_t)(config->endAddress >> (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT);
244 #else
245     base->MR[mem].MRSA = (uint32_t)config->baseAddress;
246     base->MR[mem].MREA = (uint32_t)config->endAddress;
247 #endif
248     base->MR[mem].MRC = regMRC;
249 
250     __DSB();
251 }
252 
253 /*!
254  * brief Get default memory region access policy.
255  *
256  * The default configuration is:
257  * code
258     config->lock = false;
259     config->baseAddress = 0;
260     config->endAddress = 0;
261     config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) |
262                      RDC_ACCESS_POLICY(1, kRDC_ReadWrite) |
263                      RDC_ACCESS_POLICY(2, kRDC_ReadWrite) |
264                      RDC_ACCESS_POLICY(3, kRDC_ReadWrite);
265    endcode
266  *
267  * param config Pointer to the policy configuration.
268  */
RDC_GetDefaultMemAccessConfig(rdc_mem_access_config_t * config)269 void RDC_GetDefaultMemAccessConfig(rdc_mem_access_config_t *config)
270 {
271     assert(NULL != config);
272 
273     /* Initializes the configure structure to zero. */
274     (void)memset(config, 0, sizeof(*config));
275 
276     config->lock        = false;
277     config->baseAddress = 0;
278     config->endAddress  = 0;
279     config->policy      = RDC_ACCESS_POLICY(0U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(1U, kRDC_ReadWrite) |
280                      RDC_ACCESS_POLICY(2U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(3U, kRDC_ReadWrite);
281 }
282 
283 /*!
284  * brief Get the memory region violation status.
285  *
286  * The first access violation is captured. Subsequent violations are ignored
287  * until the status register is cleared. Contents are cleared upon reading the
288  * register. Clearing of contents occurs only when the status is read by the
289  * memory region's associated domain ID(s).
290  *
291  * param base RDC peripheral base address.
292  * param mem Which memory region to get.
293  * param status The returned status.
294  */
RDC_GetMemViolationStatus(RDC_Type * base,rdc_mem_t mem,rdc_mem_status_t * status)295 void RDC_GetMemViolationStatus(RDC_Type *base, rdc_mem_t mem, rdc_mem_status_t *status)
296 {
297     assert((uint32_t)mem < RDC_MRC_COUNT);
298 
299     uint32_t regMRVS = base->MR[mem].MRVS;
300 
301     status->hasViolation = ((regMRVS & RDC_MRVS_AD_MASK) != 0U);
302     status->domainID     = (uint8_t)((regMRVS & RDC_MRVS_VDID_MASK) >> RDC_MRVS_VDID_SHIFT);
303 #if (defined(FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) && FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT)
304     regMRVS &= RDC_MRVS_VADR_MASK;
305     status->address = ((uint64_t)regMRVS) << (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT;
306 #else
307     regMRVS &= RDC_MRVS_VADR_MASK;
308     status->address = (uint64_t)regMRVS;
309 #endif
310 }
311