Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / fec.c
index 682e7f0..28db691 100644 (file)
@@ -86,8 +86,7 @@ static unsigned char  fec_mac_default[] = {
 #endif
 #endif /* CONFIG_M5272 */
 
-/* Forward declarations of some structures to support different PHYs
-*/
+/* Forward declarations of some structures to support different PHYs */
 
 typedef struct {
        uint mii_data;
@@ -123,8 +122,7 @@ typedef struct {
 #error "FEC: descriptor ring size constants too large"
 #endif
 
-/* Interrupt events/masks.
-*/
+/* Interrupt events/masks. */
 #define FEC_ENET_HBERR ((uint)0x80000000)      /* Heartbeat error */
 #define FEC_ENET_BABR  ((uint)0x40000000)      /* Babbling receiver */
 #define FEC_ENET_BABT  ((uint)0x20000000)      /* Babbling transmitter */
@@ -165,7 +163,7 @@ typedef struct {
  */
 struct fec_enet_private {
        /* Hardware registers of the FEC device */
-       volatile fec_t  *hwp;
+       void __iomem *hwp;
 
        struct net_device *netdev;
 
@@ -174,16 +172,20 @@ struct fec_enet_private {
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        unsigned char *tx_bounce[TX_RING_SIZE];
        struct  sk_buff* tx_skbuff[TX_RING_SIZE];
+       struct  sk_buff* rx_skbuff[RX_RING_SIZE];
        ushort  skb_cur;
        ushort  skb_dirty;
 
-       /* CPM dual port RAM relative addresses.
-       */
+       /* CPM dual port RAM relative addresses */
        dma_addr_t      bd_dma;
-       cbd_t   *rx_bd_base;            /* Address of Rx and Tx buffers. */
-       cbd_t   *tx_bd_base;
-       cbd_t   *cur_rx, *cur_tx;               /* The next free ring entry */
-       cbd_t   *dirty_tx;      /* The ring entries to be free()ed. */
+       /* Address of Rx and Tx buffers */
+       struct bufdesc  *rx_bd_base;
+       struct bufdesc  *tx_bd_base;
+       /* The next free ring entry */
+       struct bufdesc  *cur_rx, *cur_tx; 
+       /* The ring entries to be free()ed */
+       struct bufdesc  *dirty_tx;
+
        uint    tx_full;
        /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
        spinlock_t hw_lock;
@@ -209,17 +211,13 @@ struct fec_enet_private {
        int     full_duplex;
 };
 
-static int fec_enet_open(struct net_device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void fec_enet_mii(struct net_device *dev);
 static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
 static int fec_enet_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
 static void fec_restart(struct net_device *dev, int duplex);
 static void fec_stop(struct net_device *dev);
-static void fec_set_mac_address(struct net_device *dev);
 
 
 /* MII processing.  We keep this as simple as possible.  Requests are
@@ -241,19 +239,16 @@ static mii_list_t *mii_tail;
 static int     mii_queue(struct net_device *dev, int request,
                                void (*func)(uint, struct net_device *));
 
-/* Make MII read/write commands for the FEC.
-*/
+/* Make MII read/write commands for the FEC */
 #define mk_mii_read(REG)       (0x60020000 | ((REG & 0x1f) << 18))
 #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
                                                (VAL & 0xffff))
 #define mk_mii_end     0
 
-/* Transmitter timeout.
-*/
-#define TX_TIMEOUT (2*HZ)
+/* Transmitter timeout */
+#define TX_TIMEOUT (2 * HZ)
 
-/* Register definitions for the PHY.
-*/
+/* Register definitions for the PHY */
 
 #define MII_REG_CR          0  /* Control Register                         */
 #define MII_REG_SR          1  /* Status Register                          */
@@ -288,15 +283,11 @@ static int        mii_queue(struct net_device *dev, int request,
 static int
 fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct fec_enet_private *fep;
-       volatile fec_t  *fecp;
-       volatile cbd_t  *bdp;
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
        unsigned short  status;
        unsigned long flags;
 
-       fep = netdev_priv(dev);
-       fecp = (volatile fec_t*)dev->base_addr;
-
        if (!fep->link) {
                /* Link is down or autonegotiation is in progress. */
                return 1;
@@ -307,7 +298,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        bdp = fep->cur_tx;
 
        status = bdp->cbd_sc;
-#ifndef final_version
+
        if (status & BD_ENET_TX_READY) {
                /* Ooops.  All transmit buffers are full.  Bail out.
                 * This should not happen, since dev->tbusy should be set.
@@ -316,21 +307,18 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
                spin_unlock_irqrestore(&fep->hw_lock, flags);
                return 1;
        }
-#endif
 
-       /* Clear all of the status flags.
-        */
+       /* Clear all of the status flags */
        status &= ~BD_ENET_TX_STATS;
 
-       /* Set buffer length and buffer pointer.
-       */
+       /* Set buffer length and buffer pointer */
        bdp->cbd_bufaddr = __pa(skb->data);
        bdp->cbd_datlen = skb->len;
 
        /*
-        *      On some FEC implementations data must be aligned on
-        *      4-byte boundaries. Use bounce buffers to copy data
-        *      and get it aligned. Ugh.
+        * On some FEC implementations data must be aligned on
+        * 4-byte boundaries. Use bounce buffers to copy data
+        * and get it aligned. Ugh.
         */
        if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
                unsigned int index;
@@ -339,8 +327,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
                bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
        }
 
-       /* Save skb pointer.
-       */
+       /* Save skb pointer */
        fep->tx_skbuff[fep->skb_cur] = skb;
 
        dev->stats.tx_bytes += skb->len;
@@ -349,13 +336,12 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Push the data cache so the CPM does not get stale memory
         * data.
         */
-       dma_sync_single(NULL, bdp->cbd_bufaddr,
-                       bdp->cbd_datlen, DMA_TO_DEVICE);
+       bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+                       FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
         */
-
        status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
                        | BD_ENET_TX_LAST | BD_ENET_TX_TC);
        bdp->cbd_sc = status;
@@ -363,22 +349,20 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        /* Trigger transmission start */
-       fecp->fec_x_des_active = 0;
+       writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       /* If this was the last BD in the ring, start at the beginning again.
-       */
-       if (status & BD_ENET_TX_WRAP) {
+       /* If this was the last BD in the ring, start at the beginning again. */
+       if (status & BD_ENET_TX_WRAP)
                bdp = fep->tx_bd_base;
-       } else {
+       else
                bdp++;
-       }
 
        if (bdp == fep->dirty_tx) {
                fep->tx_full = 1;
                netif_stop_queue(dev);
        }
 
-       fep->cur_tx = (cbd_t *)bdp;
+       fep->cur_tx = bdp;
 
        spin_unlock_irqrestore(&fep->hw_lock, flags);
 
@@ -390,75 +374,33 @@ fec_timeout(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
 
-       printk("%s: transmit timed out.\n", dev->name);
        dev->stats.tx_errors++;
-#ifndef final_version
-       {
-       int     i;
-       cbd_t   *bdp;
-
-       printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
-              (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
-              (unsigned long)fep->dirty_tx,
-              (unsigned long)fep->cur_rx);
-
-       bdp = fep->tx_bd_base;
-       printk(" tx: %u buffers\n",  TX_RING_SIZE);
-       for (i = 0 ; i < TX_RING_SIZE; i++) {
-               printk("  %08x: %04x %04x %08x\n",
-                      (uint) bdp,
-                      bdp->cbd_sc,
-                      bdp->cbd_datlen,
-                      (int) bdp->cbd_bufaddr);
-               bdp++;
-       }
 
-       bdp = fep->rx_bd_base;
-       printk(" rx: %lu buffers\n",  (unsigned long) RX_RING_SIZE);
-       for (i = 0 ; i < RX_RING_SIZE; i++) {
-               printk("  %08x: %04x %04x %08x\n",
-                      (uint) bdp,
-                      bdp->cbd_sc,
-                      bdp->cbd_datlen,
-                      (int) bdp->cbd_bufaddr);
-               bdp++;
-       }
-       }
-#endif
        fec_restart(dev, fep->full_duplex);
        netif_wake_queue(dev);
 }
 
-/* The interrupt handler.
- * This is called from the MPC core interrupt.
- */
 static irqreturn_t
 fec_enet_interrupt(int irq, void * dev_id)
 {
        struct  net_device *dev = dev_id;
-       volatile fec_t  *fecp;
+       struct fec_enet_private *fep = netdev_priv(dev);
        uint    int_events;
        irqreturn_t ret = IRQ_NONE;
 
-       fecp = (volatile fec_t*)dev->base_addr;
-
-       /* Get the interrupt events that caused us to be here.
-       */
        do {
-               int_events = fecp->fec_ievent;
-               fecp->fec_ievent = int_events;
+               int_events = readl(fep->hwp + FEC_IEVENT);
+               writel(int_events, fep->hwp + FEC_IEVENT);
 
-               /* Handle receive event in its own function.
-                */
                if (int_events & FEC_ENET_RXF) {
                        ret = IRQ_HANDLED;
                        fec_enet_rx(dev);
                }
 
                /* Transmit OK, or non-fatal error. Update the buffer
-                  descriptors. FEC handles all errors, we just discover
-                  them as part of the transmit process.
-               */
+                * descriptors. FEC handles all errors, we just discover
+                * them as part of the transmit process.
+                */
                if (int_events & FEC_ENET_TXF) {
                        ret = IRQ_HANDLED;
                        fec_enet_tx(dev);
@@ -479,7 +421,7 @@ static void
 fec_enet_tx(struct net_device *dev)
 {
        struct  fec_enet_private *fep;
-       volatile cbd_t  *bdp;
+       struct bufdesc *bdp;
        unsigned short status;
        struct  sk_buff *skb;
 
@@ -488,7 +430,11 @@ fec_enet_tx(struct net_device *dev)
        bdp = fep->dirty_tx;
 
        while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-               if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+               if (bdp == fep->cur_tx && fep->tx_full == 0)
+                       break;
+
+               dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
 
                skb = fep->tx_skbuff[fep->skb_dirty];
                /* Check for errors. */
@@ -510,31 +456,27 @@ fec_enet_tx(struct net_device *dev)
                        dev->stats.tx_packets++;
                }
 
-#ifndef final_version
                if (status & BD_ENET_TX_READY)
                        printk("HEY! Enet xmit interrupt and TX_READY.\n");
-#endif
+
                /* Deferred means some collisions occurred during transmit,
                 * but we eventually sent the packet OK.
                 */
                if (status & BD_ENET_TX_DEF)
                        dev->stats.collisions++;
 
-               /* Free the sk buffer associated with this last transmit.
-                */
+               /* Free the sk buffer associated with this last transmit */
                dev_kfree_skb_any(skb);
                fep->tx_skbuff[fep->skb_dirty] = NULL;
                fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
-               /* Update pointer to next buffer descriptor to be transmitted.
-                */
+               /* Update pointer to next buffer descriptor to be transmitted */
                if (status & BD_ENET_TX_WRAP)
                        bdp = fep->tx_bd_base;
                else
                        bdp++;
 
-               /* Since we have freed up a buffer, the ring is no longer
-                * full.
+               /* Since we have freed up a buffer, the ring is no longer full
                 */
                if (fep->tx_full) {
                        fep->tx_full = 0;
@@ -542,7 +484,7 @@ fec_enet_tx(struct net_device *dev)
                                netif_wake_queue(dev);
                }
        }
-       fep->dirty_tx = (cbd_t *)bdp;
+       fep->dirty_tx = bdp;
        spin_unlock_irq(&fep->hw_lock);
 }
 
@@ -555,9 +497,8 @@ fec_enet_tx(struct net_device *dev)
 static void
 fec_enet_rx(struct net_device *dev)
 {
-       struct  fec_enet_private *fep;
-       volatile fec_t  *fecp;
-       volatile cbd_t *bdp;
+       struct  fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
        unsigned short status;
        struct  sk_buff *skb;
        ushort  pkt_len;
@@ -567,9 +508,6 @@ fec_enet_rx(struct net_device *dev)
        flush_cache_all();
 #endif
 
-       fep = netdev_priv(dev);
-       fecp = (volatile fec_t*)dev->base_addr;
-
        spin_lock_irq(&fep->hw_lock);
 
        /* First, grab all of the stats for the incoming packet.
@@ -577,143 +515,121 @@ fec_enet_rx(struct net_device *dev)
         */
        bdp = fep->cur_rx;
 
-while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
+       while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
-#ifndef final_version
-       /* Since we have allocated space to hold a complete frame,
-        * the last indicator should be set.
-        */
-       if ((status & BD_ENET_RX_LAST) == 0)
-               printk("FEC ENET: rcv is not +last\n");
-#endif
+               /* Since we have allocated space to hold a complete frame,
+                * the last indicator should be set.
+                */
+               if ((status & BD_ENET_RX_LAST) == 0)
+                       printk("FEC ENET: rcv is not +last\n");
 
-       if (!fep->opened)
-               goto rx_processing_done;
+               if (!fep->opened)
+                       goto rx_processing_done;
 
-       /* Check for errors. */
-       if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+               /* Check for errors. */
+               if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
                           BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-               dev->stats.rx_errors++;
-               if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
-               /* Frame too long or too short. */
-                       dev->stats.rx_length_errors++;
+                       dev->stats.rx_errors++;
+                       if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+                               /* Frame too long or too short. */
+                               dev->stats.rx_length_errors++;
+                       }
+                       if (status & BD_ENET_RX_NO)     /* Frame alignment */
+                               dev->stats.rx_frame_errors++;
+                       if (status & BD_ENET_RX_CR)     /* CRC Error */
+                               dev->stats.rx_crc_errors++;
+                       if (status & BD_ENET_RX_OV)     /* FIFO overrun */
+                               dev->stats.rx_fifo_errors++;
                }
-               if (status & BD_ENET_RX_NO)     /* Frame alignment */
+
+               /* Report late collisions as a frame error.
+                * On this error, the BD is closed, but we don't know what we
+                * have in the buffer.  So, just drop this frame on the floor.
+                */
+               if (status & BD_ENET_RX_CL) {
+                       dev->stats.rx_errors++;
                        dev->stats.rx_frame_errors++;
-               if (status & BD_ENET_RX_CR)     /* CRC Error */
-                       dev->stats.rx_crc_errors++;
-               if (status & BD_ENET_RX_OV)     /* FIFO overrun */
-                       dev->stats.rx_fifo_errors++;
-       }
+                       goto rx_processing_done;
+               }
 
-       /* Report late collisions as a frame error.
-        * On this error, the BD is closed, but we don't know what we
-        * have in the buffer.  So, just drop this frame on the floor.
-        */
-       if (status & BD_ENET_RX_CL) {
-               dev->stats.rx_errors++;
-               dev->stats.rx_frame_errors++;
-               goto rx_processing_done;
-       }
+               /* Process the incoming frame. */
+               dev->stats.rx_packets++;
+               pkt_len = bdp->cbd_datlen;
+               dev->stats.rx_bytes += pkt_len;
+               data = (__u8*)__va(bdp->cbd_bufaddr);
 
-       /* Process the incoming frame.
-        */
-       dev->stats.rx_packets++;
-       pkt_len = bdp->cbd_datlen;
-       dev->stats.rx_bytes += pkt_len;
-       data = (__u8*)__va(bdp->cbd_bufaddr);
-
-       dma_sync_single(NULL, (unsigned long)__pa(data),
-                       pkt_len - 4, DMA_FROM_DEVICE);
-
-       /* This does 16 byte alignment, exactly what we need.
-        * The packet length includes FCS, but we don't want to
-        * include that when passing upstream as it messes up
-        * bridging applications.
-        */
-       skb = dev_alloc_skb(pkt_len-4);
+               dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
+                               DMA_FROM_DEVICE);
 
-       if (skb == NULL) {
-               printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-               dev->stats.rx_dropped++;
-       } else {
-               skb_put(skb,pkt_len-4); /* Make room */
-               skb_copy_to_linear_data(skb, data, pkt_len-4);
-               skb->protocol=eth_type_trans(skb,dev);
-               netif_rx(skb);
-       }
-  rx_processing_done:
+               /* This does 16 byte alignment, exactly what we need.
+                * The packet length includes FCS, but we don't want to
+                * include that when passing upstream as it messes up
+                * bridging applications.
+                */
+               skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
 
-       /* Clear the status flags for this buffer.
-       */
-       status &= ~BD_ENET_RX_STATS;
+               if (unlikely(!skb)) {
+                       printk("%s: Memory squeeze, dropping packet.\n",
+                                       dev->name);
+                       dev->stats.rx_dropped++;
+               } else {
+                       skb_reserve(skb, NET_IP_ALIGN);
+                       skb_put(skb, pkt_len - 4);      /* Make room */
+                       skb_copy_to_linear_data(skb, data, pkt_len - 4);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
+               }
 
-       /* Mark the buffer empty.
-       */
-       status |= BD_ENET_RX_EMPTY;
-       bdp->cbd_sc = status;
+               bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
+                       DMA_FROM_DEVICE);
+rx_processing_done:
+               /* Clear the status flags for this buffer */
+               status &= ~BD_ENET_RX_STATS;
 
-       /* Update BD pointer to next entry.
-       */
-       if (status & BD_ENET_RX_WRAP)
-               bdp = fep->rx_bd_base;
-       else
-               bdp++;
+               /* Mark the buffer empty */
+               status |= BD_ENET_RX_EMPTY;
+               bdp->cbd_sc = status;
 
-#if 1
-       /* Doing this here will keep the FEC running while we process
-        * incoming frames.  On a heavily loaded network, we should be
-        * able to keep up at the expense of system resources.
-        */
-       fecp->fec_r_des_active = 0;
-#endif
-   } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
-       fep->cur_rx = (cbd_t *)bdp;
-
-#if 0
-       /* Doing this here will allow us to process all frames in the
-        * ring before the FEC is allowed to put more there.  On a heavily
-        * loaded network, some frames may be lost.  Unfortunately, this
-        * increases the interrupt overhead since we can potentially work
-        * our way back to the interrupt return only to come right back
-        * here.
-        */
-       fecp->fec_r_des_active = 0;
-#endif
+               /* Update BD pointer to next entry */
+               if (status & BD_ENET_RX_WRAP)
+                       bdp = fep->rx_bd_base;
+               else
+                       bdp++;
+               /* Doing this here will keep the FEC running while we process
+                * incoming frames.  On a heavily loaded network, we should be
+                * able to keep up at the expense of system resources.
+                */
+               writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+       }
+       fep->cur_rx = bdp;
 
        spin_unlock_irq(&fep->hw_lock);
 }
 
-
 /* called from interrupt context */
 static void
 fec_enet_mii(struct net_device *dev)
 {
        struct  fec_enet_private *fep;
-       volatile fec_t  *ep;
        mii_list_t      *mip;
-       uint            mii_reg;
 
        fep = netdev_priv(dev);
        spin_lock_irq(&fep->mii_lock);
 
-       ep = fep->hwp;
-       mii_reg = ep->fec_mii_data;
-
        if ((mip = mii_head) == NULL) {
                printk("MII and no head!\n");
                goto unlock;
        }
 
        if (mip->mii_func != NULL)
-               (*(mip->mii_func))(mii_reg, dev);
+               (*(mip->mii_func))(readl(fep->hwp + FEC_MII_DATA), dev);
 
        mii_head = mip->mii_next;
        mip->mii_next = mii_free;
        mii_free = mip;
 
        if ((mip = mii_head) != NULL)
-               ep->fec_mii_data = mip->mii_regval;
+               writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
 
 unlock:
        spin_unlock_irq(&fep->mii_lock);
@@ -727,8 +643,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
        mii_list_t      *mip;
        int             retval;
 
-       /* Add PHY address to register command.
-       */
+       /* Add PHY address to register command */
        fep = netdev_priv(dev);
        spin_lock_irqsave(&fep->mii_lock, flags);
 
@@ -745,7 +660,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
                        mii_tail = mip;
                } else {
                        mii_head = mii_tail = mip;
-                       fep->hwp->fec_mii_data = regval;
+                       writel(regval, fep->hwp + FEC_MII_DATA);
                }
        } else {
                retval = 1;
@@ -1246,11 +1161,8 @@ static void __inline__ fec_phy_ack_intr(void)
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       volatile fec_t *fecp;
        unsigned char *iap, tmpaddr[ETH_ALEN];
 
-       fecp = fep->hwp;
-
        if (FEC_FLASHMAC) {
                /*
                 * Get MAC address from FLASH.
@@ -1264,8 +1176,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
                        iap = fec_mac_default;
        } else {
-               *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
-               *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
+               *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW);
+               *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
                iap = &tmpaddr[0];
        }
 
@@ -1375,11 +1287,6 @@ static void mii_relink(struct work_struct *work)
                fec_restart(dev, duplex);
        } else
                fec_stop(dev);
-
-#if 0
-       enable_irq(fep->mii_irq);
-#endif
-
 }
 
 /* mii_queue_relink is called in interrupt context from mii_link_interrupt */
@@ -1388,12 +1295,12 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
        struct fec_enet_private *fep = netdev_priv(dev);
 
        /*
-       ** We cannot queue phy_task twice in the workqueue.  It
-       ** would cause an endless loop in the workqueue.
-       ** Fortunately, if the last mii_relink entry has not yet been
-       ** executed now, it will do the job for the current interrupt,
-       ** which is just what we want.
-       */
+        * We cannot queue phy_task twice in the workqueue.  It
+        * would cause an endless loop in the workqueue.
+        * Fortunately, if the last mii_relink entry has not yet been
+        * executed now, it will do the job for the current interrupt,
+        * which is just what we want.
+        */
        if (fep->mii_phy_task_queued)
                return;
 
@@ -1424,8 +1331,7 @@ phy_cmd_t const phy_cmd_config[] = {
        { mk_mii_end, }
        };
 
-/* Read remainder of PHY ID.
-*/
+/* Read remainder of PHY ID. */
 static void
 mii_discover_phy3(uint mii_reg, struct net_device *dev)
 {
@@ -1457,17 +1363,14 @@ static void
 mii_discover_phy(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep;
-       volatile fec_t *fecp;
        uint phytype;
 
        fep = netdev_priv(dev);
-       fecp = fep->hwp;
 
        if (fep->phy_addr < 32) {
                if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) {
 
-                       /* Got first part of ID, now get remainder.
-                       */
+                       /* Got first part of ID, now get remainder */
                        fep->phy_id = phytype << 16;
                        mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
                                                        mii_discover_phy3);
@@ -1479,15 +1382,15 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
        } else {
                printk("FEC: No PHY device found.\n");
                /* Disable external MII interface */
-               fecp->fec_mii_speed = fep->phy_speed = 0;
+               writel(0, fep->hwp + FEC_MII_SPEED);
+               fep->phy_speed = 0;
 #ifdef HAVE_mii_link_interrupt
                fec_disable_phy_intr();
 #endif
        }
 }
 
-/* This interrupt occurs when the PHY detects a link change.
-*/
+/* This interrupt occurs when the PHY detects a link change */
 #ifdef HAVE_mii_link_interrupt
 static irqreturn_t
 mii_link_interrupt(int irq, void * dev_id)
@@ -1497,10 +1400,6 @@ mii_link_interrupt(int irq, void * dev_id)
 
        fec_phy_ack_intr();
 
-#if 0
-       disable_irq(fep->mii_irq);  /* disable now, enable later */
-#endif
-
        mii_do_cmd(dev, fep->phy->ack_int);
        mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
 
@@ -1508,19 +1407,91 @@ mii_link_interrupt(int irq, void * dev_id)
 }
 #endif
 
+static void fec_enet_free_buffers(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       int i;
+       struct sk_buff *skb;
+       struct bufdesc  *bdp;
+
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               skb = fep->rx_skbuff[i];
+
+               if (bdp->cbd_bufaddr)
+                       dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+                                       FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+               if (skb)
+                       dev_kfree_skb(skb);
+               bdp++;
+       }
+
+       bdp = fep->tx_bd_base;
+       for (i = 0; i < TX_RING_SIZE; i++)
+               kfree(fep->tx_bounce[i]);
+}
+
+static int fec_enet_alloc_buffers(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       int i;
+       struct sk_buff *skb;
+       struct bufdesc  *bdp;
+
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+               if (!skb) {
+                       fec_enet_free_buffers(dev);
+                       return -ENOMEM;
+               }
+               fep->rx_skbuff[i] = skb;
+
+               bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+                               FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+               bdp->cbd_sc = BD_ENET_RX_EMPTY;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap. */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       bdp = fep->tx_bd_base;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+
+               bdp->cbd_sc = 0;
+               bdp->cbd_bufaddr = 0;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap. */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       return 0;
+}
+
 static int
 fec_enet_open(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
+       int ret;
 
        /* I should reset the ring buffers here, but I don't yet know
         * a simple way to do that.
         */
-       fec_set_mac_address(dev);
+
+       ret = fec_enet_alloc_buffers(dev);
+       if (ret)
+               return ret;
 
        fep->sequence_done = 0;
        fep->link = 0;
 
+       fec_restart(dev, 1);
+
        if (fep->phy) {
                mii_do_cmd(dev, fep->phy->ack_int);
                mii_do_cmd(dev, fep->phy->config);
@@ -1537,21 +1508,17 @@ fec_enet_open(struct net_device *dev)
                        schedule();
 
                mii_do_cmd(dev, fep->phy->startup);
-
-               /* Set the initial link state to true. A lot of hardware
-                * based on this device does not implement a PHY interrupt,
-                * so we are never notified of link change.
-                */
-               fep->link = 1;
-       } else {
-               fep->link = 1; /* lets just try it and see */
-               /* no phy,  go full duplex,  it's most likely a hub chip */
-               fec_restart(dev, 1);
        }
 
+       /* Set the initial link state to true. A lot of hardware
+        * based on this device does not implement a PHY interrupt,
+        * so we are never notified of link change.
+        */
+       fep->link = 1;
+
        netif_start_queue(dev);
        fep->opened = 1;
-       return 0;               /* Success */
+       return 0;
 }
 
 static int
