Commit 89be0501 authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Jeff Garzik

[PATCH] au1000_eth.c probe code straightened up

      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: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent e2fd956c
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* Alchemy Au1x00 ethernet driver * Alchemy Au1x00 ethernet driver
* *
* Copyright 2001,2002,2003 MontaVista Software Inc. * Copyright 2001-2003, 2006 MontaVista Software Inc.
* Copyright 2002 TimeSys Corp. * Copyright 2002 TimeSys Corp.
* Added ethtool/mii-tool support, * Added ethtool/mii-tool support,
* Copyright 2004 Matt Porter <mporter@kernel.crashing.org> * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
...@@ -67,7 +67,7 @@ static int au1000_debug = 5; ...@@ -67,7 +67,7 @@ static int au1000_debug = 5;
static int au1000_debug = 3; static int au1000_debug = 3;
#endif #endif
#define DRV_NAME "au1000eth" #define DRV_NAME "au1000_eth"
#define DRV_VERSION "1.5" #define DRV_VERSION "1.5"
#define DRV_AUTHOR "Pete Popov <ppopov@embeddedalley.com>" #define DRV_AUTHOR "Pete Popov <ppopov@embeddedalley.com>"
#define DRV_DESC "Au1xxx on-chip Ethernet driver" #define DRV_DESC "Au1xxx on-chip Ethernet driver"
...@@ -79,7 +79,7 @@ MODULE_LICENSE("GPL"); ...@@ -79,7 +79,7 @@ MODULE_LICENSE("GPL");
// prototypes // prototypes
static void hard_stop(struct net_device *); static void hard_stop(struct net_device *);
static void enable_rx_tx(struct net_device *dev); 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_init(struct net_device *);
static int au1000_open(struct net_device *); static int au1000_open(struct net_device *);
static int au1000_close(struct net_device *); static int au1000_close(struct net_device *);
...@@ -1159,12 +1159,27 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base) ...@@ -1159,12 +1159,27 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
} }
static struct { static struct {
int port;
u32 base_addr; u32 base_addr;
u32 macen_addr; u32 macen_addr;
int irq; int irq;
struct net_device *dev; 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; static int num_ifs;
...@@ -1175,58 +1190,14 @@ static int num_ifs; ...@@ -1175,58 +1190,14 @@ static int num_ifs;
*/ */
static int __init au1000_init_module(void) 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); int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
struct net_device *dev; struct net_device *dev;
int i, found_one = 0; int i, found_one = 0;
switch (c->cputype) { num_ifs = NUM_ETH_INTERFACES - ni;
#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++) { 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; iflist[i].dev = dev;
if (dev) if (dev)
found_one++; found_one++;
...@@ -1435,8 +1406,7 @@ static struct ethtool_ops au1000_ethtool_ops = { ...@@ -1435,8 +1406,7 @@ static struct ethtool_ops au1000_ethtool_ops = {
.get_link = au1000_get_link .get_link = au1000_get_link
}; };
static struct net_device * static struct net_device * au1000_probe(int port_num)
au1000_probe(u32 ioaddr, int irq, int port_num)
{ {
static unsigned version_printed = 0; static unsigned version_printed = 0;
struct au1000_private *aup = NULL; struct au1000_private *aup = NULL;
...@@ -1444,9 +1414,18 @@ au1000_probe(u32 ioaddr, int irq, int port_num) ...@@ -1444,9 +1414,18 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
db_dest_t *pDB, *pDBfree; db_dest_t *pDB, *pDBfree;
char *pmac, *argptr; char *pmac, *argptr;
char ethaddr[6]; 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; return NULL;
if (version_printed++ == 0) if (version_printed++ == 0)
...@@ -1454,84 +1433,76 @@ au1000_probe(u32 ioaddr, int irq, int port_num) ...@@ -1454,84 +1433,76 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
dev = alloc_etherdev(sizeof(struct au1000_private)); dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) { if (!dev) {
printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n"); printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
return NULL; return NULL;
} }
if ((err = register_netdev(dev))) { if ((err = register_netdev(dev)) != 0) {
printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n", printk(KERN_ERR "%s: Cannot register net device, error %d\n",
err); DRV_NAME, err);
free_netdev(dev); free_netdev(dev);
return NULL; return NULL;
} }
printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
dev->name, ioaddr, irq); dev->name, base, irq);
aup = dev->priv; aup = dev->priv;
/* Allocate the data buffers */ /* Allocate the data buffers */
/* Snooping works fine with eth on all au1xxx */ /* Snooping works fine with eth on all au1xxx */
aup->vaddr = (u32)dma_alloc_noncoherent(NULL, aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), (NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, &aup->dma_addr, 0);
0);
if (!aup->vaddr) { if (!aup->vaddr) {
free_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; return NULL;
} }
/* aup->mac is the base address of the MAC's registers */ /* 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 */ /* Setup some variables for quick register address access */
if (ioaddr == iflist[0].base_addr) aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
{ aup->mac_id = port_num;
/* check env variables first */ au_macs[port_num] = aup;
if (!get_ethernet_addr(ethaddr)) {
if (port_num == 0) {
/* Check the environment variables first */
if (get_ethernet_addr(ethaddr) == 0)
memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
} else { else {
/* Check command line */ /* Check command line */
argptr = prom_getcmdline(); argptr = prom_getcmdline();
if ((pmac = strstr(argptr, "ethaddr=")) == NULL) { if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
printk(KERN_INFO "%s: No mac address found\n", printk(KERN_INFO "%s: No MAC address found\n",
dev->name); dev->name);
/* use the hard coded mac addresses */ /* Use the hard coded MAC addresses */
} else { else {
str2eaddr(ethaddr, pmac + strlen("ethaddr=")); str2eaddr(ethaddr, pmac + strlen("ethaddr="));
memcpy(au1000_mac_addr, 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); setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
aup->mac_id = 0; } else if (port_num == 1)
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;
setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); 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; *aup->enable = MAC_EN_CLOCK_ENABLE;
au_sync_delay(2); au_sync_delay(2);
*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 |
MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE; MAC_EN_CLOCK_ENABLE;
au_sync_delay(2); au_sync_delay(2);
aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL); aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
...@@ -1580,7 +1551,7 @@ au1000_probe(u32 ioaddr, int irq, int port_num) ...@@ -1580,7 +1551,7 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
} }
spin_lock_init(&aup->lock); spin_lock_init(&aup->lock);
dev->base_addr = ioaddr; dev->base_addr = base;
dev->irq = irq; dev->irq = irq;
dev->open = au1000_open; dev->open = au1000_open;
dev->hard_start_xmit = au1000_tx; dev->hard_start_xmit = au1000_tx;
...@@ -1614,13 +1585,12 @@ au1000_probe(u32 ioaddr, int irq, int port_num) ...@@ -1614,13 +1585,12 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
if (aup->tx_db_inuse[i]) if (aup->tx_db_inuse[i])
ReleaseDB(aup, aup->tx_db_inuse[i]); ReleaseDB(aup, aup->tx_db_inuse[i]);
} }
dma_free_noncoherent(NULL, dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr);
(void *)aup->vaddr,
aup->dma_addr);
unregister_netdev(dev); unregister_netdev(dev);
free_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; return NULL;
} }
...@@ -1805,20 +1775,18 @@ static void __exit au1000_cleanup_module(void) ...@@ -1805,20 +1775,18 @@ static void __exit au1000_cleanup_module(void)
aup = (struct au1000_private *) dev->priv; aup = (struct au1000_private *) dev->priv;
unregister_netdev(dev); unregister_netdev(dev);
kfree(aup->mii); 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]) if (aup->rx_db_inuse[j])
ReleaseDB(aup, 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]) if (aup->tx_db_inuse[j])
ReleaseDB(aup, aup->tx_db_inuse[j]); ReleaseDB(aup, aup->tx_db_inuse[j]);
} dma_free_noncoherent(NULL, MAX_BUF_SIZE *
dma_free_noncoherent(NULL, (NUM_TX_BUFFS + NUM_RX_BUFFS),
MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr);
(void *)aup->vaddr, release_mem_region(dev->base_addr, MAC_IOSIZE);
aup->dma_addr); release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
free_netdev(dev); free_netdev(dev);
release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment