All of lore.kernel.org
 help / color / mirror / Atom feed
* Problems after merge to 2.6.18-rc1
@ 2006-07-13 16:32 Rodolfo Giometti
  2006-07-13 19:19 ` Daniel Mack
  2006-07-14  1:35 ` Atsushi Nemoto
  0 siblings, 2 replies; 8+ messages in thread
From: Rodolfo Giometti @ 2006-07-13 16:32 UTC (permalink / raw)
  To: linux-mips

Hello,

I just finished a (big) merge with linux-mips 2.6.18-rc1 and
my tree and at boot I get:

   Linux version 2.6.18-rc1-g2636fd13-dirty (giometti@gundam) (gcc version 3.4.3) #165 Thu Jul 13 18:13:26 CEST 2006
   CPU revision is: 02030204
   Board WWPC1000 version 1.0
   WWPC-setup: uC=off 
   (PRId 02030204) @ 396MHZ
   BCLK switching enabled!
   Determined physical RAM map:
    memory: 04000000 @ 00000000 (usable)
   Early serial console at AU 0x11100000 (options '115200')
   Determined physical RAM map:
    memory: 04000000 @ 00000000 (usable)
   Built 1 zonelists.  Total pages: 16384
   Kernel command line: wwpc=uc-off console=uart,au,0x11100000,115200 root=/dev/nfs rw nfsroot=192.168.32.254:/homemipsel/distro/debian ip=192.168.32.24:192.168.32.254::255.255.255.0:000:eth0:off
   Primary instruction cache 16kB, physically tagged, 4-way, linesize 32 bytes.
   Primary data cache 16kB, 4-way, linesize 32 bytes.
   Synthesized TLB refill handler (17 instructions).
   Synthesized TLB load handler fastpath (34 instructions).
   Synthesized TLB store handler fastpath (34 instructions).
   Synthesized TLB modify handler fastpath (33 instructions).
   PID hash table entries: 1024 (order: 10, 4096 bytes)
   calculating r4koff... 00182b80(1584000)
   CPU frequency 396.00 MHz
   Console: colour dummy device 80x25
   Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
   Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
   Bad page state in process 'swapper'
   page:810092a0 flags:0x00000000 mapping:00000000 mapcount:1 count:0
   Trying to fix it up, but a reboot is needed
   Backtrace:
   Call Trace:
    [<8015d91c>] bad_page+0x6c/0xac
    [<8015e4c0>] free_hot_cold_page+0x190/0x1ec
    [<8046099c>] free_all_bootmem_core+0x1ec/0x228
    [<80457110>] mem_init+0x4c/0x218
    [<80462a50>] inode_init_early+0x68/0xbc
    [<804657d8>] console_init+0x48/0x68
    [<80450824>] start_kernel+0x208/0x400
    [<8045081c>] start_kernel+0x200/0x400
    [<80450134>] unknown_bootoption+0x0/0x310

   Bad page state in process 'swapper'
   page:810092c0 flags:0x00000000 mapping:00000000 mapcount:1 count:0
   Trying to fix it up, but a reboot is needed
   ...

Suggestions? :)

Thanks,

Rodolfo

-- 

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-13 16:32 Problems after merge to 2.6.18-rc1 Rodolfo Giometti
@ 2006-07-13 19:19 ` Daniel Mack
  2006-07-14  1:35 ` Atsushi Nemoto
  1 sibling, 0 replies; 8+ messages in thread
From: Daniel Mack @ 2006-07-13 19:19 UTC (permalink / raw)
  To: Rodolfo Giometti; +Cc: linux-mips

Hi,

On Jul 13, 2006, at 6:32 PM, Rodolfo Giometti wrote:

>    Call Trace:
>     [<8015d91c>] bad_page+0x6c/0xac
>     [<8015e4c0>] free_hot_cold_page+0x190/0x1ec
>     [<8046099c>] free_all_bootmem_core+0x1ec/0x228
>     [<80457110>] mem_init+0x4c/0x218
>     [<80462a50>] inode_init_early+0x68/0xbc
>     [<804657d8>] console_init+0x48/0x68
>     [<80450824>] start_kernel+0x208/0x400
>     [<8045081c>] start_kernel+0x200/0x400
>     [<80450134>] unknown_bootoption+0x0/0x310

