aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/xscale/ixp4xx_eth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/xscale/ixp4xx_eth.c')
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c96
1 files changed, 44 insertions, 52 deletions
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 6fc04ffb22c2..d4e095d0e8f1 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -517,25 +517,14 @@ static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location,
return ret;
}
-static int ixp4xx_mdio_register(void)
+static int ixp4xx_mdio_register(struct eth_regs __iomem *regs)
{
int err;
if (!(mdio_bus = mdiobus_alloc()))
return -ENOMEM;
- if (cpu_is_ixp43x()) {
- /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
- if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
- return -ENODEV;
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
- } else {
- /* All MII PHY accesses use NPE-B Ethernet registers */
- if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
- return -ENODEV;
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
- }
-
+ mdio_regs = regs;
__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
spin_lock_init(&mdio_lock);
mdio_bus->name = "IXP4xx MII Bus";
@@ -1374,7 +1363,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int eth_init_one(struct platform_device *pdev)
+static int ixp4xx_eth_probe(struct platform_device *pdev)
{
struct port *port;
struct net_device *dev;
@@ -1384,7 +1373,7 @@ static int eth_init_one(struct platform_device *pdev)
char phy_id[MII_BUS_ID_SIZE + 3];
int err;
- if (!(dev = alloc_etherdev(sizeof(struct port))))
+ if (!(dev = devm_alloc_etherdev(&pdev->dev, sizeof(struct port))))
return -ENOMEM;
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1394,20 +1383,51 @@ static int eth_init_one(struct platform_device *pdev)
switch (port->id) {
case IXP4XX_ETH_NPEA:
+ /* If the MDIO bus is not up yet, defer probe */
+ if (!mdio_bus)
+ return -EPROBE_DEFER;
port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT;
regs_phys = IXP4XX_EthA_BASE_PHYS;
break;
case IXP4XX_ETH_NPEB:
+ /*
+ * On all except IXP43x, NPE-B is used for the MDIO bus.
+ * If there is no NPE-B in the feature set, bail out, else
+ * register the MDIO bus.
+ */
+ if (!cpu_is_ixp43x()) {
+ if (!(ixp4xx_read_feature_bits() &
+ IXP4XX_FEATURE_NPEB_ETH0))
+ return -ENODEV;
+ /* Else register the MDIO bus on NPE-B */
+ if ((err = ixp4xx_mdio_register(IXP4XX_EthC_BASE_VIRT)))
+ return err;
+ }
+ if (!mdio_bus)
+ return -EPROBE_DEFER;
port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
regs_phys = IXP4XX_EthB_BASE_PHYS;
break;
case IXP4XX_ETH_NPEC:
+ /*
+ * IXP43x lacks NPE-B and uses NPE-C for the MDIO bus access,
+ * of there is no NPE-C, no bus, nothing works, so bail out.
+ */
+ if (cpu_is_ixp43x()) {
+ if (!(ixp4xx_read_feature_bits() &
+ IXP4XX_FEATURE_NPEC_ETH))
+ return -ENODEV;
+ /* Else register the MDIO bus on NPE-C */
+ if ((err = ixp4xx_mdio_register(IXP4XX_EthC_BASE_VIRT)))
+ return err;
+ }
+ if (!mdio_bus)
+ return -EPROBE_DEFER;
port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
regs_phys = IXP4XX_EthC_BASE_PHYS;
break;
default:
- err = -ENODEV;
- goto err_free;
+ return -ENODEV;
}
dev->netdev_ops = &ixp4xx_netdev_ops;
@@ -1416,10 +1436,8 @@ static int eth_init_one(struct platform_device *pdev)
netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
- if (!(port->npe = npe_request(NPE_ID(port->id)))) {
- err = -EIO;
- goto err_free;
- }
+ if (!(port->npe = npe_request(NPE_ID(port->id))))
+ return -EIO;
port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
if (!port->mem_res) {
@@ -1465,12 +1483,10 @@ err_free_mem:
release_resource(port->mem_res);
err_npe_rel:
npe_release(port->npe);
-err_free:
- free_netdev(dev);
return err;
}
-static int eth_remove_one(struct platform_device *pdev)
+static int ixp4xx_eth_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct phy_device *phydev = dev->phydev;
@@ -1478,45 +1494,21 @@ static int eth_remove_one(struct platform_device *pdev)
unregister_netdev(dev);
phy_disconnect(phydev);
+ ixp4xx_mdio_remove();
npe_port_tab[NPE_ID(port->id)] = NULL;
npe_release(port->npe);
release_resource(port->mem_res);
- free_netdev(dev);
return 0;
}
static struct platform_driver ixp4xx_eth_driver = {
.driver.name = DRV_NAME,
- .probe = eth_init_one,
- .remove = eth_remove_one,
+ .probe = ixp4xx_eth_probe,
+ .remove = ixp4xx_eth_remove,
};
-
-static int __init eth_init_module(void)
-{
- int err;
-
- /*
- * FIXME: we bail out on device tree boot but this really needs
- * to be fixed in a nicer way: this registers the MDIO bus before
- * even matching the driver infrastructure, we should only probe
- * detected hardware.
- */
- if (of_have_populated_dt())
- return -ENODEV;
- if ((err = ixp4xx_mdio_register()))
- return err;
- return platform_driver_register(&ixp4xx_eth_driver);
-}
-
-static void __exit eth_cleanup_module(void)
-{
- platform_driver_unregister(&ixp4xx_eth_driver);
- ixp4xx_mdio_remove();
-}
+module_platform_driver(ixp4xx_eth_driver);
MODULE_AUTHOR("Krzysztof Halasa");
MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:ixp4xx_eth");
-module_init(eth_init_module);
-module_exit(eth_cleanup_module);