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 */ 30806983aa5SYueHaibing static netdev_tx_t 30906983aa5SYueHaibing mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) 310ec21e2ecSJeff Kirsher { 311ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 312ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 313ec21e2ecSJeff Kirsher unsigned long flags; 314ec21e2ecSJeff Kirsher 315ec21e2ecSJeff Kirsher if (bcom_queue_full(priv->tx_dmatsk)) { 316ec21e2ecSJeff Kirsher if (net_ratelimit()) 317ec21e2ecSJeff Kirsher dev_err(&dev->dev, "transmit queue overrun\n"); 318ec21e2ecSJeff Kirsher return NETDEV_TX_BUSY; 319ec21e2ecSJeff Kirsher } 320ec21e2ecSJeff Kirsher 321ec21e2ecSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 322ec21e2ecSJeff Kirsher 323ec21e2ecSJeff Kirsher bd = (struct bcom_fec_bd *) 324ec21e2ecSJeff Kirsher bcom_prepare_next_buffer(priv->tx_dmatsk); 325ec21e2ecSJeff Kirsher 326ec21e2ecSJeff Kirsher bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; 327ec21e2ecSJeff Kirsher bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len, 328ec21e2ecSJeff Kirsher DMA_TO_DEVICE); 329ec21e2ecSJeff Kirsher 330ec21e2ecSJeff Kirsher skb_tx_timestamp(skb); 331ec21e2ecSJeff Kirsher bcom_submit_next_buffer(priv->tx_dmatsk, skb); 332ec21e2ecSJeff Kirsher spin_unlock_irqrestore(&priv->lock, flags); 333ec21e2ecSJeff Kirsher 334ec21e2ecSJeff Kirsher if (bcom_queue_full(priv->tx_dmatsk)) { 335ec21e2ecSJeff Kirsher netif_stop_queue(dev); 336ec21e2ecSJeff Kirsher } 337ec21e2ecSJeff Kirsher 338ec21e2ecSJeff Kirsher return NETDEV_TX_OK; 339ec21e2ecSJeff Kirsher } 340ec21e2ecSJeff Kirsher 341ec21e2ecSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 342ec21e2ecSJeff Kirsher static void mpc52xx_fec_poll_controller(struct net_device *dev) 343ec21e2ecSJeff Kirsher { 344ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 345ec21e2ecSJeff Kirsher 346ec21e2ecSJeff Kirsher disable_irq(priv->t_irq); 347ec21e2ecSJeff Kirsher mpc52xx_fec_tx_interrupt(priv->t_irq, dev); 348ec21e2ecSJeff Kirsher enable_irq(priv->t_irq); 349ec21e2ecSJeff Kirsher disable_irq(priv->r_irq); 350ec21e2ecSJeff Kirsher mpc52xx_fec_rx_interrupt(priv->r_irq, dev); 351ec21e2ecSJeff Kirsher enable_irq(priv->r_irq); 352ec21e2ecSJeff Kirsher } 353ec21e2ecSJeff Kirsher #endif 354ec21e2ecSJeff Kirsher 355ec21e2ecSJeff Kirsher 356ec21e2ecSJeff Kirsher /* This handles BestComm transmit task interrupts 357ec21e2ecSJeff Kirsher */ 358ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) 359ec21e2ecSJeff Kirsher { 360ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 361ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 362ec21e2ecSJeff Kirsher 363ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 364ec21e2ecSJeff Kirsher while (bcom_buffer_done(priv->tx_dmatsk)) { 365ec21e2ecSJeff Kirsher struct sk_buff *skb; 366ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 367ec21e2ecSJeff Kirsher skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, 368ec21e2ecSJeff Kirsher (struct bcom_bd **)&bd); 369ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, 370ec21e2ecSJeff Kirsher DMA_TO_DEVICE); 371ec21e2ecSJeff Kirsher 372c50e964bSYang Wei dev_consume_skb_irq(skb); 373ec21e2ecSJeff Kirsher } 374ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 375ec21e2ecSJeff Kirsher 376ec21e2ecSJeff Kirsher netif_wake_queue(dev); 377ec21e2ecSJeff Kirsher 378ec21e2ecSJeff Kirsher return IRQ_HANDLED; 379ec21e2ecSJeff Kirsher } 380ec21e2ecSJeff Kirsher 381ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) 382ec21e2ecSJeff Kirsher { 383ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 384ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 385ec21e2ecSJeff Kirsher struct sk_buff *rskb; /* received sk_buff */ 386ec21e2ecSJeff Kirsher struct sk_buff *skb; /* new sk_buff to enqueue in its place */ 387ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 388ec21e2ecSJeff Kirsher u32 status, physaddr; 389ec21e2ecSJeff Kirsher int length; 390ec21e2ecSJeff Kirsher 391ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 392ec21e2ecSJeff Kirsher 393ec21e2ecSJeff Kirsher while (bcom_buffer_done(priv->rx_dmatsk)) { 394ec21e2ecSJeff Kirsher 395ec21e2ecSJeff Kirsher rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, 396ec21e2ecSJeff Kirsher (struct bcom_bd **)&bd); 397ec21e2ecSJeff Kirsher physaddr = bd->skb_pa; 398ec21e2ecSJeff Kirsher 399ec21e2ecSJeff Kirsher /* Test for errors in received frame */ 400ec21e2ecSJeff Kirsher if (status & BCOM_FEC_RX_BD_ERRORS) { 401ec21e2ecSJeff Kirsher /* Drop packet and reuse the buffer */ 402ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, rskb); 403ec21e2ecSJeff Kirsher dev->stats.rx_dropped++; 404ec21e2ecSJeff Kirsher continue; 405ec21e2ecSJeff Kirsher } 406ec21e2ecSJeff Kirsher 407ec21e2ecSJeff Kirsher /* skbs are allocated on open, so now we allocate a new one, 408ec21e2ecSJeff Kirsher * and remove the old (with the packet) */ 40921a4e469SPradeep A Dalvi skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); 410ec21e2ecSJeff Kirsher if (!skb) { 411ec21e2ecSJeff Kirsher /* Can't get a new one : reuse the same & drop pkt */ 412ec21e2ecSJeff Kirsher dev_notice(&dev->dev, "Low memory - dropped packet.\n"); 413ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, rskb); 414ec21e2ecSJeff Kirsher dev->stats.rx_dropped++; 415ec21e2ecSJeff Kirsher continue; 416ec21e2ecSJeff Kirsher } 417ec21e2ecSJeff Kirsher 418ec21e2ecSJeff Kirsher /* Enqueue the new sk_buff back on the hardware */ 419ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, skb); 420ec21e2ecSJeff Kirsher 421ec21e2ecSJeff Kirsher /* Process the received skb - Drop the spin lock while 422ec21e2ecSJeff Kirsher * calling into the network stack */ 423ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 424ec21e2ecSJeff Kirsher 425ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, physaddr, rskb->len, 426ec21e2ecSJeff Kirsher DMA_FROM_DEVICE); 427ec21e2ecSJeff Kirsher length = status & BCOM_FEC_RX_BD_LEN_MASK; 428ec21e2ecSJeff Kirsher skb_put(rskb, length - 4); /* length without CRC32 */ 429ec21e2ecSJeff Kirsher rskb->protocol = eth_type_trans(rskb, dev); 4309ca3cc6fSStephan Gatzka if (!skb_defer_rx_timestamp(rskb)) 431ec21e2ecSJeff Kirsher netif_rx(rskb); 432ec21e2ecSJeff Kirsher 433ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 434ec21e2ecSJeff Kirsher } 435ec21e2ecSJeff Kirsher 436ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 437ec21e2ecSJeff Kirsher 438ec21e2ecSJeff Kirsher return IRQ_HANDLED; 439ec21e2ecSJeff Kirsher } 440ec21e2ecSJeff Kirsher 441ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) 442ec21e2ecSJeff Kirsher { 443ec21e2ecSJeff Kirsher struct net_device *dev = dev_id; 444ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 445ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 446ec21e2ecSJeff Kirsher u32 ievent; 447ec21e2ecSJeff Kirsher 448ec21e2ecSJeff Kirsher ievent = in_be32(&fec->ievent); 449ec21e2ecSJeff Kirsher 450ec21e2ecSJeff Kirsher ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */ 451ec21e2ecSJeff Kirsher if (!ievent) 452ec21e2ecSJeff Kirsher return IRQ_NONE; 453ec21e2ecSJeff Kirsher 454ec21e2ecSJeff Kirsher out_be32(&fec->ievent, ievent); /* clear pending events */ 455ec21e2ecSJeff Kirsher 456ec21e2ecSJeff Kirsher /* on fifo error, soft-reset fec */ 457ec21e2ecSJeff Kirsher if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) { 458ec21e2ecSJeff Kirsher 459ec21e2ecSJeff Kirsher if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR)) 460ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n"); 461ec21e2ecSJeff Kirsher if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) 462ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); 463ec21e2ecSJeff Kirsher 464ec21e2ecSJeff Kirsher spin_lock(&priv->lock); 465ec21e2ecSJeff Kirsher mpc52xx_fec_reset(dev); 466ec21e2ecSJeff Kirsher spin_unlock(&priv->lock); 467ec21e2ecSJeff Kirsher 468ec21e2ecSJeff Kirsher return IRQ_HANDLED; 469ec21e2ecSJeff Kirsher } 470ec21e2ecSJeff Kirsher 471ec21e2ecSJeff Kirsher if (ievent & ~FEC_IEVENT_TFINT) 472ec21e2ecSJeff Kirsher dev_dbg(&dev->dev, "ievent: %08x\n", ievent); 473ec21e2ecSJeff Kirsher 474ec21e2ecSJeff Kirsher return IRQ_HANDLED; 475ec21e2ecSJeff Kirsher } 476ec21e2ecSJeff Kirsher 477ec21e2ecSJeff Kirsher /* 478ec21e2ecSJeff Kirsher * Get the current statistics. 479ec21e2ecSJeff Kirsher * This may be called with the card open or closed. 480ec21e2ecSJeff Kirsher */ 481ec21e2ecSJeff Kirsher static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev) 482ec21e2ecSJeff Kirsher { 483ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 484ec21e2ecSJeff Kirsher struct net_device_stats *stats = &dev->stats; 485ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 486ec21e2ecSJeff Kirsher 487ec21e2ecSJeff Kirsher stats->rx_bytes = in_be32(&fec->rmon_r_octets); 488ec21e2ecSJeff Kirsher stats->rx_packets = in_be32(&fec->rmon_r_packets); 489ec21e2ecSJeff Kirsher stats->rx_errors = in_be32(&fec->rmon_r_crc_align) + 490ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_undersize) + 491ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_oversize) + 492ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_frag) + 493ec21e2ecSJeff Kirsher in_be32(&fec->rmon_r_jab); 494ec21e2ecSJeff Kirsher 495ec21e2ecSJeff Kirsher stats->tx_bytes = in_be32(&fec->rmon_t_octets); 496ec21e2ecSJeff Kirsher stats->tx_packets = in_be32(&fec->rmon_t_packets); 497ec21e2ecSJeff Kirsher stats->tx_errors = in_be32(&fec->rmon_t_crc_align) + 498ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_undersize) + 499ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_oversize) + 500ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_frag) + 501ec21e2ecSJeff Kirsher in_be32(&fec->rmon_t_jab); 502ec21e2ecSJeff Kirsher 503ec21e2ecSJeff Kirsher stats->multicast = in_be32(&fec->rmon_r_mc_pkt); 504ec21e2ecSJeff Kirsher stats->collisions = in_be32(&fec->rmon_t_col); 505ec21e2ecSJeff Kirsher 506ec21e2ecSJeff Kirsher /* detailed rx_errors: */ 507ec21e2ecSJeff Kirsher stats->rx_length_errors = in_be32(&fec->rmon_r_undersize) 508ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_oversize) 509ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_frag) 510ec21e2ecSJeff Kirsher + in_be32(&fec->rmon_r_jab); 511ec21e2ecSJeff Kirsher stats->rx_over_errors = in_be32(&fec->r_macerr); 512ec21e2ecSJeff Kirsher stats->rx_crc_errors = in_be32(&fec->ieee_r_crc); 513ec21e2ecSJeff Kirsher stats->rx_frame_errors = in_be32(&fec->ieee_r_align); 514ec21e2ecSJeff Kirsher stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop); 515ec21e2ecSJeff Kirsher stats->rx_missed_errors = in_be32(&fec->rmon_r_drop); 516ec21e2ecSJeff Kirsher 517ec21e2ecSJeff Kirsher /* detailed tx_errors: */ 518ec21e2ecSJeff Kirsher stats->tx_aborted_errors = 0; 519ec21e2ecSJeff Kirsher stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr); 520ec21e2ecSJeff Kirsher stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop); 521ec21e2ecSJeff Kirsher stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe); 522ec21e2ecSJeff Kirsher stats->tx_window_errors = in_be32(&fec->ieee_t_lcol); 523ec21e2ecSJeff Kirsher 524ec21e2ecSJeff Kirsher return stats; 525ec21e2ecSJeff Kirsher } 526ec21e2ecSJeff Kirsher 527ec21e2ecSJeff Kirsher /* 528ec21e2ecSJeff Kirsher * Read MIB counters in order to reset them, 529ec21e2ecSJeff Kirsher * then zero all the stats fields in memory 530ec21e2ecSJeff Kirsher */ 531ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset_stats(struct net_device *dev) 532ec21e2ecSJeff Kirsher { 533ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 534ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 535ec21e2ecSJeff Kirsher 536ec21e2ecSJeff Kirsher out_be32(&fec->mib_control, FEC_MIB_DISABLE); 537ec21e2ecSJeff Kirsher memset_io(&fec->rmon_t_drop, 0, 538ec21e2ecSJeff Kirsher offsetof(struct mpc52xx_fec, reserved10) - 539ec21e2ecSJeff Kirsher offsetof(struct mpc52xx_fec, rmon_t_drop)); 540ec21e2ecSJeff Kirsher out_be32(&fec->mib_control, 0); 541ec21e2ecSJeff Kirsher 542ec21e2ecSJeff Kirsher memset(&dev->stats, 0, sizeof(dev->stats)); 543ec21e2ecSJeff Kirsher } 544ec21e2ecSJeff Kirsher 545ec21e2ecSJeff Kirsher /* 546ec21e2ecSJeff Kirsher * Set or clear the multicast filter for this adaptor. 547ec21e2ecSJeff Kirsher */ 548ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_multicast_list(struct net_device *dev) 549ec21e2ecSJeff Kirsher { 550ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 551ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 552ec21e2ecSJeff Kirsher u32 rx_control; 553ec21e2ecSJeff Kirsher 554ec21e2ecSJeff Kirsher rx_control = in_be32(&fec->r_cntrl); 555ec21e2ecSJeff Kirsher 556ec21e2ecSJeff Kirsher if (dev->flags & IFF_PROMISC) { 557ec21e2ecSJeff Kirsher rx_control |= FEC_RCNTRL_PROM; 558ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rx_control); 559ec21e2ecSJeff Kirsher } else { 560ec21e2ecSJeff Kirsher rx_control &= ~FEC_RCNTRL_PROM; 561ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rx_control); 562ec21e2ecSJeff Kirsher 563ec21e2ecSJeff Kirsher if (dev->flags & IFF_ALLMULTI) { 564ec21e2ecSJeff Kirsher out_be32(&fec->gaddr1, 0xffffffff); 565ec21e2ecSJeff Kirsher out_be32(&fec->gaddr2, 0xffffffff); 566ec21e2ecSJeff Kirsher } else { 567ec21e2ecSJeff Kirsher u32 crc; 568ec21e2ecSJeff Kirsher struct netdev_hw_addr *ha; 569ec21e2ecSJeff Kirsher u32 gaddr1 = 0x00000000; 570ec21e2ecSJeff Kirsher u32 gaddr2 = 0x00000000; 571ec21e2ecSJeff Kirsher 572ec21e2ecSJeff Kirsher netdev_for_each_mc_addr(ha, dev) { 573ec21e2ecSJeff Kirsher crc = ether_crc_le(6, ha->addr) >> 26; 574ec21e2ecSJeff Kirsher if (crc >= 32) 575ec21e2ecSJeff Kirsher gaddr1 |= 1 << (crc-32); 576ec21e2ecSJeff Kirsher else 577ec21e2ecSJeff Kirsher gaddr2 |= 1 << crc; 578ec21e2ecSJeff Kirsher } 579ec21e2ecSJeff Kirsher out_be32(&fec->gaddr1, gaddr1); 580ec21e2ecSJeff Kirsher out_be32(&fec->gaddr2, gaddr2); 581ec21e2ecSJeff Kirsher } 582ec21e2ecSJeff Kirsher } 583ec21e2ecSJeff Kirsher } 584ec21e2ecSJeff Kirsher 585ec21e2ecSJeff Kirsher /** 586ec21e2ecSJeff Kirsher * mpc52xx_fec_hw_init 587ec21e2ecSJeff Kirsher * @dev: network device 588ec21e2ecSJeff Kirsher * 589ec21e2ecSJeff Kirsher * Setup various hardware setting, only needed once on start 590ec21e2ecSJeff Kirsher */ 591ec21e2ecSJeff Kirsher static void mpc52xx_fec_hw_init(struct net_device *dev) 592ec21e2ecSJeff Kirsher { 593ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 594ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 595ec21e2ecSJeff Kirsher int i; 596ec21e2ecSJeff Kirsher 597ec21e2ecSJeff Kirsher /* Whack a reset. We should wait for this. */ 598ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); 599ec21e2ecSJeff Kirsher for (i = 0; i < FEC_RESET_DELAY; ++i) { 600ec21e2ecSJeff Kirsher if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) 601ec21e2ecSJeff Kirsher break; 602ec21e2ecSJeff Kirsher udelay(1); 603ec21e2ecSJeff Kirsher } 604ec21e2ecSJeff Kirsher if (i == FEC_RESET_DELAY) 605ec21e2ecSJeff Kirsher dev_err(&dev->dev, "FEC Reset timeout!\n"); 606ec21e2ecSJeff Kirsher 607ec21e2ecSJeff Kirsher /* set pause to 0x20 frames */ 608ec21e2ecSJeff Kirsher out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20); 609ec21e2ecSJeff Kirsher 610ec21e2ecSJeff Kirsher /* high service request will be deasserted when there's < 7 bytes in fifo 611ec21e2ecSJeff Kirsher * low service request will be deasserted when there's < 4*7 bytes in fifo 612ec21e2ecSJeff Kirsher */ 613ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); 614ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); 615ec21e2ecSJeff Kirsher 616ec21e2ecSJeff Kirsher /* alarm when <= x bytes in FIFO */ 617ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_alarm, 0x0000030c); 618ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_alarm, 0x00000100); 619ec21e2ecSJeff Kirsher 620ec21e2ecSJeff Kirsher /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */ 621ec21e2ecSJeff Kirsher out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B); 622ec21e2ecSJeff Kirsher 623ec21e2ecSJeff Kirsher /* enable crc generation */ 624ec21e2ecSJeff Kirsher out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC); 625ec21e2ecSJeff Kirsher out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */ 626ec21e2ecSJeff Kirsher out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */ 627ec21e2ecSJeff Kirsher 628ec21e2ecSJeff Kirsher /* set phy speed. 629ec21e2ecSJeff Kirsher * this can't be done in phy driver, since it needs to be called 630ec21e2ecSJeff Kirsher * before fec stuff (even on resume) */ 631ec21e2ecSJeff Kirsher out_be32(&fec->mii_speed, priv->mdio_speed); 632ec21e2ecSJeff Kirsher } 633ec21e2ecSJeff Kirsher 634ec21e2ecSJeff Kirsher /** 635ec21e2ecSJeff Kirsher * mpc52xx_fec_start 636ec21e2ecSJeff Kirsher * @dev: network device 637ec21e2ecSJeff Kirsher * 638ec21e2ecSJeff Kirsher * This function is called to start or restart the FEC during a link 639ec21e2ecSJeff Kirsher * change. This happens on fifo errors or when switching between half 640ec21e2ecSJeff Kirsher * and full duplex. 641ec21e2ecSJeff Kirsher */ 642ec21e2ecSJeff Kirsher static void mpc52xx_fec_start(struct net_device *dev) 643ec21e2ecSJeff Kirsher { 644ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 645ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 646ec21e2ecSJeff Kirsher u32 rcntrl; 647ec21e2ecSJeff Kirsher u32 tcntrl; 648ec21e2ecSJeff Kirsher u32 tmp; 649ec21e2ecSJeff Kirsher 650ec21e2ecSJeff Kirsher /* clear sticky error bits */ 651ec21e2ecSJeff Kirsher tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF; 652ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp); 653ec21e2ecSJeff Kirsher out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp); 654ec21e2ecSJeff Kirsher 655ec21e2ecSJeff Kirsher /* FIFOs will reset on mpc52xx_fec_enable */ 656ec21e2ecSJeff Kirsher out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET); 657ec21e2ecSJeff Kirsher 658ec21e2ecSJeff Kirsher /* Set station address. */ 659ec21e2ecSJeff Kirsher mpc52xx_fec_set_paddr(dev, dev->dev_addr); 660ec21e2ecSJeff Kirsher 661ec21e2ecSJeff Kirsher mpc52xx_fec_set_multicast_list(dev); 662ec21e2ecSJeff Kirsher 663ec21e2ecSJeff Kirsher /* set max frame len, enable flow control, select mii mode */ 664ec21e2ecSJeff Kirsher rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ 665ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_FCE; 666ec21e2ecSJeff Kirsher 667ec21e2ecSJeff Kirsher if (!priv->seven_wire_mode) 668ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_MII_MODE; 669ec21e2ecSJeff Kirsher 670ec21e2ecSJeff Kirsher if (priv->duplex == DUPLEX_FULL) 671ec21e2ecSJeff Kirsher tcntrl = FEC_TCNTRL_FDEN; /* FD enable */ 672ec21e2ecSJeff Kirsher else { 673ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ 674ec21e2ecSJeff Kirsher tcntrl = 0; 675ec21e2ecSJeff Kirsher } 676ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rcntrl); 677ec21e2ecSJeff Kirsher out_be32(&fec->x_cntrl, tcntrl); 678ec21e2ecSJeff Kirsher 679ec21e2ecSJeff Kirsher /* Clear any outstanding interrupt. */ 680ec21e2ecSJeff Kirsher out_be32(&fec->ievent, 0xffffffff); 681ec21e2ecSJeff Kirsher 682ec21e2ecSJeff Kirsher /* Enable interrupts we wish to service. */ 683ec21e2ecSJeff Kirsher out_be32(&fec->imask, FEC_IMASK_ENABLE); 684ec21e2ecSJeff Kirsher 685ec21e2ecSJeff Kirsher /* And last, enable the transmit and receive processing. */ 686ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN); 687ec21e2ecSJeff Kirsher out_be32(&fec->r_des_active, 0x01000000); 688ec21e2ecSJeff Kirsher } 689ec21e2ecSJeff Kirsher 690ec21e2ecSJeff Kirsher /** 691ec21e2ecSJeff Kirsher * mpc52xx_fec_stop 692ec21e2ecSJeff Kirsher * @dev: network device 693ec21e2ecSJeff Kirsher * 694ec21e2ecSJeff Kirsher * stop all activity on fec and empty dma buffers 695ec21e2ecSJeff Kirsher */ 696ec21e2ecSJeff Kirsher static void mpc52xx_fec_stop(struct net_device *dev) 697ec21e2ecSJeff Kirsher { 698ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 699ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 700ec21e2ecSJeff Kirsher unsigned long timeout; 701ec21e2ecSJeff Kirsher 702ec21e2ecSJeff Kirsher /* disable all interrupts */ 703ec21e2ecSJeff Kirsher out_be32(&fec->imask, 0); 704ec21e2ecSJeff Kirsher 705ec21e2ecSJeff Kirsher /* Disable the rx task. */ 706ec21e2ecSJeff Kirsher bcom_disable(priv->rx_dmatsk); 707ec21e2ecSJeff Kirsher 708ec21e2ecSJeff Kirsher /* Wait for tx queue to drain, but only if we're in process context */ 709ec21e2ecSJeff Kirsher if (!in_interrupt()) { 710ec21e2ecSJeff Kirsher timeout = jiffies + msecs_to_jiffies(2000); 711ec21e2ecSJeff Kirsher while (time_before(jiffies, timeout) && 712ec21e2ecSJeff Kirsher !bcom_queue_empty(priv->tx_dmatsk)) 713ec21e2ecSJeff Kirsher msleep(100); 714ec21e2ecSJeff Kirsher 715ec21e2ecSJeff Kirsher if (time_after_eq(jiffies, timeout)) 716ec21e2ecSJeff Kirsher dev_err(&dev->dev, "queues didn't drain\n"); 717ec21e2ecSJeff Kirsher #if 1 718ec21e2ecSJeff Kirsher if (time_after_eq(jiffies, timeout)) { 719ec21e2ecSJeff Kirsher dev_err(&dev->dev, " tx: index: %i, outdex: %i\n", 720ec21e2ecSJeff Kirsher priv->tx_dmatsk->index, 721ec21e2ecSJeff Kirsher priv->tx_dmatsk->outdex); 722ec21e2ecSJeff Kirsher dev_err(&dev->dev, " rx: index: %i, outdex: %i\n", 723ec21e2ecSJeff Kirsher priv->rx_dmatsk->index, 724ec21e2ecSJeff Kirsher priv->rx_dmatsk->outdex); 725ec21e2ecSJeff Kirsher } 726ec21e2ecSJeff Kirsher #endif 727ec21e2ecSJeff Kirsher } 728ec21e2ecSJeff Kirsher 729ec21e2ecSJeff Kirsher bcom_disable(priv->tx_dmatsk); 730ec21e2ecSJeff Kirsher 731ec21e2ecSJeff Kirsher /* Stop FEC */ 732ec21e2ecSJeff Kirsher out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); 733ec21e2ecSJeff Kirsher } 734ec21e2ecSJeff Kirsher 735ec21e2ecSJeff Kirsher /* reset fec and bestcomm tasks */ 736ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset(struct net_device *dev) 737ec21e2ecSJeff Kirsher { 738ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 739ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 740ec21e2ecSJeff Kirsher 741ec21e2ecSJeff Kirsher mpc52xx_fec_stop(dev); 742ec21e2ecSJeff Kirsher 743ec21e2ecSJeff Kirsher out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status)); 744ec21e2ecSJeff Kirsher out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO); 745ec21e2ecSJeff Kirsher 746ec21e2ecSJeff Kirsher mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); 747ec21e2ecSJeff Kirsher 748ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(dev); 749ec21e2ecSJeff Kirsher 750ec21e2ecSJeff Kirsher bcom_fec_rx_reset(priv->rx_dmatsk); 751ec21e2ecSJeff Kirsher bcom_fec_tx_reset(priv->tx_dmatsk); 752ec21e2ecSJeff Kirsher 753ec21e2ecSJeff Kirsher mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); 754ec21e2ecSJeff Kirsher 755ec21e2ecSJeff Kirsher bcom_enable(priv->rx_dmatsk); 756ec21e2ecSJeff Kirsher bcom_enable(priv->tx_dmatsk); 757ec21e2ecSJeff Kirsher 758ec21e2ecSJeff Kirsher mpc52xx_fec_start(dev); 759ec21e2ecSJeff Kirsher 760ec21e2ecSJeff Kirsher netif_wake_queue(dev); 761ec21e2ecSJeff Kirsher } 762ec21e2ecSJeff Kirsher 763ec21e2ecSJeff Kirsher 764ec21e2ecSJeff Kirsher /* ethtool interface */ 765ec21e2ecSJeff Kirsher 766ec21e2ecSJeff Kirsher static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) 767ec21e2ecSJeff Kirsher { 768ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 769ec21e2ecSJeff Kirsher return priv->msg_enable; 770ec21e2ecSJeff Kirsher } 771ec21e2ecSJeff Kirsher 772ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) 773ec21e2ecSJeff Kirsher { 774ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 775ec21e2ecSJeff Kirsher priv->msg_enable = level; 776ec21e2ecSJeff Kirsher } 777ec21e2ecSJeff Kirsher 778ec21e2ecSJeff Kirsher static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { 779ec21e2ecSJeff Kirsher .get_link = ethtool_op_get_link, 780ec21e2ecSJeff Kirsher .get_msglevel = mpc52xx_fec_get_msglevel, 781ec21e2ecSJeff Kirsher .set_msglevel = mpc52xx_fec_set_msglevel, 7820a4f2823SRichard Cochran .get_ts_info = ethtool_op_get_ts_info, 783b1725423SPhilippe Reynes .get_link_ksettings = phy_ethtool_get_link_ksettings, 784b1725423SPhilippe Reynes .set_link_ksettings = phy_ethtool_set_link_ksettings, 785ec21e2ecSJeff Kirsher }; 786ec21e2ecSJeff Kirsher 787ec21e2ecSJeff Kirsher 788ec21e2ecSJeff Kirsher static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 789ec21e2ecSJeff Kirsher { 790a54d20f8SPhilippe Reynes struct phy_device *phydev = dev->phydev; 791ec21e2ecSJeff Kirsher 792a54d20f8SPhilippe Reynes if (!phydev) 793ec21e2ecSJeff Kirsher return -ENOTSUPP; 794ec21e2ecSJeff Kirsher 795a54d20f8SPhilippe Reynes return phy_mii_ioctl(phydev, rq, cmd); 796ec21e2ecSJeff Kirsher } 797ec21e2ecSJeff Kirsher 798ec21e2ecSJeff Kirsher static const struct net_device_ops mpc52xx_fec_netdev_ops = { 799ec21e2ecSJeff Kirsher .ndo_open = mpc52xx_fec_open, 800ec21e2ecSJeff Kirsher .ndo_stop = mpc52xx_fec_close, 801ec21e2ecSJeff Kirsher .ndo_start_xmit = mpc52xx_fec_start_xmit, 802afc4b13dSJiri Pirko .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list, 803ec21e2ecSJeff Kirsher .ndo_set_mac_address = mpc52xx_fec_set_mac_address, 804ec21e2ecSJeff Kirsher .ndo_validate_addr = eth_validate_addr, 805ec21e2ecSJeff Kirsher .ndo_do_ioctl = mpc52xx_fec_ioctl, 806ec21e2ecSJeff Kirsher .ndo_tx_timeout = mpc52xx_fec_tx_timeout, 807ec21e2ecSJeff Kirsher .ndo_get_stats = mpc52xx_fec_get_stats, 808ec21e2ecSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 809ec21e2ecSJeff Kirsher .ndo_poll_controller = mpc52xx_fec_poll_controller, 810ec21e2ecSJeff Kirsher #endif 811ec21e2ecSJeff Kirsher }; 812ec21e2ecSJeff Kirsher 813ec21e2ecSJeff Kirsher /* ======================================================================== */ 814ec21e2ecSJeff Kirsher /* OF Driver */ 815ec21e2ecSJeff Kirsher /* ======================================================================== */ 816ec21e2ecSJeff Kirsher 81733897cc8SBill Pemberton static int mpc52xx_fec_probe(struct platform_device *op) 818ec21e2ecSJeff Kirsher { 819ec21e2ecSJeff Kirsher int rv; 820ec21e2ecSJeff Kirsher struct net_device *ndev; 821ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = NULL; 822ec21e2ecSJeff Kirsher struct resource mem; 823ec21e2ecSJeff Kirsher const u32 *prop; 824ec21e2ecSJeff Kirsher int prop_size; 825db98f081SStefan Roese struct device_node *np = op->dev.of_node; 826db98f081SStefan Roese const char *mac_addr; 827ec21e2ecSJeff Kirsher 828ec21e2ecSJeff Kirsher phys_addr_t rx_fifo; 829ec21e2ecSJeff Kirsher phys_addr_t tx_fifo; 830ec21e2ecSJeff Kirsher 831ec21e2ecSJeff Kirsher /* Get the ether ndev & it's private zone */ 832ec21e2ecSJeff Kirsher ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); 833ec21e2ecSJeff Kirsher if (!ndev) 834ec21e2ecSJeff Kirsher return -ENOMEM; 835ec21e2ecSJeff Kirsher 836ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 837ec21e2ecSJeff Kirsher priv->ndev = ndev; 838ec21e2ecSJeff Kirsher 839ec21e2ecSJeff Kirsher /* Reserve FEC control zone */ 840db98f081SStefan Roese rv = of_address_to_resource(np, 0, &mem); 841ec21e2ecSJeff Kirsher if (rv) { 84231b7720cSJoe Perches pr_err("Error while parsing device node resource\n"); 843ec21e2ecSJeff Kirsher goto err_netdev; 844ec21e2ecSJeff Kirsher } 845ec21e2ecSJeff Kirsher if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) { 84631b7720cSJoe Perches pr_err("invalid resource size (%lx < %x), check mpc52xx_devices.c\n", 847ec21e2ecSJeff Kirsher (unsigned long)resource_size(&mem), 848ec21e2ecSJeff Kirsher sizeof(struct mpc52xx_fec)); 849ec21e2ecSJeff Kirsher rv = -EINVAL; 850ec21e2ecSJeff Kirsher goto err_netdev; 851ec21e2ecSJeff Kirsher } 852ec21e2ecSJeff Kirsher 853ec21e2ecSJeff Kirsher if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), 854ec21e2ecSJeff Kirsher DRIVER_NAME)) { 855ec21e2ecSJeff Kirsher rv = -EBUSY; 856ec21e2ecSJeff Kirsher goto err_netdev; 857ec21e2ecSJeff Kirsher } 858ec21e2ecSJeff Kirsher 859ec21e2ecSJeff Kirsher /* Init ether ndev with what we have */ 860ec21e2ecSJeff Kirsher ndev->netdev_ops = &mpc52xx_fec_netdev_ops; 861ec21e2ecSJeff Kirsher ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; 862ec21e2ecSJeff Kirsher ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; 863ec21e2ecSJeff Kirsher ndev->base_addr = mem.start; 864ec21e2ecSJeff Kirsher SET_NETDEV_DEV(ndev, &op->dev); 865ec21e2ecSJeff Kirsher 866ec21e2ecSJeff Kirsher spin_lock_init(&priv->lock); 867ec21e2ecSJeff Kirsher 868ec21e2ecSJeff Kirsher /* ioremap the zones */ 869ec21e2ecSJeff Kirsher priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); 870ec21e2ecSJeff Kirsher 871ec21e2ecSJeff Kirsher if (!priv->fec) { 872ec21e2ecSJeff Kirsher rv = -ENOMEM; 873ec21e2ecSJeff Kirsher goto err_mem_region; 874ec21e2ecSJeff Kirsher } 875ec21e2ecSJeff Kirsher 876ec21e2ecSJeff Kirsher /* Bestcomm init */ 877ec21e2ecSJeff Kirsher rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); 878ec21e2ecSJeff Kirsher tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); 879ec21e2ecSJeff Kirsher 880ec21e2ecSJeff Kirsher priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); 881ec21e2ecSJeff Kirsher priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); 882ec21e2ecSJeff Kirsher 883ec21e2ecSJeff Kirsher if (!priv->rx_dmatsk || !priv->tx_dmatsk) { 88431b7720cSJoe Perches pr_err("Can not init SDMA tasks\n"); 885ec21e2ecSJeff Kirsher rv = -ENOMEM; 886ec21e2ecSJeff Kirsher goto err_rx_tx_dmatsk; 887ec21e2ecSJeff Kirsher } 888ec21e2ecSJeff Kirsher 889ec21e2ecSJeff Kirsher /* Get the IRQ we need one by one */ 890ec21e2ecSJeff Kirsher /* Control */ 891db98f081SStefan Roese ndev->irq = irq_of_parse_and_map(np, 0); 892ec21e2ecSJeff Kirsher 893ec21e2ecSJeff Kirsher /* RX */ 894ec21e2ecSJeff Kirsher priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); 895ec21e2ecSJeff Kirsher 896ec21e2ecSJeff Kirsher /* TX */ 897ec21e2ecSJeff Kirsher priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); 898ec21e2ecSJeff Kirsher 899db98f081SStefan Roese /* 900db98f081SStefan Roese * MAC address init: 901db98f081SStefan Roese * 902db98f081SStefan Roese * First try to read MAC address from DT 903db98f081SStefan Roese */ 904db98f081SStefan Roese mac_addr = of_get_mac_address(np); 905db98f081SStefan Roese if (mac_addr) { 906db98f081SStefan Roese memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); 907db98f081SStefan Roese } else { 908db98f081SStefan Roese struct mpc52xx_fec __iomem *fec = priv->fec; 909db98f081SStefan Roese 910db98f081SStefan Roese /* 911db98f081SStefan Roese * If the MAC addresse is not provided via DT then read 912db98f081SStefan Roese * it back from the controller regs 913db98f081SStefan Roese */ 914db98f081SStefan Roese *(u32 *)(&ndev->dev_addr[0]) = in_be32(&fec->paddr1); 915db98f081SStefan Roese *(u16 *)(&ndev->dev_addr[4]) = in_be32(&fec->paddr2) >> 16; 916db98f081SStefan Roese } 917db98f081SStefan Roese 918db98f081SStefan Roese /* 919db98f081SStefan Roese * Check if the MAC address is valid, if not get a random one 920db98f081SStefan Roese */ 921db98f081SStefan Roese if (!is_valid_ether_addr(ndev->dev_addr)) { 922db98f081SStefan Roese eth_hw_addr_random(ndev); 923db98f081SStefan Roese dev_warn(&ndev->dev, "using random MAC address %pM\n", 924db98f081SStefan Roese ndev->dev_addr); 925db98f081SStefan Roese } 926ec21e2ecSJeff Kirsher 927ec21e2ecSJeff Kirsher priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); 928ec21e2ecSJeff Kirsher 929ec21e2ecSJeff Kirsher /* 930ec21e2ecSJeff Kirsher * Link mode configuration 931ec21e2ecSJeff Kirsher */ 932ec21e2ecSJeff Kirsher 933ec21e2ecSJeff Kirsher /* Start with safe defaults for link connection */ 934ec21e2ecSJeff Kirsher priv->speed = 100; 935ec21e2ecSJeff Kirsher priv->duplex = DUPLEX_HALF; 936db98f081SStefan Roese priv->mdio_speed = ((mpc5xxx_get_bus_frequency(np) >> 20) / 5) << 1; 937ec21e2ecSJeff Kirsher 938ec21e2ecSJeff Kirsher /* The current speed preconfigures the speed of the MII link */ 939db98f081SStefan Roese prop = of_get_property(np, "current-speed", &prop_size); 940ec21e2ecSJeff Kirsher if (prop && (prop_size >= sizeof(u32) * 2)) { 941ec21e2ecSJeff Kirsher priv->speed = prop[0]; 942ec21e2ecSJeff Kirsher priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; 943ec21e2ecSJeff Kirsher } 944ec21e2ecSJeff Kirsher 945ec21e2ecSJeff Kirsher /* If there is a phy handle, then get the PHY node */ 946db98f081SStefan Roese priv->phy_node = of_parse_phandle(np, "phy-handle", 0); 947ec21e2ecSJeff Kirsher 948ec21e2ecSJeff Kirsher /* the 7-wire property means don't use MII mode */ 949db98f081SStefan Roese if (of_find_property(np, "fsl,7-wire-mode", NULL)) { 950ec21e2ecSJeff Kirsher priv->seven_wire_mode = 1; 951ec21e2ecSJeff Kirsher dev_info(&ndev->dev, "using 7-wire PHY mode\n"); 952ec21e2ecSJeff Kirsher } 953ec21e2ecSJeff Kirsher 954ec21e2ecSJeff Kirsher /* Hardware init */ 955ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(ndev); 956ec21e2ecSJeff Kirsher mpc52xx_fec_reset_stats(ndev); 957ec21e2ecSJeff Kirsher 958ec21e2ecSJeff Kirsher rv = register_netdev(ndev); 959ec21e2ecSJeff Kirsher if (rv < 0) 960ec21e2ecSJeff Kirsher goto err_node; 961ec21e2ecSJeff Kirsher 962ec21e2ecSJeff Kirsher /* We're done ! */ 9638513fbd8SJingoo Han platform_set_drvdata(op, ndev); 964f7ce9103SRob Herring netdev_info(ndev, "%pOF MAC %pM\n", 965f7ce9103SRob Herring op->dev.of_node, ndev->dev_addr); 966ec21e2ecSJeff Kirsher 967ec21e2ecSJeff Kirsher return 0; 968ec21e2ecSJeff Kirsher 969ec21e2ecSJeff Kirsher err_node: 970ec21e2ecSJeff Kirsher of_node_put(priv->phy_node); 971ec21e2ecSJeff Kirsher irq_dispose_mapping(ndev->irq); 972ec21e2ecSJeff Kirsher err_rx_tx_dmatsk: 973ec21e2ecSJeff Kirsher if (priv->rx_dmatsk) 974ec21e2ecSJeff Kirsher bcom_fec_rx_release(priv->rx_dmatsk); 975ec21e2ecSJeff Kirsher if (priv->tx_dmatsk) 976ec21e2ecSJeff Kirsher bcom_fec_tx_release(priv->tx_dmatsk); 977ec21e2ecSJeff Kirsher iounmap(priv->fec); 978ec21e2ecSJeff Kirsher err_mem_region: 979ec21e2ecSJeff Kirsher release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); 980ec21e2ecSJeff Kirsher err_netdev: 981ec21e2ecSJeff Kirsher free_netdev(ndev); 982ec21e2ecSJeff Kirsher 983ec21e2ecSJeff Kirsher return rv; 984ec21e2ecSJeff Kirsher } 985ec21e2ecSJeff Kirsher 986ec21e2ecSJeff Kirsher static int 987ec21e2ecSJeff Kirsher mpc52xx_fec_remove(struct platform_device *op) 988ec21e2ecSJeff Kirsher { 989ec21e2ecSJeff Kirsher struct net_device *ndev; 990ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv; 991ec21e2ecSJeff Kirsher 9928513fbd8SJingoo Han ndev = platform_get_drvdata(op); 993ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 994ec21e2ecSJeff Kirsher 995ec21e2ecSJeff Kirsher unregister_netdev(ndev); 996ec21e2ecSJeff Kirsher 997ec21e2ecSJeff Kirsher of_node_put(priv->phy_node); 998ec21e2ecSJeff Kirsher priv->phy_node = NULL; 999ec21e2ecSJeff Kirsher 1000ec21e2ecSJeff Kirsher irq_dispose_mapping(ndev->irq); 1001ec21e2ecSJeff Kirsher 1002ec21e2ecSJeff Kirsher bcom_fec_rx_release(priv->rx_dmatsk); 1003ec21e2ecSJeff Kirsher bcom_fec_tx_release(priv->tx_dmatsk); 1004ec21e2ecSJeff Kirsher 1005ec21e2ecSJeff Kirsher iounmap(priv->fec); 1006ec21e2ecSJeff Kirsher 1007ec21e2ecSJeff Kirsher release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); 1008ec21e2ecSJeff Kirsher 1009ec21e2ecSJeff Kirsher free_netdev(ndev); 1010ec21e2ecSJeff Kirsher 1011ec21e2ecSJeff Kirsher return 0; 1012ec21e2ecSJeff Kirsher } 1013ec21e2ecSJeff Kirsher 1014ec21e2ecSJeff Kirsher #ifdef CONFIG_PM 1015ec21e2ecSJeff Kirsher static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) 1016ec21e2ecSJeff Kirsher { 10178513fbd8SJingoo Han struct net_device *dev = platform_get_drvdata(op); 1018ec21e2ecSJeff Kirsher 1019ec21e2ecSJeff Kirsher if (netif_running(dev)) 1020ec21e2ecSJeff Kirsher mpc52xx_fec_close(dev); 1021ec21e2ecSJeff Kirsher 1022ec21e2ecSJeff Kirsher return 0; 1023ec21e2ecSJeff Kirsher } 1024ec21e2ecSJeff Kirsher 1025ec21e2ecSJeff Kirsher static int mpc52xx_fec_of_resume(struct platform_device *op) 1026ec21e2ecSJeff Kirsher { 10278513fbd8SJingoo Han struct net_device *dev = platform_get_drvdata(op); 1028ec21e2ecSJeff Kirsher 1029ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(dev); 1030ec21e2ecSJeff Kirsher mpc52xx_fec_reset_stats(dev); 1031ec21e2ecSJeff Kirsher 1032ec21e2ecSJeff Kirsher if (netif_running(dev)) 1033ec21e2ecSJeff Kirsher mpc52xx_fec_open(dev); 1034ec21e2ecSJeff Kirsher 1035ec21e2ecSJeff Kirsher return 0; 1036ec21e2ecSJeff Kirsher } 1037ec21e2ecSJeff Kirsher #endif 1038ec21e2ecSJeff Kirsher 103994e5a2a8SFabian Frederick static const struct of_device_id mpc52xx_fec_match[] = { 1040ec21e2ecSJeff Kirsher { .compatible = "fsl,mpc5200b-fec", }, 1041ec21e2ecSJeff Kirsher { .compatible = "fsl,mpc5200-fec", }, 1042ec21e2ecSJeff Kirsher { .compatible = "mpc5200-fec", }, 1043ec21e2ecSJeff Kirsher { } 1044ec21e2ecSJeff Kirsher }; 1045ec21e2ecSJeff Kirsher 1046ec21e2ecSJeff Kirsher MODULE_DEVICE_TABLE(of, mpc52xx_fec_match); 1047ec21e2ecSJeff Kirsher 1048ec21e2ecSJeff Kirsher static struct platform_driver mpc52xx_fec_driver = { 1049ec21e2ecSJeff Kirsher .driver = { 1050ec21e2ecSJeff Kirsher .name = DRIVER_NAME, 1051ec21e2ecSJeff Kirsher .of_match_table = mpc52xx_fec_match, 1052ec21e2ecSJeff Kirsher }, 1053ec21e2ecSJeff Kirsher .probe = mpc52xx_fec_probe, 1054ec21e2ecSJeff Kirsher .remove = mpc52xx_fec_remove, 1055ec21e2ecSJeff Kirsher #ifdef CONFIG_PM 1056ec21e2ecSJeff Kirsher .suspend = mpc52xx_fec_of_suspend, 1057ec21e2ecSJeff Kirsher .resume = mpc52xx_fec_of_resume, 1058ec21e2ecSJeff Kirsher #endif 1059ec21e2ecSJeff Kirsher }; 1060ec21e2ecSJeff Kirsher 1061ec21e2ecSJeff Kirsher 1062ec21e2ecSJeff Kirsher /* ======================================================================== */ 1063ec21e2ecSJeff Kirsher /* Module */ 1064ec21e2ecSJeff Kirsher /* ======================================================================== */ 1065ec21e2ecSJeff Kirsher 10668c7d3972SThierry Reding static struct platform_driver * const drivers[] = { 10678c7d3972SThierry Reding #ifdef CONFIG_FEC_MPC52xx_MDIO 10688c7d3972SThierry Reding &mpc52xx_fec_mdio_driver, 10698c7d3972SThierry Reding #endif 10708c7d3972SThierry Reding &mpc52xx_fec_driver, 10718c7d3972SThierry Reding }; 10728c7d3972SThierry Reding 1073ec21e2ecSJeff Kirsher static int __init 1074ec21e2ecSJeff Kirsher mpc52xx_fec_init(void) 1075ec21e2ecSJeff Kirsher { 10768c7d3972SThierry Reding return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); 1077ec21e2ecSJeff Kirsher } 1078ec21e2ecSJeff Kirsher 1079ec21e2ecSJeff Kirsher static void __exit 1080ec21e2ecSJeff Kirsher mpc52xx_fec_exit(void) 1081ec21e2ecSJeff Kirsher { 10828c7d3972SThierry Reding platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); 1083ec21e2ecSJeff Kirsher } 1084ec21e2ecSJeff Kirsher 1085ec21e2ecSJeff Kirsher 1086ec21e2ecSJeff Kirsher module_init(mpc52xx_fec_init); 1087ec21e2ecSJeff Kirsher module_exit(mpc52xx_fec_exit); 1088ec21e2ecSJeff Kirsher 1089ec21e2ecSJeff Kirsher MODULE_LICENSE("GPL"); 1090ec21e2ecSJeff Kirsher MODULE_AUTHOR("Dale Farnsworth"); 1091ec21e2ecSJeff Kirsher MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); 1092