Subject: Re: [PATCH 1/2] sh_eth Add SH7619 support (driver)

From: Yoshinori Sato <[email-masked]>
Date: Wed, 06 Aug 2008 19:49:00 -0400

Add support SH7619 Internal ethernet controler.

 arch/sh/include/asm/sh_eth.h |   11 +++++++
 drivers/net/Kconfig          |    5 ++-
 drivers/net/sh_eth.c         |   69 ++++++++++++++++++++++++++++++-----------
 drivers/net/sh_eth.h         |   22 +++++++++++--
 4 files changed, 82 insertions(+), 25 deletions(-)
 create mode 100644 arch/sh/include/asm/sh_eth.h

diff --git a/arch/sh/include/asm/sh_eth.h b/arch/sh/include/asm/sh_eth.h
new file mode 100644
index 0000000..bb83258
--- /dev/null
+++ b/arch/sh/include/asm/sh_eth.h
@@ -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
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8a03875..4b4cb2b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -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"
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 6a06b95..25e62cf 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -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);
 
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index 45ad1b0..73bc718 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -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 */
-- 
1.5.6.3

-- 
Yoshinori Sato
<[email-masked]>