net/macb: merge at91_ether driver into macb driver
authorCyrille Pitchen <cyrille.pitchen@atmel.com>
Sat, 7 Mar 2015 06:23:32 +0000 (07:23 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Mar 2015 03:31:37 +0000 (22:31 -0500)
macb and at91_ether drivers can be compiled as modules, but the at91_ether
driver use some functions and variables defined in the macb one, thus
creating a dependency on the macb driver.

Since these drivers are sharing the same logic we can easily merge
at91_ether into macb.

In order to factorize common probing logic we've added an ->init() function
to struct macb_config (the structure associated with the compatible
string), and moved macb specific init code from macb_probe to macb_init.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/Makefile
drivers/net/ethernet/cadence/at91_ether.c [deleted file]
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h

index 739bb0048ebf4091e829e50b72dccdd7a722c2ab..1ba3e3a67389d8a793fb7fbc6ed8a431586597e5 100644 (file)
@@ -20,14 +20,6 @@ config NET_CADENCE
 
 if NET_CADENCE
 
-config ARM_AT91_ETHER
-       tristate "AT91RM9200 Ethernet support"
-       depends on HAS_DMA && (ARCH_AT91 || COMPILE_TEST)
-       select MACB
-       ---help---
-         If you wish to compile a kernel for the AT91RM9200 and enable
-         ethernet support, then you should always answer Y to this.
-
 config MACB
        tristate "Cadence MACB/GEM support"
        depends on HAS_DMA
index 9068b8331ed18b52f5df76b75d5f5f9ad4125cf2..91f79b1f0505d25beb9935790f47146c555024cf 100644 (file)
@@ -2,5 +2,4 @@
 # Makefile for the Atmel network device drivers.
 #
 
-obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
 obj-$(CONFIG_MACB) += macb.o
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
deleted file mode 100644 (file)
index 7ef55f5..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) 2003 SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson 01/11/2003
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
-#include <linux/platform_data/macb.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-#include <linux/phy.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_net.h>
-
-#include "macb.h"
-
-/* 1518 rounded up */
-#define MAX_RBUFF_SZ   0x600
-/* max number of receive buffers */
-#define MAX_RX_DESCR   9
-
-/* Initialize and start the Receiver and Transmit subsystems */
-static int at91ether_start(struct net_device *dev)
-{
-       struct macb *lp = netdev_priv(dev);
-       dma_addr_t addr;
-       u32 ctl;
-       int i;
-
-       lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
-                                        (MAX_RX_DESCR *
-                                         sizeof(struct macb_dma_desc)),
-                                        &lp->rx_ring_dma, GFP_KERNEL);
-       if (!lp->rx_ring)
-               return -ENOMEM;
-
-       lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
-                                           MAX_RX_DESCR * MAX_RBUFF_SZ,
-                                           &lp->rx_buffers_dma, GFP_KERNEL);
-       if (!lp->rx_buffers) {
-               dma_free_coherent(&lp->pdev->dev,
-                                 MAX_RX_DESCR * sizeof(struct macb_dma_desc),
-                                 lp->rx_ring, lp->rx_ring_dma);
-               lp->rx_ring = NULL;
-               return -ENOMEM;
-       }
-
-       addr = lp->rx_buffers_dma;
-       for (i = 0; i < MAX_RX_DESCR; i++) {
-               lp->rx_ring[i].addr = addr;
-               lp->rx_ring[i].ctrl = 0;
-               addr += MAX_RBUFF_SZ;
-       }
-
-       /* Set the Wrap bit on the last descriptor */
-       lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
-
-       /* Reset buffer index */
-       lp->rx_tail = 0;
-
-       /* Program address of descriptor list in Rx Buffer Queue register */
-       macb_writel(lp, RBQP, lp->rx_ring_dma);
-
-       /* Enable Receive and Transmit */
-       ctl = macb_readl(lp, NCR);
-       macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
-
-       return 0;
-}
-
-/* Open the ethernet interface */
-static int at91ether_open(struct net_device *dev)
-{
-       struct macb *lp = netdev_priv(dev);
-       u32 ctl;
-       int ret;
-
-       /* Clear internal statistics */
-       ctl = macb_readl(lp, NCR);
-       macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
-
-       macb_set_hwaddr(lp);
-
-       ret = at91ether_start(dev);
-       if (ret)
-               return ret;
-
-       /* Enable MAC interrupts */
-       macb_writel(lp, IER, MACB_BIT(RCOMP)    |
-                            MACB_BIT(RXUBR)    |
-                            MACB_BIT(ISR_TUND) |
-                            MACB_BIT(ISR_RLE)  |
-                            MACB_BIT(TCOMP)    |
-                            MACB_BIT(ISR_ROVR) |
-                            MACB_BIT(HRESP));
-
-       /* schedule a link state check */
-       phy_start(lp->phy_dev);
-
-       netif_start_queue(dev);
-
-       return 0;
-}
-
-/* Close the interface */
-static int at91ether_close(struct net_device *dev)
-{
-       struct macb *lp = netdev_priv(dev);
-       u32 ctl;
-
-       /* Disable Receiver and Transmitter */
-       ctl = macb_readl(lp, NCR);
-       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
-
-       /* Disable MAC interrupts */
-       macb_writel(lp, IDR, MACB_BIT(RCOMP)    |
-                            MACB_BIT(RXUBR)    |
-                            MACB_BIT(ISR_TUND) |
-                            MACB_BIT(ISR_RLE)  |
-                            MACB_BIT(TCOMP)    |
-                            MACB_BIT(ISR_ROVR) |
-                            MACB_BIT(HRESP));
-
-       netif_stop_queue(dev);
-
-       dma_free_coherent(&lp->pdev->dev,
-                               MAX_RX_DESCR * sizeof(struct macb_dma_desc),
-                               lp->rx_ring, lp->rx_ring_dma);
-       lp->rx_ring = NULL;
-
-       dma_free_coherent(&lp->pdev->dev,
-                               MAX_RX_DESCR * MAX_RBUFF_SZ,
-                               lp->rx_buffers, lp->rx_buffers_dma);
-       lp->rx_buffers = NULL;
-
-       return 0;
-}
-
-/* Transmit packet */
-static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct macb *lp = netdev_priv(dev);
-
-       if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
-               netif_stop_queue(dev);
-
-               /* Store packet information (to free when Tx completed) */
-               lp->skb = skb;
-               lp->skb_length = skb->len;
-               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
-                                                       DMA_TO_DEVICE);
-
-               /* Set address of the data in the Transmit Address register */
-               macb_writel(lp, TAR, lp->skb_physaddr);
-               /* Set length of the packet in the Transmit Control register */
-               macb_writel(lp, TCR, skb->len);
-
-       } else {
-               netdev_err(dev, "%s called, but device is busy!\n", __func__);
-               return NETDEV_TX_BUSY;
-       }
-
-       return NETDEV_TX_OK;
-}
-
-/* Extract received frame from buffer descriptors and sent to upper layers.
- * (Called from interrupt context)
- */
-static void at91ether_rx(struct net_device *dev)
-{
-       struct macb *lp = netdev_priv(dev);
-       unsigned char *p_recv;
-       struct sk_buff *skb;
-       unsigned int pktlen;
-
-       while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
-               p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ;
-               pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
-               skb = netdev_alloc_skb(dev, pktlen + 2);
-               if (skb) {
-                       skb_reserve(skb, 2);
-                       memcpy(skb_put(skb, pktlen), p_recv, pktlen);
-
-                       skb->protocol = eth_type_trans(skb, dev);
-                       lp->stats.rx_packets++;
-                       lp->stats.rx_bytes += pktlen;
-                       netif_rx(skb);
-               } else {
-                       lp->stats.rx_dropped++;
-               }
-
-               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
-                       lp->stats.multicast++;
-
-               /* reset ownership bit */
-               lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
-
-               /* wrap after last buffer */
-               if (lp->rx_tail == MAX_RX_DESCR - 1)
-                       lp->rx_tail = 0;
-               else
-                       lp->rx_tail++;
-       }
-}
-
-/* MAC interrupt handler */
-static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       struct macb *lp = netdev_priv(dev);
-       u32 intstatus, ctl;
-
-       /* MAC Interrupt Status register indicates what interrupts are pending.
-        * It is automatically cleared once read.
-        */
-       intstatus = macb_readl(lp, ISR);
-
-       /* Receive complete */
-       if (intstatus & MACB_BIT(RCOMP))
-               at91ether_rx(dev);
-
-       /* Transmit complete */
-       if (intstatus & MACB_BIT(TCOMP)) {
-               /* The TCOM bit is set even if the transmission failed */
-               if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
-                       lp->stats.tx_errors++;
-
-               if (lp->skb) {
-                       dev_kfree_skb_irq(lp->skb);
-                       lp->skb = NULL;
-                       dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
-                       lp->stats.tx_packets++;
-                       lp->stats.tx_bytes += lp->skb_length;
-               }
-               netif_wake_queue(dev);
-       }
-
-       /* Work-around for EMAC Errata section 41.3.1 */
-       if (intstatus & MACB_BIT(RXUBR)) {
-               ctl = macb_readl(lp, NCR);
-               macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
-               macb_writel(lp, NCR, ctl | MACB_BIT(RE));
-       }
-
-       if (intstatus & MACB_BIT(ISR_ROVR))
-               netdev_err(dev, "ROVR error\n");
-
-       return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void at91ether_poll_controller(struct net_device *dev)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       at91ether_interrupt(dev->irq, dev);
-       local_irq_restore(flags);
-}
-#endif
-
-static const struct net_device_ops at91ether_netdev_ops = {
-       .ndo_open               = at91ether_open,
-       .ndo_stop               = at91ether_close,
-       .ndo_start_xmit         = at91ether_start_xmit,
-       .ndo_get_stats          = macb_get_stats,
-       .ndo_set_rx_mode        = macb_set_rx_mode,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_do_ioctl           = macb_ioctl,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = at91ether_poll_controller,
-#endif
-};
-
-#if defined(CONFIG_OF)
-static const struct of_device_id at91ether_dt_ids[] = {
-       { .compatible = "cdns,at91rm9200-emac" },
-       { .compatible = "cdns,emac" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, at91ether_dt_ids);
-#endif
-
-/* Detect MAC & PHY and perform ethernet interface initialization */
-static int __init at91ether_probe(struct platform_device *pdev)
-{
-       struct macb_platform_data *board_data = dev_get_platdata(&pdev->dev);
-       struct resource *regs;
-       struct net_device *dev;
-       struct phy_device *phydev;
-       struct macb *lp;
-       int res;
-       u32 reg;
-       const char *mac;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs)
-               return -ENOENT;
-
-       dev = alloc_etherdev(sizeof(struct macb));
-       if (!dev)
-               return -ENOMEM;
-
-       lp = netdev_priv(dev);
-       lp->pdev = pdev;
-       lp->dev = dev;
-       spin_lock_init(&lp->lock);
-
-       /* physical base address */
-       dev->base_addr = regs->start;
-       lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
-       if (!lp->regs) {
-               res = -ENOMEM;
-               goto err_free_dev;
-       }
-
-       /* Clock */
-       lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
-       if (IS_ERR(lp->pclk)) {
-               res = PTR_ERR(lp->pclk);
-               goto err_free_dev;
-       }
-       clk_prepare_enable(lp->pclk);
-
-       lp->hclk = ERR_PTR(-ENOENT);
-       lp->tx_clk = ERR_PTR(-ENOENT);
-
-       /* Install the interrupt handler */
-       dev->irq = platform_get_irq(pdev, 0);
-       res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
-       if (res)
-               goto err_disable_clock;
-
-       dev->netdev_ops = &at91ether_netdev_ops;
-       dev->ethtool_ops = &macb_ethtool_ops;
-       platform_set_drvdata(pdev, dev);
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
-       mac = of_get_mac_address(pdev->dev.of_node);
-       if (mac)
-               memcpy(lp->dev->dev_addr, mac, ETH_ALEN);
-       else
-               macb_get_hwaddr(lp);
-
-       res = of_get_phy_mode(pdev->dev.of_node);
-       if (res < 0) {
-               if (board_data && board_data->is_rmii)
-                       lp->phy_interface = PHY_INTERFACE_MODE_RMII;
-               else
-                       lp->phy_interface = PHY_INTERFACE_MODE_MII;
-       } else {
-               lp->phy_interface = res;
-       }
-
-       macb_writel(lp, NCR, 0);
-
-       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
-       if (lp->phy_interface == PHY_INTERFACE_MODE_RMII)
-               reg |= MACB_BIT(RM9200_RMII);
-
-       macb_writel(lp, NCFGR, reg);
-
-       /* Register the network interface */
-       res = register_netdev(dev);
-       if (res)
-               goto err_disable_clock;
-
-       res = macb_mii_init(lp);
-       if (res)
-               goto err_out_unregister_netdev;
-
-       /* will be enabled in open() */
-       netif_carrier_off(dev);
-
-       phydev = lp->phy_dev;
-       netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
-                               phydev->drv->name, dev_name(&phydev->dev),
-                               phydev->irq);
-
-       /* Display ethernet banner */
-       netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n",
-                               dev->base_addr, dev->irq, dev->dev_addr);
-
-       return 0;
-
-err_out_unregister_netdev:
-       unregister_netdev(dev);
-err_disable_clock:
-       clk_disable_unprepare(lp->pclk);
-err_free_dev:
-       free_netdev(dev);
-       return res;
-}
-
-static int at91ether_remove(struct platform_device *pdev)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-       struct macb *lp = netdev_priv(dev);
-
-       if (lp->phy_dev)
-               phy_disconnect(lp->phy_dev);
-
-       mdiobus_unregister(lp->mii_bus);
-       kfree(lp->mii_bus->irq);
-       mdiobus_free(lp->mii_bus);
-       unregister_netdev(dev);
-       clk_disable_unprepare(lp->pclk);
-       free_netdev(dev);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct macb *lp = netdev_priv(net_dev);
-
-       if (netif_running(net_dev)) {
-               netif_stop_queue(net_dev);
-               netif_device_detach(net_dev);
-
-               clk_disable_unprepare(lp->pclk);
-       }
-       return 0;
-}
-
-static int at91ether_resume(struct platform_device *pdev)
-{
-       struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct macb *lp = netdev_priv(net_dev);
-
-       if (netif_running(net_dev)) {
-               clk_prepare_enable(lp->pclk);
-
-               netif_device_attach(net_dev);
-               netif_start_queue(net_dev);
-       }
-       return 0;
-}
-#else
-#define at91ether_suspend      NULL
-#define at91ether_resume       NULL
-#endif
-
-static struct platform_driver at91ether_driver = {
-       .remove         = at91ether_remove,
-       .suspend        = at91ether_suspend,
-       .resume         = at91ether_resume,
-       .driver         = {
-               .name   = "at91_ether",
-               .of_match_table = of_match_ptr(at91ether_dt_ids),
-       },
-};
-
-module_platform_driver_probe(at91ether_driver, at91ether_probe);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:at91_ether");
index 2bb3c1c06e605c7165755bfbbeb20dada80b2945..a4c5462c071a968713f36c0861bc1b8d78d54dae 100644 (file)
@@ -102,7 +102,7 @@ static void *macb_rx_buffer(struct macb *bp, unsigned int index)
        return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
 }
 
