net: mvgbe: convert to DM
authorChris Packham <judge.packham@gmail.com>
Mon, 9 Jul 2018 09:34:00 +0000 (21:34 +1200)
committerJoe Hershberger <joe.hershberger@ni.com>
Thu, 26 Jul 2018 19:08:21 +0000 (14:08 -0500)
Add driver model support to the mvgbe driver. As a temporary measure
both DM and non-DM uses are supported. Once all the users have been
converted the non-DM support can be dropped.

Signed-off-by: Chris Packham <judge.packham@gmail.com>
Tested-by: Michael Walle <michael@walle.cc>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/Kconfig
drivers/net/mvgbe.c
drivers/net/mvgbe.h

index 79eef2d755658d6c579ed0a5b8a42c71036ad2b0..f762b0898d71a9bf21dbda6594d2840f70faf503 100644 (file)
@@ -181,6 +181,7 @@ config FTMAC100
 config MVGBE
        bool "Marvell Orion5x/Kirkwood network interface support"
        depends on KIRKWOOD || ORION5X
+       select PHYLIB if DM_ETH
        help
          This driver supports the network interface units in the
          Marvell Orion5x and Kirkwood SoCs
index aad1d279915f7dc1988ee9790f13cc65f8df62b0..74fed7abd83772a2697f1188b36e1e306a215110 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <net.h>
 #include <malloc.h>
 #include <miiphy.h>
@@ -127,8 +128,12 @@ static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr,
 static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
                        int reg_ofs)
 {
+#ifdef CONFIG_DM_ETH
+       struct mvgbe_device *dmvgbe = bus->priv;
+#else
        struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
 
        return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs);
 }
@@ -180,8 +185,12 @@ static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr,
 static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
                         int reg_ofs, u16 data)
 {
+#ifdef CONFIG_DM_ETH
+       struct mvgbe_device *dmvgbe = bus->priv;
+#else
        struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
 
        return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data);
 }
@@ -415,11 +424,13 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
        dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
 }
 
-static int __mvgbe_init(struct mvgbe_device *dmvgbe)
+static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr,
+                       const char *name)
 {
        struct mvgbe_registers *regs = dmvgbe->regs;
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) &&  \
        !defined(CONFIG_PHYLIB) &&                       \
+       !defined(CONFIG_DM_ETH) &&                       \
        defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
        int i;
 #endif
@@ -436,7 +447,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe)
 
        set_dram_access(regs);
        port_init_mac_tables(regs);
-       port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
+       port_uc_addr_set(dmvgbe, enetaddr);
 
        /* Assign port configuration and command. */
        MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
@@ -473,31 +484,34 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
        !defined(CONFIG_PHYLIB) && \
+       !defined(CONFIG_DM_ETH) && \
        defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
        /* Wait up to 5s for the link status */
        for (i = 0; i < 5; i++) {
                u16 phyadr;
 
-               miiphy_read(dmvgbe->dev.name, MV_PHY_ADR_REQUEST,
+               miiphy_read(name, MV_PHY_ADR_REQUEST,
                                MV_PHY_ADR_REQUEST, &phyadr);
                /* Return if we get link up */
-               if (miiphy_link(dmvgbe->dev.name, phyadr))
+               if (miiphy_link(name, phyadr))
                        return 0;
                udelay(1000000);
        }
 
-       printf("No link on %s\n", dmvgbe->dev.name);
+       printf("No link on %s\n", name);
        return -1;
 #endif
        return 0;
 }
 
+#ifndef CONFIG_DM_ETH
 static int mvgbe_init(struct eth_device *dev)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 
-       return __mvgbe_init(dmvgbe);
+       return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr, dmvgbe->dev.name);
 }
+#endif
 
 static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
 {
@@ -524,6 +538,7 @@ static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
        MVGBE_REG_WR(regs->peim, 0);
 }
 
+#ifndef CONFIG_DM_ETH
 static int mvgbe_halt(struct eth_device *dev)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
@@ -532,7 +547,18 @@ static int mvgbe_halt(struct eth_device *dev)
 
        return 0;
 }
+#endif
 
+#ifdef CONFIG_DM_ETH
+static int mvgbe_write_hwaddr(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr);
+
+       return 0;
+}
+#else
 static int mvgbe_write_hwaddr(struct eth_device *dev)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
@@ -541,6 +567,7 @@ static int mvgbe_write_hwaddr(struct eth_device *dev)
        port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
        return 0;
 }
+#endif
 
 static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
                        int datasize)
@@ -597,12 +624,14 @@ static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
        return 0;
 }
 
+#ifndef CONFIG_DM_ETH
 static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 
        return __mvgbe_send(dmvgbe, dataptr, datasize);
 }
+#endif
 
 static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
 {
@@ -677,6 +706,7 @@ static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
        return rx_bytes;
 }
 
