diff options
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 296 |
1 files changed, 170 insertions, 126 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 4fec8581bfd..89c0018132e 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -27,6 +27,7 @@ #include <linux/phy.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/ethtool.h> #include <linux/skbuff.h> #include <linux/platform_device.h> @@ -42,7 +43,7 @@ #define DRV_NAME "bfin_mac" #define DRV_VERSION "1.1" #define DRV_AUTHOR "Bryan Wu, Luke Yang" -#define DRV_DESC "Blackfin BF53[67] BF527 on-chip Ethernet MAC driver" +#define DRV_DESC "Blackfin on-chip Ethernet MAC driver" MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); @@ -73,8 +74,14 @@ static struct net_dma_desc_tx *current_tx_ptr; static struct net_dma_desc_tx *tx_desc; static struct net_dma_desc_rx *rx_desc; -static void bf537mac_disable(void); -static void bf537mac_enable(void); +#if defined(CONFIG_BFIN_MAC_RMII) +static u16 pin_req[] = P_RMII0; +#else +static u16 pin_req[] = P_MII0; +#endif + +static void bfin_mac_disable(void); +static void bfin_mac_enable(void); static void desc_list_free(void) { @@ -243,27 +250,6 @@ init_error: /*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ -/* Set FER regs to MUX in Ethernet pins */ -static int setup_pin_mux(int action) -{ -#if defined(CONFIG_BFIN_MAC_RMII) - u16 pin_req[] = P_RMII0; -#else - u16 pin_req[] = P_MII0; -#endif - - if (action) { - if (peripheral_request_list(pin_req, DRV_NAME)) { - printk(KERN_ERR DRV_NAME - ": Requesting Peripherals failed\n"); - return -EFAULT; - } - } else - peripheral_free_list(pin_req); - - return 0; -} - /* * MII operations */ @@ -322,9 +308,9 @@ static int mdiobus_reset(struct mii_bus *bus) return 0; } -static void bf537_adjust_link(struct net_device *dev) +static void bfin_mac_adjust_link(struct net_device *dev) { - struct bf537mac_local *lp = netdev_priv(dev); + struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev = lp->phydev; unsigned long flags; int new_state = 0; @@ -395,7 +381,7 @@ static void bf537_adjust_link(struct net_device *dev) static int mii_probe(struct net_device *dev) { - struct bf537mac_local *lp = netdev_priv(dev); + struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev = NULL; unsigned short sysctl; int i; @@ -431,10 +417,10 @@ static int mii_probe(struct net_device *dev) } #if defined(CONFIG_BFIN_MAC_RMII) - phydev = phy_connect(dev, phydev->dev.bus_id, &bf537_adjust_link, 0, + phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, PHY_INTERFACE_MODE_RMII); #else - phydev = phy_connect(dev, phydev->dev.bus_id, &bf537_adjust_link, 0, + phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, PHY_INTERFACE_MODE_MII); #endif @@ -469,6 +455,51 @@ static int mii_probe(struct net_device *dev) return 0; } +/* + * Ethtool support + */ + +static int +bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bfin_mac_local *lp = netdev_priv(dev); + + if (lp->phydev) + return phy_ethtool_gset(lp->phydev, cmd); + + return -EINVAL; +} + +static int +bfin_mac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bfin_mac_local *lp = netdev_priv(dev); + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (lp->phydev) + return phy_ethtool_sset(lp->phydev, cmd); + + return -EINVAL; +} + +static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, dev->dev.bus_id); +} + +static 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, + .get_drvinfo = bfin_mac_ethtool_getdrvinfo, +}; + /**************************************************************************/ void setup_system_regs(struct net_device *dev) { @@ -511,7 +542,7 @@ static void setup_mac_addr(u8 *mac_addr) bfin_write_EMAC_ADDRHI(addr_hi); } -static int bf537mac_set_mac_address(struct net_device *dev, void *p) +static int bfin_mac_set_mac_address(struct net_device *dev, void *p) { struct sockaddr *addr = p; if (netif_running(dev)) @@ -573,7 +604,7 @@ adjust_head: } -static int bf537mac_hard_start_xmit(struct sk_buff *skb, +static int bfin_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int data; @@ -631,7 +662,7 @@ out: return 0; } -static void bf537mac_rx(struct net_device *dev) +static void bfin_mac_rx(struct net_device *dev) { struct sk_buff *skb, *new_skb; unsigned short len; @@ -680,7 +711,7 @@ out: } /* interrupt routine to handle rx and error signal */ -static irqreturn_t bf537mac_interrupt(int irq, void *dev_id) +static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; int number = 0; @@ -700,21 +731,21 @@ get_one_packet: } real_rx: - bf537mac_rx(dev); + bfin_mac_rx(dev); number++; goto get_one_packet; } #ifdef CONFIG_NET_POLL_CONTROLLER -static void bf537mac_poll(struct net_device *dev) +static void bfin_mac_poll(struct net_device *dev) { disable_irq(IRQ_MAC_RX); - bf537mac_interrupt(IRQ_MAC_RX, dev); + bfin_mac_interrupt(IRQ_MAC_RX, dev); enable_irq(IRQ_MAC_RX); } #endif /* CONFIG_NET_POLL_CONTROLLER */ -static void bf537mac_disable(void) +static void bfin_mac_disable(void) { unsigned int opmode; @@ -728,7 +759,7 @@ static void bf537mac_disable(void) /* * Enable Interrupts, Receive, and Transmit */ -static void bf537mac_enable(void) +static void bfin_mac_enable(void) { u32 opmode; @@ -766,23 +797,23 @@ static void bf537mac_enable(void) } /* Our watchdog timed out. Called by the networking layer */ -static void bf537mac_timeout(struct net_device *dev) +static void bfin_mac_timeout(struct net_device *dev) { pr_debug("%s: %s\n", dev->name, __FUNCTION__); - bf537mac_disable(); + bfin_mac_disable(); /* reset tx queue */ tx_list_tail = tx_list_head->next; - bf537mac_enable(); + bfin_mac_enable(); /* We can accept TX packets again */ dev->trans_start = jiffies; netif_wake_queue(dev); } -static void bf537mac_multicast_hash(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; @@ -821,7 +852,7 @@ static void bf537mac_multicast_hash(struct net_device *dev) * promiscuous mode (for TCPDUMP and cousins) or accept * a select set of multicast packets */ -static void bf537mac_set_multicast_list(struct net_device *dev) +static void bfin_mac_set_multicast_list(struct net_device *dev) { u32 sysctl; @@ -840,7 +871,7 @@ static void bf537mac_set_multicast_list(struct net_device *dev) sysctl = bfin_read_EMAC_OPMODE(); sysctl |= HM; bfin_write_EMAC_OPMODE(sysctl); - bf537mac_multicast_hash(dev); + bfin_mac_multicast_hash(dev); } else { /* clear promisc or multicast mode */ sysctl = bfin_read_EMAC_OPMODE(); @@ -852,7 +883,7 @@ static void bf537mac_set_multicast_list(struct net_device *dev) /* * this puts the device in an inactive state */ -static void bf537mac_shutdown(struct net_device *dev) +static void bfin_mac_shutdown(struct net_device *dev) { /* Turn off the EMAC */ bfin_write_EMAC_OPMODE(0x00000000); @@ -866,9 +897,9 @@ static void bf537mac_shutdown(struct net_device *dev) * * Set up everything, reset the card, etc.. */ -static int bf537mac_open(struct net_device *dev) +static int bfin_mac_open(struct net_device *dev) { - struct bf537mac_local *lp = netdev_priv(dev); + struct bfin_mac_local *lp = netdev_priv(dev); int retval; pr_debug("%s: %s\n", dev->name, __FUNCTION__); @@ -891,8 +922,8 @@ static int bf537mac_open(struct net_device *dev) phy_start(lp->phydev); phy_write(lp->phydev, MII_BMCR, BMCR_RESET); setup_system_regs(dev); - bf537mac_disable(); - bf537mac_enable(); + bfin_mac_disable(); + bfin_mac_enable(); pr_debug("hardware init finished\n"); netif_start_queue(dev); netif_carrier_on(dev); @@ -906,9 +937,9 @@ static int bf537mac_open(struct net_device *dev) * and not talk to the outside world. Caused by * an 'ifconfig ethX down' */ -static int bf537mac_close(struct net_device *dev) +static int bfin_mac_close(struct net_device *dev) { - struct bf537mac_local *lp = netdev_priv(dev); + struct bfin_mac_local *lp = netdev_priv(dev); pr_debug("%s: %s\n", dev->name, __FUNCTION__); netif_stop_queue(dev); @@ -918,7 +949,7 @@ static int bf537mac_close(struct net_device *dev) phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN); /* clear everything */ - bf537mac_shutdown(dev); + bfin_mac_shutdown(dev); /* free the rx/tx buffers */ desc_list_free(); @@ -926,46 +957,59 @@ static int bf537mac_close(struct net_device *dev) return 0; } -static int __init bf537mac_probe(struct net_device *dev) +static int __init bfin_mac_probe(struct platform_device *pdev) { - struct bf537mac_local *lp = netdev_priv(dev); - int retval; - int i; + struct net_device *ndev; + struct bfin_mac_local *lp; + int rc, i; + + ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); + if (!ndev) { + dev_err(&pdev->dev, "Cannot allocate net device!\n"); + return -ENOMEM; + } + + SET_NETDEV_DEV(ndev, &pdev->dev); + platform_set_drvdata(pdev, ndev); + lp = netdev_priv(ndev); /* Grab the MAC address in the MAC */ - *(__le32 *) (&(dev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); - *(__le16 *) (&(dev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI()); + *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); + *(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI()); /* probe mac */ /*todo: how to proble? which is revision_register */ bfin_write_EMAC_ADDRLO(0x12345678); if (bfin_read_EMAC_ADDRLO() != 0x12345678) { - pr_debug("can't detect bf537 mac!\n"); - retval = -ENODEV; - goto err_out; + dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n"); + rc = -ENODEV; + goto out_err_probe_mac; } /* set the GPIO pins to Ethernet mode */ - retval = setup_pin_mux(1); - if (retval) - return retval; - - /*Is it valid? (Did bootloader initialize it?) */ - if (!is_valid_ether_addr(dev->dev_addr)) { - /* Grab the MAC from the board somehow - this is done in the - arch/blackfin/mach-bf537/boards/eth_mac.c */ - bfin_get_ether_addr(dev->dev_addr); + 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?) + * Grab the MAC from the board somehow + * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c + */ + if (!is_valid_ether_addr(ndev->dev_addr)) + bfin_get_ether_addr(ndev->dev_addr); + /* If still not valid, get a random one */ - if (!is_valid_ether_addr(dev->dev_addr)) { - random_ether_addr(dev->dev_addr); - } + if (!is_valid_ether_addr(ndev->dev_addr)) + random_ether_addr(ndev->dev_addr); - setup_mac_addr(dev->dev_addr); + setup_mac_addr(ndev->dev_addr); /* MDIO bus initial */ - lp->mii_bus.priv = dev; + lp->mii_bus.priv = ndev; lp->mii_bus.read = mdiobus_read; lp->mii_bus.write = mdiobus_write; lp->mii_bus.reset = mdiobus_reset; @@ -975,86 +1019,86 @@ static int __init bf537mac_probe(struct net_device *dev) for (i = 0; i < PHY_MAX_ADDR; ++i) lp->mii_bus.irq[i] = PHY_POLL; - mdiobus_register(&lp->mii_bus); + rc = mdiobus_register(&lp->mii_bus); + if (rc) { + dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); + goto out_err_mdiobus_register; + } - retval = mii_probe(dev); - if (retval) - return retval; + rc = mii_probe(ndev); + if (rc) { + dev_err(&pdev->dev, "MII Probe failed!\n"); + goto out_err_mii_probe; + } /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - dev->open = bf537mac_open; - dev->stop = bf537mac_close; - dev->hard_start_xmit = bf537mac_hard_start_xmit; - dev->set_mac_address = bf537mac_set_mac_address; - dev->tx_timeout = bf537mac_timeout; - dev->set_multicast_list = bf537mac_set_multicast_list; + 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 - dev->poll_controller = bf537mac_poll; + ndev->poll_controller = bfin_mac_poll; #endif + ndev->ethtool_ops = &bfin_mac_ethtool_ops; spin_lock_init(&lp->lock); /* now, enable interrupts */ /* register irq handler */ - if (request_irq - (IRQ_MAC_RX, bf537mac_interrupt, IRQF_DISABLED | IRQF_SHARED, - "EMAC_RX", dev)) { - printk(KERN_WARNING DRV_NAME - ": Unable to attach BlackFin MAC RX interrupt\n"); - return -EBUSY; + rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, + IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev); + if (rc) { + dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); + rc = -EBUSY; + goto out_err_request_irq; } - - retval = register_netdev(dev); - if (retval == 0) { - /* now, print out the card info, in a short format.. */ - printk(KERN_INFO "%s: Version %s, %s\n", - DRV_NAME, DRV_VERSION, DRV_DESC); - } - -err_out: - return retval; -} - -static int bfin_mac_probe(struct platform_device *pdev) -{ - struct net_device *ndev; - - ndev = alloc_etherdev(sizeof(struct bf537mac_local)); - if (!ndev) { - printk(KERN_WARNING DRV_NAME ": could not allocate device\n"); - return -ENOMEM; + rc = register_netdev(ndev); + if (rc) { + dev_err(&pdev->dev, "Cannot register net device!\n"); + goto out_err_reg_ndev; } - SET_NETDEV_DEV(ndev, &pdev->dev); + /* now, print out the card info, in a short format.. */ + dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); - platform_set_drvdata(pdev, ndev); + return 0; - if (bf537mac_probe(ndev) != 0) { - platform_set_drvdata(pdev, NULL); - free_netdev(ndev); - printk(KERN_WARNING DRV_NAME ": not found\n"); - return -ENODEV; - } +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: + peripheral_free_list(pin_req); +out_err_setup_pin_mux: +out_err_probe_mac: + platform_set_drvdata(pdev, NULL); + free_netdev(ndev); - return 0; + return rc; } static int bfin_mac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct bfin_mac_local *lp = netdev_priv(ndev); platform_set_drvdata(pdev, NULL); + mdiobus_unregister(&lp->mii_bus); + unregister_netdev(ndev); free_irq(IRQ_MAC_RX, ndev); free_netdev(ndev); - setup_pin_mux(0); + peripheral_free_list(pin_req); return 0; } @@ -1065,7 +1109,7 @@ static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) struct net_device *net_dev = platform_get_drvdata(pdev); if (netif_running(net_dev)) - bf537mac_close(net_dev); + bfin_mac_close(net_dev); return 0; } @@ -1075,7 +1119,7 @@ static int bfin_mac_resume(struct platform_device *pdev) struct net_device *net_dev = platform_get_drvdata(pdev); if (netif_running(net_dev)) - bf537mac_open(net_dev); + bfin_mac_open(net_dev); return 0; } |