X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fbfin_mac.c;h=587f93cf03f6ce053d2d1f9481623b1c99d63ae7;hb=6f0f2669f508fb239a0f589a8b453dbe22112bf9;hp=ab728006cfa5aa9e65ab4cfcad79d2baae95467b;hpb=a50c0c05c3bdead1ac405ca8cefd8dc290043933;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index ab72800..587f93c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -194,13 +195,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 +254,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 +270,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 +298,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; } @@ -386,8 +387,8 @@ static int mii_probe(struct net_device *dev) u32 sclk, mdc_div; /* Enable PHY output early */ - if (!(bfin_read_VR_CTL() & PHYCLKOE)) - bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE); + if (!(bfin_read_VR_CTL() & CLKBUFOE)) + bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); sclk = get_sclk(); mdc_div = ((sclk / MDC_CLK) / 2) - 1; @@ -398,7 +399,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 +416,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 +448,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 +489,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 +555,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 +567,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 +597,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 +607,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 +657,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 +667,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 +675,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,8 +690,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->dev = dev; skb->protocol = eth_type_trans(skb, dev); #if defined(BFIN_MAC_CSUM_OFFLOAD) skb->csum = current_rx_ptr->status.ip_payload_csum; @@ -812,14 +759,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 @@ -848,7 +795,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(); @@ -865,16 +812,14 @@ static void bfin_mac_timeout(struct net_device *dev) static void bfin_mac_multicast_hash(struct net_device *dev) { u32 emac_hashhi, emac_hashlo; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; emac_hashhi = emac_hashlo = 0; - for (i = 0; i < dev->mc_count; i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* skip non-multicast addresses */ if (!(*addrs & 1)) @@ -915,7 +860,7 @@ static void bfin_mac_set_multicast_list(struct net_device *dev) sysctl = bfin_read_EMAC_OPMODE(); sysctl |= PAM; bfin_write_EMAC_OPMODE(sysctl); - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { /* set up multicast hash table */ sysctl = bfin_read_EMAC_OPMODE(); sysctl |= HM; @@ -950,7 +895,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 @@ -971,6 +916,7 @@ static int bfin_mac_open(struct net_device *dev) phy_start(lp->phydev); phy_write(lp->phydev, MII_BMCR, BMCR_RESET); setup_system_regs(dev); + setup_mac_addr(dev->dev_addr); bfin_mac_disable(); bfin_mac_enable(); pr_debug("hardware init finished\n"); @@ -981,7 +927,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 +934,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 +951,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 +995,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 +1010,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 +1028,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 +1036,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 +1058,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 +1075,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 +1113,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 +1194,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 +1206,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);