xref: /openbmc/linux/drivers/net/ethernet/altera/altera_sgdma.c (revision 80175f93f3bd88817f6a59a7253a79a7267f6f82)
1f64f8808SVince Bridgers /* Altera TSE SGDMA and MSGDMA Linux driver
2f64f8808SVince Bridgers  * Copyright (C) 2014 Altera Corporation. All rights reserved
3f64f8808SVince Bridgers  *
4f64f8808SVince Bridgers  * This program is free software; you can redistribute it and/or modify it
5f64f8808SVince Bridgers  * under the terms and conditions of the GNU General Public License,
6f64f8808SVince Bridgers  * version 2, as published by the Free Software Foundation.
7f64f8808SVince Bridgers  *
8f64f8808SVince Bridgers  * This program is distributed in the hope it will be useful, but WITHOUT
9f64f8808SVince Bridgers  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10f64f8808SVince Bridgers  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11f64f8808SVince Bridgers  * more details.
12f64f8808SVince Bridgers  *
13f64f8808SVince Bridgers  * You should have received a copy of the GNU General Public License along with
14f64f8808SVince Bridgers  * this program.  If not, see <http://www.gnu.org/licenses/>.
15f64f8808SVince Bridgers  */
16f64f8808SVince Bridgers 
17f64f8808SVince Bridgers #include <linux/list.h>
18f64f8808SVince Bridgers #include "altera_utils.h"
19f64f8808SVince Bridgers #include "altera_tse.h"
20f64f8808SVince Bridgers #include "altera_sgdmahw.h"
21f64f8808SVince Bridgers #include "altera_sgdma.h"
22f64f8808SVince Bridgers 
23f64f8808SVince Bridgers static void sgdma_descrip(struct sgdma_descrip *desc,
24f64f8808SVince Bridgers 			  struct sgdma_descrip *ndesc,
25f64f8808SVince Bridgers 			  dma_addr_t ndesc_phys,
26f64f8808SVince Bridgers 			  dma_addr_t raddr,
27f64f8808SVince Bridgers 			  dma_addr_t waddr,
28f64f8808SVince Bridgers 			  u16 length,
29f64f8808SVince Bridgers 			  int generate_eop,
30f64f8808SVince Bridgers 			  int rfixed,
31f64f8808SVince Bridgers 			  int wfixed);
32f64f8808SVince Bridgers 
33f64f8808SVince Bridgers static int sgdma_async_write(struct altera_tse_private *priv,
34f64f8808SVince Bridgers 			      struct sgdma_descrip *desc);
35f64f8808SVince Bridgers 
36f64f8808SVince Bridgers static int sgdma_async_read(struct altera_tse_private *priv);
37f64f8808SVince Bridgers 
38f64f8808SVince Bridgers static dma_addr_t
39f64f8808SVince Bridgers sgdma_txphysaddr(struct altera_tse_private *priv,
40f64f8808SVince Bridgers 		 struct sgdma_descrip *desc);
41f64f8808SVince Bridgers 
42f64f8808SVince Bridgers static dma_addr_t
43f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
44f64f8808SVince Bridgers 		 struct sgdma_descrip *desc);
45f64f8808SVince Bridgers 
46f64f8808SVince Bridgers static int sgdma_txbusy(struct altera_tse_private *priv);
47f64f8808SVince Bridgers 
48f64f8808SVince Bridgers static int sgdma_rxbusy(struct altera_tse_private *priv);
49f64f8808SVince Bridgers 
50f64f8808SVince Bridgers static void
51f64f8808SVince Bridgers queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer);
52f64f8808SVince Bridgers 
53f64f8808SVince Bridgers static void
54f64f8808SVince Bridgers queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer);
55f64f8808SVince Bridgers 
56f64f8808SVince Bridgers static struct tse_buffer *
57f64f8808SVince Bridgers dequeue_tx(struct altera_tse_private *priv);
58f64f8808SVince Bridgers 
59f64f8808SVince Bridgers static struct tse_buffer *
60f64f8808SVince Bridgers dequeue_rx(struct altera_tse_private *priv);
61f64f8808SVince Bridgers 
62f64f8808SVince Bridgers static struct tse_buffer *
63f64f8808SVince Bridgers queue_rx_peekhead(struct altera_tse_private *priv);
64f64f8808SVince Bridgers 
65f64f8808SVince Bridgers int sgdma_initialize(struct altera_tse_private *priv)
66f64f8808SVince Bridgers {
67f64f8808SVince Bridgers 	priv->txctrlreg = SGDMA_CTRLREG_ILASTD;
68f64f8808SVince Bridgers 
69f64f8808SVince Bridgers 	priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP |
70f64f8808SVince Bridgers 		      SGDMA_CTRLREG_ILASTD;
71f64f8808SVince Bridgers 
72f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->txlisthd);
73f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->rxlisthd);
74f64f8808SVince Bridgers 
75f64f8808SVince Bridgers 	priv->rxdescphys = (dma_addr_t) 0;
76f64f8808SVince Bridgers 	priv->txdescphys = (dma_addr_t) 0;
77f64f8808SVince Bridgers 
78f64f8808SVince Bridgers 	priv->rxdescphys = dma_map_single(priv->device, priv->rx_dma_desc,
79f64f8808SVince Bridgers 					  priv->rxdescmem, DMA_BIDIRECTIONAL);
80f64f8808SVince Bridgers 
81f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->rxdescphys)) {
82f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
83f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping rx descriptor memory\n");
84f64f8808SVince Bridgers 		return -EINVAL;
85f64f8808SVince Bridgers 	}
86f64f8808SVince Bridgers 
87*80175f93SVince Bridgers 	priv->txdescphys = dma_map_single(priv->device, priv->tx_dma_desc,
88*80175f93SVince Bridgers 					  priv->txdescmem, DMA_TO_DEVICE);
89f64f8808SVince Bridgers 
90f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->txdescphys)) {
91f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
92f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping tx descriptor memory\n");
93f64f8808SVince Bridgers 		return -EINVAL;
94f64f8808SVince Bridgers 	}
95f64f8808SVince Bridgers 
96f64f8808SVince Bridgers 	return 0;
97f64f8808SVince Bridgers }
98f64f8808SVince Bridgers 
99f64f8808SVince Bridgers void sgdma_uninitialize(struct altera_tse_private *priv)
100f64f8808SVince Bridgers {
101f64f8808SVince Bridgers 	if (priv->rxdescphys)
102f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->rxdescphys,
103f64f8808SVince Bridgers 				 priv->rxdescmem, DMA_BIDIRECTIONAL);
104f64f8808SVince Bridgers 
105f64f8808SVince Bridgers 	if (priv->txdescphys)
106f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->txdescphys,
107f64f8808SVince Bridgers 				 priv->txdescmem, DMA_TO_DEVICE);
108f64f8808SVince Bridgers }
109f64f8808SVince Bridgers 
110f64f8808SVince Bridgers /* This function resets the SGDMA controller and clears the
111f64f8808SVince Bridgers  * descriptor memory used for transmits and receives.
112f64f8808SVince Bridgers  */
113f64f8808SVince Bridgers void sgdma_reset(struct altera_tse_private *priv)
114f64f8808SVince Bridgers {
115f64f8808SVince Bridgers 	u32 *ptxdescripmem = (u32 *)priv->tx_dma_desc;
116f64f8808SVince Bridgers 	u32 txdescriplen   = priv->txdescmem;
117f64f8808SVince Bridgers 	u32 *prxdescripmem = (u32 *)priv->rx_dma_desc;
118f64f8808SVince Bridgers 	u32 rxdescriplen   = priv->rxdescmem;
119f64f8808SVince Bridgers 	struct sgdma_csr *ptxsgdma = (struct sgdma_csr *)priv->tx_dma_csr;
120f64f8808SVince Bridgers 	struct sgdma_csr *prxsgdma = (struct sgdma_csr *)priv->rx_dma_csr;
121f64f8808SVince Bridgers 
122f64f8808SVince Bridgers 	/* Initialize descriptor memory to 0 */
123f64f8808SVince Bridgers 	memset(ptxdescripmem, 0, txdescriplen);
124f64f8808SVince Bridgers 	memset(prxdescripmem, 0, rxdescriplen);
125f64f8808SVince Bridgers 
126f64f8808SVince Bridgers 	iowrite32(SGDMA_CTRLREG_RESET, &ptxsgdma->control);
127f64f8808SVince Bridgers 	iowrite32(0, &ptxsgdma->control);
128f64f8808SVince Bridgers 
129f64f8808SVince Bridgers 	iowrite32(SGDMA_CTRLREG_RESET, &prxsgdma->control);
130f64f8808SVince Bridgers 	iowrite32(0, &prxsgdma->control);
131f64f8808SVince Bridgers }
132f64f8808SVince Bridgers 
133f64f8808SVince Bridgers void sgdma_enable_rxirq(struct altera_tse_private *priv)
134f64f8808SVince Bridgers {
135f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
136f64f8808SVince Bridgers 	priv->rxctrlreg |= SGDMA_CTRLREG_INTEN;
137f64f8808SVince Bridgers 	tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
138f64f8808SVince Bridgers }
139f64f8808SVince Bridgers 
140f64f8808SVince Bridgers void sgdma_enable_txirq(struct altera_tse_private *priv)
141f64f8808SVince Bridgers {
142f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
143f64f8808SVince Bridgers 	priv->txctrlreg |= SGDMA_CTRLREG_INTEN;
144f64f8808SVince Bridgers 	tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
145f64f8808SVince Bridgers }
146f64f8808SVince Bridgers 
147f64f8808SVince Bridgers /* for SGDMA, RX interrupts remain enabled after enabling */
148f64f8808SVince Bridgers void sgdma_disable_rxirq(struct altera_tse_private *priv)
149f64f8808SVince Bridgers {
150f64f8808SVince Bridgers }
151f64f8808SVince Bridgers 
152f64f8808SVince Bridgers /* for SGDMA, TX interrupts remain enabled after enabling */
153f64f8808SVince Bridgers void sgdma_disable_txirq(struct altera_tse_private *priv)
154f64f8808SVince Bridgers {
155f64f8808SVince Bridgers }
156f64f8808SVince Bridgers 
157f64f8808SVince Bridgers void sgdma_clear_rxirq(struct altera_tse_private *priv)
158f64f8808SVince Bridgers {
159f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
160f64f8808SVince Bridgers 	tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
161f64f8808SVince Bridgers }
162f64f8808SVince Bridgers 
163f64f8808SVince Bridgers void sgdma_clear_txirq(struct altera_tse_private *priv)
164f64f8808SVince Bridgers {
165f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
166f64f8808SVince Bridgers 	tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
167f64f8808SVince Bridgers }
168f64f8808SVince Bridgers 
169f64f8808SVince Bridgers /* transmits buffer through SGDMA. Returns number of buffers
170f64f8808SVince Bridgers  * transmitted, 0 if not possible.
171f64f8808SVince Bridgers  *
172f64f8808SVince Bridgers  * tx_lock is held by the caller
173f64f8808SVince Bridgers  */
174f64f8808SVince Bridgers int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
175f64f8808SVince Bridgers {
176f64f8808SVince Bridgers 	int pktstx = 0;
177f64f8808SVince Bridgers 	struct sgdma_descrip *descbase =
178f64f8808SVince Bridgers 		(struct sgdma_descrip *)priv->tx_dma_desc;
179f64f8808SVince Bridgers 
180f64f8808SVince Bridgers 	struct sgdma_descrip *cdesc = &descbase[0];
181f64f8808SVince Bridgers 	struct sgdma_descrip *ndesc = &descbase[1];
182f64f8808SVince Bridgers 
183f64f8808SVince Bridgers 	/* wait 'til the tx sgdma is ready for the next transmit request */
184f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
185f64f8808SVince Bridgers 		return 0;
186f64f8808SVince Bridgers 
187f64f8808SVince Bridgers 	sgdma_descrip(cdesc,			/* current descriptor */
188f64f8808SVince Bridgers 		      ndesc,			/* next descriptor */
189f64f8808SVince Bridgers 		      sgdma_txphysaddr(priv, ndesc),
190f64f8808SVince Bridgers 		      buffer->dma_addr,		/* address of packet to xmit */
191f64f8808SVince Bridgers 		      0,			/* write addr 0 for tx dma */
192f64f8808SVince Bridgers 		      buffer->len,		/* length of packet */
193f64f8808SVince Bridgers 		      SGDMA_CONTROL_EOP,	/* Generate EOP */
194f64f8808SVince Bridgers 		      0,			/* read fixed */
195f64f8808SVince Bridgers 		      SGDMA_CONTROL_WR_FIXED);	/* Generate SOP */
196f64f8808SVince Bridgers 
197f64f8808SVince Bridgers 	pktstx = sgdma_async_write(priv, cdesc);
198f64f8808SVince Bridgers 
199f64f8808SVince Bridgers 	/* enqueue the request to the pending transmit queue */
200f64f8808SVince Bridgers 	queue_tx(priv, buffer);
201f64f8808SVince Bridgers 
202f64f8808SVince Bridgers 	return 1;
203f64f8808SVince Bridgers }
204f64f8808SVince Bridgers 
205f64f8808SVince Bridgers 
206f64f8808SVince Bridgers /* tx_lock held to protect access to queued tx list
207f64f8808SVince Bridgers  */
208f64f8808SVince Bridgers u32 sgdma_tx_completions(struct altera_tse_private *priv)
209f64f8808SVince Bridgers {
210f64f8808SVince Bridgers 	u32 ready = 0;
211f64f8808SVince Bridgers 	struct sgdma_descrip *desc = (struct sgdma_descrip *)priv->tx_dma_desc;
212f64f8808SVince Bridgers 
213f64f8808SVince Bridgers 	if (!sgdma_txbusy(priv) &&
214f64f8808SVince Bridgers 	    ((desc->control & SGDMA_CONTROL_HW_OWNED) == 0) &&
215f64f8808SVince Bridgers 	    (dequeue_tx(priv))) {
216f64f8808SVince Bridgers 		ready = 1;
217f64f8808SVince Bridgers 	}
218f64f8808SVince Bridgers 
219f64f8808SVince Bridgers 	return ready;
220f64f8808SVince Bridgers }
221f64f8808SVince Bridgers 
222f64f8808SVince Bridgers int sgdma_add_rx_desc(struct altera_tse_private *priv,
223f64f8808SVince Bridgers 		      struct tse_buffer *rxbuffer)
224f64f8808SVince Bridgers {
225f64f8808SVince Bridgers 	queue_rx(priv, rxbuffer);
226f64f8808SVince Bridgers 	return sgdma_async_read(priv);
227f64f8808SVince Bridgers }
228f64f8808SVince Bridgers 
229f64f8808SVince Bridgers /* status is returned on upper 16 bits,
230f64f8808SVince Bridgers  * length is returned in lower 16 bits
231f64f8808SVince Bridgers  */
232f64f8808SVince Bridgers u32 sgdma_rx_status(struct altera_tse_private *priv)
233f64f8808SVince Bridgers {
234f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
235f64f8808SVince Bridgers 	struct sgdma_descrip *base = (struct sgdma_descrip *)priv->rx_dma_desc;
236f64f8808SVince Bridgers 	struct sgdma_descrip *desc = NULL;
237f64f8808SVince Bridgers 	int pktsrx;
238f64f8808SVince Bridgers 	unsigned int rxstatus = 0;
239f64f8808SVince Bridgers 	unsigned int pktlength = 0;
240f64f8808SVince Bridgers 	unsigned int pktstatus = 0;
241f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
242f64f8808SVince Bridgers 
243f64f8808SVince Bridgers 	dma_sync_single_for_cpu(priv->device,
244f64f8808SVince Bridgers 				priv->rxdescphys,
245f64f8808SVince Bridgers 				priv->rxdescmem,
246f64f8808SVince Bridgers 				DMA_BIDIRECTIONAL);
247f64f8808SVince Bridgers 
248f64f8808SVince Bridgers 	desc = &base[0];
249f64f8808SVince Bridgers 	if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) ||
250f64f8808SVince Bridgers 	    (desc->status & SGDMA_STATUS_EOP)) {
251f64f8808SVince Bridgers 		pktlength = desc->bytes_xferred;
252f64f8808SVince Bridgers 		pktstatus = desc->status & 0x3f;
253f64f8808SVince Bridgers 		rxstatus = pktstatus;
254f64f8808SVince Bridgers 		rxstatus = rxstatus << 16;
255f64f8808SVince Bridgers 		rxstatus |= (pktlength & 0xffff);
256f64f8808SVince Bridgers 
257f64f8808SVince Bridgers 		desc->status = 0;
258f64f8808SVince Bridgers 
259f64f8808SVince Bridgers 		rxbuffer = dequeue_rx(priv);
260f64f8808SVince Bridgers 		if (rxbuffer == NULL)
261f64f8808SVince Bridgers 			netdev_err(priv->dev,
262f64f8808SVince Bridgers 				   "sgdma rx and rx queue empty!\n");
263f64f8808SVince Bridgers 
264f64f8808SVince Bridgers 		/* kick the rx sgdma after reaping this descriptor */
265f64f8808SVince Bridgers 		pktsrx = sgdma_async_read(priv);
266f64f8808SVince Bridgers 	}
267f64f8808SVince Bridgers 
268f64f8808SVince Bridgers 	return rxstatus;
269f64f8808SVince Bridgers }
270f64f8808SVince Bridgers 
271f64f8808SVince Bridgers 
272f64f8808SVince Bridgers /* Private functions */
273f64f8808SVince Bridgers static void sgdma_descrip(struct sgdma_descrip *desc,
274f64f8808SVince Bridgers 			  struct sgdma_descrip *ndesc,
275f64f8808SVince Bridgers 			  dma_addr_t ndesc_phys,
276f64f8808SVince Bridgers 			  dma_addr_t raddr,
277f64f8808SVince Bridgers 			  dma_addr_t waddr,
278f64f8808SVince Bridgers 			  u16 length,
279f64f8808SVince Bridgers 			  int generate_eop,
280f64f8808SVince Bridgers 			  int rfixed,
281f64f8808SVince Bridgers 			  int wfixed)
282f64f8808SVince Bridgers {
283f64f8808SVince Bridgers 	/* Clear the next descriptor as not owned by hardware */
284f64f8808SVince Bridgers 	u32 ctrl = ndesc->control;
285f64f8808SVince Bridgers 	ctrl &= ~SGDMA_CONTROL_HW_OWNED;
286f64f8808SVince Bridgers 	ndesc->control = ctrl;
287f64f8808SVince Bridgers 
288f64f8808SVince Bridgers 	ctrl = 0;
289f64f8808SVince Bridgers 	ctrl = SGDMA_CONTROL_HW_OWNED;
290f64f8808SVince Bridgers 	ctrl |= generate_eop;
291f64f8808SVince Bridgers 	ctrl |= rfixed;
292f64f8808SVince Bridgers 	ctrl |= wfixed;
293f64f8808SVince Bridgers 
294f64f8808SVince Bridgers 	/* Channel is implicitly zero, initialized to 0 by default */
295f64f8808SVince Bridgers 
296f64f8808SVince Bridgers 	desc->raddr = raddr;
297f64f8808SVince Bridgers 	desc->waddr = waddr;
298f64f8808SVince Bridgers 	desc->next = lower_32_bits(ndesc_phys);
299f64f8808SVince Bridgers 	desc->control = ctrl;
300f64f8808SVince Bridgers 	desc->status = 0;
301f64f8808SVince Bridgers 	desc->rburst = 0;
302f64f8808SVince Bridgers 	desc->wburst = 0;
303f64f8808SVince Bridgers 	desc->bytes = length;
304f64f8808SVince Bridgers 	desc->bytes_xferred = 0;
305f64f8808SVince Bridgers }
306f64f8808SVince Bridgers 
307f64f8808SVince Bridgers /* If hardware is busy, don't restart async read.
308f64f8808SVince Bridgers  * if status register is 0 - meaning initial state, restart async read,
309f64f8808SVince Bridgers  * probably for the first time when populating a receive buffer.
310f64f8808SVince Bridgers  * If read status indicate not busy and a status, restart the async
311f64f8808SVince Bridgers  * DMA read.
312f64f8808SVince Bridgers  */
313f64f8808SVince Bridgers static int sgdma_async_read(struct altera_tse_private *priv)
314f64f8808SVince Bridgers {
315f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
316f64f8808SVince Bridgers 	struct sgdma_descrip *descbase =
317f64f8808SVince Bridgers 		(struct sgdma_descrip *)priv->rx_dma_desc;
318f64f8808SVince Bridgers 
319f64f8808SVince Bridgers 	struct sgdma_descrip *cdesc = &descbase[0];
320f64f8808SVince Bridgers 	struct sgdma_descrip *ndesc = &descbase[1];
321f64f8808SVince Bridgers 
322f64f8808SVince Bridgers 	unsigned int sts = ioread32(&csr->status);
323f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
324f64f8808SVince Bridgers 
325f64f8808SVince Bridgers 	if (!sgdma_rxbusy(priv)) {
326f64f8808SVince Bridgers 		rxbuffer = queue_rx_peekhead(priv);
327f64f8808SVince Bridgers 		if (rxbuffer == NULL)
328f64f8808SVince Bridgers 			return 0;
329f64f8808SVince Bridgers 
330f64f8808SVince Bridgers 		sgdma_descrip(cdesc,		/* current descriptor */
331f64f8808SVince Bridgers 			      ndesc,		/* next descriptor */
332f64f8808SVince Bridgers 			      sgdma_rxphysaddr(priv, ndesc),
333f64f8808SVince Bridgers 			      0,		/* read addr 0 for rx dma */
334f64f8808SVince Bridgers 			      rxbuffer->dma_addr, /* write addr for rx dma */
335f64f8808SVince Bridgers 			      0,		/* read 'til EOP */
336f64f8808SVince Bridgers 			      0,		/* EOP: NA for rx dma */
337f64f8808SVince Bridgers 			      0,		/* read fixed: NA for rx dma */
338f64f8808SVince Bridgers 			      0);		/* SOP: NA for rx DMA */
339f64f8808SVince Bridgers 
340f64f8808SVince Bridgers 		/* clear control and status */
341f64f8808SVince Bridgers 		iowrite32(0, &csr->control);
342f64f8808SVince Bridgers 
343*80175f93SVince Bridgers 		/* If status available, clear those bits */
344f64f8808SVince Bridgers 		if (sts & 0xf)
345f64f8808SVince Bridgers 			iowrite32(0xf, &csr->status);
346f64f8808SVince Bridgers 
347f64f8808SVince Bridgers 		dma_sync_single_for_device(priv->device,
348f64f8808SVince Bridgers 					   priv->rxdescphys,
349f64f8808SVince Bridgers 					   priv->rxdescmem,
350f64f8808SVince Bridgers 					   DMA_BIDIRECTIONAL);
351f64f8808SVince Bridgers 
352f64f8808SVince Bridgers 		iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
353f64f8808SVince Bridgers 			  &csr->next_descrip);
354f64f8808SVince Bridgers 
355f64f8808SVince Bridgers 		iowrite32((priv->rxctrlreg | SGDMA_CTRLREG_START),
356f64f8808SVince Bridgers 			  &csr->control);
357f64f8808SVince Bridgers 
358f64f8808SVince Bridgers 		return 1;
359f64f8808SVince Bridgers 	}
360f64f8808SVince Bridgers 
361f64f8808SVince Bridgers 	return 0;
362f64f8808SVince Bridgers }
363f64f8808SVince Bridgers 
364f64f8808SVince Bridgers static int sgdma_async_write(struct altera_tse_private *priv,
365f64f8808SVince Bridgers 			     struct sgdma_descrip *desc)
366f64f8808SVince Bridgers {
367f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
368f64f8808SVince Bridgers 
369f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
370f64f8808SVince Bridgers 		return 0;
371f64f8808SVince Bridgers 
372f64f8808SVince Bridgers 	/* clear control and status */
373f64f8808SVince Bridgers 	iowrite32(0, &csr->control);
374f64f8808SVince Bridgers 	iowrite32(0x1f, &csr->status);
375f64f8808SVince Bridgers 
376f64f8808SVince Bridgers 	dma_sync_single_for_device(priv->device, priv->txdescphys,
377f64f8808SVince Bridgers 				   priv->txdescmem, DMA_TO_DEVICE);
378f64f8808SVince Bridgers 
379f64f8808SVince Bridgers 	iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
380f64f8808SVince Bridgers 		  &csr->next_descrip);
381f64f8808SVince Bridgers 
382f64f8808SVince Bridgers 	iowrite32((priv->txctrlreg | SGDMA_CTRLREG_START),
383f64f8808SVince Bridgers 		  &csr->control);
384f64f8808SVince Bridgers 
385f64f8808SVince Bridgers 	return 1;
386f64f8808SVince Bridgers }
387f64f8808SVince Bridgers 
388f64f8808SVince Bridgers static dma_addr_t
389f64f8808SVince Bridgers sgdma_txphysaddr(struct altera_tse_private *priv,
390f64f8808SVince Bridgers 		 struct sgdma_descrip *desc)
391f64f8808SVince Bridgers {
392f64f8808SVince Bridgers 	dma_addr_t paddr = priv->txdescmem_busaddr;
393a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->tx_dma_desc;
394a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
395f64f8808SVince Bridgers }
396f64f8808SVince Bridgers 
397f64f8808SVince Bridgers static dma_addr_t
398f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
399f64f8808SVince Bridgers 		 struct sgdma_descrip *desc)
400f64f8808SVince Bridgers {
401f64f8808SVince Bridgers 	dma_addr_t paddr = priv->rxdescmem_busaddr;
402a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->rx_dma_desc;
403a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
404f64f8808SVince Bridgers }
405f64f8808SVince Bridgers 
406f64f8808SVince Bridgers #define list_remove_head(list, entry, type, member)			\
407f64f8808SVince Bridgers 	do {								\
408f64f8808SVince Bridgers 		entry = NULL;						\
409f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
410f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
411f64f8808SVince Bridgers 			list_del_init(&entry->member);			\
412f64f8808SVince Bridgers 		}							\
413f64f8808SVince Bridgers 	} while (0)
414f64f8808SVince Bridgers 
415f64f8808SVince Bridgers #define list_peek_head(list, entry, type, member)			\
416f64f8808SVince Bridgers 	do {								\
417f64f8808SVince Bridgers 		entry = NULL;						\
418f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
419f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
420f64f8808SVince Bridgers 		}							\
421f64f8808SVince Bridgers 	} while (0)
422f64f8808SVince Bridgers 
423f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a tx buffer list.
424f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
425f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
426f64f8808SVince Bridgers  */
427f64f8808SVince Bridgers static void
428f64f8808SVince Bridgers queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer)
429f64f8808SVince Bridgers {
430f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->txlisthd);
431f64f8808SVince Bridgers }
432f64f8808SVince Bridgers 
433f64f8808SVince Bridgers 
434f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a rx buffer list
435f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
436f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
437f64f8808SVince Bridgers  */
438f64f8808SVince Bridgers static void
439f64f8808SVince Bridgers queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer)
440f64f8808SVince Bridgers {
441f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->rxlisthd);
442f64f8808SVince Bridgers }
443f64f8808SVince Bridgers 
444f64f8808SVince Bridgers /* dequeues a tse_buffer from the transmit buffer list, otherwise
445f64f8808SVince Bridgers  * returns NULL if empty.
446f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
447f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
448f64f8808SVince Bridgers  */
449f64f8808SVince Bridgers static struct tse_buffer *
450f64f8808SVince Bridgers dequeue_tx(struct altera_tse_private *priv)
451f64f8808SVince Bridgers {
452f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
453f64f8808SVince Bridgers 	list_remove_head(&priv->txlisthd, buffer, struct tse_buffer, lh);
454f64f8808SVince Bridgers 	return buffer;
455f64f8808SVince Bridgers }
456f64f8808SVince Bridgers 
457f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
458f64f8808SVince Bridgers  * returns NULL if empty
459f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
460f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
461f64f8808SVince Bridgers  */
462f64f8808SVince Bridgers static struct tse_buffer *
463f64f8808SVince Bridgers dequeue_rx(struct altera_tse_private *priv)
464f64f8808SVince Bridgers {
465f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
466f64f8808SVince Bridgers 	list_remove_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
467f64f8808SVince Bridgers 	return buffer;
468f64f8808SVince Bridgers }
469f64f8808SVince Bridgers 
470f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
471f64f8808SVince Bridgers  * returns NULL if empty
472f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
473f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list while the
474f64f8808SVince Bridgers  * head is being examined.
475f64f8808SVince Bridgers  */
476f64f8808SVince Bridgers static struct tse_buffer *
477f64f8808SVince Bridgers queue_rx_peekhead(struct altera_tse_private *priv)
478f64f8808SVince Bridgers {
479f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
480f64f8808SVince Bridgers 	list_peek_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
481f64f8808SVince Bridgers 	return buffer;
482f64f8808SVince Bridgers }
483f64f8808SVince Bridgers 
484f64f8808SVince Bridgers /* check and return rx sgdma status without polling
485f64f8808SVince Bridgers  */
486f64f8808SVince Bridgers static int sgdma_rxbusy(struct altera_tse_private *priv)
487f64f8808SVince Bridgers {
488f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
489f64f8808SVince Bridgers 	return ioread32(&csr->status) & SGDMA_STSREG_BUSY;
490f64f8808SVince Bridgers }
491f64f8808SVince Bridgers 
492f64f8808SVince Bridgers /* waits for the tx sgdma to finish it's current operation, returns 0
493f64f8808SVince Bridgers  * when it transitions to nonbusy, returns 1 if the operation times out
494f64f8808SVince Bridgers  */
495f64f8808SVince Bridgers static int sgdma_txbusy(struct altera_tse_private *priv)
496f64f8808SVince Bridgers {
497f64f8808SVince Bridgers 	int delay = 0;
498f64f8808SVince Bridgers 	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
499f64f8808SVince Bridgers 
500f64f8808SVince Bridgers 	/* if DMA is busy, wait for current transactino to finish */
501f64f8808SVince Bridgers 	while ((ioread32(&csr->status) & SGDMA_STSREG_BUSY) && (delay++ < 100))
502f64f8808SVince Bridgers 		udelay(1);
503f64f8808SVince Bridgers 
504f64f8808SVince Bridgers 	if (ioread32(&csr->status) & SGDMA_STSREG_BUSY) {
505f64f8808SVince Bridgers 		netdev_err(priv->dev, "timeout waiting for tx dma\n");
506f64f8808SVince Bridgers 		return 1;
507f64f8808SVince Bridgers 	}
508f64f8808SVince Bridgers 	return 0;
509f64f8808SVince Bridgers }
510