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 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 Diff line number Diff line
@@ -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"
+50 −19
Original line number Diff line number Diff line
@@ -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);

+18 −4
Original line number Diff line number Diff line
@@ -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 */