Commit bd2302c2 authored by Florian Fainelli's avatar Florian Fainelli Committed by Ralf Baechle

NET: au1000-eth: Convert to platform_driver model

This patch converts the au1000-eth driver to become a full platform-driver
as it ought to be. We now pass PHY-speficic configurations through
platform_data but for compatibility the driver still assumes the default
settings (search for PHY1 on MAC0) when no platform_data is passed. Tested
on my MTX-1 board.
Signed-off-by: default avatarFlorian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Patchwork: http://patchwork.linux-mips.org/patch/619/
Patchwork: http://patchwork.linux-mips.org/patch/963/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 66f75ccb
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/platform_device.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
...@@ -63,6 +64,7 @@ ...@@ -63,6 +64,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <au1000.h> #include <au1000.h>
#include <au1xxx_eth.h>
#include <prom.h> #include <prom.h>
#include "au1000_eth.h" #include "au1000_eth.h"
...@@ -112,15 +114,15 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; ...@@ -112,15 +114,15 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
* *
* PHY detection algorithm * PHY detection algorithm
* *
* If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is * If phy_static_config is undefined, the PHY setup is
* autodetected: * autodetected:
* *
* mii_probe() first searches the current MAC's MII bus for a PHY, * mii_probe() first searches the current MAC's MII bus for a PHY,
* selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is * selecting the first (or last, if phy_search_highest_addr is
* defined) PHY address not already claimed by another netdev. * defined) PHY address not already claimed by another netdev.
* *
* If nothing was found that way when searching for the 2nd ethernet * If nothing was found that way when searching for the 2nd ethernet
* controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then * controller's PHY and phy1_search_mac0 is defined, then
* the first MII bus is searched as well for an unclaimed PHY; this is * the first MII bus is searched as well for an unclaimed PHY; this is
* needed in case of a dual-PHY accessible only through the MAC0's MII * needed in case of a dual-PHY accessible only through the MAC0's MII
* bus. * bus.
...@@ -129,9 +131,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; ...@@ -129,9 +131,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
* controller is not registered to the network subsystem. * controller is not registered to the network subsystem.
*/ */
/* autodetection defaults */ /* autodetection defaults: phy1_search_mac0 */
#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR
#define AU1XXX_PHY1_SEARCH_ON_MAC0
/* static PHY setup /* static PHY setup
* *
...@@ -148,29 +148,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; ...@@ -148,29 +148,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
* specific irq-map * specific irq-map
*/ */
#if defined(CONFIG_MIPS_BOSPORUS)
/*
* Micrel/Kendin 5 port switch attached to MAC0,
* MAC0 is associated with PHY address 5 (== WAN port)
* MAC1 is not associated with any PHY, since it's connected directly
* to the switch.
* no interrupts are used
*/
# define AU1XXX_PHY_STATIC_CONFIG
# define AU1XXX_PHY0_ADDR 5
# define AU1XXX_PHY0_BUSID 0
# undef AU1XXX_PHY0_IRQ
# undef AU1XXX_PHY1_ADDR
# undef AU1XXX_PHY1_BUSID
# undef AU1XXX_PHY1_IRQ
#endif
#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
#endif
static void enable_mac(struct net_device *dev, int force_reset) static void enable_mac(struct net_device *dev, int force_reset)
{ {
unsigned long flags; unsigned long flags;
...@@ -390,67 +367,55 @@ static int mii_probe (struct net_device *dev) ...@@ -390,67 +367,55 @@ static int mii_probe (struct net_device *dev)
struct au1000_private *const aup = netdev_priv(dev); struct au1000_private *const aup = netdev_priv(dev);
struct phy_device *phydev = NULL; struct phy_device *phydev = NULL;
#if defined(AU1XXX_PHY_STATIC_CONFIG) if (aup->phy_static_config) {
BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
if(aup->mac_id == 0) { /* get PHY0 */ if (aup->phy_addr)
# if defined(AU1XXX_PHY0_ADDR) phydev = aup->mii_bus->phy_map[aup->phy_addr];
phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus->phy_map[AU1XXX_PHY0_ADDR]; else
# else printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", dev->name);
dev->name);
return 0;
# endif /* defined(AU1XXX_PHY0_ADDR) */
} else if (aup->mac_id == 1) { /* get PHY1 */
# if defined(AU1XXX_PHY1_ADDR)
phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus->phy_map[AU1XXX_PHY1_ADDR];
# else
printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
dev->name);
return 0; return 0;
# endif /* defined(AU1XXX_PHY1_ADDR) */ } else {
} int phy_addr;
#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */ /* find the first (lowest address) PHY on the current MAC's MII bus */
int phy_addr; for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
if (aup->mii_bus->phy_map[phy_addr]) {
/* find the first (lowest address) PHY on the current MAC's MII bus */ phydev = aup->mii_bus->phy_map[phy_addr];
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) if (!aup->phy_search_highest_addr)
if (aup->mii_bus->phy_map[phy_addr]) { break; /* break out with first one found */
phydev = aup->mii_bus->phy_map[phy_addr]; }
# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
break; /* break out with first one found */
# endif
}
# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0) if (aup->phy1_search_mac0) {
/* try harder to find a PHY */ /* try harder to find a PHY */
if (!phydev && (aup->mac_id == 1)) { if (!phydev && (aup->mac_id == 1)) {
/* no PHY found, maybe we have a dual PHY? */ /* no PHY found, maybe we have a dual PHY? */
printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
"let's see if it's attached to MAC0...\n"); "let's see if it's attached to MAC0...\n");
BUG_ON(!au_macs[0]); /* find the first (lowest address) non-attached PHY on
* the MAC0 MII bus */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
struct phy_device *const tmp_phydev =
aup->mii_bus->phy_map[phy_addr];
/* find the first (lowest address) non-attached PHY on if (aup->mac_id == 1)
* the MAC0 MII bus */ break;
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
struct phy_device *const tmp_phydev =
au_macs[0]->mii_bus->phy_map[phy_addr];
if (!tmp_phydev) if (!tmp_phydev)
continue; /* no PHY here... */ continue; /* no PHY here... */
if (tmp_phydev->attached_dev) if (tmp_phydev->attached_dev)
continue; /* already claimed by MAC0 */ continue; /* already claimed by MAC0 */
phydev = tmp_phydev; phydev = tmp_phydev;
break; /* found it */ break; /* found it */
}
}
} }
} }
# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */
#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */
if (!phydev) { if (!phydev) {
printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name); printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name);
return -1; return -1;
...@@ -578,31 +543,6 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base) ...@@ -578,31 +543,6 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
} }
} }
static struct {
u32 base_addr;
u32 macen_addr;
int irq;
struct net_device *dev;
} iflist[2] = {
#ifdef CONFIG_SOC_AU1000
{AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
{AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
#endif
#ifdef CONFIG_SOC_AU1100
{AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
#endif
#ifdef CONFIG_SOC_AU1500
{AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
{AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
#endif
#ifdef CONFIG_SOC_AU1550
{AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
{AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
#endif
};
static int num_ifs;
/* /*
* ethtool operations * ethtool operations
*/ */
...@@ -711,7 +651,6 @@ static int au1000_init(struct net_device *dev) ...@@ -711,7 +651,6 @@ static int au1000_init(struct net_device *dev)
static inline void update_rx_stats(struct net_device *dev, u32 status) static inline void update_rx_stats(struct net_device *dev, u32 status)
{ {
struct au1000_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &dev->stats; struct net_device_stats *ps = &dev->stats;
ps->rx_packets++; ps->rx_packets++;
...@@ -969,7 +908,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -969,7 +908,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
} }
pDB = aup->tx_db_inuse[aup->tx_head]; pDB = aup->tx_db_inuse[aup->tx_head];
skb_copy_from_linear_data(skb, pDB->vaddr, skb->len); skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
if (skb->len < ETH_ZLEN) { if (skb->len < ETH_ZLEN) {
for (i=skb->len; i<ETH_ZLEN; i++) { for (i=skb->len; i<ETH_ZLEN; i++) {
((char *)pDB->vaddr)[i] = 0; ((char *)pDB->vaddr)[i] = 0;
...@@ -1058,53 +997,59 @@ static const struct net_device_ops au1000_netdev_ops = { ...@@ -1058,53 +997,59 @@ static const struct net_device_ops au1000_netdev_ops = {
.ndo_change_mtu = eth_change_mtu, .ndo_change_mtu = eth_change_mtu,
}; };
static struct net_device * au1000_probe(int port_num) static int __devinit au1000_probe(struct platform_device *pdev)
{ {
static unsigned version_printed = 0; static unsigned version_printed = 0;
struct au1000_private *aup = NULL; struct au1000_private *aup = NULL;
struct au1000_eth_platform_data *pd;
struct net_device *dev = NULL; struct net_device *dev = NULL;
db_dest_t *pDB, *pDBfree; db_dest_t *pDB, *pDBfree;
int irq, i, err = 0;
struct resource *base, *macen;
char ethaddr[6]; char ethaddr[6];
int irq, i, err;
u32 base, macen;
if (port_num >= NUM_ETH_INTERFACES) base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
return NULL; if (!base) {
printk(KERN_ERR DRV_NAME ": failed to retrieve base register\n");
err = -ENODEV;
goto out;
}
base = CPHYSADDR(iflist[port_num].base_addr ); macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
macen = CPHYSADDR(iflist[port_num].macen_addr); if (!macen) {
irq = iflist[port_num].irq; printk(KERN_ERR DRV_NAME ": failed to retrieve MAC Enable register\n");
err = -ENODEV;
goto out;
}
if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || irq = platform_get_irq(pdev, 0);
!request_mem_region(macen, 4, "Au1x00 ENET")) if (irq < 0) {
return NULL; printk(KERN_ERR DRV_NAME ": failed to retrieve IRQ\n");
err = -ENODEV;
goto out;
}
if (version_printed++ == 0) if (!request_mem_region(base->start, resource_size(base), pdev->name)) {
printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); printk(KERN_ERR DRV_NAME ": failed to request memory region for base registers\n");
err = -ENXIO;
goto out;
}
if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) {
printk(KERN_ERR DRV_NAME ": failed to request memory region for MAC enable register\n");
err = -ENXIO;
goto err_request;
}
dev = alloc_etherdev(sizeof(struct au1000_private)); dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) { if (!dev) {
printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
return NULL; err = -ENOMEM;
goto err_alloc;
} }
dev->base_addr = base; SET_NETDEV_DEV(dev, &pdev->dev);
dev->irq = irq; platform_set_drvdata(pdev, dev);
dev->netdev_ops = &au1000_netdev_ops;
SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
dev->watchdog_timeo = ETH_TX_TIMEOUT;
err = register_netdev(dev);
if (err != 0) {
printk(KERN_ERR "%s: Cannot register net device, error %d\n",
DRV_NAME, err);
free_netdev(dev);
return NULL;
}
printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
dev->name, base, irq);
aup = netdev_priv(dev); aup = netdev_priv(dev);
spin_lock_init(&aup->lock); spin_lock_init(&aup->lock);
...@@ -1115,21 +1060,29 @@ static struct net_device * au1000_probe(int port_num) ...@@ -1115,21 +1060,29 @@ static struct net_device * au1000_probe(int port_num)
(NUM_TX_BUFFS + NUM_RX_BUFFS), (NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0); &aup->dma_addr, 0);
if (!aup->vaddr) { if (!aup->vaddr) {
free_netdev(dev); printk(KERN_ERR DRV_NAME ": failed to allocate data buffers\n");
release_mem_region( base, MAC_IOSIZE); err = -ENOMEM;
release_mem_region(macen, 4); goto err_vaddr;
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 *)iflist[port_num].base_addr; aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base));
if (!aup->mac) {
printk(KERN_ERR DRV_NAME ": failed to ioremap MAC registers\n");
err = -ENXIO;
goto err_remap1;
}
/* Setup some variables for quick register address access */ /* Setup some variables for quick register address access */
aup->enable = (volatile u32 *)iflist[port_num].macen_addr; aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen));
aup->mac_id = port_num; if (!aup->enable) {
au_macs[port_num] = aup; printk(KERN_ERR DRV_NAME ": failed to ioremap MAC enable register\n");
err = -ENXIO;
goto err_remap2;
}
aup->mac_id = pdev->id;
if (port_num == 0) { if (pdev->id == 0) {
if (prom_get_ethernet_addr(ethaddr) == 0) if (prom_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 {
...@@ -1139,7 +1092,7 @@ static struct net_device * au1000_probe(int port_num) ...@@ -1139,7 +1092,7 @@ static struct net_device * au1000_probe(int port_num)
} }
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
} else if (port_num == 1) } else if (pdev->id == 1)
setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
/* /*
...@@ -1147,14 +1100,37 @@ static struct net_device * au1000_probe(int port_num) ...@@ -1147,14 +1100,37 @@ static struct net_device * au1000_probe(int port_num)
* to match those that are printed on their stickers * to match those that are printed on their stickers
*/ */
memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
dev->dev_addr[5] += port_num; dev->dev_addr[5] += pdev->id;
*aup->enable = 0; *aup->enable = 0;
aup->mac_enabled = 0; aup->mac_enabled = 0;
pd = pdev->dev.platform_data;
if (!pd) {
printk(KERN_INFO DRV_NAME ": no platform_data passed, PHY search on MAC0\n");
aup->phy1_search_mac0 = 1;
} else {
aup->phy_static_config = pd->phy_static_config;
aup->phy_search_highest_addr = pd->phy_search_highest_addr;
aup->phy1_search_mac0 = pd->phy1_search_mac0;
aup->phy_addr = pd->phy_addr;
aup->phy_busid = pd->phy_busid;
aup->phy_irq = pd->phy_irq;
}
if (aup->phy_busid && aup->phy_busid > 0) {
printk(KERN_ERR DRV_NAME ": MAC0-associated PHY attached 2nd MACs MII"
"bus not supported yet\n");
err = -ENODEV;
goto err_mdiobus_alloc;
}
aup->mii_bus = mdiobus_alloc(); aup->mii_bus = mdiobus_alloc();
if (aup->mii_bus == NULL) if (aup->mii_bus == NULL) {
goto err_out; printk(KERN_ERR DRV_NAME ": failed to allocate mdiobus structure\n");
err = -ENOMEM;
goto err_mdiobus_alloc;
}
aup->mii_bus->priv = dev; aup->mii_bus->priv = dev;
aup->mii_bus->read = au1000_mdiobus_read; aup->mii_bus->read = au1000_mdiobus_read;
...@@ -1168,23 +1144,19 @@ static struct net_device * au1000_probe(int port_num) ...@@ -1168,23 +1144,19 @@ static struct net_device * au1000_probe(int port_num)
for(i = 0; i < PHY_MAX_ADDR; ++i) for(i = 0; i < PHY_MAX_ADDR; ++i)
aup->mii_bus->irq[i] = PHY_POLL; aup->mii_bus->irq[i] = PHY_POLL;
/* if known, set corresponding PHY IRQs */ /* if known, set corresponding PHY IRQs */
#if defined(AU1XXX_PHY_STATIC_CONFIG) if (aup->phy_static_config)
# if defined(AU1XXX_PHY0_IRQ) if (aup->phy_irq && aup->phy_busid == aup->mac_id)
if (AU1XXX_PHY0_BUSID == aup->mac_id) aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
# endif err = mdiobus_register(aup->mii_bus);
# if defined(AU1XXX_PHY1_IRQ) if (err) {
if (AU1XXX_PHY1_BUSID == aup->mac_id) printk(KERN_ERR DRV_NAME " failed to register MDIO bus\n");
aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; goto err_mdiobus_reg;
# endif }
#endif
mdiobus_register(aup->mii_bus);
if (mii_probe(dev) != 0) { if (mii_probe(dev) != 0)
goto err_out; goto err_out;
}
pDBfree = NULL; pDBfree = NULL;
/* setup the data buffer descriptors and attach a buffer to each one */ /* setup the data buffer descriptors and attach a buffer to each one */
...@@ -1216,19 +1188,35 @@ static struct net_device * au1000_probe(int port_num) ...@@ -1216,19 +1188,35 @@ static struct net_device * au1000_probe(int port_num)
aup->tx_db_inuse[i] = pDB; aup->tx_db_inuse[i] = pDB;
} }
dev->base_addr = base->start;
dev->irq = irq;
dev->netdev_ops = &au1000_netdev_ops;
SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
dev->watchdog_timeo = ETH_TX_TIMEOUT;
/* /*
* The boot code uses the ethernet controller, so reset it to start * The boot code uses the ethernet controller, so reset it to start
* fresh. au1000_init() expects that the device is in reset state. * fresh. au1000_init() expects that the device is in reset state.
*/ */
reset_mac(dev); reset_mac(dev);
return dev; err = register_netdev(dev);
if (err) {
printk(KERN_ERR DRV_NAME "%s: Cannot register net device, aborting.\n",
dev->name);
goto err_out;
}
printk("%s: Au1xx0 Ethernet found at 0x%lx, irq %d\n",
dev->name, (unsigned long)base->start, irq);
if (version_printed++ == 0)
printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
return 0;
err_out: err_out:
if (aup->mii_bus != NULL) { if (aup->mii_bus != NULL)
mdiobus_unregister(aup->mii_bus); mdiobus_unregister(aup->mii_bus);
mdiobus_free(aup->mii_bus);
}
/* here we should have a valid dev plus aup-> register addresses /* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.*/ * so we can reset the mac properly.*/
...@@ -1242,67 +1230,84 @@ err_out: ...@@ -1242,67 +1230,84 @@ err_out:
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]);
} }
err_mdiobus_reg:
mdiobus_free(aup->mii_bus);
err_mdiobus_alloc:
iounmap(aup->enable);
err_remap2:
iounmap(aup->mac);
err_remap1:
dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
(void *)aup->vaddr, aup->dma_addr); (void *)aup->vaddr, aup->dma_addr);
unregister_netdev(dev); err_vaddr:
free_netdev(dev); free_netdev(dev);
release_mem_region( base, MAC_IOSIZE); err_alloc:
release_mem_region(macen, 4); release_mem_region(macen->start, resource_size(macen));
return NULL; err_request:
release_mem_region(base->start, resource_size(base));
out:
return err;
} }
/* static int __devexit au1000_remove(struct platform_device *pdev)
* Setup the base address and interrupt of the Au1xxx ethernet macs
* based on cpu type and whether the interface is enabled in sys_pinfunc
* register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
*/
static int __init au1000_init_module(void)
{ {
int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); struct net_device *dev = platform_get_drvdata(pdev);
struct net_device *dev; struct au1000_private *aup = netdev_priv(dev);
int i, found_one = 0; int i;
struct resource *base, *macen;
num_ifs = NUM_ETH_INTERFACES - ni; platform_set_drvdata(pdev, NULL);
unregister_netdev(dev);
mdiobus_unregister(aup->mii_bus);
mdiobus_free(aup->mii_bus);
for (i = 0; i < NUM_RX_DMA; i++)
if (aup->rx_db_inuse[i])
ReleaseDB(aup, aup->rx_db_inuse[i]);
for (i = 0; i < NUM_TX_DMA; i++)
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);
iounmap(aup->mac);
iounmap(aup->enable);
base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(base->start, resource_size(base));
macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
release_mem_region(macen->start, resource_size(macen));
free_netdev(dev);
for(i = 0; i < num_ifs; i++) {
dev = au1000_probe(i);
iflist[i].dev = dev;
if (dev)
found_one++;
}
if (!found_one)
return -ENODEV;
return 0; return 0;
} }
static void __exit au1000_cleanup_module(void) static struct platform_driver au1000_eth_driver = {
.probe = au1000_probe,
.remove = __devexit_p(au1000_remove),
.driver = {
.name = "au1000-eth",
.owner = THIS_MODULE,
},
};
MODULE_ALIAS("platform:au1000-eth");
static int __init au1000_init_module(void)
{
return platform_driver_register(&au1000_eth_driver);
}
static void __exit au1000_exit_module(void)
{ {
int i, j; platform_driver_unregister(&au1000_eth_driver);
struct net_device *dev;
struct au1000_private *aup;
for (i = 0; i < num_ifs; i++) {
dev = iflist[i].dev;
if (dev) {
aup = netdev_priv(dev);
unregister_netdev(dev);
mdiobus_unregister(aup->mii_bus);
mdiobus_free(aup->mii_bus);
for (j = 0; j < NUM_RX_DMA; j++)
if (aup->rx_db_inuse[j])
ReleaseDB(aup, aup->rx_db_inuse[j]);
for (j = 0; j < NUM_TX_DMA; j++)
if (aup->tx_db_inuse[j])
ReleaseDB(aup, aup->tx_db_inuse[j]);
dma_free_noncoherent(NULL, MAX_BUF_SIZE *
(NUM_TX_BUFFS + NUM_RX_BUFFS),
(void *)aup->vaddr, aup->dma_addr);
release_mem_region(dev->base_addr, MAC_IOSIZE);
release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
free_netdev(dev);
}
}
} }
module_init(au1000_init_module); module_init(au1000_init_module);
module_exit(au1000_cleanup_module); module_exit(au1000_exit_module);
...@@ -108,6 +108,15 @@ struct au1000_private { ...@@ -108,6 +108,15 @@ struct au1000_private {
struct phy_device *phy_dev; struct phy_device *phy_dev;
struct mii_bus *mii_bus; struct mii_bus *mii_bus;
/* PHY configuration */
int phy_static_config;
int phy_search_highest_addr;
int phy1_search_mac0;
int phy_addr;
int phy_busid;
int phy_irq;
/* These variables are just for quick access to certain regs addresses. */ /* These variables are just for quick access to certain regs addresses. */
volatile mac_reg_t *mac; /* mac registers */ volatile mac_reg_t *mac; /* mac registers */
volatile u32 *enable; /* address of MAC Enable Register */ volatile u32 *enable; /* address of MAC Enable Register */
......
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