@@ -1559,12 +1526,13 @@ fec_enet_close(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
 
-       /* Don't know what to do yet.
-       */
+       /* Don't know what to do yet. */
        fep->opened = 0;
        netif_stop_queue(dev);
        fec_stop(dev);
 
+        fec_enet_free_buffers(dev);
+
        return 0;
 }
 
@@ -1583,87 +1551,102 @@ fec_enet_close(struct net_device *dev)
 
 static void set_multicast_list(struct net_device *dev)
 {
-       struct fec_enet_private *fep;
-       volatile fec_t *ep;
+       struct fec_enet_private *fep = netdev_priv(dev);
        struct dev_mc_list *dmi;
-       unsigned int i, j, bit, data, crc;
+       unsigned int i, j, bit, data, crc, tmp;
        unsigned char hash;
 
-       fep = netdev_priv(dev);
-       ep = fep->hwp;
+       if (dev->flags & IFF_PROMISC) {
+               tmp = readl(fep->hwp + FEC_R_CNTRL);
+               tmp |= 0x8;
+               writel(tmp, fep->hwp + FEC_R_CNTRL);
+               return;
+       }
 
-       if (dev->flags&IFF_PROMISC) {
-               ep->fec_r_cntrl |= 0x0008;
-       } else {
+       tmp = readl(fep->hwp + FEC_R_CNTRL);
+       tmp &= ~0x8;
+       writel(tmp, fep->hwp + FEC_R_CNTRL);
+
+       if (dev->flags & IFF_ALLMULTI) {
+               /* Catch all multicast addresses, so set the
+                * filter to all 1's
+                */
+               writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+               writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-               ep->fec_r_cntrl &= ~0x0008;
+               return;
+       }
 
-               if (dev->flags & IFF_ALLMULTI) {
-                       /* Catch all multicast addresses, so set the
-                        * filter to all 1's.
-                        */
-                       ep->fec_grp_hash_table_high = 0xffffffff;
-                       ep->fec_grp_hash_table_low = 0xffffffff;
-               } else {
-                       /* Clear filter and add the addresses in hash register.
-                       */
-                       ep->fec_grp_hash_table_high = 0;
-                       ep->fec_grp_hash_table_low = 0;
-
-                       dmi = dev->mc_list;
-
-                       for (j = 0; j < dev->mc_count; j++, dmi = dmi->next)
-                       {
-                               /* Only support group multicast for now.
-                               */
-                               if (!(dmi->dmi_addr[0] & 1))
-                                       continue;
-
-                               /* calculate crc32 value of mac address
-                               */
-                               crc = 0xffffffff;
-
-                               for (i = 0; i < dmi->dmi_addrlen; i++)
-                               {
-                                       data = dmi->dmi_addr[i];
-                                       for (bit = 0; bit < 8; bit++, data >>= 1)
-                                       {
-                                               crc = (crc >> 1) ^
-                                               (((crc ^ data) & 1) ? CRC32_POLY : 0);
-                                       }
-                               }
-
-                               /* only upper 6 bits (HASH_BITS) are used
-                                  which point to specific bit in he hash registers
-                               */
-                               hash = (crc >> (32 - HASH_BITS)) & 0x3f;
-
-                               if (hash > 31)
-                                       ep->fec_grp_hash_table_high |= 1 << (hash - 32);
-                               else
-                                       ep->fec_grp_hash_table_low |= 1 << hash;
+       /* Clear filter and add the addresses in hash register
+        */
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+       dmi = dev->mc_list;
+
+       for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
+               /* Only support group multicast for now */
+               if (!(dmi->dmi_addr[0] & 1))
+                       continue;
+
+               /* calculate crc32 value of mac address */
+               crc = 0xffffffff;
+
+               for (i = 0; i < dmi->dmi_addrlen; i++) {
+                       data = dmi->dmi_addr[i];
+                       for (bit = 0; bit < 8; bit++, data >>= 1) {
+                               crc = (crc >> 1) ^
+                               (((crc ^ data) & 1) ? CRC32_POLY : 0);
                        }
                }
+
+               /* only upper 6 bits (HASH_BITS) are used
+                * which point to specific bit in he hash registers
+                */
+               hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+
+               if (hash > 31) {
+                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+                       tmp |= 1 << (hash - 32);
+                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+               } else {
+                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+                       tmp |= 1 << hash;
+                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+               }
        }
 }
 
-/* Set a MAC change in hardware.
- */
-static void
-fec_set_mac_address(struct net_device *dev)
+/* Set a MAC change in hardware. */
+static int
+fec_set_mac_address(struct net_device *dev, void *p)
 {
-       volatile fec_t *fecp;
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct sockaddr *addr = p;
 
-       fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
 
-       /* Set station address. */
-       fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-               (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
-       fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
-               (dev->dev_addr[4] << 24);
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
+       writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+               (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
+               fep->hwp + FEC_ADDR_LOW);
+       writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
+               fep + FEC_ADDR_HIGH);
+       return 0;
 }
 
+static const struct net_device_ops fec_netdev_ops = {
+       .ndo_open               = fec_enet_open,
+       .ndo_stop               = fec_enet_close,
+       .ndo_start_xmit         = fec_enet_start_xmit,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_tx_timeout         = fec_timeout,
+       .ndo_set_mac_address    = fec_set_mac_address,
+};
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
@@ -1672,17 +1655,13 @@ fec_set_mac_address(struct net_device *dev)
 int __init fec_enet_init(struct net_device *dev, int index)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       unsigned long   mem_addr;
-       volatile cbd_t  *bdp;
-       cbd_t           *cbd_base;
-       volatile fec_t  *fecp;
-       int             i, j;
+       struct bufdesc *cbd_base;
+       int i;
 
-       /* Allocate memory for buffer descriptors.
-       */
-       mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE,
-                       &fep->bd_dma, GFP_KERNEL);
-       if (mem_addr == 0) {
+       /* Allocate memory for buffer descriptors. */
+       cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
+                       GFP_KERNEL);
+       if (!cbd_base) {
                printk("FEC: allocate descriptor memory failed?\n");
                return -ENOMEM;
        }
@@ -1690,146 +1669,47 @@ int __init fec_enet_init(struct net_device *dev, int index)
        spin_lock_init(&fep->hw_lock);
        spin_lock_init(&fep->mii_lock);
 
-       /* Create an Ethernet device instance.
-       */
-       fecp = (volatile fec_t *)dev->base_addr;
-
        fep->index = index;
-       fep->hwp = fecp;
+       fep->hwp = (void __iomem *)dev->base_addr;
        fep->netdev = dev;
 
-       /* Whack a reset.  We should wait for this.
-       */
-       fecp->fec_ecntrl = 1;
-       udelay(10);
-
        /* Set the Ethernet address */
 #ifdef CONFIG_M5272
        fec_get_mac(dev);
 #else
        {
                unsigned long l;
-               l = fecp->fec_addr_low;
+               l = readl(fep->hwp + FEC_ADDR_LOW);
                dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
                dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
                dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
                dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
-               l = fecp->fec_addr_high;
+               l = readl(fep->hwp + FEC_ADDR_HIGH);
                dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
                dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
        }
 #endif
 
-       cbd_base = (cbd_t *)mem_addr;
-
-       /* Set receive and transmit descriptor base.
-       */
+       /* Set receive and transmit descriptor base. */
        fep->rx_bd_base = cbd_base;
        fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
-       fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
-       fep->cur_rx = fep->rx_bd_base;
-
-       fep->skb_cur = fep->skb_dirty = 0;
-
-       /* Initialize the receive buffer descriptors.
-       */
-       bdp = fep->rx_bd_base;
-       for (i=0; i<FEC_ENET_RX_PAGES; i++) {
-
-               /* Allocate a page.
-               */
-               mem_addr = __get_free_page(GFP_KERNEL);
-               /* XXX: missing check for allocation failure */
-
-               /* Initialize the BD for every fragment in the page.
-               */
-               for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
-                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
-                       bdp->cbd_bufaddr = __pa(mem_addr);
-                       mem_addr += FEC_ENET_RX_FRSIZE;
-                       bdp++;
-               }
-       }
-
-       /* Set the last buffer to wrap.
-       */
-       bdp--;
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmmit.
-       */
-       bdp = fep->tx_bd_base;
-       for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
-               if (j >= FEC_ENET_TX_FRPPG) {
-                       mem_addr = __get_free_page(GFP_KERNEL);
-                       j = 1;
-               } else {
-                       mem_addr += FEC_ENET_TX_FRSIZE;
-                       j++;
-               }
-               fep->tx_bounce[i] = (unsigned char *) mem_addr;
-
-               /* Initialize the BD for every fragment in the page.
-               */
-               bdp->cbd_sc = 0;
-               bdp->cbd_bufaddr = 0;
-               bdp++;
-       }
-
-       /* Set the last buffer to wrap.
-       */
-       bdp--;
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* Set receive and transmit descriptor base.
-       */
-       fecp->fec_r_des_start = fep->bd_dma;
-       fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-                               * RX_RING_SIZE;
-
 #ifdef HAVE_mii_link_interrupt
        fec_request_mii_intr(dev);
 #endif
