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 struct phy_device *phydev; 70ec21e2ecSJeff Kirsher enum phy_state link; 71ec21e2ecSJeff Kirsher int seven_wire_mode; 72ec21e2ecSJeff Kirsher }; 73ec21e2ecSJeff Kirsher 74ec21e2ecSJeff Kirsher 75ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_interrupt(int, void *); 76ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); 77ec21e2ecSJeff Kirsher static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); 78ec21e2ecSJeff Kirsher static void mpc52xx_fec_stop(struct net_device *dev); 79ec21e2ecSJeff Kirsher static void mpc52xx_fec_start(struct net_device *dev); 80ec21e2ecSJeff Kirsher static void mpc52xx_fec_reset(struct net_device *dev); 81ec21e2ecSJeff Kirsher 82ec21e2ecSJeff Kirsher #define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ 83ec21e2ecSJeff Kirsher NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) 84ec21e2ecSJeff Kirsher static int debug = -1; /* the above default */ 85ec21e2ecSJeff Kirsher module_param(debug, int, 0); 86ec21e2ecSJeff Kirsher MODULE_PARM_DESC(debug, "debugging messages level"); 87ec21e2ecSJeff Kirsher 88ec21e2ecSJeff Kirsher static void mpc52xx_fec_tx_timeout(struct net_device *dev) 89ec21e2ecSJeff Kirsher { 90ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 91ec21e2ecSJeff Kirsher unsigned long flags; 92ec21e2ecSJeff Kirsher 93ec21e2ecSJeff Kirsher dev_warn(&dev->dev, "transmit timed out\n"); 94ec21e2ecSJeff Kirsher 95ec21e2ecSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 96ec21e2ecSJeff Kirsher mpc52xx_fec_reset(dev); 97ec21e2ecSJeff Kirsher dev->stats.tx_errors++; 98ec21e2ecSJeff Kirsher spin_unlock_irqrestore(&priv->lock, flags); 99ec21e2ecSJeff Kirsher 100ec21e2ecSJeff Kirsher netif_wake_queue(dev); 101ec21e2ecSJeff Kirsher } 102ec21e2ecSJeff Kirsher 103ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) 104ec21e2ecSJeff Kirsher { 105ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 106ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 107ec21e2ecSJeff Kirsher 108ec21e2ecSJeff Kirsher out_be32(&fec->paddr1, *(u32 *)(&mac[0])); 109ec21e2ecSJeff Kirsher out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); 110ec21e2ecSJeff Kirsher } 111ec21e2ecSJeff Kirsher 112ec21e2ecSJeff Kirsher static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) 113ec21e2ecSJeff Kirsher { 114ec21e2ecSJeff Kirsher struct sockaddr *sock = addr; 115ec21e2ecSJeff Kirsher 116ec21e2ecSJeff Kirsher memcpy(dev->dev_addr, sock->sa_data, dev->addr_len); 117ec21e2ecSJeff Kirsher 118ec21e2ecSJeff Kirsher mpc52xx_fec_set_paddr(dev, sock->sa_data); 119ec21e2ecSJeff Kirsher return 0; 120ec21e2ecSJeff Kirsher } 121ec21e2ecSJeff Kirsher 122ec21e2ecSJeff Kirsher static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) 123ec21e2ecSJeff Kirsher { 124ec21e2ecSJeff Kirsher while (!bcom_queue_empty(s)) { 125ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 126ec21e2ecSJeff Kirsher struct sk_buff *skb; 127ec21e2ecSJeff Kirsher 128ec21e2ecSJeff Kirsher skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); 129ec21e2ecSJeff Kirsher dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, 130ec21e2ecSJeff Kirsher DMA_FROM_DEVICE); 131ec21e2ecSJeff Kirsher kfree_skb(skb); 132ec21e2ecSJeff Kirsher } 133ec21e2ecSJeff Kirsher } 134ec21e2ecSJeff Kirsher 135ec21e2ecSJeff Kirsher static void 136ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(struct net_device *dev, struct sk_buff *rskb) 137ec21e2ecSJeff Kirsher { 138ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 139ec21e2ecSJeff Kirsher struct bcom_fec_bd *bd; 140ec21e2ecSJeff Kirsher 141ec21e2ecSJeff Kirsher bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->rx_dmatsk); 142ec21e2ecSJeff Kirsher bd->status = FEC_RX_BUFFER_SIZE; 143ec21e2ecSJeff Kirsher bd->skb_pa = dma_map_single(dev->dev.parent, rskb->data, 144ec21e2ecSJeff Kirsher FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); 145ec21e2ecSJeff Kirsher bcom_submit_next_buffer(priv->rx_dmatsk, rskb); 146ec21e2ecSJeff Kirsher } 147ec21e2ecSJeff Kirsher 148ec21e2ecSJeff Kirsher static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) 149ec21e2ecSJeff Kirsher { 150ec21e2ecSJeff Kirsher struct sk_buff *skb; 151ec21e2ecSJeff Kirsher 152ec21e2ecSJeff Kirsher while (!bcom_queue_full(rxtsk)) { 15321a4e469SPradeep A Dalvi skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); 154ec21e2ecSJeff Kirsher if (!skb) 155ec21e2ecSJeff Kirsher return -EAGAIN; 156ec21e2ecSJeff Kirsher 157ec21e2ecSJeff Kirsher /* zero out the initial receive buffers to aid debugging */ 158ec21e2ecSJeff Kirsher memset(skb->data, 0, FEC_RX_BUFFER_SIZE); 159ec21e2ecSJeff Kirsher mpc52xx_fec_rx_submit(dev, skb); 160ec21e2ecSJeff Kirsher } 161ec21e2ecSJeff Kirsher return 0; 162ec21e2ecSJeff Kirsher } 163ec21e2ecSJeff Kirsher 164ec21e2ecSJeff Kirsher /* based on generic_adjust_link from fs_enet-main.c */ 165ec21e2ecSJeff Kirsher static void mpc52xx_fec_adjust_link(struct net_device *dev) 166ec21e2ecSJeff Kirsher { 167ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 168ec21e2ecSJeff Kirsher struct phy_device *phydev = priv->phydev; 169ec21e2ecSJeff Kirsher int new_state = 0; 170ec21e2ecSJeff Kirsher 171ec21e2ecSJeff Kirsher if (phydev->link != PHY_DOWN) { 172ec21e2ecSJeff Kirsher if (phydev->duplex != priv->duplex) { 173ec21e2ecSJeff Kirsher struct mpc52xx_fec __iomem *fec = priv->fec; 174ec21e2ecSJeff Kirsher u32 rcntrl; 175ec21e2ecSJeff Kirsher u32 tcntrl; 176ec21e2ecSJeff Kirsher 177ec21e2ecSJeff Kirsher new_state = 1; 178ec21e2ecSJeff Kirsher priv->duplex = phydev->duplex; 179ec21e2ecSJeff Kirsher 180ec21e2ecSJeff Kirsher rcntrl = in_be32(&fec->r_cntrl); 181ec21e2ecSJeff Kirsher tcntrl = in_be32(&fec->x_cntrl); 182ec21e2ecSJeff Kirsher 183ec21e2ecSJeff Kirsher rcntrl &= ~FEC_RCNTRL_DRT; 184ec21e2ecSJeff Kirsher tcntrl &= ~FEC_TCNTRL_FDEN; 185ec21e2ecSJeff Kirsher if (phydev->duplex == DUPLEX_FULL) 186ec21e2ecSJeff Kirsher tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */ 187ec21e2ecSJeff Kirsher else 188ec21e2ecSJeff Kirsher rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ 189ec21e2ecSJeff Kirsher 190ec21e2ecSJeff Kirsher out_be32(&fec->r_cntrl, rcntrl); 191ec21e2ecSJeff Kirsher out_be32(&fec->x_cntrl, tcntrl); 192ec21e2ecSJeff Kirsher } 193ec21e2ecSJeff Kirsher 194ec21e2ecSJeff Kirsher if (phydev->speed != priv->speed) { 195ec21e2ecSJeff Kirsher new_state = 1; 196ec21e2ecSJeff Kirsher priv->speed = phydev->speed; 197ec21e2ecSJeff Kirsher } 198ec21e2ecSJeff Kirsher 199ec21e2ecSJeff Kirsher if (priv->link == PHY_DOWN) { 200ec21e2ecSJeff Kirsher new_state = 1; 201ec21e2ecSJeff Kirsher priv->link = phydev->link; 202ec21e2ecSJeff Kirsher } 203ec21e2ecSJeff Kirsher 204ec21e2ecSJeff Kirsher } else if (priv->link) { 205ec21e2ecSJeff Kirsher new_state = 1; 206ec21e2ecSJeff Kirsher priv->link = PHY_DOWN; 207ec21e2ecSJeff Kirsher priv->speed = 0; 208ec21e2ecSJeff Kirsher priv->duplex = -1; 209ec21e2ecSJeff Kirsher } 210ec21e2ecSJeff Kirsher 211ec21e2ecSJeff Kirsher if (new_state && netif_msg_link(priv)) 212ec21e2ecSJeff Kirsher phy_print_status(phydev); 213ec21e2ecSJeff Kirsher } 214ec21e2ecSJeff Kirsher 215ec21e2ecSJeff Kirsher static int mpc52xx_fec_open(struct net_device *dev) 216ec21e2ecSJeff Kirsher { 217ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 218ec21e2ecSJeff Kirsher int err = -EBUSY; 219ec21e2ecSJeff Kirsher 220ec21e2ecSJeff Kirsher if (priv->phy_node) { 221ec21e2ecSJeff Kirsher priv->phydev = of_phy_connect(priv->ndev, priv->phy_node, 222ec21e2ecSJeff Kirsher mpc52xx_fec_adjust_link, 0, 0); 223ec21e2ecSJeff Kirsher if (!priv->phydev) { 224ec21e2ecSJeff Kirsher dev_err(&dev->dev, "of_phy_connect failed\n"); 225ec21e2ecSJeff Kirsher return -ENODEV; 226ec21e2ecSJeff Kirsher } 227ec21e2ecSJeff Kirsher phy_start(priv->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: 271ec21e2ecSJeff Kirsher if (priv->phydev) { 272ec21e2ecSJeff Kirsher phy_stop(priv->phydev); 273ec21e2ecSJeff Kirsher phy_disconnect(priv->phydev); 274ec21e2ecSJeff Kirsher priv->phydev = NULL; 275ec21e2ecSJeff Kirsher } 276ec21e2ecSJeff Kirsher 277ec21e2ecSJeff Kirsher return err; 278ec21e2ecSJeff Kirsher } 279ec21e2ecSJeff Kirsher 280ec21e2ecSJeff Kirsher static int mpc52xx_fec_close(struct net_device *dev) 281ec21e2ecSJeff Kirsher { 282ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 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 294ec21e2ecSJeff Kirsher if (priv->phydev) { 295ec21e2ecSJeff Kirsher /* power down phy */ 296ec21e2ecSJeff Kirsher phy_stop(priv->phydev); 297ec21e2ecSJeff Kirsher phy_disconnect(priv->phydev); 298ec21e2ecSJeff Kirsher priv->phydev = NULL; 299ec21e2ecSJeff Kirsher } 300ec21e2ecSJeff Kirsher 301ec21e2ecSJeff Kirsher return 0; 302ec21e2ecSJeff Kirsher } 303ec21e2ecSJeff Kirsher 304ec21e2ecSJeff Kirsher /* This will only be invoked if your driver is _not_ in XOFF state. 305ec21e2ecSJeff Kirsher * What this means is that you need not check it, and that this 306ec21e2ecSJeff Kirsher * invariant will hold if you make sure that the netif_*_queue() 307ec21e2ecSJeff Kirsher * calls are done at the proper times. 308ec21e2ecSJeff Kirsher */ 309ec21e2ecSJeff Kirsher static int 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 372ec21e2ecSJeff Kirsher dev_kfree_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 int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 767ec21e2ecSJeff Kirsher { 768ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 769ec21e2ecSJeff Kirsher 770ec21e2ecSJeff Kirsher if (!priv->phydev) 771ec21e2ecSJeff Kirsher return -ENODEV; 772ec21e2ecSJeff Kirsher 773ec21e2ecSJeff Kirsher return phy_ethtool_gset(priv->phydev, cmd); 774ec21e2ecSJeff Kirsher } 775ec21e2ecSJeff Kirsher 776ec21e2ecSJeff Kirsher static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 777ec21e2ecSJeff Kirsher { 778ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 779ec21e2ecSJeff Kirsher 780ec21e2ecSJeff Kirsher if (!priv->phydev) 781ec21e2ecSJeff Kirsher return -ENODEV; 782ec21e2ecSJeff Kirsher 783ec21e2ecSJeff Kirsher return phy_ethtool_sset(priv->phydev, cmd); 784ec21e2ecSJeff Kirsher } 785ec21e2ecSJeff Kirsher 786ec21e2ecSJeff Kirsher static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) 787ec21e2ecSJeff Kirsher { 788ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 789ec21e2ecSJeff Kirsher return priv->msg_enable; 790ec21e2ecSJeff Kirsher } 791ec21e2ecSJeff Kirsher 792ec21e2ecSJeff Kirsher static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) 793ec21e2ecSJeff Kirsher { 794ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 795ec21e2ecSJeff Kirsher priv->msg_enable = level; 796ec21e2ecSJeff Kirsher } 797ec21e2ecSJeff Kirsher 798ec21e2ecSJeff Kirsher static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { 799ec21e2ecSJeff Kirsher .get_settings = mpc52xx_fec_get_settings, 800ec21e2ecSJeff Kirsher .set_settings = mpc52xx_fec_set_settings, 801ec21e2ecSJeff Kirsher .get_link = ethtool_op_get_link, 802ec21e2ecSJeff Kirsher .get_msglevel = mpc52xx_fec_get_msglevel, 803ec21e2ecSJeff Kirsher .set_msglevel = mpc52xx_fec_set_msglevel, 8040a4f2823SRichard Cochran .get_ts_info = ethtool_op_get_ts_info, 805ec21e2ecSJeff Kirsher }; 806ec21e2ecSJeff Kirsher 807ec21e2ecSJeff Kirsher 808ec21e2ecSJeff Kirsher static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 809ec21e2ecSJeff Kirsher { 810ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = netdev_priv(dev); 811ec21e2ecSJeff Kirsher 812ec21e2ecSJeff Kirsher if (!priv->phydev) 813ec21e2ecSJeff Kirsher return -ENOTSUPP; 814ec21e2ecSJeff Kirsher 815ec21e2ecSJeff Kirsher return phy_mii_ioctl(priv->phydev, rq, cmd); 816ec21e2ecSJeff Kirsher } 817ec21e2ecSJeff Kirsher 818ec21e2ecSJeff Kirsher static const struct net_device_ops mpc52xx_fec_netdev_ops = { 819ec21e2ecSJeff Kirsher .ndo_open = mpc52xx_fec_open, 820ec21e2ecSJeff Kirsher .ndo_stop = mpc52xx_fec_close, 821ec21e2ecSJeff Kirsher .ndo_start_xmit = mpc52xx_fec_start_xmit, 822afc4b13dSJiri Pirko .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list, 823ec21e2ecSJeff Kirsher .ndo_set_mac_address = mpc52xx_fec_set_mac_address, 824ec21e2ecSJeff Kirsher .ndo_validate_addr = eth_validate_addr, 825ec21e2ecSJeff Kirsher .ndo_do_ioctl = mpc52xx_fec_ioctl, 826ec21e2ecSJeff Kirsher .ndo_change_mtu = eth_change_mtu, 827ec21e2ecSJeff Kirsher .ndo_tx_timeout = mpc52xx_fec_tx_timeout, 828ec21e2ecSJeff Kirsher .ndo_get_stats = mpc52xx_fec_get_stats, 829ec21e2ecSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 830ec21e2ecSJeff Kirsher .ndo_poll_controller = mpc52xx_fec_poll_controller, 831ec21e2ecSJeff Kirsher #endif 832ec21e2ecSJeff Kirsher }; 833ec21e2ecSJeff Kirsher 834ec21e2ecSJeff Kirsher /* ======================================================================== */ 835ec21e2ecSJeff Kirsher /* OF Driver */ 836ec21e2ecSJeff Kirsher /* ======================================================================== */ 837ec21e2ecSJeff Kirsher 83833897cc8SBill Pemberton static int mpc52xx_fec_probe(struct platform_device *op) 839ec21e2ecSJeff Kirsher { 840ec21e2ecSJeff Kirsher int rv; 841ec21e2ecSJeff Kirsher struct net_device *ndev; 842ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv = NULL; 843ec21e2ecSJeff Kirsher struct resource mem; 844ec21e2ecSJeff Kirsher const u32 *prop; 845ec21e2ecSJeff Kirsher int prop_size; 846db98f081SStefan Roese struct device_node *np = op->dev.of_node; 847db98f081SStefan Roese const char *mac_addr; 848ec21e2ecSJeff Kirsher 849ec21e2ecSJeff Kirsher phys_addr_t rx_fifo; 850ec21e2ecSJeff Kirsher phys_addr_t tx_fifo; 851ec21e2ecSJeff Kirsher 852ec21e2ecSJeff Kirsher /* Get the ether ndev & it's private zone */ 853ec21e2ecSJeff Kirsher ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); 854ec21e2ecSJeff Kirsher if (!ndev) 855ec21e2ecSJeff Kirsher return -ENOMEM; 856ec21e2ecSJeff Kirsher 857ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 858ec21e2ecSJeff Kirsher priv->ndev = ndev; 859ec21e2ecSJeff Kirsher 860ec21e2ecSJeff Kirsher /* Reserve FEC control zone */ 861db98f081SStefan Roese rv = of_address_to_resource(np, 0, &mem); 862ec21e2ecSJeff Kirsher if (rv) { 86331b7720cSJoe Perches pr_err("Error while parsing device node resource\n"); 864ec21e2ecSJeff Kirsher goto err_netdev; 865ec21e2ecSJeff Kirsher } 866ec21e2ecSJeff Kirsher if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) { 86731b7720cSJoe Perches pr_err("invalid resource size (%lx < %x), check mpc52xx_devices.c\n", 868ec21e2ecSJeff Kirsher (unsigned long)resource_size(&mem), 869ec21e2ecSJeff Kirsher sizeof(struct mpc52xx_fec)); 870ec21e2ecSJeff Kirsher rv = -EINVAL; 871ec21e2ecSJeff Kirsher goto err_netdev; 872ec21e2ecSJeff Kirsher } 873ec21e2ecSJeff Kirsher 874ec21e2ecSJeff Kirsher if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), 875ec21e2ecSJeff Kirsher DRIVER_NAME)) { 876ec21e2ecSJeff Kirsher rv = -EBUSY; 877ec21e2ecSJeff Kirsher goto err_netdev; 878ec21e2ecSJeff Kirsher } 879ec21e2ecSJeff Kirsher 880ec21e2ecSJeff Kirsher /* Init ether ndev with what we have */ 881ec21e2ecSJeff Kirsher ndev->netdev_ops = &mpc52xx_fec_netdev_ops; 882ec21e2ecSJeff Kirsher ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; 883ec21e2ecSJeff Kirsher ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; 884ec21e2ecSJeff Kirsher ndev->base_addr = mem.start; 885ec21e2ecSJeff Kirsher SET_NETDEV_DEV(ndev, &op->dev); 886ec21e2ecSJeff Kirsher 887ec21e2ecSJeff Kirsher spin_lock_init(&priv->lock); 888ec21e2ecSJeff Kirsher 889ec21e2ecSJeff Kirsher /* ioremap the zones */ 890ec21e2ecSJeff Kirsher priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); 891ec21e2ecSJeff Kirsher 892ec21e2ecSJeff Kirsher if (!priv->fec) { 893ec21e2ecSJeff Kirsher rv = -ENOMEM; 894ec21e2ecSJeff Kirsher goto err_mem_region; 895ec21e2ecSJeff Kirsher } 896ec21e2ecSJeff Kirsher 897ec21e2ecSJeff Kirsher /* Bestcomm init */ 898ec21e2ecSJeff Kirsher rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); 899ec21e2ecSJeff Kirsher tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); 900ec21e2ecSJeff Kirsher 901ec21e2ecSJeff Kirsher priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); 902ec21e2ecSJeff Kirsher priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); 903ec21e2ecSJeff Kirsher 904ec21e2ecSJeff Kirsher if (!priv->rx_dmatsk || !priv->tx_dmatsk) { 90531b7720cSJoe Perches pr_err("Can not init SDMA tasks\n"); 906ec21e2ecSJeff Kirsher rv = -ENOMEM; 907ec21e2ecSJeff Kirsher goto err_rx_tx_dmatsk; 908ec21e2ecSJeff Kirsher } 909ec21e2ecSJeff Kirsher 910ec21e2ecSJeff Kirsher /* Get the IRQ we need one by one */ 911ec21e2ecSJeff Kirsher /* Control */ 912db98f081SStefan Roese ndev->irq = irq_of_parse_and_map(np, 0); 913ec21e2ecSJeff Kirsher 914ec21e2ecSJeff Kirsher /* RX */ 915ec21e2ecSJeff Kirsher priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); 916ec21e2ecSJeff Kirsher 917ec21e2ecSJeff Kirsher /* TX */ 918ec21e2ecSJeff Kirsher priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); 919ec21e2ecSJeff Kirsher 920db98f081SStefan Roese /* 921db98f081SStefan Roese * MAC address init: 922db98f081SStefan Roese * 923db98f081SStefan Roese * First try to read MAC address from DT 924db98f081SStefan Roese */ 925db98f081SStefan Roese mac_addr = of_get_mac_address(np); 926db98f081SStefan Roese if (mac_addr) { 927db98f081SStefan Roese memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); 928db98f081SStefan Roese } else { 929db98f081SStefan Roese struct mpc52xx_fec __iomem *fec = priv->fec; 930db98f081SStefan Roese 931db98f081SStefan Roese /* 932db98f081SStefan Roese * If the MAC addresse is not provided via DT then read 933db98f081SStefan Roese * it back from the controller regs 934db98f081SStefan Roese */ 935db98f081SStefan Roese *(u32 *)(&ndev->dev_addr[0]) = in_be32(&fec->paddr1); 936db98f081SStefan Roese *(u16 *)(&ndev->dev_addr[4]) = in_be32(&fec->paddr2) >> 16; 937db98f081SStefan Roese } 938db98f081SStefan Roese 939db98f081SStefan Roese /* 940db98f081SStefan Roese * Check if the MAC address is valid, if not get a random one 941db98f081SStefan Roese */ 942db98f081SStefan Roese if (!is_valid_ether_addr(ndev->dev_addr)) { 943db98f081SStefan Roese eth_hw_addr_random(ndev); 944db98f081SStefan Roese dev_warn(&ndev->dev, "using random MAC address %pM\n", 945db98f081SStefan Roese ndev->dev_addr); 946db98f081SStefan Roese } 947ec21e2ecSJeff Kirsher 948ec21e2ecSJeff Kirsher priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); 949ec21e2ecSJeff Kirsher 950ec21e2ecSJeff Kirsher /* 951ec21e2ecSJeff Kirsher * Link mode configuration 952ec21e2ecSJeff Kirsher */ 953ec21e2ecSJeff Kirsher 954ec21e2ecSJeff Kirsher /* Start with safe defaults for link connection */ 955ec21e2ecSJeff Kirsher priv->speed = 100; 956ec21e2ecSJeff Kirsher priv->duplex = DUPLEX_HALF; 957db98f081SStefan Roese priv->mdio_speed = ((mpc5xxx_get_bus_frequency(np) >> 20) / 5) << 1; 958ec21e2ecSJeff Kirsher 959ec21e2ecSJeff Kirsher /* The current speed preconfigures the speed of the MII link */ 960db98f081SStefan Roese prop = of_get_property(np, "current-speed", &prop_size); 961ec21e2ecSJeff Kirsher if (prop && (prop_size >= sizeof(u32) * 2)) { 962ec21e2ecSJeff Kirsher priv->speed = prop[0]; 963ec21e2ecSJeff Kirsher priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; 964ec21e2ecSJeff Kirsher } 965ec21e2ecSJeff Kirsher 966ec21e2ecSJeff Kirsher /* If there is a phy handle, then get the PHY node */ 967db98f081SStefan Roese priv->phy_node = of_parse_phandle(np, "phy-handle", 0); 968ec21e2ecSJeff Kirsher 969ec21e2ecSJeff Kirsher /* the 7-wire property means don't use MII mode */ 970db98f081SStefan Roese if (of_find_property(np, "fsl,7-wire-mode", NULL)) { 971ec21e2ecSJeff Kirsher priv->seven_wire_mode = 1; 972ec21e2ecSJeff Kirsher dev_info(&ndev->dev, "using 7-wire PHY mode\n"); 973ec21e2ecSJeff Kirsher } 974ec21e2ecSJeff Kirsher 975ec21e2ecSJeff Kirsher /* Hardware init */ 976ec21e2ecSJeff Kirsher mpc52xx_fec_hw_init(ndev); 977ec21e2ecSJeff Kirsher mpc52xx_fec_reset_stats(ndev); 978ec21e2ecSJeff Kirsher 979ec21e2ecSJeff Kirsher rv = register_netdev(ndev); 980ec21e2ecSJeff Kirsher if (rv < 0) 981ec21e2ecSJeff Kirsher goto err_node; 982ec21e2ecSJeff Kirsher 983ec21e2ecSJeff Kirsher /* We're done ! */ 9848513fbd8SJingoo Han platform_set_drvdata(op, ndev); 98531b7720cSJoe Perches netdev_info(ndev, "%s MAC %pM\n", 98631b7720cSJoe Perches op->dev.of_node->full_name, ndev->dev_addr); 987ec21e2ecSJeff Kirsher 988ec21e2ecSJeff Kirsher return 0; 989ec21e2ecSJeff Kirsher 990ec21e2ecSJeff Kirsher err_node: 991ec21e2ecSJeff Kirsher of_node_put(priv->phy_node); 992ec21e2ecSJeff Kirsher irq_dispose_mapping(ndev->irq); 993ec21e2ecSJeff Kirsher err_rx_tx_dmatsk: 994ec21e2ecSJeff Kirsher if (priv->rx_dmatsk) 995ec21e2ecSJeff Kirsher bcom_fec_rx_release(priv->rx_dmatsk); 996ec21e2ecSJeff Kirsher if (priv->tx_dmatsk) 997ec21e2ecSJeff Kirsher bcom_fec_tx_release(priv->tx_dmatsk); 998ec21e2ecSJeff Kirsher iounmap(priv->fec); 999ec21e2ecSJeff Kirsher err_mem_region: 1000ec21e2ecSJeff Kirsher release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); 1001ec21e2ecSJeff Kirsher err_netdev: 1002ec21e2ecSJeff Kirsher free_netdev(ndev); 1003ec21e2ecSJeff Kirsher 1004ec21e2ecSJeff Kirsher return rv; 1005ec21e2ecSJeff Kirsher } 1006ec21e2ecSJeff Kirsher 1007ec21e2ecSJeff Kirsher static int 1008ec21e2ecSJeff Kirsher mpc52xx_fec_remove(struct platform_device *op) 1009ec21e2ecSJeff Kirsher { 1010ec21e2ecSJeff Kirsher struct net_device *ndev; 1011ec21e2ecSJeff Kirsher struct mpc52xx_fec_priv *priv; 1012ec21e2ecSJeff Kirsher 10138513fbd8SJingoo Han ndev = platform_get_drvdata(op); 1014ec21e2ecSJeff Kirsher priv = netdev_priv(ndev); 1015ec21e2ecSJeff Kirsher 1016ec21e2ecSJeff Kirsher unregister_netdev(ndev); 1017ec21e2ecSJeff Kirsher 1018ec21e2ecSJeff Kirsher if (priv->phy_node) 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 1061ec21e2ecSJeff Kirsher static 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 .owner = THIS_MODULE, 1074ec21e2ecSJeff Kirsher .of_match_table = mpc52xx_fec_match, 1075ec21e2ecSJeff Kirsher }, 1076ec21e2ecSJeff Kirsher .probe = mpc52xx_fec_probe, 1077ec21e2ecSJeff Kirsher .remove = mpc52xx_fec_remove, 1078ec21e2ecSJeff Kirsher #ifdef CONFIG_PM 1079ec21e2ecSJeff Kirsher .suspend = mpc52xx_fec_of_suspend, 1080ec21e2ecSJeff Kirsher .resume = mpc52xx_fec_of_resume, 1081ec21e2ecSJeff Kirsher #endif 1082ec21e2ecSJeff Kirsher }; 1083ec21e2ecSJeff Kirsher 1084ec21e2ecSJeff Kirsher 1085ec21e2ecSJeff Kirsher /* ======================================================================== */ 1086ec21e2ecSJeff Kirsher /* Module */ 1087ec21e2ecSJeff Kirsher /* ======================================================================== */ 1088ec21e2ecSJeff Kirsher 1089ec21e2ecSJeff Kirsher static int __init 1090ec21e2ecSJeff Kirsher mpc52xx_fec_init(void) 1091ec21e2ecSJeff Kirsher { 1092ec21e2ecSJeff Kirsher #ifdef CONFIG_FEC_MPC52xx_MDIO 1093ec21e2ecSJeff Kirsher int ret; 1094ec21e2ecSJeff Kirsher ret = platform_driver_register(&mpc52xx_fec_mdio_driver); 1095ec21e2ecSJeff Kirsher if (ret) { 109631b7720cSJoe Perches pr_err("failed to register mdio driver\n"); 1097ec21e2ecSJeff Kirsher return ret; 1098ec21e2ecSJeff Kirsher } 1099ec21e2ecSJeff Kirsher #endif 1100ec21e2ecSJeff Kirsher return platform_driver_register(&mpc52xx_fec_driver); 1101ec21e2ecSJeff Kirsher } 1102ec21e2ecSJeff Kirsher 1103ec21e2ecSJeff Kirsher static void __exit 1104ec21e2ecSJeff Kirsher mpc52xx_fec_exit(void) 1105ec21e2ecSJeff Kirsher { 1106ec21e2ecSJeff Kirsher platform_driver_unregister(&mpc52xx_fec_driver); 1107ec21e2ecSJeff Kirsher #ifdef CONFIG_FEC_MPC52xx_MDIO 1108ec21e2ecSJeff Kirsher platform_driver_unregister(&mpc52xx_fec_mdio_driver); 1109ec21e2ecSJeff Kirsher #endif 1110ec21e2ecSJeff Kirsher } 1111ec21e2ecSJeff Kirsher 1112ec21e2ecSJeff Kirsher 1113ec21e2ecSJeff Kirsher module_init(mpc52xx_fec_init); 1114ec21e2ecSJeff Kirsher module_exit(mpc52xx_fec_exit); 1115ec21e2ecSJeff Kirsher 1116ec21e2ecSJeff Kirsher MODULE_LICENSE("GPL"); 1117ec21e2ecSJeff Kirsher MODULE_AUTHOR("Dale Farnsworth"); 1118ec21e2ecSJeff Kirsher MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); 1119