-void macb_set_hwaddr(struct macb *bp)
+static void macb_set_hwaddr(struct macb *bp)
 {
        u32 bottom;
        u16 top;
@@ -120,9 +120,8 @@ void macb_set_hwaddr(struct macb *bp)
        macb_or_gem_writel(bp, SA4B, 0);
        macb_or_gem_writel(bp, SA4T, 0);
 }
-EXPORT_SYMBOL_GPL(macb_set_hwaddr);
 
-void macb_get_hwaddr(struct macb *bp)
+static void macb_get_hwaddr(struct macb *bp)
 {
        struct macb_platform_data *pdata;
        u32 bottom;
@@ -162,7 +161,6 @@ void macb_get_hwaddr(struct macb *bp)
        netdev_info(bp->dev, "invalid hw address, using random\n");
        eth_hw_addr_random(bp->dev);
 }
-EXPORT_SYMBOL_GPL(macb_get_hwaddr);
 
 static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
@@ -359,7 +357,7 @@ static int macb_mii_probe(struct net_device *dev)
        return 0;
 }
 
-int macb_mii_init(struct macb *bp)
+static int macb_mii_init(struct macb *bp)
 {
        struct macb_platform_data *pdata;
        struct device_node *np;
@@ -440,7 +438,6 @@ err_out_free_mdiobus:
 err_out:
        return err;
 }
-EXPORT_SYMBOL_GPL(macb_mii_init);
 
 static void macb_update_stats(struct macb *bp)
 {
@@ -1743,7 +1740,7 @@ static void macb_sethashtable(struct net_device *dev)
 /*
  * Enable/Disable promiscuous and multicast modes.
  */
-void macb_set_rx_mode(struct net_device *dev)
+static void macb_set_rx_mode(struct net_device *dev)
 {
        unsigned long cfg;
        struct macb *bp = netdev_priv(dev);
@@ -1784,7 +1781,6 @@ void macb_set_rx_mode(struct net_device *dev)
 
        macb_writel(bp, NCFGR, cfg);
 }
-EXPORT_SYMBOL_GPL(macb_set_rx_mode);
 
 static int macb_open(struct net_device *dev)
 {
@@ -1937,7 +1933,7 @@ static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)
        }
 }
 
-struct net_device_stats *macb_get_stats(struct net_device *dev)
+static struct net_device_stats *macb_get_stats(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
        struct net_device_stats *nstat = &bp->stats;
@@ -1983,7 +1979,6 @@ struct net_device_stats *macb_get_stats(struct net_device *dev)
 
        return nstat;
 }
-EXPORT_SYMBOL_GPL(macb_get_stats);
 
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -2045,7 +2040,7 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        }
 }
 