Well, what might 'unknown_bootoption' be trying to tell you?
What boot options did you set?

Daniel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-13 16:32 Problems after merge to 2.6.18-rc1 Rodolfo Giometti
  2006-07-13 19:19 ` Daniel Mack
@ 2006-07-14  1:35 ` Atsushi Nemoto
  2006-07-14  7:54   ` Rodolfo Giometti
  1 sibling, 1 reply; 8+ messages in thread
From: Atsushi Nemoto @ 2006-07-14  1:35 UTC (permalink / raw)
  To: giometti; +Cc: linux-mips

On Thu, 13 Jul 2006 18:32:00 +0200, Rodolfo Giometti <giometti@linux.it> wrote:
> I just finished a (big) merge with linux-mips 2.6.18-rc1 and
> my tree and at boot I get:
> 
>    Linux version 2.6.18-rc1-g2636fd13-dirty (giometti@gundam) (gcc version 3.4.3) #165 Thu Jul 13 18:13:26 CEST 2006
>    CPU revision is: 02030204
>    Board WWPC1000 version 1.0
>    WWPC-setup: uC=off 
>    (PRId 02030204) @ 396MHZ
>    BCLK switching enabled!
>    Determined physical RAM map:
>     memory: 04000000 @ 00000000 (usable)
>    Early serial console at AU 0x11100000 (options '115200')
>    Determined physical RAM map:
>     memory: 04000000 @ 00000000 (usable)
>    Built 1 zonelists.  Total pages: 16384

Two "Determined physycal RAM map:" line here.  If both were printed in
parse_cmdline_early() (i.e. parse_cmdline_early was called twice),
something is seriously broken.

---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-14  1:35 ` Atsushi Nemoto
@ 2006-07-14  7:54   ` Rodolfo Giometti
  2006-07-14 10:48     ` Rodolfo Giometti
                       ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Rodolfo Giometti @ 2006-07-14  7:54 UTC (permalink / raw)
  To: Atsushi Nemoto; +Cc: linux-mips

[-- Attachment #1: Type: text/plain, Size: 3351 bytes --]

On Fri, Jul 14, 2006 at 10:35:21AM +0900, Atsushi Nemoto wrote:
> 
> Two "Determined physycal RAM map:" line here.  If both were printed in
> parse_cmdline_early() (i.e. parse_cmdline_early was called twice),
> something is seriously broken.

Yes, you was right. I fixed it! :)

However now I have another (strange) problem.

Attached you can find my patch to add power managament to the new
version of file "drivers/net/au1000_eth.c" that implements the
PHY-layer support.

Please, note the hack after the function mii_probe() called by
au1000_lowlevel_probe().

Kernel messages during suspend are:

   hostname:~# apm --suspend
   Stopping tasks: ===============================|
   au1xxx_pm_prepare: state = 3
    usbdev1.1_ep81: PM: suspend 0->2, parent 1-0:1.0 already 1
   warning! Serial console ttyS0 is not disabled in debug kernel mode
   au1xxx_pm_enter: state = 3
   au_sleep: reason -3 force 0 wakeup 100 ticks 3000
   au_sleep: Zzz...
   au_sleep: Yep!
   kobject_add failed for 0:1f with -EEXIST, don't try to register things with the same name in the same directory.
   Call Trace:
    [<80252ca8>] kobject_add+0x17c/0x1e0
    [<80252b98>] kobject_add+0x6c/0x1e0
    [<80292008>] device_add+0xc0/0x464
    [<80291ff4>] device_add+0xac/0x464
    [<802a2e64>] mdiobus_register+0x134/0x198
    [<802a3ac0>] au1000_lowlevel_probe+0x104/0x4b4
    [<802a58a4>] au1000_drv_resume+0x3c/0xc8
    [<80138978>] process_timeout+0x0/0x8
    [<80298610>] platform_resume+0x34/0x40
    [<8029bf7c>] resume_device+0x19c/0x200
    [<802528e4>] kobject_get+0x20/0x34
    [<8029391c>] __sysdev_resume+0xf0/0xf8
    [<80291da4>] get_device+0x20/0x34
    [<8029c1c4>] dpm_resume+0x1e4/0x3c0
    [<8029c3fc>] device_resume+0x5c/0x174
    [<80153848>] enter_state+0x290/0x314
    [<80153840>] enter_state+0x288/0x314
    [<8010e824>] apm_suspend+0x1c/0xa0
    [<80219750>] nfs_getattr+0x88/0xf8
    [<80219708>] nfs_getattr+0x40/0xf8
    [<8010eca8>] apm_ioctl+0x198/0x22c
    [<80110e84>] do_page_fault+0x364/0x3d0
    [<80110c24>] do_page_fault+0x104/0x3d0
    [<801a0d24>] do_ioctl+0x54/0x90
    [<801a0f6c>] vfs_ioctl+0x20c/0x394
    [<801b7950>] sync_inodes+0x20/0x54
    [<801a1144>] sys_ioctl+0x50/0x9c
    [<8010f66c>] stack_done+0x20/0x40
    [<8010f66c>] stack_done+0x20/0x40

   phy 31 failed to register
   au1000_eth_mii: probed
   eth0: 0:1f already attached
   eth0: Could not attach to PHY
   usb usb1: root hub lost power or was reset
   Restarting tasks... done
   au1xxx_pm_finish: state = 3
   hostname:~#