-
-       fecp->fec_grp_hash_table_high = 0;
-       fecp->fec_grp_hash_table_low = 0;
-       fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
-       fecp->fec_ecntrl = 2;
-       fecp->fec_r_des_active = 0;
-#ifndef CONFIG_M5272
-       fecp->fec_hash_table_high = 0;
-       fecp->fec_hash_table_low = 0;
-#endif
-
-       /* The FEC Ethernet specific entries in the device structure. */
-       dev->open = fec_enet_open;
-       dev->hard_start_xmit = fec_enet_start_xmit;
-       dev->tx_timeout = fec_timeout;
+       /* The FEC Ethernet specific entries in the device structure */
        dev->watchdog_timeo = TX_TIMEOUT;
-       dev->stop = fec_enet_close;
-       dev->set_multicast_list = set_multicast_list;
+       dev->netdev_ops = &fec_netdev_ops;
 
        for (i=0; i<NMII-1; i++)
                mii_cmds[i].mii_next = &mii_cmds[i+1];
        mii_free = mii_cmds;
 
-       /* setup MII interface */
-       fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
-       fecp->fec_x_cntrl = 0x00;
-
-       /*
-        * Set MII speed to 2.5 MHz
-        */
+       /* Set MII speed to 2.5 MHz */
        fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
                                        / 2500000) / 2) & 0x3F) << 1;
