From 18867965f79a4dc13db50cdc529c102373da64a8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 8 Dec 2009 10:29:27 +0000 Subject: [PATCH] ar71xx: add support for external mii_bus SVN-Revision: 18692 --- .../ar71xx/files/arch/mips/ar71xx/devices.c | 3 ++ .../mips/include/asm/mach-ar71xx/platform.h | 1 + .../ar71xx/files/drivers/net/ag71xx/ag71xx.h | 1 - .../files/drivers/net/ag71xx/ag71xx_main.c | 7 +++- .../files/drivers/net/ag71xx/ag71xx_mdio.c | 7 ---- .../files/drivers/net/ag71xx/ag71xx_phy.c | 42 +++++++++++++++++++ 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c index bed23938ea..43212ed3bf 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @@ -628,6 +628,9 @@ void __init ar71xx_add_device_eth(unsigned int id) ar71xx_eth_instance); } + if (pdata->mii_bus_dev == NULL) + pdata->mii_bus_dev = &ar71xx_mdio_device.dev; + /* Reset the device */ ar71xx_device_stop(pdata->reset_bit); mdelay(100); diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h index baded8b8b9..145e79fcea 100644 --- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h @@ -25,6 +25,7 @@ struct ag71xx_platform_data { u32 reset_bit; u32 mii_if; u8 mac_addr[ETH_ALEN]; + struct device *mii_bus_dev; u8 has_gbit:1; u8 is_ar91xx:1; diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index 77962fec80..ac52896ab2 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h @@ -135,7 +135,6 @@ struct ag71xx { extern struct ethtool_ops ag71xx_ethtool_ops; -extern struct ag71xx_mdio *ag71xx_mdio_bus; int ag71xx_mdio_driver_init(void) __init; void ag71xx_mdio_driver_exit(void); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c index 28708f4216..88edb2fd4c 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -824,6 +824,12 @@ static int __init ag71xx_probe(struct platform_device *pdev) goto err_out; } + if (pdata->mii_bus_dev == NULL) { + dev_err(&pdev->dev, "no MII bus device specified\n"); + err = -EINVAL; + goto err_out; + } + dev = alloc_etherdev(sizeof(*ag)); if (!dev) { dev_err(&pdev->dev, "alloc_etherdev failed\n"); @@ -836,7 +842,6 @@ static int __init ag71xx_probe(struct platform_device *pdev) ag = netdev_priv(dev); ag->pdev = pdev; ag->dev = dev; - ag->mii_bus = ag71xx_mdio_bus->mii_bus; ag->msg_enable = netif_msg_init(ag71xx_msg_level, AG71XX_DEFAULT_MSG_ENABLE); spin_lock_init(&ag->lock); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c index d3ff13ec4f..6bc858cf8d 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c @@ -16,8 +16,6 @@ #define AG71XX_MDIO_RETRY 1000 #define AG71XX_MDIO_DELAY 5 -struct ag71xx_mdio *ag71xx_mdio_bus; - static inline void ag71xx_mdio_wr(struct ag71xx_mdio *am, unsigned reg, u32 value) { @@ -143,9 +141,6 @@ static int __init ag71xx_mdio_probe(struct platform_device *pdev) int i; int err; - if (ag71xx_mdio_bus) - return -EBUSY; - pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data specified\n"); @@ -202,7 +197,6 @@ static int __init ag71xx_mdio_probe(struct platform_device *pdev) ag71xx_mdio_dump_regs(am); platform_set_drvdata(pdev, am); - ag71xx_mdio_bus = am; return 0; err_free_bus: @@ -220,7 +214,6 @@ static int __exit ag71xx_mdio_remove(struct platform_device *pdev) struct ag71xx_mdio *am = platform_get_drvdata(pdev); if (am) { - ag71xx_mdio_bus = NULL; mdiobus_unregister(am->mii_bus); mdiobus_free(am->mii_bus); iounmap(am->mdio_base); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c index 176eddaaff..0db0a4bf78 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c @@ -262,10 +262,52 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) return ret; } +static int dev_is_class(struct device *dev, void *class) +{ + if (dev->class != NULL && !strcmp(dev->class->name, class)) + return 1; + + return 0; +} + +static struct device *dev_find_class(struct device *parent, char *class) +{ + if (dev_is_class(parent, class)) { + get_device(parent); + return parent; + } + + return device_find_child(parent, class, dev_is_class); +} + +static struct mii_bus *dev_to_mii_bus(struct device *dev) +{ + struct device *d; + + d = dev_find_class(dev, "mdio_bus"); + if (d != NULL) { + struct mii_bus *bus; + + bus = to_mii_bus(d); + put_device(d); + + return bus; + } + + return NULL; +} + int ag71xx_phy_connect(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + ag->mii_bus = dev_to_mii_bus(pdata->mii_bus_dev); + if (ag->mii_bus == NULL) { + printk(KERN_ERR "%s: unable to find MII bus on device '%s'\n", + ag->dev->name, dev_name(pdata->mii_bus_dev)); + return -ENODEV; + } + if (pdata->phy_mask) return ag71xx_phy_connect_multi(ag);