Merge branch 'u-boot/master' into 'u-boot-arm/master'
[oweals/u-boot.git] / drivers / net / pcnet.c
index a30a0bc9cae3f3f9e0238d79dc5076da189f985a..71a3110712defe0f97ea63e4aeac7fedca1a716d 100644 (file)
@@ -291,16 +291,6 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis)
        /* Switch pcnet to 32bit mode */
        pcnet_write_bcr(dev, 20, 2);
 
-#ifdef CONFIG_PN62
-       /* Setup LED registers */
-       val = pcnet_read_bcr(dev, 2) | 0x1000;
-       pcnet_write_bcr(dev, 2, val);   /* enable LEDPE */
-       pcnet_write_bcr(dev, 4, 0x5080);        /* 100MBit */
-       pcnet_write_bcr(dev, 5, 0x40c0);        /* LNKSE */
-       pcnet_write_bcr(dev, 6, 0x4090);        /* TX Activity */
-       pcnet_write_bcr(dev, 7, 0x4084);        /* RX Activity */
-#endif
-
        /* Set/reset autoselect bit */
        val = pcnet_read_bcr(dev, 2) & ~2;
        val |= 2;
@@ -311,6 +301,21 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis)
        val |= 0x20;
        pcnet_write_bcr(dev, 32, val);
 
+       /*
+        * Enable NOUFLO on supported controllers, with the transmit
+        * start point set to the full packet. This will cause entire
+        * packets to be buffered by the ethernet controller before
+        * transmission, eliminating underflows which are common on
+        * slower devices. Controllers which do not support NOUFLO will
+        * simply be left with a larger transmit FIFO threshold.
+        */
+       val = pcnet_read_bcr(dev, 18);
+       val |= 1 << 11;
+       pcnet_write_bcr(dev, 18, val);
+       val = pcnet_read_csr(dev, 80);
+       val |= 0x3 << 10;
+       pcnet_write_csr(dev, 80, val);
+
        /*
         * We only maintain one structure because the drivers will never
         * be used concurrently. In 32bit mode the RX and TX ring entries
@@ -364,6 +369,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis)
                                               RX_RING_LEN_BITS);
        lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
        lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);
+       flush_dcache_range((unsigned long)lp, (unsigned long)&lp->rx_buf);
 
        PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
                     lp->init_block.tlen_rlen,
@@ -407,8 +413,13 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len)
        PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len,
                     packet);
 
+       flush_dcache_range((unsigned long)packet,
+                          (unsigned long)packet + pkt_len);
+
        /* Wait for completion by testing the OWN bit */
        for (i = 1000; i > 0; i--) {
+               invalidate_dcache_range((unsigned long)entry,
+                                       (unsigned long)entry + sizeof(*entry));
                status = le16_to_cpu(entry->status);
                if ((status & 0x8000) == 0)
                        break;
@@ -427,10 +438,12 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len)
         * set the status with the "ownership" bits last.
         */
        status = 0x8300;
-       entry->length = le16_to_cpu(-pkt_len);
+       entry->length = cpu_to_le16(-pkt_len);
        entry->misc = 0x00000000;
        entry->base = PCI_TO_MEM_LE(dev, packet);
-       entry->status = le16_to_cpu(status);
+       entry->status = cpu_to_le16(status);
+       flush_dcache_range((unsigned long)entry,
+                          (unsigned long)entry + sizeof(*entry));
 
        /* Trigger an immediate send poll. */
        pcnet_write_csr(dev, 0, 0x0008);
@@ -451,6 +464,8 @@ static int pcnet_recv (struct eth_device *dev)
 
        while (1) {
                entry = &lp->rx_ring[lp->cur_rx];
+               invalidate_dcache_range((unsigned long)entry,
+                                       (unsigned long)entry + sizeof(*entry));
                /*
                 * If we own the next entry, it's a new packet. Send it up.
                 */
@@ -479,6 +494,10 @@ static int pcnet_recv (struct eth_device *dev)
                                printf("%s: Rx%d: invalid packet length %d\n",
                                       dev->name, lp->cur_rx, pkt_len);
                        } else {
+                               invalidate_dcache_range(
+                                       (unsigned long)lp->rx_buf[lp->cur_rx],
+                                       (unsigned long)lp->rx_buf[lp->cur_rx] +
+                                       pkt_len);
                                NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
                                PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n",
                                             lp->cur_rx, pkt_len,
@@ -486,6 +505,8 @@ static int pcnet_recv (struct eth_device *dev)
                        }
                }
                entry->status |= cpu_to_le16(0x8000);
+               flush_dcache_range((unsigned long)entry,
+                                  (unsigned long)entry + sizeof(*entry));
 
                if (++lp->cur_rx >= RX_RING_SIZE)
                        lp->cur_rx = 0;