mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
[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
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 New Issue
Block a user