Module: xenomai-gch
Branch: for-forge
Commit: 764475937d39094d6d0f451c52c5b13820b28db4
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=764475937d39094d6d0f451c52c5b13820b28db4

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Sun Nov 16 07:04:00 2014 +0100

rtnet: update at91_ether driver

To the version from Linux 3.16
This fixes compilation issues with recent kernels.

---

 kernel/drivers/net/drivers/Kconfig      |    1 +
 kernel/drivers/net/drivers/at91_ether.c | 1108 ++++++++-----------------------
 kernel/drivers/net/drivers/macb.c       |   15 +-
 kernel/drivers/net/drivers/rt_macb.h    |    5 +
 4 files changed, 300 insertions(+), 829 deletions(-)

diff --git a/kernel/drivers/net/drivers/Kconfig 
b/kernel/drivers/net/drivers/Kconfig
index 376810d..267396c 100644
--- a/kernel/drivers/net/drivers/Kconfig
+++ b/kernel/drivers/net/drivers/Kconfig
@@ -118,6 +118,7 @@ if ARCH = arm
 
 config XENO_DRIVERS_NET_DRV_AT91_ETHER
     depends on XENO_DRIVERS_NET && SOC_AT91RM9200
+    select XENO_DRIVERS_NET_DRV_MACB
     tristate "AT91RM9200 Board Ethernet Driver"
 
 config XENO_DRIVERS_NET_DRV_MACB
diff --git a/kernel/drivers/net/drivers/at91_ether.c 
b/kernel/drivers/net/drivers/at91_ether.c
index 41e4010..b9dc2ea 100644
--- a/kernel/drivers/net/drivers/at91_ether.c
+++ b/kernel/drivers/net/drivers/at91_ether.c
@@ -1,7 +1,4 @@
-/* rtnet/drivers/rt_at91_ether.c: An Atmel AT91RM9200 (Thunder) 
Real-Time-Ethernet driver for Linux. */
 /*
- * RTnet porting 2007 by Chun Yeow, Yeoh <yeohchuny...@gmail.com>
- *
  * Ethernet driver for the Atmel AT91RM9200 (Thunder)
  *
  *  Copyright (C) 2003 SAN People (Pty) Ltd
@@ -9,992 +6,447 @@
  * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
  * Initial version by Rick Bronson 01/11/2003
  *
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- *   (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <ro...@imsystems.ru>
- *
  * 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.
+ *
+ * RTnet port:
+ * Copyright (C) 2014 Gilles Chanteperdrix <g...@xenomai.org>
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/mii.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 <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/at91rm9200_emac.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/board.h>
-
-#include "rt_at91_ether.h"
-
-/* RTnet */
-#include <rtdm/driver.h>
 #include <rtdev.h>
+#include <rtnet.h>
 #include <rtnet_port.h>
+#include <rtskb.h>
+#include "rt_macb.h"
 
