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