+#ifndef CONFIG_DM_ETH
 static int mvgbe_recv(struct eth_device *dev)
 {
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
@@ -691,8 +721,41 @@ static int mvgbe_recv(struct eth_device *dev)
 
        return 0;
 }
+#endif
 
-#if defined(CONFIG_PHYLIB)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH)
+#if defined(CONFIG_DM_ETH)
+static struct phy_device *__mvgbe_phy_init(struct udevice *dev,
+                                          struct mii_dev *bus,
+                                          phy_interface_t phy_interface,
+                                          int phyid)
+#else
+static struct phy_device *__mvgbe_phy_init(struct eth_device *dev,
+                                          struct mii_dev *bus,
+                                          phy_interface_t phy_interface,
+                                          int phyid)
+#endif
+{
+       struct phy_device *phydev;
+
+       /* Set phy address of the port */
+       miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST,
+                    phyid);
+
+       phydev = phy_connect(bus, phyid, dev, phy_interface);
+       if (!phydev) {
+               printf("phy_connect failed\n");
+               return NULL;
+       }
+
+       phy_config(phydev);
+       phy_startup(phydev);
+
+       return phydev;
+}
+#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */
+
+#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH)
 int mvgbe_phylib_init(struct eth_device *dev, int phyid)
 {
        struct mii_dev *bus;
@@ -715,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid)
                return -ENOMEM;
        }
 
-       /* Set phy address of the port */
-       smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
-
-       phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
-       if (!phydev) {
-               printf("phy_connect failed\n");
+       phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid);
+       if (!phydev)
                return -ENODEV;
-       }
-
-       phy_config(phydev);
-       phy_startup(phydev);
 
        return 0;
 }
 #endif
 
+static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe)
+{
+       dmvgbe->p_rxdesc = memalign(PKTALIGN,
+                                   MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1);
+       if (!dmvgbe->p_rxdesc)
+               goto error1;
+
+       dmvgbe->p_rxbuf = memalign(PKTALIGN,
+                                  RINGSZ * PKTSIZE_ALIGN + 1);
+       if (!dmvgbe->p_rxbuf)
+               goto error2;
+
+       dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
+       if (!dmvgbe->p_aligned_txbuf)
+               goto error3;
+
+       dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
+       if (!dmvgbe->p_txdesc)
+               goto error4;
+
+       return 0;
+
+error4:
+       free(dmvgbe->p_aligned_txbuf);
+error3:
+       free(dmvgbe->p_rxbuf);
+error2:
+       free(dmvgbe->p_rxdesc);
+error1:
+       return -ENOMEM;
+}
+
+#ifndef CONFIG_DM_ETH
 int mvgbe_initialize(bd_t *bis)
 {
        struct mvgbe_device *dmvgbe;
        struct eth_device *dev;
        int devnum;
+       int ret;
        u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
 
        for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
@@ -744,45 +833,16 @@ int mvgbe_initialize(bd_t *bis)
                        continue;
 
                dmvgbe = malloc(sizeof(struct mvgbe_device));
-
                if (!dmvgbe)
-                       goto error1;
+                       return -ENOMEM;
 
                memset(dmvgbe, 0, sizeof(struct mvgbe_device));
-
-               dmvgbe->p_rxdesc =
-                       (struct mvgbe_rxdesc *)memalign(PKTALIGN,
-                       MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
-
-               if (!dmvgbe->p_rxdesc)
-                       goto error2;
-
-               dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
-                       RINGSZ*PKTSIZE_ALIGN + 1);
-
-               if (!dmvgbe->p_rxbuf)
-                       goto error3;
-
-               dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
-
-               if (!dmvgbe->p_aligned_txbuf)
-                       goto error4;
-
-               dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
-                       PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
-
-               if (!dmvgbe->p_txdesc) {
-                       free(dmvgbe->p_aligned_txbuf);
-error4:
-                       free(dmvgbe->p_rxbuf);
-error3:
-                       free(dmvgbe->p_rxdesc);
-error2:
-                       free(dmvgbe);
-error1:
+               ret = mvgbe_alloc_buffers(dmvgbe);
+               if (ret) {
                        printf("Err.. %s Failed to allocate memory\n",
                                __func__);
-                       return -1;
+                       free(dmvgbe);
+                       return ret;
                }
 
                dev = &dmvgbe->dev;
@@ -834,3 +894,154 @@ error1:
        }
        return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe)
