net: axi_emac: Move driver to DM

Move driver to DM.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 77b1869..c03f8f7 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -8,12 +8,15 @@
 
 #include <config.h>
 #include <common.h>
+#include <dm.h>
 #include <net.h>
 #include <malloc.h>
 #include <asm/io.h>
 #include <phy.h>
 #include <miiphy.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #if !defined(CONFIG_PHYLIB)
 # error AXI_ETHERNET requires PHYLIB
 #endif
@@ -87,6 +90,7 @@
 	struct axidma_reg *dmarx;
 	int phyaddr;
 	struct axi_regs *iobase;
+	phy_interface_t interface;
 	struct phy_device *phydev;
 	struct mii_dev *bus;
 };
@@ -218,11 +222,11 @@
 }
 
 /* Setting axi emac and phy to proper setting */
-static int setup_phy(struct eth_device *dev)
+static int setup_phy(struct udevice *dev)
 {
 	u16 phyreg;
 	u32 i, speed, emmc_reg, ret;
-	struct axidma_priv *priv = dev->priv;
+	struct axidma_priv *priv = dev_get_priv(dev);
 	struct axi_regs *regs = priv->iobase;
 	struct phy_device *phydev;
 
@@ -298,9 +302,9 @@
 }
 
 /* STOP DMA transfers */
-static void axiemac_halt(struct eth_device *dev)
+static void axiemac_halt(struct udevice *dev)
 {
-	struct axidma_priv *priv = dev->priv;
+	struct axidma_priv *priv = dev_get_priv(dev);
 	u32 temp;
 
 	/* Stop the hardware */
@@ -358,16 +362,18 @@
 	return 0;
 }
 
-static int axiemac_setup_mac(struct eth_device *dev)
+static int axiemac_setup_mac(struct udevice *dev)
 {
-	struct axi_regs *regs = (struct axi_regs *)dev->iobase;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct axidma_priv *priv = dev_get_priv(dev);
+	struct axi_regs *regs = priv->iobase;
 
 	/* Set the MAC address */
-	int val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
-		(dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
+	int val = ((pdata->enetaddr[3] << 24) | (pdata->enetaddr[2] << 16) |
+		(pdata->enetaddr[1] << 8) | (pdata->enetaddr[0]));
 	out_be32(&regs->uaw0, val);
 
-	val = (dev->enetaddr[5] << 8) | dev->enetaddr[4] ;
+	val = (pdata->enetaddr[5] << 8) | pdata->enetaddr[4];
 	val |= in_be32(&regs->uaw1) & ~XAE_UAW1_UNICASTADDR_MASK;
 	out_be32(&regs->uaw1, val);
 	return 0;
@@ -396,10 +402,10 @@
 		printf("%s: Timeout\n", __func__);
 }
 
-static int axiemac_init(struct eth_device *dev, bd_t * bis)
+static int axiemac_init(struct udevice *dev)
 {
-	struct axidma_priv *priv = dev->priv;
-	struct axi_regs *regs = (struct axi_regs *)dev->iobase;
+	struct axidma_priv *priv = dev_get_priv(dev);
+	struct axi_regs *regs = priv->iobase;
 	u32 temp;
 
 	debug("axiemac: Init started\n");
@@ -458,9 +464,9 @@
 	return 0;
 }
 
-static int axiemac_send(struct eth_device *dev, void *ptr, int len)
+static int axiemac_send(struct udevice *dev, void *ptr, int len)
 {
-	struct axidma_priv *priv = dev->priv;
+	struct axidma_priv *priv = dev_get_priv(dev);
 	u32 timeout;
 
 	if (len > PKTSIZE_ALIGN)
@@ -530,15 +536,15 @@
 	return 0;
 }
 
-static int axiemac_recv(struct eth_device *dev)
+static int axiemac_recv(struct udevice *dev, int flags, uchar **packetp)
 {
 	u32 length;
-	struct axidma_priv *priv = dev->priv;
+	struct axidma_priv *priv = dev_get_priv(dev);
 	u32 temp;
 
 	/* Wait for an incoming packet */
 	if (!isrxready(priv))
-		return 0;
+		return -1;
 
 	debug("axiemac: RX data ready\n");
 
@@ -578,77 +584,125 @@
 
 	debug("axiemac: RX completed, framelength = %d\n", length);
 
-	return length;
+	return 0;
 }
 
-static int axiemac_miiphy_read(const char *devname, uchar addr,
-							uchar reg, ushort *val)
+static int axiemac_miiphy_read(struct mii_dev *bus, int addr,
+			       int devad, int reg)
 {
-	struct eth_device *dev = eth_get_dev();
-	u32 ret;
+	int ret;
+	u16 value;
 
-	ret = phyread(dev->priv, addr, reg, val);
-	debug("axiemac: Read MII 0x%x, 0x%x, 0x%x\n", addr, reg, *val);
-	return ret;
+	ret = phyread(bus->priv, addr, reg, &value);
+	debug("axiemac: Read MII 0x%x, 0x%x, 0x%x, %d\n", addr, reg,
+	      value, ret);
+	return value;
 }
 
-static int axiemac_miiphy_write(const char *devname, uchar addr,
-							uchar reg, ushort val)
+static int axiemac_miiphy_write(struct mii_dev *bus, int addr, int devad,
+				int reg, u16 value)
 {
-	struct eth_device *dev = eth_get_dev();
-
-	debug("axiemac: Write MII 0x%x, 0x%x, 0x%x\n", addr, reg, val);
-	return phywrite(dev->priv, addr, reg, val);
+	debug("axiemac: Write MII 0x%x, 0x%x, 0x%x\n", addr, reg, value);
+	return phywrite(bus->priv, addr, reg, value);
 }
 
-static int axiemac_bus_reset(struct mii_dev *bus)
+static int axi_emac_probe(struct udevice *dev)
 {
-	debug("axiemac: Bus reset\n");
+	struct axidma_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->bus = mdio_alloc();
+	priv->bus->read = axiemac_miiphy_read;
+	priv->bus->write = axiemac_miiphy_write;
+	priv->bus->priv = priv;
+	strcpy(priv->bus->name, "axi_emac");
+
+	ret = mdio_register(priv->bus);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
-int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
-							unsigned long dma_addr)
+static int axi_emac_remove(struct udevice *dev)
 {
-	struct eth_device *dev;
-	struct axidma_priv *priv;
+	struct axidma_priv *priv = dev_get_priv(dev);
 
-	dev = calloc(1, sizeof(struct eth_device));
-	if (dev == NULL)
-		return -1;
+	free(priv->phydev);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
 
-	dev->priv = calloc(1, sizeof(struct axidma_priv));
-	if (dev->priv == NULL) {
-		free(dev);
-		return -1;
-	}
-	priv = dev->priv;
+	return 0;
+}
+
+static const struct eth_ops axi_emac_ops = {
+	.start			= axiemac_init,
+	.send			= axiemac_send,
+	.recv			= axiemac_recv,
+	.stop			= axiemac_halt,
+	.write_hwaddr		= axiemac_setup_mac,
+};
+
+static int axi_emac_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct axidma_priv *priv = dev_get_priv(dev);
+	int offset = 0;
+	const char *phy_mode;
 
-	sprintf(dev->name, "aximac.%lx", base_addr);
+	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	priv->iobase = (struct axi_regs *)pdata->iobase;
 
-	dev->iobase = base_addr;
-	priv->iobase = (struct axi_regs *)base_addr;
-	priv->dmatx = (struct axidma_reg *)dma_addr;
+	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+				       "axistream-connected");
+	if (offset <= 0) {
+		printf("%s: axistream is not found\n", __func__);
+		return -EINVAL;
+	}
+	priv->dmatx = (struct axidma_reg *)fdtdec_get_int(gd->fdt_blob,
+							  offset, "reg", 0);
+	if (!priv->dmatx) {
+		printf("%s: axi_dma register space not found\n", __func__);
+		return -EINVAL;
+	}
 	/* RX channel offset is 0x30 */
