b43: N-PHY: save calibration for further restore
[safe/jmp/linux-2.6] / drivers / net / bfin_mac.c
index 3db7db1..8ffea39 100644 (file)
@@ -194,13 +194,13 @@ static int desc_list_init(void)
                struct dma_descriptor *b = &(r->desc_b);
 
                /* allocate a new skb for next time receive */
-               new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+               new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
                if (!new_skb) {
                        printk(KERN_NOTICE DRV_NAME
                               ": init: low on mem - packet dropped\n");
                        goto init_error;
                }
-               skb_reserve(new_skb, 2);
+               skb_reserve(new_skb, NET_IP_ALIGN);
                r->skb = new_skb;
 
                /*
@@ -253,7 +253,7 @@ init_error:
  * MII operations
  */
 /* Wait until the previous MDC/MDIO transaction has completed */
-static void mdio_poll(void)
+static void bfin_mdio_poll(void)
 {
        int timeout_cnt = MAX_TIMEOUT_CNT;
 
@@ -269,25 +269,25 @@ static void mdio_poll(void)
 }
 
 /* Read an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 {
-       mdio_poll();
+       bfin_mdio_poll();
 
        /* read mode */
        bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
                                SET_REGAD((u16) regnum) |
                                STABUSY);
 
-       mdio_poll();
+       bfin_mdio_poll();
 
        return (int) bfin_read_EMAC_STADAT();
 }
 
 /* Write an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
-                        u16 value)
+static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+                             u16 value)
 {
-       mdio_poll();
+       bfin_mdio_poll();
 
        bfin_write_EMAC_STADAT((u32) value);
 
@@ -297,12 +297,12 @@ static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
                                STAOP |
                                STABUSY);
 
-       mdio_poll();
+       bfin_mdio_poll();
 
        return 0;
 }
 
-static int mdiobus_reset(struct mii_bus *bus)
+static int bfin_mdiobus_reset(struct mii_bus *bus)
 {
        return 0;
 }
@@ -398,7 +398,7 @@ static int mii_probe(struct net_device *dev)
 
        /* search for connect PHY device */
        for (i = 0; i < PHY_MAX_ADDR; i++) {
-               struct phy_device *const tmp_phydev = lp->mii_bus.phy_map[i];
+               struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
 
                if (!tmp_phydev)
                        continue; /* no PHY here... */
@@ -415,11 +415,11 @@ static int mii_probe(struct net_device *dev)
        }
 
 #if defined(CONFIG_BFIN_MAC_RMII)
-       phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
-                       PHY_INTERFACE_MODE_RMII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+                       0, PHY_INTERFACE_MODE_RMII);
 #else
-       phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
-                       PHY_INTERFACE_MODE_MII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+                       0, PHY_INTERFACE_MODE_MII);
 #endif
 
        if (IS_ERR(phydev)) {
@@ -447,7 +447,7 @@ static int mii_probe(struct net_device *dev)
        printk(KERN_INFO "%s: attached PHY driver [%s] "
               "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)"
               "@sclk=%dMHz)\n",
-              DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq,
+              DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
               MDC_CLK, mdc_div, sclk/1000000);
 
        return 0;
@@ -488,10 +488,10 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
        strcpy(info->driver, DRV_NAME);
        strcpy(info->version, DRV_VERSION);
        strcpy(info->fw_version, "N/A");
-       strcpy(info->bus_info, dev->dev.bus_id);
+       strcpy(info->bus_info, dev_name(&dev->dev));
 }
 
