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