Skip to contentSkip to conversation

Power management for au1000_eth.c

PATCH NAK Rodolfo Giometti 3 participants 11 messages Apr 5, 2006 – May 31, 2006

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Hello,

I'm trying to add power management support to au1000_eth.c driver.

In order to to it I 've added these two functions:

   static int au1000_eth_suspend(struct device *dev, pm_message_t state, u32 level)
   {
   	struct net_device *ndev = dev_get_drvdata(dev);
   	struct au1000_private *aup = (struct au1000_private *) ndev->priv;

if (!ndev)
return 0;

   	switch (level) {
   	case SUSPEND_DISABLE :
   		if (netif_running(ndev))
   			netif_device_detach(ndev);

break;

   	case SUSPEND_SAVE_STATE :
   		/* bring the device out of reset, otherwise accessing to mii
   	 	 * will hang */
   		*aup->enable = MAC_EN_CLOCK_ENABLE;
   		au_sync_delay(2);
   		*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
   				MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
   		au_sync_delay(2);

   		if (aup->phy_ops->phy_suspend)
   			aup->phy_ops->phy_suspend(ndev, aup->phy_addr, level);

   		del_timer_sync(&aup->timer); /* FIXME: REMOVED??? */
   		reset_mac(ndev);

   		netif_stop_queue(ndev);

   		free_irq(ndev->irq, dev);

break;

case SUSPEND_POWER_DOWN :

   		break;
   	}

   	return 0;
   }

   static int au1000_eth_resume(struct device *dev, u32 level)
   {
   	struct net_device *ndev = dev_get_drvdata(dev);
   	struct au1000_private *aup = (struct au1000_private *) ndev->priv;
           u32 flags;
   	int ret;

if (!ndev)
return 0;

   	switch (level) {
   	case RESUME_RESTORE_STATE :
   		/* bring the device out of reset, otherwise accessing to mii
   	 	 * will hang */
   		*aup->enable = MAC_EN_CLOCK_ENABLE;
   		au_sync_delay(2);
   		*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
   				MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
   		au_sync_delay(2);

   		if (aup->phy_ops->phy_resume)
   			aup->phy_ops->phy_resume(ndev, aup->phy_addr, level);
   		aup->phy_ops->phy_init(ndev, aup->phy_addr);

/* au1000_init() expects that the device is in reset state.
*/
reset_mac(ndev); /* au1000_init() expects the device in reset */ au1000_init(ndev);

   	        ret = request_irq(ndev->irq, &au1000_interrupt, 0, ndev->name, ndev);
   	        if (ret) {
   			printk(KERN_ERR "%s: unable to get IRQ %d\n",
   	                                 ndev->name, ndev->irq);
   			return ret; //FIXME
   		}

   		init_timer(&aup->timer); /* used in ioctl() */
   		aup->timer.expires = RUN_AT((3*HZ));
   		aup->timer.data = (unsigned long) ndev;
   		aup->timer.function = &au1000_timer; /* timer handler */
   		add_timer(&aup->timer);

break;

   	case RESUME_ENABLE :
   		if (netif_running(ndev))
   			netif_device_attach(ndev);

   		break;
   	}

   	return 0;
   }

The problem is that after wakeup the system hangs or returns lots of errors like:

Reserved instruction in kernel code in arch/mips/kernel/traps.c::do_ri, line 706[#169]:

Note that if I compile the driver as a module and removing it before sleeping and reinstalling it after wake up the system (and the ethernet) works correctly...

Suggestions? :)

Thanks in advance,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#1 lore raw
Quoted 3 lines · Rodolfo Giometti

Hello,

I'm trying to add power management support to au1000_eth.c driver.

Solved! :)

Here a patch to implement power management functions for au1000_eth.

Note that this patch needs my previous one who implements new power management's sysfs interface.

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#2 lore raw

PATCH 1/1 Oops! - Re: Power management for au1000_eth.c

Quoted 11 lines · Rodolfo Giometti
Quoted 3 lines · Rodolfo Giometti

