]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/designware.c
sunxi-common.h: Remove dead #ifdef CONFIG_CMD_NET code block
[u-boot] / drivers / net / designware.c
index 44c1e350ced0da662cb2984062b88c023402e5a8..7186e3b491ecabd6128720a6284a1ef42d4b93c0 100644 (file)
@@ -119,6 +119,11 @@ static void tx_descs_init(struct eth_device *dev)
        /* Correcting the last pointer of the chain */
        desc_p->dmamac_next = &desc_table_p[0];
 
+       /* Flush all Tx buffer descriptors at once */
+       flush_dcache_range((unsigned int)priv->tx_mac_descrtable,
+                          (unsigned int)priv->tx_mac_descrtable +
+                          sizeof(priv->tx_mac_descrtable));
+
        writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
        priv->tx_currdescnum = 0;
 }
@@ -132,6 +137,15 @@ static void rx_descs_init(struct eth_device *dev)
        struct dmamacdescr *desc_p;
        u32 idx;
 
+       /* Before passing buffers to GMAC we need to make sure zeros
+        * written there right after "priv" structure allocation were
+        * flushed into RAM.
+        * Otherwise there's a chance to get some of them flushed in RAM when
+        * GMAC is already pushing data to RAM via DMA. This way incoming from
+        * GMAC data will be corrupted. */
+       flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs +
+                          RX_TOTAL_BUFSIZE);
+
        for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
                desc_p = &desc_table_p[idx];
                desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
@@ -147,6 +161,11 @@ static void rx_descs_init(struct eth_device *dev)
        /* Correcting the last pointer of the chain */
        desc_p->dmamac_next = &desc_table_p[0];
 
+       /* Flush all Rx buffer descriptors at once */
+       flush_dcache_range((unsigned int)priv->rx_mac_descrtable,
+                          (unsigned int)priv->rx_mac_descrtable +
+                          sizeof(priv->rx_mac_descrtable));
+
        writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
        priv->rx_currdescnum = 0;
 }
@@ -230,7 +249,7 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
        rx_descs_init(dev);
        tx_descs_init(dev);
 
-       writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode);
+       writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode);
 
        writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD,
               &dma_p->opmode);
@@ -261,6 +280,19 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
        u32 desc_num = priv->tx_currdescnum;
        struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
 
+       /*
+        * Strictly we only need to invalidate the "txrx_status" field
+        * for the following check, but on some platforms we cannot
+        * invalidate only 4 bytes, so roundup to
+        * ARCH_DMA_MINALIGN. This is safe because the individual
+        * descriptors in the array are each aligned to
+        * ARCH_DMA_MINALIGN.
+        */
+       invalidate_dcache_range(
+               (unsigned long)desc_p,
+               (unsigned long)desc_p +
+               roundup(sizeof(desc_p->txrx_status), ARCH_DMA_MINALIGN));
+
        /* Check if the descriptor is owned by CPU */
        if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
                printf("CPU not owner of tx frame\n");
@@ -269,6 +301,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
 
        memcpy((void *)desc_p->dmamac_addr, packet, length);
 
+       /* Flush data to be sent */
+       flush_dcache_range((unsigned long)desc_p->dmamac_addr,
+                          (unsigned long)desc_p->dmamac_addr + length);
+
 #if defined(CONFIG_DW_ALTDESCRIPTOR)
        desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
        desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
@@ -284,6 +320,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
        desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
 #endif
 
+       /* Flush modified buffer descriptor */
+       flush_dcache_range((unsigned long)desc_p,
+                          (unsigned long)desc_p + sizeof(struct dmamacdescr));
+
        /* Test the wrap-around condition. */
        if (++desc_num >= CONFIG_TX_DESCR_NUM)
                desc_num = 0;
@@ -299,18 +339,28 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
 static int dw_eth_recv(struct eth_device *dev)
 {
        struct dw_eth_dev *priv = dev->priv;
-       u32 desc_num = priv->rx_currdescnum;
+       u32 status, desc_num = priv->rx_currdescnum;
        struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
-
-       u32 status = desc_p->txrx_status;
        int length = 0;
 
+       /* Invalidate entire buffer descriptor */
+       invalidate_dcache_range((unsigned long)desc_p,
+                               (unsigned long)desc_p +
+                               sizeof(struct dmamacdescr));
+
+       status = desc_p->txrx_status;
+
        /* Check  if the owner is the CPU */
        if (!(status & DESC_RXSTS_OWNBYDMA)) {
 
                length = (status & DESC_RXSTS_FRMLENMSK) >> \
                         DESC_RXSTS_FRMLENSHFT;
 
+               /* Invalidate received data */
+               invalidate_dcache_range((unsigned long)desc_p->dmamac_addr,
+                                       (unsigned long)desc_p->dmamac_addr +
+                                       roundup(length, ARCH_DMA_MINALIGN));
+
                NetReceive(desc_p->dmamac_addr, length);
 
                /*
@@ -319,6 +369,11 @@ static int dw_eth_recv(struct eth_device *dev)
                 */
                desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
 
+               /* Flush only status field - others weren't changed */
+               flush_dcache_range((unsigned long)&desc_p->txrx_status,
+                                  (unsigned long)&desc_p->txrx_status +
+                                  sizeof(desc_p->txrx_status));
+
                /* Test the wrap-around condition. */
                if (++desc_num >= CONFIG_RX_DESCR_NUM)
                        desc_num = 0;
@@ -343,6 +398,8 @@ static int dw_phy_init(struct eth_device *dev)
        if (!phydev)
                return -1;
 
+       phy_connect_dev(phydev, dev);
+
        phydev->supported &= PHY_GBIT_FEATURES;
        phydev->advertising = phydev->supported;
 
@@ -365,7 +422,8 @@ int designware_initialize(ulong base_addr, u32 interface)
         * Since the priv structure contains the descriptors which need a strict
         * buswidth alignment, memalign is used to allocate memory
         */
-       priv = (struct dw_eth_dev *) memalign(16, sizeof(struct dw_eth_dev));
+       priv = (struct dw_eth_dev *) memalign(ARCH_DMA_MINALIGN,
+                                             sizeof(struct dw_eth_dev));
        if (!priv) {
                free(dev);
                return -ENOMEM;