Xilinx: ARM: I2C: SI570: Driver updated for more error checking
[linux-2.6-xlnx.git] / drivers / xilinx_common / xlldma.c
blob274e449fe409b0411c20270b944fe45cc2076e68
1 /* $Id: */
2 /******************************************************************************
4 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
5 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
6 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
7 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
8 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
9 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
10 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
11 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
12 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
13 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
14 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
15 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16 * FOR A PARTICULAR PURPOSE.
18 * (c) Copyright 2007-2008 Xilinx Inc.
19 * All rights reserved.
20 * This program is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License as published by the
22 * Free Software Foundation; either version 2 of the License, or (at your
23 * option) any later version.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 ******************************************************************************/
30 /*****************************************************************************/
31 /**
33 * @file xlldma.c
35 * This file implements initialization and control related functions. For more
36 * information on this driver, see xlldma.h.
38 * <pre>
39 * MODIFICATION HISTORY:
41 * Ver Who Date Changes
42 * ----- ---- -------- -------------------------------------------------------
43 * 1.00a xd 12/21/06 First release
44 * </pre>
45 ******************************************************************************/
47 /***************************** Include Files *********************************/
49 #include <linux/string.h>
51 #include "xlldma.h"
52 #include "xenv.h"
54 /************************** Constant Definitions *****************************/
57 /**************************** Type Definitions *******************************/
60 /***************** Macros (Inline Functions) Definitions *********************/
63 /************************** Function Prototypes ******************************/
66 /************************** Variable Definitions *****************************/
69 /*****************************************************************************/
70 /**
71 * This function initializes a DMA engine. This function must be called
72 * prior to using a DMA engine. Initialization of a engine includes setting
73 * up the register base address, setting up the instance data, and ensuring the
74 * hardware is in a quiescent state.
76 * @param InstancePtr is a pointer to the DMA engine instance to be worked on.
77 * @param BaseAddress is where the registers for this engine can be found.
78 * If address translation is being used, then this parameter must
79 * reflect the virtual base address.
80 * @return None.
82 *****************************************************************************/
83 void XLlDma_Initialize(XLlDma * InstancePtr, u32 BaseAddress)
85 /* Setup the instance */
86 memset(InstancePtr, 0, sizeof(XLlDma));
87 InstancePtr->RegBase = BaseAddress;
89 /* Initialize the ring structures */
90 InstancePtr->TxBdRing.RunState = XST_DMA_SG_IS_STOPPED;
91 InstancePtr->TxBdRing.ChanBase = BaseAddress + XLLDMA_TX_OFFSET;
92 InstancePtr->TxBdRing.IsRxChannel = 0;
93 InstancePtr->RxBdRing.RunState = XST_DMA_SG_IS_STOPPED;
94 InstancePtr->RxBdRing.ChanBase = BaseAddress + XLLDMA_RX_OFFSET;
95 InstancePtr->RxBdRing.IsRxChannel = 1;
97 /* Reset the device and return */
98 XLlDma_Reset(InstancePtr);
101 /*****************************************************************************/
103 * Reset both TX and RX channels of a DMA engine.
105 * Any DMA transaction in progress aborts immediately. The DMA engine is in
106 * stop state after the reset.
108 * @param InstancePtr is a pointer to the DMA engine instance to be worked on.
110 * @return None.
112 * @note
113 * - If the hardware is not working properly, this function will enter
114 * infinite loop and never return.
115 * - After the reset, the Normal mode is enabled, and the overflow error
116 * for both TX/RX channels are disabled.
117 * - After the reset, the DMA engine is no longer in pausing state, if
118 * the DMA engine is paused before the reset operation.
119 * - After the reset, the coalescing count value and the delay timeout
120 * value are both set to 1 for TX and RX channels.
121 * - After the reset, all interrupts are disabled.
123 ******************************************************************************/
124 void XLlDma_Reset(XLlDma * InstancePtr)
126 u32 IrqStatus;
127 XLlDma_BdRing *TxRingPtr, *RxRingPtr;
129 TxRingPtr = &XLlDma_mGetTxRing(InstancePtr);
130 RxRingPtr = &XLlDma_mGetRxRing(InstancePtr);
132 /* Save the locations of current BDs both rings are working on
133 * before the reset so later we can resume the rings smoothly.
135 XLlDma_mBdRingSnapShotCurrBd(TxRingPtr);
136 XLlDma_mBdRingSnapShotCurrBd(RxRingPtr);
138 /* Start reset process then wait for completion */
139 XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_SW_RESET_MASK);
141 /* Loop until the reset is done */
142 while ((XLlDma_mGetCr(InstancePtr) & XLLDMA_DMACR_SW_RESET_MASK)) {
145 /* Disable all interrupts after issue software reset */
146 XLlDma_mBdRingIntDisable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);
147 XLlDma_mBdRingIntDisable(RxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);
149 /* Clear Interrupt registers of both channels, as the software reset
150 * does not clear any register values. Not doing so will cause
151 * interrupts asserted after the software reset if there is any
152 * interrupt left over before.
154 IrqStatus = XLlDma_mBdRingGetIrq(TxRingPtr);
155 XLlDma_mBdRingAckIrq(TxRingPtr, IrqStatus);
156 IrqStatus = XLlDma_mBdRingGetIrq(RxRingPtr);
157 XLlDma_mBdRingAckIrq(RxRingPtr, IrqStatus);
159 /* Enable Normal mode, and disable overflow errors for both channels */
160 XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_TAIL_PTR_EN_MASK |
161 XLLDMA_DMACR_RX_OVERFLOW_ERR_DIS_MASK |
162 XLLDMA_DMACR_TX_OVERFLOW_ERR_DIS_MASK);
164 /* Set TX/RX Channel coalescing setting */
165 XLlDma_BdRingSetCoalesce(TxRingPtr, 1, 1);
166 XLlDma_BdRingSetCoalesce(RxRingPtr, 1, 1);
168 TxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
169 RxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
172 /*****************************************************************************/
174 * Pause DMA transactions on both channels. The DMA enters the pausing state
175 * immediately. So if a DMA transaction is in progress, it will be left
176 * unfinished and will be continued once the DMA engine is resumed
177 * (see XLlDma_Resume()).
179 * @param InstancePtr is a pointer to the DMA engine instance to be worked on.
181 * @return None.
183 * @note
184 * - If the hardware is not working properly, this function will enter
185 * infinite loop and never return.
186 * - After the DMA is paused, DMA channels still could accept more BDs
187 * from software (see XLlDma_BdRingToHw()), but new BDs will not be
188 * processed until the DMA is resumed (see XLlDma_Resume()).
190 *****************************************************************************/
191 void XLlDma_Pause(XLlDma * InstancePtr)
193 u32 RegValue;
194 XLlDma_BdRing *TxRingPtr, *RxRingPtr;
196 TxRingPtr = &XLlDma_mGetTxRing(InstancePtr);
197 RxRingPtr = &XLlDma_mGetRxRing(InstancePtr);
199 /* Do nothing if both channels already stopped */
200 if ((TxRingPtr->RunState == XST_DMA_SG_IS_STOPPED) &&
201 (RxRingPtr->RunState == XST_DMA_SG_IS_STOPPED)) {
202 return;
205 /* Enable pause bits for both TX/ RX channels */
206 RegValue = XLlDma_mGetCr(InstancePtr);
207 XLlDma_mSetCr(InstancePtr, RegValue | XLLDMA_DMACR_TX_PAUSE_MASK |
208 XLLDMA_DMACR_RX_PAUSE_MASK);
210 /* Loop until Write Command Queue of RX channel is empty, which
211 * indicates that all the write data associated with the pending
212 * commands has been flushed.*/
213 while (!(XLlDma_mBdRingGetIrq(RxRingPtr) | XLLDMA_IRQ_WRQ_EMPTY_MASK));
215 TxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
216 RxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
219 /*****************************************************************************/
221 * Resume DMA transactions on both channels. Any interrupted DMA transaction
222 * caused by DMA pause operation (see XLlDma_Pause()) and all committed
223 * transactions after DMA is paused will be continued upon the return of this
224 * function.
226 * @param InstancePtr is a pointer to the DMA engine instance to be worked on.
228 * @return None.
230 *****************************************************************************/
231 void XLlDma_Resume(XLlDma * InstancePtr)
233 u32 RegValue;
234 XLlDma_BdRing *TxRingPtr, *RxRingPtr;
236 TxRingPtr = &XLlDma_mGetTxRing(InstancePtr);
237 RxRingPtr = &XLlDma_mGetRxRing(InstancePtr);
239 /* Do nothing if both channels already started */
240 if ((TxRingPtr->RunState == XST_DMA_SG_IS_STARTED) &&
241 (RxRingPtr->RunState == XST_DMA_SG_IS_STARTED)) {
242 return;
245 /* Clear pause bits for both TX/ RX channels */
246 RegValue = XLlDma_mGetCr(InstancePtr);
247 XLlDma_mSetCr(InstancePtr, RegValue & ~(XLLDMA_DMACR_TX_PAUSE_MASK |
248 XLLDMA_DMACR_RX_PAUSE_MASK));
250 TxRingPtr->RunState = XST_DMA_SG_IS_STARTED;
251 RxRingPtr->RunState = XST_DMA_SG_IS_STARTED;