Hello,

I'm trying to add power management support to au1000_eth.c driver.

Solved! :)

Here a patch to implement power management functions for au1000_eth.

Note that this patch needs my previous one who implements new power management's sysfs interface.

The forgotten attachment. :)

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
mips/au1000/common/au1xxx_irqmap.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/au1xxx_irqmap.c +2 -2
@@ -118,7 +118,7 @@
 	{ 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 },
 
@@ -152,7 +152,7 @@
 	{ 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 },
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +79 -0

91 lines not on this page · raw message

drivers/net/Kconfig +2 -2
@@ -440,12 +440,12 @@
 	  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 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"
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +306 -185

641 lines not on this page · raw message

net/au1000_eth.h renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.h +2 -0
@@ -152,6 +152,8 @@
 	int (*phy_init) (struct net_device *, int);
 	int (*phy_reset) (struct net_device *, int);
 	int (*phy_status) (struct net_device *, int, u16 *, u16 *);
+	int (*phy_suspend) (struct net_device *, int, int);
+	int (*phy_resume) (struct net_device *, int, int);
 };
 
 /* 
#3 lore raw

Re: [PATCH] Oops! - Re: Power management for au1000_eth.c

Hello.

Quoted 5 lines · Rodolfo Giometti
Quoted 5 lines
Quoted 1 line

I'm trying to add power management support to au1000_eth.c driver.

Solved! :)

Here a patch to implement power management functions for au1000_eth.

Actually, the network driver patches should be sent to Jeff Garzik and
Andrew Morton.

Quoted 4 lines
Quoted 2 lines

Note that this patch needs my previous one who implements new power management's sysfs interface.

The forgotten attachment. :)

Funny, I've also been cooking a patch to straighten Alchemy Ethernet
probing code a bit...

Quoted 14 lines

------------------------------------------------------------------------

mips/au1000/common/au1xxx_irqmap.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/au1xxx_irqmap.c +1 -1
@@ -118,7 +118,7 @@
 	{ 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 },
 

mips/au1000/common/au1xxx_irqmap.c line 158

Quoted 8 lines
mips/au1000/common/au1xxx_irqmap.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/au1xxx_irqmap.c +1 -1
@@ -152,7 +152,7 @@
 	{ 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 },

Don't think these changes are necessary.

Quoted 5 lines
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +0 -0
@@ -16,6 +16,78 @@
 
 #include <asm/mach-au1x00/au1xxx.h>

mips/au1000/common/platform.c line 27

Quoted 10 lines
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +9 -0
 
+#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 + 0x0ffff,
+		.flags	= IORESOURCE_MEM,
+	},

NAK, ETH0_BASE not defined anywhere, and that address differs between SOCs.
Note that this must be a *physical* address, not KSEG1-base.

mips/au1000/common/platform.c line 33

Quoted 6 lines
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +6 -0
+	[1] = {
+		.name	= "eth-mac",
+		.start	= MAC0_ENABLE,
+		.end	= MAC0_ENABLE + 0x0ffff,
+		.flags	= IORESOURCE_MEM,
+	},

NAK, because:

1) MAC0_ENABLE not defined anywhere, and that address differs between SOCs;
2) MAC enable register occupies 4 bytes, not 65536.

[...]

Quoted 5 lines
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +5 -0
+#if defined(CONFIG_SOC_AU1000) || \
+    defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+static struct resource au1xxx_eth1_resources[] = {
+	[0] = {
+		.name	= "eth-base",

mips/au1000/common/platform.c line 68

Quoted 10 lines
mips/au1000/common/platform.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c +10 -0
+		.start	= ETH1_BASE,
+		.end	= ETH1_BASE + 0x0ffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name	= "eth-mac",
+		.start	= MAC1_ENABLE,
+		.end	= MAC1_ENABLE + 0x0ffff,
+		.flags	= IORESOURCE_MEM,
+	},

Same here.

Quoted 2 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +0 -0

[...]

net/au1000_eth.c line 74

Quoted 7 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -2
@@ -67,8 +71,8 @@
 static int au1000_debug = 3;
 #endif
 
-#define DRV_NAME	"au1000eth"
-#define DRV_VERSION	"1.5"
+#define DRV_NAME	"au1xxx-eth"

au1000_eth, according to the driver name.

net/au1000_eth.c line 75

Quoted 1 line
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -0
+#define DRV_VERSION	"1.6"

Heh, nobody keeps track of the versions. :-)

Quoted 8 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +2 -2
@@ -1435,40 +1391,14 @@
 	.get_link = au1000_get_link
 };
 
-static struct net_device *
-au1000_probe(u32 ioaddr, int irq, int port_num)
+static int 
+au1000_lowlevel_probe(struct net_device *ndev, u32 ioaddr, u32 macen_addr, int port_num)

[...]

Quoted 5 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +0 -1
@@ -1477,15 +1407,16 @@
 			&aup->dma_addr,
 			0);
 	if (!aup->vaddr) {
-		free_netdev(dev);

net/au1000_eth.c line 1417

Quoted 10 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +4 -2
-		release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
-		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 *)((unsigned long)ioaddr);

NAK, ioaddr should be physical address.

net/au1000_eth.c line 1419

Quoted 3 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -1
 	/* Setup some variables for quick register address access */
