summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/mdio_bus.c
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2005-08-25 01:46:21 +0200
committerJeff Garzik <jgarzik@pobox.com>2005-08-29 02:28:25 +0200
commite13934563db047043ccead26412f552375cea90c (patch)
tree4013ca99f718559447315370c9d5e220e71d99d5 /drivers/net/phy/mdio_bus.c
parent[PATCH] r8169: avoid conflict between revisions 2 and 3 of the Linksys EG1032 (diff)
downloadlinux-e13934563db047043ccead26412f552375cea90c.tar.xz
linux-e13934563db047043ccead26412f552375cea90c.zip
[PATCH] PHY Layer fixup
This patch adds back the code that was taken out, thus re-enabling: * The PHY Layer to initialize without crashing * Drivers to actually connect to PHYs * The entire PHY Control Layer This patch is used by the gianfar driver, and other drivers which are in development. Signed-off-by: Andy Fleming <afleming@freescale.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/phy/mdio_bus.c')
-rw-r--r--drivers/net/phy/mdio_bus.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d5a05be28818..41f62c0c5fcb 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,6 +38,80 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+/* mdiobus_register
+ *
+ * description: Called by a bus driver to bring up all the PHYs
+ * on a given bus, and attach them to the bus
+ */
+int mdiobus_register(struct mii_bus *bus)
+{
+ int i;
+ int err = 0;
+
+ spin_lock_init(&bus->mdio_lock);
+
+ if (NULL == bus || NULL == bus->name ||
+ NULL == bus->read ||
+ NULL == bus->write)
+ return -EINVAL;
+
+ if (bus->reset)
+ bus->reset(bus);
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *phydev;
+
+ phydev = get_phy_device(bus, i);
+
+ if (IS_ERR(phydev))
+ return PTR_ERR(phydev);
+
+ /* There's a PHY at this address
+ * We need to set:
+ * 1) IRQ
+ * 2) bus_id
+ * 3) parent
+ * 4) bus
+ * 5) mii_bus
+ * And, we need to register it */
+ if (phydev) {
+ phydev->irq = bus->irq[i];
+
+ phydev->dev.parent = bus->dev;
+ phydev->dev.bus = &mdio_bus_type;
+ sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+
+ phydev->bus = bus;
+
+ err = device_register(&phydev->dev);
+
+ if (err)
+ printk(KERN_ERR "phy %d failed to register\n",
+ i);
+ }
+
+ bus->phy_map[i] = phydev;
+ }
+
+ pr_info("%s: probed\n", bus->name);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_register);
+
+void mdiobus_unregister(struct mii_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if (bus->phy_map[i]) {
+ device_unregister(&bus->phy_map[i]->dev);
+ kfree(bus->phy_map[i]);
+ }
+ }
+}
+EXPORT_SYMBOL(mdiobus_unregister);
+
/* mdio_bus_match
*
* description: Given a PHY device, and a PHY driver, return 1 if
@@ -96,4 +170,7 @@ int __init mdio_bus_init(void)
return bus_register(&mdio_bus_type);
}
-
+void __exit mdio_bus_exit(void)
+{
+ bus_unregister(&mdio_bus_type);
+}