-#define DRV_NAME       "at91_ether"
-#define DRV_VERSION    "1.0"
-
-#define LINK_POLL_INTERVAL     (HZ)
-
-static int use_phy_timer;      /* Without a PHY IRQ, should we poll? */
-
-module_param(use_phy_timer, int, 0444);
-MODULE_PARM_DESC(use_phy_timer, "Poll PHY at 1 HZ if IRQ is lacking (0)");
+/* 1518 rounded up */
+#define MAX_RBUFF_SZ   0x600
+/* max number of receive buffers */
+#define MAX_RX_DESCR   9
 
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(unsigned int reg)
-{
-       void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-       return __raw_readl(emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(unsigned int reg, unsigned long value)
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct rtnet_device *dev)
 {
-       void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-       __raw_writel(value, emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * Control register manipulation must be lock-protected - but also the code
- * between enable_mdi and disable_mdi???
- */
-static void enable_mdi(void)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(AT91_EMAC_CTL);
-       at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);    /* enable 
management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(void)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(AT91_EMAC_CTL);
-       at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);   /* disable 
management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(void) {
-       unsigned long timeout = jiffies + 2;
-
-       while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-               if (time_after(jiffies, timeout)) {
-                       printk("at91_ether: MIO timeout\n");
-                       break;
-               }
-               cpu_relax();
-       }
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(unsigned char phy_addr, unsigned char address, unsigned 
int value)
-{
-       at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-               | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & 
AT91_EMAC_DATA));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait();
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(unsigned char phy_addr, unsigned char address, unsigned 
int *value)
-{
-       at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-               | ((phy_addr & 0x1f) << 23) | (address << 18));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait();
-
-       *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-static int mdio_read(struct rtnet_device *dev, int phy_id, int location)
-{
-       unsigned int value;
-
-       read_phy(phy_id, location, &value);
-       return value;
-}
-
-/*static void mdio_write(struct rtnet_device *dev, int phy_id, int location, 
int value)
-{
-       write_phy(phy_id, location, value);
-}*/
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct rtnet_device *dev, int silent)
-{
-       struct at91_private *lp = dev->priv;
-       unsigned int bmsr, bmcr, lpa, mac_cfg;
-       unsigned int speed, duplex;
-       int val=0;
-
-       mdio_read(dev, lp->mii.phy_id, MII_BMSR);
-       if (mdio_read(dev, lp->mii.phy_id, MII_BMSR) & BMSR_LSTATUS)
-         val = 1;
-
-       if (!val) {             /* no link */
-         rtnetif_carrier_off(dev);
-               if (!silent)
-                       printk(KERN_INFO "%s: Link down.\n", dev->name);
-               return;
-       }
+       struct macb *lp = rtnetdev_priv(dev);
+       dma_addr_t addr;
+       u32 ctl;
+       int i;
 
-       /* Link up, or auto-negotiation still in progress */
-       read_phy(lp->phy_address, MII_BMSR, &bmsr);
-       read_phy(lp->phy_address, MII_BMCR, &bmcr);
-       if (bmcr & BMCR_ANENABLE) {                             /* 
AutoNegotiation is enabled */
-               if (!(bmsr & BMSR_ANEGCOMPLETE))
-                       return;                 /* Do nothing - another 
interrupt generated when negotiation complete */
-
-               read_phy(lp->phy_address, MII_LPA, &lpa);
-               if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = 
SPEED_100;
-               else speed = SPEED_10;
-               if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = 
DUPLEX_FULL;
-               else duplex = DUPLEX_HALF;
-       } else {
-               speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-               duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-       }
+       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;
 
-       /* Update the MAC */
-       mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | 
AT91_EMAC_FD);
-       if (speed == SPEED_100) {
-               if (duplex == DUPLEX_FULL)              /* 100 Full Duplex */
-                       mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-               else                                    /* 100 Half Duplex */
-                       mac_cfg |= AT91_EMAC_SPD;
-       } else {
-               if (duplex == DUPLEX_FULL)              /* 10 Full Duplex */
-                       mac_cfg |= AT91_EMAC_FD;
-               else {}                                 /* 10 Half Duplex */
+       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;
        }
-       at91_emac_write(AT91_EMAC_CFG, mac_cfg);
 
-       if (!silent)
-               printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, 
(duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-       rtnetif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static int at91ether_phy_interrupt(rtdm_irq_t *irq_handle)
-{
-       struct rtnet_device *dev = rtdm_irq_get_arg(irq_handle, struct 
rtnet_device);
-       struct at91_private *lp = dev->priv;
-       unsigned int phy;
-
-       /*
-        * This hander is triggered on both edges, but the PHY chips expect
-        * level-triggering.  We therefore have to check if the PHY actually has
-        * an IRQ pending.
-        */
-       rtdm_lock_get(&lp->lock);
-       enable_mdi();
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == 
MII_DM9161A_ID)) {
-               read_phy(lp->phy_address, MII_DSINTR_REG, &phy);        /* ack 
interrupt in Davicom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {
-               read_phy(lp->phy_address, MII_ISINTS_REG, &phy);        /* ack 
interrupt in Intel PHY */
-               if (!(phy & (1 << 2)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {
-               read_phy(lp->phy_address, MII_BCMINTR_REG, &phy);       /* ack 
interrupt in Broadcom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {
-               read_phy(lp->phy_address, MII_TPISTATUS, &phy);         /* ack 
interrupt in Micrel PHY */
-               if (!(phy & ((1 << 2) | 1)))
-                       goto done;
+       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;
        }
 
-       update_linkspeed(dev, 0);
-
-done:
-       disable_mdi();
-       rtdm_lock_put(&lp->lock);
-
-       return RTDM_IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct rtnet_device *dev)
-{
-       struct at91_private *lp = dev->priv;
-       unsigned int dsintr, irq_number;
-       int err;
-       rtdm_lockctx_t context;
-
-       irq_number = lp->board_data.phy_irq_pin;
-       if (!irq_number) {
-               /*
-                * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
-                * or board does not have it connected.
-                */
-               if (use_phy_timer)
-                       mod_timer(&lp->check_timer, jiffies + 
LINK_POLL_INTERVAL);
-               return;
-       }
+       /* Set the Wrap bit on the last descriptor */
+       lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
 
-       err = rtdm_irq_request(&lp->phy_irq_handle, irq_number, 
at91ether_phy_interrupt, 0, dev->name, dev);
-       if (err) {
-               printk(KERN_ERR "at91_ether: PHY IRQ %d request failed: %d!\n", 
irq_number, err);
-               return;
-       }
+       /* Reset buffer index */
+       lp->rx_tail = 0;
 
-       rtdm_lock_get_irqsave(&lp->lock, context);
-       enable_mdi();
+       /* Program address of descriptor list in Rx Buffer Queue register */
+       macb_writel(lp, RBQP, lp->rx_ring_dma);
 
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == 
MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr & ~0xf00;               /* clear bits 8..11 */
-               write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr | 0xf2;                 /* set bits 1, 4..7 */
-               write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               dsintr = (1 << 15) | ( 1 << 14);
-               write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               dsintr = (1 << 10) | ( 1 << 8);
-               write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-       }
+       /* Enable Receive and Transmit */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
 
-       disable_mdi();
-       rtdm_lock_put_irqrestore(&lp->lock, context);
+       return 0;
 }
 
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct rtnet_device *dev)
+/* Open the ethernet interface */
+static int at91ether_open(struct rtnet_device *dev)
 {
-       struct at91_private *lp = dev->priv;
-       unsigned int dsintr;
-       unsigned int irq_number;
-       rtdm_lockctx_t context;
-
-       irq_number = lp->board_data.phy_irq_pin;
-       if (!irq_number) {
-               if (use_phy_timer)
-                       del_timer_sync(&lp->check_timer);
-               return;
-       }
-
-       rtdm_lock_get_irqsave(&lp->lock, context);
-       enable_mdi();
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == 
MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr | 0xf00;                        /* set bits 
8..11 */
-               write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr & ~0xf2;                        /* clear bits 
1, 4..7 */
-               write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
-               dsintr = ~(1 << 14);
-               write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
-               dsintr = ~((1 << 10) | (1 << 8));
-               write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-       }
+       struct macb *lp = rtnetdev_priv(dev);
+       u32 ctl;
+       int ret;
 
-       disable_mdi();
-       rtdm_lock_put_irqrestore(&lp->lock, context);
+       rt_stack_connect(dev, &STACK_manager);
 
-       rtdm_irq_free(&lp->phy_irq_handle);                     /* Free 
interrupt handler */
-}
+       /* Clear internal statistics */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
 