-	if (ioaddr == iflist[0].base_addr)
+	if (port_num == 0)

Yep, I disliked this code too. :-)

Quoted 13 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -1
 	{
 		/* check env variables first */
 		if (!get_ethernet_addr(ethaddr)) { 
@@ -1495,7 +1426,7 @@
 			argptr = prom_getcmdline();
 			if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
 				printk(KERN_INFO "%s: No mac address found\n", 
-						dev->name);
+						ndev->name);
 				/* use the hard coded mac addresses */
 			} else {
 				str2eaddr(ethaddr, pmac + strlen("ethaddr="));

net/au1000_eth.c line 1438

Quoted 6 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -2
@@ -1504,26 +1435,26 @@
 			}
 		}
 			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[0].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+				((unsigned long) macen_addr);

NAK, macen_addr should have been a physical address at that point too
(if the plarform definitions were correct :-). Also, this could have been done outside of "if".

net/au1000_eth.c line 1439

Quoted 1 line
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -0
+		memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));

That too.

Quoted 5 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +0 -0
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
 		aup->mac_id = 0;
 		au_macs[0] = aup;
 	}
 		else

net/au1000_eth.c line 1450

Quoted 10 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +4 -4
-	if (ioaddr == iflist[1].base_addr)
+	if (port_num == 1)
 	{
 			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[1].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-		dev->dev_addr[4] += 0x10;
+				((unsigned long) macen_addr);
+		memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+		ndev->dev_addr[4] += 0x10;

Actually, the DBAu15x0 boards have their Ethernet addresess differ by 1 in
the last byte, not by 0x10 in the next to last one. This code assigns to the port an address different to what's printed on a port's sticker. This should be fixed I guess...

net/au1000_eth.c line 1458

Quoted 9 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -1
 		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", dev->name);
+		printk(KERN_ERR "%s: bad ioaddr\n", ndev->name);
 	}

Doubt we need this "else" at all...

Quoted 31 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +25 -2
@@ -2255,5 +2162,232 @@
 	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, macen_addr;
+	int irq, ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-base");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
+	base_addr = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-mac");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;

net/au1000_eth.c line 2199

