All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rodolfo Giometti <giometti@linux.it>
To: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Subject: [PATCH] au1000_eth.c power management and driver registration support
Date: Wed, 19 Jul 2006 10:29:40 +0200	[thread overview]
Message-ID: <20060719082940.GC6887@enneenne.com> (raw)
In-Reply-To: <20060714075441.GE7186@gundam.enneenne.com>


[-- 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 --]

      parent reply	other threads:[~2006-07-19  8:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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     ` Rodolfo Giometti [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060719082940.GC6887@enneenne.com \
    --to=giometti@linux.it \
    --cc=linux-mips@linux-mips.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.