The first strange thing is that this time the kernel messages stop
after "au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..."
as before the merge! Maybe something as changed in serial console
magement?

The second strange thing is that _only_ calling the mii_probe()
the resume works correctly, otherwise the CPU loops forever
calling the au1000_lowlevel_probe() without showing the printk()
messages through the serial console. =:-o

Suggestions?

Ciao,

Rodolfo

-- 

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 #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-14  7:54   ` Rodolfo Giometti
@ 2006-07-14 10:48     ` Rodolfo Giometti
  2006-07-18 17:46     ` Rodolfo Giometti
  2006-07-19  8:29     ` [PATCH] au1000_eth.c power management and driver registration support Rodolfo Giometti
  2 siblings, 0 replies; 8+ messages in thread
From: Rodolfo Giometti @ 2006-07-14 10:48 UTC (permalink / raw)
  To: linux-mips


[-- Attachment #1.1: Type: text/plain, Size: 446 bytes --]

On Fri, Jul 14, 2006 at 09:54:41AM +0200, Rodolfo Giometti wrote:
> 
> Attached you can find my patch to add power managament to the new

Sorry... :)

Ciao,

Rodolfo

-- 

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.c --]
[-- Type: text/x-csrc, Size: 18236 bytes --]

diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 55f6e3f..ff536c4 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,53 +581,62 @@ 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.priv = ndev;
 	aup->mii_bus.read = mdiobus_read;
 	aup->mii_bus.write = mdiobus_write;
 	aup->mii_bus.reset = mdiobus_reset;
@@ -733,8 +659,18 @@ # endif
 #endif
 	mdiobus_register(&aup->mii_bus);
 
-	if (mii_probe(dev) != 0) {
-		goto err_out;
+	if (mii_probe(ndev) != 0) {
+		/* Hack, hack, hack!
+		 * This is needed during resume... you'll get a "Call Trace"
+		 * error message, but at least the wake up works...
+		 * Feel free to post a patch. :)
+		 *
+		 * Rodolfo Giometti
+		 * */
+		if (!skip_prom) {
+			ret = -EBUSY;
+			goto err_out;
+		}
 	}
 
 	pDBfree = NULL;
@@ -752,6 +688,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 +697,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 +705,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 +731,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 +936,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 +977,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 +999,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 +1018,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 +1038,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 +1240,211 @@ 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 irq, ret;
+
+	/* 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;
+	}
+	/* ...and then came back to a more standard name. */
+	strcpy(ndev->name, "eth%d");
+
+	aup = ndev->priv;
+
+	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_lowlevel_remove;
+	}
+
+	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_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);
+
+	dev_set_drvdata(dev, NULL);
+
+	unregister_netdev(ndev);
+	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.
+	 */
+	reset_mac(ndev); /* au1000_init() expects the device in reset */
+	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);

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-14  7:54   ` Rodolfo Giometti
  2006-07-14 10:48     ` Rodolfo Giometti
@ 2006-07-18 17:46     ` Rodolfo Giometti
  2006-07-18 19:36       ` Ralf Baechle
  2006-07-19  8:29     ` [PATCH] au1000_eth.c power management and driver registration support Rodolfo Giometti
  2 siblings, 1 reply; 8+ messages in thread