Quoted 10 lines
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +10 -0
+	}
+	macen_addr = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eth-irq");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
+	irq = res->start;
+
+	if (!request_mem_region(CPHYSADDR(base_addr), MAC_IOSIZE, "Au1x00 ENET")) {

NAK, base_addr should adready be a physical address. Also, why no
request_mem_region()
for the MAC enable register?

net/au1000_eth.c line 2216

Quoted 1 line
net/au1000_eth.c renamed from home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c +1 -0
+	ret = au1000_lowlevel_probe(ndev, base_addr, macen_addr, pdev->id);

Remember, The passed addresses are physical at that point.

[...]

WBR, Sergei

#4 lore raw

Re: [PATCH] Oops! - Re: Power management for au1000_eth.c

Quoted 3 lines · Sergei Shtylyov

Actually, the network driver patches should be sent to Jeff Garzik and
Andrew Morton.

Ok. Sorry. Hope they can get the patch from this list.

Quoted 2 lines

Funny, I've also been cooking a patch to straighten Alchemy Ethernet
probing code a bit...

:)

Quoted 15 lines
Quoted 15 lines

------------------------------------------------------------------------

---
/home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/au1xxx_irqmap.c 2006-03-31 16:57:26.000000000 +0200
+++ arch/mips/au1000/common/au1xxx_irqmap.c 2006-04-03
17:50:49.000000000 +0200

(quoted diff) +1 -1
@@ -118,7 +118,7 @@
 	{ 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 },
 
Quoted 11 lines

Review line 158

Quoted 9 lines
(quoted diff) +1 -1
@@ -152,7 +152,7 @@
 	{ 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 },

Don't think these changes are necessary.

These are necessary to group togheter CPUs that have the same parameters.

Quoted 8 lines
Quoted 8 lines

---
/home/develop/embedded/mipsel/linux/linux-mips.git/arch/mips/au1000/common/platform.c 2006-04-03 18:22:05.000000000 +0200
+++ arch/mips/au1000/common/platform.c 2006-04-05
23:08:55.000000000 +0200

(quoted diff) +0 -0
@@ -16,6 +16,78 @@
 
 #include <asm/mach-au1x00/au1xxx.h>
 
Quoted 14 lines

Review line 28

Quoted 10 lines
(quoted diff) +9 -0
+#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 + 0x0ffff,
+		.flags	= IORESOURCE_MEM,
+	},

NAK, ETH0_BASE not defined anywhere, and that address differs between SOCs.
Note that this must be a *physical* address, not KSEG1-base.

You are right! I forgot to add the attached file... I'm very sorry but I must work on an older Linux version which still use CVS. I can't switch to GIT right now and I have to build my patches by hands.

In the attached file you can see that I grouped togheter CPUs that have the same configuration parameters.

Quoted 5 lines

Review line 30

Quoted 3 lines
(quoted diff) +1 -1
 	/* Setup some variables for quick register address access */
-	if (ioaddr == iflist[0].base_addr)
+	if (port_num == 0)

Yep, I disliked this code too. :-)

I just use the "id" filed instaed of using the base address. It seems to me more readable...

Quoted 18 lines
Quoted 18 lines
	{
		/* check env variables first */
		if (!get_ethernet_addr(ethaddr)) { 
(quoted diff) +1 -0
@@ -1495,7 +1426,7 @@
 			argptr = prom_getcmdline();
 			if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
 				printk(KERN_INFO "%s: No mac address 
 				found\n", -						dev->name);
+						ndev->name);
 				/* use the hard coded mac addresses */
 			} else {
				str2eaddr(ethaddr, pmac + 
				strlen("ethaddr="));
(quoted diff) +0 -1
@@ -1504,26 +1435,26 @@
 			}
 		}
 			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[0].macen_addr);
Quoted 8 lines

Review line 1439

Quoted 3 lines
(quoted diff) +1 -1
-		memcpy(dev->dev_addr, au1000_mac_addr, 
 sizeof(au1000_mac_addr));
+				((unsigned long) macen_addr);

NAK, macen_addr should have been a physical address at that point too
(if the plarform definitions were correct :-). Also, this could have been done
outside of "if".

I just keeped the original structure...

Quoted 14 lines
Quoted 14 lines
(quoted diff) +2 -4
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
 		aup->mac_id = 0;
 		au_macs[0] = aup;
 	}
 		else
-	if (ioaddr == iflist[1].base_addr)
+	if (port_num == 1)
 	{
 			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[1].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, 
 sizeof(au1000_mac_addr));
