Azure: Add 'tools-only' build for macOS X hosts
[oweals/u-boot.git] / drivers / net / xilinx_axi_emac.c
index 70a2e95a8ec179cbbf1e597a39b89bb3d2dc33c0..d0683db80d88413ea95c765a9fb8b3fe613edb76 100644 (file)
@@ -1,20 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2011 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2011 PetaLogix
  * Copyright (C) 2010 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <config.h>
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
+#include <log.h>
 #include <net.h>
 #include <malloc.h>
 #include <asm/io.h>
 #include <phy.h>
 #include <miiphy.h>
 #include <wait_bit.h>
+#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -78,9 +80,10 @@ static u8 rxframe[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN)));
 struct axidma_reg {
        u32 control; /* DMACR */
        u32 status; /* DMASR */
-       u32 current; /* CURDESC */
-       u32 reserved;
-       u32 tail; /* TAILDESC */
+       u32 current; /* CURDESC low 32 bit */
+       u32 current_hi; /* CURDESC high 32 bit */
+       u32 tail; /* TAILDESC low 32 bit */
+       u32 tail_hi; /* TAILDESC high 32 bit */
 };
 
 /* Private driver structures */
@@ -93,6 +96,7 @@ struct axidma_priv {
        struct phy_device *phydev;
        struct mii_dev *bus;
        u8 eth_hasnobuf;
+       int phy_of_handle;
 };
 
 /* BD descriptors */
@@ -168,6 +172,22 @@ static inline int mdio_wait(struct axi_regs *regs)
        return 0;
 }
 
+/**
+ * axienet_dma_write - Memory mapped Axi DMA register Buffer Descriptor write.
+ * @bd:                pointer to BD descriptor structure
+ * @desc:      Address offset of DMA descriptors
+ *
+ * This function writes the value into the corresponding Axi DMA register.
+ */
+static inline void axienet_dma_write(struct axidma_bd *bd, u32 *desc)
+{
+#if defined(CONFIG_PHYS_64BIT)
+       writeq(bd, desc);
+#else
+       writel((u32)bd, desc);
+#endif
+}
+
 static u32 phyread(struct axidma_priv *priv, u32 phyaddress, u32 registernum,
                   u16 *val)
 {
@@ -260,6 +280,8 @@ static int axiemac_phy_init(struct udevice *dev)
        phydev->supported &= supported;
        phydev->advertising = phydev->supported;
        priv->phydev = phydev;
+       if (priv->phy_of_handle)
+               priv->phydev->node = offset_to_ofnode(priv->phy_of_handle);
        phy_config(phydev);
 
        return 0;
@@ -465,7 +487,7 @@ static int axiemac_start(struct udevice *dev)
        writel(temp, &priv->dmarx->control);
 
        /* Start DMA RX channel. Now it's ready to receive data.*/
-       writel((u32)&rx_bd, &priv->dmarx->current);
+       axienet_dma_write(&rx_bd, &priv->dmarx->current);
 
        /* Setup the BD. */
        memset(&rx_bd, 0, sizeof(rx_bd));
@@ -485,7 +507,7 @@ static int axiemac_start(struct udevice *dev)
        writel(temp, &priv->dmarx->control);
 
        /* Rx BD is ready - start */
-       writel((u32)&rx_bd, &priv->dmarx->tail);
+       axienet_dma_write(&rx_bd, &priv->dmarx->tail);
 
        /* Enable TX */
        writel(XAE_TC_TX_MASK, &regs->tc);
@@ -527,7 +549,7 @@ static int axiemac_send(struct udevice *dev, void *ptr, int len)
 
        if (readl(&priv->dmatx->status) & XAXIDMA_HALTED_MASK) {
                u32 temp;
-               writel((u32)&tx_bd, &priv->dmatx->current);
+               axienet_dma_write(&tx_bd, &priv->dmatx->current);
                /* Start the hardware */
                temp = readl(&priv->dmatx->control);
                temp |= XAXIDMA_CR_RUNSTOP_MASK;
@@ -535,7 +557,7 @@ static int axiemac_send(struct udevice *dev, void *ptr, int len)
        }
 
        /* Start transfer */
-       writel((u32)&tx_bd, &priv->dmatx->tail);
+       axienet_dma_write(&tx_bd, &priv->dmatx->tail);
 
        /* Wait for transmission to complete */
        debug("axiemac: Waiting for tx to be done\n");
@@ -626,7 +648,7 @@ static int axiemac_free_pkt(struct udevice *dev, uchar *packet, int length)
        flush_cache((u32)&rxframe, sizeof(rxframe));
 
        /* Rx BD is ready - start again */
-       writel((u32)&rx_bd, &priv->dmarx->tail);
+       axienet_dma_write(&rx_bd, &priv->dmarx->tail);
 
        debug("axiemac: RX completed, framelength = %d\n", length);
 
@@ -720,8 +742,10 @@ static int axi_emac_ofdata_to_platdata(struct udevice *dev)
        priv->phyaddr = -1;
 
        offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
-       if (offset > 0)
+       if (offset > 0) {
                priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
+               priv->phy_of_handle = offset;
+       }
 
        phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
        if (phy_mode)