From: Rodolfo Giometti @ 2006-07-18 17:46 UTC (permalink / raw)
  To: linux-mips

[-- Attachment #1: Type: text/plain, Size: 1245 bytes --]

On Fri, Jul 14, 2006 at 09:54:41AM +0200, Rodolfo Giometti wrote:
> 
> The first strange thing is that this time the kernel messages stop
> after "au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..."
> as before the merge! Maybe something as changed in serial console
> magement?

Yes, something as changed... here the patch to remove the problem.

   diff --git a/kernel/power/main.c b/kernel/power/main.c
   index 6d295c7..10bf859 100644
   --- a/kernel/power/main.c
   +++ b/kernel/power/main.c
   @@ -86,7 +86,9 @@ static int suspend_prepare(suspend_state
    			goto Thaw;
    	}
    
   +#ifndef CONFIG_DEBUG_KERNEL
    	suspend_console();
   +#endif
    	if ((error = device_suspend(PMSG_SUSPEND))) {
    		printk(KERN_ERR "Some devices failed to suspend\n");
    		goto Finish;

I'd like also sending this patch to the Linux main tree, where should
I send it? I found nothing useful in MAINTAINERS file... :-o

Ciao,

Rodolfo

-- 

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 #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Problems after merge to 2.6.18-rc1
  2006-07-18 17:46     ` Rodolfo Giometti
@ 2006-07-18 19:36       ` Ralf Baechle
  0 siblings, 0 replies; 8+ messages in thread
From: Ralf Baechle @ 2006-07-18 19:36 UTC (permalink / raw)
  To: Rodolfo Giometti; +Cc: linux-mips

On Tue, Jul 18, 2006 at 07:46:39PM +0200, Rodolfo Giometti wrote:

> > The first strange thing is that this time the kernel messages stop
> > after "au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..."
> > as before the merge! Maybe something as changed in serial console
> > magement?
> 
> Yes, something as changed... here the patch to remove the problem.
> 
>    diff --git a/kernel/power/main.c b/kernel/power/main.c
>    index 6d295c7..10bf859 100644
>    --- a/kernel/power/main.c
>    +++ b/kernel/power/main.c
>    @@ -86,7 +86,9 @@ static int suspend_prepare(suspend_state
>     			goto Thaw;
>     	}
>     
>    +#ifndef CONFIG_DEBUG_KERNEL
>     	suspend_console();
>    +#endif
>     	if ((error = device_suspend(PMSG_SUSPEND))) {
>     		printk(KERN_ERR "Some devices failed to suspend\n");
>     		goto Finish;
> 
> I'd like also sending this patch to the Linux main tree, where should
> I send it? I found nothing useful in MAINTAINERS file... :-o

You missed the last entry in MAINTAINERS ;-)  Send such stuff to
linux-kernel@vger.kernel.org.

  Ralf

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] au1000_eth.c power management and driver registration support
  2006-07-14  7:54   ` Rodolfo Giometti
  2006-07-14 10:48     ` Rodolfo Giometti
  2006-07-18 17:46     ` Rodolfo Giometti
@ 2006-07-19  8:29     ` Rodolfo Giometti
  2 siblings, 0 replies; 8+ messages 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] 8+ messages in thread

end of thread, other threads:[~2006-07-19  8:30 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-13 16:32 Problems after merge to 2.6.18-rc1 Rodolfo Giometti
2006-07-13 19:19 ` Daniel Mack
2006-07-14  1:35 ` Atsushi Nemoto
2006-07-14  7:54   ` Rodolfo Giometti
2006-07-14 10:48     ` Rodolfo Giometti
2006-07-18 17:46     ` Rodolfo Giometti
2006-07-18 19:36       ` Ralf Baechle
2006-07-19  8:29     ` [PATCH] au1000_eth.c power management and driver registration support Rodolfo Giometti

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.