-		dev->dev_addr[4] += 0x10;
+				((unsigned long) macen_addr);
Quoted 8 lines

Review line 1452

Quoted 3 lines
(quoted diff) +2 -0
+		memcpy(ndev->dev_addr, au1000_mac_addr, 
 sizeof(au1000_mac_addr));
+		ndev->dev_addr[4] += 0x10;

Actually, the DBAu15x0 boards have their Ethernet addresess differ by 1 in the last byte, not by 0x10 in the next to last one. This code assigns to
the port an address different to what's printed on a port's sticker. This should be fixed I guess...

Yes. However this comes from the previous driver version and I'm working on an Au1100 based board. :)

Quoted 38 lines
Quoted 38 lines
(quoted diff) +32 -2
@@ -2255,5 +2162,232 @@
 	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, macen_addr;
+	int irq, ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-base");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
+	base_addr = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-mac");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
+	macen_addr = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eth-irq");
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
Quoted 8 lines
Quoted 4 lines
(quoted diff) +3 -0
+	irq = res->start;
+
+	if (!request_mem_region(CPHYSADDR(base_addr), MAC_IOSIZE, "Au1x00 

ENET")) {

NAK, base_addr should adready be a physical address. Also, why no
request_mem_region()
for the MAC enable register?

Yes. I forgot to add it.

Thanks for your suggestions! But I'd like to know if I have to change something and resubmit the patch or these suggestions can be resolved during the merging of the code...

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
asm-mips/mach-au1x00/au1000.h renamed from home/develop/embedded/mipsel/linux/linux-mips.git/include/asm-mips/mach-au1x00/au1000.h +18 -21
@@ -606,11 +690,10 @@
 #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		  0xB0500000
+#define ETH1_BASE		  0xB0510000
+#define MAC0_ENABLE		  0xB0520000
+#define MAC1_ENABLE		  0xB0520004
 #endif /* CONFIG_SOC_AU1000 */
 
 /* Au1500 */
@@ -635,8 +718,8 @@
 #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
@@ -683,11 +766,10 @@
 #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		  0xB1500000
+#define ETH1_BASE		  0xB1510000
+#define MAC0_ENABLE		  0xB1520000
+#define MAC1_ENABLE		  0xB1520004
 #endif /* CONFIG_SOC_AU1500 */
 
 /* Au1100 */
@@ -713,8 +795,8 @@
 #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	AU1100_GPIO_208_215	29
+#define AU1000_MAC0_DMA_INT	  28
+#define	AU1100_GPIO_208_215	  29
 #define	AU1100_LCD_INT            30
 #define AU1000_AC97C_INT          31
 #define AU1000_GPIO_0             32
@@ -757,8 +839,8 @@
 #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 ETH0_BASE		  0xB0500000
+#define MAC0_ENABLE		  0xB0520000
 #define NUM_ETH_INTERFACES 1
 #endif /* CONFIG_SOC_AU1100 */
 
@@ -841,11 +923,10 @@
 #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		  0xB0500000
+#define ETH1_BASE		  0xB0510000
+#define MAC0_ENABLE		  0xB0520000
+#define MAC1_ENABLE		  0xB0520004
 #endif /* CONFIG_SOC_AU1550 */
 
 #ifdef CONFIG_SOC_AU1200
#10 lore raw

Re: Oops! - Re: Power management for au1000_eth.c

In reply to Sergei Shtylyov
Quoted 4 lines · Sergei Shtylyov

Hello.

Rodolfo Giometti wrote:

Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 1 line

I'm trying to add power management support to au1000_eth.c driver.

Solved! :)

Here a patch to implement power management functions for au1000_eth.

Actually, the network driver patches should be sent to Jeff Garzik and
Andrew Morton.

And the description is wrong - this isn't exactly just power management, there are lots of changes here. You should separate them out into multiple patches.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Note that this patch needs my previous one who implements new power management's sysfs interface.

Thats OK, as long as this patch can be applied on its own, without requiring the previous patch. It is one thing to write a new PM interface for the whole system, but the driver suspend and resume functions should never be system specific. That makes life easier for future developers.

Quoted 2 lines

Funny, I've also been cooking a patch to straighten Alchemy Ethernet
probing code a bit...

I think we can all get along here. The PM stuff looks decent to me, and Sergei had some good comments about the rest of the patch. I don't see any reason why the two of you can't get together and bang out a few patches to fix all of our ills.

Jordan

--
Jordan Crouse
Senior Linux Engineer
AMD - Personal Connectivity Solutions Group
<www.amd.com/embeddedprocessors>

#5 lore raw

PATCH 1/1 au1000_eth.c probe code straightened up

In reply to Rodolfo Giometti

Straighten up the AMD Au1xx0 Ethernet probing code, make it print out (and
store in the 'net_device' structure) the physical address of the controller, not the KSEG1-based virtual. Make the driver also claim/release the 4-byte MAC enable registers and assign to the Ethernet ports two consecutive MAC addresses to match those that are printed on their stickers.

drivers/net/au1000_eth.c +87 -119
index 1363083..d5dfc78 100644
@@ -2,7 +2,7 @@
  *
  * Alchemy Au1x00 ethernet driver
  *
- * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2001-2003, 2006 MontaVista Software Inc.
  * Copyright 2002 TimeSys Corp.
  * Added ethtool/mii-tool support,
  * Copyright 2004 Matt Porter <[email protected]>
@@ -67,7 +67,7 @@ static int au1000_debug = 5;
 static int au1000_debug = 3;
 #endif
 
-#define DRV_NAME	"au1000eth"
+#define DRV_NAME	"au1000_eth"
 #define DRV_VERSION	"1.5"
 #define DRV_AUTHOR	"Pete Popov <[email protected]>"
 #define DRV_DESC	"Au1xxx on-chip Ethernet driver"
@@ -79,7 +79,7 @@ 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(u32 ioaddr, int irq, int port_num);
+static struct net_device * au1000_probe(int port_num);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
 static int au1000_close(struct net_device *);
@@ -1159,12 +1159,27 @@ setup_hw_rings(struct au1000_private *au
 }
 
 static struct {
-	int port;
 	u32 base_addr;
 	u32 macen_addr;
 	int irq;
 	struct net_device *dev;
-} iflist[2];
+} 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;
 