-	priv->dmarx = (struct axidma_reg *)(dma_addr + 0x30);
-	dev->init = axiemac_init;
-	dev->halt = axiemac_halt;
-	dev->send = axiemac_send;
-	dev->recv = axiemac_recv;
-	dev->write_hwaddr = axiemac_setup_mac;
+	priv->dmarx = (struct axidma_reg *)((u32)priv->dmatx + 0x30);
 
-#ifdef CONFIG_PHY_ADDR
-	priv->phyaddr = CONFIG_PHY_ADDR;
-#else
 	priv->phyaddr = -1;
-#endif
 
-	eth_register(dev);
+	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+				       "phy-handle");
+	if (offset > 0)
+		priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-	miiphy_register(dev->name, axiemac_miiphy_read, axiemac_miiphy_write);
-	priv->bus = miiphy_get_dev_by_name(dev->name);
-	priv->bus->reset = axiemac_bus_reset;
-#endif
-	return 1;
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+	priv->interface = pdata->phy_interface;
+
+	printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase,
+	       priv->phyaddr, phy_string_for_interface(priv->interface));
+
+	return 0;
 }
+
+static const struct udevice_id axi_emac_ids[] = {
+	{ .compatible = "xlnx,axi-ethernet-1.00.a" },
+	{ }
+};
+
+U_BOOT_DRIVER(axi_emac) = {
+	.name	= "axi_emac",
+	.id	= UCLASS_ETH,
+	.of_match = axi_emac_ids,
+	.ofdata_to_platdata = axi_emac_ofdata_to_platdata,
+	.probe	= axi_emac_probe,
+	.remove	= axi_emac_remove,
+	.ops	= &axi_emac_ops,
+	.priv_auto_alloc_size = sizeof(struct axidma_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};