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