diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-08-26 07:08:46 -0400 |
---|---|---|
committer | Lennert Buytenhek <buytenh@marvell.com> | 2008-09-18 23:13:54 -0400 |
commit | 4fd5f812c23c7deee6425f4a318e85c317cd1d6c (patch) | |
tree | c554d67d67921e66516d978afc58878286b02966 | |
parent | 4ff3495a51c7226376d8013c5742d1d5e54876a7 (diff) |
phylib: allow incremental scanning of an mii bus
This patch splits the bus scanning code in mdiobus_register() off
into a separate function, and makes this function available for
calling from external code. This allows incrementally scanning an
mii bus, e.g. as information about which addresses are 'safe' to
scan becomes available.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Acked-by: Andy Fleming <afleming@freescale.com>
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 89 | ||||
-rw-r--r-- | include/linux/phy.h | 2 |
2 files changed, 50 insertions, 41 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 94e0b7ed76f1..e7508c10887c 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -60,49 +60,14 @@ int mdiobus_register(struct mii_bus *bus) | |||
60 | bus->reset(bus); | 60 | bus->reset(bus); |
61 | 61 | ||
62 | for (i = 0; i < PHY_MAX_ADDR; i++) { | 62 | for (i = 0; i < PHY_MAX_ADDR; i++) { |
63 | struct phy_device *phydev; | 63 | bus->phy_map[i] = NULL; |
64 | if ((bus->phy_mask & (1 << i)) == 0) { | ||
65 | struct phy_device *phydev; | ||
64 | 66 | ||
65 | if (bus->phy_mask & (1 << i)) { | 67 | phydev = mdiobus_scan(bus, i); |
66 | bus->phy_map[i] = NULL; | 68 | if (IS_ERR(phydev)) |
67 | continue; | 69 | err = PTR_ERR(phydev); |
68 | } | 70 | } |
69 | |||
70 | phydev = get_phy_device(bus, i); | ||
71 | |||
72 | if (IS_ERR(phydev)) | ||
73 | return PTR_ERR(phydev); | ||
74 | |||
75 | /* There's a PHY at this address | ||
76 | * We need to set: | ||
77 | * 1) IRQ | ||
78 | * 2) bus_id | ||
79 | * 3) parent | ||
80 | * 4) bus | ||
81 | * 5) mii_bus | ||
82 | * And, we need to register it */ | ||
83 | if (phydev) { | ||
84 | phydev->irq = bus->irq[i]; | ||
85 | |||
86 | phydev->dev.parent = bus->dev; | ||
87 | phydev->dev.bus = &mdio_bus_type; | ||
88 | snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); | ||
89 | |||
90 | phydev->bus = bus; | ||
91 | |||
92 | /* Run all of the fixups for this PHY */ | ||
93 | phy_scan_fixups(phydev); | ||
94 | |||
95 | err = device_register(&phydev->dev); | ||
96 | |||
97 | if (err) { | ||
98 | printk(KERN_ERR "phy %d failed to register\n", | ||
99 | i); | ||
100 | phy_device_free(phydev); | ||
101 | phydev = NULL; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | bus->phy_map[i] = phydev; | ||
106 | } | 71 | } |
107 | 72 | ||
108 | pr_info("%s: probed\n", bus->name); | 73 | pr_info("%s: probed\n", bus->name); |
@@ -122,6 +87,48 @@ void mdiobus_unregister(struct mii_bus *bus) | |||
122 | } | 87 | } |
123 | EXPORT_SYMBOL(mdiobus_unregister); | 88 | EXPORT_SYMBOL(mdiobus_unregister); |
124 | 89 | ||
90 | struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) | ||
91 | { | ||
92 | struct phy_device *phydev; | ||
93 | int err; | ||
94 | |||
95 | phydev = get_phy_device(bus, addr); | ||
96 | if (IS_ERR(phydev) || phydev == NULL) | ||
97 | return phydev; | ||
98 | |||
99 | /* There's a PHY at this address | ||
100 | * We need to set: | ||
101 | * 1) IRQ | ||
102 | * 2) bus_id | ||
103 | * 3) parent | ||
104 | * 4) bus | ||
105 | * 5) mii_bus | ||
106 | * And, we need to register it */ | ||
107 | |||
108 | phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; | ||
109 | |||
110 | phydev->dev.parent = bus->dev; | ||
111 | phydev->dev.bus = &mdio_bus_type; | ||
112 | snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr); | ||
113 | |||
114 | phydev->bus = bus; | ||
115 | |||
116 | /* Run all of the fixups for this PHY */ | ||
117 | phy_scan_fixups(phydev); | ||
118 | |||
119 | err = device_register(&phydev->dev); | ||
120 | if (err) { | ||
121 | printk(KERN_ERR "phy %d failed to register\n", addr); | ||
122 | phy_device_free(phydev); | ||
123 | phydev = NULL; | ||
124 | } | ||
125 | |||
126 | bus->phy_map[addr] = phydev; | ||
127 | |||
128 | return phydev; | ||
129 | } | ||
130 | EXPORT_SYMBOL(mdiobus_scan); | ||
131 | |||
125 | /** | 132 | /** |
126 | * mdio_bus_match - determine if given PHY driver supports the given PHY device | 133 | * mdio_bus_match - determine if given PHY driver supports the given PHY device |
127 | * @dev: target PHY device | 134 | * @dev: target PHY device |
diff --git a/include/linux/phy.h b/include/linux/phy.h index 7224c4099a28..5f170f5b1a30 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -410,6 +410,8 @@ int phy_start_aneg(struct phy_device *phydev); | |||
410 | 410 | ||
411 | int mdiobus_register(struct mii_bus *bus); | 411 | int mdiobus_register(struct mii_bus *bus); |
412 | void mdiobus_unregister(struct mii_bus *bus); | 412 | void mdiobus_unregister(struct mii_bus *bus); |
413 | struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); | ||
414 | |||
413 | void phy_sanitize_settings(struct phy_device *phydev); | 415 | void phy_sanitize_settings(struct phy_device *phydev); |
414 | int phy_stop_interrupts(struct phy_device *phydev); | 416 | int phy_stop_interrupts(struct phy_device *phydev); |
415 | int phy_enable_interrupts(struct phy_device *phydev); | 417 | int phy_enable_interrupts(struct phy_device *phydev); |