xref: /openbmc/linux/drivers/net/ethernet/altera/altera_sgdma.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
19952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f64f8808SVince Bridgers /* Altera TSE SGDMA and MSGDMA Linux driver
3f64f8808SVince Bridgers  * Copyright (C) 2014 Altera Corporation. All rights reserved
4f64f8808SVince Bridgers  */
5f64f8808SVince Bridgers 
6f64f8808SVince Bridgers #include <linux/list.h>
7f64f8808SVince Bridgers #include "altera_utils.h"
8f64f8808SVince Bridgers #include "altera_tse.h"
9f64f8808SVince Bridgers #include "altera_sgdmahw.h"
10f64f8808SVince Bridgers #include "altera_sgdma.h"
11f64f8808SVince Bridgers 
1289830580SVince Bridgers static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
1389830580SVince Bridgers 				struct sgdma_descrip __iomem *ndesc,
14f64f8808SVince Bridgers 				dma_addr_t ndesc_phys,
15f64f8808SVince Bridgers 				dma_addr_t raddr,
16f64f8808SVince Bridgers 				dma_addr_t waddr,
17f64f8808SVince Bridgers 				u16 length,
18f64f8808SVince Bridgers 				int generate_eop,
19f64f8808SVince Bridgers 				int rfixed,
20f64f8808SVince Bridgers 				int wfixed);
21f64f8808SVince Bridgers 
22f64f8808SVince Bridgers static int sgdma_async_write(struct altera_tse_private *priv,
2389830580SVince Bridgers 			      struct sgdma_descrip __iomem *desc);
24f64f8808SVince Bridgers 
25f64f8808SVince Bridgers static int sgdma_async_read(struct altera_tse_private *priv);
26f64f8808SVince Bridgers 
27f64f8808SVince Bridgers static dma_addr_t
28f64f8808SVince Bridgers sgdma_txphysaddr(struct altera_tse_private *priv,
2989830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc);
30f64f8808SVince Bridgers 
31f64f8808SVince Bridgers static dma_addr_t
32f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
3389830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc);
34f64f8808SVince Bridgers 
35f64f8808SVince Bridgers static int sgdma_txbusy(struct altera_tse_private *priv);
36f64f8808SVince Bridgers 
37f64f8808SVince Bridgers static int sgdma_rxbusy(struct altera_tse_private *priv);
38f64f8808SVince Bridgers 
39f64f8808SVince Bridgers static void
40f64f8808SVince Bridgers queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer);
41f64f8808SVince Bridgers 
42f64f8808SVince Bridgers static void
43f64f8808SVince Bridgers queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer);
44f64f8808SVince Bridgers 
45f64f8808SVince Bridgers static struct tse_buffer *
46f64f8808SVince Bridgers dequeue_tx(struct altera_tse_private *priv);
47f64f8808SVince Bridgers 
48f64f8808SVince Bridgers static struct tse_buffer *
49f64f8808SVince Bridgers dequeue_rx(struct altera_tse_private *priv);
50f64f8808SVince Bridgers 
51f64f8808SVince Bridgers static struct tse_buffer *
52f64f8808SVince Bridgers queue_rx_peekhead(struct altera_tse_private *priv);
53f64f8808SVince Bridgers 
sgdma_initialize(struct altera_tse_private * priv)54f64f8808SVince Bridgers int sgdma_initialize(struct altera_tse_private *priv)
55f64f8808SVince Bridgers {
5637c0ffaaSVince Bridgers 	priv->txctrlreg = SGDMA_CTRLREG_ILASTD |
5737c0ffaaSVince Bridgers 		      SGDMA_CTRLREG_INTEN;
58f64f8808SVince Bridgers 
59f64f8808SVince Bridgers 	priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP |
6037c0ffaaSVince Bridgers 		      SGDMA_CTRLREG_INTEN |
61f64f8808SVince Bridgers 		      SGDMA_CTRLREG_ILASTD;
62f64f8808SVince Bridgers 
63f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->txlisthd);
64f64f8808SVince Bridgers 	INIT_LIST_HEAD(&priv->rxlisthd);
65f64f8808SVince Bridgers 
66f64f8808SVince Bridgers 	priv->rxdescphys = (dma_addr_t) 0;
67f64f8808SVince Bridgers 	priv->txdescphys = (dma_addr_t) 0;
68f64f8808SVince Bridgers 
6989830580SVince Bridgers 	priv->rxdescphys = dma_map_single(priv->device,
7089830580SVince Bridgers 					  (void __force *)priv->rx_dma_desc,
71f64f8808SVince Bridgers 					  priv->rxdescmem, DMA_BIDIRECTIONAL);
72f64f8808SVince Bridgers 
73f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->rxdescphys)) {
74f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
75f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping rx descriptor memory\n");
76f64f8808SVince Bridgers 		return -EINVAL;
77f64f8808SVince Bridgers 	}
78f64f8808SVince Bridgers 
7989830580SVince Bridgers 	priv->txdescphys = dma_map_single(priv->device,
8089830580SVince Bridgers 					  (void __force *)priv->tx_dma_desc,
8180175f93SVince Bridgers 					  priv->txdescmem, DMA_TO_DEVICE);
82f64f8808SVince Bridgers 
83f64f8808SVince Bridgers 	if (dma_mapping_error(priv->device, priv->txdescphys)) {
84f64f8808SVince Bridgers 		sgdma_uninitialize(priv);
85f64f8808SVince Bridgers 		netdev_err(priv->dev, "error mapping tx descriptor memory\n");
86f64f8808SVince Bridgers 		return -EINVAL;
87f64f8808SVince Bridgers 	}
88f64f8808SVince Bridgers 
8937c0ffaaSVince Bridgers 	/* Initialize descriptor memory to all 0's, sync memory to cache */
9089830580SVince Bridgers 	memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
9189830580SVince Bridgers 	memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
9237c0ffaaSVince Bridgers 
9337c0ffaaSVince Bridgers 	dma_sync_single_for_device(priv->device, priv->txdescphys,
9437c0ffaaSVince Bridgers 				   priv->txdescmem, DMA_TO_DEVICE);
9537c0ffaaSVince Bridgers 
9637c0ffaaSVince Bridgers 	dma_sync_single_for_device(priv->device, priv->rxdescphys,
9737c0ffaaSVince Bridgers 				   priv->rxdescmem, DMA_TO_DEVICE);
9837c0ffaaSVince Bridgers 
99f64f8808SVince Bridgers 	return 0;
100f64f8808SVince Bridgers }
101f64f8808SVince Bridgers 
sgdma_uninitialize(struct altera_tse_private * priv)102f64f8808SVince Bridgers void sgdma_uninitialize(struct altera_tse_private *priv)
103f64f8808SVince Bridgers {
104f64f8808SVince Bridgers 	if (priv->rxdescphys)
105f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->rxdescphys,
106f64f8808SVince Bridgers 				 priv->rxdescmem, DMA_BIDIRECTIONAL);
107f64f8808SVince Bridgers 
108f64f8808SVince Bridgers 	if (priv->txdescphys)
109f64f8808SVince Bridgers 		dma_unmap_single(priv->device, priv->txdescphys,
110f64f8808SVince Bridgers 				 priv->txdescmem, DMA_TO_DEVICE);
111f64f8808SVince Bridgers }
112f64f8808SVince Bridgers 
113f64f8808SVince Bridgers /* This function resets the SGDMA controller and clears the
114f64f8808SVince Bridgers  * descriptor memory used for transmits and receives.
115f64f8808SVince Bridgers  */
sgdma_reset(struct altera_tse_private * priv)116f64f8808SVince Bridgers void sgdma_reset(struct altera_tse_private *priv)
117f64f8808SVince Bridgers {
118f64f8808SVince Bridgers 	/* Initialize descriptor memory to 0 */
11989830580SVince Bridgers 	memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
12089830580SVince Bridgers 	memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
121f64f8808SVince Bridgers 
12289830580SVince Bridgers 	csrwr32(SGDMA_CTRLREG_RESET, priv->tx_dma_csr, sgdma_csroffs(control));
12389830580SVince Bridgers 	csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
124f64f8808SVince Bridgers 
12589830580SVince Bridgers 	csrwr32(SGDMA_CTRLREG_RESET, priv->rx_dma_csr, sgdma_csroffs(control));
12689830580SVince Bridgers 	csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
127f64f8808SVince Bridgers }
128f64f8808SVince Bridgers 
12937c0ffaaSVince Bridgers /* For SGDMA, interrupts remain enabled after initially enabling,
13037c0ffaaSVince Bridgers  * so no need to provide implementations for abstract enable
13137c0ffaaSVince Bridgers  * and disable
13237c0ffaaSVince Bridgers  */
13337c0ffaaSVince Bridgers 
sgdma_enable_rxirq(struct altera_tse_private * priv)134f64f8808SVince Bridgers void sgdma_enable_rxirq(struct altera_tse_private *priv)
135f64f8808SVince Bridgers {
136f64f8808SVince Bridgers }
137f64f8808SVince Bridgers 
sgdma_enable_txirq(struct altera_tse_private * priv)138f64f8808SVince Bridgers void sgdma_enable_txirq(struct altera_tse_private *priv)
139f64f8808SVince Bridgers {
140f64f8808SVince Bridgers }
141f64f8808SVince Bridgers 
sgdma_disable_rxirq(struct altera_tse_private * priv)142f64f8808SVince Bridgers void sgdma_disable_rxirq(struct altera_tse_private *priv)
143f64f8808SVince Bridgers {
144f64f8808SVince Bridgers }
145f64f8808SVince Bridgers 
sgdma_disable_txirq(struct altera_tse_private * priv)146f64f8808SVince Bridgers void sgdma_disable_txirq(struct altera_tse_private *priv)
147f64f8808SVince Bridgers {
148f64f8808SVince Bridgers }
149f64f8808SVince Bridgers 
sgdma_clear_rxirq(struct altera_tse_private * priv)150f64f8808SVince Bridgers void sgdma_clear_rxirq(struct altera_tse_private *priv)
151f64f8808SVince Bridgers {
15289830580SVince Bridgers 	tse_set_bit(priv->rx_dma_csr, sgdma_csroffs(control),
15389830580SVince Bridgers 		    SGDMA_CTRLREG_CLRINT);
154f64f8808SVince Bridgers }
155f64f8808SVince Bridgers 
sgdma_clear_txirq(struct altera_tse_private * priv)156f64f8808SVince Bridgers void sgdma_clear_txirq(struct altera_tse_private *priv)
157f64f8808SVince Bridgers {
15889830580SVince Bridgers 	tse_set_bit(priv->tx_dma_csr, sgdma_csroffs(control),
15989830580SVince Bridgers 		    SGDMA_CTRLREG_CLRINT);
160f64f8808SVince Bridgers }
161f64f8808SVince Bridgers 
162f64f8808SVince Bridgers /* transmits buffer through SGDMA. Returns number of buffers
163f64f8808SVince Bridgers  * transmitted, 0 if not possible.
164f64f8808SVince Bridgers  *
165f64f8808SVince Bridgers  * tx_lock is held by the caller
166f64f8808SVince Bridgers  */
sgdma_tx_buffer(struct altera_tse_private * priv,struct tse_buffer * buffer)167f64f8808SVince Bridgers int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
168f64f8808SVince Bridgers {
16989830580SVince Bridgers 	struct sgdma_descrip __iomem *descbase =
17089830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->tx_dma_desc;
171f64f8808SVince Bridgers 
17289830580SVince Bridgers 	struct sgdma_descrip __iomem *cdesc = &descbase[0];
17389830580SVince Bridgers 	struct sgdma_descrip __iomem *ndesc = &descbase[1];
174f64f8808SVince Bridgers 
175f64f8808SVince Bridgers 	/* wait 'til the tx sgdma is ready for the next transmit request */
176f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
177f64f8808SVince Bridgers 		return 0;
178f64f8808SVince Bridgers 
1791b444881STobias Klauser 	sgdma_setup_descrip(cdesc,			/* current descriptor */
180f64f8808SVince Bridgers 			    ndesc,			/* next descriptor */
181f64f8808SVince Bridgers 			    sgdma_txphysaddr(priv, ndesc),
182f64f8808SVince Bridgers 			    buffer->dma_addr,		/* address of packet to xmit */
183f64f8808SVince Bridgers 			    0,				/* write addr 0 for tx dma */
184f64f8808SVince Bridgers 			    buffer->len,		/* length of packet */
185f64f8808SVince Bridgers 			    SGDMA_CONTROL_EOP,		/* Generate EOP */
186f64f8808SVince Bridgers 			    0,				/* read fixed */
187f64f8808SVince Bridgers 			    SGDMA_CONTROL_WR_FIXED);	/* Generate SOP */
188f64f8808SVince Bridgers 
18989830580SVince Bridgers 	sgdma_async_write(priv, cdesc);
190f64f8808SVince Bridgers 
191f64f8808SVince Bridgers 	/* enqueue the request to the pending transmit queue */
192f64f8808SVince Bridgers 	queue_tx(priv, buffer);
193f64f8808SVince Bridgers 
194f64f8808SVince Bridgers 	return 1;
195f64f8808SVince Bridgers }
196f64f8808SVince Bridgers 
197f64f8808SVince Bridgers 
198f64f8808SVince Bridgers /* tx_lock held to protect access to queued tx list
199f64f8808SVince Bridgers  */
sgdma_tx_completions(struct altera_tse_private * priv)200f64f8808SVince Bridgers u32 sgdma_tx_completions(struct altera_tse_private *priv)
201f64f8808SVince Bridgers {
202f64f8808SVince Bridgers 	u32 ready = 0;
203f64f8808SVince Bridgers 
204f64f8808SVince Bridgers 	if (!sgdma_txbusy(priv) &&
20589830580SVince Bridgers 	    ((csrrd8(priv->tx_dma_desc, sgdma_descroffs(control))
20689830580SVince Bridgers 	     & SGDMA_CONTROL_HW_OWNED) == 0) &&
207f64f8808SVince Bridgers 	    (dequeue_tx(priv))) {
208f64f8808SVince Bridgers 		ready = 1;
209f64f8808SVince Bridgers 	}
210f64f8808SVince Bridgers 
211f64f8808SVince Bridgers 	return ready;
212f64f8808SVince Bridgers }
213f64f8808SVince Bridgers 
sgdma_start_rxdma(struct altera_tse_private * priv)21437c0ffaaSVince Bridgers void sgdma_start_rxdma(struct altera_tse_private *priv)
21537c0ffaaSVince Bridgers {
21637c0ffaaSVince Bridgers 	sgdma_async_read(priv);
21737c0ffaaSVince Bridgers }
21837c0ffaaSVince Bridgers 
sgdma_add_rx_desc(struct altera_tse_private * priv,struct tse_buffer * rxbuffer)21937c0ffaaSVince Bridgers void sgdma_add_rx_desc(struct altera_tse_private *priv,
220f64f8808SVince Bridgers 		       struct tse_buffer *rxbuffer)
221f64f8808SVince Bridgers {
222f64f8808SVince Bridgers 	queue_rx(priv, rxbuffer);
223f64f8808SVince Bridgers }
224f64f8808SVince Bridgers 
225f64f8808SVince Bridgers /* status is returned on upper 16 bits,
226f64f8808SVince Bridgers  * length is returned in lower 16 bits
227f64f8808SVince Bridgers  */
sgdma_rx_status(struct altera_tse_private * priv)228f64f8808SVince Bridgers u32 sgdma_rx_status(struct altera_tse_private *priv)
229f64f8808SVince Bridgers {
23089830580SVince Bridgers 	struct sgdma_descrip __iomem *base =
23189830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->rx_dma_desc;
23289830580SVince Bridgers 	struct sgdma_descrip __iomem *desc = NULL;
233f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
23489830580SVince Bridgers 	unsigned int rxstatus = 0;
235f64f8808SVince Bridgers 
23689830580SVince Bridgers 	u32 sts = csrrd32(priv->rx_dma_csr, sgdma_csroffs(status));
237f64f8808SVince Bridgers 
238f64f8808SVince Bridgers 	desc = &base[0];
23937c0ffaaSVince Bridgers 	if (sts & SGDMA_STSREG_EOP) {
24089830580SVince Bridgers 		unsigned int pktlength = 0;
24189830580SVince Bridgers 		unsigned int pktstatus = 0;
24237c0ffaaSVince Bridgers 		dma_sync_single_for_cpu(priv->device,
24337c0ffaaSVince Bridgers 					priv->rxdescphys,
244c3ffe0caSTobias Klauser 					SGDMA_DESC_LEN,
24537c0ffaaSVince Bridgers 					DMA_FROM_DEVICE);
24637c0ffaaSVince Bridgers 
24789830580SVince Bridgers 		pktlength = csrrd16(desc, sgdma_descroffs(bytes_xferred));
24889830580SVince Bridgers 		pktstatus = csrrd8(desc, sgdma_descroffs(status));
24989830580SVince Bridgers 		rxstatus = pktstatus & ~SGDMA_STATUS_EOP;
250f64f8808SVince Bridgers 		rxstatus = rxstatus << 16;
251f64f8808SVince Bridgers 		rxstatus |= (pktlength & 0xffff);
252f64f8808SVince Bridgers 
25337c0ffaaSVince Bridgers 		if (rxstatus) {
25489830580SVince Bridgers 			csrwr8(0, desc, sgdma_descroffs(status));
255f64f8808SVince Bridgers 
256f64f8808SVince Bridgers 			rxbuffer = dequeue_rx(priv);
257f64f8808SVince Bridgers 			if (rxbuffer == NULL)
25837c0ffaaSVince Bridgers 				netdev_info(priv->dev,
259f64f8808SVince Bridgers 					    "sgdma rx and rx queue empty!\n");
260f64f8808SVince Bridgers 
26137c0ffaaSVince Bridgers 			/* Clear control */
26289830580SVince Bridgers 			csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
26337c0ffaaSVince Bridgers 			/* clear status */
26489830580SVince Bridgers 			csrwr32(0xf, priv->rx_dma_csr, sgdma_csroffs(status));
26537c0ffaaSVince Bridgers 
266f64f8808SVince Bridgers 			/* kick the rx sgdma after reaping this descriptor */
26789830580SVince Bridgers 			sgdma_async_read(priv);
26837c0ffaaSVince Bridgers 
26937c0ffaaSVince Bridgers 		} else {
27037c0ffaaSVince Bridgers 			/* If the SGDMA indicated an end of packet on recv,
27137c0ffaaSVince Bridgers 			 * then it's expected that the rxstatus from the
27237c0ffaaSVince Bridgers 			 * descriptor is non-zero - meaning a valid packet
27337c0ffaaSVince Bridgers 			 * with a nonzero length, or an error has been
27437c0ffaaSVince Bridgers 			 * indicated. if not, then all we can do is signal
27537c0ffaaSVince Bridgers 			 * an error and return no packet received. Most likely
27637c0ffaaSVince Bridgers 			 * there is a system design error, or an error in the
27737c0ffaaSVince Bridgers 			 * underlying kernel (cache or cache management problem)
27837c0ffaaSVince Bridgers 			 */
27937c0ffaaSVince Bridgers 			netdev_err(priv->dev,
28037c0ffaaSVince Bridgers 				   "SGDMA RX Error Info: %x, %x, %x\n",
28189830580SVince Bridgers 				   sts, csrrd8(desc, sgdma_descroffs(status)),
28289830580SVince Bridgers 				   rxstatus);
28337c0ffaaSVince Bridgers 		}
28437c0ffaaSVince Bridgers 	} else if (sts == 0) {
28589830580SVince Bridgers 		sgdma_async_read(priv);
286f64f8808SVince Bridgers 	}
287f64f8808SVince Bridgers 
288f64f8808SVince Bridgers 	return rxstatus;
289f64f8808SVince Bridgers }
290f64f8808SVince Bridgers 
291f64f8808SVince Bridgers 
292f64f8808SVince Bridgers /* Private functions */
sgdma_setup_descrip(struct sgdma_descrip __iomem * desc,struct sgdma_descrip __iomem * ndesc,dma_addr_t ndesc_phys,dma_addr_t raddr,dma_addr_t waddr,u16 length,int generate_eop,int rfixed,int wfixed)29389830580SVince Bridgers static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
29489830580SVince Bridgers 				struct sgdma_descrip __iomem *ndesc,
295f64f8808SVince Bridgers 				dma_addr_t ndesc_phys,
296f64f8808SVince Bridgers 				dma_addr_t raddr,
297f64f8808SVince Bridgers 				dma_addr_t waddr,
298f64f8808SVince Bridgers 				u16 length,
299f64f8808SVince Bridgers 				int generate_eop,
300f64f8808SVince Bridgers 				int rfixed,
301f64f8808SVince Bridgers 				int wfixed)
302f64f8808SVince Bridgers {
303f64f8808SVince Bridgers 	/* Clear the next descriptor as not owned by hardware */
304f64f8808SVince Bridgers 
30589830580SVince Bridgers 	u32 ctrl = csrrd8(ndesc, sgdma_descroffs(control));
30689830580SVince Bridgers 	ctrl &= ~SGDMA_CONTROL_HW_OWNED;
30789830580SVince Bridgers 	csrwr8(ctrl, ndesc, sgdma_descroffs(control));
30889830580SVince Bridgers 
309f64f8808SVince Bridgers 	ctrl = SGDMA_CONTROL_HW_OWNED;
310f64f8808SVince Bridgers 	ctrl |= generate_eop;
311f64f8808SVince Bridgers 	ctrl |= rfixed;
312f64f8808SVince Bridgers 	ctrl |= wfixed;
313f64f8808SVince Bridgers 
314f64f8808SVince Bridgers 	/* Channel is implicitly zero, initialized to 0 by default */
31589830580SVince Bridgers 	csrwr32(lower_32_bits(raddr), desc, sgdma_descroffs(raddr));
31689830580SVince Bridgers 	csrwr32(lower_32_bits(waddr), desc, sgdma_descroffs(waddr));
317f64f8808SVince Bridgers 
31889830580SVince Bridgers 	csrwr32(0, desc, sgdma_descroffs(pad1));
31989830580SVince Bridgers 	csrwr32(0, desc, sgdma_descroffs(pad2));
32089830580SVince Bridgers 	csrwr32(lower_32_bits(ndesc_phys), desc, sgdma_descroffs(next));
32189830580SVince Bridgers 
32289830580SVince Bridgers 	csrwr8(ctrl, desc, sgdma_descroffs(control));
32389830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(status));
32489830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(wburst));
32589830580SVince Bridgers 	csrwr8(0, desc, sgdma_descroffs(rburst));
32689830580SVince Bridgers 	csrwr16(length, desc, sgdma_descroffs(bytes));
32789830580SVince Bridgers 	csrwr16(0, desc, sgdma_descroffs(bytes_xferred));
328f64f8808SVince Bridgers }
329f64f8808SVince Bridgers 
330f64f8808SVince Bridgers /* If hardware is busy, don't restart async read.
331f64f8808SVince Bridgers  * if status register is 0 - meaning initial state, restart async read,
332f64f8808SVince Bridgers  * probably for the first time when populating a receive buffer.
333f64f8808SVince Bridgers  * If read status indicate not busy and a status, restart the async
334f64f8808SVince Bridgers  * DMA read.
335f64f8808SVince Bridgers  */
sgdma_async_read(struct altera_tse_private * priv)336f64f8808SVince Bridgers static int sgdma_async_read(struct altera_tse_private *priv)
337f64f8808SVince Bridgers {
33889830580SVince Bridgers 	struct sgdma_descrip __iomem *descbase =
33989830580SVince Bridgers 		(struct sgdma_descrip __iomem *)priv->rx_dma_desc;
340f64f8808SVince Bridgers 
34189830580SVince Bridgers 	struct sgdma_descrip __iomem *cdesc = &descbase[0];
34289830580SVince Bridgers 	struct sgdma_descrip __iomem *ndesc = &descbase[1];
343f64f8808SVince Bridgers 	struct tse_buffer *rxbuffer = NULL;
344f64f8808SVince Bridgers 
345f64f8808SVince Bridgers 	if (!sgdma_rxbusy(priv)) {
346f64f8808SVince Bridgers 		rxbuffer = queue_rx_peekhead(priv);
34737c0ffaaSVince Bridgers 		if (rxbuffer == NULL) {
34837c0ffaaSVince Bridgers 			netdev_err(priv->dev, "no rx buffers available\n");
349f64f8808SVince Bridgers 			return 0;
35037c0ffaaSVince Bridgers 		}
351f64f8808SVince Bridgers 
3521b444881STobias Klauser 		sgdma_setup_descrip(cdesc,		/* current descriptor */
353f64f8808SVince Bridgers 				    ndesc,		/* next descriptor */
354f64f8808SVince Bridgers 				    sgdma_rxphysaddr(priv, ndesc),
355f64f8808SVince Bridgers 				    0,			/* read addr 0 for rx dma */
356f64f8808SVince Bridgers 				    rxbuffer->dma_addr, /* write addr for rx dma */
357f64f8808SVince Bridgers 				    0,			/* read 'til EOP */
358f64f8808SVince Bridgers 				    0,			/* EOP: NA for rx dma */
359f64f8808SVince Bridgers 				    0,			/* read fixed: NA for rx dma */
360f64f8808SVince Bridgers 				    0);			/* SOP: NA for rx DMA */
361f64f8808SVince Bridgers 
362f64f8808SVince Bridgers 		dma_sync_single_for_device(priv->device,
363f64f8808SVince Bridgers 					   priv->rxdescphys,
364c3ffe0caSTobias Klauser 					   SGDMA_DESC_LEN,
36537c0ffaaSVince Bridgers 					   DMA_TO_DEVICE);
366f64f8808SVince Bridgers 
36789830580SVince Bridgers 		csrwr32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
36889830580SVince Bridgers 			priv->rx_dma_csr,
36989830580SVince Bridgers 			sgdma_csroffs(next_descrip));
370f64f8808SVince Bridgers 
37189830580SVince Bridgers 		csrwr32((priv->rxctrlreg | SGDMA_CTRLREG_START),
37289830580SVince Bridgers 			priv->rx_dma_csr,
37389830580SVince Bridgers 			sgdma_csroffs(control));
374f64f8808SVince Bridgers 
375f64f8808SVince Bridgers 		return 1;
376f64f8808SVince Bridgers 	}
377f64f8808SVince Bridgers 
378f64f8808SVince Bridgers 	return 0;
379f64f8808SVince Bridgers }
380f64f8808SVince Bridgers 
sgdma_async_write(struct altera_tse_private * priv,struct sgdma_descrip __iomem * desc)381f64f8808SVince Bridgers static int sgdma_async_write(struct altera_tse_private *priv,
38289830580SVince Bridgers 			     struct sgdma_descrip __iomem *desc)
383f64f8808SVince Bridgers {
384f64f8808SVince Bridgers 	if (sgdma_txbusy(priv))
385f64f8808SVince Bridgers 		return 0;
386f64f8808SVince Bridgers 
387f64f8808SVince Bridgers 	/* clear control and status */
38889830580SVince Bridgers 	csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
38989830580SVince Bridgers 	csrwr32(0x1f, priv->tx_dma_csr, sgdma_csroffs(status));
390f64f8808SVince Bridgers 
391f64f8808SVince Bridgers 	dma_sync_single_for_device(priv->device, priv->txdescphys,
392c3ffe0caSTobias Klauser 				   SGDMA_DESC_LEN, DMA_TO_DEVICE);
393f64f8808SVince Bridgers 
39489830580SVince Bridgers 	csrwr32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
39589830580SVince Bridgers 		priv->tx_dma_csr,
39689830580SVince Bridgers 		sgdma_csroffs(next_descrip));
397f64f8808SVince Bridgers 
39889830580SVince Bridgers 	csrwr32((priv->txctrlreg | SGDMA_CTRLREG_START),
39989830580SVince Bridgers 		priv->tx_dma_csr,
40089830580SVince Bridgers 		sgdma_csroffs(control));
401f64f8808SVince Bridgers 
402f64f8808SVince Bridgers 	return 1;
403f64f8808SVince Bridgers }
404f64f8808SVince Bridgers 
405f64f8808SVince Bridgers static dma_addr_t
sgdma_txphysaddr(struct altera_tse_private * priv,struct sgdma_descrip __iomem * desc)406f64f8808SVince Bridgers sgdma_txphysaddr(struct altera_tse_private *priv,
40789830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc)
408f64f8808SVince Bridgers {
409f64f8808SVince Bridgers 	dma_addr_t paddr = priv->txdescmem_busaddr;
410a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->tx_dma_desc;
411a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
412f64f8808SVince Bridgers }
413f64f8808SVince Bridgers 
414f64f8808SVince Bridgers static dma_addr_t
sgdma_rxphysaddr(struct altera_tse_private * priv,struct sgdma_descrip __iomem * desc)415f64f8808SVince Bridgers sgdma_rxphysaddr(struct altera_tse_private *priv,
41689830580SVince Bridgers 		 struct sgdma_descrip __iomem *desc)
417f64f8808SVince Bridgers {
418f64f8808SVince Bridgers 	dma_addr_t paddr = priv->rxdescmem_busaddr;
419a804ad0eSVince Bridgers 	uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->rx_dma_desc;
420a804ad0eSVince Bridgers 	return (dma_addr_t)((uintptr_t)paddr + offs);
421f64f8808SVince Bridgers }
422f64f8808SVince Bridgers 
423f64f8808SVince Bridgers #define list_remove_head(list, entry, type, member)			\
424f64f8808SVince Bridgers 	do {								\
425f64f8808SVince Bridgers 		entry = NULL;						\
426f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
427f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
428f64f8808SVince Bridgers 			list_del_init(&entry->member);			\
429f64f8808SVince Bridgers 		}							\
430f64f8808SVince Bridgers 	} while (0)
431f64f8808SVince Bridgers 
432f64f8808SVince Bridgers #define list_peek_head(list, entry, type, member)			\
433f64f8808SVince Bridgers 	do {								\
434f64f8808SVince Bridgers 		entry = NULL;						\
435f64f8808SVince Bridgers 		if (!list_empty(list)) {				\
436f64f8808SVince Bridgers 			entry = list_entry((list)->next, type, member);	\
437f64f8808SVince Bridgers 		}							\
438f64f8808SVince Bridgers 	} while (0)
439f64f8808SVince Bridgers 
440f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a tx buffer list.
441f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
442f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
443f64f8808SVince Bridgers  */
444f64f8808SVince Bridgers static void
queue_tx(struct altera_tse_private * priv,struct tse_buffer * buffer)445f64f8808SVince Bridgers queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer)
446f64f8808SVince Bridgers {
447f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->txlisthd);
448f64f8808SVince Bridgers }
449f64f8808SVince Bridgers 
450f64f8808SVince Bridgers 
451f64f8808SVince Bridgers /* adds a tse_buffer to the tail of a rx buffer list
452f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
453f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
454f64f8808SVince Bridgers  */
455f64f8808SVince Bridgers static void
queue_rx(struct altera_tse_private * priv,struct tse_buffer * buffer)456f64f8808SVince Bridgers queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer)
457f64f8808SVince Bridgers {
458f64f8808SVince Bridgers 	list_add_tail(&buffer->lh, &priv->rxlisthd);
459f64f8808SVince Bridgers }
460f64f8808SVince Bridgers 
461f64f8808SVince Bridgers /* dequeues a tse_buffer from the transmit buffer list, otherwise
462f64f8808SVince Bridgers  * returns NULL if empty.
463f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
464f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
465f64f8808SVince Bridgers  */
466f64f8808SVince Bridgers static struct tse_buffer *
dequeue_tx(struct altera_tse_private * priv)467f64f8808SVince Bridgers dequeue_tx(struct altera_tse_private *priv)
468f64f8808SVince Bridgers {
469f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
470f64f8808SVince Bridgers 	list_remove_head(&priv->txlisthd, buffer, struct tse_buffer, lh);
471f64f8808SVince Bridgers 	return buffer;
472f64f8808SVince Bridgers }
473f64f8808SVince Bridgers 
474f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
475f64f8808SVince Bridgers  * returns NULL if empty
476f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
477f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list.
478f64f8808SVince Bridgers  */
479f64f8808SVince Bridgers static struct tse_buffer *
dequeue_rx(struct altera_tse_private * priv)480f64f8808SVince Bridgers dequeue_rx(struct altera_tse_private *priv)
481f64f8808SVince Bridgers {
482f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
483f64f8808SVince Bridgers 	list_remove_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
484f64f8808SVince Bridgers 	return buffer;
485f64f8808SVince Bridgers }
486f64f8808SVince Bridgers 
487f64f8808SVince Bridgers /* dequeues a tse_buffer from the receive buffer list, otherwise
488f64f8808SVince Bridgers  * returns NULL if empty
489f64f8808SVince Bridgers  * assumes the caller is managing and holding a mutual exclusion
490f64f8808SVince Bridgers  * primitive to avoid simultaneous pushes/pops to the list while the
491f64f8808SVince Bridgers  * head is being examined.
492f64f8808SVince Bridgers  */
493f64f8808SVince Bridgers static struct tse_buffer *
queue_rx_peekhead(struct altera_tse_private * priv)494f64f8808SVince Bridgers queue_rx_peekhead(struct altera_tse_private *priv)
495f64f8808SVince Bridgers {
496f64f8808SVince Bridgers 	struct tse_buffer *buffer = NULL;
497f64f8808SVince Bridgers 	list_peek_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
498f64f8808SVince Bridgers 	return buffer;
499f64f8808SVince Bridgers }
500f64f8808SVince Bridgers 
501f64f8808SVince Bridgers /* check and return rx sgdma status without polling
502f64f8808SVince Bridgers  */
sgdma_rxbusy(struct altera_tse_private * priv)503f64f8808SVince Bridgers static int sgdma_rxbusy(struct altera_tse_private *priv)
504f64f8808SVince Bridgers {
50589830580SVince Bridgers 	return csrrd32(priv->rx_dma_csr, sgdma_csroffs(status))
50689830580SVince Bridgers 		       & SGDMA_STSREG_BUSY;
507f64f8808SVince Bridgers }
508f64f8808SVince Bridgers 
509f64f8808SVince Bridgers /* waits for the tx sgdma to finish it's current operation, returns 0
510f64f8808SVince Bridgers  * when it transitions to nonbusy, returns 1 if the operation times out
511f64f8808SVince Bridgers  */
sgdma_txbusy(struct altera_tse_private * priv)512f64f8808SVince Bridgers static int sgdma_txbusy(struct altera_tse_private *priv)
513f64f8808SVince Bridgers {
514f64f8808SVince Bridgers 	int delay = 0;
515f64f8808SVince Bridgers 
516*a5e516d0STom Rix 	/* if DMA is busy, wait for current transaction to finish */
51789830580SVince Bridgers 	while ((csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
51889830580SVince Bridgers 		& SGDMA_STSREG_BUSY) && (delay++ < 100))
519f64f8808SVince Bridgers 		udelay(1);
520f64f8808SVince Bridgers 
52189830580SVince Bridgers 	if (csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
52289830580SVince Bridgers 	    & SGDMA_STSREG_BUSY) {
523f64f8808SVince Bridgers 		netdev_err(priv->dev, "timeout waiting for tx dma\n");
524f64f8808SVince Bridgers 		return 1;
525f64f8808SVince Bridgers 	}
526f64f8808SVince Bridgers 	return 0;
527f64f8808SVince Bridgers }
528