1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_xbar.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.xbar"
18 #endif
19
20 /* Macros for entire XBAR_CTRL register. */
21 #define XBAR_CTRLx(base, index) (((volatile uint16_t *)(&((base)->CTRL0)))[(index)])
22
23 #define XBAR_CTRL_STS_MASK ((uint32_t)XBAR_CTRL0_STS0_MASK | ((uint32_t)XBAR_CTRL0_STS0_MASK << 8UL))
24
25 typedef union
26 {
27 uint8_t _u8[2];
28 uint16_t _u16;
29 } xbar_u8_u16_t;
30
31 /*******************************************************************************
32 * Prototypes
33 ******************************************************************************/
34
35 /*!
36 * @brief Get the XBAR instance from peripheral base address.
37 *
38 * @param base XBAR peripheral base address.
39 * @return XBAR instance.
40 */
41 static uint32_t XBAR_GetInstance(XBAR_Type *base);
42
43 /*******************************************************************************
44 * Variables
45 ******************************************************************************/
46
47 /* Array of XBAR peripheral base address. */
48 static XBAR_Type *const s_xbarBases[] = XBAR_BASE_PTRS;
49
50 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
51 /* Array of XBAR clock name. */
52 static const clock_ip_name_t s_xbarClock[] = XBAR_CLOCKS;
53 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
54
55 /*******************************************************************************
56 * Code
57 ******************************************************************************/
58
XBAR_GetInstance(XBAR_Type * base)59 static uint32_t XBAR_GetInstance(XBAR_Type *base)
60 {
61 uint32_t instance;
62 uint32_t xbarInstanceCount = ARRAY_SIZE(s_xbarBases);
63
64 /* Find the instance index from base address mappings. */
65 for (instance = 0; instance < xbarInstanceCount; instance++)
66 {
67 if (s_xbarBases[instance] == base)
68 {
69 break;
70 }
71 }
72
73 assert(instance < xbarInstanceCount);
74
75 return instance;
76 }
77
78 /*!
79 * brief Initializes the XBAR modules.
80 *
81 * This function un-gates the XBAR clock.
82 *
83 * param base XBAR peripheral address.
84 */
XBAR_Init(XBAR_Type * base)85 void XBAR_Init(XBAR_Type *base)
86 {
87 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
88 /* Enable XBAR module clock. */
89 CLOCK_EnableClock(s_xbarClock[XBAR_GetInstance(base)]);
90 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
91 }
92
93 /*!
94 * brief Shutdown the XBAR modules.
95 *
96 * This function disables XBAR clock.
97 *
98 * param base XBAR peripheral address.
99 */
XBAR_Deinit(XBAR_Type * base)100 void XBAR_Deinit(XBAR_Type *base)
101 {
102 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
103 /* Disable XBAR module clock. */
104 CLOCK_DisableClock(s_xbarClock[XBAR_GetInstance(base)]);
105 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
106 }
107
108 /*!
109 * brief Set connection between the selected XBAR_IN[*] input and the XBAR_OUT[*] output signal.
110 *
111 * This function connects the XBAR input to the selected XBAR output.
112 * If more than one XBAR module is available, only the inputs and outputs from the same module
113 * can be connected.
114 *
115 * Example:
116 code
117 XBAR_SetSignalsConnection(XBAR, kXBAR_InputTMR_CH0_Output, kXBAR_OutputXB_DMA_INT2);
118 endcode
119 *
120 * param base XBAR peripheral address
121 * param input XBAR input signal.
122 * param output XBAR output signal.
123 */
XBAR_SetSignalsConnection(XBAR_Type * base,xbar_input_signal_t input,xbar_output_signal_t output)124 void XBAR_SetSignalsConnection(XBAR_Type *base, xbar_input_signal_t input, xbar_output_signal_t output)
125 {
126 xbar_u8_u16_t regVal;
127 uint8_t byteInReg;
128 uint8_t outputIndex = (uint8_t)output;
129
130 byteInReg = outputIndex % 2U;
131
132 regVal._u16 = XBAR_SELx(base, outputIndex);
133
134 regVal._u8[byteInReg] = (uint8_t)input;
135
136 XBAR_SELx(base, outputIndex) = regVal._u16;
137 }
138
139 /*!
140 * brief Gets the active edge detection status.
141 *
142 * This function gets the active edge detect status of all XBAR_OUTs. If the
143 * active edge occurs, the return value is asserted. When the interrupt or the DMA
144 * functionality is enabled for the XBAR_OUTx, this field is 1 when the interrupt
145 * or DMA request is asserted and 0 when the interrupt or DMA request has been
146 * cleared.
147 *
148 * Example:
149 code
150 uint32_t status;
151
152 status = XBAR_GetStatusFlags(XBAR);
153 endcode
154 *
155 * param base XBAR peripheral address.
156 * return the mask of these status flag bits.
157 */
XBAR_GetStatusFlags(XBAR_Type * base)158 uint32_t XBAR_GetStatusFlags(XBAR_Type *base)
159 {
160 uint32_t status_flag;
161
162 status_flag = (uint32_t)base->CTRL0 & XBAR_CTRL_STS_MASK;
163
164 #if FSL_FEATURE_XBAR_INTERRUPT_COUNT > 2
165 status_flag |= (((uint32_t)base->CTRL1 & XBAR_CTRL_STS_MASK) << 16U);
166 #endif
167 return status_flag;
168 }
169
170 /*!
171 * brief Clears the edge detection status flags of relative mask.
172 *
173 * param base XBAR peripheral address
174 * param mask the status flags to clear.
175 */
XBAR_ClearStatusFlags(XBAR_Type * base,uint32_t mask)176 void XBAR_ClearStatusFlags(XBAR_Type *base, uint32_t mask)
177 {
178 uint16_t regVal;
179
180 /* Assign regVal to CTRL0 register's value */
181 regVal = (base->CTRL0);
182 /* Perform this command to avoid writing 1 into interrupt flag bits */
183 regVal &= (uint16_t)(~(XBAR_CTRL_STS_MASK));
184 /* Write 1 to interrupt flag bits corresponding to mask */
185 regVal |= (uint16_t)(mask & XBAR_CTRL_STS_MASK);
186
187 /* Write regVal value into CTRL0 register */
188 base->CTRL0 = regVal;
189
190 /* Assign regVal to CTRL1 register's value */
191 #if FSL_FEATURE_XBAR_INTERRUPT_COUNT > 2
192 regVal = (base->CTRL1);
193 /* Perform this command to avoid writing 1 into interrupt flag bits */
194 regVal &= (uint16_t)(~(XBAR_CTRL_STS_MASK));
195 /* Write 1 to interrupt flag bits corresponding to mask */
196 regVal |= (uint16_t)((mask >> 16U) & (XBAR_CTRL_STS_MASK));
197
198 /* Write regVal value into CTRL1 register */
199 base->CTRL1 = regVal;
200 #endif
201 }
202
203 /*!
204 * brief Configures the XBAR control register.
205 *
206 * This function configures an XBAR control register. The active edge detection
207 * and the DMA/IRQ function on the corresponding XBAR output can be set.
208 *
209 * Example:
210 code
211 xbar_control_config_t userConfig;
212 userConfig.activeEdge = kXBAR_EdgeRising;
213 userConfig.requestType = kXBAR_RequestInterruptEnalbe;
214 XBAR_SetOutputSignalConfig(XBAR, kXBAR_OutputXB_DMA_INT0, &userConfig);
215 endcode
216 *
217 * param base XBAR peripheral address
218 * param output XBAR output number.
219 * param controlConfig Pointer to structure that keeps configuration of control register.
220 */
XBAR_SetOutputSignalConfig(XBAR_Type * base,xbar_output_signal_t output,const xbar_control_config_t * controlConfig)221 void XBAR_SetOutputSignalConfig(XBAR_Type *base,
222 xbar_output_signal_t output,
223 const xbar_control_config_t *controlConfig)
224
225 {
226 uint8_t outputIndex = (uint8_t)output;
227 uint8_t regIndex;
228 uint8_t byteInReg;
229 xbar_u8_u16_t regVal;
230
231 assert(outputIndex < (uint8_t)FSL_FEATURE_XBAR_INTERRUPT_COUNT);
232
233 regIndex = outputIndex / 2U;
234 byteInReg = outputIndex % 2U;
235
236 regVal._u16 = XBAR_CTRLx(base, regIndex);
237
238 /* Don't clear the status flags. */
239 regVal._u16 &= (uint16_t)(~(XBAR_CTRL_STS_MASK));
240 regVal._u8[byteInReg] = (uint8_t)(XBAR_CTRL0_EDGE0(controlConfig->activeEdge) |
241 (uint16_t)(((uint32_t)controlConfig->requestType) << XBAR_CTRL0_DEN0_SHIFT));
242
243 XBAR_CTRLx(base, regIndex) = regVal._u16;
244 }
245