@@ -1175,58 +1190,14 @@ static int num_ifs;
  */
 static int __init au1000_init_module(void)
 {
-	struct cpuinfo_mips *c = &current_cpu_data;
 	int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
 	struct net_device *dev;
 	int i, found_one = 0;
 
-	switch (c->cputype) {
-#ifdef CONFIG_SOC_AU1000
-	case CPU_AU1000:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1000_ETH0_BASE;
-		iflist[1].base_addr = AU1000_ETH1_BASE;
-		iflist[0].macen_addr = AU1000_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1000_MAC1_ENABLE;
-		iflist[0].irq = AU1000_MAC0_DMA_INT;
-		iflist[1].irq = AU1000_MAC1_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1100
-	case CPU_AU1100:
-		num_ifs = 1 - ni;
-		iflist[0].base_addr = AU1100_ETH0_BASE;
-		iflist[0].macen_addr = AU1100_MAC0_ENABLE;
-		iflist[0].irq = AU1100_MAC0_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1500
-	case CPU_AU1500:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1500_ETH0_BASE;
-		iflist[1].base_addr = AU1500_ETH1_BASE;
-		iflist[0].macen_addr = AU1500_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1500_MAC1_ENABLE;
-		iflist[0].irq = AU1500_MAC0_DMA_INT;
-		iflist[1].irq = AU1500_MAC1_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1550
-	case CPU_AU1550:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1550_ETH0_BASE;
-		iflist[1].base_addr = AU1550_ETH1_BASE;
-		iflist[0].macen_addr = AU1550_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1550_MAC1_ENABLE;
-		iflist[0].irq = AU1550_MAC0_DMA_INT;
-		iflist[1].irq = AU1550_MAC1_DMA_INT;
-		break;
-#endif
-	default:
-		num_ifs = 0;
-	}
+	num_ifs = NUM_ETH_INTERFACES - ni;
+
 	for(i = 0; i < num_ifs; i++) {
-		dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+		dev = au1000_probe(i);
 		iflist[i].dev = dev;
 		if (dev)
 			found_one++;
@@ -1435,8 +1406,7 @@ static struct ethtool_ops au1000_ethtool
 	.get_link = au1000_get_link
 };
 
-static struct net_device *
-au1000_probe(u32 ioaddr, int irq, int port_num)
+static struct net_device * au1000_probe(int port_num)
 {
 	static unsigned version_printed = 0;
 	struct au1000_private *aup = NULL;
@@ -1444,94 +1414,95 @@ au1000_probe(u32 ioaddr, int irq, int po
 	db_dest_t *pDB, *pDBfree;
 	char *pmac, *argptr;
 	char ethaddr[6];
-	int i, err;
+	int irq, i, err;
+	u32 base, macen;
+
+	if (port_num >= NUM_ETH_INTERFACES)
+ 		return NULL;
 
-	if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+	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) 
+	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 "au1000 eth: alloc_etherdev failed\n");  
+		printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
 		return NULL;
 	}
 
