ARM: 6124/1: ep93xx: SPI driver platform support code
[safe/jmp/linux-2.6] / drivers / net / fec.c
index e3d99fe..9f98c1c 100644 (file)
@@ -285,6 +285,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct bufdesc *bdp;
+       void *bufaddr;
        unsigned short  status;
        unsigned long flags;
 
@@ -312,7 +313,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        status &= ~BD_ENET_TX_STATS;
 
        /* Set buffer length and buffer pointer */
-       bdp->cbd_bufaddr = __pa(skb->data);
+       bufaddr = skb->data;
        bdp->cbd_datlen = skb->len;
 
        /*
@@ -320,11 +321,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * 4-byte boundaries. Use bounce buffers to copy data
         * and get it aligned. Ugh.
         */
-       if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+       if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
                unsigned int index;
                index = bdp - fep->tx_bd_base;
                memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
-               bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+               bufaddr = fep->tx_bounce[index];
        }
 
        /* Save skb pointer */
@@ -336,7 +337,7 @@ 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.
         */
-       bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+       bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
                        FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
@@ -426,7 +427,7 @@ fec_enet_tx(struct net_device *dev)
        struct  sk_buff *skb;
 
        fep = netdev_priv(dev);
-       spin_lock_irq(&fep->hw_lock);
+       spin_lock(&fep->hw_lock);
        bdp = fep->dirty_tx;
 
        while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
@@ -485,7 +486,7 @@ fec_enet_tx(struct net_device *dev)
                }
        }
        fep->dirty_tx = bdp;
-       spin_unlock_irq(&fep->hw_lock);
+       spin_unlock(&fep->hw_lock);
 }
 
 
@@ -508,7 +509,7 @@ fec_enet_rx(struct net_device *dev)
        flush_cache_all();
 #endif
 
-       spin_lock_irq(&fep->hw_lock);
+       spin_lock(&fep->hw_lock);
 
        /* First, grab all of the stats for the incoming packet.
         * These get messed up if we get called due to a busy condition.
@@ -603,7 +604,7 @@ rx_processing_done:
        }
        fep->cur_rx = bdp;
 
-       spin_unlock_irq(&fep->hw_lock);
+       spin_unlock(&fep->hw_lock);
 }
 
 /* called from interrupt context */
@@ -614,7 +615,7 @@ fec_enet_mii(struct net_device *dev)
        mii_list_t      *mip;
 
        fep = netdev_priv(dev);
-       spin_lock_irq(&fep->mii_lock);
+       spin_lock(&fep->mii_lock);
 
        if ((mip = mii_head) == NULL) {
                printk("MII and no head!\n");
@@ -632,20 +633,19 @@ fec_enet_mii(struct net_device *dev)
                writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
 
 unlock:
-       spin_unlock_irq(&fep->mii_lock);
+       spin_unlock(&fep->mii_lock);
 }
 
 static int
-mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+mii_queue_unlocked(struct net_device *dev, int regval,
+               void (*func)(uint, struct net_device *))
 {
        struct fec_enet_private *fep;
-       unsigned long   flags;
        mii_list_t      *mip;
        int             retval;
 
        /* Add PHY address to register command */
        fep = netdev_priv(dev);
-       spin_lock_irqsave(&fep->mii_lock, flags);
 
        regval |= fep->phy_addr << 23;
        retval = 0;
@@ -666,6 +666,19 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
                retval = 1;
        }
 
+       return retval;
+}
+
+static int
+mii_queue(struct net_device *dev, int regval,
+               void (*func)(uint, struct net_device *))
+{
+       struct fec_enet_private *fep;
+       unsigned long   flags;
+       int             retval;
+       fep = netdev_priv(dev);
+       spin_lock_irqsave(&fep->mii_lock, flags);
+       retval = mii_queue_unlocked(dev, regval, func);
        spin_unlock_irqrestore(&fep->mii_lock, flags);
        return retval;
 }
@@ -1115,6 +1128,26 @@ static phy_info_t phy_info_dp83848= {
        },
 };
 
