aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2013-04-06 21:09:48 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-08 16:55:26 -0400
commit779d835e7eee114f9bfdf7401d1efcf2d53baccf (patch)
tree3bf252e7d10f8bd8b86de41a4ee61abdeb597d46 /drivers/of
parent3d604da1e9547c09c9dcc0ee443c306c9ae1a480 (diff)
net: of_mdio: scan mdiobus for PHYs without reg property
Using DT for mdiobus and ethernet-phy requires to know the PHY address, which is hard to guess if you don't know it. This patch extends of_mdiobus_register to scan mdiobus for PHYs if reg property of the corresponding node is not set. This also allows to have phy nodes in SoC DT files where the reg property can be overwritten in the board file later. To encourage people to finally set the actual phy address, the mdiobus scan is noisier than required. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/of_mdio.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index e3a8b22ef9dd..23049aeca662 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -34,7 +34,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
34{ 34{
35 struct phy_device *phy; 35 struct phy_device *phy;
36 struct device_node *child; 36 struct device_node *child;
37 int rc, i; 37 const __be32 *paddr;
38 u32 addr;
39 bool is_c45, scanphys = false;
40 int rc, i, len;
38 41
39 /* Mask out all PHYs from auto probing. Instead the PHYs listed in 42 /* Mask out all PHYs from auto probing. Instead the PHYs listed in
40 * the device tree are populated after the bus has been registered */ 43 * the device tree are populated after the bus has been registered */
@@ -54,14 +57,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
54 57
55 /* Loop over the child nodes and register a phy_device for each one */ 58 /* Loop over the child nodes and register a phy_device for each one */
56 for_each_available_child_of_node(np, child) { 59 for_each_available_child_of_node(np, child) {
57 const __be32 *paddr;
58 u32 addr;
59 int len;
60 bool is_c45;
61
62 /* A PHY must have a reg property in the range [0-31] */ 60 /* A PHY must have a reg property in the range [0-31] */
63 paddr = of_get_property(child, "reg", &len); 61 paddr = of_get_property(child, "reg", &len);
64 if (!paddr || len < sizeof(*paddr)) { 62 if (!paddr || len < sizeof(*paddr)) {
63 scanphys = true;
65 dev_err(&mdio->dev, "%s has invalid PHY address\n", 64 dev_err(&mdio->dev, "%s has invalid PHY address\n",
66 child->full_name); 65 child->full_name);
67 continue; 66 continue;
@@ -111,6 +110,59 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
111 child->name, addr); 110 child->name, addr);
112 } 111 }
113 112
113 if (!scanphys)
114 return 0;
115
116 /* auto scan for PHYs with empty reg property */
117 for_each_available_child_of_node(np, child) {
118 /* Skip PHYs with reg property set */
119 paddr = of_get_property(child, "reg", &len);
120 if (paddr)
121 continue;
122
123 is_c45 = of_device_is_compatible(child,
124 "ethernet-phy-ieee802.3-c45");
125
126 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
127 /* skip already registered PHYs */
128 if (mdio->phy_map[addr])
129 continue;
130
131 /* be noisy to encourage people to set reg property */
132 dev_info(&mdio->dev, "scan phy %s at address %i\n",
133 child->name, addr);
134
135 phy = get_phy_device(mdio, addr, is_c45);
136 if (!phy || IS_ERR(phy))
137 continue;
138
139 if (mdio->irq) {
140 mdio->irq[addr] =
141 irq_of_parse_and_map(child, 0);
142 if (!mdio->irq[addr])
143 mdio->irq[addr] = PHY_POLL;
144 }
145
146 /* Associate the OF node with the device structure so it
147 * can be looked up later */
148 of_node_get(child);
149 phy->dev.of_node = child;
150
151 /* All data is now stored in the phy struct;
152 * register it */
153 rc = phy_device_register(phy);
154 if (rc) {
155 phy_device_free(phy);
156 of_node_put(child);
157 continue;
158 }
159
160 dev_info(&mdio->dev, "registered phy %s at address %i\n",
161 child->name, addr);
162 break;
163 }
164 }
165
114 return 0; 166 return 0;
115} 167}
116EXPORT_SYMBOL(of_mdiobus_register); 168EXPORT_SYMBOL(of_mdiobus_register);