Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71557a37 authored by Yoshinori Sato's avatar Yoshinori Sato Committed by Jeff Garzik
Browse files

[netdrvr] sh_eth: Add SH7619 support



Add support SH7619 Internal ethernet controler.

Signed-off-by: default avatarYoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent d91d4bb9
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
#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
+3 −2
Original line number Original line Diff line number Diff line
@@ -510,14 +510,15 @@ config STNIC
config SH_ETH
config SH_ETH
	tristate "Renesas SuperH Ethernet support"
	tristate "Renesas SuperH Ethernet support"
	depends on SUPERH && \
	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 CRC32
	select MII
	select MII
	select MDIO_BITBANG
	select MDIO_BITBANG
	select PHYLIB
	select PHYLIB
	help
	help
	  Renesas SuperH Ethernet device driver.
	  Renesas SuperH Ethernet device driver.
	  This driver support SH7710, SH7712 and SH7763.
	  This driver support SH7710, SH7712, SH7763 and SH7619.


config SUNLANCE
config SUNLANCE
	tristate "Sun LANCE support"
	tristate "Sun LANCE support"
+50 −19
Original line number Original line Diff line number Diff line
@@ -34,6 +34,29 @@


#include "sh_eth.h"
#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.
 * 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 */
		/* RX descriptor */
		rxdesc = &mdp->rx_ring[i];
		rxdesc = &mdp->rx_ring[i];
		rxdesc->addr = (u32)skb->data & ~0x3UL;
		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. */
		/* The size of the buffer is 16 byte boundary. */
		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
		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);
	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);


	/* Mark the last entry as wrapping the ring. */
	/* 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);
	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++) {
	for (i = 0; i < TX_RING_SIZE; i++) {
		mdp->tx_skbuff[i] = NULL;
		mdp->tx_skbuff[i] = NULL;
		txdesc = &mdp->tx_ring[i];
		txdesc = &mdp->tx_ring[i];
		txdesc->status = cpu_to_le32(TD_TFP);
		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
		txdesc->buffer_length = 0;
		txdesc->buffer_length = 0;
		if (i == 0) {
		if (i == 0) {
			/* Rx descriptor address set */
			/* Tx descriptor address set */
			ctrl_outl((u32)txdesc, ioaddr + TDLAR);
			ctrl_outl((u32)txdesc, ioaddr + TDLAR);
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
			ctrl_outl((u32)txdesc, ioaddr + TDFAR);
			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)
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
	ctrl_outl((u32)txdesc, ioaddr + TDFXR);
	ctrl_outl((u32)txdesc, ioaddr + TDFXR);
	ctrl_outl(0x1, ioaddr + TDFFR);
	ctrl_outl(0x1, ioaddr + TDFFR);
#endif
#endif


	txdesc->status |= cpu_to_le32(TD_TDLE);
	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
}
}


/* Get skb and descriptor buffer */
/* 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++) {
	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
		entry = mdp->dirty_tx % TX_RING_SIZE;
		entry = mdp->dirty_tx % TX_RING_SIZE;
		txdesc = &mdp->tx_ring[entry];
		txdesc = &mdp->tx_ring[entry];
		if (txdesc->status & cpu_to_le32(TD_TACT))
		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
			break;
			break;
		/* Free the original skb. */
		/* Free the original skb. */
		if (mdp->tx_skbuff[entry]) {
		if (mdp->tx_skbuff[entry]) {
@@ -463,9 +486,9 @@ static int sh_eth_txfree(struct net_device *ndev)
			mdp->tx_skbuff[entry] = NULL;
			mdp->tx_skbuff[entry] = NULL;
			freeNum++;
			freeNum++;
		}
		}
		txdesc->status = cpu_to_le32(TD_TFP);
		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
		if (entry >= TX_RING_SIZE - 1)
		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_packets++;
		mdp->stats.tx_bytes += txdesc->buffer_length;
		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;
	u32 desc_status, reserve = 0;


	rxdesc = &mdp->rx_ring[entry];
	rxdesc = &mdp->rx_ring[entry];
	while (!(rxdesc->status & cpu_to_le32(RD_RACT))) {
	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
		desc_status = le32_to_cpu(rxdesc->status);
		desc_status = edmac_to_cpu(mdp, rxdesc->status);
		pkt_len = rxdesc->frame_length;
		pkt_len = rxdesc->frame_length;


		if (--boguscnt < 0)
		if (--boguscnt < 0)
@@ -522,7 +545,7 @@ static int sh_eth_rx(struct net_device *ndev)
			mdp->stats.rx_packets++;
			mdp->stats.rx_packets++;
			mdp->stats.rx_bytes += pkt_len;
			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;
		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)
		if (entry >= RX_RING_SIZE - 1)
			rxdesc->status |=
			rxdesc->status |=
				cpu_to_le32(RD_RACT | RD_RFP | RD_RDEL);
				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
		else
		else
			rxdesc->status |=
			rxdesc->status |=
				cpu_to_le32(RD_RACT | RD_RFP);
				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
	}
	}


	/* Restart Rx engine if stopped. */
	/* 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;
		txdesc->buffer_length = skb->len;


	if (entry >= TX_RING_SIZE - 1)
	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
	else
		txdesc->status |= cpu_to_le32(TD_TACT);
		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);


	mdp->cur_tx++;
	mdp->cur_tx++;


@@ -1159,6 +1182,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
	struct resource *res;
	struct resource *res;
	struct net_device *ndev = NULL;
	struct net_device *ndev = NULL;
	struct sh_eth_private *mdp;
	struct sh_eth_private *mdp;
	struct sh_eth_plat_data *pd;


	/* get base addr */
	/* get base addr */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	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);
	mdp = netdev_priv(ndev);
	spin_lock_init(&mdp->lock);
	spin_lock_init(&mdp->lock);


	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
	/* get PHY ID */
	/* 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 */
	/* set function */
	ndev->open = sh_eth_open;
	ndev->open = sh_eth_open;