-static void at91ether_check_link(unsigned long dev_id)
-{
-       struct rtnet_device *dev = (struct rtnet_device *) dev_id;
-       struct at91_private *lp = dev->priv;
-       rtdm_lockctx_t context;
+       rtmacb_set_hwaddr(lp);
 
-       rtdm_lock_get_irqsave(&lp->lock, context);
-       enable_mdi();
-       update_linkspeed(dev, 1);
-       disable_mdi();
-       rtdm_lock_put_irqrestore(&lp->lock, context);
-
-       mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
+       ret = at91ether_start(dev);
+       if (ret)
+               return ret;
 
-/* ......................... ADDRESS MANAGEMENT ........................ */
+       /* 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));
 
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- *   happen to access the Ethernet while it's booting.  Some versions of
- *   U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- *   MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- *   continues to do so, for bug-compatibility).
- */
+       /* schedule a link state check */
+       phy_start(lp->phy_dev);
 
-static short unpack_mac_address(struct rtnet_device *dev, unsigned int hi, 
unsigned int lo)
-{
-       char addr[6];
-
-       if (machine_is_csb337()) {
-               addr[5] = (lo & 0xff);                  /* The CSB337 
bootloader stores the MAC the wrong-way around */
-               addr[4] = (lo & 0xff00) >> 8;
-               addr[3] = (lo & 0xff0000) >> 16;
-               addr[2] = (lo & 0xff000000) >> 24;
-               addr[1] = (hi & 0xff);
-               addr[0] = (hi & 0xff00) >> 8;
-       }
-       else {
-               addr[0] = (lo & 0xff);
-               addr[1] = (lo & 0xff00) >> 8;
-               addr[2] = (lo & 0xff0000) >> 16;
-               addr[3] = (lo & 0xff000000) >> 24;
-               addr[4] = (hi & 0xff);
-               addr[5] = (hi & 0xff00) >> 8;
-       }
+       rtnetif_start_queue(dev);
 
-       if (is_valid_ether_addr(addr)) {
-               memcpy(dev->dev_addr, &addr, 6);
-               return 1;
-       }
        return 0;
 }
 
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void get_mac_address(struct rtnet_device *dev)
-{
-       /* Check Specific-Address 1 */
-       if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), 
at91_emac_read(AT91_EMAC_SA1L)))
-               return;
-       /* Check Specific-Address 2 */
-       if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), 
at91_emac_read(AT91_EMAC_SA2L)))
-               return;
-       /* Check Specific-Address 3 */
-       if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), 
at91_emac_read(AT91_EMAC_SA3L)))
-               return;
-       /* Check Specific-Address 4 */
-       if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), 
at91_emac_read(AT91_EMAC_SA4L)))
-               return;
-
-       printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC 
address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct rtnet_device *dev)
-{
-       at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | 
(dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-       at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | 
(dev->dev_addr[4]));
-
-       at91_emac_write(AT91_EMAC_SA2L, 0);
-       at91_emac_write(AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
+/* Close the interface */
+static int at91ether_close(struct rtnet_device *dev)
 {
-       if (addr[bitnr / 8] & (1 << (bitnr % 8)))
-               return 1;
-       return 0;
-}
+       struct macb *lp = rtnetdev_priv(dev);
+       u32 ctl;
 
-/*
- * The hash address register is 64 bits long and takes up two locations in the 
memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network 
configuration
- *  register enable the reception of hash matched frames. The destination 
address is
- *  reduced to a 6 bit index into the 64 bit hash register using the following 
hash function.
- * The hash function is an exclusive or of every sixth bit of the destination 
address.
- *   hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ 
da[41] ^ da[47]
- *   hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ 
da[40] ^ da[46]
- *   hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ 
da[39] ^ da[45]
- *   hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ 
da[38] ^ da[44]
- *   hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ 
da[37] ^ da[43]
- *   hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ 
da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that 
is, the multicast/
- *  unicast indicator, and da[47] represents the most significant bit of the 
last byte
- *  received.
- * If the hash index points to a bit that is set in the hash register then the 
frame will be
- *  matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is 
set, da[0] is 1 and
- *  the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, 
da[0] is 0 and the
- *  hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all 
ones and the
- *  multicast hash enable bit should be set in the network configuration 
register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct rtnet_device *dev)
-{
-       struct at91_private *lp = dev->priv;
-       struct recv_desc_bufs *dlist, *dlist_phys;
-       int i;
-       unsigned long ctl;
+       /* Disable Receiver and Transmitter */
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
 
-       dlist = lp->dlist;
-       dlist_phys = lp->dlist_phys;
+       /* 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));
 
-       for (i = 0; i < MAX_RX_DESCR; i++) {
-               dlist->descriptors[i].addr = (unsigned int) 
&dlist_phys->recv_buf[i][0];
-               dlist->descriptors[i].size = 0;
-       }
+       rtnetif_stop_queue(dev);
 
-       /* Set the Wrap bit on the last descriptor */
-       dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+       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;
 
-       /* Reset buffer index */
-       lp->rxBuffIndex = 0;
+       dma_free_coherent(&lp->pdev->dev,
+                               MAX_RX_DESCR * MAX_RBUFF_SZ,
+                               lp->rx_buffers, lp->rx_buffers_dma);
+       lp->rx_buffers = NULL;
 
-       /* Program address of descriptor list in Rx Buffer Queue register */
-       at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+       rt_stack_disconnect(dev);
 
-       /* Enable Receive and Transmit */
-       ctl = at91_emac_read(AT91_EMAC_CTL);
-       at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+       return 0;
 }
 
-/*
- * Transmit packet.
- */
-static int at91ether_tx(struct rtskb *skb, struct rtnet_device *dev)
+/* Transmit packet */
+static int at91ether_start_xmit(struct rtskb *skb, struct rtnet_device *dev)
 {
-       struct at91_private *lp = dev->priv;
-       rtdm_lockctx_t context;
+       struct macb *lp = rtnetdev_priv(dev);
 
-       if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+       if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
                rtnetif_stop_queue(dev);
 
                /* Store packet information (to free when Tx completed) */
                lp->skb = skb;
                lp->skb_length = skb->len;
-               lp->stats.tx_bytes += skb->len;
-
-               /* RTNet */
-               rtdm_lock_irqsave(context);
-               if (skb->xmit_stamp)
-                       *skb->xmit_stamp = cpu_to_be64(rtdm_clock_read() + 
*skb->xmit_stamp);
-
-               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, 
DMA_TO_DEVICE);
+               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
+                                                       DMA_TO_DEVICE);
 
                /* Set address of the data in the Transmit Address register */