+static phy_info_t phy_info_lan8700 = {
+       0x0007C0C,
+       "LAN8700",
+       (const phy_cmd_t []) { /* config */
+               { mk_mii_read(MII_REG_CR), mii_parse_cr },
+               { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+               { mk_mii_end, }
+       },
+       (const phy_cmd_t []) { /* startup */
+               { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+               { mk_mii_read(MII_REG_SR), mii_parse_sr },
+               { mk_mii_end, }
+       },
+       (const phy_cmd_t []) { /* act_int */
+               { mk_mii_end, }
+       },
+       (const phy_cmd_t []) { /* shutdown */
+               { mk_mii_end, }
+       },
+};
 /* ------------------------------------------------------------------------- */
 
 static phy_info_t const * const phy_info[] = {
@@ -1124,6 +1157,7 @@ static phy_info_t const * const phy_info[] = {
        &phy_info_am79c874,
        &phy_info_ks8721bl,
        &phy_info_dp83848,
+       &phy_info_lan8700,
        NULL
 };
 
@@ -1141,19 +1175,9 @@ static void __inline__ fec_request_mii_intr(struct net_device *dev)
                printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
 }
 
-static void __inline__ fec_disable_phy_intr(void)
-{
-       volatile unsigned long *icrp;
-       icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-       *icrp = 0x08000000;
-}
-
-static void __inline__ fec_phy_ack_intr(void)
+static void __inline__ fec_disable_phy_intr(struct net_device *dev)
 {
-       volatile unsigned long *icrp;
-       /* Acknowledge the interrupt */
-       icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-       *icrp = 0x0d000000;
+       free_irq(66, dev);
 }
 #endif
 
@@ -1372,11 +1396,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
 
                        /* Got first part of ID, now get remainder */
                        fep->phy_id = phytype << 16;
-                       mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
+                       mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
                                                        mii_discover_phy3);
                } else {
                        fep->phy_addr++;
-                       mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+                       mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
                                                        mii_discover_phy);
                }
        } else {
@@ -1385,7 +1409,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
                writel(0, fep->hwp + FEC_MII_SPEED);
                fep->phy_speed = 0;
 #ifdef HAVE_mii_link_interrupt
-               fec_disable_phy_intr();
+               fec_disable_phy_intr(dev);
 #endif
        }
 }
@@ -1398,8 +1422,6 @@ mii_link_interrupt(int irq, void * dev_id)
        struct  net_device *dev = dev_id;
        struct fec_enet_private *fep = netdev_priv(dev);
 
-       fec_phy_ack_intr();
-
        mii_do_cmd(dev, fep->phy->ack_int);
        mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
 
@@ -1553,7 +1575,7 @@ static void set_multicast_list(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct dev_mc_list *dmi;
-       unsigned int i, j, bit, data, crc, tmp;
+       unsigned int i, bit, data, crc, tmp;
        unsigned char hash;
 
        if (dev->flags & IFF_PROMISC) {
@@ -1582,9 +1604,7 @@ static void set_multicast_list(struct net_device *dev)
        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) {
+       netdev_for_each_mc_addr(dmi, dev) {
                /* Only support group multicast for now */
                if (!(dmi->dmi_addr[0] & 1))
                        continue;
@@ -1653,10 +1673,11 @@ static const struct net_device_ops fec_netdev_ops = {
   *
   * index is only used in legacy code
   */
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct bufdesc *cbd_base;
+       struct bufdesc *bdp;
        int i;
 
        /* Allocate memory for buffer descriptors. */
@@ -1709,6 +1730,34 @@ int __init fec_enet_init(struct net_device *dev, int index)
        /* Set MII speed to 2.5 MHz */
        fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
                                        / 2500000) / 2) & 0x3F) << 1;
+
+       /* Initialize the receive buffer descriptors. */
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               bdp->cbd_sc = 0;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       /* ...and the same for transmit */
+       bdp = fep->tx_bd_base;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+
+               /* 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;
+
        fec_restart(dev, 0);
 
        /* Queue up command to detect the PHY and initialize the
@@ -1729,7 +1778,6 @@ static void
 fec_restart(struct net_device *dev, int duplex)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       struct bufdesc *bdp;
        int i;
 
        /* Whack a reset.  We should wait for this. */
@@ -1767,33 +1815,6 @@ fec_restart(struct net_device *dev, int duplex)
                }
        }
 
-       /* Initialize the receive buffer descriptors. */
-       bdp = fep->rx_bd_base;
-       for (i = 0; i < RX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = BD_ENET_RX_EMPTY;
-               bdp++;
-       }
-
-       /* Set the last buffer to wrap */
-       bdp--;
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmit */
-       bdp = fep->tx_bd_base;
-       for (i = 0; i < TX_RING_SIZE; i++) {
-
-               /* 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;
-
        /* Enable MII mode */
        if (duplex) {
                /* MII enable / FD enable */