X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fftgmac100.c;h=5ccc4beda817891edf8fdc39f69711eb8b36f94a;hb=35e3fca7e3ddaa2ae1fe9bd00b22be73e60a6042;hp=dc7a80e5c77386d29c3b6bca1225de3c5590f79e;hpb=1ad98ad66e5bb8a46a186a92f180bb9592d47673;p=oweals%2Fu-boot.git diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c index dc7a80e5c7..5ccc4beda8 100644 --- a/drivers/net/ftgmac100.c +++ b/drivers/net/ftgmac100.c @@ -7,19 +7,7 @@ * (C) Copyright 2010 Andes Technology * Macpaul Lin * - * 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 @@ -27,13 +15,13 @@ #include #include #include +#include #include #include "ftgmac100.h" #define ETH_ZLEN 60 - -#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); }) +#define CFG_XBUF_SIZE 1536 /* RBSR - hw default init value is also 0x640 */ #define RBSR_DEFAULT_VALUE 0x640 @@ -42,8 +30,10 @@ #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; @@ -377,14 +367,33 @@ 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__); - ftgmac100_reset(dev); + 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); @@ -401,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 = net_rx_packets[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); @@ -470,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); + net_process_received_packet((void *)curr_des->rxdes2, rxlen); /* release buffer to DMA */ curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY; @@ -484,13 +506,11 @@ static int ftgmac100_recv(struct eth_device *dev) /* * Send a data block via Ethernet */ -static int -ftgmac100_send(struct eth_device *dev, void *packet, int length) +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__); @@ -501,8 +521,8 @@ 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; @@ -514,15 +534,6 @@ 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; @@ -551,7 +562,7 @@ int ftgmac100_initialize(bd_t *bd) memset(dev, 0, sizeof(*dev)); memset(priv, 0, sizeof(*priv)); - sprintf(dev->name, "FTGMAC100"); + strcpy(dev->name, "FTGMAC100"); dev->iobase = CONFIG_FTGMAC100_BASE; dev->init = ftgmac100_init; dev->halt = ftgmac100_halt; @@ -561,6 +572,8 @@ int ftgmac100_initialize(bd_t *bd) eth_register(dev); + ftgmac100_reset(dev); + return 1; free_dev: