Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+87 −119
Original line number Original line Diff line number Diff line
@@ -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;
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");
// 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)
}
}


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;
 */
 */
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 = {
	.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)
	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)


	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)
	}
	}


	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)
		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)
			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);
		}
		}
	}
	}
}
}