forked from mirrors/linux
		
	[netdrvr] sh_eth: Add SH7619 support
Add support SH7619 Internal ethernet controler. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
		
							parent
							
								
									d91d4bb9db
								
							
						
					
					
						commit
						71557a37ad
					
				
					 4 changed files with 82 additions and 25 deletions
				
			
		
							
								
								
									
										11
									
								
								arch/sh/include/asm/sh_eth.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								arch/sh/include/asm/sh_eth.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
#ifndef __ASM_SH_ETH_H__
 | 
			
		||||
#define __ASM_SH_ETH_H__
 | 
			
		||||
 | 
			
		||||
enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
 | 
			
		||||
 | 
			
		||||
struct sh_eth_plat_data {
 | 
			
		||||
	int phy;
 | 
			
		||||
	int edmac_endian;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -510,14 +510,15 @@ config STNIC
 | 
			
		|||
config SH_ETH
 | 
			
		||||
	tristate "Renesas SuperH Ethernet support"
 | 
			
		||||
	depends on SUPERH && \
 | 
			
		||||
		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763)
 | 
			
		||||
		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763 || \
 | 
			
		||||
		 CPU_SUBTYPE_SH7619)
 | 
			
		||||
	select CRC32
 | 
			
		||||
	select MII
 | 
			
		||||
	select MDIO_BITBANG
 | 
			
		||||
	select PHYLIB
 | 
			
		||||
	help
 | 
			
		||||
	  Renesas SuperH Ethernet device driver.
 | 
			
		||||
	  This driver support SH7710, SH7712 and SH7763.
 | 
			
		||||
	  This driver support SH7710, SH7712, SH7763 and SH7619.
 | 
			
		||||
 | 
			
		||||
config SUNLANCE
 | 
			
		||||
	tristate "Sun LANCE support"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,29 @@
 | 
			
		|||
 | 
			
		||||
#include "sh_eth.h"
 | 
			
		||||
 | 
			
		||||
/* CPU <-> EDMAC endian convert */
 | 
			
		||||
static inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
 | 
			
		||||
{
 | 
			
		||||
	switch (mdp->edmac_endian) {
 | 
			
		||||
	case EDMAC_LITTLE_ENDIAN:
 | 
			
		||||
		return cpu_to_le32(x);
 | 
			
		||||
	case EDMAC_BIG_ENDIAN:
 | 
			
		||||
		return cpu_to_be32(x);
 | 
			
		||||
	}
 | 
			
		||||
	return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
 | 
			
		||||
{
 | 
			
		||||
	switch (mdp->edmac_endian) {
 | 
			
		||||
	case EDMAC_LITTLE_ENDIAN:
 | 
			
		||||
		return le32_to_cpu(x);
 | 
			
		||||
	case EDMAC_BIG_ENDIAN:
 | 
			
		||||
		return be32_to_cpu(x);
 | 
			
		||||
	}
 | 
			
		||||
	return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Program the hardware MAC address from dev->dev_addr.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -240,7 +263,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
 | 
			
		|||
		/* RX descriptor */
 | 
			
		||||
		rxdesc = &mdp->rx_ring[i];
 | 
			
		||||
		rxdesc->addr = (u32)skb->data & ~0x3UL;
 | 
			
		||||
		rxdesc->status = cpu_to_le32(RD_RACT | RD_RFP);
 | 
			
		||||
		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 | 
			
		||||
 | 
			
		||||
		/* The size of the buffer is 16 byte boundary. */
 | 
			
		||||
		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +285,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
 | 
			
		|||
	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* Mark the last entry as wrapping the ring. */
 | 
			
		||||
	rxdesc->status |= cpu_to_le32(RD_RDEL);
 | 
			
		||||
	rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
 | 
			
		||||
 | 
			
		||||
	memset(mdp->tx_ring, 0, tx_ringsize);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -270,10 +293,10 @@ static void sh_eth_ring_format(struct net_device *ndev)
 | 
			
		|||
	for (i = 0; i < TX_RING_SIZE; i++) {
 | 
			
		||||
		mdp->tx_skbuff[i] = NULL;
 | 
			
		||||
		txdesc = &mdp->tx_ring[i];
 | 
			
		||||
		txdesc->status = cpu_to_le32(TD_TFP);
 | 
			
		||||
		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
 | 
			
		||||
		txdesc->buffer_length = 0;
 | 
			
		||||
		if (i == 0) {
 | 
			
		||||
			/* Rx descriptor address set */
 | 
			
		||||
			/* Tx descriptor address set */
 | 
			
		||||
			ctrl_outl((u32)txdesc, ioaddr + TDLAR);
 | 
			
		||||
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
 | 
			
		||||
			ctrl_outl((u32)txdesc, ioaddr + TDFAR);
 | 
			
		||||
| 
						 | 
				
			
			@ -281,13 +304,13 @@ static void sh_eth_ring_format(struct net_device *ndev)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Rx descriptor address set */
 | 
			
		||||
	/* Tx descriptor address set */
 | 
			
		||||
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
 | 
			
		||||
	ctrl_outl((u32)txdesc, ioaddr + TDFXR);
 | 
			
		||||
	ctrl_outl(0x1, ioaddr + TDFFR);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	txdesc->status |= cpu_to_le32(TD_TDLE);
 | 
			
		||||
	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get skb and descriptor buffer */
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +478,7 @@ static int sh_eth_txfree(struct net_device *ndev)
 | 
			
		|||
	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
 | 
			
		||||
		entry = mdp->dirty_tx % TX_RING_SIZE;
 | 
			
		||||
		txdesc = &mdp->tx_ring[entry];
 | 
			
		||||
		if (txdesc->status & cpu_to_le32(TD_TACT))
 | 
			
		||||
		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
 | 
			
		||||
			break;
 | 
			
		||||
		/* Free the original skb. */
 | 
			
		||||
		if (mdp->tx_skbuff[entry]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -463,9 +486,9 @@ static int sh_eth_txfree(struct net_device *ndev)
 | 
			
		|||
			mdp->tx_skbuff[entry] = NULL;
 | 
			
		||||
			freeNum++;
 | 
			
		||||
		}
 | 
			
		||||
		txdesc->status = cpu_to_le32(TD_TFP);
 | 
			
		||||
		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
 | 
			
		||||
		if (entry >= TX_RING_SIZE - 1)
 | 
			
		||||
			txdesc->status |= cpu_to_le32(TD_TDLE);
 | 
			
		||||
			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
 | 
			
		||||
 | 
			
		||||
		mdp->stats.tx_packets++;
 | 
			
		||||
		mdp->stats.tx_bytes += txdesc->buffer_length;
 | 
			
		||||
| 
						 | 
				
			
			@ -486,8 +509,8 @@ static int sh_eth_rx(struct net_device *ndev)
 | 
			
		|||
	u32 desc_status, reserve = 0;
 | 
			
		||||
 | 
			
		||||
	rxdesc = &mdp->rx_ring[entry];
 | 
			
		||||
	while (!(rxdesc->status & cpu_to_le32(RD_RACT))) {
 | 
			
		||||
		desc_status = le32_to_cpu(rxdesc->status);
 | 
			
		||||
	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
 | 
			
		||||
		desc_status = edmac_to_cpu(mdp, rxdesc->status);
 | 
			
		||||
		pkt_len = rxdesc->frame_length;
 | 
			
		||||
 | 
			
		||||
		if (--boguscnt < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -522,7 +545,7 @@ static int sh_eth_rx(struct net_device *ndev)
 | 
			
		|||
			mdp->stats.rx_packets++;
 | 
			
		||||
			mdp->stats.rx_bytes += pkt_len;
 | 
			
		||||
		}
 | 
			
		||||
		rxdesc->status |= cpu_to_le32(RD_RACT);
 | 
			
		||||
		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
 | 
			
		||||
		entry = (++mdp->cur_rx) % RX_RING_SIZE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -552,10 +575,10 @@ static int sh_eth_rx(struct net_device *ndev)
 | 
			
		|||
		}
 | 
			
		||||
		if (entry >= RX_RING_SIZE - 1)
 | 
			
		||||
			rxdesc->status |=
 | 
			
		||||
				cpu_to_le32(RD_RACT | RD_RFP | RD_RDEL);
 | 
			
		||||
				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
 | 
			
		||||
		else
 | 
			
		||||
			rxdesc->status |=
 | 
			
		||||
				cpu_to_le32(RD_RACT | RD_RFP);
 | 
			
		||||
				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Restart Rx engine if stopped. */
 | 
			
		||||
| 
						 | 
				
			
			@ -931,9 +954,9 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 | 
			
		|||
		txdesc->buffer_length = skb->len;
 | 
			
		||||
 | 
			
		||||
	if (entry >= TX_RING_SIZE - 1)
 | 
			
		||||
		txdesc->status |= cpu_to_le32(TD_TACT | TD_TDLE);
 | 
			
		||||
		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
 | 
			
		||||
	else
 | 
			
		||||
		txdesc->status |= cpu_to_le32(TD_TACT);
 | 
			
		||||
		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
 | 
			
		||||
 | 
			
		||||
	mdp->cur_tx++;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1159,6 +1182,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 | 
			
		|||
	struct resource *res;
 | 
			
		||||
	struct net_device *ndev = NULL;
 | 
			
		||||
	struct sh_eth_private *mdp;
 | 
			
		||||
	struct sh_eth_plat_data *pd;
 | 
			
		||||
 | 
			
		||||
	/* get base addr */
 | 
			
		||||
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1196,8 +1220,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 | 
			
		|||
	mdp = netdev_priv(ndev);
 | 
			
		||||
	spin_lock_init(&mdp->lock);
 | 
			
		||||
 | 
			
		||||
	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
 | 
			
		||||
	/* get PHY ID */
 | 
			
		||||
	mdp->phy_id = (int)pdev->dev.platform_data;
 | 
			
		||||
	mdp->phy_id = pd->phy;
 | 
			
		||||
	/* EDMAC endian */
 | 
			
		||||
	mdp->edmac_endian = pd->edmac_endian;
 | 
			
		||||
 | 
			
		||||
	/* set function */
 | 
			
		||||
	ndev->open = sh_eth_open;
 | 
			
		||||
| 
						 | 
				
			
			@ -1217,12 +1244,16 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 | 
			
		|||
 | 
			
		||||
	/* First device only init */
 | 
			
		||||
	if (!devno) {
 | 
			
		||||
#if defined(ARSTR)
 | 
			
		||||
		/* reset device */
 | 
			
		||||
		ctrl_outl(ARSTR_ARSTR, ARSTR);
 | 
			
		||||
		mdelay(1);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(SH_TSU_ADDR)
 | 
			
		||||
		/* TSU init (Init only)*/
 | 
			
		||||
		sh_eth_tsu_init(SH_TSU_ADDR);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* network device register */
 | 
			
		||||
| 
						 | 
				
			
			@ -1240,8 +1271,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 | 
			
		|||
	       ndev->name, CARDNAME, (u32) ndev->base_addr);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 5; i++)
 | 
			
		||||
		printk(KERN_INFO "%02X:", ndev->dev_addr[i]);
 | 
			
		||||
	printk(KERN_INFO "%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);
 | 
			
		||||
		printk("%02X:", ndev->dev_addr[i]);
 | 
			
		||||
	printk("%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);
 | 
			
		||||
 | 
			
		||||
	platform_set_drvdata(pdev, ndev);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,8 @@
 | 
			
		|||
#include <linux/netdevice.h>
 | 
			
		||||
#include <linux/phy.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/sh_eth.h>
 | 
			
		||||
 | 
			
		||||
#define CARDNAME	"sh-eth"
 | 
			
		||||
#define TX_TIMEOUT	(5*HZ)
 | 
			
		||||
#define TX_RING_SIZE	64	/* Tx ring size */
 | 
			
		||||
| 
						 | 
				
			
			@ -143,10 +145,11 @@
 | 
			
		|||
 | 
			
		||||
#else /* CONFIG_CPU_SUBTYPE_SH7763 */
 | 
			
		||||
# define RX_OFFSET 2	/* skb offset */
 | 
			
		||||
#ifndef CONFIG_CPU_SUBTYPE_SH7619
 | 
			
		||||
/* Chip base address */
 | 
			
		||||
# define SH_TSU_ADDR  0xA7000804
 | 
			
		||||
# define ARSTR		  0xA7000800
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
/* Chip Registers */
 | 
			
		||||
/* E-DMAC */
 | 
			
		||||
# define EDMR	0x0000
 | 
			
		||||
| 
						 | 
				
			
			@ -384,7 +387,11 @@ enum FCFTR_BIT {
 | 
			
		|||
	FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001,
 | 
			
		||||
};
 | 
			
		||||
#define FIFO_F_D_RFF	(FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0)
 | 
			
		||||
#ifndef CONFIG_CPU_SUBTYPE_SH7619
 | 
			
		||||
#define FIFO_F_D_RFD	(FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0)
 | 
			
		||||
#else
 | 
			
		||||
#define FIFO_F_D_RFD	(FCFTR_RFD0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Transfer descriptor bit */
 | 
			
		||||
enum TD_STS_BIT {
 | 
			
		||||
| 
						 | 
				
			
			@ -414,8 +421,10 @@ enum FELIC_MODE_BIT {
 | 
			
		|||
#ifdef CONFIG_CPU_SUBTYPE_SH7763
 | 
			
		||||
#define ECMR_CHG_DM	(ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\
 | 
			
		||||
			ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
 | 
			
		||||
#elif CONFIG_CPU_SUBTYPE_SH7619
 | 
			
		||||
#define ECMR_CHG_DM	(ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF)
 | 
			
		||||
#else
 | 
			
		||||
#define ECMR_CHG_DM	(ECMR_ZPF | ECMR_PFR ECMR_RXF | ECMR_TXF | ECMR_MCT)
 | 
			
		||||
#define ECMR_CHG_DM	(ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ECSR */
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +494,11 @@ enum RPADIR_BIT {
 | 
			
		|||
 | 
			
		||||
/* FDR */
 | 
			
		||||
enum FIFO_SIZE_BIT {
 | 
			
		||||
#ifndef CONFIG_CPU_SUBTYPE_SH7619
 | 
			
		||||
	FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
 | 
			
		||||
#else
 | 
			
		||||
	FIFO_SIZE_T = 0x00000100, FIFO_SIZE_R = 0x00000001,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
enum phy_offsets {
 | 
			
		||||
	PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
 | 
			
		||||
| 
						 | 
				
			
			@ -601,7 +614,7 @@ struct sh_eth_txdesc {
 | 
			
		|||
#endif
 | 
			
		||||
	u32 addr;		/* TD2 */
 | 
			
		||||
	u32 pad1;		/* padding data */
 | 
			
		||||
};
 | 
			
		||||
} __attribute__((aligned(2), packed));
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The sh ether Rx buffer descriptors.
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +631,7 @@ struct sh_eth_rxdesc {
 | 
			
		|||
#endif
 | 
			
		||||
	u32 addr;		/* RD2 */
 | 
			
		||||
	u32 pad0;		/* padding data */
 | 
			
		||||
};
 | 
			
		||||
} __attribute__((aligned(2), packed));
 | 
			
		||||
 | 
			
		||||
struct sh_eth_private {
 | 
			
		||||
	dma_addr_t rx_desc_dma;
 | 
			
		||||
| 
						 | 
				
			
			@ -633,6 +646,7 @@ struct sh_eth_private {
 | 
			
		|||
	u32 cur_rx, dirty_rx;	/* Producer/consumer ring indices */
 | 
			
		||||
	u32 cur_tx, dirty_tx;
 | 
			
		||||
	u32 rx_buf_sz;		/* Based on MTU+slack. */
 | 
			
		||||
	int edmac_endian;
 | 
			
		||||
	/* MII transceiver section. */
 | 
			
		||||
	u32 phy_id;					/* PHY ID */
 | 
			
		||||
	struct mii_bus *mii_bus;	/* MDIO bus control */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue