diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2009-12-08 10:29:27 +0000 |
---|---|---|
committer | Gabor Juhos <juhosg@openwrt.org> | 2009-12-08 10:29:27 +0000 |
commit | 5504bc6629b98745f571ce06e1ebf45c33d90630 (patch) | |
tree | 91864b9fa4ca31774965dd23c96b2536f12ad64d /target/linux/ar71xx/files/drivers | |
parent | 0346ad9467e2df93e20794eb80c3a241626f078e (diff) | |
download | master-187ad058-5504bc6629b98745f571ce06e1ebf45c33d90630.tar.gz master-187ad058-5504bc6629b98745f571ce06e1ebf45c33d90630.tar.bz2 master-187ad058-5504bc6629b98745f571ce06e1ebf45c33d90630.zip |
ar71xx: add support for external mii_bus
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18692 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ar71xx/files/drivers')
4 files changed, 48 insertions, 9 deletions
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); |