-       fecp->fec_mii_speed = fep->phy_speed;
        fec_restart(dev, 0);
 
-       /* Clear and enable interrupts */
-       fecp->fec_ievent = 0xffc00000;
-       fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
-
        /* Queue up command to detect the PHY and initialize the
         * remainder of the interface.
         */
@@ -1847,145 +1727,118 @@ int __init fec_enet_init(struct net_device *dev, int index)
 static void
 fec_restart(struct net_device *dev, int duplex)
 {
-       struct fec_enet_private *fep;
-       volatile cbd_t *bdp;
-       volatile fec_t *fecp;
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
        int i;
 
-       fep = netdev_priv(dev);
-       fecp = fep->hwp;
-
-       /* Whack a reset.  We should wait for this.
-       */
-       fecp->fec_ecntrl = 1;
+       /* Whack a reset.  We should wait for this. */
+       writel(1, fep->hwp + FEC_ECNTRL);
        udelay(10);
 
-       /* Clear any outstanding interrupt.
-       */
-       fecp->fec_ievent = 0xffc00000;
+       /* Clear any outstanding interrupt. */
+       writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-       /* Set station address.
-       */
-       fec_set_mac_address(dev);
+       /* Reset all multicast. */
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+#ifndef CONFIG_M5272
+       writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
 
-       /* Reset all multicast.
-       */
-       fecp->fec_grp_hash_table_high = 0;
-       fecp->fec_grp_hash_table_low = 0;
+       /* Set maximum receive buffer size. */
+       writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
-       /* Set maximum receive buffer size.
-       */
-       fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
-
-       /* Set receive and transmit descriptor base.
-       */
-       fecp->fec_r_des_start = fep->bd_dma;
-       fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-                               * RX_RING_SIZE;
+       /* Set receive and transmit descriptor base. */
+       writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
+       writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
+                       fep->hwp + FEC_X_DES_START);
 
        fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
        fep->cur_rx = fep->rx_bd_base;
 