-               at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
+               macb_writel(lp, TAR, lp->skb_physaddr);
                /* Set length of the packet in the Transmit Control register */
-               at91_emac_write(AT91_EMAC_TCR, skb->len);
-
-               rtdm_lock_irqrestore(context);
+               macb_writel(lp, TCR, skb->len);
 
-               /*dev->trans_start = jiffies;*/
        } else {
-               rtdm_printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but 
device is busy!\n");
-               return 1;       /* if we return anything but zero, dev.c:1055 
calls kfree_skb(skb)
-                               on this skb, he also reports -ENETDOWN and 
printk's, so either
-                               we free and return(0) or don't free and return 
1 */
+               rtdev_err(dev, "%s called, but device is busy!\n", __func__);
+               return RTDEV_TX_BUSY;
        }
 
-       return 0;
+       return RTDEV_TX_OK;
 }
 
-/*
- * Update the current statistics from the internal statistics registers.
- */
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
+/* Extract received frame from buffer descriptors and sent to upper layers.
  * (Called from interrupt context)
  */
-static void at91ether_rx(struct rtnet_device *dev, int *packets, 
nanosecs_abs_t *time_stamp)
+static bool at91ether_rx(struct rtnet_device *dev, nanosecs_abs_t *time_stamp)
 {
-       struct at91_private *lp = dev->priv;
-       struct recv_desc_bufs *dlist;
+       struct macb *lp = rtnetdev_priv(dev);
        unsigned char *p_recv;
        struct rtskb *skb;
        unsigned int pktlen;
+       bool ret = false;
 
-       dlist = lp->dlist;
-
-       while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-               p_recv = dlist->recv_buf[lp->rxBuffIndex];
-               pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;      
/* Length of frame including FCS */
+       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 = rtnetdev_alloc_rtskb(dev, pktlen + 2);
-               if (skb != NULL) {
+               if (skb) {
                        rtskb_reserve(skb, 2);
                        memcpy(rtskb_put(skb, pktlen), p_recv, pktlen);
+
                        skb->protocol = rt_eth_type_trans(skb, dev);
-                       skb->time_stamp = *time_stamp;
+                       lp->stats.rx_packets++;
                        lp->stats.rx_bytes += pktlen;
+                       ret = true;
+                       skb->time_stamp = *time_stamp;
                        rtnetif_rx(skb);
-                       (*packets)++;
-                       /*dev->last_rx = jiffies;*/
-               }
-               else {
-                       lp->stats.rx_dropped += 1;
-                       rtdm_printk(KERN_NOTICE "%s: Memory squeeze, dropping 
packet.\n", dev->name);
+               } else {
+                       lp->stats.rx_dropped++;
                }
 
-               if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
+               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
                        lp->stats.multicast++;
 
-               dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;    
/* reset ownership bit */
-               if (lp->rxBuffIndex == MAX_RX_DESCR-1)                          
/* wrap after last buffer */
-                 {
-                       lp->rxBuffIndex = 0;
-                 }
+               /* 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->rxBuffIndex++;
-                 }
+                       lp->rx_tail++;
        }
+
+       return ret;
 }
 
-/*
- * MAC interrupt handler
- */
+/* MAC interrupt handler */
 static int at91ether_interrupt(rtdm_irq_t *irq_handle)
 {
-       struct rtnet_device *dev = rtdm_irq_get_arg(irq_handle, struct 
rtnet_device);
-       struct at91_private *lp = dev->priv;
-       unsigned long intstatus, ctl;
+       void *dev_id = rtdm_irq_get_arg(irq_handle, void);
        nanosecs_abs_t time_stamp = rtdm_clock_read();
-       int packets=0;
+       struct rtnet_device *dev = dev_id;
+       struct macb *lp = rtnetdev_priv(dev);
+       u32 intstatus, ctl;
 
        /* MAC Interrupt Status register indicates what interrupts are pending.
-          It is automatically cleared once read. */
-       intstatus = at91_emac_read(AT91_EMAC_ISR);
-
+        * It is automatically cleared once read.
+        */
+       intstatus = macb_readl(lp, ISR);
 
-       if (intstatus & AT91_EMAC_RCOM)         /* Receive complete */
-               at91ether_rx(dev, &packets, &time_stamp);
+       /* Receive complete */
+       if ((intstatus & MACB_BIT(RCOMP)) && at91ether_rx(dev, &time_stamp))
+               rt_mark_stack_mgr(dev);
 
-       if (intstatus & AT91_EMAC_TCOM) {       /* Transmit complete */
-               /* The TCOM bit is set even if the transmission failed. */
-               if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
-                       lp->stats.tx_errors += 1;
+       /* 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_rtskb(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;
                }
                rtnetif_wake_queue(dev);
        }
 
-       /* Work-around for Errata #11 */
-       if (intstatus & AT91_EMAC_RBNA) {
-               rtdm_lock_get(&lp->lock);
-               ctl = at91_emac_read(AT91_EMAC_CTL);
-               at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-               at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
-               rtdm_lock_put(&lp->lock);
+       /* 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 & AT91_EMAC_ROVR)
-               rtdm_printk("%s: ROVR error\n", dev->name);
-
-       if(packets > 0)
-               rt_mark_stack_mgr(dev);
+       if (intstatus & MACB_BIT(ISR_ROVR))
+               rtdev_err(dev, "ROVR error\n");
 
        return RTDM_IRQ_HANDLED;
 }
 
-/*
- * Open the ethernet interface
- */
-static int at91ether_open_rt(struct rtnet_device *dev)
-{
-       struct at91_private *lp = dev->priv;
-       unsigned long ctl;
-       int err;
-       rtdm_lockctx_t context;
-
-       rt_stack_connect(dev, &STACK_manager);
-
-       /* Request RTDM IRQ */
-       err = rtdm_irq_request(&lp->irq_handle, dev->irq,  at91ether_interrupt, 
0, dev->name, dev);
-       if (err)
-               return err;
-
-       if (!is_valid_ether_addr(dev->dev_addr))
-               return -EADDRNOTAVAIL;
-
-       clk_enable(lp->ether_clk);              /* Re-enable Peripheral clock */
-
-       /* Clear internal statistics
-          Note: No need for locking yet, IRQs sources still off */
-       ctl = at91_emac_read(AT91_EMAC_CTL);
-       at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
-
-       /* Update the MAC address (incase user has changed it) */
-       update_mac_address(dev);
-
-       /* Enable PHY interrupt */
-       enable_phyirq(dev);
-
-       /* Enable MAC interrupts */
-       at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | 
AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-       rtdm_lock_get_irqsave(&lp->lock, context);
-
-       /* Determine current link speed */
-       enable_mdi();
-       update_linkspeed(dev, 0);
-       disable_mdi();
-
-       at91ether_start(dev);
-
-       rtdm_lock_put_irqrestore(&lp->lock, context);
-
-       rtnetif_start_queue(dev);
-       return 0;
-}
-
-/*
- * Close the interface
- */
-static int at91ether_close_rt(struct rtnet_device *dev)
-{
-       struct at91_private *lp = dev->priv;
-       unsigned long ctl;
-       rtdm_lockctx_t context;
-
-       /* Disable Receiver and Transmitter */
-       rtdm_lock_get_irqsave(&lp->lock, context);
-       ctl = at91_emac_read(AT91_EMAC_CTL);
-       at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-       rtdm_lock_put_irqrestore(&lp->lock, context);
-
-       /* Disable PHY interrupt */
-       disable_phyirq(dev);
-
-       /* Disable MAC interrupts */
-       at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | 
AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-       rtnetif_stop_queue(dev);
-
-       clk_disable(lp->ether_clk);             /* Disable Peripheral clock */
-
-       rtdm_irq_free(&lp->irq_handle);
-
-       rt_stack_disconnect(dev);
-
-       return 0;
-}
-
+#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
 
-/*
- * Initialize the ethernet interface
- */
-static int at91ether_setup_rt(unsigned long phy_type, unsigned short 
phy_address,
-                       struct platform_device *pdev, struct clk *ether_clk)
+/* Detect MAC & PHY and perform ethernet interface initialization */
+static int __init at91ether_probe(struct platform_device *pdev)
 {
-       struct at91_eth_data *board_data = pdev->dev.platform_data;
+       struct macb_platform_data *board_data = dev_get_platdata(&pdev->dev);
+       struct resource *regs;
        struct rtnet_device *dev;
-       struct at91_private *lp;
-       unsigned int val;
-       struct resource *res;
-       int ret;
+       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 = rt_alloc_etherdev(sizeof(struct at91_private), MAX_RX_DESCR); /* 
RTnet */
+       dev = rt_alloc_etherdev(sizeof(struct macb), MAX_RX_DESCR * 2);
        if (!dev)
-         return -ENOMEM;
+               return -ENOMEM;
 
        rtdev_alloc_name(dev, "rteth%d");
        rt_rtdev_connect(dev, &RTDEV_manager);
        dev->vers = RTDEV_VERS_2_0;
 
-       /* Get I/O base address and IRQ */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               rtdev_free(dev); /* RTnet */
-               return -ENODEV;
-       }
-       dev->base_addr = res->start;
-       dev->irq = platform_get_irq(pdev, 0);
+       lp = rtnetdev_priv(dev);
+       lp->pdev = pdev;
+       lp->dev = dev;
+       rtdm_lock_init(&lp->lock);
 
-       /* Chun Yeow: Install the interrupt handler in device open routine */
+       /* 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;
+       }
 
-       /* Allocate memory for DMA Receive descriptors */
-       lp = dev->priv;
-       lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, 
sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
-       if (lp->dlist == NULL) {
-               rtdev_free(dev);
-               return -ENOMEM;
+       /* Clock */
+       lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+       if (IS_ERR(lp->pclk)) {
+               res = PTR_ERR(lp->pclk);
+               goto err_free_dev;
        }
-       lp->board_data = *board_data;
-       lp->ether_clk = ether_clk;
-       platform_set_drvdata(pdev, dev);
+       clk_enable(lp->pclk);
 
-       rtdm_lock_init(&lp->lock);
+       lp->hclk = ERR_PTR(-ENOENT);
+       lp->tx_clk = ERR_PTR(-ENOENT);
 
-       /*ether_setup(dev);*/
-       dev->open = at91ether_open_rt;
-       dev->stop = at91ether_close_rt;
-       dev->hard_start_xmit = at91ether_tx;
-       /*dev->get_stats = at91ether_stats;*/
-       /*dev->set_multicast_list = at91ether_set_rx_mode;*/
-       /*dev->set_mac_address = set_mac_address;*/
-       /*dev->ethtool_ops = &at91ether_ethtool_ops;*/
-       /*dev->do_ioctl = at91ether_ioctl_rt;*/
+       /* Install the interrupt handler */
+       dev->irq = platform_get_irq(pdev, 0);
+       res = rtdm_irq_request(&lp->irq_handle, dev->irq, at91ether_interrupt, 
0, dev->name, dev);
+       if (res)
+               goto err_disable_clock;
 
-       get_mac_address(dev);           /* Get ethernet address and store it in 
dev->dev_addr */
-       update_mac_address(dev);        /* Program ethernet address into MAC */
+       dev->open = at91ether_open;
+       dev->stop = at91ether_close;
+       dev->hard_start_xmit = at91ether_start_xmit;
+       dev->do_ioctl = rtmacb_ioctl;
+       dev->get_stats = rtmacb_get_stats;
 
-       at91_emac_write(AT91_EMAC_CTL, 0);
+       platform_set_drvdata(pdev, dev);
 
-       if (lp->board_data.is_rmii)
-               at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | 
AT91_EMAC_BIG | AT91_EMAC_RMII);
+       mac = of_get_mac_address(pdev->dev.of_node);
+       if (mac)
+               memcpy(lp->dev->dev_addr, mac, ETH_ALEN);
        else
-               at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | 
AT91_EMAC_BIG);
-
-       /* Perform PHY-specific initialization
-          Note: No need for locking, device IRQ sources are still off. */
-       enable_mdi();
-       if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-               read_phy(phy_address, MII_DSCR_REG, &val);
-               if ((val & (1 << 10)) == 0)                     /* DSCR bit 10 
is 0 -- fiber mode */
-                       lp->phy_media = PORT_FIBRE;
-       } else if (machine_is_csb337()) {
-               /* mix link activity status into LED2 link state */
-               write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
+               rtmacb_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;
        }
-       disable_mdi();
 
-       /*lp->mii.dev = dev;*/          /* Support for ethtool */
-       /*lp->mii.mdio_read = mdio_read;
-         lp->mii.mdio_write = mdio_write;*/
-       lp->mii.phy_id = phy_address;
-       lp->mii.phy_id_mask = 0x1f;
-       lp->mii.reg_num_mask = 0x1f;
+       macb_writel(lp, NCR, 0);
 
-       lp->phy_type = phy_type;        /* Type of PHY connected */
-       lp->phy_address = phy_address;  /* MDI address of PHY */
+       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
+       if (lp->phy_interface == PHY_INTERFACE_MODE_RMII)
+               reg |= MACB_BIT(RM9200_RMII);
 
-       /* Register the network interface */
-       ret = rt_register_rtnetdev(dev);
-       if (ret) {
-               rtdev_free(dev);
-               dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), 
lp->dlist, (dma_addr_t)lp->dlist_phys);
-               return ret;
-       }
-
-       /* Determine current link speed */
-       enable_mdi();
-       update_linkspeed(dev, 0);
-       disable_mdi();
-       rtnetif_carrier_off(dev);               /* will be enabled in open() */
-
-       /* If board has no PHY IRQ, use a timer to poll the PHY */
-       if (!lp->board_data.phy_irq_pin) {
-               init_timer(&lp->check_timer);
-               lp->check_timer.data = (unsigned long)dev;
-               lp->check_timer.function = at91ether_check_link;
-       }
+       macb_writel(lp, NCFGR, reg);
 
-       /* Display ethernet banner */
-       printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s 
(%02x:%02x:%02x:%02x:%02x:%02x)\n",
-               dev->name, (uint) dev->base_addr, dev->irq,
-               at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-               at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : 
"HalfDuplex",
-               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-       if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-               printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, 
(lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-       else if (phy_type == MII_LXT971A_ID)
-               printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-       else if (phy_type == MII_RTL8201_ID)
-               printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-       else if (phy_type == MII_BCM5221_ID)
-               printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-       else if (phy_type == MII_DP83847_ID)
-               printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", 
dev->name);
-       else if (phy_type == MII_AC101L_ID)
-               printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-       else if (phy_type == MII_KS8721_ID)
-               printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
+       /* Register the network interface */
+       res = rt_register_rtnetdev(dev);
+       if (res)
+               goto err_irq_free;
 
-       return 0;
+       res = rtmacb_mii_init(lp);
+       if (res)
+               goto err_out_unregister_netdev;
 
- err_out:
-       return ret;
-}
+       /* will be enabled in open() */
+       rtnetif_carrier_off(dev);
 
-/*
- * Detect MAC and PHY and perform initialization
- */
-static int at91ether_probe(struct platform_device *pdev)
-{
-       unsigned int phyid1, phyid2;
-       int detected = -1;
-       unsigned long phy_id;
-       unsigned short phy_address = 0;
-       struct clk *ether_clk;
-
-       ether_clk = clk_get(&pdev->dev, "ether_clk");
-       if (IS_ERR(ether_clk)) {
-               printk(KERN_ERR "at91_ether: no clock defined\n");
-               return -ENODEV;
-       }
-       clk_enable(ether_clk);                                  /* Enable 
Peripheral clock */
-
-       while ((detected != 0) && (phy_address < 32)) {
-               /* Read the PHY ID registers */
-               enable_mdi();
-               read_phy(phy_address, MII_PHYSID1, &phyid1);
-               read_phy(phy_address, MII_PHYSID2, &phyid2);
-               disable_mdi();
-
-               phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-               switch (phy_id) {
-                       case MII_DM9161_ID:             /* Davicom 9161: 
PHY_ID1 = 0x181, PHY_ID2 = B881 */
-                       case MII_DM9161A_ID:            /* Davicom 9161A: 
PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-                       case MII_LXT971A_ID:            /* Intel LXT971A: 
PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-                       case MII_RTL8201_ID:            /* Realtek RTL8201: 
PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-                       case MII_BCM5221_ID:            /* Broadcom BCM5221: 
PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-                       case MII_DP83847_ID:            /* National 
Semiconductor DP83847: */
-                       case MII_AC101L_ID:             /* Altima AC101L: 
PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-                       case MII_KS8721_ID:             /* Micrel KS8721: 
PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-                               detected = at91ether_setup_rt(phy_id, 
phy_address, pdev, ether_clk);
-                               break;
-               }
+       phydev = lp->phy_dev;
+       rtdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, 
irq=%d)\n",
+                               phydev->drv->name, dev_name(&phydev->dev),
+                               phydev->irq);
 
-               phy_address++;
-       }
+       /* Display ethernet banner */
+       rtdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n",
+                               dev->base_addr, dev->irq, dev->dev_addr);
 
-       clk_disable(ether_clk);                                 /* Disable 
Peripheral clock */
+       return 0;
 
-       return detected;
+err_out_unregister_netdev:
+       rt_unregister_rtnetdev(dev);
+err_irq_free:
+       rtdm_irq_free(&lp->irq_handle);
+err_disable_clock:
+       clk_disable(lp->pclk);
+err_free_dev:
+       rtdev_free(dev);
+       return res;
 }
 
 static int at91ether_remove(struct platform_device *pdev)
 {
        struct rtnet_device *dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = dev->priv;
+       struct macb *lp = rtnetdev_priv(dev);
 
-       rt_unregister_rtnetdev(dev);
+       if (lp->phy_dev)
+               phy_disconnect(lp->phy_dev);
+
+       mdiobus_unregister(lp->mii_bus);
+       if (lp->phy_phony_net_device)
+               free_netdev(lp->phy_phony_net_device);
+       kfree(lp->mii_bus->irq);
        rt_rtdev_disconnect(dev);
-       dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, 
(dma_addr_t)lp->dlist_phys);
-       clk_put(lp->ether_clk);
-       platform_set_drvdata(pdev, NULL);
+       rtdm_irq_free(&lp->irq_handle);
+       mdiobus_free(lp->mii_bus);
+       rt_unregister_rtnetdev(dev);
+       clk_disable(lp->pclk);
        rtdev_free(dev);
+
        return 0;
 }
 
 static struct platform_driver at91ether_driver = {
-       .probe          = at91ether_probe,
        .remove         = at91ether_remove,
        .driver         = {
-               .name   = DRV_NAME,
+               .name   = "at91_ether",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91ether_dt_ids),
        },
 };
 
