* [PATCH] au1000_eth.c power management and driver registration support
[not found] ` <20060714075441.GE7186@gundam.enneenne.com>
@ 2006-07-19 8:29 ` Rodolfo Giometti
0 siblings, 0 replies; only message in thread
From: Rodolfo Giometti @ 2006-07-19 8:29 UTC (permalink / raw)
To: linux-mips; +Cc: netdev
[-- Attachment #1.1: Type: text/plain, Size: 539 bytes --]
Hello,
Attached you can find my patch to add power managament and driver
registration to the new version of file "drivers/net/au1000_eth.c"
that implements the PHY-layer support.
Ciao,
Rodolfo Giometti
Signed-off-by: Rodolfo Giometti <giometti@linux.it
--
GNU/Linux Solutions e-mail: giometti@enneenne.com
Linux Device Driver giometti@gnudd.com
Embedded Systems giometti@linux.it
UNIX programming phone: +39 349 2432127
[-- Attachment #1.2: patch-au1000_eth-pm-and-registration --]
[-- Type: text/plain, Size: 28787 bytes --]
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
index 7acfe9b..d94bde1 100644
--- a/arch/mips/au1000/common/au1xxx_irqmap.c
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -117,7 +117,7 @@ #elif defined(CONFIG_SOC_AU1500)
{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
{ AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
@@ -151,7 +151,7 @@ #elif defined(CONFIG_SOC_AU1100)
{ AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
{ AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
/*{ AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0},*/
{ AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
{ AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8fd203d..ec81d4b 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -15,6 +15,78 @@ #include <linux/resource.h>
#include <asm/mach-au1x00/au1xxx.h>
+#if defined(CONFIG_MIPS_AU1X00_ENET) || defined(CONFIG_MIPS_AU1X00_ENET_MODULE)
+/* Ethernet controllers */
+static struct resource au1xxx_eth0_resources[] = {
+ [0] = {
+ .name = "eth-base",
+ .start = ETH0_BASE,
+ .end = ETH0_BASE + MAC_IOSIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "eth-mac",
+ .start = MAC0_ENABLE,
+ .end = MAC0_ENABLE + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "eth-irq",
+#if defined(CONFIG_SOC_AU1550)
+ .start = AU1550_MAC0_DMA_INT,
+ .end = AU1550_MAC0_DMA_INT,
+#else
+ .start = AU1000_MAC0_DMA_INT,
+ .end = AU1000_MAC0_DMA_INT,
+#endif
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device au1xxx_eth0_device = {
+ .name = "au1000_eth",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(au1xxx_eth0_resources),
+ .resource = au1xxx_eth0_resources,
+};
+
+#if defined(CONFIG_SOC_AU1000) || \
+ defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+static struct resource au1xxx_eth1_resources[] = {
+ [0] = {
+ .name = "eth-base",
+ .start = ETH1_BASE,
+ .end = ETH1_BASE + MAC_IOSIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "eth-mac",
+ .start = MAC1_ENABLE,
+ .end = MAC1_ENABLE + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "eth-irq",
+#if defined(CONFIG_SOC_AU1550)
+ .start = AU1550_MAC1_DMA_INT,
+ .end = AU1550_MAC1_DMA_INT,
+#else
+ .start = AU1000_MAC1_DMA_INT,
+ .end = AU1000_MAC1_DMA_INT,
+#endif
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device au1xxx_eth1_device = {
+ .name = "au1000_eth",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(au1xxx_eth1_resources),
+ .resource = au1xxx_eth1_resources,
+};
+#endif
+#endif
+
/* OHCI (USB full speed host controller) */
static struct resource au1xxx_usb_ohci_resources[] = {
[0] = {
@@ -270,7 +367,14 @@ static struct platform_device smc91x_dev
#endif
static struct platform_device *au1xxx_platform_devices[] __initdata = {
+#if defined(CONFIG_MIPS_AU1X00_ENET) || defined(CONFIG_MIPS_AU1X00_ENET_MODULE)
+ &au1xxx_eth0_device,
+#if defined(CONFIG_SOC_AU1000) || \
+ defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+ &au1xxx_eth1_device,
+#endif
+#endif
&au1xxx_usb_ohci_device,
&au1x00_pcmcia_device,
#ifdef CONFIG_FB_AU1100
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 27d465f..47c624b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -453,13 +453,13 @@ config MIPS_GT96100ETH
Say Y here to support the Ethernet subsystem on your GT96100 card.
config MIPS_AU1X00_ENET
- bool "MIPS AU1000 Ethernet support"
+ tristate "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && SOC_AU1X00
select PHYLIB
select CRC32
help
If you have an Alchemy Semi AU1X00 based system
- say Y. Otherwise, say N.
+ say Y or M. Otherwise, say N.
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 55f6e3f..004452f 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -11,6 +11,8 @@
* ioctls (SIOCGMIIPHY)
* Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
* converted to use linux-2.6.x's PHY framework
+ * Copyright 2006 Rodolfo Giometti <giometti@linux.it>
+ * power management, driver registration and module support.
*
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
@@ -61,6 +63,7 @@ #include <asm/irq.h>
#include <asm/io.h>
#include <asm/processor.h>
+#include <linux/platform_device.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/cpu.h>
#include "au1000_eth.h"
@@ -83,7 +86,8 @@ MODULE_LICENSE("GPL");
// prototypes
static void hard_stop(struct net_device *);
static void enable_rx_tx(struct net_device *dev);
-static struct net_device * au1000_probe(int port_num);
+static int au1000_lowlevel_probe(struct net_device *ndev, void *ioaddr, void *macen_addr, int port_num, int skip_prom);
+static void au1000_lowlevel_remove(struct net_device *ndev);
static int au1000_init(struct net_device *);
static int au1000_open(struct net_device *);
static int au1000_close(struct net_device *);
@@ -520,59 +524,6 @@ setup_hw_rings(struct au1000_private *au
}
}
-static struct {
- u32 base_addr;
- u32 macen_addr;
- int irq;
- struct net_device *dev;
-} iflist[2] = {
-#ifdef CONFIG_SOC_AU1000
- {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
- {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1100
- {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1500
- {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
- {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1550
- {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
- {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
-#endif
-};
-
-static int num_ifs;
-
-/*
- * Setup the base address and interupt of the Au1xxx ethernet macs
- * based on cpu type and whether the interface is enabled in sys_pinfunc
- * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
- */
-static int __init au1000_init_module(void)
-{
- int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
- struct net_device *dev;
- int i, found_one = 0;
-
- num_ifs = NUM_ETH_INTERFACES - ni;
-
- for(i = 0; i < num_ifs; i++) {
- dev = au1000_probe(i);
- iflist[i].dev = dev;
- if (dev)
- found_one++;
- }
- if (!found_one)
- return -ENODEV;
- return 0;
-}
-
-/*
- * ethtool operations
- */
-
static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct au1000_private *aup = (struct au1000_private *)dev->priv;
@@ -615,48 +566,14 @@ static struct ethtool_ops au1000_ethtool
.get_link = ethtool_op_get_link,
};
-static struct net_device * au1000_probe(int port_num)
+static int
+au1000_lowlevel_probe(struct net_device *ndev, void *ioaddr, void *macen_addr, int port_num, int skip_prom)
{
- static unsigned version_printed = 0;
- struct au1000_private *aup = NULL;
- struct net_device *dev = NULL;
+ struct au1000_private *aup = ndev->priv;
db_dest_t *pDB, *pDBfree;
char *pmac, *argptr;
char ethaddr[6];
- int irq, i, err;
- u32 base, macen;
-
- if (port_num >= NUM_ETH_INTERFACES)
- return NULL;
-
- base = CPHYSADDR(iflist[port_num].base_addr );
- macen = CPHYSADDR(iflist[port_num].macen_addr);
- irq = iflist[port_num].irq;
-
- if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
- !request_mem_region(macen, 4, "Au1x00 ENET"))
- return NULL;
-
- if (version_printed++ == 0)
- printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
-
- dev = alloc_etherdev(sizeof(struct au1000_private));
- if (!dev) {
- printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
- return NULL;
- }
-
- if ((err = register_netdev(dev)) != 0) {
- printk(KERN_ERR "%s: Cannot register net device, error %d\n",
- DRV_NAME, err);
- free_netdev(dev);
- return NULL;
- }
-
- printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
- dev->name, base, irq);
-
- aup = dev->priv;
+ int i, ret;
/* Allocate the data buffers */
/* Snooping works fine with eth on all au1xxx */
@@ -664,79 +581,61 @@ static struct net_device * au1000_probe(
(NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0);
if (!aup->vaddr) {
- free_netdev(dev);
- release_mem_region( base, MAC_IOSIZE);
- release_mem_region(macen, 4);
- return NULL;
+ printk(KERN_ERR "%s: cannot dma_alloc_noncoherent\n",
+ ndev->name);
+ ret = -ENOMEM;
+ goto out;
}
/* aup->mac is the base address of the MAC's registers */
- aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
-
+ aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
/* Setup some variables for quick register address access */
- aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
- aup->mac_id = port_num;
- au_macs[port_num] = aup;
-
- if (port_num == 0) {
- /* Check the environment variables first */
- if (get_ethernet_addr(ethaddr) == 0)
- memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
- else {
- /* Check command line */
- argptr = prom_getcmdline();
- if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
- printk(KERN_INFO "%s: No MAC address found\n",
- dev->name);
- /* Use the hard coded MAC addresses */
- else {
- str2eaddr(ethaddr, pmac + strlen("ethaddr="));
- memcpy(au1000_mac_addr, ethaddr,
- sizeof(au1000_mac_addr));
+ if (port_num == 0)
+ {
+ if (!skip_prom) {
+ /* check env variables first */
+ if (!get_ethernet_addr(ethaddr)) {
+ memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
+ } else {
+ /* Check command line */
+ argptr = prom_getcmdline();
+ if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
+ printk(KERN_INFO "%s: No mac address found\n",
+ ndev->name);
+ /* use the hard coded mac addresses */
+ } else {
+ str2eaddr(ethaddr, pmac + strlen("ethaddr="));
+ memcpy(au1000_mac_addr, ethaddr,
+ sizeof(au1000_mac_addr));
+ }
}
}
+ aup->enable = (volatile u32 *) ((unsigned long) macen_addr);
+ memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
- } else if (port_num == 1)
- setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
+ aup->mac_id = 0;
+ au_macs[0] = aup;
+ }
+ else
+ if (port_num == 1)
+ {
+ aup->enable = (volatile u32 *) ((unsigned long) macen_addr);
+ memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+ ndev->dev_addr[5] += 0x01;
- /*
- * Assign to the Ethernet ports two consecutive MAC addresses
- * to match those that are printed on their stickers
- */
- memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
- dev->dev_addr[5] += port_num;
+ setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
+ aup->mac_id = 1;
+ au_macs[1] = aup;
+ }
+ else
+ {
+ printk(KERN_ERR "%s: bad ioaddr\n", ndev->name);
+ }
*aup->enable = 0;
aup->mac_enabled = 0;
- aup->mii_bus.priv = dev;
- aup->mii_bus.read = mdiobus_read;
- aup->mii_bus.write = mdiobus_write;
- aup->mii_bus.reset = mdiobus_reset;
- aup->mii_bus.name = "au1000_eth_mii";
- aup->mii_bus.id = aup->mac_id;
- aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
- for(i = 0; i < PHY_MAX_ADDR; ++i)
- aup->mii_bus.irq[i] = PHY_POLL;
-
- /* if known, set corresponding PHY IRQs */
-#if defined(AU1XXX_PHY_STATIC_CONFIG)
-# if defined(AU1XXX_PHY0_IRQ)
- if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
- aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
-# endif
-# if defined(AU1XXX_PHY1_IRQ)
- if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
- aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
-# endif
-#endif
- mdiobus_register(&aup->mii_bus);
-
- if (mii_probe(dev) != 0) {
- goto err_out;
- }
-
pDBfree = NULL;
/* setup the data buffer descriptors and attach a buffer to each one */
pDB = aup->db;
@@ -752,6 +651,7 @@ #endif
for (i = 0; i < NUM_RX_DMA; i++) {
pDB = GetFreeDB(aup);
if (!pDB) {
+ ret = -ENOMEM;
goto err_out;
}
aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
@@ -760,6 +660,7 @@ #endif
for (i = 0; i < NUM_TX_DMA; i++) {
pDB = GetFreeDB(aup);
if (!pDB) {
+ ret = -ENOMEM;
goto err_out;
}
aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
@@ -767,31 +668,23 @@ #endif
aup->tx_db_inuse[i] = pDB;
}
- spin_lock_init(&aup->lock);
- dev->base_addr = base;
- dev->irq = irq;
- dev->open = au1000_open;
- dev->hard_start_xmit = au1000_tx;
- dev->stop = au1000_close;
- dev->get_stats = au1000_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &au1000_ioctl;
- SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
- dev->tx_timeout = au1000_tx_timeout;
- dev->watchdog_timeo = ETH_TX_TIMEOUT;
+ return 0;
- /*
- * The boot code uses the ethernet controller, so reset it to start
- * fresh. au1000_init() expects that the device is in reset state.
- */
- reset_mac(dev);
+err_out :
+ au1000_lowlevel_remove(ndev);
+out :
+ return ret;
+}
- return dev;
+static void
+au1000_lowlevel_remove(struct net_device *ndev)
+{
+ struct au1000_private *aup = ndev->priv;
+ int i;
-err_out:
/* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.*/
- reset_mac(dev);
+ reset_mac(ndev);
for (i = 0; i < NUM_RX_DMA; i++) {
if (aup->rx_db_inuse[i])
@@ -801,13 +694,10 @@ err_out:
if (aup->tx_db_inuse[i])
ReleaseDB(aup, aup->tx_db_inuse[i]);
}
- dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
- (void *)aup->vaddr, aup->dma_addr);
- unregister_netdev(dev);
- free_netdev(dev);
- release_mem_region( base, MAC_IOSIZE);
- release_mem_region(macen, 4);
- return NULL;
+ dma_free_noncoherent(NULL,
+ MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+ (void *)aup->vaddr,
+ aup->dma_addr);
}
/*
@@ -1009,38 +899,15 @@ static int au1000_close(struct net_devic
return 0;
}
-static void __exit au1000_cleanup_module(void)
-{
- int i, j;
- struct net_device *dev;
- struct au1000_private *aup;
-
- for (i = 0; i < num_ifs; i++) {
- dev = iflist[i].dev;
- if (dev) {
- aup = (struct au1000_private *) dev->priv;
- unregister_netdev(dev);
- for (j = 0; j < NUM_RX_DMA; j++)
- if (aup->rx_db_inuse[j])
- ReleaseDB(aup, aup->rx_db_inuse[j]);
- for (j = 0; j < NUM_TX_DMA; j++)
- if (aup->tx_db_inuse[j])
- ReleaseDB(aup, aup->tx_db_inuse[j]);
- dma_free_noncoherent(NULL, MAX_BUF_SIZE *
- (NUM_TX_BUFFS + NUM_RX_BUFFS),
- (void *)aup->vaddr, aup->dma_addr);
- release_mem_region(dev->base_addr, MAC_IOSIZE);
- release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
- free_netdev(dev);
- }
- }
-}
-
-static void update_tx_stats(struct net_device *dev, u32 status)
+static inline void
+update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
struct net_device_stats *ps = &aup->stats;
+ ps->tx_packets++;
+ ps->tx_bytes += pkt_len;
+
if (status & TX_FRAME_ABORTED) {
if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
@@ -1073,7 +940,7 @@ static void au1000_tx_ack(struct net_dev
ptxd = aup->tx_dma_ring[aup->tx_tail];
while (ptxd->buff_stat & TX_T_DONE) {
- update_tx_stats(dev, ptxd->status);
+ update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
ptxd->buff_stat &= ~TX_T_DONE;
ptxd->len = 0;
au_sync();
@@ -1095,7 +962,6 @@ static void au1000_tx_ack(struct net_dev
static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
- struct net_device_stats *ps = &aup->stats;
volatile tx_dma_t *ptxd;
u32 buff_stat;
db_dest_t *pDB;
@@ -1115,7 +981,7 @@ static int au1000_tx(struct sk_buff *skb
return 1;
}
else if (buff_stat & TX_T_DONE) {
- update_tx_stats(dev, ptxd->status);
+ update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
ptxd->len = 0;
}
@@ -1135,9 +1001,6 @@ static int au1000_tx(struct sk_buff *skb
else
ptxd->len = skb->len;
- ps->tx_packets++;
- ps->tx_bytes += ptxd->len;
-
ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
au_sync();
dev_kfree_skb(skb);
@@ -1340,5 +1203,251 @@ static struct net_device_stats *au1000_g
return 0;
}
-module_init(au1000_init_module);
-module_exit(au1000_cleanup_module);
+/*
+ * Setup the base address and interupt of the Au1xxx ethernet macs
+ * based on cpu type and whether the interface is enabled in sys_pinfunc
+ * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
+ */
+static int au1000_drv_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev;
+ struct au1000_private *aup;
+ struct resource *res;
+ static unsigned version_printed = 0;
+ u32 base_addr_phys;
+ void *base_addr, *macen_addr;
+ int i, irq, ret;
+
+ if (pdev->id == 1 && (au_readl(SYS_PINFUNC) & SYS_PF_NI2) != 0)
+ return -ENODEV;
+
+ /* Get the resource info */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-base");
+ if (!res) {
+ ret = -ENODEV;
+ goto out;
+ }
+ base_addr_phys = res->start;
+ base_addr = ioremap(res->start, res->end - res->start);
+ if (!base_addr) {
+ printk (KERN_ERR "%s: unable to remap address %lx\n",
+ DRV_NAME, (long unsigned int) res->start);
+ ret = -EINVAL;
+ goto out;
+ }
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-mac");
+ if (!res) {
+ ret = -ENODEV;
+ goto out_release_io;
+ }
+ macen_addr = ioremap(res->start, res->end - res->start);
+ if (!macen_addr) {
+ printk (KERN_ERR "%s: unable to remap address %lx\n",
+ DRV_NAME, (long unsigned int) res->start);
+ ret = -ENOMEM;
+ goto out_release_io;
+ }
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eth-irq");
+ if (!res) {
+ ret = -ENODEV;
+ goto out_release_iomac;
+ }
+ irq = res->start;
+
+ if (version_printed++ == 0)
+ printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+
+ ndev = alloc_etherdev(sizeof(struct au1000_private));
+ if (!ndev) {
+ printk (KERN_ERR "%s: alloc etherdev failed\n", DRV_NAME);
+ ret = -ENOMEM;
+ goto out_release_iomac;
+ }
+ SET_MODULE_OWNER(ndev);
+ SET_NETDEV_DEV(ndev, dev);
+
+ /* Force the device name to a know state... */
+ sprintf(ndev->name, "au1xxx_eth(%d)", pdev->id);
+ ret = au1000_lowlevel_probe(ndev, base_addr, macen_addr, pdev->id, 0);
+ if (ret < 0) {
+ printk (KERN_ERR "%s: low level probe failed\n", DRV_NAME);
+ goto out_free_netdev;
+ }
+
+ aup = ndev->priv;
+
+ /* Register the MII bus */
+ aup->mii_bus.priv = ndev;
+ aup->mii_bus.read = mdiobus_read;
+ aup->mii_bus.write = mdiobus_write;
+ aup->mii_bus.reset = mdiobus_reset;
+ aup->mii_bus.name = "au1000_eth_mii";
+ aup->mii_bus.id = aup->mac_id;
+ aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for(i = 0; i < PHY_MAX_ADDR; ++i)
+ aup->mii_bus.irq[i] = PHY_POLL;
+
+ /* if known, set corresponding PHY IRQs */
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+# if defined(AU1XXX_PHY0_IRQ)
+ if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
+ aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+# endif
+# if defined(AU1XXX_PHY1_IRQ)
+ if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
+ aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+# endif
+#endif
+ mdiobus_register(&aup->mii_bus);
+
+ if (mii_probe(ndev) != 0) {
+ ret = -EBUSY;
+ goto out_lowlevel_remove;
+ }
+
+ /* Came back to a more standard name before registering the
+ * net device... */
+ strcpy(ndev->name, "eth%d");
+
+ /* Setup base info */
+ spin_lock_init(&aup->lock);
+ ndev->base_addr = base_addr_phys;
+ ndev->irq = irq;
+ ndev->open = au1000_open;
+ ndev->hard_start_xmit = au1000_tx;
+ ndev->stop = au1000_close;
+ ndev->get_stats = au1000_get_stats;
+ ndev->set_multicast_list = &set_rx_mode;
+ ndev->do_ioctl = &au1000_ioctl;
+ SET_ETHTOOL_OPS(ndev, &au1000_ethtool_ops);
+ ndev->tx_timeout = au1000_tx_timeout;
+ ndev->watchdog_timeo = ETH_TX_TIMEOUT;
+
+ /*
+ * The boot code uses the ethernet controller, so reset it to start
+ * fresh. au1000_init() expects that the device is in reset state.
+ */
+ reset_mac(ndev);
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ printk(KERN_ERR "%s: cannot register net device err %d\n",
+ DRV_NAME, ret);
+ goto out_mdiobus_unregister;
+ }
+
+ printk("%s: Au1x Ethernet found at 0x%x, irq %d\n",
+ ndev->name, base_addr_phys, irq);
+
+ dev_set_drvdata(dev, ndev);
+
+ return 0;
+
+out_mdiobus_unregister :
+ mdiobus_unregister(&aup->mii_bus);
+out_lowlevel_remove :
+ au1000_lowlevel_remove(ndev);
+out_free_netdev :
+ free_netdev(ndev);
+out_release_iomac :
+ iounmap(macen_addr);
+out_release_io :
+ iounmap(base_addr);
+out :
+ printk("%s: not found (%d).\n", DRV_NAME, ret);
+
+ return ret;
+}
+
+static int au1000_drv_remove(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct au1000_private *aup = (struct au1000_private *) ndev->priv;
+
+ dev_set_drvdata(dev, NULL);
+
+ unregister_netdev(ndev);
+ mdiobus_unregister(&aup->mii_bus);
+ au1000_lowlevel_remove(ndev);
+ free_netdev(ndev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1000_drv_suspend(struct device *dev, pm_message_t state)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct au1000_private *aup;
+ struct phy_device *phydev;
+
+ if (!ndev)
+ return 0;
+
+ aup = (struct au1000_private *) ndev->priv;
+ phydev = aup->phy_dev;
+
+ if (netif_running(ndev))
+ netif_device_detach(ndev);
+
+ au1000_lowlevel_remove(ndev);
+
+ return 0;
+}
+
+static int au1000_drv_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct au1000_private *aup;
+ struct phy_device *phydev;
+ int ret;
+
+ if (!ndev)
+ return 0;
+
+ aup = (struct au1000_private *) ndev->priv;
+ phydev = aup->phy_dev;
+
+ ret = au1000_lowlevel_probe(ndev, (void *) aup->mac, (void *) aup->enable, aup->mac_id, ~0);
+ if (ret < 0) {
+ printk (KERN_ERR "%s: low level probe failed\n", DRV_NAME);
+ return ret;
+ }
+
+ /* au1000_init() expects that the device is in reset state.
+ */
+ aup->mii_bus.reset(&aup->mii_bus);
+ reset_mac(ndev);
+ au1000_init(ndev);
+
+ if (netif_running(ndev))
+ netif_device_attach(ndev);
+
+ return 0;
+}
+#endif
+
+static struct device_driver au1000_driver = {
+ .name = DRV_NAME,
+ .bus = &platform_bus_type,
+ .probe = au1000_drv_probe,
+ .remove = au1000_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = au1000_drv_suspend,
+ .resume = au1000_drv_resume,
+#endif
+};
+
+static int __init au1000_eth_init(void)
+{
+ return driver_register(&au1000_driver);
+}
+
+static void __exit au1000_eth_cleanup(void)
+{
+ driver_unregister(&au1000_driver);
+}
+
+module_init(au1000_eth_init);
+module_exit(au1000_eth_cleanup);
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index 41c2f84..056ecdc 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -27,7 +27,6 @@
*/
-#define MAC_IOSIZE 0x10000
#define NUM_RX_DMA 4 /* Au1x00 has 4 rx hardware descriptors */
#define NUM_TX_DMA 4 /* Au1x00 has 4 tx hardware descriptors */
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 582acd8..5d58ce6 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -605,11 +605,11 @@ #define UART3_ADDR 0xB140
#define USB_OHCI_BASE 0x10100000 // phys addr for ioremap
#define USB_HOST_CONFIG 0xB017fffc
-#define AU1000_ETH0_BASE 0xB0500000
-#define AU1000_ETH1_BASE 0xB0510000
-#define AU1000_MAC0_ENABLE 0xB0520000
-#define AU1000_MAC1_ENABLE 0xB0520004
-#define NUM_ETH_INTERFACES 2
+#define ETH0_BASE 0x10500000
+#define ETH1_BASE 0x10510000
+#define MAC0_ENABLE 0x10520000
+#define MAC1_ENABLE 0x10520004
+#define NUM_ETH_INTERFACES 2
#endif /* CONFIG_SOC_AU1000 */
/* Au1500 */
@@ -634,8 +634,8 @@ #define AU1000_USB_DEV_REQ_INT 24
#define AU1000_USB_DEV_SUS_INT 25
#define AU1000_USB_HOST_INT 26
#define AU1000_ACSYNC_INT 27
-#define AU1500_MAC0_DMA_INT 28
-#define AU1500_MAC1_DMA_INT 29
+#define AU1000_MAC0_DMA_INT 28
+#define AU1000_MAC1_DMA_INT 29
#define AU1000_AC97C_INT 31
#define AU1000_GPIO_0 32
#define AU1000_GPIO_1 33
@@ -682,11 +682,11 @@ #define UART3_ADDR 0xB140
#define USB_OHCI_BASE 0x10100000 // phys addr for ioremap
#define USB_HOST_CONFIG 0xB017fffc
-#define AU1500_ETH0_BASE 0xB1500000
-#define AU1500_ETH1_BASE 0xB1510000
-#define AU1500_MAC0_ENABLE 0xB1520000
-#define AU1500_MAC1_ENABLE 0xB1520004
-#define NUM_ETH_INTERFACES 2
+#define ETH0_BASE 0x11500000
+#define ETH1_BASE 0x11510000
+#define MAC0_ENABLE 0x11520000
+#define MAC1_ENABLE 0x11520004
+#define NUM_ETH_INTERFACES 2
#endif /* CONFIG_SOC_AU1500 */
/* Au1100 */
@@ -712,7 +712,7 @@ #define AU1000_USB_DEV_REQ_INT 24
#define AU1000_USB_DEV_SUS_INT 25
#define AU1000_USB_HOST_INT 26
#define AU1000_ACSYNC_INT 27
-#define AU1100_MAC0_DMA_INT 28
+#define AU1000_MAC0_DMA_INT 28
#define AU1100_GPIO_208_215 29
#define AU1100_LCD_INT 30
#define AU1000_AC97C_INT 31
@@ -756,9 +756,9 @@ #define UART3_ADDR 0xB140
#define USB_OHCI_BASE 0x10100000 // phys addr for ioremap
#define USB_HOST_CONFIG 0xB017fffc
-#define AU1100_ETH0_BASE 0xB0500000
-#define AU1100_MAC0_ENABLE 0xB0520000
-#define NUM_ETH_INTERFACES 1
+#define ETH0_BASE 0x10500000
+#define MAC0_ENABLE 0x10520000
+#define NUM_ETH_INTERFACES 1
#endif /* CONFIG_SOC_AU1100 */
#ifdef CONFIG_SOC_AU1550
@@ -791,8 +791,8 @@ #define AU1550_USB_HOST_INT 26
#define AU1000_USB_DEV_REQ_INT AU1550_USB_DEV_REQ_INT
#define AU1000_USB_DEV_SUS_INT AU1550_USB_DEV_SUS_INT
#define AU1000_USB_HOST_INT AU1550_USB_HOST_INT
-#define AU1550_MAC0_DMA_INT 27
-#define AU1550_MAC1_DMA_INT 28
+#define AU1000_MAC0_DMA_INT 27
+#define AU1000_MAC1_DMA_INT 28
#define AU1000_GPIO_0 32
#define AU1000_GPIO_1 33
#define AU1000_GPIO_2 34
@@ -840,11 +840,11 @@ #define USB_OHCI_BASE 0x1402
#define USB_OHCI_LEN 0x00060000
#define USB_HOST_CONFIG 0xB4027ffc
-#define AU1550_ETH0_BASE 0xB0500000
-#define AU1550_ETH1_BASE 0xB0510000
-#define AU1550_MAC0_ENABLE 0xB0520000
-#define AU1550_MAC1_ENABLE 0xB0520004
-#define NUM_ETH_INTERFACES 2
+#define ETH0_BASE 0x10500000
+#define ETH1_BASE 0x10510000
+#define MAC0_ENABLE 0x10520000
+#define MAC1_ENABLE 0x10520004
+#define NUM_ETH_INTERFACES 2
#endif /* CONFIG_SOC_AU1550 */
#ifdef CONFIG_SOC_AU1200
@@ -1069,6 +1069,7 @@ #define USBD_ENABLE 0xB020
#endif /* !CONFIG_SOC_AU1200 */
/* Ethernet Controllers */
+#define MAC_IOSIZE 0x10000
/* 4 byte offsets from AU1000_ETH_BASE */
#define MAC_CONTROL 0x0
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2006-07-19 8:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20060713163200.GA7186@gundam.enneenne.com>
[not found] ` <20060714.103521.25910483.nemoto@toshiba-tops.co.jp>
[not found] ` <20060714075441.GE7186@gundam.enneenne.com>
2006-07-19 8:29 ` [PATCH] au1000_eth.c power management and driver registration support Rodolfo Giometti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).