summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshinori Sato <ysato@users.sourceforge.jp>2008-08-07 03:49:00 +0400
committerJeff Garzik <jgarzik@redhat.com>2008-08-07 10:20:57 +0400
commit71557a37adb5df17631c493b3b7d912938c720b2 (patch)
tree7fdb2548aa5053289f0198d057e3428d43367688
parentd91d4bb9db4a7b2a78accff3560bfd42988c56e4 (diff)
downloadlinux-71557a37adb5df17631c493b3b7d912938c720b2.tar.xz
[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>
-rw-r--r--arch/sh/include/asm/sh_eth.h11
-rw-r--r--drivers/net/Kconfig5
-rw-r--r--drivers/net/sh_eth.c69
-rw-r--r--drivers/net/sh_eth.h22
4 files changed, 82 insertions, 25 deletions
diff --git a/arch/sh/include/asm/sh_eth.h b/arch/sh/include/asm/sh_eth.h
new file mode 100644
index 000000000000..bb832584f3c1
--- /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 8a03875ec877..4b4cb2bf4f11 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 6a06b9503e4f..25e62cf58d3a 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 45ad1b09ca5a..73bc7181cc18 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 */