-static int __init at91ether_init(void)
-{
-       return platform_driver_register(&at91ether_driver);
-}
-
-static void __exit at91ether_exit(void)
-{
-       platform_driver_unregister(&at91ether_driver);
-}
-
-module_init(at91ether_init)
-module_exit(at91ether_exit)
+module_platform_driver_probe(at91ether_driver, at91ether_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-MODULE_AUTHOR("RTDM Porting by Chun Yeow, Yeoh <yeohchuny...@gmail.com> 
Original Author Andrew Victor");
+MODULE_AUTHOR("Andrew Victor");
+MODULE_ALIAS("platform:at91_ether");
diff --git a/kernel/drivers/net/drivers/macb.c 
b/kernel/drivers/net/drivers/macb.c
index 8a606e4..e166db9 100644
--- a/kernel/drivers/net/drivers/macb.c
+++ b/kernel/drivers/net/drivers/macb.c
@@ -1783,7 +1783,20 @@ static struct platform_driver macb_driver = {
        },
 };
 
-module_platform_driver_probe(macb_driver, macb_probe);
+static bool found;
+static int __init macb_driver_init(void)
+{
+       found = platform_driver_probe(&macb_driver, macb_probe) == 0;
+       return 0;
+}
+module_init(macb_driver_init);
+
+static void __exit macb_driver_exit(void)
+{
+       if (found)
+               platform_driver_unregister(&macb_driver);
+}
+module_exit(macb_driver_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver");
diff --git a/kernel/drivers/net/drivers/rt_macb.h 
b/kernel/drivers/net/drivers/rt_macb.h
index dedf14a..bc69939 100644
--- a/kernel/drivers/net/drivers/rt_macb.h
+++ b/kernel/drivers/net/drivers/rt_macb.h
@@ -599,6 +599,11 @@ struct macb {
 
        struct net_device       *phy_phony_net_device;
        rtdm_irq_t              irq_handle;
+
+       /* AT91RM9200 transmit */
+       struct rtskb *skb;                      /* holds skb until xmit 
interrupt completes */
+       dma_addr_t skb_physaddr;                /* phys addr from 
pci_map_single */
+       int skb_length;                         /* saved skb length for 
pci_unmap_single */
 };
 
 extern const struct ethtool_ops macb_ethtool_ops;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to