@@ -1217,12 +1244,16 @@ static int sh_eth_drv_probe(struct platform_device *pdev)


	/* First device only init */
	/* First device only init */
	if (!devno) {
	if (!devno) {
#if defined(ARSTR)
		/* reset device */
		/* reset device */
		ctrl_outl(ARSTR_ARSTR, ARSTR);
		ctrl_outl(ARSTR_ARSTR, ARSTR);
		mdelay(1);
		mdelay(1);
#endif


#if defined(SH_TSU_ADDR)
		/* TSU init (Init only)*/
		/* TSU init (Init only)*/
		sh_eth_tsu_init(SH_TSU_ADDR);
		sh_eth_tsu_init(SH_TSU_ADDR);
#endif
	}
	}


	/* network device register */
	/* network device register */
@@ -1240,8 +1271,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
	       ndev->name, CARDNAME, (u32) ndev->base_addr);
	       ndev->name, CARDNAME, (u32) ndev->base_addr);


	for (i = 0; i < 5; i++)
	for (i = 0; i < 5; i++)
		printk(KERN_INFO "%02X:", ndev->dev_addr[i]);
		printk("%02X:", ndev->dev_addr[i]);
	printk(KERN_INFO "%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);
	printk("%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);


	platform_set_drvdata(pdev, ndev);
	platform_set_drvdata(pdev, ndev);


+18 −4
Original line number Original line Diff line number Diff line
@@ -30,6 +30,8 @@
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/phy.h>


#include <asm/sh_eth.h>

#define CARDNAME	"sh-eth"
#define CARDNAME	"sh-eth"
#define TX_TIMEOUT	(5*HZ)
#define TX_TIMEOUT	(5*HZ)
#define TX_RING_SIZE	64	/* Tx ring size */
#define TX_RING_SIZE	64	/* Tx ring size */
@@ -143,10 +145,11 @@


#else /* CONFIG_CPU_SUBTYPE_SH7763 */
#else /* CONFIG_CPU_SUBTYPE_SH7763 */
# define RX_OFFSET 2	/* skb offset */
# define RX_OFFSET 2	/* skb offset */
#ifndef CONFIG_CPU_SUBTYPE_SH7619
/* Chip base address */
/* Chip base address */
# define SH_TSU_ADDR  0xA7000804
# define SH_TSU_ADDR  0xA7000804
# define ARSTR		  0xA7000800
# define ARSTR		  0xA7000800

#endif
/* Chip Registers */
/* Chip Registers */
/* E-DMAC */
/* E-DMAC */
# define EDMR	0x0000
# define EDMR	0x0000
@@ -384,7 +387,11 @@ enum FCFTR_BIT {
	FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001,
	FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001,
};
};
#define FIFO_F_D_RFF	(FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0)
#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)
#define FIFO_F_D_RFD	(FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0)
#else
#define FIFO_F_D_RFD	(FCFTR_RFD0)
#endif


/* Transfer descriptor bit */
/* Transfer descriptor bit */
enum TD_STS_BIT {
enum TD_STS_BIT {
@@ -414,8 +421,10 @@ enum FELIC_MODE_BIT {
#ifdef CONFIG_CPU_SUBTYPE_SH7763
#ifdef CONFIG_CPU_SUBTYPE_SH7763
#define ECMR_CHG_DM	(ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\
#define ECMR_CHG_DM	(ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\
			ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
			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
#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
#endif


/* ECSR */
/* ECSR */
@@ -485,7 +494,11 @@ enum RPADIR_BIT {


/* FDR */
/* FDR */
enum FIFO_SIZE_BIT {
enum FIFO_SIZE_BIT {
#ifndef CONFIG_CPU_SUBTYPE_SH7619
	FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
	FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
#else
	FIFO_SIZE_T = 0x00000100, FIFO_SIZE_R = 0x00000001,
#endif
};
};
enum phy_offsets {
enum phy_offsets {
	PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
	PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
@@ -601,7 +614,7 @@ struct sh_eth_txdesc {
#endif
#endif
	u32 addr;		/* TD2 */
	u32 addr;		/* TD2 */
	u32 pad1;		/* padding data */
	u32 pad1;		/* padding data */
};
} __attribute__((aligned(2), packed));


/*
/*
 * The sh ether Rx buffer descriptors.
 * The sh ether Rx buffer descriptors.
@@ -618,7 +631,7 @@ struct sh_eth_rxdesc {
#endif
#endif
	u32 addr;		/* RD2 */
	u32 addr;		/* RD2 */
	u32 pad0;		/* padding data */
	u32 pad0;		/* padding data */
};
} __attribute__((aligned(2), packed));


struct sh_eth_private {
struct sh_eth_private {
	dma_addr_t rx_desc_dma;
	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_rx, dirty_rx;	/* Producer/consumer ring indices */
	u32 cur_tx, dirty_tx;
	u32 cur_tx, dirty_tx;
	u32 rx_buf_sz;		/* Based on MTU+slack. */
	u32 rx_buf_sz;		/* Based on MTU+slack. */
	int edmac_endian;
	/* MII transceiver section. */
	/* MII transceiver section. */
	u32 phy_id;					/* PHY ID */
	u32 phy_id;					/* PHY ID */
	struct mii_bus *mii_bus;	/* MDIO bus control */
	struct mii_bus *mii_bus;	/* MDIO bus control */