Newer
Older
if (!aup->phy_dev)
return -EINVAL; /* PHY not controllable */
return phy_mii_ioctl(aup->phy_dev, rq, cmd);
static const struct net_device_ops au1000_netdev_ops = {
.ndo_open = au1000_open,
.ndo_stop = au1000_close,
.ndo_start_xmit = au1000_tx,
.ndo_set_multicast_list = au1000_multicast_list,
.ndo_do_ioctl = au1000_ioctl,
.ndo_tx_timeout = au1000_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
};
static int __devinit au1000_probe(struct platform_device *pdev)
struct au1000_eth_platform_data *pd;
int irq, i, err = 0;
struct resource *base, *macen;
base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!base) {
dev_err(&pdev->dev, "failed to retrieve base register\n");
err = -ENODEV;
goto out;
}
macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!macen) {
dev_err(&pdev->dev, "failed to retrieve MAC Enable register\n");
err = -ENODEV;
goto out;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to retrieve IRQ\n");
err = -ENODEV;
goto out;
}
if (!request_mem_region(base->start, resource_size(base),
pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for base registers\n");
err = -ENXIO;
goto out;
}
if (!request_mem_region(macen->start, resource_size(macen),
pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
err = -ENXIO;
goto err_request;
}
dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) {
dev_err(&pdev->dev, "alloc_etherdev failed\n");
err = -ENOMEM;
goto err_alloc;
SET_NETDEV_DEV(dev, &pdev->dev);
platform_set_drvdata(pdev, dev);
aup = netdev_priv(dev);
spin_lock_init(&aup->lock);
aup->msg_enable = (au1000_debug < 4 ?
AU1000_DEF_MSG_ENABLE : au1000_debug);
/* 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);
if (!aup->vaddr) {
dev_err(&pdev->dev, "failed to allocate data buffers\n");
err = -ENOMEM;
goto err_vaddr;
}
/* aup->mac is the base address of the MAC's registers */
aup->mac = (struct mac_reg *)
ioremap_nocache(base->start, resource_size(base));
dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
err = -ENXIO;
goto err_remap1;
}
/* Setup some variables for quick register address access */
aup->enable = (u32 *)ioremap_nocache(macen->start,
resource_size(macen));
if (!aup->enable) {
dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
err = -ENXIO;
goto err_remap2;
}
aup->mac_id = pdev->id;
if (pdev->id == 0)
au1000_setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
else if (pdev->id == 1)
au1000_setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
/* set a random MAC now in case platform_data doesn't provide one */
random_ether_addr(dev->dev_addr);
writel(0, aup->enable);
pd = pdev->dev.platform_data;
if (!pd) {
dev_info(&pdev->dev, "no platform_data passed,"
" PHY search on MAC0\n");
aup->phy1_search_mac0 = 1;
} else {
if (is_valid_ether_addr(pd->mac))
memcpy(dev->dev_addr, pd->mac, 6);
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) {
dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII bus not supported yet\n");
err = -ENODEV;
goto err_mdiobus_alloc;
}
if (aup->mii_bus == NULL) {
dev_err(&pdev->dev, "failed to allocate mdiobus structure\n");
err = -ENOMEM;
goto err_mdiobus_alloc;
}
aup->mii_bus->priv = dev;
aup->mii_bus->read = au1000_mdiobus_read;
aup->mii_bus->write = au1000_mdiobus_write;
aup->mii_bus->reset = au1000_mdiobus_reset;
aup->mii_bus->name = "au1000_eth_mii";
snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
if (aup->mii_bus->irq == NULL)
goto err_out;
for (i = 0; i < PHY_MAX_ADDR; ++i)
aup->mii_bus->irq[i] = PHY_POLL;
/* if known, set corresponding PHY IRQs */
if (aup->phy_static_config)
if (aup->phy_irq && aup->phy_busid == aup->mac_id)
aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
err = mdiobus_register(aup->mii_bus);
if (err) {
dev_err(&pdev->dev, "failed to register MDIO bus\n");
goto err_mdiobus_reg;
}
if (au1000_mii_probe(dev) != 0)
goto err_out;
pDBfree = NULL;
/* setup the data buffer descriptors and attach a buffer to each one */
pDB = aup->db;
for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
pDB->pnext = pDBfree;
pDBfree = pDB;
pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
pDB++;
}
aup->pDBfree = pDBfree;
for (i = 0; i < NUM_RX_DMA; i++) {
pDB = au1000_GetFreeDB(aup);
aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->rx_db_inuse[i] = pDB;
}
for (i = 0; i < NUM_TX_DMA; i++) {
pDB = au1000_GetFreeDB(aup);
aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->tx_dma_ring[i]->len = 0;
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
* fresh. au1000_init() expects that the device is in reset state.
*/
au1000_reset_mac(dev);
err = register_netdev(dev);
if (err) {
netdev_err(dev, "Cannot register net device, aborting.\n");
goto err_out;
}
netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
(unsigned long)base->start, irq);
if (version_printed++ == 0)
pr_info("%s version %s %s\n",
DRV_NAME, DRV_VERSION, DRV_AUTHOR);
if (aup->mii_bus != NULL)
mdiobus_unregister(aup->mii_bus);
/* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.
*/
au1000_reset_mac(dev);
for (i = 0; i < NUM_RX_DMA; i++) {
if (aup->rx_db_inuse[i])
au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
}
for (i = 0; i < NUM_TX_DMA; i++) {
if (aup->tx_db_inuse[i])
au1000_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),
(void *)aup->vaddr, aup->dma_addr);
err_alloc:
release_mem_region(macen->start, resource_size(macen));
err_request:
release_mem_region(base->start, resource_size(base));
out:
return err;
static int __devexit au1000_remove(struct platform_device *pdev)
struct net_device *dev = platform_get_drvdata(pdev);
struct au1000_private *aup = netdev_priv(dev);
int i;
struct resource *base, *macen;
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])
au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
for (i = 0; i < NUM_TX_DMA; i++)
if (aup->tx_db_inuse[i])
au1000_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);
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)
platform_driver_unregister(&au1000_eth_driver);
module_exit(au1000_exit_module);