]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - drivers/net/ftgmac100.c
Update from 2013.01 to 2013.07
[karo-tx-uboot.git] / drivers / net / ftgmac100.c
index 69ba57d3d006e7638b96106221966b7980389682..85193140af32d662d0f507062cfd3fe1904c23c0 100644 (file)
@@ -7,19 +7,7 @@
  * (C) Copyright 2010 Andes Technology
  * Macpaul Lin <macpaul@andestech.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <config.h>
 #include <malloc.h>
 #include <net.h>
 #include <asm/io.h>
+#include <asm/dma-mapping.h>
 #include <linux/mii.h>
 
 #include "ftgmac100.h"
 
 #define ETH_ZLEN       60
+#define CFG_XBUF_SIZE  1536
 
 /* RBSR - hw default init value is also 0x640 */
 #define RBSR_DEFAULT_VALUE     0x640
 #define PKTBUFSTX      4       /* must be power of 2 */
 
 struct ftgmac100_data {
-       struct ftgmac100_txdes txdes[PKTBUFSTX];
-       struct ftgmac100_rxdes rxdes[PKTBUFSRX];
+       ulong txdes_dma;
+       struct ftgmac100_txdes *txdes;
+       ulong rxdes_dma;
+       struct ftgmac100_rxdes *rxdes;
        int tx_index;
        int rx_index;
        int phy_addr;
@@ -375,13 +367,34 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 {
        struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
        struct ftgmac100_data *priv = dev->priv;
-       struct ftgmac100_txdes *txdes = priv->txdes;
-       struct ftgmac100_rxdes *rxdes = priv->rxdes;
+       struct ftgmac100_txdes *txdes;
+       struct ftgmac100_rxdes *rxdes;
        unsigned int maccr;
+       void *buf;
        int i;
 
        debug("%s()\n", __func__);
 
+       if (!priv->txdes) {
+               txdes = dma_alloc_coherent(
+                       sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
+               if (!txdes)
+                       panic("ftgmac100: out of memory\n");
+               memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
+               priv->txdes = txdes;
+       }
+       txdes = priv->txdes;
+
+       if (!priv->rxdes) {
+               rxdes = dma_alloc_coherent(
+                       sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
+               if (!rxdes)
+                       panic("ftgmac100: out of memory\n");
+               memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
+               priv->rxdes = rxdes;
+       }
+       rxdes = priv->rxdes;
+
        /* set the ethernet address */
        ftgmac100_set_mac_from_env(dev);
 
@@ -397,21 +410,31 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 
        for (i = 0; i < PKTBUFSTX; i++) {
                /* TXBUF_BADR */
-               txdes[i].txdes3 = 0;
+               if (!txdes[i].txdes2) {
+                       buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
+                       if (!buf)
+                               panic("ftgmac100: out of memory\n");
+                       txdes[i].txdes3 = virt_to_phys(buf);
+                       txdes[i].txdes2 = (uint)buf;
+               }
                txdes[i].txdes1 = 0;
        }
 
        for (i = 0; i < PKTBUFSRX; i++) {
                /* RXBUF_BADR */
-               rxdes[i].rxdes3 = (unsigned int)NetRxPackets[i];
+               if (!rxdes[i].rxdes2) {
+                       buf = NetRxPackets[i];
+                       rxdes[i].rxdes3 = virt_to_phys(buf);
+                       rxdes[i].rxdes2 = (uint)buf;
+               }
                rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
        }
 
        /* transmit ring */
-       writel((unsigned int)txdes, &ftgmac100->txr_badr);
+       writel(priv->txdes_dma, &ftgmac100->txr_badr);
 
        /* receive ring */
-       writel((unsigned int)rxdes, &ftgmac100->rxr_badr);
+       writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
 
        /* poll receive descriptor automatically */
        writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
@@ -466,8 +489,11 @@ static int ftgmac100_recv(struct eth_device *dev)
        debug("%s(): RX buffer %d, %x received\n",
               __func__, priv->rx_index, rxlen);
 
+       /* invalidate d-cache */
+       dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
+
        /* pass the packet up to the protocol layers. */
-       NetReceive((void *)curr_des->rxdes3, rxlen);
+       NetReceive((void *)curr_des->rxdes2, rxlen);
 
        /* release buffer to DMA */
        curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
@@ -485,7 +511,6 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
        struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
        struct ftgmac100_data *priv = dev->priv;
        struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
-       int start;
 
        if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
                debug("%s(): no TX descriptor available\n", __func__);
@@ -496,8 +521,8 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
 
        length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 
-       /* initiate a transmit sequence */
-       curr_des->txdes3 = (unsigned int)packet;        /* TXBUF_BADR */
+       memcpy((void *)curr_des->txdes2, (void *)packet, length);
+       dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
 
        /* only one descriptor on TXBUF */
        curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
@@ -509,15 +534,6 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
        /* start transmit */
        writel(1, &ftgmac100->txpd);
 
-       /* wait for transfer to succeed */
-       start = get_timer(0);
-       while (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
-               if (get_timer(0) >= 5) {
-                       debug("%s(): timed out\n", __func__);
-                       return -1;
-               }
-       }
-
        debug("%s(): packet sent\n", __func__);
 
        priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;