-	if ((err = register_netdev(dev))) {
-		printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
-				err);
+	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: Au1x Ethernet found at 0x%x, irq %d\n", 
-			dev->name, ioaddr, irq);
+	printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+		dev->name, base, irq);
 
 	aup = dev->priv;
 
 	/* Allocate the data buffers */
 	/* Snooping works fine with eth on all au1xxx */
-	aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
-			MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-			&aup->dma_addr,
-			0);
+	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+						(NUM_TX_BUFFS + NUM_RX_BUFFS),
+						&aup->dma_addr,	0);
 	if (!aup->vaddr) {
 		free_netdev(dev);
-		release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+		release_mem_region( base, MAC_IOSIZE);
+		release_mem_region(macen, 4);
 		return NULL;
 	}
 
 	/* aup->mac is the base address of the MAC's registers */
-	aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
+	aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+
 	/* Setup some variables for quick register address access */
-	if (ioaddr == iflist[0].base_addr)
-	{
-		/* check env variables first */
-		if (!get_ethernet_addr(ethaddr)) { 
+	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 {
+		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 {
+			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));
+				       sizeof(au1000_mac_addr));
 			}
 		}
-			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[0].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-		aup->mac_id = 0;
-		au_macs[0] = aup;
-	}
-		else
-	if (ioaddr == iflist[1].base_addr)
-	{
-			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[1].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-		dev->dev_addr[4] += 0x10;
+	} else if (port_num == 1)
 		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", dev->name);
-	}
 
-	/* bring the device out of reset, otherwise probing the mii
-	 * will hang */
+	/*
+	 * 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;
+
+	/* Bring the device out of reset, otherwise probing the MII will hang */
 	*aup->enable = MAC_EN_CLOCK_ENABLE;
 	au_sync_delay(2);
-	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
+	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 |
+		       MAC_EN_CLOCK_ENABLE;
 	au_sync_delay(2);
 
 	aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
@@ -1580,7 +1551,7 @@ au1000_probe(u32 ioaddr, int irq, int po
 	}
 
 	spin_lock_init(&aup->lock);
-	dev->base_addr = ioaddr;
+	dev->base_addr = base;
 	dev->irq = irq;
 	dev->open = au1000_open;
 	dev->hard_start_xmit = au1000_tx;
@@ -1614,13 +1585,12 @@ 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);
+	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(CPHYSADDR(ioaddr), MAC_IOSIZE);
+	release_mem_region( base, MAC_IOSIZE);
+	release_mem_region(macen, 4);
 	return NULL;
 }
 
