Merge branch 'upstream-davem' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

This commit is contained in:
David S. Miller 2008-07-30 15:44:30 -07:00
commit e62112c53a
18 changed files with 947 additions and 332 deletions

View File

@ -18,6 +18,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <linux/mv643xx_eth.h> #include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/pci.h> #include <asm/mach/pci.h>
@ -69,6 +70,8 @@ static struct platform_device rd88f6281_nand_flash = {
static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { static struct mv643xx_eth_platform_data rd88f6281_ge00_data = {
.phy_addr = -1, .phy_addr = -1,
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
}; };
static struct mv_sata_platform_data rd88f6281_sata_data = { static struct mv_sata_platform_data rd88f6281_sata_data = {

View File

@ -15,6 +15,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h> #include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/leds.h> #include <asm/leds.h>
@ -88,6 +89,8 @@ static struct orion5x_mpp_mode rd88f5181l_fxo_mpp_modes[] __initdata = {
static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = { static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = {
.phy_addr = -1, .phy_addr = -1,
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
}; };
static void __init rd88f5181l_fxo_init(void) static void __init rd88f5181l_fxo_init(void)

View File

@ -15,6 +15,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h> #include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/gpio.h> #include <asm/gpio.h>
@ -89,6 +90,8 @@ static struct orion5x_mpp_mode rd88f5181l_ge_mpp_modes[] __initdata = {
static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = { static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = {
.phy_addr = -1, .phy_addr = -1,
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
}; };
static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = { static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = {

View File

@ -14,6 +14,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h> #include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -92,6 +93,8 @@ static struct platform_device wnr854t_nor_flash = {
static struct mv643xx_eth_platform_data wnr854t_eth_data = { static struct mv643xx_eth_platform_data wnr854t_eth_data = {
.phy_addr = -1, .phy_addr = -1,
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
}; };
static void __init wnr854t_init(void) static void __init wnr854t_init(void)

View File

@ -14,6 +14,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h> #include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -100,6 +101,8 @@ static struct platform_device wrt350n_v2_nor_flash = {
static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = { static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = {
.phy_addr = -1, .phy_addr = -1,
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
}; };
static void __init wrt350n_v2_init(void) static void __init wrt350n_v2_init(void)

View File

@ -510,14 +510,14 @@ 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_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763)
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 and SH7712. This driver support SH7710, SH7712 and SH7763.
config SUNLANCE config SUNLANCE
tristate "Sun LANCE support" tristate "Sun LANCE support"

View File

@ -605,36 +605,87 @@ adjust_head:
static int bfin_mac_hard_start_xmit(struct sk_buff *skb, static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
unsigned int data; u16 *data;
current_tx_ptr->skb = skb; current_tx_ptr->skb = skb;
/* if (ANOMALY_05000285) {
* Is skb->data always 16-bit aligned? /*
* Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)? * TXDWA feature is not avaible to older revision < 0.3 silicon
*/ * of BF537
if ((((unsigned int)(skb->data)) & 0x02) == 2) { *
/* move skb->data to current_tx_ptr payload */ * Only if data buffer is ODD WORD alignment, we do not
data = (unsigned int)(skb->data) - 2; * need to memcpy
*((unsigned short *)data) = (unsigned short)(skb->len); */
current_tx_ptr->desc_a.start_addr = (unsigned long)data; u32 data_align = (u32)(skb->data) & 0x3;
/* this is important! */ if (data_align == 0x2) {
blackfin_dcache_flush_range(data, (data + (skb->len)) + 2); /* move skb->data to current_tx_ptr payload */
data = (u16 *)(skb->data) - 1;
*data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */
blackfin_dcache_flush_range((u32)data,
(u32)((u8 *)data + skb->len + 4));
} else {
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len);
current_tx_ptr->desc_a.start_addr =
(u32)current_tx_ptr->packet;
if (current_tx_ptr->status.status_word != 0)
current_tx_ptr->status.status_word = 0;
blackfin_dcache_flush_range(
(u32)current_tx_ptr->packet,
(u32)(current_tx_ptr->packet + skb->len + 2));
}
} else { } else {
*((unsigned short *)(current_tx_ptr->packet)) = /*
(unsigned short)(skb->len); * TXDWA feature is avaible to revision < 0.3 silicon of
memcpy((char *)(current_tx_ptr->packet + 2), skb->data, * BF537 and always avaible to BF52x
(skb->len)); */
current_tx_ptr->desc_a.start_addr = u32 data_align = (u32)(skb->data) & 0x3;
(unsigned long)current_tx_ptr->packet; if (data_align == 0x0) {
if (current_tx_ptr->status.status_word != 0) u16 sysctl = bfin_read_EMAC_SYSCTL();
current_tx_ptr->status.status_word = 0; sysctl |= TXDWA;
blackfin_dcache_flush_range((unsigned int)current_tx_ptr-> bfin_write_EMAC_SYSCTL(sysctl);
packet,
(unsigned int)(current_tx_ptr-> /* move skb->data to current_tx_ptr payload */
packet + skb->len) + data = (u16 *)(skb->data) - 2;
2); *data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */
blackfin_dcache_flush_range(
(u32)data,
(u32)((u8 *)data + skb->len + 4));
} else if (data_align == 0x2) {
u16 sysctl = bfin_read_EMAC_SYSCTL();
sysctl &= ~TXDWA;
bfin_write_EMAC_SYSCTL(sysctl);
/* move skb->data to current_tx_ptr payload */
data = (u16 *)(skb->data) - 1;
*data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */
blackfin_dcache_flush_range(
(u32)data,
(u32)((u8 *)data + skb->len + 4));
} else {
u16 sysctl = bfin_read_EMAC_SYSCTL();
sysctl &= ~TXDWA;
bfin_write_EMAC_SYSCTL(sysctl);
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len);
current_tx_ptr->desc_a.start_addr =
(u32)current_tx_ptr->packet;
if (current_tx_ptr->status.status_word != 0)
current_tx_ptr->status.status_word = 0;
blackfin_dcache_flush_range(
(u32)current_tx_ptr->packet,
(u32)(current_tx_ptr->packet + skb->len + 2));
}
} }
/* enable this packet's dma */ /* enable this packet's dma */
@ -691,7 +742,6 @@ static void bfin_mac_rx(struct net_device *dev)
(unsigned long)skb->tail); (unsigned long)skb->tail);
dev->last_rx = jiffies; dev->last_rx = jiffies;
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
#if defined(BFIN_MAC_CSUM_OFFLOAD) #if defined(BFIN_MAC_CSUM_OFFLOAD)
skb->csum = current_rx_ptr->status.ip_payload_csum; skb->csum = current_rx_ptr->status.ip_payload_csum;
@ -920,6 +970,7 @@ static int bfin_mac_open(struct net_device *dev)
phy_start(lp->phydev); phy_start(lp->phydev);
phy_write(lp->phydev, MII_BMCR, BMCR_RESET); phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
setup_system_regs(dev); setup_system_regs(dev);
setup_mac_addr(dev->dev_addr);
bfin_mac_disable(); bfin_mac_disable();
bfin_mac_enable(); bfin_mac_enable();
pr_debug("hardware init finished\n"); pr_debug("hardware init finished\n");
@ -955,7 +1006,7 @@ static int bfin_mac_close(struct net_device *dev)
return 0; return 0;
} }
static int __init bfin_mac_probe(struct platform_device *pdev) static int __devinit bfin_mac_probe(struct platform_device *pdev)
{ {
struct net_device *ndev; struct net_device *ndev;
struct bfin_mac_local *lp; struct bfin_mac_local *lp;
@ -1081,7 +1132,7 @@ out_err_probe_mac:
return rc; return rc;
} }
static int bfin_mac_remove(struct platform_device *pdev) static int __devexit bfin_mac_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct bfin_mac_local *lp = netdev_priv(ndev); struct bfin_mac_local *lp = netdev_priv(ndev);
@ -1128,7 +1179,7 @@ static int bfin_mac_resume(struct platform_device *pdev)
static struct platform_driver bfin_mac_driver = { static struct platform_driver bfin_mac_driver = {
.probe = bfin_mac_probe, .probe = bfin_mac_probe,
.remove = bfin_mac_remove, .remove = __devexit_p(bfin_mac_remove),
.resume = bfin_mac_resume, .resume = bfin_mac_resume,
.suspend = bfin_mac_suspend, .suspend = bfin_mac_suspend,
.driver = { .driver = {

View File

@ -683,7 +683,7 @@ enum {
SF_ERASE_SECTOR = 0xd8, /* erase sector */ SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */
FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */ FW_VERS_ADDR = 0x7fffc, /* flash address holding FW version */
FW_MIN_SIZE = 8 /* at least version and csum */ FW_MIN_SIZE = 8 /* at least version and csum */
}; };

View File

@ -2937,9 +2937,9 @@ static void ehea_rereg_mrs(struct work_struct *work)
} }
} }
} }
mutex_unlock(&dlpar_mem_lock); ehea_info("re-initializing driver complete");
ehea_info("re-initializing driver complete");
out: out:
mutex_unlock(&dlpar_mem_lock);
return; return;
} }

View File