+{
+       return dmvgbe->phyaddr > PHY_MAX_ADDR;
+}
+
+static int mvgbe_start(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+       int ret;
+
+       ret = __mvgbe_init(dmvgbe, pdata->enetaddr, dev->name);
+       if (ret)
+               return ret;
+
+       if (!mvgbe_port_is_fixed_link(dmvgbe)) {
+               dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus,
+                                                 dmvgbe->phy_interface,
+                                                 dmvgbe->phyaddr);
+               if (!dmvgbe->phydev)
+                       return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int mvgbe_send(struct udevice *dev, void *packet, int length)
+{
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+       return __mvgbe_send(dmvgbe, packet, length);
+}
+
+static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+       return __mvgbe_recv(dmvgbe, packetp);
+}
+
+static void mvgbe_stop(struct udevice *dev)
+{
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+       __mvgbe_halt(dmvgbe);
+}
+
+static int mvgbe_probe(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+       struct mii_dev *bus;
+       int ret;
+
+       ret = mvgbe_alloc_buffers(dmvgbe);
+       if (ret)
+               return ret;
+
+       dmvgbe->regs = (void __iomem *)pdata->iobase;
+
+       bus  = mdio_alloc();
+       if (!bus) {
+               printf("Failed to allocate MDIO bus\n");
+               return -ENOMEM;
+       }
+
+       bus->read = smi_reg_read;
+       bus->write = smi_reg_write;
+       snprintf(bus->name, sizeof(bus->name), dev->name);
+       bus->priv = dmvgbe;
+       dmvgbe->bus = bus;
+
+       ret = mdio_register(bus);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static const struct eth_ops mvgbe_ops = {
+       .start          = mvgbe_start,
+       .send           = mvgbe_send,
+       .recv           = mvgbe_recv,
+       .stop           = mvgbe_stop,
+       .write_hwaddr   = mvgbe_write_hwaddr,
+};
+
+static int mvgbe_ofdata_to_platdata(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+       void *blob = (void *)gd->fdt_blob;
+       int node = dev_of_offset(dev);
+       const char *phy_mode;
+       int fl_node;
+       int pnode;
+       unsigned long addr;
+
+       pdata->iobase = devfdt_get_addr(dev);
+       pdata->phy_interface = -1;
+
+       pnode = fdt_node_offset_by_compatible(blob, node,
+                                             "marvell,kirkwood-eth-port");
+
+       /* Get phy-mode / phy_interface from DT */
+       phy_mode = fdt_getprop(gd->fdt_blob, pnode, "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;
+       }
+
+       dmvgbe->phy_interface = pdata->phy_interface;
+
+       /* fetch 'fixed-link' property */
+       fl_node = fdt_subnode_offset(blob, pnode, "fixed-link");
+       if (fl_node != -FDT_ERR_NOTFOUND) {
+               /* set phy_addr to invalid value for fixed link */
+               dmvgbe->phyaddr = PHY_MAX_ADDR + 1;
+               dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
+               dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0);
+       } else {
+               /* Now read phyaddr from DT */
+               addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle");
+               if (addr > 0)
+                       dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0);
+       }
+
+       return 0;
+}
+
+static const struct udevice_id mvgbe_ids[] = {
+       { .compatible = "marvell,kirkwood-eth" },
+       { }
+};
+
+U_BOOT_DRIVER(mvgbe) = {
+       .name   = "mvgbe",
+       .id     = UCLASS_ETH,
+       .of_match = mvgbe_ids,
+       .ofdata_to_platdata = mvgbe_ofdata_to_platdata,
+       .probe  = mvgbe_probe,
+       .ops    = &mvgbe_ops,
+       .priv_auto_alloc_size = sizeof(struct mvgbe_device),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+#endif /* CONFIG_DM_ETH */
index 1dc9bbea2f424ab23cece511f32abc0105045e02..44541c0a85e302fb87b4024268615d70048a789d 100644 (file)
@@ -30,7 +30,9 @@
 #define RXUQ   0 /* Used Rx queue */
 #define TXUQ   0 /* Used Rx queue */
 
+#ifndef CONFIG_DM_ETH
 #define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev)
+#endif
 #define MVGBE_REG_WR(adr, val)         writel(val, &adr)
 #define MVGBE_REG_RD(adr)              readl(&adr)
 #define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr)
@@ -479,13 +481,27 @@ struct mvgbe_txdesc {
 
 /* port device data struct */
 struct mvgbe_device {
+#ifndef CONFIG_DM_ETH
        struct eth_device dev;
+#endif
        struct mvgbe_registers *regs;
        struct mvgbe_txdesc *p_txdesc;
        struct mvgbe_rxdesc *p_rxdesc;
        struct mvgbe_rxdesc *p_rxdesc_curr;
        u8 *p_rxbuf;
        u8 *p_aligned_txbuf;
+
+#ifdef CONFIG_DM_ETH
+       phy_interface_t phy_interface;
+       unsigned int link;
+       unsigned int duplex;
+       unsigned int speed;
+
+       int init;
+       int phyaddr;
+       struct phy_device *phydev;
+       struct mii_dev *bus;
+#endif
 };
 
 #endif /* __MVGBE_H__ */