@@ -1805,20 +1775,18 @@ static void __exit au1000_cleanup_module
 			aup = (struct au1000_private *) dev->priv;
 			unregister_netdev(dev);
 			kfree(aup->mii);
-			for (j = 0; j < NUM_RX_DMA; j++) {
+			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++) {
+			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);
+ 			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);
-			release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
 		}
 	}
 }
#6 lore raw

Re: [PATCH] au1000_eth.c Power Management, driver registration and module support

Hello,

here:

http://ftp.enneenne.com/pub/misc/au1100-patches/linux/patch-au1000_eth-pm-and-registration

the new version of my patch for au1000_eth.c who should implement:

* Module support.

- bool "MIPS AU1000 Ethernet support"
+ tristate "MIPS AU1000 Ethernet support"

* Driver registration.

   +static int __init au1000_eth_init(void)
   +{
   +	return driver_register(&au1000_driver);
   +}
   +
   +static void __exit au1000_eth_cleanup(void)
   +{
   +	driver_unregister(&au1000_driver);
   +}      

* Power Management.

+#ifdef CONFIG_PM
+ .suspend = au1000_drv_suspend,
+ .resume = au1000_drv_resume,
+#endif

Also, as suggested by Sergei it:

* uses physical addresses and not KSEG1-based virtual anymore and claims/releases the 4-byte MAC enable registers:

   wwpc:~# cat /proc/iomem
   10500000-1050ffff : eth-base
   10520000-10520003 : eth-mac

* assigns to the Ethernet ports two consecutive MAC addresses:

   -		dev->dev_addr[4] += 0x10;
   +				((unsigned long) macen_addr);
   +		memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
   +		ndev->dev_addr[5] += 0x01;

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#7 lore raw

Re: [PATCH] au1000_eth.c Power Management, driver registration and module support

Hello,

yesterday I did a little mess with GIT... now the patch is complete. Sorry. :)

I forgot also to say that it has been done against «linux-2.6.16-stable» branch.

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#8 lore raw

Re: [PATCH] au1000_eth.c Power Management, driver registration and module support

In reply to Rodolfo Giometti

Hello.

Quoted 15 lines · Rodolfo Giometti

here:

   http://ftp.enneenne.com/pub/misc/au1100-patches/linux/patch-au1000_eth-pm-and-registration

the new version of my patch for au1000_eth.c who should implement:

Also, as suggested by Sergei it:

* uses physical addresses and not KSEG1-based virtual anymore and claims/releases the 4-byte MAC enable registers:

   wwpc:~# cat /proc/iomem
   10500000-1050ffff : eth-base
   10520000-10520003 : eth-mac
Quoted 8 lines

* assigns to the Ethernet ports two consecutive MAC addresses:

   -		dev->dev_addr[4] += 0x10;
   +				((unsigned long) macen_addr);
   +		memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
   +		ndev->dev_addr[5] += 0x01;

Ciao,

Now that this is merged, Rodolfo's patch should probably preempt mine...
but it looks like something was lost during the transition: I failed to see
where SYS_PINFUNC register is actually read (the comment mentioning this was retained :-) to check whether Ethernet port 1 is enabled (its pins are shared w/GPIO)...

Quoted 1 line

Rodolfo

WBR, Sergei

#9 lore raw

Re: [PATCH] au1000_eth.c Power Management, driver registration and module support

Quoted 6 lines · Sergei Shtylyov

Now that this is merged, Rodolfo's patch should probably preempt mine...
but it looks like something was lost during the transition: I failed to see where SYS_PINFUNC register is actually read (the comment mentioning this was retained :-) to check whether Ethernet port 1 is enabled (its pins are shared w/GPIO)...

You are right! Maybe something like this may fix the problem:

   diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
   index 341fdc4..8a6427e 100644
   --- a/drivers/net/au1000_eth.c
   +++ b/drivers/net/au1000_eth.c
   @@ -2149,6 +2149,9 @@ static int au1000_drv_probe(struct devic
           void *base_addr, *macen_addr;
           int 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) {

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127