-const struct ethtool_ops macb_ethtool_ops = {
+static const struct ethtool_ops macb_ethtool_ops = {
        .get_settings           = macb_get_settings,
        .set_settings           = macb_set_settings,
        .get_regs_len           = macb_get_regs_len,
@@ -2053,7 +2048,6 @@ const struct ethtool_ops macb_ethtool_ops = {
        .get_link               = ethtool_op_get_link,
        .get_ts_info            = ethtool_op_get_ts_info,
 };
-EXPORT_SYMBOL_GPL(macb_ethtool_ops);
 
 static const struct ethtool_ops gem_ethtool_ops = {
        .get_settings           = macb_get_settings,
@@ -2067,7 +2061,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
        .get_sset_count         = gem_get_sset_count,
 };
 
-int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct macb *bp = netdev_priv(dev);
        struct phy_device *phydev = bp->phy_dev;
@@ -2080,7 +2074,6 @@ int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        return phy_mii_ioctl(phydev, rq, cmd);
 }
-EXPORT_SYMBOL_GPL(macb_ioctl);
 
 static int macb_set_features(struct net_device *netdev,
                             netdev_features_t features)
@@ -2132,39 +2125,6 @@ static const struct net_device_ops macb_netdev_ops = {
        .ndo_set_features       = macb_set_features,
 };
 
-#if defined(CONFIG_OF)
-static struct macb_config at91sam9260_config = {
-       .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII,
-};
-
-static struct macb_config pc302gem_config = {
-       .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
-       .dma_burst_length = 16,
-};
-
-static struct macb_config sama5d3_config = {
-       .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
-       .dma_burst_length = 16,
-};
-
-static struct macb_config sama5d4_config = {
-       .caps = 0,
-       .dma_burst_length = 4,
-};
-
-static const struct of_device_id macb_dt_ids[] = {
-       { .compatible = "cdns,at32ap7000-macb" },
-       { .compatible = "cdns,at91sam9260-macb", .data = &at91sam9260_config },
-       { .compatible = "cdns,macb" },
-       { .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
-       { .compatible = "cdns,gem", .data = &pc302gem_config },
-       { .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config },
-       { .compatible = "atmel,sama5d4-gem", .data = &sama5d4_config },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, macb_dt_ids);
-#endif
-
 /*
  * Configure peripheral capacities according to device tree
  * and integration options used
@@ -2172,22 +2132,6 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids);
 static void macb_configure_caps(struct macb *bp)
 {
        u32 dcfg;
-       const struct of_device_id *match;
-       const struct macb_config *config;
-
-       if (bp->pdev->dev.of_node) {
-               match = of_match_node(macb_dt_ids, bp->pdev->dev.of_node);
-               if (match && match->data) {
-                       config = (const struct macb_config *)match->data;
-
-                       bp->caps = config->caps;
-                       /*
-                        * As we have access to the matching node, configure
-                        * DMA burst length as well
-                        */
-                       bp->dma_burst_length = config->dma_burst_length;
-               }
-       }
 
        if (MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2)
                bp->caps |= MACB_CAPS_MACB_IS_GEM;
