/* * Driver for the MPC5200 Fast Ethernet Controller * * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and * now maintained by Sylvain Munaut <tnt@246tNt.com> * * Copyright (C) 2007 Domen Puncer, Telargo, Inc. * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com> * Copyright (C) 2003-2004 MontaVista, Software, Inc. * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. *
*/
if (phydev) { /* power down phy */
phy_stop(phydev);
phy_disconnect(phydev);
}
return0;
}
/* This will only be invoked if your driver is _not_ in XOFF state. * What this means is that you need not check it, and that this * invariant will hold if you make sure that the netif_*_queue() * calls are done at the proper times.
*/ static netdev_tx_t
mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct bcom_fec_bd *bd; unsignedlong flags;
if (bcom_queue_full(priv->tx_dmatsk)) { if (net_ratelimit())
dev_err(&dev->dev, "transmit queue overrun\n"); return NETDEV_TX_BUSY;
}
/* Test for errors in received frame */ if (status & BCOM_FEC_RX_BD_ERRORS) { /* Drop packet and reuse the buffer */
mpc52xx_fec_rx_submit(dev, rskb);
dev->stats.rx_dropped++; continue;
}
/* skbs are allocated on open, so now we allocate a new one,
* and remove the old (with the packet) */
skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); if (!skb) { /* Can't get a new one : reuse the same & drop pkt */
dev_notice(&dev->dev, "Low memory - dropped packet.\n");
mpc52xx_fec_rx_submit(dev, rskb);
dev->stats.rx_dropped++; continue;
}
/* Enqueue the new sk_buff back on the hardware */
mpc52xx_fec_rx_submit(dev, skb);
/* Process the received skb - Drop the spin lock while
* calling into the network stack */
spin_unlock(&priv->lock);
dma_unmap_single(dev->dev.parent, physaddr, rskb->len,
DMA_FROM_DEVICE);
length = status & BCOM_FEC_RX_BD_LEN_MASK;
skb_put(rskb, length - 4); /* length without CRC32 */
rskb->protocol = eth_type_trans(rskb, dev); if (!skb_defer_rx_timestamp(rskb))
netif_rx(rskb);
if (ievent & ~FEC_IEVENT_TFINT)
dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
return IRQ_HANDLED;
}
/* * Get the current statistics. * This may be called with the card open or closed.
*/ staticstruct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev)
{ struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct mpc52xx_fec __iomem *fec = priv->fec;
/* * Read MIB counters in order to reset them, * then zero all the stats fields in memory
*/ staticvoid mpc52xx_fec_reset_stats(struct net_device *dev)
{ struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct mpc52xx_fec __iomem *fec = priv->fec;
/** * mpc52xx_fec_hw_init * @dev: network device * * Setup various hardware setting, only needed once on start
*/ staticvoid mpc52xx_fec_hw_init(struct net_device *dev)
{ struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct mpc52xx_fec __iomem *fec = priv->fec; int i;
/* Whack a reset. We should wait for this. */
out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); for (i = 0; i < FEC_RESET_DELAY; ++i) { if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) break;
udelay(1);
} if (i == FEC_RESET_DELAY)
dev_err(&dev->dev, "FEC Reset timeout!\n");
/* set pause to 0x20 frames */
out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20);
/* high service request will be deasserted when there's < 7 bytes in fifo * low service request will be deasserted when there's < 4*7 bytes in fifo
*/
out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
/* alarm when <= x bytes in FIFO */
out_be32(&fec->rfifo_alarm, 0x0000030c);
out_be32(&fec->tfifo_alarm, 0x00000100);
/* begin transmission when 256 bytes are in FIFO (or EOF or FIFO full) */
out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B);
/* set phy speed. * this can't be done in phy driver, since it needs to be called
* before fec stuff (even on resume) */
out_be32(&fec->mii_speed, priv->mdio_speed);
}
/** * mpc52xx_fec_start * @dev: network device * * This function is called to start or restart the FEC during a link * change. This happens on fifo errors or when switching between half * and full duplex.
*/ staticvoid mpc52xx_fec_start(struct net_device *dev)
{ struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct mpc52xx_fec __iomem *fec = priv->fec;
u32 rcntrl;
u32 tcntrl;
u32 tmp;
/* disable all interrupts */
out_be32(&fec->imask, 0);
/* Disable the rx task. */
bcom_disable(priv->rx_dmatsk);
/* Wait for tx queue to drain, but only if we're in process context */ if (may_sleep) {
timeout = jiffies + msecs_to_jiffies(2000); while (time_before(jiffies, timeout) &&
!bcom_queue_empty(priv->tx_dmatsk))
msleep(100);
/* * MAC address init: * * First try to read MAC address from DT
*/
rv = of_get_ethdev_address(np, ndev); if (rv) { struct mpc52xx_fec __iomem *fec = priv->fec;
u8 addr[ETH_ALEN] __aligned(4);
/* * If the MAC addresse is not provided via DT then read * it back from the controller regs
*/
*(u32 *)(&addr[0]) = in_be32(&fec->paddr1);
*(u16 *)(&addr[4]) = in_be32(&fec->paddr2) >> 16;
eth_hw_addr_set(ndev, addr);
}
/* * Check if the MAC address is valid, if not get a random one
*/ if (!is_valid_ether_addr(ndev->dev_addr)) {
eth_hw_addr_random(ndev);
dev_warn(&ndev->dev, "using random MAC address %pM\n",
ndev->dev_addr);
}
/* Start with safe defaults for link connection */
priv->speed = 100;
priv->duplex = DUPLEX_HALF;
priv->mdio_speed = ((mpc5xxx_get_bus_frequency(&op->dev) >> 20) / 5) << 1;
/* The current speed preconfigures the speed of the MII link */
prop = of_get_property(np, "current-speed", &prop_size); if (prop && (prop_size >= sizeof(u32) * 2)) {
priv->speed = prop[0];
priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF;
}
/* If there is a phy handle, then get the PHY node */
priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
/* the 7-wire property means don't use MII mode */ if (of_property_read_bool(np, "fsl,7-wire-mode")) {
priv->seven_wire_mode = 1;
dev_info(&ndev->dev, "using 7-wire PHY mode\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dale Farnsworth");
MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.19Bemerkung:
(vorverarbeitet am 2026-06-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.