* Power management for au1000_eth.c
@ 2006-04-05 15:47 Rodolfo Giometti
2006-04-05 22:23 ` Rodolfo Giometti
0 siblings, 1 reply; 11+ messages in thread
From: Rodolfo Giometti @ 2006-04-05 15:47 UTC (permalink / raw)
To: Linux MIPS; +Cc: ppopov
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
--
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] 11+ messages in thread* Re: Power management for au1000_eth.c 2006-04-05 15:47 Power management for au1000_eth.c Rodolfo Giometti @ 2006-04-05 22:23 ` Rodolfo Giometti 2006-04-05 22:26 ` [PATCH] Oops! - " Rodolfo Giometti 0 siblings, 1 reply; 11+ messages in thread From: Rodolfo Giometti @ 2006-04-05 22:23 UTC (permalink / raw) To: Linux MIPS; +Cc: ppopov On Wed, Apr 05, 2006 at 05:47:11PM +0200, Rodolfo Giometti wrote: > 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 -- 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] 11+ messages in thread
* [PATCH] Oops! - Re: Power management for au1000_eth.c 2006-04-05 22:23 ` Rodolfo Giometti @ 2006-04-05 22:26 ` Rodolfo Giometti 2006-04-06 14:43 ` Sergei Shtylyov 0 siblings, 1 reply; 11+ messages in thread From: Rodolfo Giometti @ 2006-04-05 22:26 UTC (permalink / raw) To: Linux MIPS; +Cc: ppopov [-- Attachment #1.1: Type: text/plain, Size: 751 bytes --] On Thu, Apr 06, 2006 at 12:23:32AM +0200, Rodolfo Giometti wrote: > On Wed, Apr 05, 2006 at 05:47:11PM +0200, Rodolfo Giometti wrote: > > 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 -- 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 --] [-- Type: text/plain, Size: 22531 bytes --] --- /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 @@ -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 }, --- /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 @@ -16,6 +16,78 @@ #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 + 0x0ffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "eth-mac", + .start = MAC0_ENABLE, + .end = MAC0_ENABLE + 0x0ffff, + .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 = "au1xxx-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 + 0x0ffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "eth-mac", + .start = MAC1_ENABLE, + .end = MAC1_ENABLE + 0x0ffff, + .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 = "au1xxx-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] = { @@ -272,6 +344,13 @@ #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 --- a/drivers/net/Kconfig 2 Jul 2005 06:46:30 -0000 1.1.1.1 +++ b/drivers/net/Kconfig 5 Apr 2006 21:20:30 -0000 @@ -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" --- /home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c 2006-04-03 18:23:17.000000000 +0200 +++ drivers/net/au1000_eth.c 2006-04-05 23:43:18.000000000 +0200 @@ -9,6 +9,9 @@ * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de * or riemer@riemer-nt.de: fixed the link beat detection with * ioctls (SIOCGMIIPHY) + * Update: 2006 Rodolfo Giometti: PM support, module support. + * Copyright 2006 Rodolfo Giometti <giometti@linux.it> + * * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * @@ -57,6 +60,7 @@ #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" @@ -67,8 +71,8 @@ static int au1000_debug = 3; #endif -#define DRV_NAME "au1000eth" -#define DRV_VERSION "1.5" +#define DRV_NAME "au1xxx-eth" +#define DRV_VERSION "1.6" #define DRV_AUTHOR "Pete Popov <ppopov@embeddedalley.com>" #define DRV_DESC "Au1xxx on-chip Ethernet driver" @@ -79,7 +83,8 @@ // 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 int au1000_lowlevel_probe(struct net_device *ndev, u32 ioaddr, u32 macen_addr, int port_num); +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 *); @@ -432,6 +437,34 @@ return 0; } +#ifdef CONFIG_PM +int am79c874_suspend(struct net_device *dev, int phy_addr, int level) +{ + s16 mii_control; + + if (au1000_debug > 4) + printk("am79c874_suspend\n"); + + mii_control = mdio_read(dev, phy_addr, MII_CONTROL); + mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_PWRDWN); + mdelay(1); + return 0; +} + +int am79c874_resume(struct net_device *dev, int phy_addr, int level) +{ + s16 mii_control; + + if (au1000_debug > 4) + printk("am79c874_resume\n"); + + mii_control = mdio_read(dev, phy_addr, MII_CONTROL); + mdio_write(dev, phy_addr, MII_CONTROL, mii_control & ~MII_CNTL_PWRDWN); + mdelay(1); + return 0; +} +#endif + int lxt971a_init(struct net_device *dev, int phy_addr) { if (au1000_debug > 4) @@ -727,6 +760,10 @@ am79c874_init, am79c874_reset, am79c874_status, +#ifdef CONFIG_PM + am79c874_suspend, + am79c874_resume, +#endif }; struct phy_ops am79c901_ops = { @@ -1108,9 +1145,6 @@ dev->name, (unsigned)aup); spin_lock_irqsave(&aup->lock, flags); - if (aup->timer.function == &au1000_timer) {/* check if timer initted */ - del_timer(&aup->timer); - } hard_stop(dev); #ifdef CONFIG_BCM5222_DUAL_PHY @@ -1158,84 +1192,6 @@ } } -static struct { - int port; - u32 base_addr; - u32 macen_addr; - int irq; - struct net_device *dev; -} iflist[2]; - -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) -{ - struct cpuinfo_mips *c = ¤t_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; - } - for(i = 0; i < num_ifs; i++) { - dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i); - iflist[i].dev = dev; - if (dev) - found_one++; - } - if (!found_one) - return -ENODEV; - return 0; -} - static int au1000_setup_aneg(struct net_device *dev, u32 advertise) { struct au1000_private *aup = (struct au1000_private *)dev->priv; @@ -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) { - 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 i, err; - - if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "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 "au1000 eth: alloc_etherdev failed\n"); - return NULL; - } - - if ((err = register_netdev(dev))) { - printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n", - err); - free_netdev(dev); - return NULL; - } - - printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", - dev->name, ioaddr, irq); - - aup = dev->priv; + int i, ret; /* Allocate the data buffers */ /* Snooping works fine with eth on all au1xxx */ @@ -1477,15 +1407,16 @@ &aup->dma_addr, 0); if (!aup->vaddr) { - free_netdev(dev); - 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); /* Setup some variables for quick register address access */ - if (ioaddr == iflist[0].base_addr) + if (port_num == 0) { /* 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=")); @@ -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); + memcpy(ndev->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) + 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; 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); } /* bring the device out of reset, otherwise probing the mii @@ -1536,7 +1467,8 @@ aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL); if (!aup->mii) { - printk(KERN_ERR "%s: out of memory\n", dev->name); + printk(KERN_ERR "%s: out of memory\n", ndev->name); + ret = -ENOMEM; goto err_out; } aup->mii->next = NULL; @@ -1545,7 +1477,8 @@ aup->mii->mii_control_reg = 0; aup->mii->mii_data_reg = 0; - if (mii_probe(dev) != 0) { + if (mii_probe(ndev) != 0) { + ret = -EBUSY; goto err_out; } @@ -1564,6 +1497,7 @@ 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; @@ -1572,6 +1506,7 @@ 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; @@ -1579,32 +1514,24 @@ aup->tx_db_inuse[i] = pDB; } - spin_lock_init(&aup->lock); - dev->base_addr = ioaddr; - 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->set_config = &au1000_set_config; - dev->tx_timeout = au1000_tx_timeout; - dev->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(dev); + return 0; - return dev; +err_out : + au1000_lowlevel_remove(ndev); +out : + return ret; +} + +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); kfree(aup->mii); for (i = 0; i < NUM_RX_DMA; i++) { if (aup->rx_db_inuse[i]) @@ -1618,10 +1545,6 @@ 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); - return NULL; } /* @@ -1779,6 +1712,7 @@ if (au1000_debug > 4) printk("%s: close: dev=%p\n", dev->name, dev); + del_timer_sync(&aup->timer); reset_mac(dev); spin_lock_irqsave(&aup->lock, flags); @@ -1793,36 +1727,6 @@ 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); - kfree(aup->mii); - 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); - free_netdev(dev); - release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE); - } - } -} - static void update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; @@ -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; + } + irq = res->start; + + if (!request_mem_region(CPHYSADDR(base_addr), MAC_IOSIZE, "Au1x00 ENET")) { + ret = -EBUSY; + goto out; + } + + 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_io; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, dev); + + ret = au1000_lowlevel_probe(ndev, base_addr, macen_addr, pdev->id); + if (ret < 0) { + printk (KERN_ERR "%s: low level probe failed\n", DRV_NAME); + goto out_free_netdev; + } + + aup = ndev->priv; + + spin_lock_init(&aup->lock); + ndev->base_addr = base_addr; + 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->set_config = &au1000_set_config; + 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, irq); + + dev_set_drvdata(dev, ndev); + + return 0; + +out_lowlevel_remove : + au1000_lowlevel_remove(ndev); +out_free_netdev : + free_netdev(ndev); +out_release_io : + release_mem_region(CPHYSADDR(base_addr), MAC_IOSIZE); +out : + printk("%s: not found (%d).\n", DRV_NAME, ret); + + return ret; +} + +static int au1000_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + struct resource *res; + + dev_set_drvdata(dev, NULL); + + unregister_netdev(ndev); + au1000_lowlevel_remove(ndev); + free_netdev(ndev); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth-base"); + if (!res) { + printk(DRV_NAME ": warning! Invalid data!"); + return -EINVAL; + } + release_mem_region(CPHYSADDR(res->start), MAC_IOSIZE); + + return 0; +} + +#ifdef CONFIG_PM +static int au1000_drv_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); + + au1000_lowlevel_remove(ndev); + + break; + + case SUSPEND_POWER_DOWN : + + break; + } + + return 0; +} + +static int au1000_drv_resume(struct device *dev, u32 level) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct au1000_private *aup = (struct au1000_private *) ndev->priv; + int ret; + + if (!ndev) + return 0; + + switch (level) { + case RESUME_RESTORE_STATE : + ret = au1000_lowlevel_probe(ndev, aup->mac, aup->enable, aup->mac_id); + if (ret < 0) { + printk (KERN_ERR "%s: low level probe failed\n", DRV_NAME); + return ret; + } + + 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); + + break; + + case RESUME_ENABLE : + if (netif_running(ndev)) + netif_device_attach(ndev); + + break; + } + + 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); --- /home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.h 2006-03-31 16:58:55.000000000 +0200 +++ drivers/net/au1000_eth.h 2006-04-05 12:55:56.000000000 +0200 @@ -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); }; /* [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Oops! - Re: Power management for au1000_eth.c 2006-04-05 22:26 ` [PATCH] Oops! - " Rodolfo Giometti @ 2006-04-06 14:43 ` Sergei Shtylyov 2006-04-06 15:50 ` Rodolfo Giometti 2006-04-06 17:10 ` Oops! - Re: Power management for au1000_eth.c Jordan Crouse 0 siblings, 2 replies; 11+ messages in thread From: Sergei Shtylyov @ 2006-04-06 14:43 UTC (permalink / raw) To: Linux MIPS; +Cc: Rodolfo Giometti, Jordan Crouse, Pete Popov Hello. Rodolfo Giometti wrote: >>>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. >>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... > ------------------------------------------------------------------------ > > --- /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 > @@ -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 }, Don't think these changes are necessary. > --- /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 > @@ -16,6 +16,78 @@ > > #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 + 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. > + [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. [...] > +#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 + 0x0ffff, > + .flags = IORESOURCE_MEM, > + }, > + [1] = { > + .name = "eth-mac", > + .start = MAC1_ENABLE, > + .end = MAC1_ENABLE + 0x0ffff, > + .flags = IORESOURCE_MEM, > + }, Same here. > --- /home/develop/embedded/mipsel/linux/linux-mips.git/drivers/net/au1000_eth.c 2006-04-03 18:23:17.000000000 +0200 > +++ drivers/net/au1000_eth.c 2006-04-05 23:43:18.000000000 +0200 [...] > @@ -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. > +#define DRV_VERSION "1.6" Heh, nobody keeps track of the versions. :-) > @@ -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) [...] > @@ -1477,15 +1407,16 @@ > &aup->dma_addr, > 0); > if (!aup->vaddr) { > - free_netdev(dev); > - 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. > /* Setup some variables for quick register address access */ > - if (ioaddr == iflist[0].base_addr) > + if (port_num == 0) Yep, I disliked this code too. :-) > { > /* 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=")); > @@ -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". > + memcpy(ndev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); That too. > 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); > + 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... > 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... > @@ -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; > + } > + 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? > + ret = au1000_lowlevel_probe(ndev, base_addr, macen_addr, pdev->id); Remember, The passed addresses are physical at that point. [...] WBR, Sergei ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Oops! - Re: Power management for au1000_eth.c 2006-04-06 14:43 ` Sergei Shtylyov @ 2006-04-06 15:50 ` Rodolfo Giometti 2006-04-19 18:46 ` [PATCH] au1000_eth.c probe code straightened up Sergei Shtylyov 2006-04-06 17:10 ` Oops! - Re: Power management for au1000_eth.c Jordan Crouse 1 sibling, 1 reply; 11+ messages in thread From: Rodolfo Giometti @ 2006-04-06 15:50 UTC (permalink / raw) To: Linux MIPS; +Cc: Sergei Shtylyov, Jordan Crouse, Pete Popov [-- Attachment #1.1: Type: text/plain, Size: 6811 bytes --] On Thu, Apr 06, 2006 at 06:43:24PM +0400, Sergei Shtylyov wrote: > > 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. > Funny, I've also been cooking a patch to straighten Alchemy Ethernet > probing code a bit... :) > >------------------------------------------------------------------------ > > > >--- > >/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 > >@@ -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 }, > > Don't think these changes are necessary. These are necessary to group togheter CPUs that have the same parameters. > >--- > >/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 > >@@ -16,6 +16,78 @@ > > > > #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 + 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. > > /* 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... > > { > > /* 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=")); > >@@ -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". I just keeped the original structure... > > 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); > >+ 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. :) > >@@ -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; > >+ } > >+ 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 -- 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-2 --] [-- Type: text/plain, Size: 2999 bytes --] --- /home/develop/embedded/mipsel/linux/linux-mips.git/include/asm-mips/mach-au1x00/au1000.h 2006-04-03 18:24:38.000000000 +0200 +++ include/asm-mips/mach-au1x00/au1000.h 2006-04-06 17:31:04.000000000 +0200 @@ -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 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] au1000_eth.c probe code straightened up 2006-04-06 15:50 ` Rodolfo Giometti @ 2006-04-19 18:46 ` Sergei Shtylyov 2006-05-02 15:09 ` [PATCH] au1000_eth.c Power Management, driver registration and module support Rodolfo Giometti 0 siblings, 1 reply; 11+ messages in thread From: Sergei Shtylyov @ 2006-04-19 18:46 UTC (permalink / raw) To: jgarzik; +Cc: Rodolfo Giometti, netdev, Linux-MIPS [-- Attachment #1: Type: text/plain, Size: 429 bytes --] 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. Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> [-- Attachment #2: au1000_eth-probe-rewrite.patch --] [-- Type: text/plain, Size: 10374 bytes --] diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 1363083..d5dfc78 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -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 <mporter@kernel.crashing.org> @@ -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 <ppopov@embeddedalley.com>" #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 = ¤t_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); } } } ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] au1000_eth.c Power Management, driver registration and module support 2006-04-19 18:46 ` [PATCH] au1000_eth.c probe code straightened up Sergei Shtylyov @ 2006-05-02 15:09 ` Rodolfo Giometti 2006-05-03 7:47 ` Rodolfo Giometti 2006-05-31 15:01 ` Sergei Shtylyov 0 siblings, 2 replies; 11+ messages in thread From: Rodolfo Giometti @ 2006-05-02 15:09 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: jgarzik, netdev, Linux-MIPS [-- Attachment #1: Type: text/plain, Size: 1492 bytes --] 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 -- 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] 11+ messages in thread
* Re: [PATCH] au1000_eth.c Power Management, driver registration and module support 2006-05-02 15:09 ` [PATCH] au1000_eth.c Power Management, driver registration and module support Rodolfo Giometti @ 2006-05-03 7:47 ` Rodolfo Giometti 2006-05-31 15:01 ` Sergei Shtylyov 1 sibling, 0 replies; 11+ messages in thread From: Rodolfo Giometti @ 2006-05-03 7:47 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: jgarzik, netdev, Linux-MIPS [-- Attachment #1: Type: text/plain, Size: 467 bytes --] 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 -- 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] 11+ messages in thread
* Re: [PATCH] au1000_eth.c Power Management, driver registration and module support 2006-05-02 15:09 ` [PATCH] au1000_eth.c Power Management, driver registration and module support Rodolfo Giometti 2006-05-03 7:47 ` Rodolfo Giometti @ 2006-05-31 15:01 ` Sergei Shtylyov 2006-05-31 15:21 ` Rodolfo Giometti 1 sibling, 1 reply; 11+ messages in thread From: Sergei Shtylyov @ 2006-05-31 15:01 UTC (permalink / raw) To: Rodolfo Giometti; +Cc: jgarzik, netdev, Linux-MIPS, Jordan Crouse Hello. Rodolfo Giometti wrote: > 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 > > * 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)... > Rodolfo WBR, Sergei ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] au1000_eth.c Power Management, driver registration and module support 2006-05-31 15:01 ` Sergei Shtylyov @ 2006-05-31 15:21 ` Rodolfo Giometti 0 siblings, 0 replies; 11+ messages in thread From: Rodolfo Giometti @ 2006-05-31 15:21 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: jgarzik, netdev, Linux-MIPS, Jordan Crouse [-- Attachment #1: Type: text/plain, Size: 1337 bytes --] On Wed, May 31, 2006 at 07:01:02PM +0400, Sergei Shtylyov wrote: > > 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 -- 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] 11+ messages in thread
* Re: Oops! - Re: Power management for au1000_eth.c 2006-04-06 14:43 ` Sergei Shtylyov 2006-04-06 15:50 ` Rodolfo Giometti @ 2006-04-06 17:10 ` Jordan Crouse 1 sibling, 0 replies; 11+ messages in thread From: Jordan Crouse @ 2006-04-06 17:10 UTC (permalink / raw) To: Sergei Shtylyov; +Cc: Linux MIPS, Rodolfo Giometti, Pete Popov On 06/04/06 18:43 +0400, Sergei Shtylyov wrote: > Hello. > > Rodolfo Giometti wrote: > > >>>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. > >>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. > 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> ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2006-05-31 15:21 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-04-05 15:47 Power management for au1000_eth.c Rodolfo Giometti 2006-04-05 22:23 ` Rodolfo Giometti 2006-04-05 22:26 ` [PATCH] Oops! - " Rodolfo Giometti 2006-04-06 14:43 ` Sergei Shtylyov 2006-04-06 15:50 ` Rodolfo Giometti 2006-04-19 18:46 ` [PATCH] au1000_eth.c probe code straightened up Sergei Shtylyov 2006-05-02 15:09 ` [PATCH] au1000_eth.c Power Management, driver registration and module support Rodolfo Giometti 2006-05-03 7:47 ` Rodolfo Giometti 2006-05-31 15:01 ` Sergei Shtylyov 2006-05-31 15:21 ` Rodolfo Giometti 2006-04-06 17:10 ` Oops! - Re: Power management for au1000_eth.c Jordan Crouse
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.