@@ -2230,92 +2174,57 @@ static void macb_probe_queues(void __iomem *mem,
                        (*num_queues)++;
 }
 
-static int macb_probe(struct platform_device *pdev)
+static int macb_init(struct platform_device *pdev)
 {
-       struct macb_platform_data *pdata;
-       struct resource *regs;
-       struct net_device *dev;
-       struct macb *bp;
-       struct macb_queue *queue;
-       struct phy_device *phydev;
-       u32 config;
-       int err = -ENXIO;
-       const char *mac;
-       void __iomem *mem;
+       struct net_device *dev = platform_get_drvdata(pdev);
        unsigned int hw_q, queue_mask, q, num_queues;
-       struct clk *pclk, *hclk, *tx_clk;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_err(&pdev->dev, "no mmio resource defined\n");
-               goto err_out;
-       }
+       struct macb *bp = netdev_priv(dev);
+       struct macb_queue *queue;
+       int err;
+       u32 val;
 
-       pclk = devm_clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(pclk)) {
-               err = PTR_ERR(pclk);
+       bp->pclk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(bp->pclk)) {
+               err = PTR_ERR(bp->pclk);
                dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err);
-               goto err_out;
+               return err;
        }
 
-       hclk = devm_clk_get(&pdev->dev, "hclk");
-       if (IS_ERR(hclk)) {
-               err = PTR_ERR(hclk);
+       bp->hclk = devm_clk_get(&pdev->dev, "hclk");
+       if (IS_ERR(bp->hclk)) {
+               err = PTR_ERR(bp->hclk);
                dev_err(&pdev->dev, "failed to get hclk (%u)\n", err);
-               goto err_out;
+               return err;
        }
 
-       tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
-       if (IS_ERR(tx_clk))
-               tx_clk = NULL;
+       bp->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
+       if (IS_ERR(bp->tx_clk))
+               bp->tx_clk = NULL;
 
-       err = clk_prepare_enable(pclk);
+       err = clk_prepare_enable(bp->pclk);
        if (err) {
                dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
-               goto err_out;
+               return err;
        }
 
-       err = clk_prepare_enable(hclk);
+       err = clk_prepare_enable(bp->hclk);
        if (err) {
                dev_err(&pdev->dev, "failed to enable hclk (%u)\n", err);
-               goto err_out_disable_pclk;
+               goto err_disable_pclk;
        }
 
-       err = clk_prepare_enable(tx_clk);
+       err = clk_prepare_enable(bp->tx_clk);
        if (err) {
                dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
-               goto err_out_disable_hclk;
+               goto err_disable_hclk;
        }
 
-       err = -ENOMEM;
-       mem = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
-       if (!mem) {
-               dev_err(&pdev->dev, "failed to map registers, aborting.\n");
-               goto err_out_disable_clocks;
-       }
-
-       macb_probe_queues(mem, &queue_mask, &num_queues);
-       dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
-       if (!dev)
-               goto err_out_disable_clocks;
-
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
-       bp = netdev_priv(dev);
-       bp->pdev = pdev;
-       bp->dev = dev;
-       bp->regs = mem;
-       bp->num_queues = num_queues;
-       bp->pclk = pclk;
-       bp->hclk = hclk;
-       bp->tx_clk = tx_clk;
-
-       spin_lock_init(&bp->lock);
-
        /* set the queue register mapping once for all: queue0 has a special
         * register mapping but we don't want to test the queue index then
         * compute the corresponding register offset at run time.
         */
+       macb_probe_queues(bp->regs, &queue_mask, &num_queues);
+
        for (hw_q = 0, q = 0; hw_q < MACB_MAX_QUEUES; ++hw_q) {
                if (!(queue_mask & (1 << hw_q)))
                        continue;
@@ -2349,22 +2258,16 @@ static int macb_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "Unable to request IRQ %d (error %d)\n",
                                queue->irq, err);
-                       goto err_out_free_netdev;
+                       goto err_disable_tx_clk;
                }
 
                INIT_WORK(&queue->tx_error_task, macb_tx_error_task);
                q++;
        }
-       dev->irq = bp->queues[0].irq;
 
        dev->netdev_ops = &macb_netdev_ops;
        netif_napi_add(dev, &bp->napi, macb_poll, 64);
 
