1ec21e2ecSJeff Kirsher /* 2ec21e2ecSJeff Kirsher * Driver for the MPC5200 Fast Ethernet Controller 3ec21e2ecSJeff Kirsher * 4ec21e2ecSJeff Kirsher * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and 5ec21e2ecSJeff Kirsher * now maintained by Sylvain Munaut <tnt@246tNt.com> 6ec21e2ecSJeff Kirsher * 7ec21e2ecSJeff Kirsher * Copyright (C) 2007 Domen Puncer, Telargo, Inc. 8ec21e2ecSJeff Kirsher * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com> 9ec21e2ecSJeff Kirsher * Copyright (C) 2003-2004 MontaVista, Software, Inc. 10ec21e2ecSJeff Kirsher * 11ec21e2ecSJeff Kirsher * This file is licensed under the terms of the GNU General Public License 12ec21e2ecSJeff Kirsher * version 2. This program is licensed "as is" without any warranty of any 13ec21e2ecSJeff Kirsher * kind, whether express or implied. 14ec21e2ecSJeff Kirsher * 15ec21e2ecSJeff Kirsher */ 16ec21e2ecSJeff Kirsher 1731b7720cSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1831b7720cSJoe Perches 19ec21e2ecSJeff Kirsher #include <linux/dma-mapping.h> 20ec21e2ecSJeff Kirsher #include <linux/module.h> 21ec21e2ecSJeff Kirsher 22ec21e2ecSJeff Kirsher #include <linux/kernel.h> 23ec21e2ecSJeff Kirsher #include <linux/types.h> 24ec21e2ecSJeff Kirsher #include <linux/spinlock.h> 25ec21e2ecSJeff Kirsher #include <linux/slab.h> 26ec21e2ecSJeff Kirsher #include <linux/errno.h> 27ec21e2ecSJeff Kirsher #include <linux/init.h> 28ec21e2ecSJeff Kirsher #include <linux/interrupt.h> 29ec21e2ecSJeff Kirsher #include <linux/crc32.h> 30ec21e2ecSJeff Kirsher #include <linux/hardirq.h> 31ec21e2ecSJeff Kirsher #include <linux/delay.h> 32ec21e2ecSJeff Kirsher #include <linux/of_device.h> 33ec21e2ecSJeff Kirsher #include <linux/of_mdio.h> 34db98f081SStefan Roese #include <linux/of_net.h> 35ec21e2ecSJeff Kirsher #include <linux/of_platform.h> 36ec21e2ecSJeff Kirsher 37ec21e2ecSJeff Kirsher #include <linux/netdevice.h> 38ec21e2ecSJeff Kirsher #include <linux/etherdevice.h> 39ec21e2ecSJeff Kirsher #include <linux/ethtool.h> 40ec21e2ecSJeff Kirsher #include <linux/skbuff.h> 41ec21e2ecSJeff Kirsher 42ec21e2ecSJeff Kirsher #include <asm/io.h> 43ec21e2ecSJeff Kirsher #include <asm/delay.h> 44ec21e2ecSJeff Kirsher #include <asm/mpc52xx.h> 45ec21e2ecSJeff Kirsher 469a322993SPhilippe De Muyter #include <linux/fsl/bestcomm/bestcomm.h> 479a322993SPhilippe De Muyter #include <linux/fsl/bestcomm/fec.h> 48ec21e2ecSJeff Kirsher 49ec21e2ecSJeff Kirsher #include "fec_mpc52xx.h" 50ec21e2ecSJeff Kirsher 51ec21e2ecSJeff Kirsher #define DRIVER_NAME "mpc52xx-fec" 52ec21e2ecSJeff Kirsher 53ec21e2ecSJeff Kirsher /* Private driver data structure */ 54ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv { 55ec21e2ecSJeff Kirsher struct net_device *ndev; 56ec21e2ecSJeff Kirsher int duplex; 57ec21e2ecSJeff Kirsher int speed; 58ec21e2ecSJeff Kirsher int r_irq; 59ec21e2ecSJeff Kirsher int t_irq; 60ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec; 61ec21e2ecSJeff Kirsher struct bcom_task *rx_dmatsk; 62ec21e2ecSJeff Kirsher struct bcom_task *tx_dmatsk; 63ec21e2ecSJeff Kirsher spinlock_t lock; 64ec21e2ecSJeff Kirsher int msg_enable; 65ec21e2ecSJeff Kirsher 66ec21e2ecSJeff Kirsher /* MDIO link details */ 67ec21e2ecSJeff Kirsher unsigned int mdio_speed; 68ec21e2ecSJeff Kirsher struct device_node *phy_node; 69ec21e2ecSJeff Kirsher enum phy_state link; 70ec21e2ecSJeff Kirsher int seven_wire_mode; 71ec21e2ecSJeff Kirsher }; 72ec21e2ecSJeff Kirsher 73ec21e2ecSJeff Kirsher 74ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_interrupt(int, void *); 75ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); 76ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); 77ec21e2ecSJeff Kirsher static void mpc52xx_fec_stop(struct net_device *dev); 78ec21e2ecSJeff Kirsher static void mpc52xx_fec_start(struct net_device *dev); 79ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset(struct net_device *dev); 80ec21e2ecSJeff Kirsher 81ec21e2ecSJeff Kirsher #define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ 82ec21e2ecSJeff Kirsher NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) 83ec21e2ecSJeff Kirsher static int debug = -1; /* the above default */ 84ec21e2ecSJeff Kirsher module_param(debug, int, 0); 85ec21e2ecSJeff Kirsher MODULE_PARM_DESC(debug, "debugging messages level"); 86ec21e2ecSJeff Kirsher 87ec21e2ecSJeff Kirsher static void mpc52xx_fec_tx_timeout(struct net_device *dev) 88ec21e2ecSJeff Kirsher { 89ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 90ec21e2ecSJeff Kirsher unsigned long flags; 91ec21e2ecSJeff Kirsher 92ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "transmit timed out\n"); 93ec21e2ecSJeff Kirsher 94ec21e2ecSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 95ec21e2ecSJeff Kirsher mpc52xx_fec_reset(dev); 96ec21e2ecSJeff Kirsher dev->stats.tx_errors++; 97ec21e2ecSJeff Kirsher spin_unlock_irqrestore(&priv->lock, flags); 98ec21e2ecSJeff Kirsher 99ec21e2ecSJeff Kirsher netif_wake_queue(dev); 100ec21e2ecSJeff Kirsher } 101ec21e2ecSJeff Kirsher 102ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) 103ec21e2ecSJeff Kirsher { 104ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 105ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 106ec21e2ecSJeff Kirsher 107ec21e2ecSJeff Kirsher out_be32(&fec->paddr1, *(u32 *)(&mac[0])); 108ec21e2ecSJeff Kirsher out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); 109ec21e2ecSJeff Kirsher } 110ec21e2ecSJeff Kirsher 111ec21e2ecSJeff Kirsher static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) 112ec21e2ecSJeff Kirsher { 113ec21e2ecSJeff Kirsher struct sockaddr *sock = addr; 114ec21e2ecSJeff Kirsher 115ec21e2ecSJeff Kirsher memcpy(dev->dev_addr, sock->sa_data, dev->addr_len); 116ec21e2ecSJeff Kirsher 117ec21e2ecSJeff Kirsher mpc52xx_fec_set_paddr(dev, sock->sa_data); 118ec21e2ecSJeff Kirsher return 0; 119ec21e2ecSJeff Kirsher } 120ec21e2ecSJeff Kirsher 121ec21e2ecSJeff Kirsher static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) 122ec21e2ecSJeff Kirsher { 123ec21e2ecSJeff Kirsher while (!bcom_queue_empty(s)) { 124ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 125ec21e2ecSJeff Kirsher struct sk_buff *skb; 126ec21e2ecSJeff Kirsher 127ec21e2ecSJeff Kirsher skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); 128ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, 129ec21e2ecSJeff Kirsher DMA_FROM_DEVICE); 130ec21e2ecSJeff Kirsher kfree_skb(skb); 131ec21e2ecSJeff Kirsher } 132ec21e2ecSJeff Kirsher } 133ec21e2ecSJeff Kirsher 134ec21e2ecSJeff Kirsher static void 135ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(struct net_device *dev, struct sk_buff *rskb) 136ec21e2ecSJeff Kirsher { 137ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 138ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 139ec21e2ecSJeff Kirsher 140ec21e2ecSJeff Kirsher bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->rx_dmatsk); 141ec21e2ecSJeff Kirsher bd->status = FEC_RX_BUFFER_SIZE; 142ec21e2ecSJeff Kirsher bd->skb_pa = dma_map_single(dev->dev.parent, rskb->data, 143ec21e2ecSJeff Kirsher FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); 144ec21e2ecSJeff Kirsher bcom_submit_next_buffer(priv->rx_dmatsk, rskb); 145ec21e2ecSJeff Kirsher } 146ec21e2ecSJeff Kirsher 147ec21e2ecSJeff Kirsher static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) 148ec21e2ecSJeff Kirsher { 149ec21e2ecSJeff Kirsher struct sk_buff *skb; 150ec21e2ecSJeff Kirsher 151ec21e2ecSJeff Kirsher while (!bcom_queue_full(rxtsk)) { 15221a4e469SPradeep A Dalvi skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); 153ec21e2ecSJeff Kirsher if (!skb) 154ec21e2ecSJeff Kirsher return -EAGAIN; 155ec21e2ecSJeff Kirsher 156ec21e2ecSJeff Kirsher /* zero out the initial receive buffers to aid debugging */ 157ec21e2ecSJeff Kirsher memset(skb->data, 0, FEC_RX_BUFFER_SIZE); 158ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, skb); 159ec21e2ecSJeff Kirsher } 160ec21e2ecSJeff Kirsher return 0; 161ec21e2ecSJeff Kirsher } 162ec21e2ecSJeff Kirsher 163ec21e2ecSJeff Kirsher /* based on generic_adjust_link from fs_enet-main.c */ 164ec21e2ecSJeff Kirsher static void mpc52xx_fec_adjust_link(struct net_device *dev) 165ec21e2ecSJeff Kirsher { 166ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 167a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 168ec21e2ecSJeff Kirsher int new_state = 0; 169ec21e2ecSJeff Kirsher 170ec21e2ecSJeff Kirsher if (phydev->link != PHY_DOWN) { 171ec21e2ecSJeff Kirsher if (phydev->duplex != priv->duplex) { 172ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 173ec21e2ecSJeff Kirsher u32 rcntrl; 174ec21e2ecSJeff Kirsher u32 tcntrl; 175ec21e2ecSJeff Kirsher 176ec21e2ecSJeff Kirsher new_state = 1; 177ec21e2ecSJeff Kirsher priv->duplex = phydev->duplex; 178ec21e2ecSJeff Kirsher 179ec21e2ecSJeff Kirsher rcntrl = in_be32(&fec->r_cntrl); 180ec21e2ecSJeff Kirsher tcntrl = in_be32(&fec->x_cntrl); 181ec21e2ecSJeff Kirsher 182ec21e2ecSJeff Kirsher rcntrl &= ~FEC_RCNTRL_DRT; 183ec21e2ecSJeff Kirsher tcntrl &= ~FEC_TCNTRL_FDEN; 184ec21e2ecSJeff Kirsher if (phydev->duplex == DUPLEX_FULL) 185ec21e2ecSJeff Kirsher tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */ 186ec21e2ecSJeff Kirsher else 187ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ 188ec21e2ecSJeff Kirsher 189ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rcntrl); 190ec21e2ecSJeff Kirsher out_be32(&fec->x_cntrl, tcntrl); 191ec21e2ecSJeff Kirsher } 192ec21e2ecSJeff Kirsher 193ec21e2ecSJeff Kirsher if (phydev->speed != priv->speed) { 194ec21e2ecSJeff Kirsher new_state = 1; 195ec21e2ecSJeff Kirsher priv->speed = phydev->speed; 196ec21e2ecSJeff Kirsher } 197ec21e2ecSJeff Kirsher 198ec21e2ecSJeff Kirsher if (priv->link == PHY_DOWN) { 199ec21e2ecSJeff Kirsher new_state = 1; 200ec21e2ecSJeff Kirsher priv->link = phydev->link; 201ec21e2ecSJeff Kirsher } 202ec21e2ecSJeff Kirsher 203ec21e2ecSJeff Kirsher } else if (priv->link) { 204ec21e2ecSJeff Kirsher new_state = 1; 205ec21e2ecSJeff Kirsher priv->link = PHY_DOWN; 206ec21e2ecSJeff Kirsher priv->speed = 0; 207ec21e2ecSJeff Kirsher priv->duplex = -1; 208ec21e2ecSJeff Kirsher } 209ec21e2ecSJeff Kirsher 210ec21e2ecSJeff Kirsher if (new_state && netif_msg_link(priv)) 211ec21e2ecSJeff Kirsher phy_print_status(phydev); 212ec21e2ecSJeff Kirsher } 213ec21e2ecSJeff Kirsher 214ec21e2ecSJeff Kirsher static int mpc52xx_fec_open(struct net_device *dev) 215ec21e2ecSJeff Kirsher { 216ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 217a54d20f8SPhilippe Reynes struct phy_device *phydev = NULL; 218ec21e2ecSJeff Kirsher int err = -EBUSY; 219ec21e2ecSJeff Kirsher 220ec21e2ecSJeff Kirsher if (priv->phy_node) { 221a54d20f8SPhilippe Reynes phydev = of_phy_connect(priv->ndev, priv->phy_node, 222ec21e2ecSJeff Kirsher mpc52xx_fec_adjust_link, 0, 0); 223a54d20f8SPhilippe Reynes if (!phydev) { 224ec21e2ecSJeff Kirsher dev_err(&dev->dev, "of_phy_connect failed\n"); 225ec21e2ecSJeff Kirsher return -ENODEV; 226ec21e2ecSJeff Kirsher } 227a54d20f8SPhilippe Reynes phy_start(phydev); 228ec21e2ecSJeff Kirsher } 229ec21e2ecSJeff Kirsher 230ec21e2ecSJeff Kirsher if (request_irq(dev->irq, mpc52xx_fec_interrupt, IRQF_SHARED, 231ec21e2ecSJeff Kirsher DRIVER_NAME "_ctrl", dev)) { 232ec21e2ecSJeff Kirsher dev_err(&dev->dev, "ctrl interrupt request failed\n"); 233ec21e2ecSJeff Kirsher goto free_phy; 234ec21e2ecSJeff Kirsher } 235ec21e2ecSJeff Kirsher if (request_irq(priv->r_irq, mpc52xx_fec_rx_interrupt, 0, 236ec21e2ecSJeff Kirsher DRIVER_NAME "_rx", dev)) { 237ec21e2ecSJeff Kirsher dev_err(&dev->dev, "rx interrupt request failed\n"); 238ec21e2ecSJeff Kirsher goto free_ctrl_irq; 239ec21e2ecSJeff Kirsher } 240ec21e2ecSJeff Kirsher if (request_irq(priv->t_irq, mpc52xx_fec_tx_interrupt, 0, 241ec21e2ecSJeff Kirsher DRIVER_NAME "_tx", dev)) { 242ec21e2ecSJeff Kirsher dev_err(&dev->dev, "tx interrupt request failed\n"); 243ec21e2ecSJeff Kirsher goto free_2irqs; 244ec21e2ecSJeff Kirsher } 245ec21e2ecSJeff Kirsher 246ec21e2ecSJeff Kirsher bcom_fec_rx_reset(priv->rx_dmatsk); 247ec21e2ecSJeff Kirsher bcom_fec_tx_reset(priv->tx_dmatsk); 248ec21e2ecSJeff Kirsher 249ec21e2ecSJeff Kirsher err = mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); 250ec21e2ecSJeff Kirsher if (err) { 251ec21e2ecSJeff Kirsher dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n"); 252ec21e2ecSJeff Kirsher goto free_irqs; 253ec21e2ecSJeff Kirsher } 254ec21e2ecSJeff Kirsher 255ec21e2ecSJeff Kirsher bcom_enable(priv->rx_dmatsk); 256ec21e2ecSJeff Kirsher bcom_enable(priv->tx_dmatsk); 257ec21e2ecSJeff Kirsher 258ec21e2ecSJeff Kirsher mpc52xx_fec_start(dev); 259ec21e2ecSJeff Kirsher 260ec21e2ecSJeff Kirsher netif_start_queue(dev); 261ec21e2ecSJeff Kirsher 262ec21e2ecSJeff Kirsher return 0; 263ec21e2ecSJeff Kirsher 264ec21e2ecSJeff Kirsher free_irqs: 265ec21e2ecSJeff Kirsher free_irq(priv->t_irq, dev); 266ec21e2ecSJeff Kirsher free_2irqs: 267ec21e2ecSJeff Kirsher free_irq(priv->r_irq, dev); 268ec21e2ecSJeff Kirsher free_ctrl_irq: 269ec21e2ecSJeff Kirsher free_irq(dev->irq, dev); 270ec21e2ecSJeff Kirsher free_phy: 271a54d20f8SPhilippe Reynes if (phydev) { 272a54d20f8SPhilippe Reynes phy_stop(phydev); 273a54d20f8SPhilippe Reynes phy_disconnect(phydev); 274ec21e2ecSJeff Kirsher } 275ec21e2ecSJeff Kirsher 276ec21e2ecSJeff Kirsher return err; 277ec21e2ecSJeff Kirsher } 278ec21e2ecSJeff Kirsher 279ec21e2ecSJeff Kirsher static int mpc52xx_fec_close(struct net_device *dev) 280ec21e2ecSJeff Kirsher { 281ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 282a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 283ec21e2ecSJeff Kirsher 284ec21e2ecSJeff Kirsher netif_stop_queue(dev); 285ec21e2ecSJeff Kirsher 286ec21e2ecSJeff Kirsher mpc52xx_fec_stop(dev); 287ec21e2ecSJeff Kirsher 288ec21e2ecSJeff Kirsher mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); 289ec21e2ecSJeff Kirsher 290ec21e2ecSJeff Kirsher free_irq(dev->irq, dev); 291ec21e2ecSJeff Kirsher free_irq(priv->r_irq, dev); 292ec21e2ecSJeff Kirsher free_irq(priv->t_irq, dev); 293ec21e2ecSJeff Kirsher 294a54d20f8SPhilippe Reynes if (phydev) { 295ec21e2ecSJeff Kirsher /* power down phy */ 296a54d20f8SPhilippe Reynes phy_stop(phydev); 297a54d20f8SPhilippe Reynes phy_disconnect(phydev); 298ec21e2ecSJeff Kirsher } 299ec21e2ecSJeff Kirsher 300ec21e2ecSJeff Kirsher return 0; 301ec21e2ecSJeff Kirsher } 302ec21e2ecSJeff Kirsher 303ec21e2ecSJeff Kirsher /* This will only be invoked if your driver is _not_ in XOFF state. 304ec21e2ecSJeff Kirsher * What this means is that you need not check it, and that this 305ec21e2ecSJeff Kirsher * invariant will hold if you make sure that the netif_*_queue() 306ec21e2ecSJeff Kirsher * calls are done at the proper times. 307ec21e2ecSJeff Kirsher */ 308ec21e2ecSJeff Kirsher static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) 309ec21e2ecSJeff Kirsher { 310ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 311ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 312ec21e2ecSJeff Kirsher unsigned long flags; 313ec21e2ecSJeff Kirsher 314ec21e2ecSJeff Kirsher if (bcom_queue_full(priv->tx_dmatsk)) { 315ec21e2ecSJeff Kirsher if (net_ratelimit()) 316ec21e2ecSJeff Kirsher dev_err(&dev->dev, "transmit queue overrun\n"); 317ec21e2ecSJeff Kirsher return NETDEV_TX_BUSY; 318ec21e2ecSJeff Kirsher } 319ec21e2ecSJeff Kirsher 320ec21e2ecSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 321ec21e2ecSJeff Kirsher 322ec21e2ecSJeff Kirsher bd = (struct bcom_fec_bd *) 323ec21e2ecSJeff Kirsher bcom_prepare_next_buffer(priv->tx_dmatsk); 324ec21e2ecSJeff Kirsher 325ec21e2ecSJeff Kirsher bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; 326ec21e2ecSJeff Kirsher bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len, 327ec21e2ecSJeff Kirsher DMA_TO_DEVICE); 328ec21e2ecSJeff Kirsher 329ec21e2ecSJeff Kirsher skb_tx_timestamp(skb); 330ec21e2ecSJeff Kirsher bcom_submit_next_buffer(priv->tx_dmatsk, skb); 331ec21e2ecSJeff Kirsher spin_unlock_irqrestore(&priv->lock, flags); 332ec21e2ecSJeff Kirsher 333ec21e2ecSJeff Kirsher if (bcom_queue_full(priv->tx_dmatsk)) { 334ec21e2ecSJeff Kirsher netif_stop_queue(dev); 335ec21e2ecSJeff Kirsher } 336ec21e2ecSJeff Kirsher 337ec21e2ecSJeff Kirsher return NETDEV_TX_OK; 338ec21e2ecSJeff Kirsher } 339ec21e2ecSJeff Kirsher 340ec21e2ecSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 341ec21e2ecSJeff Kirsher static void mpc52xx_fec_poll_controller(struct net_device *dev) 342ec21e2ecSJeff Kirsher { 343ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 344ec21e2ecSJeff Kirsher 345ec21e2ecSJeff Kirsher disable_irq(priv->t_irq); 346ec21e2ecSJeff Kirsher mpc52xx_fec_tx_interrupt(priv->t_irq, dev); 347ec21e2ecSJeff Kirsher enable_irq(priv->t_irq); 348ec21e2ecSJeff Kirsher disable_irq(priv->r_irq); 349ec21e2ecSJeff Kirsher mpc52xx_fec_rx_interrupt(priv->r_irq, dev); 350ec21e2ecSJeff Kirsher enable_irq(priv->r_irq); 351ec21e2ecSJeff Kirsher } 352ec21e2ecSJeff Kirsher #endif 353ec21e2ecSJeff Kirsher 354ec21e2ecSJeff Kirsher 355ec21e2ecSJeff Kirsher /* This handles BestComm transmit task interrupts 356ec21e2ecSJeff Kirsher */ 357ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) 358ec21e2ecSJeff Kirsher { 359ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 360ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 361ec21e2ecSJeff Kirsher 362ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 363ec21e2ecSJeff Kirsher while (bcom_buffer_done(priv->tx_dmatsk)) { 364ec21e2ecSJeff Kirsher struct sk_buff *skb; 365ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 366ec21e2ecSJeff Kirsher skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, 367ec21e2ecSJeff Kirsher (struct bcom_bd **)&bd); 368ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, 369ec21e2ecSJeff Kirsher DMA_TO_DEVICE); 370ec21e2ecSJeff Kirsher 371ec21e2ecSJeff Kirsher dev_kfree_skb_irq(skb); 372ec21e2ecSJeff Kirsher } 373ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 374ec21e2ecSJeff Kirsher 375ec21e2ecSJeff Kirsher netif_wake_queue(dev); 376ec21e2ecSJeff Kirsher 377ec21e2ecSJeff Kirsher return IRQ_HANDLED; 378ec21e2ecSJeff Kirsher } 379ec21e2ecSJeff Kirsher 380ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) 381ec21e2ecSJeff Kirsher { 382ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 383ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 384ec21e2ecSJeff Kirsher struct sk_buff *rskb; /* received sk_buff */ 385ec21e2ecSJeff Kirsher struct sk_buff *skb; /* new sk_buff to enqueue in its place */ 386ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 387ec21e2ecSJeff Kirsher u32 status, physaddr; 388ec21e2ecSJeff Kirsher int length; 389ec21e2ecSJeff Kirsher 390ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 391ec21e2ecSJeff Kirsher 392ec21e2ecSJeff Kirsher while (bcom_buffer_done(priv->rx_dmatsk)) { 393ec21e2ecSJeff Kirsher 394ec21e2ecSJeff Kirsher rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, 395ec21e2ecSJeff Kirsher (struct bcom_bd **)&bd); 396ec21e2ecSJeff Kirsher physaddr = bd->skb_pa; 397ec21e2ecSJeff Kirsher 398ec21e2ecSJeff Kirsher /* Test for errors in received frame */ 399ec21e2ecSJeff Kirsher if (status & BCOM_FEC_RX_BD_ERRORS) { 400ec21e2ecSJeff Kirsher /* Drop packet and reuse the buffer */ 401ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, rskb); 402ec21e2ecSJeff Kirsher dev->stats.rx_dropped++; 403ec21e2ecSJeff Kirsher continue; 404ec21e2ecSJeff Kirsher } 405ec21e2ecSJeff Kirsher 406ec21e2ecSJeff Kirsher /* skbs are allocated on open, so now we allocate a new one, 407ec21e2ecSJeff Kirsher * and remove the old (with the packet) */ 40821a4e469SPradeep A Dalvi skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); 409ec21e2ecSJeff Kirsher if (!skb) { 410ec21e2ecSJeff Kirsher /* Can't get a new one : reuse the same & drop pkt */ 411ec21e2ecSJeff Kirsher dev_notice(&dev->dev, "Low memory - dropped packet.\n"); 412ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, rskb); 413ec21e2ecSJeff Kirsher dev->stats.rx_dropped++; 414ec21e2ecSJeff Kirsher continue; 415ec21e2ecSJeff Kirsher } 416ec21e2ecSJeff Kirsher 417ec21e2ecSJeff Kirsher /* Enqueue the new sk_buff back on the hardware */ 418ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, skb); 419ec21e2ecSJeff Kirsher 420ec21e2ecSJeff Kirsher /* Process the received skb - Drop the spin lock while 421ec21e2ecSJeff Kirsher * calling into the network stack */ 422ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 423ec21e2ecSJeff Kirsher 424ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, physaddr, rskb->len, 425ec21e2ecSJeff Kirsher DMA_FROM_DEVICE); 426ec21e2ecSJeff Kirsher length = status & BCOM_FEC_RX_BD_LEN_MASK; 427ec21e2ecSJeff Kirsher skb_put(rskb, length - 4); /* length without CRC32 */ 428ec21e2ecSJeff Kirsher rskb->protocol = eth_type_trans(rskb, dev); 4299ca3cc6fSStephan Gatzka if (!skb_defer_rx_timestamp(rskb)) 430ec21e2ecSJeff Kirsher netif_rx(rskb); 431ec21e2ecSJeff Kirsher 432ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 433ec21e2ecSJeff Kirsher } 434ec21e2ecSJeff Kirsher 435ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 436ec21e2ecSJeff Kirsher 437ec21e2ecSJeff Kirsher return IRQ_HANDLED; 438ec21e2ecSJeff Kirsher } 439ec21e2ecSJeff Kirsher 440ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) 441ec21e2ecSJeff Kirsher { 442ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 443ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 444ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 445ec21e2ecSJeff Kirsher u32 ievent; 446ec21e2ecSJeff Kirsher 447ec21e2ecSJeff Kirsher ievent = in_be32(&fec->ievent); 448ec21e2ecSJeff Kirsher 449ec21e2ecSJeff Kirsher ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */ 450ec21e2ecSJeff Kirsher if (!ievent) 451ec21e2ecSJeff Kirsher return IRQ_NONE; 452ec21e2ecSJeff Kirsher 453ec21e2ecSJeff Kirsher out_be32(&fec->ievent, ievent); /* clear pending events */ 454ec21e2ecSJeff Kirsher 455ec21e2ecSJeff Kirsher /* on fifo error, soft-reset fec */ 456ec21e2ecSJeff Kirsher if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) { 457ec21e2ecSJeff Kirsher 458ec21e2ecSJeff Kirsher if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR)) 459ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n"); 460ec21e2ecSJeff Kirsher if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) 461ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); 462ec21e2ecSJeff Kirsher 463ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 464ec21e2ecSJeff Kirsher mpc52xx_fec_reset(dev); 465ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 466ec21e2ecSJeff Kirsher 467ec21e2ecSJeff Kirsher return IRQ_HANDLED; 468ec21e2ecSJeff Kirsher } 469ec21e2ecSJeff Kirsher 470ec21e2ecSJeff Kirsher if (ievent & ~FEC_IEVENT_TFINT) 471ec21e2ecSJeff Kirsher dev_dbg(&dev->dev, "ievent: %08x\n", ievent); 472ec21e2ecSJeff Kirsher 473ec21e2ecSJeff Kirsher return IRQ_HANDLED; 474ec21e2ecSJeff Kirsher } 475ec21e2ecSJeff Kirsher 476ec21e2ecSJeff Kirsher /* 477ec21e2ecSJeff Kirsher * Get the current statistics. 478ec21e2ecSJeff Kirsher * This may be called with the card open or closed. 479ec21e2ecSJeff Kirsher */ 480ec21e2ecSJeff Kirsher static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev) 481ec21e2ecSJeff Kirsher { 482ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 483ec21e2ecSJeff Kirsher struct net_device_stats *stats = &dev->stats; 484ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 485ec21e2ecSJeff Kirsher 486ec21e2ecSJeff Kirsher stats->rx_bytes = in_be32(&fec->rmon_r_octets); 487ec21e2ecSJeff Kirsher stats->rx_packets = in_be32(&fec->rmon_r_packets); 488ec21e2ecSJeff Kirsher stats->rx_errors = in_be32(&fec->rmon_r_crc_align) + 489ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_undersize) + 490ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_oversize) + 491ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_frag) + 492ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_jab); 493ec21e2ecSJeff Kirsher 494ec21e2ecSJeff Kirsher stats->tx_bytes = in_be32(&fec->rmon_t_octets); 495ec21e2ecSJeff Kirsher stats->tx_packets = in_be32(&fec->rmon_t_packets); 496ec21e2ecSJeff Kirsher stats->tx_errors = in_be32(&fec->rmon_t_crc_align) + 497ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_undersize) + 498ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_oversize) + 499ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_frag) + 500ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_jab); 501ec21e2ecSJeff Kirsher 502ec21e2ecSJeff Kirsher stats->multicast = in_be32(&fec->rmon_r_mc_pkt); 503ec21e2ecSJeff Kirsher stats->collisions = in_be32(&fec->rmon_t_col); 504ec21e2ecSJeff Kirsher 505ec21e2ecSJeff Kirsher /* detailed rx_errors: */ 506ec21e2ecSJeff Kirsher stats->rx_length_errors = in_be32(&fec->rmon_r_undersize) 507ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_oversize) 508ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_frag) 509ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_jab); 510ec21e2ecSJeff Kirsher stats->rx_over_errors = in_be32(&fec->r_macerr); 511ec21e2ecSJeff Kirsher stats->rx_crc_errors = in_be32(&fec->ieee_r_crc); 512ec21e2ecSJeff Kirsher stats->rx_frame_errors = in_be32(&fec->ieee_r_align); 513ec21e2ecSJeff Kirsher stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop); 514ec21e2ecSJeff Kirsher stats->rx_missed_errors = in_be32(&fec->rmon_r_drop); 515ec21e2ecSJeff Kirsher 516ec21e2ecSJeff Kirsher /* detailed tx_errors: */ 517ec21e2ecSJeff Kirsher stats->tx_aborted_errors = 0; 518ec21e2ecSJeff Kirsher stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr); 519ec21e2ecSJeff Kirsher stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop); 520ec21e2ecSJeff Kirsher stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe); 521ec21e2ecSJeff Kirsher stats->tx_window_errors = in_be32(&fec->ieee_t_lcol); 522ec21e2ecSJeff Kirsher 523ec21e2ecSJeff Kirsher return stats; 524ec21e2ecSJeff Kirsher } 525ec21e2ecSJeff Kirsher 526ec21e2ecSJeff Kirsher /* 527ec21e2ecSJeff Kirsher * Read MIB counters in order to reset them, 528ec21e2ecSJeff Kirsher * then zero all the stats fields in memory 529ec21e2ecSJeff Kirsher */ 530ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset_stats(struct net_device *dev) 531ec21e2ecSJeff Kirsher { 532ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 533ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 534ec21e2ecSJeff Kirsher 535ec21e2ecSJeff Kirsher out_be32(&fec->mib_control, FEC_MIB_DISABLE); 536ec21e2ecSJeff Kirsher memset_io(&fec->rmon_t_drop, 0, 537ec21e2ecSJeff Kirsher offsetof(struct mpc52xx_fec, reserved10) - 538ec21e2ecSJeff Kirsher offsetof(struct mpc52xx_fec, rmon_t_drop)); 539ec21e2ecSJeff Kirsher out_be32(&fec->mib_control, 0); 540ec21e2ecSJeff Kirsher 541ec21e2ecSJeff Kirsher memset(&dev->stats, 0, sizeof(dev->stats)); 542ec21e2ecSJeff Kirsher } 543ec21e2ecSJeff Kirsher 544ec21e2ecSJeff Kirsher /* 545ec21e2ecSJeff Kirsher * Set or clear the multicast filter for this adaptor. 546ec21e2ecSJeff Kirsher */ 547ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_multicast_list(struct net_device *dev) 548ec21e2ecSJeff Kirsher { 549ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 550ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 551ec21e2ecSJeff Kirsher u32 rx_control; 552ec21e2ecSJeff Kirsher 553ec21e2ecSJeff Kirsher rx_control = in_be32(&fec->r_cntrl); 554ec21e2ecSJeff Kirsher 555ec21e2ecSJeff Kirsher if (dev->flags & IFF_PROMISC) { 556ec21e2ecSJeff Kirsher rx_control |= FEC_RCNTRL_PROM; 557ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rx_control); 558ec21e2ecSJeff Kirsher } else { 559ec21e2ecSJeff Kirsher rx_control &= ~FEC_RCNTRL_PROM; 560ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rx_control); 561ec21e2ecSJeff Kirsher 562ec21e2ecSJeff Kirsher if (dev->flags & IFF_ALLMULTI) { 563ec21e2ecSJeff Kirsher out_be32(&fec->gaddr1, 0xffffffff); 564ec21e2ecSJeff Kirsher out_be32(&fec->gaddr2, 0xffffffff); 565ec21e2ecSJeff Kirsher } else { 566ec21e2ecSJeff Kirsher u32 crc; 567ec21e2ecSJeff Kirsher struct netdev_hw_addr *ha; 568ec21e2ecSJeff Kirsher u32 gaddr1 = 0x00000000; 569ec21e2ecSJeff Kirsher u32 gaddr2 = 0x00000000; 570ec21e2ecSJeff Kirsher 571ec21e2ecSJeff Kirsher netdev_for_each_mc_addr(ha, dev) { 572ec21e2ecSJeff Kirsher crc = ether_crc_le(6, ha->addr) >> 26; 573ec21e2ecSJeff Kirsher if (crc >= 32) 574ec21e2ecSJeff Kirsher gaddr1 |= 1 << (crc-32); 575ec21e2ecSJeff Kirsher else 576ec21e2ecSJeff Kirsher gaddr2 |= 1 << crc; 577ec21e2ecSJeff Kirsher } 578ec21e2ecSJeff Kirsher out_be32(&fec->gaddr1, gaddr1); 579ec21e2ecSJeff Kirsher out_be32(&fec->gaddr2, gaddr2); 580ec21e2ecSJeff Kirsher } 581ec21e2ecSJeff Kirsher } 582ec21e2ecSJeff Kirsher } 583ec21e2ecSJeff Kirsher 584ec21e2ecSJeff Kirsher /** 585ec21e2ecSJeff Kirsher * mpc52xx_fec_hw_init 586ec21e2ecSJeff Kirsher * @dev: network device 587ec21e2ecSJeff Kirsher * 588ec21e2ecSJeff Kirsher * Setup various hardware setting, only needed once on start 589ec21e2ecSJeff Kirsher */ 590ec21e2ecSJeff Kirsher static void mpc52xx_fec_hw_init(struct net_device *dev) 591ec21e2ecSJeff Kirsher { 592ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 593ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 594ec21e2ecSJeff Kirsher int i; 595ec21e2ecSJeff Kirsher 596ec21e2ecSJeff Kirsher /* Whack a reset. We should wait for this. */ 597ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); 598ec21e2ecSJeff Kirsher for (i = 0; i < FEC_RESET_DELAY; ++i) { 599ec21e2ecSJeff Kirsher if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) 600ec21e2ecSJeff Kirsher break; 601ec21e2ecSJeff Kirsher udelay(1); 602ec21e2ecSJeff Kirsher } 603ec21e2ecSJeff Kirsher if (i == FEC_RESET_DELAY) 604ec21e2ecSJeff Kirsher dev_err(&dev->dev, "FEC Reset timeout!\n"); 605ec21e2ecSJeff Kirsher 606ec21e2ecSJeff Kirsher /* set pause to 0x20 frames */ 607ec21e2ecSJeff Kirsher out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20); 608ec21e2ecSJeff Kirsher 609ec21e2ecSJeff Kirsher /* high service request will be deasserted when there's < 7 bytes in fifo 610ec21e2ecSJeff Kirsher * low service request will be deasserted when there's < 4*7 bytes in fifo 611ec21e2ecSJeff Kirsher */ 612ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); 613ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); 614ec21e2ecSJeff Kirsher 615ec21e2ecSJeff Kirsher /* alarm when <= x bytes in FIFO */ 616ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_alarm, 0x0000030c); 617ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_alarm, 0x00000100); 618ec21e2ecSJeff Kirsher 619ec21e2ecSJeff Kirsher /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */ 620ec21e2ecSJeff Kirsher out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B); 621ec21e2ecSJeff Kirsher 622ec21e2ecSJeff Kirsher /* enable crc generation */ 623ec21e2ecSJeff Kirsher out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC); 624ec21e2ecSJeff Kirsher out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */ 625ec21e2ecSJeff Kirsher out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */ 626ec21e2ecSJeff Kirsher 627ec21e2ecSJeff Kirsher /* set phy speed. 628ec21e2ecSJeff Kirsher * this can't be done in phy driver, since it needs to be called 629ec21e2ecSJeff Kirsher * before fec stuff (even on resume) */ 630ec21e2ecSJeff Kirsher out_be32(&fec->mii_speed, priv->mdio_speed); 631ec21e2ecSJeff Kirsher } 632ec21e2ecSJeff Kirsher 633ec21e2ecSJeff Kirsher /** 634ec21e2ecSJeff Kirsher * mpc52xx_fec_start 635ec21e2ecSJeff Kirsher * @dev: network device 636ec21e2ecSJeff Kirsher * 637ec21e2ecSJeff Kirsher * This function is called to start or restart the FEC during a link 638ec21e2ecSJeff Kirsher * change. This happens on fifo errors or when switching between half 639ec21e2ecSJeff Kirsher * and full duplex. 640ec21e2ecSJeff Kirsher */ 641ec21e2ecSJeff Kirsher static void mpc52xx_fec_start(struct net_device *dev) 642ec21e2ecSJeff Kirsher { 643ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 644ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 645ec21e2ecSJeff Kirsher u32 rcntrl; 646ec21e2ecSJeff Kirsher u32 tcntrl; 647ec21e2ecSJeff Kirsher u32 tmp; 648ec21e2ecSJeff Kirsher 649ec21e2ecSJeff Kirsher /* clear sticky error bits */ 650ec21e2ecSJeff Kirsher tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF; 651ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp); 652ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp); 653ec21e2ecSJeff Kirsher 654ec21e2ecSJeff Kirsher /* FIFOs will reset on mpc52xx_fec_enable */ 655ec21e2ecSJeff Kirsher out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET); 656ec21e2ecSJeff Kirsher 657ec21e2ecSJeff Kirsher /* Set station address. */ 658ec21e2ecSJeff Kirsher mpc52xx_fec_set_paddr(dev, dev->dev_addr); 659ec21e2ecSJeff Kirsher 660ec21e2ecSJeff Kirsher mpc52xx_fec_set_multicast_list(dev); 661ec21e2ecSJeff Kirsher 662ec21e2ecSJeff Kirsher /* set max frame len, enable flow control, select mii mode */ 663ec21e2ecSJeff Kirsher rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ 664ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_FCE; 665ec21e2ecSJeff Kirsher 666ec21e2ecSJeff Kirsher if (!priv->seven_wire_mode) 667ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_MII_MODE; 668ec21e2ecSJeff Kirsher 669ec21e2ecSJeff Kirsher if (priv->duplex == DUPLEX_FULL) 670ec21e2ecSJeff Kirsher tcntrl = FEC_TCNTRL_FDEN; /* FD enable */ 671ec21e2ecSJeff Kirsher else { 672ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ 673ec21e2ecSJeff Kirsher tcntrl = 0; 674ec21e2ecSJeff Kirsher } 675ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rcntrl); 676ec21e2ecSJeff Kirsher out_be32(&fec->x_cntrl, tcntrl); 677ec21e2ecSJeff Kirsher 678ec21e2ecSJeff Kirsher /* Clear any outstanding interrupt. */ 679ec21e2ecSJeff Kirsher out_be32(&fec->ievent, 0xffffffff); 680ec21e2ecSJeff Kirsher 681ec21e2ecSJeff Kirsher /* Enable interrupts we wish to service. */ 682ec21e2ecSJeff Kirsher out_be32(&fec->imask, FEC_IMASK_ENABLE); 683ec21e2ecSJeff Kirsher 684ec21e2ecSJeff Kirsher /* And last, enable the transmit and receive processing. */ 685ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN); 686ec21e2ecSJeff Kirsher out_be32(&fec->r_des_active, 0x01000000); 687ec21e2ecSJeff Kirsher } 688ec21e2ecSJeff Kirsher 689ec21e2ecSJeff Kirsher /** 690ec21e2ecSJeff Kirsher * mpc52xx_fec_stop 691ec21e2ecSJeff Kirsher * @dev: network device 692ec21e2ecSJeff Kirsher * 693ec21e2ecSJeff Kirsher * stop all activity on fec and empty dma buffers 694ec21e2ecSJeff Kirsher */ 695ec21e2ecSJeff Kirsher static void mpc52xx_fec_stop(struct net_device *dev) 696ec21e2ecSJeff Kirsher { 697ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 698ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 699ec21e2ecSJeff Kirsher unsigned long timeout; 700ec21e2ecSJeff Kirsher 701ec21e2ecSJeff Kirsher /* disable all interrupts */ 702ec21e2ecSJeff Kirsher out_be32(&fec->imask, 0); 703ec21e2ecSJeff Kirsher 704ec21e2ecSJeff Kirsher /* Disable the rx task. */ 705ec21e2ecSJeff Kirsher bcom_disable(priv->rx_dmatsk); 706ec21e2ecSJeff Kirsher 707ec21e2ecSJeff Kirsher /* Wait for tx queue to drain, but only if we're in process context */ 708ec21e2ecSJeff Kirsher if (!in_interrupt()) { 709ec21e2ecSJeff Kirsher timeout = jiffies + msecs_to_jiffies(2000); 710ec21e2ecSJeff Kirsher while (time_before(jiffies, timeout) && 711ec21e2ecSJeff Kirsher !bcom_queue_empty(priv->tx_dmatsk)) 712ec21e2ecSJeff Kirsher msleep(100); 713ec21e2ecSJeff Kirsher 714ec21e2ecSJeff Kirsher if (time_after_eq(jiffies, timeout)) 715ec21e2ecSJeff Kirsher dev_err(&dev->dev, "queues didn't drain\n"); 716ec21e2ecSJeff Kirsher #if 1 717ec21e2ecSJeff Kirsher if (time_after_eq(jiffies, timeout)) { 718ec21e2ecSJeff Kirsher dev_err(&dev->dev, " tx: index: %i, outdex: %i\n", 719ec21e2ecSJeff Kirsher priv->tx_dmatsk->index, 720ec21e2ecSJeff Kirsher priv->tx_dmatsk->outdex); 721ec21e2ecSJeff Kirsher dev_err(&dev->dev, " rx: index: %i, outdex: %i\n", 722ec21e2ecSJeff Kirsher priv->rx_dmatsk->index, 723ec21e2ecSJeff Kirsher priv->rx_dmatsk->outdex); 724ec21e2ecSJeff Kirsher } 725ec21e2ecSJeff Kirsher #endif 726ec21e2ecSJeff Kirsher } 727ec21e2ecSJeff Kirsher 728ec21e2ecSJeff Kirsher bcom_disable(priv->tx_dmatsk); 729ec21e2ecSJeff Kirsher 730ec21e2ecSJeff Kirsher /* Stop FEC */ 731ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); 732ec21e2ecSJeff Kirsher } 733ec21e2ecSJeff Kirsher 734ec21e2ecSJeff Kirsher /* reset fec and bestcomm tasks */ 735ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset(struct net_device *dev) 736ec21e2ecSJeff Kirsher { 737ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 738ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 739ec21e2ecSJeff Kirsher 740ec21e2ecSJeff Kirsher mpc52xx_fec_stop(dev); 741ec21e2ecSJeff Kirsher 742ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status)); 743ec21e2ecSJeff Kirsher out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO); 744ec21e2ecSJeff Kirsher 745ec21e2ecSJeff Kirsher mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); 746ec21e2ecSJeff Kirsher 747ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(dev); 748ec21e2ecSJeff Kirsher 749ec21e2ecSJeff Kirsher bcom_fec_rx_reset(priv->rx_dmatsk); 750ec21e2ecSJeff Kirsher bcom_fec_tx_reset(priv->tx_dmatsk); 751ec21e2ecSJeff Kirsher 752ec21e2ecSJeff Kirsher mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); 753ec21e2ecSJeff Kirsher 754ec21e2ecSJeff Kirsher bcom_enable(priv->rx_dmatsk); 755ec21e2ecSJeff Kirsher bcom_enable(priv->tx_dmatsk); 756ec21e2ecSJeff Kirsher 757ec21e2ecSJeff Kirsher mpc52xx_fec_start(dev); 758ec21e2ecSJeff Kirsher 759ec21e2ecSJeff Kirsher netif_wake_queue(dev); 760ec21e2ecSJeff Kirsher } 761ec21e2ecSJeff Kirsher 762ec21e2ecSJeff Kirsher 763ec21e2ecSJeff Kirsher /* ethtool interface */ 764ec21e2ecSJeff Kirsher 765e03179feSPhilippe Reynes static int mpc52xx_fec_get_ksettings(struct net_device *dev, 766e03179feSPhilippe Reynes struct ethtool_link_ksettings *cmd) 767ec21e2ecSJeff Kirsher { 768a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 769ec21e2ecSJeff Kirsher 770a54d20f8SPhilippe Reynes if (!phydev) 771ec21e2ecSJeff Kirsher return -ENODEV; 772ec21e2ecSJeff Kirsher 773e03179feSPhilippe Reynes return phy_ethtool_ksettings_get(phydev, cmd); 774ec21e2ecSJeff Kirsher } 775ec21e2ecSJeff Kirsher 776e03179feSPhilippe Reynes static int mpc52xx_fec_set_ksettings(struct net_device *dev, 777e03179feSPhilippe Reynes const struct ethtool_link_ksettings *cmd) 778ec21e2ecSJeff Kirsher { 779a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 780ec21e2ecSJeff Kirsher 781a54d20f8SPhilippe Reynes if (!phydev) 782ec21e2ecSJeff Kirsher return -ENODEV; 783ec21e2ecSJeff Kirsher 784e03179feSPhilippe Reynes return phy_ethtool_ksettings_set(phydev, cmd); 785ec21e2ecSJeff Kirsher } 786ec21e2ecSJeff Kirsher 787ec21e2ecSJeff Kirsher static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) 788ec21e2ecSJeff Kirsher { 789ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 790ec21e2ecSJeff Kirsher return priv->msg_enable; 791ec21e2ecSJeff Kirsher } 792ec21e2ecSJeff Kirsher 793ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) 794ec21e2ecSJeff Kirsher { 795ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 796ec21e2ecSJeff Kirsher priv->msg_enable = level; 797ec21e2ecSJeff Kirsher } 798ec21e2ecSJeff Kirsher 799ec21e2ecSJeff Kirsher static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { 800ec21e2ecSJeff Kirsher .get_link = ethtool_op_get_link, 801ec21e2ecSJeff Kirsher .get_msglevel = mpc52xx_fec_get_msglevel, 802ec21e2ecSJeff Kirsher .set_msglevel = mpc52xx_fec_set_msglevel, 8030a4f2823SRichard Cochran .get_ts_info = ethtool_op_get_ts_info, 804e03179feSPhilippe Reynes .get_link_ksettings = mpc52xx_fec_get_ksettings, 805e03179feSPhilippe Reynes .set_link_ksettings = mpc52xx_fec_set_ksettings, 806ec21e2ecSJeff Kirsher }; 807ec21e2ecSJeff Kirsher 808ec21e2ecSJeff Kirsher 809ec21e2ecSJeff Kirsher static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 810ec21e2ecSJeff Kirsher { 811a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 812ec21e2ecSJeff Kirsher 813a54d20f8SPhilippe Reynes if (!phydev) 814ec21e2ecSJeff Kirsher return -ENOTSUPP; 815ec21e2ecSJeff Kirsher 816a54d20f8SPhilippe Reynes return phy_mii_ioctl(phydev, rq, cmd); 817ec21e2ecSJeff Kirsher } 818ec21e2ecSJeff Kirsher 819ec21e2ecSJeff Kirsher static const struct net_device_ops mpc52xx_fec_netdev_ops = { 820ec21e2ecSJeff Kirsher .ndo_open = mpc52xx_fec_open, 821ec21e2ecSJeff Kirsher .ndo_stop = mpc52xx_fec_close, 822ec21e2ecSJeff Kirsher .ndo_start_xmit = mpc52xx_fec_start_xmit, 823afc4b13dSJiri Pirko .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list, 824ec21e2ecSJeff Kirsher .ndo_set_mac_address = mpc52xx_fec_set_mac_address, 825ec21e2ecSJeff Kirsher .ndo_validate_addr = eth_validate_addr, 826ec21e2ecSJeff Kirsher .ndo_do_ioctl = mpc52xx_fec_ioctl, 827ec21e2ecSJeff Kirsher .ndo_change_mtu = eth_change_mtu, 828ec21e2ecSJeff Kirsher .ndo_tx_timeout = mpc52xx_fec_tx_timeout, 829ec21e2ecSJeff Kirsher .ndo_get_stats = mpc52xx_fec_get_stats, 830ec21e2ecSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 831ec21e2ecSJeff Kirsher .ndo_poll_controller = mpc52xx_fec_poll_controller, 832ec21e2ecSJeff Kirsher #endif 833ec21e2ecSJeff Kirsher }; 834ec21e2ecSJeff Kirsher 835ec21e2ecSJeff Kirsher /* ======================================================================== */ 836ec21e2ecSJeff Kirsher /* OF Driver */ 837ec21e2ecSJeff Kirsher /* ======================================================================== */ 838ec21e2ecSJeff Kirsher 83933897cc8SBill Pemberton static int mpc52xx_fec_probe(struct platform_device *op) 840ec21e2ecSJeff Kirsher { 841ec21e2ecSJeff Kirsher int rv; 842ec21e2ecSJeff Kirsher struct net_device *ndev; 843ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = NULL; 844ec21e2ecSJeff Kirsher struct resource mem; 845ec21e2ecSJeff Kirsher const u32 *prop; 846ec21e2ecSJeff Kirsher int prop_size; 847db98f081SStefan Roese struct device_node *np = op->dev.of_node; 848db98f081SStefan Roese const char *mac_addr; 849ec21e2ecSJeff Kirsher 850ec21e2ecSJeff Kirsher phys_addr_t rx_fifo; 851ec21e2ecSJeff Kirsher phys_addr_t tx_fifo; 852ec21e2ecSJeff Kirsher 853ec21e2ecSJeff Kirsher /* Get the ether ndev & it's private zone */ 854ec21e2ecSJeff Kirsher ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); 855ec21e2ecSJeff Kirsher if (!ndev) 856ec21e2ecSJeff Kirsher return -ENOMEM; 857ec21e2ecSJeff Kirsher 858ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 859ec21e2ecSJeff Kirsher priv->ndev = ndev; 860ec21e2ecSJeff Kirsher 861ec21e2ecSJeff Kirsher /* Reserve FEC control zone */ 862db98f081SStefan Roese rv = of_address_to_resource(np, 0, &mem); 863ec21e2ecSJeff Kirsher if (rv) { 86431b7720cSJoe Perches pr_err("Error while parsing device node resource\n"); 865ec21e2ecSJeff Kirsher goto err_netdev; 866ec21e2ecSJeff Kirsher } 867ec21e2ecSJeff Kirsher if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) { 86831b7720cSJoe Perches pr_err("invalid resource size (%lx < %x), check mpc52xx_devices.c\n", 869ec21e2ecSJeff Kirsher (unsigned long)resource_size(&mem), 870ec21e2ecSJeff Kirsher sizeof(struct mpc52xx_fec)); 871ec21e2ecSJeff Kirsher rv = -EINVAL; 872ec21e2ecSJeff Kirsher goto err_netdev; 873ec21e2ecSJeff Kirsher } 874ec21e2ecSJeff Kirsher 875ec21e2ecSJeff Kirsher if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), 876ec21e2ecSJeff Kirsher DRIVER_NAME)) { 877ec21e2ecSJeff Kirsher rv = -EBUSY; 878ec21e2ecSJeff Kirsher goto err_netdev; 879ec21e2ecSJeff Kirsher } 880ec21e2ecSJeff Kirsher 881ec21e2ecSJeff Kirsher /* Init ether ndev with what we have */ 882ec21e2ecSJeff Kirsher ndev->netdev_ops = &mpc52xx_fec_netdev_ops; 883ec21e2ecSJeff Kirsher ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; 884ec21e2ecSJeff Kirsher ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; 885ec21e2ecSJeff Kirsher ndev->base_addr = mem.start; 886ec21e2ecSJeff Kirsher SET_NETDEV_DEV(ndev, &op->dev); 887ec21e2ecSJeff Kirsher 888ec21e2ecSJeff Kirsher spin_lock_init(&priv->lock); 889ec21e2ecSJeff Kirsher 890ec21e2ecSJeff Kirsher /* ioremap the zones */ 891ec21e2ecSJeff Kirsher priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); 892ec21e2ecSJeff Kirsher 893ec21e2ecSJeff Kirsher if (!priv->fec) { 894ec21e2ecSJeff Kirsher rv = -ENOMEM; 895ec21e2ecSJeff Kirsher goto err_mem_region; 896ec21e2ecSJeff Kirsher } 897ec21e2ecSJeff Kirsher 898ec21e2ecSJeff Kirsher /* Bestcomm init */ 899ec21e2ecSJeff Kirsher rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); 900ec21e2ecSJeff Kirsher tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); 901ec21e2ecSJeff Kirsher 902ec21e2ecSJeff Kirsher priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); 903ec21e2ecSJeff Kirsher priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); 904ec21e2ecSJeff Kirsher 905ec21e2ecSJeff Kirsher if (!priv->rx_dmatsk || !priv->tx_dmatsk) { 90631b7720cSJoe Perches pr_err("Can not init SDMA tasks\n"); 907ec21e2ecSJeff Kirsher rv = -ENOMEM; 908ec21e2ecSJeff Kirsher goto err_rx_tx_dmatsk; 909ec21e2ecSJeff Kirsher } 910ec21e2ecSJeff Kirsher 911ec21e2ecSJeff Kirsher /* Get the IRQ we need one by one */ 912ec21e2ecSJeff Kirsher /* Control */ 913db98f081SStefan Roese ndev->irq = irq_of_parse_and_map(np, 0); 914ec21e2ecSJeff Kirsher 915ec21e2ecSJeff Kirsher /* RX */ 916ec21e2ecSJeff Kirsher priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); 917ec21e2ecSJeff Kirsher 918ec21e2ecSJeff Kirsher /* TX */ 919ec21e2ecSJeff Kirsher priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); 920ec21e2ecSJeff Kirsher 921db98f081SStefan Roese /* 922db98f081SStefan Roese * MAC address init: 923db98f081SStefan Roese * 924db98f081SStefan Roese * First try to read MAC address from DT 925db98f081SStefan Roese */ 926db98f081SStefan Roese mac_addr = of_get_mac_address(np); 927db98f081SStefan Roese if (mac_addr) { 928db98f081SStefan Roese memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); 929db98f081SStefan Roese } else { 930db98f081SStefan Roese struct mpc52xx_fec __iomem *fec = priv->fec; 931db98f081SStefan Roese 932db98f081SStefan Roese /* 933db98f081SStefan Roese * If the MAC addresse is not provided via DT then read 934db98f081SStefan Roese * it back from the controller regs 935db98f081SStefan Roese */ 936db98f081SStefan Roese *(u32 *)(&ndev->dev_addr[0]) = in_be32(&fec->paddr1); 937db98f081SStefan Roese *(u16 *)(&ndev->dev_addr[4]) = in_be32(&fec->paddr2) >> 16; 938db98f081SStefan Roese } 939db98f081SStefan Roese 940db98f081SStefan Roese /* 941db98f081SStefan Roese * Check if the MAC address is valid, if not get a random one 942db98f081SStefan Roese */ 943db98f081SStefan Roese if (!is_valid_ether_addr(ndev->dev_addr)) { 944db98f081SStefan Roese eth_hw_addr_random(ndev); 945db98f081SStefan Roese dev_warn(&ndev->dev, "using random MAC address %pM\n", 946db98f081SStefan Roese ndev->dev_addr); 947db98f081SStefan Roese } 948ec21e2ecSJeff Kirsher 949ec21e2ecSJeff Kirsher priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); 950ec21e2ecSJeff Kirsher 951ec21e2ecSJeff Kirsher /* 952ec21e2ecSJeff Kirsher * Link mode configuration 953ec21e2ecSJeff Kirsher */ 954ec21e2ecSJeff Kirsher 955ec21e2ecSJeff Kirsher /* Start with safe defaults for link connection */ 956ec21e2ecSJeff Kirsher priv->speed = 100; 957ec21e2ecSJeff Kirsher priv->duplex = DUPLEX_HALF; 958db98f081SStefan Roese priv->mdio_speed = ((mpc5xxx_get_bus_frequency(np) >> 20) / 5) << 1; 959ec21e2ecSJeff Kirsher 960ec21e2ecSJeff Kirsher /* The current speed preconfigures the speed of the MII link */ 961db98f081SStefan Roese prop = of_get_property(np, "current-speed", &prop_size); 962ec21e2ecSJeff Kirsher if (prop && (prop_size >= sizeof(u32) * 2)) { 963ec21e2ecSJeff Kirsher priv->speed = prop[0]; 964ec21e2ecSJeff Kirsher priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; 965ec21e2ecSJeff Kirsher } 966ec21e2ecSJeff Kirsher 967ec21e2ecSJeff Kirsher /* If there is a phy handle, then get the PHY node */ 968db98f081SStefan Roese priv->phy_node = of_parse_phandle(np, "phy-handle", 0); 969ec21e2ecSJeff Kirsher 970ec21e2ecSJeff Kirsher /* the 7-wire property means don't use MII mode */ 971db98f081SStefan Roese if (of_find_property(np, "fsl,7-wire-mode", NULL)) { 972ec21e2ecSJeff Kirsher priv->seven_wire_mode = 1; 973ec21e2ecSJeff Kirsher dev_info(&ndev->dev, "using 7-wire PHY mode\n"); 974ec21e2ecSJeff Kirsher } 975ec21e2ecSJeff Kirsher 976ec21e2ecSJeff Kirsher /* Hardware init */ 977ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(ndev); 978ec21e2ecSJeff Kirsher mpc52xx_fec_reset_stats(ndev); 979ec21e2ecSJeff Kirsher 980ec21e2ecSJeff Kirsher rv = register_netdev(ndev); 981ec21e2ecSJeff Kirsher if (rv < 0) 982ec21e2ecSJeff Kirsher goto err_node; 983ec21e2ecSJeff Kirsher 984ec21e2ecSJeff Kirsher /* We're done ! */ 9858513fbd8SJingoo Han platform_set_drvdata(op, ndev); 98631b7720cSJoe Perches netdev_info(ndev, "%s MAC %pM\n", 98731b7720cSJoe Perches op->dev.of_node->full_name, ndev->dev_addr); 988ec21e2ecSJeff Kirsher 989ec21e2ecSJeff Kirsher return 0; 990ec21e2ecSJeff Kirsher 991ec21e2ecSJeff Kirsher err_node: 992ec21e2ecSJeff Kirsher of_node_put(priv->phy_node); 993ec21e2ecSJeff Kirsher irq_dispose_mapping(ndev->irq); 994ec21e2ecSJeff Kirsher err_rx_tx_dmatsk: 995ec21e2ecSJeff Kirsher if (priv->rx_dmatsk) 996ec21e2ecSJeff Kirsher bcom_fec_rx_release(priv->rx_dmatsk); 997ec21e2ecSJeff Kirsher if (priv->tx_dmatsk) 998ec21e2ecSJeff Kirsher bcom_fec_tx_release(priv->tx_dmatsk); 999ec21e2ecSJeff Kirsher iounmap(priv->fec); 1000ec21e2ecSJeff Kirsher err_mem_region: 1001ec21e2ecSJeff Kirsher release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); 1002ec21e2ecSJeff Kirsher err_netdev: 1003ec21e2ecSJeff Kirsher free_netdev(ndev); 1004ec21e2ecSJeff Kirsher 1005ec21e2ecSJeff Kirsher return rv; 1006ec21e2ecSJeff Kirsher } 1007ec21e2ecSJeff Kirsher 1008ec21e2ecSJeff Kirsher static int 1009ec21e2ecSJeff Kirsher mpc52xx_fec_remove(struct platform_device *op) 1010ec21e2ecSJeff Kirsher { 1011ec21e2ecSJeff Kirsher struct net_device *ndev; 1012ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv; 1013ec21e2ecSJeff Kirsher 10148513fbd8SJingoo Han ndev = platform_get_drvdata(op); 1015ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 1016ec21e2ecSJeff Kirsher 1017ec21e2ecSJeff Kirsher unregister_netdev(ndev); 1018ec21e2ecSJeff Kirsher 1019ec21e2ecSJeff Kirsher of_node_put(priv->phy_node); 1020ec21e2ecSJeff Kirsher priv->phy_node = NULL; 1021ec21e2ecSJeff Kirsher 1022ec21e2ecSJeff Kirsher irq_dispose_mapping(ndev->irq); 1023ec21e2ecSJeff Kirsher 1024ec21e2ecSJeff Kirsher bcom_fec_rx_release(priv->rx_dmatsk); 1025ec21e2ecSJeff Kirsher bcom_fec_tx_release(priv->tx_dmatsk); 1026ec21e2ecSJeff Kirsher 1027ec21e2ecSJeff Kirsher iounmap(priv->fec); 1028ec21e2ecSJeff Kirsher 1029ec21e2ecSJeff Kirsher release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); 1030ec21e2ecSJeff Kirsher 1031ec21e2ecSJeff Kirsher free_netdev(ndev); 1032ec21e2ecSJeff Kirsher 1033ec21e2ecSJeff Kirsher return 0; 1034ec21e2ecSJeff Kirsher } 1035ec21e2ecSJeff Kirsher 1036ec21e2ecSJeff Kirsher #ifdef CONFIG_PM 1037ec21e2ecSJeff Kirsher static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) 1038ec21e2ecSJeff Kirsher { 10398513fbd8SJingoo Han struct net_device *dev = platform_get_drvdata(op); 1040ec21e2ecSJeff Kirsher 1041ec21e2ecSJeff Kirsher if (netif_running(dev)) 1042ec21e2ecSJeff Kirsher mpc52xx_fec_close(dev); 1043ec21e2ecSJeff Kirsher 1044ec21e2ecSJeff Kirsher return 0; 1045ec21e2ecSJeff Kirsher } 1046ec21e2ecSJeff Kirsher 1047ec21e2ecSJeff Kirsher static int mpc52xx_fec_of_resume(struct platform_device *op) 1048ec21e2ecSJeff Kirsher { 10498513fbd8SJingoo Han struct net_device *dev = platform_get_drvdata(op); 1050ec21e2ecSJeff Kirsher 1051ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(dev); 1052ec21e2ecSJeff Kirsher mpc52xx_fec_reset_stats(dev); 1053ec21e2ecSJeff Kirsher 1054ec21e2ecSJeff Kirsher if (netif_running(dev)) 1055ec21e2ecSJeff Kirsher mpc52xx_fec_open(dev); 1056ec21e2ecSJeff Kirsher 1057ec21e2ecSJeff Kirsher return 0; 1058ec21e2ecSJeff Kirsher } 1059ec21e2ecSJeff Kirsher #endif 1060ec21e2ecSJeff Kirsher 106194e5a2a8SFabian Frederick static const struct of_device_id mpc52xx_fec_match[] = { 1062ec21e2ecSJeff Kirsher { .compatible = "fsl,mpc5200b-fec", }, 1063ec21e2ecSJeff Kirsher { .compatible = "fsl,mpc5200-fec", }, 1064ec21e2ecSJeff Kirsher { .compatible = "mpc5200-fec", }, 1065ec21e2ecSJeff Kirsher { } 1066ec21e2ecSJeff Kirsher }; 1067ec21e2ecSJeff Kirsher 1068ec21e2ecSJeff Kirsher MODULE_DEVICE_TABLE(of, mpc52xx_fec_match); 1069ec21e2ecSJeff Kirsher 1070ec21e2ecSJeff Kirsher static struct platform_driver mpc52xx_fec_driver = { 1071ec21e2ecSJeff Kirsher .driver = { 1072ec21e2ecSJeff Kirsher .name = DRIVER_NAME, 1073ec21e2ecSJeff Kirsher .of_match_table = mpc52xx_fec_match, 1074ec21e2ecSJeff Kirsher }, 1075ec21e2ecSJeff Kirsher .probe = mpc52xx_fec_probe, 1076ec21e2ecSJeff Kirsher .remove = mpc52xx_fec_remove, 1077ec21e2ecSJeff Kirsher #ifdef CONFIG_PM 1078ec21e2ecSJeff Kirsher .suspend = mpc52xx_fec_of_suspend, 1079ec21e2ecSJeff Kirsher .resume = mpc52xx_fec_of_resume, 1080ec21e2ecSJeff Kirsher #endif 1081ec21e2ecSJeff Kirsher }; 1082ec21e2ecSJeff Kirsher 1083ec21e2ecSJeff Kirsher 1084ec21e2ecSJeff Kirsher /* ======================================================================== */ 1085ec21e2ecSJeff Kirsher /* Module */ 1086ec21e2ecSJeff Kirsher /* ======================================================================== */ 1087ec21e2ecSJeff Kirsher 10888c7d3972SThierry Reding static struct platform_driver * const drivers[] = { 10898c7d3972SThierry Reding #ifdef CONFIG_FEC_MPC52xx_MDIO 10908c7d3972SThierry Reding &mpc52xx_fec_mdio_driver, 10918c7d3972SThierry Reding #endif 10928c7d3972SThierry Reding &mpc52xx_fec_driver, 10938c7d3972SThierry Reding }; 10948c7d3972SThierry Reding 1095ec21e2ecSJeff Kirsher static int __init 1096ec21e2ecSJeff Kirsher mpc52xx_fec_init(void) 1097ec21e2ecSJeff Kirsher { 10988c7d3972SThierry Reding return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); 1099ec21e2ecSJeff Kirsher } 1100ec21e2ecSJeff Kirsher 1101ec21e2ecSJeff Kirsher static void __exit 1102ec21e2ecSJeff Kirsher mpc52xx_fec_exit(void) 1103ec21e2ecSJeff Kirsher { 11048c7d3972SThierry Reding platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); 1105ec21e2ecSJeff Kirsher } 1106ec21e2ecSJeff Kirsher 1107ec21e2ecSJeff Kirsher 1108ec21e2ecSJeff Kirsher module_init(mpc52xx_fec_init); 1109ec21e2ecSJeff Kirsher module_exit(mpc52xx_fec_exit); 1110ec21e2ecSJeff Kirsher 1111ec21e2ecSJeff Kirsher MODULE_LICENSE("GPL"); 1112ec21e2ecSJeff Kirsher MODULE_AUTHOR("Dale Farnsworth"); 1113ec21e2ecSJeff Kirsher MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); 1114