1213 lines · 28.4 KB · C
RawDownload
/* * Atmel MACB Ethernet Controller driver * * Copyright (C) 2004-2006 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/clk.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/mii.h>#include <linux/mutex.h>#include <linux/dma-mapping.h>#include <linux/ethtool.h>#include <linux/platform_device.h> #include <asm/arch/board.h> #include "macb.h" #define RX_BUFFER_SIZE		128#define RX_RING_SIZE		512#define RX_RING_BYTES		(sizeof(struct dma_desc) * RX_RING_SIZE) /* Make the IP header word-aligned (the ethernet header is 14 bytes) */#define RX_OFFSET		2 #define TX_RING_SIZE		128#define DEF_TX_RING_PENDING	(TX_RING_SIZE - 1)#define TX_RING_BYTES		(sizeof(struct dma_desc) * TX_RING_SIZE) #define TX_RING_GAP(bp)						\	(TX_RING_SIZE - (bp)->tx_pending)#define TX_BUFFS_AVAIL(bp)					\	(((bp)->tx_tail <= (bp)->tx_head) ?			\	 (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head :	\	 (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))#define NEXT_TX(n)		(((n) + 1) & (TX_RING_SIZE - 1)) #define NEXT_RX(n)		(((n) + 1) & (RX_RING_SIZE - 1)) /* minimum number of free TX descriptors before waking up TX process */#define MACB_TX_WAKEUP_THRESH	(TX_RING_SIZE / 4) #define MACB_RX_INT_FLAGS	(MACB_BIT(RCOMP) | MACB_BIT(RXUBR)	\				 | MACB_BIT(ISR_ROVR)) static void __macb_set_hwaddr(struct macb *bp){	u32 bottom;	u16 top; 	bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr));	macb_writel(bp, SA1B, bottom);	top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));	macb_writel(bp, SA1T, top);} static void __init macb_get_hwaddr(struct macb *bp){	u32 bottom;	u16 top;	u8 addr[6]; 	bottom = macb_readl(bp, SA1B);	top = macb_readl(bp, SA1T); 	addr[0] = bottom & 0xff;	addr[1] = (bottom >> 8) & 0xff;	addr[2] = (bottom >> 16) & 0xff;	addr[3] = (bottom >> 24) & 0xff;	addr[4] = top & 0xff;	addr[5] = (top >> 8) & 0xff; 	if (is_valid_ether_addr(addr))		memcpy(bp->dev->dev_addr, addr, sizeof(addr));} static void macb_enable_mdio(struct macb *bp){	unsigned long flags;	u32 reg; 	spin_lock_irqsave(&bp->lock, flags);	reg = macb_readl(bp, NCR);	reg |= MACB_BIT(MPE);	macb_writel(bp, NCR, reg);	macb_writel(bp, IER, MACB_BIT(MFD));	spin_unlock_irqrestore(&bp->lock, flags);} static void macb_disable_mdio(struct macb *bp){	unsigned long flags;	u32 reg; 	spin_lock_irqsave(&bp->lock, flags);	reg = macb_readl(bp, NCR);	reg &= ~MACB_BIT(MPE);	macb_writel(bp, NCR, reg);	macb_writel(bp, IDR, MACB_BIT(MFD));	spin_unlock_irqrestore(&bp->lock, flags);} static int macb_mdio_read(struct net_device *dev, int phy_id, int location){	struct macb *bp = netdev_priv(dev);	int value; 	mutex_lock(&bp->mdio_mutex); 	macb_enable_mdio(bp);	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)			      | MACB_BF(RW, MACB_MAN_READ)			      | MACB_BF(PHYA, phy_id)			      | MACB_BF(REGA, location)			      | MACB_BF(CODE, MACB_MAN_CODE))); 	wait_for_completion(&bp->mdio_complete); 	value = MACB_BFEXT(DATA, macb_readl(bp, MAN));	macb_disable_mdio(bp);	mutex_unlock(&bp->mdio_mutex); 	return value;} static void macb_mdio_write(struct net_device *dev, int phy_id,			    int location, int val){	struct macb *bp = netdev_priv(dev); 	dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",		phy_id, location, val); 	mutex_lock(&bp->mdio_mutex);	macb_enable_mdio(bp); 	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)			      | MACB_BF(RW, MACB_MAN_WRITE)			      | MACB_BF(PHYA, phy_id)			      | MACB_BF(REGA, location)			      | MACB_BF(CODE, MACB_MAN_CODE)			      | MACB_BF(DATA, val))); 	wait_for_completion(&bp->mdio_complete); 	macb_disable_mdio(bp);	mutex_unlock(&bp->mdio_mutex);} static int macb_phy_probe(struct macb *bp){	int phy_address;	u16 phyid1, phyid2; 	for (phy_address = 0; phy_address < 32; phy_address++) {		phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);		phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); 		if (phyid1 != 0xffff && phyid1 != 0x0000		    && phyid2 != 0xffff && phyid2 != 0x0000)			break;	} 	if (phy_address == 32)		return -ENODEV; 	dev_info(&bp->pdev->dev,		 "detected PHY at address %d (ID %04x:%04x)\n",		 phy_address, phyid1, phyid2); 	bp->mii.phy_id = phy_address;	return 0;} static void macb_set_media(struct macb *bp, int media){	u32 reg; 	spin_lock_irq(&bp->lock);	reg = macb_readl(bp, NCFGR);	reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));	if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))		reg |= MACB_BIT(SPD);	if (media & ADVERTISE_FULL)		reg |= MACB_BIT(FD);	macb_writel(bp, NCFGR, reg);	spin_unlock_irq(&bp->lock);} static void macb_check_media(struct macb *bp, int ok_to_print, int init_media){	struct mii_if_info *mii = &bp->mii;	unsigned int old_carrier, new_carrier;	int advertise, lpa, media, duplex; 	/* if forced media, go no further */	if (mii->force_media)		return; 	/* check current and old link status */	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;	new_carrier = (unsigned int) mii_link_ok(mii); 	/* if carrier state did not change, assume nothing else did */	if (!init_media && old_carrier == new_carrier)		return; 	/* no carrier, nothing much to do */	if (!new_carrier) {		netif_carrier_off(mii->dev);		printk(KERN_INFO "%s: link down\n", mii->dev->name);		return;	} 	/*	 * we have carrier, see who's on the other end	 */	netif_carrier_on(mii->dev); 	/* get MII advertise and LPA values */	if (!init_media && mii->advertising) {		advertise = mii->advertising;	} else {		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);		mii->advertising = advertise;	}	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); 	/* figure out media and duplex from advertise and LPA values */	media = mii_nway_result(lpa & advertise);	duplex = (media & ADVERTISE_FULL) ? 1 : 0; 	if (ok_to_print)		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",		       mii->dev->name,		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",		       duplex ? "full" : "half", lpa); 	mii->full_duplex = duplex; 	/* Let the MAC know about the new link state */	macb_set_media(bp, media);} static void macb_update_stats(struct macb *bp){	u32 __iomem *reg = bp->regs + MACB_PFR;	u32 *p = &bp->hw_stats.rx_pause_frames;	u32 *end = &bp->hw_stats.tx_pause_frames + 1; 	WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); 	for(; p < end; p++, reg++)		*p += __raw_readl(reg);} static void macb_periodic_task(struct work_struct *work){	struct macb *bp = container_of(work, struct macb, periodic_task.work); 	macb_update_stats(bp);	macb_check_media(bp, 1, 0); 	schedule_delayed_work(&bp->periodic_task, HZ);} static void macb_tx(struct macb *bp){	unsigned int tail;	unsigned int head;	u32 status; 	status = macb_readl(bp, TSR);	macb_writel(bp, TSR, status); 	dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n",		(unsigned long)status); 	if (status & MACB_BIT(UND)) {		printk(KERN_ERR "%s: TX underrun, resetting buffers\n",		       bp->dev->name);		bp->tx_head = bp->tx_tail = 0;	} 	if (!(status & MACB_BIT(COMP)))		/*		 * This may happen when a buffer becomes complete		 * between reading the ISR and scanning the		 * descriptors.  Nothing to worry about.		 */		return; 	head = bp->tx_head;	for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {		struct ring_info *rp = &bp->tx_skb[tail];		struct sk_buff *skb = rp->skb;		u32 bufstat; 		BUG_ON(skb == NULL); 		rmb();		bufstat = bp->tx_ring[tail].ctrl; 		if (!(bufstat & MACB_BIT(TX_USED)))			break; 		dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n",			tail, skb->data);		dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,				 DMA_TO_DEVICE);		bp->stats.tx_packets++;		bp->stats.tx_bytes += skb->len;		rp->skb = NULL;		dev_kfree_skb_irq(skb);	} 	bp->tx_tail = tail;	if (netif_queue_stopped(bp->dev) &&	    TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)		netif_wake_queue(bp->dev);} static int macb_rx_frame(struct macb *bp, unsigned int first_frag,			 unsigned int last_frag){	unsigned int len;	unsigned int frag;	unsigned int offset = 0;	struct sk_buff *skb; 	len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); 	dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n",		first_frag, last_frag, len); 	skb = dev_alloc_skb(len + RX_OFFSET);	if (!skb) {		bp->stats.rx_dropped++;		for (frag = first_frag; ; frag = NEXT_RX(frag)) {			bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);			if (frag == last_frag)				break;		}		wmb();		return 1;	} 	skb_reserve(skb, RX_OFFSET);	skb->dev = bp->dev;	skb->ip_summed = CHECKSUM_NONE;	skb_put(skb, len); 	for (frag = first_frag; ; frag = NEXT_RX(frag)) {		unsigned int frag_len = RX_BUFFER_SIZE; 		if (offset + frag_len > len) {			BUG_ON(frag != last_frag);			frag_len = len - offset;		}		memcpy(skb->data + offset,		       bp->rx_buffers + (RX_BUFFER_SIZE * frag),		       frag_len);		offset += RX_BUFFER_SIZE;		bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);		wmb(); 		if (frag == last_frag)			break;	} 	skb->protocol = eth_type_trans(skb, bp->dev); 	bp->stats.rx_packets++;	bp->stats.rx_bytes += len;	bp->dev->last_rx = jiffies;	dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n",		skb->len, skb->csum);	netif_receive_skb(skb); 	return 0;} /* Mark DMA descriptors from begin up to and not including end as unused */static void discard_partial_frame(struct macb *bp, unsigned int begin,				  unsigned int end){	unsigned int frag; 	for (frag = begin; frag != end; frag = NEXT_RX(frag))		bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);	wmb(); 	/*	 * When this happens, the hardware stats registers for	 * whatever caused this is updated, so we don't have to record	 * anything.	 */} static int macb_rx(struct macb *bp, int budget){	int received = 0;	unsigned int tail = bp->rx_tail;	int first_frag = -1; 	for (; budget > 0; tail = NEXT_RX(tail)) {		u32 addr, ctrl; 		rmb();		addr = bp->rx_ring[tail].addr;		ctrl = bp->rx_ring[tail].ctrl; 		if (!(addr & MACB_BIT(RX_USED)))			break; 		if (ctrl & MACB_BIT(RX_SOF)) {			if (first_frag != -1)				discard_partial_frame(bp, first_frag, tail);			first_frag = tail;		} 		if (ctrl & MACB_BIT(RX_EOF)) {			int dropped;			BUG_ON(first_frag == -1); 			dropped = macb_rx_frame(bp, first_frag, tail);			first_frag = -1;			if (!dropped) {				received++;				budget--;			}		}	} 	if (first_frag != -1)		bp->rx_tail = first_frag;	else		bp->rx_tail = tail; 	return received;} static int macb_poll(struct net_device *dev, int *budget){	struct macb *bp = netdev_priv(dev);	int orig_budget, work_done, retval = 0;	u32 status; 	status = macb_readl(bp, RSR);	macb_writel(bp, RSR, status); 	if (!status) {		/*		 * This may happen if an interrupt was pending before		 * this function was called last time, and no packets		 * have been received since.		 */		netif_rx_complete(dev);		goto out;	} 	dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n",		(unsigned long)status, *budget); 	if (!(status & MACB_BIT(REC))) {		dev_warn(&bp->pdev->dev,			 "No RX buffers complete, status = %02lx\n",			 (unsigned long)status);		netif_rx_complete(dev);		goto out;	} 	orig_budget = *budget;	if (orig_budget > dev->quota)		orig_budget = dev->quota; 	work_done = macb_rx(bp, orig_budget);	if (work_done < orig_budget) {		netif_rx_complete(dev);		retval = 0;	} else {		retval = 1;	} 	/*	 * We've done what we can to clean the buffers. Make sure we	 * get notified when new packets arrive.	 */out:

Lines 1–500 of 1213.