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