-       dev->base_addr = regs->start;
-
-       /* setup capacities */
-       macb_configure_caps(bp);
-
        /* setup appropriated routines according to adapter type */
        if (macb_is_gem(bp)) {
                bp->max_tx_length = GEM_MAX_TX_LEN;
@@ -2391,18 +2294,439 @@ static int macb_probe(struct platform_device *pdev)
                dev->hw_features &= ~NETIF_F_SG;
        dev->features = dev->hw_features;
 
+       val = 0;
+       if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
+               val = GEM_BIT(RGMII);
+       else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
+                (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+               val = MACB_BIT(RMII);
+       else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+               val = MACB_BIT(MII);
+
+       if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
+               val |= MACB_BIT(CLKEN);
+
+       macb_or_gem_writel(bp, USRIO, val);
+
+       /* setup capacities */
+       macb_configure_caps(bp);
+
        /* Set MII management clock divider */
-       config = macb_mdc_clk_div(bp);
-       config |= macb_dbw(bp);
-       macb_writel(bp, NCFGR, config);
+       val = macb_mdc_clk_div(bp);
+       val |= macb_dbw(bp);
+       macb_writel(bp, NCFGR, val);
+
+       return 0;
+
+err_disable_tx_clk:
+       clk_disable_unprepare(bp->tx_clk);
+
+err_disable_hclk:
+       clk_disable_unprepare(bp->hclk);
+
+err_disable_pclk:
+       clk_disable_unprepare(bp->pclk);
+
+       return err;
+}
+
+#if defined(CONFIG_OF)
+/* 1518 rounded up */
+#define AT91ETHER_MAX_RBUFF_SZ 0x600
+/* max number of receive buffers */
+#define AT91ETHER_MAX_RX_DESCR 9
+
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct net_device *dev)
+{
+       struct macb *lp = netdev_priv(dev);
+       dma_addr_t addr;
+       u32 ctl;
+       int i;
+
+       lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
+                                        (AT91ETHER_MAX_RX_DESCR *
+                                         sizeof(struct macb_dma_desc)),
+                                        &lp->rx_ring_dma, GFP_KERNEL);
+       if (!lp->rx_ring)
+               return -ENOMEM;
+
+       lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
+                                           AT91ETHER_MAX_RX_DESCR *
+                                           AT91ETHER_MAX_RBUFF_SZ,
+                                           &lp->rx_buffers_dma, GFP_KERNEL);
+       if (!lp->rx_buffers) {
+               dma_free_coherent(&lp->pdev->dev,
+                                 AT91ETHER_MAX_RX_DESCR *
+                                 sizeof(struct macb_dma_desc),
+                                 lp->rx_ring, lp->rx_ring_dma);
+               lp->rx_ring = NULL;
+               return -ENOMEM;
+       }
+
+       addr = lp->rx_buffers_dma;
+       for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
+               lp->rx_ring[i].addr = addr;
+               lp->rx_ring[i].ctrl = 0;
+               addr += AT91ETHER_MAX_RBUFF_SZ;
+       }
+
+       /* Set the Wrap bit on the last descriptor */
+       lp->rx_ring[AT91ETHER_MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
+
+       /* Reset buffer index */
+       lp->rx_tail = 0;
+
+       /* Program address of descriptor list in Rx Buffer Queue register */
+       macb_writel(lp, RBQP, lp->rx_ring_dma);
+
+       /* Enable Receive and Transmit */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+
+       return 0;
+}
+
+/* Open the ethernet interface */
+static int at91ether_open(struct net_device *dev)
+{
+       struct macb *lp = netdev_priv(dev);
+       u32 ctl;
+       int ret;
+
+       /* Clear internal statistics */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
+
+       macb_set_hwaddr(lp);
+
+       ret = at91ether_start(dev);
+       if (ret)
+               return ret;
+
+       /* Enable MAC interrupts */
+       macb_writel(lp, IER, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
+
+       /* schedule a link state check */
+       phy_start(lp->phy_dev);
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+/* Close the interface */
+static int at91ether_close(struct net_device *dev)
+{
+       struct macb *lp = netdev_priv(dev);
+       u32 ctl;
+
+       /* Disable Receiver and Transmitter */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
+
+       /* Disable MAC interrupts */
+       macb_writel(lp, IDR, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
+
+       netif_stop_queue(dev);
+
+       dma_free_coherent(&lp->pdev->dev,
+                         AT91ETHER_MAX_RX_DESCR *
+                         sizeof(struct macb_dma_desc),
+                         lp->rx_ring, lp->rx_ring_dma);
+       lp->rx_ring = NULL;
+
+       dma_free_coherent(&lp->pdev->dev,
+                         AT91ETHER_MAX_RX_DESCR * AT91ETHER_MAX_RBUFF_SZ,
+                         lp->rx_buffers, lp->rx_buffers_dma);
+       lp->rx_buffers = NULL;
+
+       return 0;
+}
+
+/* Transmit packet */
+static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct macb *lp = netdev_priv(dev);
+
+       if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
+               netif_stop_queue(dev);
+
+               /* Store packet information (to free when Tx completed) */
+               lp->skb = skb;
+               lp->skb_length = skb->len;
+               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
+                                                       DMA_TO_DEVICE);
+
+               /* Set address of the data in the Transmit Address register */
+               macb_writel(lp, TAR, lp->skb_physaddr);
+               /* Set length of the packet in the Transmit Control register */
+               macb_writel(lp, TCR, skb->len);
 
-       mac = of_get_mac_address(pdev->dev.of_node);
+       } else {
+               netdev_err(dev, "%s called, but device is busy!\n", __func__);
+               return NETDEV_TX_BUSY;
+       }
+
+       return NETDEV_TX_OK;
+}
+
+/* Extract received frame from buffer descriptors and sent to upper layers.
+ * (Called from interrupt context)
+ */
+static void at91ether_rx(struct net_device *dev)
+{
+       struct macb *lp = netdev_priv(dev);
+       unsigned char *p_recv;
+       struct sk_buff *skb;
+       unsigned int pktlen;
+
+       while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+               p_recv = lp->rx_buffers + lp->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
+               pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
+               skb = netdev_alloc_skb(dev, pktlen + 2);
+               if (skb) {
+                       skb_reserve(skb, 2);
+                       memcpy(skb_put(skb, pktlen), p_recv, pktlen);
+
+                       skb->protocol = eth_type_trans(skb, dev);
+                       lp->stats.rx_packets++;
+                       lp->stats.rx_bytes += pktlen;
+                       netif_rx(skb);
+               } else {
+                       lp->stats.rx_dropped++;
+               }
+
+               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+                       lp->stats.multicast++;
+
+               /* reset ownership bit */
+               lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
+
+               /* wrap after last buffer */
+               if (lp->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
+                       lp->rx_tail = 0;
+               else
+                       lp->rx_tail++;
+       }
+}
+
+/* MAC interrupt handler */
+static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct macb *lp = netdev_priv(dev);
+       u32 intstatus, ctl;
+
+       /* MAC Interrupt Status register indicates what interrupts are pending.
+        * It is automatically cleared once read.
+        */
+       intstatus = macb_readl(lp, ISR);
+
+       /* Receive complete */
+       if (intstatus & MACB_BIT(RCOMP))
+               at91ether_rx(dev);
+
+       /* Transmit complete */
+       if (intstatus & MACB_BIT(TCOMP)) {
+               /* The TCOM bit is set even if the transmission failed */
+               if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
+                       lp->stats.tx_errors++;
+
+               if (lp->skb) {
+                       dev_kfree_skb_irq(lp->skb);
+                       lp->skb = NULL;
+                       dma_unmap_single(NULL, lp->skb_physaddr,
+                                        lp->skb_length, DMA_TO_DEVICE);
+                       lp->stats.tx_packets++;
+                       lp->stats.tx_bytes += lp->skb_length;
+               }
+               netif_wake_queue(dev);
+       }
+
+       /* Work-around for EMAC Errata section 41.3.1 */
+       if (intstatus & MACB_BIT(RXUBR)) {
+               ctl = macb_readl(lp, NCR);
+               macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+               macb_writel(lp, NCR, ctl | MACB_BIT(RE));
+       }
+
+       if (intstatus & MACB_BIT(ISR_ROVR))
+               netdev_err(dev, "ROVR error\n");
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void at91ether_poll_controller(struct net_device *dev)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       at91ether_interrupt(dev->irq, dev);
+       local_irq_restore(flags);
+}
+#endif
+
+static const struct net_device_ops at91ether_netdev_ops = {
+       .ndo_open               = at91ether_open,
+       .ndo_stop               = at91ether_close,
+       .ndo_start_xmit         = at91ether_start_xmit,
+       .ndo_get_stats          = macb_get_stats,
+       .ndo_set_rx_mode        = macb_set_rx_mode,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_do_ioctl           = macb_ioctl,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = at91ether_poll_controller,
+#endif
+};
+
+static int at91ether_init(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct macb *bp = netdev_priv(dev);
+       int err;
+       u32 reg;
+
+       bp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+       if (IS_ERR(bp->pclk))
+               return PTR_ERR(bp->pclk);
+
+       err = clk_prepare_enable(bp->pclk);
+       if (err) {
+               dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
+               return err;
+       }
+
+       dev->netdev_ops = &at91ether_netdev_ops;
+       dev->ethtool_ops = &macb_ethtool_ops;
+
+       err = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt,
+                              0, dev->name, dev);
+       if (err)
+               goto err_disable_clk;
+
+       macb_writel(bp, NCR, 0);
+
+       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
+       if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
+               reg |= MACB_BIT(RM9200_RMII);
+
+       macb_writel(bp, NCFGR, reg);
+
+       return 0;
+
+err_disable_clk:
+       clk_disable_unprepare(bp->pclk);
+
+       return err;
+}
+
+static struct macb_config at91sam9260_config = {
+       .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII,
+       .init = macb_init,
+};
+
+static struct macb_config pc302gem_config = {
+       .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+       .dma_burst_length = 16,
+       .init = macb_init,
+};
+
+static struct macb_config sama5d3_config = {
+       .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+       .dma_burst_length = 16,
+       .init = macb_init,
+};
+
+static struct macb_config sama5d4_config = {
+       .caps = 0,
+       .dma_burst_length = 4,
+       .init = macb_init,
+};
+
+static struct macb_config emac_config = {
+       .init = at91ether_init,
+};
+
+static const struct of_device_id macb_dt_ids[] = {
+       { .compatible = "cdns,at32ap7000-macb" },
+       { .compatible = "cdns,at91sam9260-macb", .data = &at91sam9260_config },
+       { .compatible = "cdns,macb" },
+       { .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
+       { .compatible = "cdns,gem", .data = &pc302gem_config },
+       { .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config },
+       { .compatible = "atmel,sama5d4-gem", .data = &sama5d4_config },
+       { .compatible = "cdns,at91rm9200-emac", .data = &emac_config },
+       { .compatible = "cdns,emac", .data = &emac_config },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, macb_dt_ids);
+#endif /* CONFIG_OF */
+
+static int macb_probe(struct platform_device *pdev)
+{
+       int (*init)(struct platform_device *) = macb_init;
+       struct device_node *np = pdev->dev.of_node;
+       const struct macb_config *macb_config = NULL;
+       unsigned int queue_mask, num_queues;
+       struct macb_platform_data *pdata;
+       struct phy_device *phydev;
+       struct net_device *dev;
+       struct resource *regs;
+       void __iomem *mem;
+       const char *mac;
+       struct macb *bp;
+       int err;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mem = devm_ioremap_resource(&pdev->dev, regs);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
+
+       macb_probe_queues(mem, &queue_mask, &num_queues);
+       dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->base_addr = regs->start;
+
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       bp = netdev_priv(dev);
+       bp->pdev = pdev;
+       bp->dev = dev;
+       bp->regs = mem;
+       bp->num_queues = num_queues;
+       spin_lock_init(&bp->lock);
+
+       platform_set_drvdata(pdev, dev);
+
+       dev->irq = platform_get_irq(pdev, 0);
+       if (dev->irq < 0)
+               return dev->irq;
+
+       mac = of_get_mac_address(np);
        if (mac)
                memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
        else
                macb_get_hwaddr(bp);
 
-       err = of_get_phy_mode(pdev->dev.of_node);
+       err = of_get_phy_mode(np);
        if (err < 0) {
                pdata = dev_get_platdata(&pdev->dev);
                if (pdata && pdata->is_rmii)
@@ -2413,32 +2737,35 @@ static int macb_probe(struct platform_device *pdev)
                bp->phy_interface = err;
        }
 
-       config = 0;
-       if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
-               config = GEM_BIT(RGMII);
-       else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
-                (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
-               config = MACB_BIT(RMII);
-       else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
-               config = MACB_BIT(MII);
+       if (np) {
+               const struct of_device_id *match;
 
-       if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
-               config |= MACB_BIT(CLKEN);
+               match = of_match_node(macb_dt_ids, np);
+               if (match)
+                       macb_config = match->data;
+       }
+
+       if (macb_config) {
+               bp->caps = macb_config->caps;
+               bp->dma_burst_length = macb_config->dma_burst_length;
+               init = macb_config->init;
+       }
 
-       macb_or_gem_writel(bp, USRIO, config);
+       /* IP specific init */
+       err = init(pdev);
+       if (err)
+               goto err_out_free_netdev;
 
        err = register_netdev(dev);
        if (err) {
                dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-               goto err_out_free_netdev;
+               goto err_disable_clocks;
        }
 
        err = macb_mii_init(bp);
        if (err)
                goto err_out_unregister_netdev;
 
-       platform_set_drvdata(pdev, dev);
-
        netif_carrier_off(dev);
 
        netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
@@ -2453,15 +2780,15 @@ static int macb_probe(struct platform_device *pdev)
 
 err_out_unregister_netdev:
        unregister_netdev(dev);
+
+err_disable_clocks:
+       clk_disable_unprepare(bp->tx_clk);
+       clk_disable_unprepare(bp->hclk);
+       clk_disable_unprepare(bp->pclk);
+
 err_out_free_netdev:
        free_netdev(dev);
-err_out_disable_clocks:
-       clk_disable_unprepare(tx_clk);
-err_out_disable_hclk:
-       clk_disable_unprepare(hclk);
-err_out_disable_pclk:
-       clk_disable_unprepare(pclk);
-err_out:
+
        return err;
 }
 
index 1797fb00124b4af3d9db852ebf8918bab5f63d1c..21e4147d8b5ca72efbe11fb6f7aa89d17a0fe5f9 100644 (file)
@@ -754,6 +754,7 @@ struct macb_or_gem_ops {
 struct macb_config {
        u32                     caps;
        unsigned int            dma_burst_length;
+       int     (*init)(struct platform_device *pdev);
 };
 
 struct macb_queue {
@@ -824,15 +825,6 @@ struct macb {
        u64                     ethtool_stats[GEM_STATS_LEN];
 };
 
-extern const struct ethtool_ops macb_ethtool_ops;
-
-int macb_mii_init(struct macb *bp);
-int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-struct net_device_stats *macb_get_stats(struct net_device *dev);
-void macb_set_rx_mode(struct net_device *dev);
-void macb_set_hwaddr(struct macb *bp);
-void macb_get_hwaddr(struct macb *bp);
-
 static inline bool macb_is_gem(struct macb *bp)
 {
        return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);