-       /* Reset SKB transmit buffers.
-       */
+       /* Reset SKB transmit buffers. */
        fep->skb_cur = fep->skb_dirty = 0;
-       for (i=0; i<=TX_RING_MOD_MASK; i++) {
-               if (fep->tx_skbuff[i] != NULL) {
+       for (i = 0; i <= TX_RING_MOD_MASK; i++) {
+               if (fep->tx_skbuff[i]) {
                        dev_kfree_skb_any(fep->tx_skbuff[i]);
                        fep->tx_skbuff[i] = NULL;
                }
        }
 
-       /* Initialize the receive buffer descriptors.
-       */
+       /* Initialize the receive buffer descriptors. */
        bdp = fep->rx_bd_base;
-       for (i=0; i<RX_RING_SIZE; i++) {
+       for (i = 0; i < RX_RING_SIZE; i++) {
 
-               /* Initialize the BD for every fragment in the page.
-               */
+               /* Initialize the BD for every fragment in the page. */
                bdp->cbd_sc = BD_ENET_RX_EMPTY;
                bdp++;
        }
 
-       /* Set the last buffer to wrap.
-       */
+       /* Set the last buffer to wrap */
        bdp--;
        bdp->cbd_sc |= BD_SC_WRAP;
 
-       /* ...and the same for transmmit.
-       */
+       /* ...and the same for transmit */
        bdp = fep->tx_bd_base;
-       for (i=0; i<TX_RING_SIZE; i++) {
+       for (i = 0; i < TX_RING_SIZE; i++) {
 
-               /* Initialize the BD for every fragment in the page.
-               */
+               /* Initialize the BD for every fragment in the page. */
                bdp->cbd_sc = 0;
                bdp->cbd_bufaddr = 0;
                bdp++;
        }
 
-       /* Set the last buffer to wrap.
-       */
+       /* Set the last buffer to wrap */
        bdp--;
        bdp->cbd_sc |= BD_SC_WRAP;
 
-       /* Enable MII mode.
-       */
+       /* Enable MII mode */
        if (duplex) {
-               fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */
-               fecp->fec_x_cntrl = 0x04;                 /* FD enable */
+               /* MII enable / FD enable */
+               writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
+               writel(0x04, fep->hwp + FEC_X_CNTRL);
        } else {
-               /* MII enable|No Rcv on Xmit */
-               fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06;
-               fecp->fec_x_cntrl = 0x00;
+               /* MII enable / No Rcv on Xmit */
+               writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
+               writel(0x0, fep->hwp + FEC_X_CNTRL);
        }
        fep->full_duplex = duplex;
 
-       /* Set MII speed.
-       */
-       fecp->fec_mii_speed = fep->phy_speed;
+       /* Set MII speed */
+       writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
-       /* And last, enable the transmit and receive processing.
-       */
-       fecp->fec_ecntrl = 2;
-       fecp->fec_r_des_active = 0;
+       /* And last, enable the transmit and receive processing */
+       writel(2, fep->hwp + FEC_ECNTRL);
+       writel(0, fep->hwp + FEC_R_DES_ACTIVE);
 
-       /* Enable interrupts we wish to service.
-       */
-       fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
+       /* Enable interrupts we wish to service */
+       writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
+                       fep->hwp + FEC_IMASK);
 }
 
 static void
 fec_stop(struct net_device *dev)
 {
-       volatile fec_t *fecp;
-       struct fec_enet_private *fep;
-
-       fep = netdev_priv(dev);
-       fecp = fep->hwp;
+       struct fec_enet_private *fep = netdev_priv(dev);
 
-       /*
-       ** We cannot expect a graceful transmit stop without link !!!
-       */
-       if (fep->link)
-               {
-               fecp->fec_x_cntrl = 0x01;       /* Graceful transmit stop */
+       /* We cannot expect a graceful transmit stop without link !!! */
+       if (fep->link) {
+               writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
                udelay(10);
-               if (!(fecp->fec_ievent & FEC_ENET_GRA))
+               if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
                        printk("fec_stop : Graceful transmit stop did not complete !\n");
-               }
+       }
 
-       /* Whack a reset.  We should wait for this.
-       */
-       fecp->fec_ecntrl = 1;
+       /* Whack a reset.  We should wait for this. */
+       writel(1, fep->hwp + FEC_ECNTRL);
        udelay(10);
 
-       /* Clear outstanding MII command interrupts.
-       */
-       fecp->fec_ievent = FEC_ENET_MII;
+       /* Clear outstanding MII command interrupts. */
+       writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
 
-       fecp->fec_imask = FEC_ENET_MII;
-       fecp->fec_mii_speed = fep->phy_speed;
+       writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+       writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 }
 
 static int __devinit