@ -1547,8 +1547,10 @@ static int __devinit enc28j60_probe(struct spi_device *spi)
random_ether_addr(dev->dev_addr); random_ether_addr(dev->dev_addr);
enc28j60_set_hw_macaddr(dev); enc28j60_set_hw_macaddr(dev);
ret = request_irq(spi->irq, enc28j60_irq, IRQF_TRIGGER_FALLING, /* Board setup must set the relevant edge trigger type;
DRV_NAME, priv); * level triggers won't currently work.
*/
ret = request_irq(spi->irq, enc28j60_irq, 0, DRV_NAME, priv);
if (ret < 0) { if (ret < 0) {
if (netif_msg_probe(priv)) if (netif_msg_probe(priv))
dev_err(&spi->dev, DRV_NAME ": request irq %d failed " dev_err(&spi->dev, DRV_NAME ": request irq %d failed "

View File

@ -333,6 +333,7 @@ enum {
NvRegPowerState2 = 0x600, NvRegPowerState2 = 0x600,
#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11
#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
#define NVREG_POWERSTATE2_PHY_RESET 0x0004
}; };
/* Big endian: should work, but is untested */ /* Big endian: should work, but is untested */
@ -529,6 +530,7 @@ union ring_type {
#define PHY_REALTEK_INIT_REG4 0x14 #define PHY_REALTEK_INIT_REG4 0x14
#define PHY_REALTEK_INIT_REG5 0x18 #define PHY_REALTEK_INIT_REG5 0x18
#define PHY_REALTEK_INIT_REG6 0x11 #define PHY_REALTEK_INIT_REG6 0x11
#define PHY_REALTEK_INIT_REG7 0x01
#define PHY_REALTEK_INIT1 0x0000 #define PHY_REALTEK_INIT1 0x0000
#define PHY_REALTEK_INIT2 0x8e00 #define PHY_REALTEK_INIT2 0x8e00
#define PHY_REALTEK_INIT3 0x0001 #define PHY_REALTEK_INIT3 0x0001
@ -537,6 +539,9 @@ union ring_type {
#define PHY_REALTEK_INIT6 0xf5c7 #define PHY_REALTEK_INIT6 0xf5c7
#define PHY_REALTEK_INIT7 0x1000 #define PHY_REALTEK_INIT7 0x1000
#define PHY_REALTEK_INIT8 0x0003 #define PHY_REALTEK_INIT8 0x0003
#define PHY_REALTEK_INIT9 0x0008
#define PHY_REALTEK_INIT10 0x0005
#define PHY_REALTEK_INIT11 0x0200
#define PHY_REALTEK_INIT_MSK1 0x0003 #define PHY_REALTEK_INIT_MSK1 0x0003
#define PHY_GIGABIT 0x0100 #define PHY_GIGABIT 0x0100
@ -1149,6 +1154,42 @@ static int phy_init(struct net_device *dev)
return PHY_ERROR; return PHY_ERROR;
} }
} }
if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
np->phy_rev == PHY_REV_REALTEK_8211C) {
u32 powerstate = readl(base + NvRegPowerState2);
/* need to perform hw phy reset */
powerstate |= NVREG_POWERSTATE2_PHY_RESET;
writel(powerstate, base + NvRegPowerState2);
msleep(25);
powerstate &= ~NVREG_POWERSTATE2_PHY_RESET;
writel(powerstate, base + NvRegPowerState2);
msleep(25);
reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
reg |= PHY_REALTEK_INIT9;
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ);
if (!(reg & PHY_REALTEK_INIT11)) {
reg |= PHY_REALTEK_INIT11;
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
}
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
}
if (np->phy_model == PHY_MODEL_REALTEK_8201) { if (np->phy_model == PHY_MODEL_REALTEK_8201) {
if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 || if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 || np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
@ -1201,12 +1242,23 @@ static int phy_init(struct net_device *dev)
mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
mii_control |= BMCR_ANENABLE; mii_control |= BMCR_ANENABLE;
/* reset the phy if (np->phy_oui == PHY_OUI_REALTEK &&
* (certain phys need bmcr to be setup with reset) np->phy_model == PHY_MODEL_REALTEK_8211 &&
*/ np->phy_rev == PHY_REV_REALTEK_8211C) {
if (phy_reset(dev, mii_control)) { /* start autoneg since we already performed hw reset above */
printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev)); mii_control |= BMCR_ANRESTART;
return PHY_ERROR; if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
printk(KERN_INFO "%s: phy init failed\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
} else {
/* reset the phy
* (certain phys need bmcr to be setup with reset)
*/
if (phy_reset(dev, mii_control)) {
printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
} }
/* phy vendor specific configuration */ /* phy vendor specific configuration */

View File

@ -55,7 +55,7 @@
#include <asm/system.h> #include <asm/system.h>
static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_name[] = "mv643xx_eth";
static char mv643xx_eth_driver_version[] = "1.1"; static char mv643xx_eth_driver_version[] = "1.2";
#define MV643XX_ETH_CHECKSUM_OFFLOAD_TX #define MV643XX_ETH_CHECKSUM_OFFLOAD_TX
#define MV643XX_ETH_NAPI #define MV643XX_ETH_NAPI
@ -90,12 +90,21 @@ static char mv643xx_eth_driver_version[] = "1.1";
#define PORT_SERIAL_CONTROL(p) (0x043c + ((p) << 10)) #define PORT_SERIAL_CONTROL(p) (0x043c + ((p) << 10))
#define PORT_STATUS(p) (0x0444 + ((p) << 10)) #define PORT_STATUS(p) (0x0444 + ((p) << 10))
#define TX_FIFO_EMPTY 0x00000400 #define TX_FIFO_EMPTY 0x00000400
#define TX_IN_PROGRESS 0x00000080
#define PORT_SPEED_MASK 0x00000030
#define PORT_SPEED_1000 0x00000010
#define PORT_SPEED_100 0x00000020
#define PORT_SPEED_10 0x00000000
#define FLOW_CONTROL_ENABLED 0x00000008
#define FULL_DUPLEX 0x00000004
#define LINK_UP 0x00000002
#define TXQ_COMMAND(p) (0x0448 + ((p) << 10)) #define TXQ_COMMAND(p) (0x0448 + ((p) << 10))
#define TXQ_FIX_PRIO_CONF(p) (0x044c + ((p) << 10)) #define TXQ_FIX_PRIO_CONF(p) (0x044c + ((p) << 10))
#define TX_BW_RATE(p) (0x0450 + ((p) << 10)) #define TX_BW_RATE(p) (0x0450 + ((p) << 10))
#define TX_BW_MTU(p) (0x0458 + ((p) << 10)) #define TX_BW_MTU(p) (0x0458 + ((p) << 10))
#define TX_BW_BURST(p) (0x045c + ((p) << 10)) #define TX_BW_BURST(p) (0x045c + ((p) << 10))
#define INT_CAUSE(p) (0x0460 + ((p) << 10)) #define INT_CAUSE(p) (0x0460 + ((p) << 10))
#define INT_TX_END_0 0x00080000
#define INT_TX_END 0x07f80000 #define INT_TX_END 0x07f80000
#define INT_RX 0x0007fbfc #define INT_RX 0x0007fbfc
#define INT_EXT 0x00000002 #define INT_EXT 0x00000002
@ -127,21 +136,21 @@ static char mv643xx_eth_driver_version[] = "1.1";
/* /*
* SDMA configuration register. * SDMA configuration register.
*/ */
#define RX_BURST_SIZE_4_64BIT (2 << 1) #define RX_BURST_SIZE_16_64BIT (4 << 1)
#define BLM_RX_NO_SWAP (1 << 4) #define BLM_RX_NO_SWAP (1 << 4)
#define BLM_TX_NO_SWAP (1 << 5) #define BLM_TX_NO_SWAP (1 << 5)
#define TX_BURST_SIZE_4_64BIT (2 << 22) #define TX_BURST_SIZE_16_64BIT (4 << 22)
#if defined(__BIG_ENDIAN) #if defined(__BIG_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \ #define PORT_SDMA_CONFIG_DEFAULT_VALUE \
RX_BURST_SIZE_4_64BIT | \ RX_BURST_SIZE_16_64BIT | \
TX_BURST_SIZE_4_64BIT TX_BURST_SIZE_16_64BIT
#elif defined(__LITTLE_ENDIAN) #elif defined(__LITTLE_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \ #define PORT_SDMA_CONFIG_DEFAULT_VALUE \
RX_BURST_SIZE_4_64BIT | \ RX_BURST_SIZE_16_64BIT | \
BLM_RX_NO_SWAP | \ BLM_RX_NO_SWAP | \
BLM_TX_NO_SWAP | \ BLM_TX_NO_SWAP | \
TX_BURST_SIZE_4_64BIT TX_BURST_SIZE_16_64BIT
#else #else
#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined #error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
#endif #endif
@ -153,9 +162,7 @@ static char mv643xx_eth_driver_version[] = "1.1";
#define SET_MII_SPEED_TO_100 (1 << 24) #define SET_MII_SPEED_TO_100 (1 << 24)
#define SET_GMII_SPEED_TO_1000 (1 << 23) #define SET_GMII_SPEED_TO_1000 (1 << 23)
#define SET_FULL_DUPLEX_MODE (1 << 21) #define SET_FULL_DUPLEX_MODE (1 << 21)
#define MAX_RX_PACKET_1522BYTE (1 << 17)
#define MAX_RX_PACKET_9700BYTE (5 << 17) #define MAX_RX_PACKET_9700BYTE (5 << 17)
#define MAX_RX_PACKET_MASK (7 << 17)
#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13) #define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13)
#define DO_NOT_FORCE_LINK_FAIL (1 << 10) #define DO_NOT_FORCE_LINK_FAIL (1 << 10)
#define SERIAL_PORT_CONTROL_RESERVED (1 << 9) #define SERIAL_PORT_CONTROL_RESERVED (1 << 9)
@ -228,6 +235,8 @@ struct tx_desc {
#define GEN_IP_V4_CHECKSUM 0x00040000 #define GEN_IP_V4_CHECKSUM 0x00040000
#define GEN_TCP_UDP_CHECKSUM 0x00020000 #define GEN_TCP_UDP_CHECKSUM 0x00020000
#define UDP_FRAME 0x00010000 #define UDP_FRAME 0x00010000
#define MAC_HDR_EXTRA_4_BYTES 0x00008000
#define MAC_HDR_EXTRA_8_BYTES 0x00000200
#define TX_IHL_SHIFT 11 #define TX_IHL_SHIFT 11
@ -404,6 +413,17 @@ static void rxq_disable(struct rx_queue *rxq)
udelay(10); udelay(10);
} }
static void txq_reset_hw_ptr(struct tx_queue *txq)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int off = TXQ_CURRENT_DESC_PTR(mp->port_num, txq->index);
u32 addr;
addr = (u32)txq->tx_desc_dma;
addr += txq->tx_curr_desc * sizeof(struct tx_desc);
wrl(mp, off, addr);
}
static void txq_enable(struct tx_queue *txq) static void txq_enable(struct tx_queue *txq)
{ {
struct mv643xx_eth_private *mp = txq_to_mp(txq); struct mv643xx_eth_private *mp = txq_to_mp(txq);
@ -614,6 +634,12 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
if (mp->txq_mask & (1 << i)) if (mp->txq_mask & (1 << i))
txq_reclaim(mp->txq + i, 0); txq_reclaim(mp->txq + i, 0);
if (netif_carrier_ok(mp->dev)) {
spin_lock(&mp->lock);
__txq_maybe_wake(mp->txq + mp->txq_primary);
spin_unlock(&mp->lock);
}
} }
#endif #endif
@ -706,6 +732,7 @@ static inline __be16 sum16_as_be(__sum16 sum)
static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
{ {
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int nr_frags = skb_shinfo(skb)->nr_frags; int nr_frags = skb_shinfo(skb)->nr_frags;
int tx_index; int tx_index;
struct tx_desc *desc; struct tx_desc *desc;
@ -732,12 +759,36 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
BUG_ON(skb->protocol != htons(ETH_P_IP)); int mac_hdr_len;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
cmd_sts |= GEN_TCP_UDP_CHECKSUM | cmd_sts |= GEN_TCP_UDP_CHECKSUM |
GEN_IP_V4_CHECKSUM | GEN_IP_V4_CHECKSUM |
ip_hdr(skb)->ihl << TX_IHL_SHIFT; ip_hdr(skb)->ihl << TX_IHL_SHIFT;
mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
switch (mac_hdr_len - ETH_HLEN) {
case 0:
break;
case 4:
cmd_sts |= MAC_HDR_EXTRA_4_BYTES;
break;
case 8:
cmd_sts |= MAC_HDR_EXTRA_8_BYTES;
break;
case 12:
cmd_sts |= MAC_HDR_EXTRA_4_BYTES;
cmd_sts |= MAC_HDR_EXTRA_8_BYTES;
break;
default:
if (net_ratelimit())
dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev,
"mac header length is %d?!\n", mac_hdr_len);
break;
}
switch (ip_hdr(skb)->protocol) { switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP: case IPPROTO_UDP:
cmd_sts |= UDP_FRAME; cmd_sts |= UDP_FRAME;
@ -759,6 +810,10 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
wmb(); wmb();
desc->cmd_sts = cmd_sts; desc->cmd_sts = cmd_sts;
/* clear TX_END interrupt status */
wrl(mp, INT_CAUSE(mp->port_num), ~(INT_TX_END_0 << txq->index));
rdl(mp, INT_CAUSE(mp->port_num));
/* ensure all descriptors are written before poking hardware */ /* ensure all descriptors are written before poking hardware */
wmb(); wmb();
txq_enable(txq); txq_enable(txq);
@ -1112,10 +1167,28 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *
static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct mv643xx_eth_private *mp = netdev_priv(dev);
u32 port_status;
port_status = rdl(mp, PORT_STATUS(mp->port_num));
cmd->supported = SUPPORTED_MII; cmd->supported = SUPPORTED_MII;
cmd->advertising = ADVERTISED_MII; cmd->advertising = ADVERTISED_MII;
cmd->speed = SPEED_1000; switch (port_status & PORT_SPEED_MASK) {
cmd->duplex = DUPLEX_FULL; case PORT_SPEED_10:
cmd->speed = SPEED_10;
break;
case PORT_SPEED_100:
cmd->speed = SPEED_100;
break;
case PORT_SPEED_1000:
cmd->speed = SPEED_1000;
break;
default:
cmd->speed = -1;
break;
}
cmd->duplex = (port_status & FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
cmd->port = PORT_MII; cmd->port = PORT_MII;
cmd->phy_address = 0; cmd->phy_address = 0;
cmd->transceiver = XCVR_INTERNAL; cmd->transceiver = XCVR_INTERNAL;
@ -1539,8 +1612,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
tx_desc = (struct tx_desc *)txq->tx_desc_area; tx_desc = (struct tx_desc *)txq->tx_desc_area;
for (i = 0; i < txq->tx_ring_size; i++) { for (i = 0; i < txq->tx_ring_size; i++) {
struct tx_desc *txd = tx_desc + i;
int nexti = (i + 1) % txq->tx_ring_size; int nexti = (i + 1) % txq->tx_ring_size;
tx_desc[i].next_desc_ptr = txq->tx_desc_dma +
txd->cmd_sts = 0;
txd->next_desc_ptr = txq->tx_desc_dma +
nexti * sizeof(struct tx_desc); nexti * sizeof(struct tx_desc);
} }
@ -1577,8 +1653,11 @@ static void txq_reclaim(struct tx_queue *txq, int force)
desc = &txq->tx_desc_area[tx_index]; desc = &txq->tx_desc_area[tx_index];
cmd_sts = desc->cmd_sts; cmd_sts = desc->cmd_sts;
if (!force && (cmd_sts & BUFFER_OWNED_BY_DMA)) if (cmd_sts & BUFFER_OWNED_BY_DMA) {
break; if (!force)
break;
desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA;
}
txq->tx_used_desc = (tx_index + 1) % txq->tx_ring_size; txq->tx_used_desc = (tx_index + 1) % txq->tx_ring_size;
txq->tx_desc_count--; txq->tx_desc_count--;
@ -1632,49 +1711,61 @@ static void txq_deinit(struct tx_queue *txq)
/* netdev ops and related ***************************************************/ /* netdev ops and related ***************************************************/
static void update_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) static void handle_link_event(struct mv643xx_eth_private *mp)
{ {
u32 pscr_o; struct net_device *dev = mp->dev;
u32 pscr_n; u32 port_status;
int speed;
int duplex;
int fc;
pscr_o = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num)); port_status = rdl(mp, PORT_STATUS(mp->port_num));
if (!(port_status & LINK_UP)) {
/* clear speed, duplex and rx buffer size fields */ if (netif_carrier_ok(dev)) {
pscr_n = pscr_o & ~(SET_MII_SPEED_TO_100 |
SET_GMII_SPEED_TO_1000 |
SET_FULL_DUPLEX_MODE |
MAX_RX_PACKET_MASK);
if (speed == SPEED_1000) {
pscr_n |= SET_GMII_SPEED_TO_1000 | MAX_RX_PACKET_9700BYTE;
} else {
if (speed == SPEED_100)
pscr_n |= SET_MII_SPEED_TO_100;
pscr_n |= MAX_RX_PACKET_1522BYTE;
}
if (duplex == DUPLEX_FULL)
pscr_n |= SET_FULL_DUPLEX_MODE;
if (pscr_n != pscr_o) {
if ((pscr_o & SERIAL_PORT_ENABLE) == 0)
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr_n);
else {
int i; int i;
for (i = 0; i < 8; i++) printk(KERN_INFO "%s: link down\n", dev->name);
if (mp->txq_mask & (1 << i))
txq_disable(mp->txq + i);
pscr_o &= ~SERIAL_PORT_ENABLE; netif_carrier_off(dev);
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr_o); netif_stop_queue(dev);
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr_n);
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr_n);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
if (mp->txq_mask & (1 << i)) struct tx_queue *txq = mp->txq + i;
txq_enable(mp->txq + i);
if (mp->txq_mask & (1 << i)) {
txq_reclaim(txq, 1);
txq_reset_hw_ptr(txq);
}
}
} }
return;
}
switch (port_status & PORT_SPEED_MASK) {
case PORT_SPEED_10:
speed = 10;
break;
case PORT_SPEED_100:
speed = 100;
break;
case PORT_SPEED_1000:
speed = 1000;
break;
default:
speed = -1;
break;
}
duplex = (port_status & FULL_DUPLEX) ? 1 : 0;
fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0;
printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
"flow control %sabled\n", dev->name,
speed, duplex ? "full" : "half",
fc ? "en" : "dis");
if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
netif_wake_queue(dev);
} }
} }
@ -1684,7 +1775,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
struct mv643xx_eth_private *mp = netdev_priv(dev); struct mv643xx_eth_private *mp = netdev_priv(dev);
u32 int_cause; u32 int_cause;
u32 int_cause_ext; u32 int_cause_ext;
u32 txq_active;
int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
(INT_TX_END | INT_RX | INT_EXT); (INT_TX_END | INT_RX | INT_EXT);
@ -1698,30 +1788,8 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext);
} }
if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) { if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK))
if (mp->phy_addr == -1 || mii_link_ok(&mp->mii)) { handle_link_event(mp);
int i;
if (mp->phy_addr != -1) {
struct ethtool_cmd cmd;
mii_ethtool_gset(&mp->mii, &cmd);
update_pscr(mp, cmd.speed, cmd.duplex);
}
for (i = 0; i < 8; i++)
if (mp->txq_mask & (1 << i))
txq_enable(mp->txq + i);
if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
__txq_maybe_wake(mp->txq + mp->txq_primary);
}
} else if (netif_carrier_ok(dev)) {
netif_stop_queue(dev);
netif_carrier_off(dev);
}
}
/* /*
* RxBuffer or RxError set for any of the 8 queues? * RxBuffer or RxError set for any of the 8 queues?
@ -1743,8 +1811,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
} }
#endif #endif
txq_active = rdl(mp, TXQ_COMMAND(mp->port_num));
/* /*
* TxBuffer or TxError set for any of the 8 queues? * TxBuffer or TxError set for any of the 8 queues?
*/ */
@ -1754,6 +1820,16 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
if (mp->txq_mask & (1 << i)) if (mp->txq_mask & (1 << i))
txq_reclaim(mp->txq + i, 0); txq_reclaim(mp->txq + i, 0);
/*
* Enough space again in the primary TX queue for a
* full packet?
*/
if (netif_carrier_ok(dev)) {
spin_lock(&mp->lock);
__txq_maybe_wake(mp->txq + mp->txq_primary);
spin_unlock(&mp->lock);
}
} }
/* /*
@ -1763,19 +1839,25 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
int i; int i;
wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END)); wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END));
spin_lock(&mp->lock);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
struct tx_queue *txq = mp->txq + i; struct tx_queue *txq = mp->txq + i;
if (txq->tx_desc_count && !((txq_active >> i) & 1)) u32 hw_desc_ptr;
u32 expected_ptr;
if ((int_cause & (INT_TX_END_0 << i)) == 0)
continue;
hw_desc_ptr =
rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, i));
expected_ptr = (u32)txq->tx_desc_dma +
txq->tx_curr_desc * sizeof(struct tx_desc);
if (hw_desc_ptr != expected_ptr)
txq_enable(txq); txq_enable(txq);
} }
} spin_unlock(&mp->lock);
/*
* Enough space again in the primary TX queue for a full packet?
*/
if (int_cause_ext & INT_EXT_TX) {
struct tx_queue *txq = mp->txq + mp->txq_primary;
__txq_maybe_wake(txq);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
@ -1785,14 +1867,14 @@ static void phy_reset(struct mv643xx_eth_private *mp)
{ {
unsigned int data; unsigned int data;
smi_reg_read(mp, mp->phy_addr, 0, &data); smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
data |= 0x8000; data |= BMCR_RESET;
smi_reg_write(mp, mp->phy_addr, 0, data); smi_reg_write(mp, mp->phy_addr, MII_BMCR, data);
do { do {
udelay(1); udelay(1);
smi_reg_read(mp, mp->phy_addr, 0, &data); smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
} while (data & 0x8000); } while (data & BMCR_RESET);
} }
static void port_start(struct mv643xx_eth_private *mp) static void port_start(struct mv643xx_eth_private *mp)
@ -1800,23 +1882,6 @@ static void port_start(struct mv643xx_eth_private *mp)
u32 pscr; u32 pscr;
int i; int i;
/*
* Configure basic link parameters.
*/
pscr = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
DISABLE_AUTO_NEG_SPEED_GMII |
DISABLE_AUTO_NEG_FOR_DUPLEX |
DO_NOT_FORCE_LINK_FAIL |
SERIAL_PORT_CONTROL_RESERVED;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
pscr |= SERIAL_PORT_ENABLE;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
wrl(mp, SDMA_CONFIG(mp->port_num), PORT_SDMA_CONFIG_DEFAULT_VALUE);
/* /*
* Perform PHY reset, if there is a PHY. * Perform PHY reset, if there is a PHY.
*/ */
@ -1828,22 +1893,32 @@ static void port_start(struct mv643xx_eth_private *mp)
mv643xx_eth_set_settings(mp->dev, &cmd); mv643xx_eth_set_settings(mp->dev, &cmd);
} }
/*
* Configure basic link parameters.
*/
pscr = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
pscr |= SERIAL_PORT_ENABLE;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
pscr |= DO_NOT_FORCE_LINK_FAIL;
if (mp->phy_addr == -1)
pscr |= FORCE_LINK_PASS;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
wrl(mp, SDMA_CONFIG(mp->port_num), PORT_SDMA_CONFIG_DEFAULT_VALUE);
/* /*
* Configure TX path and queues. * Configure TX path and queues.
*/ */
tx_set_rate(mp, 1000000000, 16777216); tx_set_rate(mp, 1000000000, 16777216);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
struct tx_queue *txq = mp->txq + i; struct tx_queue *txq = mp->txq + i;
int off = TXQ_CURRENT_DESC_PTR(mp->port_num, i);
u32 addr;
if ((mp->txq_mask & (1 << i)) == 0) if ((mp->txq_mask & (1 << i)) == 0)
continue; continue;
addr = (u32)txq->tx_desc_dma; txq_reset_hw_ptr(txq);
addr += txq->tx_curr_desc * sizeof(struct tx_desc);
wrl(mp, off, addr);
txq_set_rate(txq, 1000000000, 16777216); txq_set_rate(txq, 1000000000, 16777216);
txq_set_fixed_prio_mode(txq); txq_set_fixed_prio_mode(txq);
} }
@ -1965,6 +2040,9 @@ static int mv643xx_eth_open(struct net_device *dev)
napi_enable(&mp->napi); napi_enable(&mp->napi);
#endif #endif
netif_carrier_off(dev);
netif_stop_queue(dev);
port_start(mp); port_start(mp);
set_rx_coal(mp, 0); set_rx_coal(mp, 0);
@ -1999,8 +2077,14 @@ static void port_reset(struct mv643xx_eth_private *mp)
if (mp->txq_mask & (1 << i)) if (mp->txq_mask & (1 << i))
txq_disable(mp->txq + i); txq_disable(mp->txq + i);
} }
while (!(rdl(mp, PORT_STATUS(mp->port_num)) & TX_FIFO_EMPTY))
while (1) {
u32 ps = rdl(mp, PORT_STATUS(mp->port_num));
if ((ps & (TX_IN_PROGRESS | TX_FIFO_EMPTY)) == TX_FIFO_EMPTY)
break;
udelay(10); udelay(10);
}
/* Reset the Enable bit in the Configuration Register */ /* Reset the Enable bit in the Configuration Register */
data = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num)); data = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
@ -2202,7 +2286,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
int ret; int ret;
if (!mv643xx_eth_version_printed++) if (!mv643xx_eth_version_printed++)
printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n"); printk(KERN_NOTICE "MV-643xx 10/100/1000 ethernet "
"driver version %s\n", mv643xx_eth_driver_version);
ret = -EINVAL; ret = -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -2338,14 +2423,14 @@ static int phy_detect(struct mv643xx_eth_private *mp)
unsigned int data; unsigned int data;
unsigned int data2; unsigned int data2;
smi_reg_read(mp, mp->phy_addr, 0, &data); smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
smi_reg_write(mp, mp->phy_addr, 0, data ^ 0x1000); smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE);
smi_reg_read(mp, mp->phy_addr, 0, &data2); smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data2);
if (((data ^ data2) & 0x1000) == 0) if (((data ^ data2) & BMCR_ANENABLE) == 0)
return -ENODEV; return -ENODEV;
smi_reg_write(mp, mp->phy_addr, 0, data); smi_reg_write(mp, mp->phy_addr, MII_BMCR, data);
return 0; return 0;
} }
@ -2393,12 +2478,39 @@ static int phy_init(struct mv643xx_eth_private *mp,
cmd.duplex = pd->duplex; cmd.duplex = pd->duplex;
} }
update_pscr(mp, cmd.speed, cmd.duplex);
mv643xx_eth_set_settings(mp->dev, &cmd); mv643xx_eth_set_settings(mp->dev, &cmd);
return 0; return 0;
} }
static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
{
u32 pscr;
pscr = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
if (pscr & SERIAL_PORT_ENABLE) {
pscr &= ~SERIAL_PORT_ENABLE;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
}
pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
if (mp->phy_addr == -1) {
pscr |= DISABLE_AUTO_NEG_SPEED_GMII;
if (speed == SPEED_1000)
pscr |= SET_GMII_SPEED_TO_1000;
else if (speed == SPEED_100)
pscr |= SET_MII_SPEED_TO_100;
pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL;
pscr |= DISABLE_AUTO_NEG_FOR_DUPLEX;
if (duplex == DUPLEX_FULL)
pscr |= SET_FULL_DUPLEX_MODE;
}
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
}
static int mv643xx_eth_probe(struct platform_device *pdev) static int mv643xx_eth_probe(struct platform_device *pdev)
{ {
struct mv643xx_eth_platform_data *pd; struct mv643xx_eth_platform_data *pd;
@ -2452,6 +2564,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
} else { } else {
SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless);
} }
init_pscr(mp, pd->speed, pd->duplex);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@ -2478,6 +2591,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
* have to map the buffers to ISA memory which is only 16 MB * have to map the buffers to ISA memory which is only 16 MB
*/ */
dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM;
#endif #endif
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);

