xref: /openbmc/linux/drivers/net/ethernet/altera/altera_sgdma.c (revision 898305806ad56ae11dc2c80931062e6a2c7bba48)
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 
23*89830580SVince Bridgers static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
24*89830580SVince Bridgers 				struct sgdma_descrip __iomem *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,
34*89830580SVince Bridgers 			      struct sgdma_descrip __iomem *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,
40*89830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc);
41f64f8808SVince Bridgers 
42f64f8808SVince Bridgers static dma_addr_t
43f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
44*89830580SVince Bridgers 		 struct sgdma_descrip __iomem *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 {
6737c0ffaaSVince Bridgers 	priv->txctrlreg = SGDMA_CTRLREG_ILASTD |
6837c0ffaaSVince Bridgers 		      SGDMA_CTRLREG_INTEN;
69f64f8808SVince Bridgers 
70f64f8808SVince Bridgers 	priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP |
7137c0ffaaSVince Bridgers 		      SGDMA_CTRLREG_INTEN |
72f64f8808SVince Bridgers 		      SGDMA_CTRLREG_ILASTD;
73f64f8808SVince Bridgers 
741b444881STobias Klauser 	priv->sgdmadesclen = sizeof(struct sgdma_descrip);
7537c0ffaaSVince Bridgers 
76f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->txlisthd);
77f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->rxlisthd);
78f64f8808SVince Bridgers 
79f64f8808SVince Bridgers 	priv->rxdescphys = (dma_addr_t) 0;
80f64f8808SVince Bridgers 	priv->txdescphys = (dma_addr_t) 0;
81f64f8808SVince Bridgers 
82*89830580SVince Bridgers 	priv->rxdescphys = dma_map_single(priv->device,
83*89830580SVince Bridgers 					  (void __force *)priv->rx_dma_desc,
84f64f8808SVince Bridgers 					  priv->rxdescmem, DMA_BIDIRECTIONAL);
85f64f8808SVince Bridgers 
86f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->rxdescphys)) {
87f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
88f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping rx descriptor memory\n");
89f64f8808SVince Bridgers 		return -EINVAL;
90f64f8808SVince Bridgers 	}
91f64f8808SVince Bridgers 
92*89830580SVince Bridgers 	priv->txdescphys = dma_map_single(priv->device,
93*89830580SVince Bridgers 					  (void __force *)priv->tx_dma_desc,
9480175f93SVince Bridgers 					  priv->txdescmem, DMA_TO_DEVICE);
95f64f8808SVince Bridgers 
96f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->txdescphys)) {
97f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
98f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping tx descriptor memory\n");
99f64f8808SVince Bridgers 		return -EINVAL;
100f64f8808SVince Bridgers 	}
101f64f8808SVince Bridgers 
10237c0ffaaSVince Bridgers 	/* Initialize descriptor memory to all 0's, sync memory to cache */
103*89830580SVince Bridgers 	memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
104*89830580SVince Bridgers 	memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
10537c0ffaaSVince Bridgers 
10637c0ffaaSVince Bridgers 	dma_sync_single_for_device(priv->device, priv->txdescphys,
10737c0ffaaSVince Bridgers 				   priv->txdescmem, DMA_TO_DEVICE);
10837c0ffaaSVince Bridgers 
10937c0ffaaSVince Bridgers 	dma_sync_single_for_device(priv->device, priv->rxdescphys,
11037c0ffaaSVince Bridgers 				   priv->rxdescmem, DMA_TO_DEVICE);
11137c0ffaaSVince Bridgers 
112f64f8808SVince Bridgers 	return 0;
113f64f8808SVince Bridgers }
114f64f8808SVince Bridgers 
115f64f8808SVince Bridgers void sgdma_uninitialize(struct altera_tse_private *priv)
116f64f8808SVince Bridgers {
117f64f8808SVince Bridgers 	if (priv->rxdescphys)
118f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->rxdescphys,
119f64f8808SVince Bridgers 				 priv->rxdescmem, DMA_BIDIRECTIONAL);
120f64f8808SVince Bridgers 
121f64f8808SVince Bridgers 	if (priv->txdescphys)
122f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->txdescphys,
123f64f8808SVince Bridgers 				 priv->txdescmem, DMA_TO_DEVICE);
124f64f8808SVince Bridgers }
125f64f8808SVince Bridgers 
126f64f8808SVince Bridgers /* This function resets the SGDMA controller and clears the
127f64f8808SVince Bridgers  * descriptor memory used for transmits and receives.
128f64f8808SVince Bridgers  */
129f64f8808SVince Bridgers void sgdma_reset(struct altera_tse_private *priv)
130f64f8808SVince Bridgers {
131f64f8808SVince Bridgers 	/* Initialize descriptor memory to 0 */
132*89830580SVince Bridgers 	memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
133*89830580SVince Bridgers 	memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
134f64f8808SVince Bridgers 
135*89830580SVince Bridgers 	csrwr32(SGDMA_CTRLREG_RESET, priv->tx_dma_csr, sgdma_csroffs(control));
136*89830580SVince Bridgers 	csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
137f64f8808SVince Bridgers 
138*89830580SVince Bridgers 	csrwr32(SGDMA_CTRLREG_RESET, priv->rx_dma_csr, sgdma_csroffs(control));
139*89830580SVince Bridgers 	csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
140f64f8808SVince Bridgers }
141f64f8808SVince Bridgers 
14237c0ffaaSVince Bridgers /* For SGDMA, interrupts remain enabled after initially enabling,
14337c0ffaaSVince Bridgers  * so no need to provide implementations for abstract enable
14437c0ffaaSVince Bridgers  * and disable
14537c0ffaaSVince Bridgers  */
14637c0ffaaSVince Bridgers 
147f64f8808SVince Bridgers void sgdma_enable_rxirq(struct altera_tse_private *priv)
148f64f8808SVince Bridgers {
149f64f8808SVince Bridgers }
150f64f8808SVince Bridgers 
151f64f8808SVince Bridgers void sgdma_enable_txirq(struct altera_tse_private *priv)
152f64f8808SVince Bridgers {
153f64f8808SVince Bridgers }
154f64f8808SVince Bridgers 
155f64f8808SVince Bridgers void sgdma_disable_rxirq(struct altera_tse_private *priv)
156f64f8808SVince Bridgers {
157f64f8808SVince Bridgers }
158f64f8808SVince Bridgers 
159f64f8808SVince Bridgers void sgdma_disable_txirq(struct altera_tse_private *priv)
160f64f8808SVince Bridgers {
161f64f8808SVince Bridgers }
162f64f8808SVince Bridgers 
163f64f8808SVince Bridgers void sgdma_clear_rxirq(struct altera_tse_private *priv)
164f64f8808SVince Bridgers {
165*89830580SVince Bridgers 	tse_set_bit(priv->rx_dma_csr, sgdma_csroffs(control),
166*89830580SVince Bridgers 		    SGDMA_CTRLREG_CLRINT);
167f64f8808SVince Bridgers }
168f64f8808SVince Bridgers 
169f64f8808SVince Bridgers void sgdma_clear_txirq(struct altera_tse_private *priv)
170f64f8808SVince Bridgers {
171*89830580SVince Bridgers 	tse_set_bit(priv->tx_dma_csr, sgdma_csroffs(control),
172*89830580SVince Bridgers 		    SGDMA_CTRLREG_CLRINT);
173f64f8808SVince Bridgers }
174f64f8808SVince Bridgers 
175f64f8808SVince Bridgers /* transmits buffer through SGDMA. Returns number of buffers
176f64f8808SVince Bridgers  * transmitted, 0 if not possible.
177f64f8808SVince Bridgers  *
178f64f8808SVince Bridgers  * tx_lock is held by the caller
179f64f8808SVince Bridgers  */
180f64f8808SVince Bridgers int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
181f64f8808SVince Bridgers {
182*89830580SVince Bridgers 	struct sgdma_descrip __iomem *descbase =
183*89830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->tx_dma_desc;
184f64f8808SVince Bridgers 
185*89830580SVince Bridgers 	struct sgdma_descrip __iomem *cdesc = &descbase[0];
186*89830580SVince Bridgers 	struct sgdma_descrip __iomem *ndesc = &descbase[1];
187f64f8808SVince Bridgers 
188f64f8808SVince Bridgers 	/* wait 'til the tx sgdma is ready for the next transmit request */
189f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
190f64f8808SVince Bridgers 		return 0;
191f64f8808SVince Bridgers 
1921b444881STobias Klauser 	sgdma_setup_descrip(cdesc,			/* current descriptor */
193f64f8808SVince Bridgers 			    ndesc,			/* next descriptor */
194f64f8808SVince Bridgers 			    sgdma_txphysaddr(priv, ndesc),
195f64f8808SVince Bridgers 			    buffer->dma_addr,		/* address of packet to xmit */
196f64f8808SVince Bridgers 			    0,				/* write addr 0 for tx dma */
197f64f8808SVince Bridgers 			    buffer->len,		/* length of packet */
198f64f8808SVince Bridgers 			    SGDMA_CONTROL_EOP,		/* Generate EOP */
199f64f8808SVince Bridgers 			    0,				/* read fixed */
200f64f8808SVince Bridgers 			    SGDMA_CONTROL_WR_FIXED);	/* Generate SOP */
201f64f8808SVince Bridgers 
202*89830580SVince Bridgers 	sgdma_async_write(priv, cdesc);
203f64f8808SVince Bridgers 
204f64f8808SVince Bridgers 	/* enqueue the request to the pending transmit queue */
205f64f8808SVince Bridgers 	queue_tx(priv, buffer);
206f64f8808SVince Bridgers 
207f64f8808SVince Bridgers 	return 1;
208f64f8808SVince Bridgers }
209f64f8808SVince Bridgers 
210f64f8808SVince Bridgers 
211f64f8808SVince Bridgers /* tx_lock held to protect access to queued tx list
212f64f8808SVince Bridgers  */
213f64f8808SVince Bridgers u32 sgdma_tx_completions(struct altera_tse_private *priv)
214f64f8808SVince Bridgers {
215f64f8808SVince Bridgers 	u32 ready = 0;
216f64f8808SVince Bridgers 
217f64f8808SVince Bridgers 	if (!sgdma_txbusy(priv) &&
218*89830580SVince Bridgers 	    ((csrrd8(priv->tx_dma_desc, sgdma_descroffs(control))
219*89830580SVince Bridgers 	     & SGDMA_CONTROL_HW_OWNED) == 0) &&
220f64f8808SVince Bridgers 	    (dequeue_tx(priv))) {
221f64f8808SVince Bridgers 		ready = 1;
222f64f8808SVince Bridgers 	}
223f64f8808SVince Bridgers 
224f64f8808SVince Bridgers 	return ready;
225f64f8808SVince Bridgers }
226f64f8808SVince Bridgers 
22737c0ffaaSVince Bridgers void sgdma_start_rxdma(struct altera_tse_private *priv)
22837c0ffaaSVince Bridgers {
22937c0ffaaSVince Bridgers 	sgdma_async_read(priv);
23037c0ffaaSVince Bridgers }
23137c0ffaaSVince Bridgers 
23237c0ffaaSVince Bridgers void sgdma_add_rx_desc(struct altera_tse_private *priv,
233f64f8808SVince Bridgers 		       struct tse_buffer *rxbuffer)
234f64f8808SVince Bridgers {
235f64f8808SVince Bridgers 	queue_rx(priv, rxbuffer);
236f64f8808SVince Bridgers }
237f64f8808SVince Bridgers 
238f64f8808SVince Bridgers /* status is returned on upper 16 bits,
239f64f8808SVince Bridgers  * length is returned in lower 16 bits
240f64f8808SVince Bridgers  */
241f64f8808SVince Bridgers u32 sgdma_rx_status(struct altera_tse_private *priv)
242f64f8808SVince Bridgers {
243*89830580SVince Bridgers 	struct sgdma_descrip __iomem *base =
244*89830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->rx_dma_desc;
245*89830580SVince Bridgers 	struct sgdma_descrip __iomem *desc = NULL;
246f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
247*89830580SVince Bridgers 	unsigned int rxstatus = 0;
248f64f8808SVince Bridgers 
249*89830580SVince Bridgers 	u32 sts = csrrd32(priv->rx_dma_csr, sgdma_csroffs(status));
250f64f8808SVince Bridgers 
251f64f8808SVince Bridgers 	desc = &base[0];
25237c0ffaaSVince Bridgers 	if (sts & SGDMA_STSREG_EOP) {
253*89830580SVince Bridgers 		unsigned int pktlength = 0;
254*89830580SVince Bridgers 		unsigned int pktstatus = 0;
25537c0ffaaSVince Bridgers 		dma_sync_single_for_cpu(priv->device,
25637c0ffaaSVince Bridgers 					priv->rxdescphys,
25737c0ffaaSVince Bridgers 					priv->sgdmadesclen,
25837c0ffaaSVince Bridgers 					DMA_FROM_DEVICE);
25937c0ffaaSVince Bridgers 
260*89830580SVince Bridgers 		pktlength = csrrd16(desc, sgdma_descroffs(bytes_xferred));
261*89830580SVince Bridgers 		pktstatus = csrrd8(desc, sgdma_descroffs(status));
262*89830580SVince Bridgers 		rxstatus = pktstatus & ~SGDMA_STATUS_EOP;
263f64f8808SVince Bridgers 		rxstatus = rxstatus << 16;
264f64f8808SVince Bridgers 		rxstatus |= (pktlength & 0xffff);
265f64f8808SVince Bridgers 
26637c0ffaaSVince Bridgers 		if (rxstatus) {
267*89830580SVince Bridgers 			csrwr8(0, desc, sgdma_descroffs(status));
268f64f8808SVince Bridgers 
269f64f8808SVince Bridgers 			rxbuffer = dequeue_rx(priv);
270f64f8808SVince Bridgers 			if (rxbuffer == NULL)
27137c0ffaaSVince Bridgers 				netdev_info(priv->dev,
272f64f8808SVince Bridgers 					    "sgdma rx and rx queue empty!\n");
273f64f8808SVince Bridgers 
27437c0ffaaSVince Bridgers 			/* Clear control */
275*89830580SVince Bridgers 			csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
27637c0ffaaSVince Bridgers 			/* clear status */
277*89830580SVince Bridgers 			csrwr32(0xf, priv->rx_dma_csr, sgdma_csroffs(status));
27837c0ffaaSVince Bridgers 
279f64f8808SVince Bridgers 			/* kick the rx sgdma after reaping this descriptor */
280*89830580SVince Bridgers 			sgdma_async_read(priv);
28137c0ffaaSVince Bridgers 
28237c0ffaaSVince Bridgers 		} else {
28337c0ffaaSVince Bridgers 			/* If the SGDMA indicated an end of packet on recv,
28437c0ffaaSVince Bridgers 			 * then it's expected that the rxstatus from the
28537c0ffaaSVince Bridgers 			 * descriptor is non-zero - meaning a valid packet
28637c0ffaaSVince Bridgers 			 * with a nonzero length, or an error has been
28737c0ffaaSVince Bridgers 			 * indicated. if not, then all we can do is signal
28837c0ffaaSVince Bridgers 			 * an error and return no packet received. Most likely
28937c0ffaaSVince Bridgers 			 * there is a system design error, or an error in the
29037c0ffaaSVince Bridgers 			 * underlying kernel (cache or cache management problem)
29137c0ffaaSVince Bridgers 			 */
29237c0ffaaSVince Bridgers 			netdev_err(priv->dev,
29337c0ffaaSVince Bridgers 				   "SGDMA RX Error Info: %x, %x, %x\n",
294*89830580SVince Bridgers 				   sts, csrrd8(desc, sgdma_descroffs(status)),
295*89830580SVince Bridgers 				   rxstatus);
29637c0ffaaSVince Bridgers 		}
29737c0ffaaSVince Bridgers 	} else if (sts == 0) {
298*89830580SVince Bridgers 		sgdma_async_read(priv);
299f64f8808SVince Bridgers 	}
300f64f8808SVince Bridgers 
301f64f8808SVince Bridgers 	return rxstatus;
302f64f8808SVince Bridgers }
303f64f8808SVince Bridgers 
304f64f8808SVince Bridgers 
305f64f8808SVince Bridgers /* Private functions */
306*89830580SVince Bridgers static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
307*89830580SVince Bridgers 				struct sgdma_descrip __iomem *ndesc,
308f64f8808SVince Bridgers 				dma_addr_t ndesc_phys,
309f64f8808SVince Bridgers 				dma_addr_t raddr,
310f64f8808SVince Bridgers 				dma_addr_t waddr,
311f64f8808SVince Bridgers 				u16 length,
312f64f8808SVince Bridgers 				int generate_eop,
313f64f8808SVince Bridgers 				int rfixed,
314f64f8808SVince Bridgers 				int wfixed)
315f64f8808SVince Bridgers {
316f64f8808SVince Bridgers 	/* Clear the next descriptor as not owned by hardware */
317f64f8808SVince Bridgers 
318*89830580SVince Bridgers 	u32 ctrl = csrrd8(ndesc, sgdma_descroffs(control));
319*89830580SVince Bridgers 	ctrl &= ~SGDMA_CONTROL_HW_OWNED;
320*89830580SVince Bridgers 	csrwr8(ctrl, ndesc, sgdma_descroffs(control));
321*89830580SVince Bridgers 
322f64f8808SVince Bridgers 	ctrl = SGDMA_CONTROL_HW_OWNED;
323f64f8808SVince Bridgers 	ctrl |= generate_eop;
324f64f8808SVince Bridgers 	ctrl |= rfixed;
325f64f8808SVince Bridgers 	ctrl |= wfixed;
326f64f8808SVince Bridgers 
327f64f8808SVince Bridgers 	/* Channel is implicitly zero, initialized to 0 by default */
328*89830580SVince Bridgers 	csrwr32(lower_32_bits(raddr), desc, sgdma_descroffs(raddr));
329*89830580SVince Bridgers 	csrwr32(lower_32_bits(waddr), desc, sgdma_descroffs(waddr));
330f64f8808SVince Bridgers 
331*89830580SVince Bridgers 	csrwr32(0, desc, sgdma_descroffs(pad1));
332*89830580SVince Bridgers 	csrwr32(0, desc, sgdma_descroffs(pad2));
333*89830580SVince Bridgers 	csrwr32(lower_32_bits(ndesc_phys), desc, sgdma_descroffs(next));
334*89830580SVince Bridgers 
335*89830580SVince Bridgers 	csrwr8(ctrl, desc, sgdma_descroffs(control));
336*89830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(status));
337*89830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(wburst));
338*89830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(rburst));
339*89830580SVince Bridgers 	csrwr16(length, desc, sgdma_descroffs(bytes));
340*89830580SVince Bridgers 	csrwr16(0, desc, sgdma_descroffs(bytes_xferred));
341f64f8808SVince Bridgers }
342f64f8808SVince Bridgers 
343f64f8808SVince Bridgers /* If hardware is busy, don't restart async read.
344f64f8808SVince Bridgers  * if status register is 0 - meaning initial state, restart async read,
345f64f8808SVince Bridgers  * probably for the first time when populating a receive buffer.
346f64f8808SVince Bridgers  * If read status indicate not busy and a status, restart the async
347f64f8808SVince Bridgers  * DMA read.
348f64f8808SVince Bridgers  */
349f64f8808SVince Bridgers static int sgdma_async_read(struct altera_tse_private *priv)
350f64f8808SVince Bridgers {
351*89830580SVince Bridgers 	struct sgdma_descrip __iomem *descbase =
352*89830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->rx_dma_desc;
353f64f8808SVince Bridgers 
354*89830580SVince Bridgers 	struct sgdma_descrip __iomem *cdesc = &descbase[0];
355*89830580SVince Bridgers 	struct sgdma_descrip __iomem *ndesc = &descbase[1];
356f64f8808SVince Bridgers 
357f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
358f64f8808SVince Bridgers 
359f64f8808SVince Bridgers 	if (!sgdma_rxbusy(priv)) {
360f64f8808SVince Bridgers 		rxbuffer = queue_rx_peekhead(priv);
36137c0ffaaSVince Bridgers 		if (rxbuffer == NULL) {
36237c0ffaaSVince Bridgers 			netdev_err(priv->dev, "no rx buffers available\n");
363f64f8808SVince Bridgers 			return 0;
36437c0ffaaSVince Bridgers 		}
365f64f8808SVince Bridgers 
3661b444881STobias Klauser 		sgdma_setup_descrip(cdesc,		/* current descriptor */
367f64f8808SVince Bridgers 				    ndesc,		/* next descriptor */
368f64f8808SVince Bridgers 				    sgdma_rxphysaddr(priv, ndesc),
369f64f8808SVince Bridgers 				    0,			/* read addr 0 for rx dma */
370f64f8808SVince Bridgers 				    rxbuffer->dma_addr, /* write addr for rx dma */
371f64f8808SVince Bridgers 				    0,			/* read 'til EOP */
372f64f8808SVince Bridgers 				    0,			/* EOP: NA for rx dma */
373f64f8808SVince Bridgers 				    0,			/* read fixed: NA for rx dma */
374f64f8808SVince Bridgers 				    0);			/* SOP: NA for rx DMA */
375f64f8808SVince Bridgers 
376f64f8808SVince Bridgers 		dma_sync_single_for_device(priv->device,
377f64f8808SVince Bridgers 					   priv->rxdescphys,
37837c0ffaaSVince Bridgers 					   priv->sgdmadesclen,
37937c0ffaaSVince Bridgers 					   DMA_TO_DEVICE);
380f64f8808SVince Bridgers 
381*89830580SVince Bridgers 		csrwr32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
382*89830580SVince Bridgers 			priv->rx_dma_csr,
383*89830580SVince Bridgers 			sgdma_csroffs(next_descrip));
384f64f8808SVince Bridgers 
385*89830580SVince Bridgers 		csrwr32((priv->rxctrlreg | SGDMA_CTRLREG_START),
386*89830580SVince Bridgers 			priv->rx_dma_csr,
387*89830580SVince Bridgers 			sgdma_csroffs(control));
388f64f8808SVince Bridgers 
389f64f8808SVince Bridgers 		return 1;
390f64f8808SVince Bridgers 	}
391f64f8808SVince Bridgers 
392f64f8808SVince Bridgers 	return 0;
393f64f8808SVince Bridgers }
394f64f8808SVince Bridgers 
395f64f8808SVince Bridgers static int sgdma_async_write(struct altera_tse_private *priv,
396*89830580SVince Bridgers 			     struct sgdma_descrip __iomem *desc)
397f64f8808SVince Bridgers {
398f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
399f64f8808SVince Bridgers 		return 0;
400f64f8808SVince Bridgers 
401f64f8808SVince Bridgers 	/* clear control and status */
402*89830580SVince Bridgers 	csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
403*89830580SVince Bridgers 	csrwr32(0x1f, priv->tx_dma_csr, sgdma_csroffs(status));
404f64f8808SVince Bridgers 
405f64f8808SVince Bridgers 	dma_sync_single_for_device(priv->device, priv->txdescphys,
40637c0ffaaSVince Bridgers 				   priv->sgdmadesclen, DMA_TO_DEVICE);
407f64f8808SVince Bridgers 
408*89830580SVince Bridgers 	csrwr32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
409*89830580SVince Bridgers 		priv->tx_dma_csr,
410*89830580SVince Bridgers 		sgdma_csroffs(next_descrip));
411f64f8808SVince Bridgers 
412*89830580SVince Bridgers 	csrwr32((priv->txctrlreg | SGDMA_CTRLREG_START),
413*89830580SVince Bridgers 		priv->tx_dma_csr,
414*89830580SVince Bridgers 		sgdma_csroffs(control));
415f64f8808SVince Bridgers 
416f64f8808SVince Bridgers 	return 1;
417f64f8808SVince Bridgers }
418f64f8808SVince Bridgers 
419f64f8808SVince Bridgers static dma_addr_t
420f64f8808SVince Bridgers sgdma_txphysaddr(struct altera_tse_private *priv,
421*89830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc)
422f64f8808SVince Bridgers {
423f64f8808SVince Bridgers 	dma_addr_t paddr = priv->txdescmem_busaddr;
424a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->tx_dma_desc;
425a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
426f64f8808SVince Bridgers }
427f64f8808SVince Bridgers 
428f64f8808SVince Bridgers static dma_addr_t
429f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
430*89830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc)
431f64f8808SVince Bridgers {
432f64f8808SVince Bridgers 	dma_addr_t paddr = priv->rxdescmem_busaddr;
433a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->rx_dma_desc;
434a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
435f64f8808SVince Bridgers }
436f64f8808SVince Bridgers 
437f64f8808SVince Bridgers #define list_remove_head(list, entry, type, member)			\
438f64f8808SVince Bridgers 	do {								\
439f64f8808SVince Bridgers 		entry = NULL;						\
440f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
441f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
442f64f8808SVince Bridgers 			list_del_init(&entry->member);			\
443f64f8808SVince Bridgers 		}							\
444f64f8808SVince Bridgers 	} while (0)
445f64f8808SVince Bridgers 
446f64f8808SVince Bridgers #define list_peek_head(list, entry, type, member)			\
447f64f8808SVince Bridgers 	do {								\
448f64f8808SVince Bridgers 		entry = NULL;						\
449f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
450f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
451f64f8808SVince Bridgers 		}							\
452f64f8808SVince Bridgers 	} while (0)
453f64f8808SVince Bridgers 
454f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a tx buffer list.
455f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
456f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
457f64f8808SVince Bridgers  */
458f64f8808SVince Bridgers static void
459f64f8808SVince Bridgers queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer)
460f64f8808SVince Bridgers {
461f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->txlisthd);
462f64f8808SVince Bridgers }
463f64f8808SVince Bridgers 
464f64f8808SVince Bridgers 
465f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a rx buffer list
466f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
467f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
468f64f8808SVince Bridgers  */
469f64f8808SVince Bridgers static void
470f64f8808SVince Bridgers queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer)
471f64f8808SVince Bridgers {
472f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->rxlisthd);
473f64f8808SVince Bridgers }
474f64f8808SVince Bridgers 
475f64f8808SVince Bridgers /* dequeues a tse_buffer from the transmit buffer list, otherwise
476f64f8808SVince Bridgers  * returns NULL if empty.
477f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
478f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
479f64f8808SVince Bridgers  */
480f64f8808SVince Bridgers static struct tse_buffer *
481f64f8808SVince Bridgers dequeue_tx(struct altera_tse_private *priv)
482f64f8808SVince Bridgers {
483f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
484f64f8808SVince Bridgers 	list_remove_head(&priv->txlisthd, buffer, struct tse_buffer, lh);
485f64f8808SVince Bridgers 	return buffer;
486f64f8808SVince Bridgers }
487f64f8808SVince Bridgers 
488f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
489f64f8808SVince Bridgers  * returns NULL if empty
490f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
491f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
492f64f8808SVince Bridgers  */
493f64f8808SVince Bridgers static struct tse_buffer *
494f64f8808SVince Bridgers dequeue_rx(struct altera_tse_private *priv)
495f64f8808SVince Bridgers {
496f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
497f64f8808SVince Bridgers 	list_remove_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
498f64f8808SVince Bridgers 	return buffer;
499f64f8808SVince Bridgers }
500f64f8808SVince Bridgers 
501f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
502f64f8808SVince Bridgers  * returns NULL if empty
503f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
504f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list while the
505f64f8808SVince Bridgers  * head is being examined.
506f64f8808SVince Bridgers  */
507f64f8808SVince Bridgers static struct tse_buffer *
508f64f8808SVince Bridgers queue_rx_peekhead(struct altera_tse_private *priv)
509f64f8808SVince Bridgers {
510f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
511f64f8808SVince Bridgers 	list_peek_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
512f64f8808SVince Bridgers 	return buffer;
513f64f8808SVince Bridgers }
514f64f8808SVince Bridgers 
515f64f8808SVince Bridgers /* check and return rx sgdma status without polling
516f64f8808SVince Bridgers  */
517f64f8808SVince Bridgers static int sgdma_rxbusy(struct altera_tse_private *priv)
518f64f8808SVince Bridgers {
519*89830580SVince Bridgers 	return csrrd32(priv->rx_dma_csr, sgdma_csroffs(status))
520*89830580SVince Bridgers 		       & SGDMA_STSREG_BUSY;
521f64f8808SVince Bridgers }
522f64f8808SVince Bridgers 
523f64f8808SVince Bridgers /* waits for the tx sgdma to finish it's current operation, returns 0
524f64f8808SVince Bridgers  * when it transitions to nonbusy, returns 1 if the operation times out
525f64f8808SVince Bridgers  */
526f64f8808SVince Bridgers static int sgdma_txbusy(struct altera_tse_private *priv)
527f64f8808SVince Bridgers {
528f64f8808SVince Bridgers 	int delay = 0;
529f64f8808SVince Bridgers 
530f64f8808SVince Bridgers 	/* if DMA is busy, wait for current transactino to finish */
531*89830580SVince Bridgers 	while ((csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
532*89830580SVince Bridgers 		& SGDMA_STSREG_BUSY) && (delay++ < 100))
533f64f8808SVince Bridgers 		udelay(1);
534f64f8808SVince Bridgers 
535*89830580SVince Bridgers 	if (csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
536*89830580SVince Bridgers 	    & SGDMA_STSREG_BUSY) {
537f64f8808SVince Bridgers 		netdev_err(priv->dev, "timeout waiting for tx dma\n");
538f64f8808SVince Bridgers 		return 1;
539f64f8808SVince Bridgers 	}
540f64f8808SVince Bridgers 	return 0;
541f64f8808SVince Bridgers }
542