1 /*
2 * Copyright 2022, 2024 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_xbar.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.xbar_1"
17 #endif
18
19 #define XBAR_INST_FROM_INPUT(input) ((uint16_t)(input) >> 8U)
20 #define XBAR_INST_FROM_OUTPUT(output) ((uint16_t)(output) >> 8U)
21
22 #define XBAR_EXTRACT_INPUT(input) ((uint16_t)(input)&0xFFU)
23 #define XBAR_EXTRACT_OUTPUT(output) ((uint16_t)(output)&0xFFU)
24
25 #define XBAR_CTRL_STAT_SHIFT 4U
26 #define XBAR_CTRL_STAT_MASK ((xbar_reg_t)1U << 4U)
27
28 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
29 #define XBAR_CTRL_ALL_STAT_MASK (XBAR_CTRL_STAT_MASK)
30 #else
31 #define XBAR_CTRL_ALL_STAT_MASK (XBAR_CTRL_STAT_MASK | (XBAR_CTRL_STAT_MASK << 8U))
32 #endif
33
34 /* Array of XBAR clock name. */
35 static const clock_ip_name_t s_xbaraClock[] = XBAR_CLOCKS;
36
37 static const xbar_info_t s_xbarInfo[] = XBAR_INFO;
38
39 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
40 /*!
41 * brief Get the XBAR peripheral address CTRL register address.
42 *
43 * param output XBAR output signal.
44 * param ctrlReg Addr XBAR control register address.
45 * retval kStatus_Success Signal connection set successfully.
46 * retval kStatus_InvalidArgument Failed because of invalid argument.
47 */
XBAR_GetCtrlReg(xbar_output_signal_t output,volatile xbar_reg_t ** ctrlRegAddr)48 static status_t XBAR_GetCtrlReg(xbar_output_signal_t output, volatile xbar_reg_t **ctrlRegAddr)
49 {
50 status_t status;
51 uint16_t inst = XBAR_INST_FROM_OUTPUT(output);
52 uint16_t outputIndex = XBAR_EXTRACT_OUTPUT(output);
53
54 if ((inst > ARRAY_SIZE(s_xbarInfo)) || (outputIndex > (s_xbarInfo[inst - 1U].regCtrlNum)))
55 {
56 status = kStatus_InvalidArgument;
57 }
58 else
59 {
60 *ctrlRegAddr = s_xbarInfo[inst - 1U].baseAddr + (s_xbarInfo[inst - 1U].regCtrlOffset + outputIndex);
61 status = kStatus_Success;
62 }
63
64 return status;
65 }
66 #else
67 /*!
68 * brief Get the XBAR peripheral address and shift.
69 *
70 * Example:
71 code
72 XBAR_GetCtrlRegAndShift(kXBAR_DSC1_InputLogicLow, XBAR_DSC1_BASE, 1);
73 endcode
74 *
75 * param output XBAR output signal.
76 * param ctrlReg Addr XBAR control register address.
77 * param shift Number of XBAR control register.
78 * retval kStatus_Success Signal connection set successfully.
79 * retval kStatus_InvalidArgument Failed because of invalid argument.
80 */
XBAR_GetCtrlRegAndShift(xbar_output_signal_t output,volatile xbar_reg_t ** ctrlRegAddr,uint8_t * shift)81 static status_t XBAR_GetCtrlRegAndShift(xbar_output_signal_t output, volatile xbar_reg_t **ctrlRegAddr, uint8_t *shift)
82 {
83 status_t status;
84 uint16_t inst = XBAR_INST_FROM_OUTPUT(output);
85 uint16_t outputIndex = XBAR_EXTRACT_OUTPUT(output);
86
87 if ((inst > ARRAY_SIZE(s_xbarInfo)) || (outputIndex > (s_xbarInfo[inst - 1U].regCtrlNum * 2U)))
88 {
89 status = kStatus_InvalidArgument;
90 }
91 else
92 {
93 *ctrlRegAddr = s_xbarInfo[inst - 1U].baseAddr + ((s_xbarInfo[inst - 1U].regCtrlOffset + outputIndex) / 2U);
94 *shift = (uint8_t)(uint16_t)(8U * (outputIndex % 2U));
95 status = kStatus_Success;
96 }
97
98 return status;
99 }
100 #endif
101
102 /*!
103 * brief Initializes the XBAR module.
104 *
105 * This function un-gates the XBAR clock.
106 *
107 * param xbarInstance XBAR peripheral address.
108 */
XBAR_Init(xbar_instance_t xbarInstance)109 void XBAR_Init(xbar_instance_t xbarInstance)
110 {
111 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
112 /* Enable XBARA module clock. */
113 (void)CLOCK_EnableClock(s_xbaraClock[xbarInstance]);
114 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
115 }
116
117 /*!
118 * brief Shuts down the XBAR module.
119 *
120 * This function disables XBAR clock.
121 *
122 * param xbarInstance XBAR peripheral address.
123 */
XBAR_Deinit(xbar_instance_t xbarInstance)124 void XBAR_Deinit(xbar_instance_t xbarInstance)
125 {
126 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
127 /* Disable XBARA module clock. */
128 (void)CLOCK_DisableClock(s_xbaraClock[xbarInstance]);
129 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
130 }
131
132 /*!
133 * brief Sets a connection between the selected XBAR_IN[*] input and the XBAR_OUT[*] output signal.
134 *
135 * This function connects the XBAR input to the selected XBAR output.
136 * If more than one XBAR module is available, only the inputs and outputs from the same module
137 * can be connected.
138 *
139 * Example:
140 code
141 XBAR_SetSignalsConnection(kXBAR_DSC1_InputLogicLow, kXBAR_DSC1_OutputTriggerSyncIn0);
142 endcode
143 *
144 * param input XBAR input signal.
145 * param output XBAR output signal.
146 * retval kStatus_Success Signal connection set successfully.
147 * retval kStatus_InvalidArgument Failed because of invalid argument.
148 */
XBAR_SetSignalsConnection(xbar_input_signal_t input,xbar_output_signal_t output)149 status_t XBAR_SetSignalsConnection(xbar_input_signal_t input, xbar_output_signal_t output)
150 {
151 status_t status;
152 uint16_t inst = XBAR_INST_FROM_OUTPUT(output);
153 uint16_t outputIndex = XBAR_EXTRACT_OUTPUT(output);
154 uint16_t inputIndex = XBAR_EXTRACT_INPUT(input);
155 volatile xbar_reg_t *selRegAddr;
156
157 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
158 if ((inst > ARRAY_SIZE(s_xbarInfo)) || (outputIndex > (s_xbarInfo[inst - 1U].regSelNum)))
159 {
160 status = kStatus_InvalidArgument;
161 }
162 else
163 {
164 selRegAddr = s_xbarInfo[inst - 1U].baseAddr + ((s_xbarInfo[inst - 1U].regSelOffset + outputIndex));
165 *selRegAddr = (*selRegAddr & ~((xbar_reg_t)0xFFU)) | (inputIndex);
166 status = kStatus_Success;
167 }
168 #else
169 uint8_t shiftInReg;
170
171 if ((inst > ARRAY_SIZE(s_xbarInfo)) || (outputIndex > (s_xbarInfo[inst - 1U].regSelNum * 2U)))
172 {
173 status = kStatus_InvalidArgument;
174 }
175 else
176 {
177 selRegAddr = s_xbarInfo[inst - 1U].baseAddr + ((s_xbarInfo[inst - 1U].regSelOffset + outputIndex) / 2U);
178 shiftInReg = (uint8_t)(uint16_t)(8U * (outputIndex % 2U));
179 *selRegAddr = (*selRegAddr & ~((xbar_reg_t)0xFFU << shiftInReg)) | (inputIndex << shiftInReg);
180 status = kStatus_Success;
181 }
182 #endif
183
184 return status;
185 }
186
187 /*!
188 * brief Clears the edge detection status flags.
189 *
190 * param output XBAR output signal.
191 * retval kStatus_Success Signal connection set successfully.
192 * retval kStatus_InvalidArgument Failed because of invalid argument.
193 */
XBAR_ClearOutputStatusFlag(xbar_output_signal_t output)194 status_t XBAR_ClearOutputStatusFlag(xbar_output_signal_t output)
195 {
196 status_t status;
197 volatile xbar_reg_t *ctrlRegAddr;
198
199 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
200 status = XBAR_GetCtrlReg(output, &ctrlRegAddr);
201
202 if (status == kStatus_Success)
203 {
204 *ctrlRegAddr |= XBAR_CTRL_STAT_MASK;
205 }
206 #else
207 uint8_t shiftInReg;
208
209 status = XBAR_GetCtrlRegAndShift(output, &ctrlRegAddr, &shiftInReg);
210
211 if (status == kStatus_Success)
212 {
213 *ctrlRegAddr = (*ctrlRegAddr & (~XBAR_CTRL_ALL_STAT_MASK)) | (XBAR_CTRL_STAT_MASK << shiftInReg);
214 }
215 #endif
216
217 return status;
218 }
219
220 /*!
221 * brief Gets the active edge detection status.
222 *
223 * This function gets the active edge detect status of all XBAR_OUTs. If the
224 * active edge occurs, the return value is asserted. When the interrupt or the DMA
225 * functionality is enabled for the XBAR_OUTx, this field is 1 when the interrupt
226 * or DMA request is asserted and 0 when the interrupt or DMA request has been
227 * cleared.
228 *
229 * param output XBAR output signal.
230 * param flag get XBAR output status flag.
231 * retval kStatus_Success Signal connection set successfully.
232 * retval kStatus_InvalidArgument Failed because of invalid argument.
233 */
XBAR_GetOutputStatusFlag(xbar_output_signal_t output,bool * flag)234 status_t XBAR_GetOutputStatusFlag(xbar_output_signal_t output, bool *flag)
235 {
236 status_t status;
237 volatile xbar_reg_t *ctrlRegAddr;
238 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
239 status = XBAR_GetCtrlReg(output, &ctrlRegAddr);
240
241 if (status == kStatus_Success)
242 {
243 *flag = (0U != (*ctrlRegAddr & ((xbar_reg_t)XBAR_CTRL_STAT_MASK)));
244 }
245 #else
246 uint8_t shiftInReg;
247
248 status = XBAR_GetCtrlRegAndShift(output, &ctrlRegAddr, &shiftInReg);
249
250 if (status == kStatus_Success)
251 {
252 *flag = (0U != (*ctrlRegAddr & ((xbar_reg_t)XBAR_CTRL_STAT_MASK << shiftInReg)));
253 }
254 #endif
255
256 return status;
257 }
258
259 /*!
260 * brief Configures the XBAR control register.
261 *
262 * This function configures an XBAR control register. The active edge detection
263 * and the DMA/IRQ function on the corresponding XBAR output can be set.
264 *
265 * Example:
266 code
267 xbar_control_config_t userConfig;
268 userConfig.activeEdge = kXBAR_EdgeRising;
269 userConfig.requestType = kXBAR_RequestInterruptEnable;
270 XBAR_SetOutputSignalConfig(kXBAR_DSC1_OutputTriggerSyncIn0, &userConfig);
271 endcode
272 *
273 * param output XBAR output signal.
274 * param controlConfig Pointer to structure that keeps configuration of control register.
275 * retval kStatus_Success Signal connection set successfully.
276 * retval kStatus_InvalidArgument Failed because of invalid argument.
277 */
XBAR_SetOutputSignalConfig(xbar_output_signal_t output,const xbar_control_config_t * controlConfig)278 status_t XBAR_SetOutputSignalConfig(xbar_output_signal_t output, const xbar_control_config_t *controlConfig)
279 {
280 status_t status;
281 volatile xbar_reg_t *ctrlRegAddr;
282 #if defined(FSL_FEATURE_XBAR_REG_WIDTH) && (FSL_FEATURE_XBAR_REG_WIDTH == 32)
283 status = XBAR_GetCtrlReg(output, &ctrlRegAddr);
284
285 if (status == kStatus_Success)
286 {
287 *ctrlRegAddr |= ((((xbar_reg_t)controlConfig->activeEdge)) << 2) |
288 (((xbar_reg_t)controlConfig->requestType));
289 }
290 #else
291 uint8_t shiftInReg;
292
293 status = XBAR_GetCtrlRegAndShift(output, &ctrlRegAddr, &shiftInReg);
294
295 if (status == kStatus_Success)
296 {
297 *ctrlRegAddr |= ((((xbar_reg_t)controlConfig->activeEdge) << shiftInReg) << 2) |
298 (((xbar_reg_t)controlConfig->requestType) << shiftInReg);
299 }
300 #endif
301
302 return status;
303 }
304