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