-static struct ethtool_ops bfin_mac_ethtool_ops = {
+static const struct ethtool_ops bfin_mac_ethtool_ops = {
        .get_settings = bfin_mac_ethtool_getsettings,
        .set_settings = bfin_mac_ethtool_setsettings,
        .get_link = ethtool_op_get_link,
@@ -554,8 +554,8 @@ static void adjust_tx_list(void)
 {
        int timeout_cnt = MAX_TIMEOUT_CNT;
 
-       if (tx_list_head->status.status_word != 0
-           && current_tx_ptr != tx_list_head) {
+       if (tx_list_head->status.status_word != 0 &&
+           current_tx_ptr != tx_list_head) {
                goto adjust_head;       /* released something, just return; */
        }
 
@@ -566,9 +566,9 @@ static void adjust_tx_list(void)
         */
        if (current_tx_ptr->next->next == tx_list_head) {
                while (tx_list_head->status.status_word == 0) {
-                       mdelay(1);
-                       if (tx_list_head->status.status_word != 0
-                           || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
+                       udelay(10);
+                       if (tx_list_head->status.status_word != 0 ||
+                           !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) {
                                goto adjust_head;
                        }
                        if (timeout_cnt-- < 0) {
@@ -596,8 +596,8 @@ adjust_head:
                               ": no sk_buff in a transmitted frame!\n");
                }
                tx_list_head = tx_list_head->next;
-       } while (tx_list_head->status.status_word != 0
-                && current_tx_ptr != tx_list_head);
+       } while (tx_list_head->status.status_word != 0 &&
+                current_tx_ptr != tx_list_head);
        return;
 
 }
@@ -606,93 +606,41 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
                                struct net_device *dev)
 {
        u16 *data;
-
+       u32 data_align = (unsigned long)(skb->data) & 0x3;
        current_tx_ptr->skb = skb;
 
-       if (ANOMALY_05000285) {
-               /*
-                * TXDWA feature is not avaible to older revision < 0.3 silicon
-                * of BF537
-                *
-                * Only if data buffer is ODD WORD alignment, we do not
-                * need to memcpy
-                */
-               u32 data_align = (u32)(skb->data) & 0x3;
-               if (data_align == 0x2) {
-                       /* move skb->data to current_tx_ptr payload */
-                       data = (u16 *)(skb->data) - 1;
-                       *data = (u16)(skb->len);
-                       current_tx_ptr->desc_a.start_addr = (u32)data;
-                       /* this is important! */
-                       blackfin_dcache_flush_range((u32)data,
-                                       (u32)((u8 *)data + skb->len + 4));
-               } else {
-                       *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
-                       memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
-                               skb->len);
-                       current_tx_ptr->desc_a.start_addr =
-                               (u32)current_tx_ptr->packet;
-                       if (current_tx_ptr->status.status_word != 0)
-                               current_tx_ptr->status.status_word = 0;
-                       blackfin_dcache_flush_range(
-                               (u32)current_tx_ptr->packet,
-                               (u32)(current_tx_ptr->packet + skb->len + 2));
-               }
+       if (data_align == 0x2) {
+               /* move skb->data to current_tx_ptr payload */
+               data = (u16 *)(skb->data) - 1;
+                               *data = (u16)(skb->len);
+               current_tx_ptr->desc_a.start_addr = (u32)data;
+               /* this is important! */
+               blackfin_dcache_flush_range((u32)data,
+                               (u32)((u8 *)data + skb->len + 4));
        } else {
-               /*
-                * TXDWA feature is avaible to revision < 0.3 silicon of
-                * BF537 and always avaible to BF52x
-                */
-               u32 data_align = (u32)(skb->data) & 0x3;
-               if (data_align == 0x0) {
-                       u16 sysctl = bfin_read_EMAC_SYSCTL();
-                       sysctl |= TXDWA;
-                       bfin_write_EMAC_SYSCTL(sysctl);
-
-                       /* move skb->data to current_tx_ptr payload */
-                       data = (u16 *)(skb->data) - 2;
-                       *data = (u16)(skb->len);
-                       current_tx_ptr->desc_a.start_addr = (u32)data;
-                       /* this is important! */
-                       blackfin_dcache_flush_range(
-                                       (u32)data,
-                                       (u32)((u8 *)data + skb->len + 4));
-               } else if (data_align == 0x2) {
-                       u16 sysctl = bfin_read_EMAC_SYSCTL();
-                       sysctl &= ~TXDWA;
-                       bfin_write_EMAC_SYSCTL(sysctl);
-
-                       /* move skb->data to current_tx_ptr payload */
-                       data = (u16 *)(skb->data) - 1;
-                       *data = (u16)(skb->len);
-                       current_tx_ptr->desc_a.start_addr = (u32)data;
-                       /* this is important! */
-                       blackfin_dcache_flush_range(
-                                       (u32)data,
-                                       (u32)((u8 *)data + skb->len + 4));
-               } else {
-                       u16 sysctl = bfin_read_EMAC_SYSCTL();
-                       sysctl &= ~TXDWA;
-                       bfin_write_EMAC_SYSCTL(sysctl);
-
-                       *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
-                       memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
-                               skb->len);
-                       current_tx_ptr->desc_a.start_addr =
-                               (u32)current_tx_ptr->packet;
-                       if (current_tx_ptr->status.status_word != 0)
-                               current_tx_ptr->status.status_word = 0;
-                       blackfin_dcache_flush_range(
-                               (u32)current_tx_ptr->packet,
-                               (u32)(current_tx_ptr->packet + skb->len + 2));
-               }
+               *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
+               memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
+                       skb->len);
+               current_tx_ptr->desc_a.start_addr =
+                       (u32)current_tx_ptr->packet;
+               if (current_tx_ptr->status.status_word != 0)
+                       current_tx_ptr->status.status_word = 0;
+               blackfin_dcache_flush_range(
+                       (u32)current_tx_ptr->packet,
+                       (u32)(current_tx_ptr->packet + skb->len + 2));
        }
 
+       /* make sure the internal data buffers in the core are drained
+        * so that the DMA descriptors are completely written when the
+        * DMA engine goes to fetch them below
+        */
+       SSYNC();
+
        /* enable this packet's dma */
        current_tx_ptr->desc_a.config |= DMAEN;
 
        /* tx dma is running, just return */
-       if (bfin_read_DMA2_IRQ_STATUS() & 0x08)
+       if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
                goto out;
 
        /* tx dma is not running */
@@ -708,7 +656,7 @@ out:
        dev->trans_start = jiffies;
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += (skb->len);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void bfin_mac_rx(struct net_device *dev)
@@ -718,7 +666,7 @@ static void bfin_mac_rx(struct net_device *dev)
 
        /* allocate a new skb for next time receive */
        skb = current_rx_ptr->skb;
-       new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+       new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
        if (!new_skb) {
                printk(KERN_NOTICE DRV_NAME
                       ": rx: low on mem - packet dropped\n");
@@ -726,7 +674,7 @@ static void bfin_mac_rx(struct net_device *dev)
                goto out;
        }
        /* reserve 2 bytes for RXDWA padding */
-       skb_reserve(new_skb, 2);
+       skb_reserve(new_skb, NET_IP_ALIGN);
        current_rx_ptr->skb = new_skb;
        current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
 
@@ -741,7 +689,6 @@ static void bfin_mac_rx(struct net_device *dev)
        blackfin_dcache_invalidate_range((unsigned long)skb->head,
                                         (unsigned long)skb->tail);
 
-       dev->last_rx = jiffies;
        skb->protocol = eth_type_trans(skb, dev);
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
        skb->csum = current_rx_ptr->status.ip_payload_csum;
@@ -811,14 +758,14 @@ static void bfin_mac_enable(void)
 {
        u32 opmode;
 
-       pr_debug("%s: %s\n", DRV_NAME, __FUNCTION__);
+       pr_debug("%s: %s\n", DRV_NAME, __func__);
 
        /* Set RX DMA */
        bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
        bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
 
        /* Wait MII done */
-       mdio_poll();
+       bfin_mdio_poll();
 
        /* We enable only RX here */
        /* ASTP   : Enable Automatic Pad Stripping
@@ -847,7 +794,7 @@ static void bfin_mac_enable(void)
 /* Our watchdog timed out. Called by the networking layer */
 static void bfin_mac_timeout(struct net_device *dev)
 {
-       pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+       pr_debug("%s: %s\n", dev->name, __func__);
 
        bfin_mac_disable();
 
@@ -949,7 +896,7 @@ static int bfin_mac_open(struct net_device *dev)
 {
        struct bfin_mac_local *lp = netdev_priv(dev);
        int retval;
-       pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+       pr_debug("%s: %s\n", dev->name, __func__);
 
        /*
         * Check that the address is valid.  If its not, refuse
@@ -981,7 +928,6 @@ static int bfin_mac_open(struct net_device *dev)
 }
 
 /*
- *
  * this makes the board clean up everything that it can
  * and not talk to the outside world.   Caused by
  * an 'ifconfig ethX down'
@@ -989,7 +935,7 @@ static int bfin_mac_open(struct net_device *dev)
 static int bfin_mac_close(struct net_device *dev)
 {
        struct bfin_mac_local *lp = netdev_priv(dev);
-       pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+       pr_debug("%s: %s\n", dev->name, __func__);
 
        netif_stop_queue(dev);
        netif_carrier_off(dev);
@@ -1006,11 +952,26 @@ static int bfin_mac_close(struct net_device *dev)
        return 0;
 }
 
+static const struct net_device_ops bfin_mac_netdev_ops = {
+       .ndo_open               = bfin_mac_open,
+       .ndo_stop               = bfin_mac_close,
+       .ndo_start_xmit         = bfin_mac_hard_start_xmit,
+       .ndo_set_mac_address    = bfin_mac_set_mac_address,
+       .ndo_tx_timeout         = bfin_mac_timeout,
+       .ndo_set_multicast_list = bfin_mac_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = bfin_mac_poll,
+#endif
+};
+
 static int __devinit bfin_mac_probe(struct platform_device *pdev)
 {
        struct net_device *ndev;
        struct bfin_mac_local *lp;
-       int rc, i;
+       struct platform_device *pd;
+       int rc;
 
        ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
        if (!ndev) {
@@ -1035,13 +996,6 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
                goto out_err_probe_mac;
        }
 
-       /* set the GPIO pins to Ethernet mode */
-       rc = peripheral_request_list(pin_req, DRV_NAME);
-       if (rc) {
-               dev_err(&pdev->dev, "Requesting peripherals failed!\n");
-               rc = -EFAULT;
-               goto out_err_setup_pin_mux;
-       }
 
        /*
         * Is it valid? (Did bootloader initialize it?)
@@ -1057,22 +1011,14 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
 
        setup_mac_addr(ndev->dev_addr);
 
-       /* MDIO bus initial */
-       lp->mii_bus.priv = ndev;
-       lp->mii_bus.read = mdiobus_read;
-       lp->mii_bus.write = mdiobus_write;
-       lp->mii_bus.reset = mdiobus_reset;
-       lp->mii_bus.name = "bfin_mac_mdio";
-       snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "0");
-       lp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-       for (i = 0; i < PHY_MAX_ADDR; ++i)
-               lp->mii_bus.irq[i] = PHY_POLL;
-
-       rc = mdiobus_register(&lp->mii_bus);
-       if (rc) {
-               dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
-               goto out_err_mdiobus_register;
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
+               rc = -ENODEV;
+               goto out_err_probe_mac;
        }
+       pd = pdev->dev.platform_data;
+       lp->mii_bus = platform_get_drvdata(pd);
+       lp->mii_bus->priv = ndev;
 
        rc = mii_probe(ndev);
        if (rc) {
@@ -1083,15 +1029,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(ndev);
 
-       ndev->open = bfin_mac_open;
-       ndev->stop = bfin_mac_close;
-       ndev->hard_start_xmit = bfin_mac_hard_start_xmit;
-       ndev->set_mac_address = bfin_mac_set_mac_address;
-       ndev->tx_timeout = bfin_mac_timeout;
-       ndev->set_multicast_list = bfin_mac_set_multicast_list;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       ndev->poll_controller = bfin_mac_poll;
-#endif
+       ndev->netdev_ops = &bfin_mac_netdev_ops;
        ndev->ethtool_ops = &bfin_mac_ethtool_ops;
 
        spin_lock_init(&lp->lock);
@@ -1099,7 +1037,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        /* now, enable interrupts */
        /* register irq handler */
        rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
-                       IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev);
+                       IRQF_DISABLED, "EMAC_RX", ndev);
        if (rc) {
                dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
                rc = -EBUSY;
@@ -1121,10 +1059,9 @@ out_err_reg_ndev:
        free_irq(IRQ_MAC_RX, ndev);
 out_err_request_irq:
 out_err_mii_probe:
-       mdiobus_unregister(&lp->mii_bus);
-out_err_mdiobus_register:
+       mdiobus_unregister(lp->mii_bus);
+       mdiobus_free(lp->mii_bus);
        peripheral_free_list(pin_req);
-out_err_setup_pin_mux:
 out_err_probe_mac:
        platform_set_drvdata(pdev, NULL);
        free_netdev(ndev);
@@ -1139,7 +1076,7 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       mdiobus_unregister(&lp->mii_bus);
+       lp->mii_bus->priv = NULL;
 
        unregister_netdev(ndev);
 
@@ -1177,6 +1114,74 @@ static int bfin_mac_resume(struct platform_device *pdev)
 #define bfin_mac_resume NULL
 #endif /* CONFIG_PM */
 
+static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+{
+       struct mii_bus *miibus;
+       int rc, i;
+
+       /*
+        * We are setting up a network card,
+        * so set the GPIO pins to Ethernet mode
+        */
+       rc = peripheral_request_list(pin_req, DRV_NAME);
+       if (rc) {
+               dev_err(&pdev->dev, "Requesting peripherals failed!\n");
+               return rc;
+       }
+
+       rc = -ENOMEM;
+       miibus = mdiobus_alloc();
+       if (miibus == NULL)
+               goto out_err_alloc;
+       miibus->read = bfin_mdiobus_read;
+       miibus->write = bfin_mdiobus_write;
+       miibus->reset = bfin_mdiobus_reset;
+
+       miibus->parent = &pdev->dev;
+       miibus->name = "bfin_mii_bus";
+       snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
+       miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+       if (miibus->irq == NULL)
+               goto out_err_alloc;
+       for (i = 0; i < PHY_MAX_ADDR; ++i)
+               miibus->irq[i] = PHY_POLL;
+
+       rc = mdiobus_register(miibus);
+       if (rc) {
+               dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+               goto out_err_mdiobus_register;
+       }
+
+       platform_set_drvdata(pdev, miibus);
+       return 0;
+
+out_err_mdiobus_register:
+       mdiobus_free(miibus);
+out_err_alloc:
+       peripheral_free_list(pin_req);
+
+       return rc;
+}
+
+static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+{
+       struct mii_bus *miibus = platform_get_drvdata(pdev);
+       platform_set_drvdata(pdev, NULL);
+       mdiobus_unregister(miibus);
+       mdiobus_free(miibus);
+       peripheral_free_list(pin_req);
+       return 0;
+}
+
+static struct platform_driver bfin_mii_bus_driver = {
+       .probe = bfin_mii_bus_probe,
+       .remove = __devexit_p(bfin_mii_bus_remove),
+       .driver = {
+               .name = "bfin_mii_bus",
+               .owner  = THIS_MODULE,
+       },
+};
+
 static struct platform_driver bfin_mac_driver = {
        .probe = bfin_mac_probe,
        .remove = __devexit_p(bfin_mac_remove),
@@ -1190,7 +1195,11 @@ static struct platform_driver bfin_mac_driver = {
 
 static int __init bfin_mac_init(void)
 {
-       return platform_driver_register(&bfin_mac_driver);
+       int ret;
+       ret = platform_driver_register(&bfin_mii_bus_driver);
+       if (!ret)
+               return platform_driver_register(&bfin_mac_driver);
+       return -ENODEV;
 }
 
 module_init(bfin_mac_init);
@@ -1198,6 +1207,7 @@ module_init(bfin_mac_init);
 static void __exit bfin_mac_cleanup(void)
 {
        platform_driver_unregister(&bfin_mac_driver);
+       platform_driver_unregister(&bfin_mii_bus_driver);
 }
 
 module_exit(bfin_mac_cleanup);