View File

@ -536,7 +536,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = eip_poll; dev->poll_controller = eip_poll;
#endif #endif
NS8390_init(dev, 0); NS8390p_init(dev, 0);
ret = register_netdev(dev); ret = register_netdev(dev);
if (ret) if (ret)
@ -794,7 +794,7 @@ retry:
if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
ne_reset_8390(dev); ne_reset_8390(dev);
NS8390_init(dev,1); NS8390p_init(dev, 1);
break; break;
} }
@ -855,7 +855,7 @@ static int ne_drv_resume(struct platform_device *pdev)
if (netif_running(dev)) { if (netif_running(dev)) {
ne_reset_8390(dev); ne_reset_8390(dev);
NS8390_init(dev, 1); NS8390p_init(dev, 1);
netif_device_attach(dev); netif_device_attach(dev);
} }
return 0; return 0;

View File

@ -3143,7 +3143,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
pkt_cnt++; pkt_cnt++;
/* Updating the statistics block */ /* Updating the statistics block */
nic->stats.tx_bytes += skb->len; nic->dev->stats.tx_bytes += skb->len;
nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
@ -4896,25 +4896,42 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
/* Configure Stats for immediate updt */ /* Configure Stats for immediate updt */
s2io_updt_stats(sp); s2io_updt_stats(sp);
/* Using sp->stats as a staging area, because reset (due to mtu
change, for example) will clear some hardware counters */
dev->stats.tx_packets +=
le32_to_cpu(mac_control->stats_info->tmac_frms) -
sp->stats.tx_packets;
sp->stats.tx_packets = sp->stats.tx_packets =
le32_to_cpu(mac_control->stats_info->tmac_frms); le32_to_cpu(mac_control->stats_info->tmac_frms);
dev->stats.tx_errors +=
le32_to_cpu(mac_control->stats_info->tmac_any_err_frms) -
sp->stats.tx_errors;
sp->stats.tx_errors = sp->stats.tx_errors =
le32_to_cpu(mac_control->stats_info->tmac_any_err_frms); le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
dev->stats.rx_errors +=
le64_to_cpu(mac_control->stats_info->rmac_drop_frms) -
sp->stats.rx_errors;
sp->stats.rx_errors = sp->stats.rx_errors =
le64_to_cpu(mac_control->stats_info->rmac_drop_frms); le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
dev->stats.multicast =
le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms) -
sp->stats.multicast;
sp->stats.multicast = sp->stats.multicast =
le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms); le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
dev->stats.rx_length_errors =
le64_to_cpu(mac_control->stats_info->rmac_long_frms) -
sp->stats.rx_length_errors;
sp->stats.rx_length_errors = sp->stats.rx_length_errors =
le64_to_cpu(mac_control->stats_info->rmac_long_frms); le64_to_cpu(mac_control->stats_info->rmac_long_frms);
/* collect per-ring rx_packets and rx_bytes */ /* collect per-ring rx_packets and rx_bytes */
sp->stats.rx_packets = sp->stats.rx_bytes = 0; dev->stats.rx_packets = dev->stats.rx_bytes = 0;
for (i = 0; i < config->rx_ring_num; i++) { for (i = 0; i < config->rx_ring_num; i++) {
sp->stats.rx_packets += mac_control->rings[i].rx_packets; dev->stats.rx_packets += mac_control->rings[i].rx_packets;
sp->stats.rx_bytes += mac_control->rings[i].rx_bytes; dev->stats.rx_bytes += mac_control->rings[i].rx_bytes;
} }
return (&sp->stats); return (&dev->stats);
} }
/** /**
@ -7419,7 +7436,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
if (err_mask != 0x5) { if (err_mask != 0x5) {
DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n", DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n",
dev->name, err_mask); dev->name, err_mask);
sp->stats.rx_crc_errors++; dev->stats.rx_crc_errors++;
sp->mac_control.stats_info->sw_stat.mem_freed sp->mac_control.stats_info->sw_stat.mem_freed
+= skb->truesize; += skb->truesize;
dev_kfree_skb(skb); dev_kfree_skb(skb);

View File

@ -1,7 +1,7 @@
/* /*
* SuperH Ethernet device driver * SuperH Ethernet device driver
* *
* Copyright (C) 2006,2007 Nobuhiro Iwamatsu * Copyright (C) 2006-2008 Nobuhiro Iwamatsu
* Copyright (C) 2008 Renesas Solutions Corp. * Copyright (C) 2008 Renesas Solutions Corp.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -143,13 +143,39 @@ static struct mdiobb_ops bb_ops = {
.get_mdio_data = sh_get_mdio, .get_mdio_data = sh_get_mdio,
}; };
/* Chip Reset */
static void sh_eth_reset(struct net_device *ndev) static void sh_eth_reset(struct net_device *ndev)
{ {
u32 ioaddr = ndev->base_addr; u32 ioaddr = ndev->base_addr;
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
int cnt = 100;
ctrl_outl(EDSR_ENALL, ioaddr + EDSR);
ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
while (cnt > 0) {
if (!(ctrl_inl(ioaddr + EDMR) & 0x3))
break;
mdelay(1);
cnt--;
}
if (cnt < 0)
printk(KERN_ERR "Device reset fail\n");
/* Table Init */
ctrl_outl(0x0, ioaddr + TDLAR);
ctrl_outl(0x0, ioaddr + TDFAR);
ctrl_outl(0x0, ioaddr + TDFXR);
ctrl_outl(0x0, ioaddr + TDFFR);
ctrl_outl(0x0, ioaddr + RDLAR);
ctrl_outl(0x0, ioaddr + RDFAR);
ctrl_outl(0x0, ioaddr + RDFXR);
ctrl_outl(0x0, ioaddr + RDFFR);
#else
ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
mdelay(3); mdelay(3);
ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
#endif
} }
/* free skb and descriptor buffer */ /* free skb and descriptor buffer */
@ -180,6 +206,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
/* format skb and descriptor buffer */ /* format skb and descriptor buffer */
static void sh_eth_ring_format(struct net_device *ndev) static void sh_eth_ring_format(struct net_device *ndev)
{ {
u32 ioaddr = ndev->base_addr, reserve = 0;
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
int i; int i;
struct sk_buff *skb; struct sk_buff *skb;
@ -201,9 +228,15 @@ static void sh_eth_ring_format(struct net_device *ndev)
mdp->rx_skbuff[i] = skb; mdp->rx_skbuff[i] = skb;
if (skb == NULL) if (skb == NULL)
break; break;
skb->dev = ndev; /* Mark as being used by this device. */ skb->dev = ndev; /* Mark as being used by this device. */
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
reserve = SH7763_SKB_ALIGN
- ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1));
if (reserve)
skb_reserve(skb, reserve);
#else
skb_reserve(skb, RX_OFFSET); skb_reserve(skb, RX_OFFSET);
#endif
/* 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;
@ -211,12 +244,25 @@ static void sh_eth_ring_format(struct net_device *ndev)
/* 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;
/* Rx descriptor address set */
if (i == 0) {
ctrl_outl((u32)rxdesc, ioaddr + RDLAR);
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl((u32)rxdesc, ioaddr + RDFAR);
#endif
}
} }
/* Rx descriptor address set */
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl((u32)rxdesc, ioaddr + RDFXR);
ctrl_outl(0x1, ioaddr + RDFFR);
#endif
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(RC_RDEL); rxdesc->status |= cpu_to_le32(RD_RDEL);
memset(mdp->tx_ring, 0, tx_ringsize); memset(mdp->tx_ring, 0, tx_ringsize);
@ -226,8 +272,21 @@ static void sh_eth_ring_format(struct net_device *ndev)
txdesc = &mdp->tx_ring[i]; txdesc = &mdp->tx_ring[i];
txdesc->status = cpu_to_le32(TD_TFP); txdesc->status = cpu_to_le32(TD_TFP);
txdesc->buffer_length = 0; txdesc->buffer_length = 0;
if (i == 0) {
/* Rx descriptor address set */
ctrl_outl((u32)txdesc, ioaddr + TDLAR);
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl((u32)txdesc, ioaddr + TDFAR);
#endif
}
} }
/* Rx 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_le32(TD_TDLE);
} }
@ -311,31 +370,43 @@ static int sh_eth_dev_init(struct net_device *ndev)
/* Soft Reset */ /* Soft Reset */
sh_eth_reset(ndev); sh_eth_reset(ndev);
ctrl_outl(RPADIR_PADS1, ioaddr + RPADIR); /* SH7712-DMA-RX-PAD2 */ /* Descriptor format */
sh_eth_ring_format(ndev);
ctrl_outl(RPADIR_INIT, ioaddr + RPADIR);
/* all sh_eth int mask */ /* all sh_eth int mask */
ctrl_outl(0, ioaddr + EESIPR); ctrl_outl(0, ioaddr + EESIPR);
/* FIFO size set */ #if defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl(EDMR_EL, ioaddr + EDMR);
#else
ctrl_outl(0, ioaddr + EDMR); /* Endian change */ ctrl_outl(0, ioaddr + EDMR); /* Endian change */
#endif
/* FIFO size set */
ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR); ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR);
ctrl_outl(0, ioaddr + TFTR); ctrl_outl(0, ioaddr + TFTR);
/* Frame recv control */
ctrl_outl(0, ioaddr + RMCR); ctrl_outl(0, ioaddr + RMCR);
rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5; rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
tx_int_var = mdp->tx_int_var = DESC_I_TINT2; tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER); ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER);
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
/* Burst sycle set */
ctrl_outl(0x800, ioaddr + BCULR);
#endif
ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR); ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR);
#if !defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl(0, ioaddr + TRIMD); ctrl_outl(0, ioaddr + TRIMD);
#endif
/* Descriptor format */ /* Recv frame limit set register */
sh_eth_ring_format(ndev); ctrl_outl(RFLR_VALUE, ioaddr + RFLR);
ctrl_outl((u32)mdp->rx_ring, ioaddr + RDLAR);
ctrl_outl((u32)mdp->tx_ring, ioaddr + TDLAR);
ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR); ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR);
ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR); ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR);
@ -345,21 +416,26 @@ static int sh_eth_dev_init(struct net_device *ndev)
ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE; ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
ctrl_outl(val, ioaddr + ECMR); ctrl_outl(val, ioaddr + ECMR);
ctrl_outl(ECSR_BRCRX | ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD |
ECSIPR_MPDIP, ioaddr + ECSR); /* E-MAC Status Register clear */
ctrl_outl(ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ctrl_outl(ECSR_INIT, ioaddr + ECSR);
ECSIPR_ICDIP | ECSIPR_MPDIP, ioaddr + ECSIPR);
/* E-MAC Interrupt Enable register */
ctrl_outl(ECSIPR_INIT, ioaddr + ECSIPR);
/* Set MAC address */ /* Set MAC address */
update_mac_address(ndev); update_mac_address(ndev);
/* mask reset */ /* mask reset */
#if defined(CONFIG_CPU_SUBTYPE_SH7710) #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl(APR_AP, ioaddr + APR); ctrl_outl(APR_AP, ioaddr + APR);
ctrl_outl(MPR_MP, ioaddr + MPR); ctrl_outl(MPR_MP, ioaddr + MPR);
ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER); ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7710)
ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR); ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR);
#endif #endif
/* Setting the Rx mode will start the Rx process. */ /* Setting the Rx mode will start the Rx process. */
ctrl_outl(EDRRR_R, ioaddr + EDRRR); ctrl_outl(EDRRR_R, ioaddr + EDRRR);
@ -407,7 +483,7 @@ static int sh_eth_rx(struct net_device *ndev)
int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
struct sk_buff *skb; struct sk_buff *skb;
u16 pkt_len = 0; u16 pkt_len = 0;
u32 desc_status; 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_le32(RD_RACT))) {
@ -454,28 +530,38 @@ static int sh_eth_rx(struct net_device *ndev)
for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
entry = mdp->dirty_rx % RX_RING_SIZE; entry = mdp->dirty_rx % RX_RING_SIZE;
rxdesc = &mdp->rx_ring[entry]; rxdesc = &mdp->rx_ring[entry];
/* The size of the buffer is 16 byte boundary. */
rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
if (mdp->rx_skbuff[entry] == NULL) { if (mdp->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb(mdp->rx_buf_sz); skb = dev_alloc_skb(mdp->rx_buf_sz);
mdp->rx_skbuff[entry] = skb; mdp->rx_skbuff[entry] = skb;
if (skb == NULL) if (skb == NULL)
break; /* Better luck next round. */ break; /* Better luck next round. */
skb->dev = ndev; skb->dev = ndev;
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
reserve = SH7763_SKB_ALIGN
- ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1));
if (reserve)
skb_reserve(skb, reserve);
#else
skb_reserve(skb, RX_OFFSET); skb_reserve(skb, RX_OFFSET);
#endif
skb->ip_summed = CHECKSUM_NONE;
rxdesc->addr = (u32)skb->data & ~0x3UL; rxdesc->addr = (u32)skb->data & ~0x3UL;
} }
/* The size of the buffer is 16 byte boundary. */
rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
if (entry >= RX_RING_SIZE - 1) if (entry >= RX_RING_SIZE - 1)
rxdesc->status |= rxdesc->status |=
cpu_to_le32(RD_RACT | RD_RFP | RC_RDEL); cpu_to_le32(RD_RACT | RD_RFP | RD_RDEL);
else else
rxdesc->status |= rxdesc->status |=
cpu_to_le32(RD_RACT | RD_RFP); cpu_to_le32(RD_RACT | RD_RFP);
} }
/* Restart Rx engine if stopped. */ /* Restart Rx engine if stopped. */
/* If we don't need to check status, don't. -KDU */ /* If we don't need to check status, don't. -KDU */
ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR); if (!(ctrl_inl(ndev->base_addr + EDRRR) & EDRRR_R))
ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR);
return 0; return 0;
} }
@ -529,13 +615,14 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
printk(KERN_ERR "Receive Frame Overflow\n"); printk(KERN_ERR "Receive Frame Overflow\n");
} }
} }
#if !defined(CONFIG_CPU_SUBTYPE_SH7763)
if (intr_status & EESR_ADE) { if (intr_status & EESR_ADE) {
if (intr_status & EESR_TDE) { if (intr_status & EESR_TDE) {
if (intr_status & EESR_TFE) if (intr_status & EESR_TFE)
mdp->stats.tx_fifo_errors++; mdp->stats.tx_fifo_errors++;
} }
} }
#endif
if (intr_status & EESR_RDE) { if (intr_status & EESR_RDE) {
/* Receive Descriptor Empty int */ /* Receive Descriptor Empty int */
@ -550,8 +637,11 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
mdp->stats.rx_fifo_errors++; mdp->stats.rx_fifo_errors++;
printk(KERN_ERR "Receive FIFO Overflow\n"); printk(KERN_ERR "Receive FIFO Overflow\n");
} }
if (intr_status & if (intr_status & (EESR_TWB | EESR_TABT |
(EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE)) { #if !defined(CONFIG_CPU_SUBTYPE_SH7763)
EESR_ADE |
#endif
EESR_TDE | EESR_TFE)) {
/* Tx error */ /* Tx error */
u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR); u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR);
/* dmesg */ /* dmesg */
@ -582,17 +672,23 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
ioaddr = ndev->base_addr; ioaddr = ndev->base_addr;
spin_lock(&mdp->lock); spin_lock(&mdp->lock);
/* Get interrpt stat */
intr_status = ctrl_inl(ioaddr + EESR); intr_status = ctrl_inl(ioaddr + EESR);
/* Clear interrupt */ /* Clear interrupt */
ctrl_outl(intr_status, ioaddr + EESR); ctrl_outl(intr_status, ioaddr + EESR);
if (intr_status & (EESR_FRC | EESR_RINT8 | if (intr_status & (EESR_FRC | /* Frame recv*/
EESR_RINT5 | EESR_RINT4 | EESR_RINT3 | EESR_RINT2 | EESR_RMAF | /* Multi cast address recv*/
EESR_RINT1)) EESR_RRF | /* Bit frame recv */
EESR_RTLF | /* Long frame recv*/
EESR_RTSF | /* short frame recv */
EESR_PRE | /* PHY-LSI recv error */
EESR_CERF)){ /* recv frame CRC error */
sh_eth_rx(ndev); sh_eth_rx(ndev);
if (intr_status & (EESR_FTC | }
EESR_TINT4 | EESR_TINT3 | EESR_TINT2 | EESR_TINT1)) {
/* Tx Check */
if (intr_status & TX_CHECK) {
sh_eth_txfree(ndev); sh_eth_txfree(ndev);
netif_wake_queue(ndev); netif_wake_queue(ndev);
} }
@ -631,11 +727,32 @@ static void sh_eth_adjust_link(struct net_device *ndev)
if (phydev->duplex != mdp->duplex) { if (phydev->duplex != mdp->duplex) {
new_state = 1; new_state = 1;
mdp->duplex = phydev->duplex; mdp->duplex = phydev->duplex;
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
if (mdp->duplex) { /* FULL */
ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM,
ioaddr + ECMR);
} else { /* Half */
ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM,
ioaddr + ECMR);
}
#endif
} }
if (phydev->speed != mdp->speed) { if (phydev->speed != mdp->speed) {
new_state = 1; new_state = 1;
mdp->speed = phydev->speed; mdp->speed = phydev->speed;
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
switch (mdp->speed) {
case 10: /* 10BASE */
ctrl_outl(GECMR_10, ioaddr + GECMR); break;
case 100:/* 100BASE */
ctrl_outl(GECMR_100, ioaddr + GECMR); break;
case 1000: /* 1000BASE */
ctrl_outl(GECMR_1000, ioaddr + GECMR); break;
default:
break;
}
#endif
} }
if (mdp->link == PHY_DOWN) { if (mdp->link == PHY_DOWN) {
ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF) ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF)
@ -730,7 +847,7 @@ static int sh_eth_open(struct net_device *ndev)
/* Set the timer to check for link beat. */ /* Set the timer to check for link beat. */
init_timer(&mdp->timer); init_timer(&mdp->timer);
mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */ mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
setup_timer(&mdp->timer, sh_eth_timer, ndev); setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev);
return ret; return ret;
@ -820,7 +937,9 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
mdp->cur_tx++; mdp->cur_tx++;
ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); if (!(ctrl_inl(ndev->base_addr + EDTRR) & EDTRR_TRNS))
ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR);
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
return 0; return 0;
@ -877,9 +996,15 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
ctrl_outl(0, ioaddr + CDCR); /* (write clear) */ ctrl_outl(0, ioaddr + CDCR); /* (write clear) */
mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR); mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR);
ctrl_outl(0, ioaddr + LCCR); /* (write clear) */ ctrl_outl(0, ioaddr + LCCR); /* (write clear) */
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CERCR);/* CERCR */
ctrl_outl(0, ioaddr + CERCR); /* (write clear) */
mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CEECR);/* CEECR */
ctrl_outl(0, ioaddr + CEECR); /* (write clear) */
#else
mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR); mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR);
ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */ ctrl_outl(0, ioaddr + CNDCR); /* (write clear) */
#endif
return &mdp->stats; return &mdp->stats;
} }
@ -929,8 +1054,13 @@ static void sh_eth_tsu_init(u32 ioaddr)
ctrl_outl(0, ioaddr + TSU_FWSL0); ctrl_outl(0, ioaddr + TSU_FWSL0);
ctrl_outl(0, ioaddr + TSU_FWSL1); ctrl_outl(0, ioaddr + TSU_FWSL1);
ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC); ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
ctrl_outl(0, ioaddr + TSU_QTAG0); /* Disable QTAG(0->1) */
ctrl_outl(0, ioaddr + TSU_QTAG1); /* Disable QTAG(1->0) */
#else
ctrl_outl(0, ioaddr + TSU_QTAGM0); /* Disable QTAG(0->1) */ ctrl_outl(0, ioaddr + TSU_QTAGM0); /* Disable QTAG(0->1) */
ctrl_outl(0, ioaddr + TSU_QTAGM1); /* Disable QTAG(1->0) */ ctrl_outl(0, ioaddr + TSU_QTAGM1); /* Disable QTAG(1->0) */
#endif
ctrl_outl(0, ioaddr + TSU_FWSR); /* all interrupt status clear */ ctrl_outl(0, ioaddr + TSU_FWSR); /* all interrupt status clear */
ctrl_outl(0, ioaddr + TSU_FWINMK); /* Disable all interrupt */ ctrl_outl(0, ioaddr + TSU_FWINMK); /* Disable all interrupt */
ctrl_outl(0, ioaddr + TSU_TEN); /* Disable all CAM entry */ ctrl_outl(0, ioaddr + TSU_TEN); /* Disable all CAM entry */
@ -1088,7 +1218,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
/* First device only init */ /* First device only init */
if (!devno) { if (!devno) {
/* reset device */ /* reset device */
ctrl_outl(ARSTR_ARSTR, ndev->base_addr + ARSTR); ctrl_outl(ARSTR_ARSTR, ARSTR);
mdelay(1); mdelay(1);
/* TSU init (Init only)*/ /* TSU init (Init only)*/
@ -1110,8 +1240,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 "%2.2x:", ndev->dev_addr[i]); printk(KERN_INFO "%02X:", ndev->dev_addr[i]);
printk(KERN_INFO "%2.2x, IRQ %d.\n", ndev->dev_addr[i], ndev->irq); printk(KERN_INFO "%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);
platform_set_drvdata(pdev, ndev); platform_set_drvdata(pdev, ndev);

View File

@ -32,118 +32,249 @@
#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 128 /* Tx ring size */ #define RX_RING_SIZE 64 /* Rx ring size */
#define RX_RING_SIZE 128 /* Rx ring size */
#define RX_OFFSET 2 /* skb offset */
#define ETHERSMALL 60 #define ETHERSMALL 60
#define PKT_BUF_SZ 1538 #define PKT_BUF_SZ 1538
#ifdef CONFIG_CPU_SUBTYPE_SH7763
#define SH7763_SKB_ALIGN 32
/* Chip Base Address */ /* Chip Base Address */
#define SH_TSU_ADDR 0xA7000804 # define SH_TSU_ADDR 0xFFE01800
# define ARSTR 0xFFE01800
/* Chip Registers */ /* Chip Registers */
/* E-DMAC */ /* E-DMAC */
#define EDMR 0x0000 # define EDSR 0x000
#define EDTRR 0x0004 # define EDMR 0x400
#define EDRRR 0x0008 # define EDTRR 0x408
#define TDLAR 0x000C # define EDRRR 0x410
#define RDLAR 0x0010 # define EESR 0x428
#define EESR 0x0014 # define EESIPR 0x430
#define EESIPR 0x0018 # define TDLAR 0x010
#define TRSCER 0x001C # define TDFAR 0x014
#define RMFCR 0x0020 # define TDFXR 0x018
#define TFTR 0x0024 # define TDFFR 0x01C
#define FDR 0x0028 # define RDLAR 0x030
#define RMCR 0x002C # define RDFAR 0x034
#define EDOCR 0x0030 # define RDFXR 0x038
#define FCFTR 0x0034 # define RDFFR 0x03C
#define RPADIR 0x0038 # define TRSCER 0x438
#define TRIMD 0x003C # define RMFCR 0x440
#define RBWAR 0x0040 # define TFTR 0x448
#define RDFAR 0x0044 # define FDR 0x450
#define TBRAR 0x004C # define RMCR 0x458
#define TDFAR 0x0050 # define RPADIR 0x460
/* Ether Register */ # define FCFTR 0x468
#define ECMR 0x0160
#define ECSR 0x0164
#define ECSIPR 0x0168
#define PIR 0x016C
#define MAHR 0x0170
#define MALR 0x0174
#define RFLR 0x0178
#define PSR 0x017C
#define TROCR 0x0180
#define CDCR 0x0184
#define LCCR 0x0188
#define CNDCR 0x018C
#define CEFCR 0x0194
#define FRECR 0x0198
#define TSFRCR 0x019C
#define TLFRCR 0x01A0
#define RFCR 0x01A4
#define MAFCR 0x01A8
#define IPGR 0x01B4
#if defined(CONFIG_CPU_SUBTYPE_SH7710)
#define APR 0x01B8
#define MPR 0x01BC
#define TPAUSER 0x1C4
#define BCFR 0x1CC
#endif /* CONFIG_CPU_SH7710 */
#define ARSTR 0x0800 /* Ether Register */
# define ECMR 0x500
# define ECSR 0x510
# define ECSIPR 0x518
# define PIR 0x520
# define PSR 0x528
# define PIPR 0x52C
# define RFLR 0x508
# define APR 0x554
# define MPR 0x558
# define PFTCR 0x55C
# define PFRCR 0x560
# define TPAUSER 0x564
# define GECMR 0x5B0
# define BCULR 0x5B4
# define MAHR 0x5C0
# define MALR 0x5C8
# define TROCR 0x700
# define CDCR 0x708
# define LCCR 0x710
# define CEFCR 0x740
# define FRECR 0x748
# define TSFRCR 0x750
# define TLFRCR 0x758
# define RFCR 0x760
# define CERCR 0x768
# define CEECR 0x770
# define MAFCR 0x778
/* TSU Absolute Address */
# define TSU_CTRST 0x004
# define TSU_FWEN0 0x010
# define TSU_FWEN1 0x014
# define TSU_FCM 0x18
# define TSU_BSYSL0 0x20
# define TSU_BSYSL1 0x24
# define TSU_PRISL0 0x28
# define TSU_PRISL1 0x2C
# define TSU_FWSL0 0x30
# define TSU_FWSL1 0x34
# define TSU_FWSLC 0x38
# define TSU_QTAG0 0x40
# define TSU_QTAG1 0x44
# define TSU_FWSR 0x50
# define TSU_FWINMK 0x54
# define TSU_ADQT0 0x48
# define TSU_ADQT1 0x4C
# define TSU_VTAG0 0x58
# define TSU_VTAG1 0x5C
# define TSU_ADSBSY 0x60
# define TSU_TEN 0x64
# define TSU_POST1 0x70
# define TSU_POST2 0x74
# define TSU_POST3 0x78
# define TSU_POST4 0x7C
# define TSU_ADRH0 0x100
# define TSU_ADRL0 0x104
# define TSU_ADRH31 0x1F8
# define TSU_ADRL31 0x1FC
# define TXNLCR0 0x80
# define TXALCR0 0x84
# define RXNLCR0 0x88
# define RXALCR0 0x8C
# define FWNLCR0 0x90
# define FWALCR0 0x94
# define TXNLCR1 0xA0
# define TXALCR1 0xA4
# define RXNLCR1 0xA8
# define RXALCR1 0xAC
# define FWNLCR1 0xB0
# define FWALCR1 0x40
#else /* CONFIG_CPU_SUBTYPE_SH7763 */
# define RX_OFFSET 2 /* skb offset */
/* Chip base address */
# define SH_TSU_ADDR 0xA7000804
# define ARSTR 0xA7000800
/* Chip Registers */
/* E-DMAC */
# define EDMR 0x0000
# define EDTRR 0x0004
# define EDRRR 0x0008
# define TDLAR 0x000C
# define RDLAR 0x0010
# define EESR 0x0014
# define EESIPR 0x0018
# define TRSCER 0x001C
# define RMFCR 0x0020
# define TFTR 0x0024
# define FDR 0x0028
# define RMCR 0x002C
# define EDOCR 0x0030
# define FCFTR 0x0034
# define RPADIR 0x0038
# define TRIMD 0x003C
# define RBWAR 0x0040
# define RDFAR 0x0044
# define TBRAR 0x004C
# define TDFAR 0x0050
/* Ether Register */
# define ECMR 0x0160
# define ECSR 0x0164
# define ECSIPR 0x0168
# define PIR 0x016C
# define MAHR 0x0170
# define MALR 0x0174
# define RFLR 0x0178
# define PSR 0x017C
# define TROCR 0x0180
# define CDCR 0x0184
# define LCCR 0x0188
# define CNDCR 0x018C
# define CEFCR 0x0194
# define FRECR 0x0198
# define TSFRCR 0x019C
# define TLFRCR 0x01A0
# define RFCR 0x01A4
# define MAFCR 0x01A8
# define IPGR 0x01B4
# if defined(CONFIG_CPU_SUBTYPE_SH7710)
# define APR 0x01B8
# define MPR 0x01BC
# define TPAUSER 0x1C4
# define BCFR 0x1CC
# endif /* CONFIG_CPU_SH7710 */
/* TSU */ /* TSU */
#define TSU_CTRST 0x004 # define TSU_CTRST 0x004
#define TSU_FWEN0 0x010 # define TSU_FWEN0 0x010
#define TSU_FWEN1 0x014 # define TSU_FWEN1 0x014
#define TSU_FCM 0x018 # define TSU_FCM 0x018
#define TSU_BSYSL0 0x020 # define TSU_BSYSL0 0x020
#define TSU_BSYSL1 0x024 # define TSU_BSYSL1 0x024
#define TSU_PRISL0 0x028 # define TSU_PRISL0 0x028
#define TSU_PRISL1 0x02C # define TSU_PRISL1 0x02C
#define TSU_FWSL0 0x030 # define TSU_FWSL0 0x030
#define TSU_FWSL1 0x034 # define TSU_FWSL1 0x034
#define TSU_FWSLC 0x038 # define TSU_FWSLC 0x038
#define TSU_QTAGM0 0x040 # define TSU_QTAGM0 0x040
#define TSU_QTAGM1 0x044 # define TSU_QTAGM1 0x044
#define TSU_ADQT0 0x048 # define TSU_ADQT0 0x048
#define TSU_ADQT1 0x04C # define TSU_ADQT1 0x04C
#define TSU_FWSR 0x050 # define TSU_FWSR 0x050
#define TSU_FWINMK 0x054 # define TSU_FWINMK 0x054
#define TSU_ADSBSY 0x060 # define TSU_ADSBSY 0x060
#define TSU_TEN 0x064 # define TSU_TEN 0x064
#define TSU_POST1 0x070 # define TSU_POST1 0x070
#define TSU_POST2 0x074 # define TSU_POST2 0x074
#define TSU_POST3 0x078 # define TSU_POST3 0x078
#define TSU_POST4 0x07C # define TSU_POST4 0x07C
#define TXNLCR0 0x080 # define TXNLCR0 0x080
#define TXALCR0 0x084 # define TXALCR0 0x084
#define RXNLCR0 0x088 # define RXNLCR0 0x088
#define RXALCR0 0x08C # define RXALCR0 0x08C
#define FWNLCR0 0x090 # define FWNLCR0 0x090
#define FWALCR0 0x094 # define FWALCR0 0x094
#define TXNLCR1 0x0A0 # define TXNLCR1 0x0A0
#define TXALCR1 0x0A4 # define TXALCR1 0x0A4
#define RXNLCR1 0x0A8 # define RXNLCR1 0x0A8
#define RXALCR1 0x0AC # define RXALCR1 0x0AC
#define FWNLCR1 0x0B0 # define FWNLCR1 0x0B0
#define FWALCR1 0x0B4 # define FWALCR1 0x0B4
#define TSU_ADRH0 0x0100 #define TSU_ADRH0 0x0100
#define TSU_ADRL0 0x0104 #define TSU_ADRL0 0x0104
#define TSU_ADRL31 0x01FC #define TSU_ADRL31 0x01FC
/* Register's bits */ #endif /* CONFIG_CPU_SUBTYPE_SH7763 */
/*
* Register's bits
*/
#ifdef CONFIG_CPU_SUBTYPE_SH7763
/* EDSR */
enum EDSR_BIT {
EDSR_ENT = 0x01, EDSR_ENR = 0x02,
};
#define EDSR_ENALL (EDSR_ENT|EDSR_ENR)
/* GECMR */
enum GECMR_BIT {
GECMR_10 = 0x0, GECMR_100 = 0x04, GECMR_1000 = 0x01,
};
#endif
/* EDMR */ /* EDMR */
enum DMAC_M_BIT { enum DMAC_M_BIT {
EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, EDMR_SRST = 0x01, EDMR_DL1 = 0x20, EDMR_DL0 = 0x10,
#ifdef CONFIG_CPU_SUBTYPE_SH7763
EDMR_SRST = 0x03,
EMDR_DESC_R = 0x30, /* Descriptor reserve size */
EDMR_EL = 0x40, /* Litte endian */
#else /* CONFIG_CPU_SUBTYPE_SH7763 */
EDMR_SRST = 0x01,
#endif
}; };
/* EDTRR */ /* EDTRR */
enum DMAC_T_BIT { enum DMAC_T_BIT {
#ifdef CONFIG_CPU_SUBTYPE_SH7763
EDTRR_TRNS = 0x03,
#else
EDTRR_TRNS = 0x01, EDTRR_TRNS = 0x01,
#endif
}; };
/* EDRRR*/ /* EDRRR*/
@ -173,21 +304,47 @@ enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, };
/* EESR */ /* EESR */
enum EESR_BIT { enum EESR_BIT {
EESR_TWB = 0x40000000, EESR_TABT = 0x04000000, #ifndef CONFIG_CPU_SUBTYPE_SH7763
EESR_TWB = 0x40000000,
#else
EESR_TWB = 0xC0000000,
EESR_TC1 = 0x20000000,
EESR_TUC = 0x10000000,
EESR_ROC = 0x80000000,
#endif
EESR_TABT = 0x04000000,
EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000, EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000,
EESR_ADE = 0x00800000, EESR_ECI = 0x00400000, #ifndef CONFIG_CPU_SUBTYPE_SH7763
EESR_FTC = 0x00200000, EESR_TDE = 0x00100000, EESR_ADE = 0x00800000,
EESR_TFE = 0x00080000, EESR_FRC = 0x00040000, #endif
EESR_RDE = 0x00020000, EESR_RFE = 0x00010000, EESR_ECI = 0x00400000,
EESR_TINT4 = 0x00000800, EESR_TINT3 = 0x00000400, EESR_FTC = 0x00200000, EESR_TDE = 0x00100000,
EESR_TINT2 = 0x00000200, EESR_TINT1 = 0x00000100, EESR_TFE = 0x00080000, EESR_FRC = 0x00040000,
EESR_RINT8 = 0x00000080, EESR_RINT5 = 0x00000010, EESR_RDE = 0x00020000, EESR_RFE = 0x00010000,
EESR_RINT4 = 0x00000008, EESR_RINT3 = 0x00000004, #ifndef CONFIG_CPU_SUBTYPE_SH7763
EESR_RINT2 = 0x00000002, EESR_RINT1 = 0x00000001, EESR_CND = 0x00000800,
#endif
EESR_DLC = 0x00000400,
EESR_CD = 0x00000200, EESR_RTO = 0x00000100,
EESR_RMAF = 0x00000080, EESR_CEEF = 0x00000040,
EESR_CELF = 0x00000020, EESR_RRF = 0x00000010,
EESR_RTLF = 0x00000008, EESR_RTSF = 0x00000004,
EESR_PRE = 0x00000002, EESR_CERF = 0x00000001,
}; };
#define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
#ifdef CONFIG_CPU_SUBTYPE_SH7763
# define TX_CHECK (EESR_TC1 | EESR_FTC)
# define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
| EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI)
# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE)
#else
# define TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO)
# define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
| EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI) | EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI)
# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE)
#endif
/* EESIPR */ /* EESIPR */
enum DMAC_IM_BIT { enum DMAC_IM_BIT {
@ -207,8 +364,8 @@ enum DMAC_IM_BIT {
/* Receive descriptor bit */ /* Receive descriptor bit */
enum RD_STS_BIT { enum RD_STS_BIT {
RD_RACT = 0x80000000, RC_RDEL = 0x40000000, RD_RACT = 0x80000000, RD_RDEL = 0x40000000,
RC_RFP1 = 0x20000000, RC_RFP0 = 0x10000000, RD_RFP1 = 0x20000000, RD_RFP0 = 0x10000000,
RD_RFE = 0x08000000, RD_RFS10 = 0x00000200, RD_RFE = 0x08000000, RD_RFS10 = 0x00000200,
RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080, RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080,
RD_RFS7 = 0x00000040, RD_RFS6 = 0x00000020, RD_RFS7 = 0x00000040, RD_RFS6 = 0x00000020,
@ -216,9 +373,9 @@ enum RD_STS_BIT {
RD_RFS3 = 0x00000004, RD_RFS2 = 0x00000002, RD_RFS3 = 0x00000004, RD_RFS2 = 0x00000002,
RD_RFS1 = 0x00000001, RD_RFS1 = 0x00000001,
}; };
#define RDF1ST RC_RFP1 #define RDF1ST RD_RFP1
#define RDFEND RC_RFP0 #define RDFEND RD_RFP0
#define RD_RFP (RC_RFP1|RC_RFP0) #define RD_RFP (RD_RFP1|RD_RFP0)
/* FCFTR */ /* FCFTR */
enum FCFTR_BIT { enum FCFTR_BIT {
@ -231,7 +388,8 @@ enum FCFTR_BIT {
/* Transfer descriptor bit */ /* Transfer descriptor bit */
enum TD_STS_BIT { enum TD_STS_BIT {
TD_TACT = 0x80000000, TD_TDLE = 0x40000000, TD_TFP1 = 0x20000000, TD_TACT = 0x80000000,
TD_TDLE = 0x40000000, TD_TFP1 = 0x20000000,
TD_TFP0 = 0x10000000, TD_TFP0 = 0x10000000,
}; };
#define TDF1ST TD_TFP1 #define TDF1ST TD_TFP1
@ -242,6 +400,10 @@ enum TD_STS_BIT {
enum RECV_RST_BIT { RMCR_RST = 0x01, }; enum RECV_RST_BIT { RMCR_RST = 0x01, };
/* ECMR */ /* ECMR */
enum FELIC_MODE_BIT { enum FELIC_MODE_BIT {
#ifdef CONFIG_CPU_SUBTYPE_SH7763
ECMR_TRCCM = 0x04000000, ECMR_RCSC = 0x00800000,
ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000,
#endif
ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000,
ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000,
ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020,
@ -249,18 +411,45 @@ enum FELIC_MODE_BIT {
ECMR_PRM = 0x00000001, ECMR_PRM = 0x00000001,
}; };
#ifdef CONFIG_CPU_SUBTYPE_SH7763
#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\
ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
#else
#define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR ECMR_RXF | ECMR_TXF | ECMR_MCT)
#endif
/* ECSR */ /* ECSR */
enum ECSR_STATUS_BIT { enum ECSR_STATUS_BIT {
ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10, ECSR_LCHNG = 0x04, #ifndef CONFIG_CPU_SUBTYPE_SH7763
ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10,
#endif
ECSR_LCHNG = 0x04,
ECSR_MPD = 0x02, ECSR_ICD = 0x01, ECSR_MPD = 0x02, ECSR_ICD = 0x01,
}; };
#ifdef CONFIG_CPU_SUBTYPE_SH7763
# define ECSR_INIT (ECSR_ICD | ECSIPR_MPDIP)
#else
# define ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | \
ECSR_LCHNG | ECSR_ICD | ECSIPR_MPDIP)
#endif
/* ECSIPR */ /* ECSIPR */
enum ECSIPR_STATUS_MASK_BIT { enum ECSIPR_STATUS_MASK_BIT {
ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10, ECSIPR_LCHNGIP = 0x04, #ifndef CONFIG_CPU_SUBTYPE_SH7763
ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10,
#endif
ECSIPR_LCHNGIP = 0x04,
ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01, ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01,
}; };
#ifdef CONFIG_CPU_SUBTYPE_SH7763
# define ECSIPR_INIT (ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP)
#else
# define ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | \
ECSIPR_ICDIP | ECSIPR_MPDIP)
#endif
/* APR */ /* APR */
enum APR_BIT { enum APR_BIT {
APR_AP = 0x00000001, APR_AP = 0x00000001,
@ -285,6 +474,15 @@ enum RPADIR_BIT {
RPADIR_PADR = 0x0003f, RPADIR_PADR = 0x0003f,
}; };
#if defined(CONFIG_CPU_SUBTYPE_SH7763)
# define RPADIR_INIT (0x00)
#else
# define RPADIR_INIT (RPADIR_PADS1)
#endif
/* RFLR */
#define RFLR_VALUE 0x1000
/* FDR */ /* FDR */
enum FIFO_SIZE_BIT { enum FIFO_SIZE_BIT {
FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007, FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
@ -316,7 +514,7 @@ enum PHY_ANA_BIT {
PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000, PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000,
PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100, PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100,
PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020, PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020,
PHY_A_SEL = 0x001f, PHY_A_SEL = 0x001e,
}; };
/* PHY_ANL */ /* PHY_ANL */
enum PHY_ANL_BIT { enum PHY_ANL_BIT {
@ -449,6 +647,10 @@ struct sh_eth_private {
struct net_device_stats tsu_stats; /* TSU forward status */ struct net_device_stats tsu_stats; /* TSU forward status */
}; };
#ifdef CONFIG_CPU_SUBTYPE_SH7763
/* SH7763 has endian control register */
#define swaps(x, y)
#else
static void swaps(char *src, int len) static void swaps(char *src, int len)
{ {
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
@ -460,5 +662,5 @@ static void swaps(char *src, int len)
*p = swab32(*p); *p = swab32(*p);
#endif #endif
} }
#endif /* CONFIG_CPU_SUBTYPE_SH7763 */
#endif #endif

View File

@ -55,12 +55,28 @@
static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
{ {
void *buf;
int err = -ENOMEM;
devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length); devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length);
return usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0), buf = kmalloc(length, GFP_KERNEL);
DM_READ_REGS, if (!buf)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, goto out;
0, reg, data, length, USB_CTRL_SET_TIMEOUT);
err = usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
DM_READ_REGS,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
if (err == length)
memcpy(data, buf, length);
else if (err >= 0)
err = -EINVAL;
kfree(buf);
out:
return err;
} }
static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value) static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
@ -70,12 +86,28 @@ static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
{ {
void *buf = NULL;
int err = -ENOMEM;
devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length); devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length);
return usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0), if (data) {
DM_WRITE_REGS, buf = kmalloc(length, GFP_KERNEL);
USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, if (!buf)
0, reg, data, length, USB_CTRL_SET_TIMEOUT); goto out;
memcpy(buf, data, length);
}
err = usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
DM_WRITE_REGS,
USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
kfree(buf);
if (err >= 0 && err < length)
err = -EINVAL;
out:
return err;
} }
static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)

View File

@ -337,7 +337,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ei_poll; dev->poll_controller = ei_poll;
#endif #endif
NS8390_init(dev, 0); NS8390p_init(dev, 0);
#if 1 #if 1
/* Enable interrupt generation on softconfig cards -- M.U */ /* Enable interrupt generation on softconfig cards -- M.U */