1
2
3
4
5
6
7
8
9
10
11
12#include <linux/kernel.h>
13#include <linux/device.h>
14#include <linux/netdevice.h>
15#include <linux/err.h>
16#include <linux/phy.h>
17#include <linux/phy_fixed.h>
18#include <linux/of.h>
19#include <linux/of_irq.h>
20#include <linux/of_mdio.h>
21#include <linux/of_net.h>
22#include <linux/module.h>
23
24#define DEFAULT_GPIO_RESET_DELAY 10
25
26MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
27MODULE_LICENSE("GPL");
28
29
30
31static int of_get_phy_id(struct device_node *device, u32 *phy_id)
32{
33 struct property *prop;
34 const char *cp;
35 unsigned int upper, lower;
36
37 of_property_for_each_string(device, "compatible", prop, cp) {
38 if (sscanf(cp, "ethernet-phy-id%4x.%4x", &upper, &lower) == 2) {
39 *phy_id = ((upper & 0xFFFF) << 16) | (lower & 0xFFFF);
40 return 0;
41 }
42 }
43 return -EINVAL;
44}
45
46static struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
47{
48 struct of_phandle_args arg;
49 int err;
50
51 err = of_parse_phandle_with_fixed_args(node, "timestamper", 1, 0, &arg);
52
53 if (err == -ENOENT)
54 return NULL;
55 else if (err)
56 return ERR_PTR(err);
57
58 if (arg.args_count != 1)
59 return ERR_PTR(-EINVAL);
60
61 return register_mii_timestamper(arg.np, arg.args[0]);
62}
63
64static int of_mdiobus_register_phy(struct mii_bus *mdio,
65 struct device_node *child, u32 addr)
66{
67 struct mii_timestamper *mii_ts;
68 struct phy_device *phy;
69 bool is_c45;
70 int rc;
71 u32 phy_id;
72
73 mii_ts = of_find_mii_timestamper(child);
74 if (IS_ERR(mii_ts))
75 return PTR_ERR(mii_ts);
76
77 is_c45 = of_device_is_compatible(child,
78 "ethernet-phy-ieee802.3-c45");
79
80 if (!is_c45 && !of_get_phy_id(child, &phy_id))
81 phy = phy_device_create(mdio, addr, phy_id, 0, NULL);
82 else
83 phy = get_phy_device(mdio, addr, is_c45);
84 if (IS_ERR(phy)) {
85 if (mii_ts)
86 unregister_mii_timestamper(mii_ts);
87 return PTR_ERR(phy);
88 }
89
90 rc = of_irq_get(child, 0);
91 if (rc == -EPROBE_DEFER) {
92 if (mii_ts)
93 unregister_mii_timestamper(mii_ts);
94 phy_device_free(phy);
95 return rc;
96 }
97 if (rc > 0) {
98 phy->irq = rc;
99 mdio->irq[addr] = rc;
100 } else {
101 phy->irq = mdio->irq[addr];
102 }
103
104 if (of_property_read_bool(child, "broken-turn-around"))
105 mdio->phy_ignore_ta_mask |= 1 << addr;
106
107 of_property_read_u32(child, "reset-assert-us",
108 &phy->mdio.reset_assert_delay);
109 of_property_read_u32(child, "reset-deassert-us",
110 &phy->mdio.reset_deassert_delay);
111
112
113
114 of_node_get(child);
115 phy->mdio.dev.of_node = child;
116 phy->mdio.dev.fwnode = of_fwnode_handle(child);
117
118
119
120 rc = phy_device_register(phy);
121 if (rc) {
122 if (mii_ts)
123 unregister_mii_timestamper(mii_ts);
124 phy_device_free(phy);
125 of_node_put(child);
126 return rc;
127 }
128
129
130
131
132
133 if (mii_ts)
134 phy->mii_ts = mii_ts;
135
136 dev_dbg(&mdio->dev, "registered phy %pOFn at address %i\n",
137 child, addr);
138 return 0;
139}
140
141static int of_mdiobus_register_device(struct mii_bus *mdio,
142 struct device_node *child, u32 addr)
143{
144 struct mdio_device *mdiodev;
145 int rc;
146
147 mdiodev = mdio_device_create(mdio, addr);
148 if (IS_ERR(mdiodev))
149 return PTR_ERR(mdiodev);
150
151
152
153
154 of_node_get(child);
155 mdiodev->dev.of_node = child;
156 mdiodev->dev.fwnode = of_fwnode_handle(child);
157
158
159 rc = mdio_device_register(mdiodev);
160 if (rc) {
161 mdio_device_free(mdiodev);
162 of_node_put(child);
163 return rc;
164 }
165
166 dev_dbg(&mdio->dev, "registered mdio device %pOFn at address %i\n",
167 child, addr);
168 return 0;
169}
170
171
172
173
174
175
176
177static const struct of_device_id whitelist_phys[] = {
178 { .compatible = "brcm,40nm-ephy" },
179 { .compatible = "broadcom,bcm5241" },
180 { .compatible = "marvell,88E1111", },
181 { .compatible = "marvell,88e1116", },
182 { .compatible = "marvell,88e1118", },
183 { .compatible = "marvell,88e1145", },
184 { .compatible = "marvell,88e1149r", },
185 { .compatible = "marvell,88e1310", },
186 { .compatible = "marvell,88E1510", },
187 { .compatible = "marvell,88E1514", },
188 { .compatible = "moxa,moxart-rtl8201cp", },
189 {}
190};
191
192
193
194
195
196
197
198
199
200
201
202
203bool of_mdiobus_child_is_phy(struct device_node *child)
204{
205 u32 phy_id;
206
207 if (of_get_phy_id(child, &phy_id) != -EINVAL)
208 return true;
209
210 if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"))
211 return true;
212
213 if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22"))
214 return true;
215
216 if (of_match_node(whitelist_phys, child)) {
217 pr_warn(FW_WARN
218 "%pOF: Whitelisted compatible string. Please remove\n",
219 child);
220 return true;
221 }
222
223 if (!of_find_property(child, "compatible", NULL))
224 return true;
225
226 return false;
227}
228EXPORT_SYMBOL(of_mdiobus_child_is_phy);
229
230
231
232
233
234
235
236
237
238int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
239{
240 struct device_node *child;
241 bool scanphys = false;
242 int addr, rc;
243
244 if (!np)
245 return mdiobus_register(mdio);
246
247
248 if (!of_device_is_available(np))
249 return -ENODEV;
250
251
252
253 mdio->phy_mask = ~0;
254
255 mdio->dev.of_node = np;
256 mdio->dev.fwnode = of_fwnode_handle(np);
257
258
259 mdio->reset_delay_us = DEFAULT_GPIO_RESET_DELAY;
260 of_property_read_u32(np, "reset-delay-us", &mdio->reset_delay_us);
261
262
263 rc = mdiobus_register(mdio);
264 if (rc)
265 return rc;
266
267
268 for_each_available_child_of_node(np, child) {
269 addr = of_mdio_parse_addr(&mdio->dev, child);
270 if (addr < 0) {
271 scanphys = true;
272 continue;
273 }
274
275 if (of_mdiobus_child_is_phy(child))
276 rc = of_mdiobus_register_phy(mdio, child, addr);
277 else
278 rc = of_mdiobus_register_device(mdio, child, addr);
279
280 if (rc == -ENODEV)
281 dev_err(&mdio->dev,
282 "MDIO device at address %d is missing.\n",
283 addr);
284 else if (rc)
285 goto unregister;
286 }
287
288 if (!scanphys)
289 return 0;
290
291
292 for_each_available_child_of_node(np, child) {
293
294 if (of_find_property(child, "reg", NULL))
295 continue;
296
297 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
298
299 if (mdiobus_is_registered_device(mdio, addr))
300 continue;
301
302
303 dev_info(&mdio->dev, "scan phy %pOFn at address %i\n",
304 child, addr);
305
306 if (of_mdiobus_child_is_phy(child)) {
307 rc = of_mdiobus_register_phy(mdio, child, addr);
308 if (rc && rc != -ENODEV)
309 goto unregister;
310 break;
311 }
312 }
313 }
314
315 return 0;
316
317unregister:
318 mdiobus_unregister(mdio);
319 return rc;
320}
321EXPORT_SYMBOL(of_mdiobus_register);
322
323
324
325
326
327
328
329
330struct phy_device *of_phy_find_device(struct device_node *phy_np)
331{
332 struct device *d;
333 struct mdio_device *mdiodev;
334
335 if (!phy_np)
336 return NULL;
337
338 d = bus_find_device_by_of_node(&mdio_bus_type, phy_np);
339 if (d) {
340 mdiodev = to_mdio_device(d);
341 if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
342 return to_phy_device(d);
343 put_device(d);
344 }
345
346 return NULL;
347}
348EXPORT_SYMBOL(of_phy_find_device);
349
350
351
352
353
354
355
356
357
358
359
360
361
362struct phy_device *of_phy_connect(struct net_device *dev,
363 struct device_node *phy_np,
364 void (*hndlr)(struct net_device *), u32 flags,
365 phy_interface_t iface)
366{
367 struct phy_device *phy = of_phy_find_device(phy_np);
368 int ret;
369
370 if (!phy)
371 return NULL;
372
373 phy->dev_flags = flags;
374
375 ret = phy_connect_direct(dev, phy, hndlr, iface);
376
377
378 put_device(&phy->mdio.dev);
379
380 return ret ? NULL : phy;
381}
382EXPORT_SYMBOL(of_phy_connect);
383
384
385
386
387
388
389
390
391
392
393
394
395struct phy_device *of_phy_get_and_connect(struct net_device *dev,
396 struct device_node *np,
397 void (*hndlr)(struct net_device *))
398{
399 phy_interface_t iface;
400 struct device_node *phy_np;
401 struct phy_device *phy;
402 int ret;
403
404 iface = of_get_phy_mode(np);
405 if ((int)iface < 0)
406 return NULL;
407 if (of_phy_is_fixed_link(np)) {
408 ret = of_phy_register_fixed_link(np);
409 if (ret < 0) {
410 netdev_err(dev, "broken fixed-link specification\n");
411 return NULL;
412 }
413 phy_np = of_node_get(np);
414 } else {
415 phy_np = of_parse_phandle(np, "phy-handle", 0);
416 if (!phy_np)
417 return NULL;
418 }
419
420 phy = of_phy_connect(dev, phy_np, hndlr, 0, iface);
421
422 of_node_put(phy_np);
423
424 return phy;
425}
426EXPORT_SYMBOL(of_phy_get_and_connect);
427
428
429
430
431
432
433
434
435
436
437
438
439struct phy_device *of_phy_attach(struct net_device *dev,
440 struct device_node *phy_np, u32 flags,
441 phy_interface_t iface)
442{
443 struct phy_device *phy = of_phy_find_device(phy_np);
444 int ret;
445
446 if (!phy)
447 return NULL;
448
449 ret = phy_attach_direct(dev, phy, flags, iface);
450
451
452 put_device(&phy->mdio.dev);
453
454 return ret ? NULL : phy;
455}
456EXPORT_SYMBOL(of_phy_attach);
457
458
459
460
461
462
463
464
465
466bool of_phy_is_fixed_link(struct device_node *np)
467{
468 struct device_node *dn;
469 int len, err;
470 const char *managed;
471
472
473 dn = of_get_child_by_name(np, "fixed-link");
474 if (dn) {
475 of_node_put(dn);
476 return true;
477 }
478
479 err = of_property_read_string(np, "managed", &managed);
480 if (err == 0 && strcmp(managed, "auto") != 0)
481 return true;
482
483
484 if (of_get_property(np, "fixed-link", &len) &&
485 len == (5 * sizeof(__be32)))
486 return true;
487
488 return false;
489}
490EXPORT_SYMBOL(of_phy_is_fixed_link);
491
492int of_phy_register_fixed_link(struct device_node *np)
493{
494 struct fixed_phy_status status = {};
495 struct device_node *fixed_link_node;
496 u32 fixed_link_prop[5];
497 const char *managed;
498
499 if (of_property_read_string(np, "managed", &managed) == 0 &&
500 strcmp(managed, "in-band-status") == 0) {
501
502 goto register_phy;
503 }
504
505
506 fixed_link_node = of_get_child_by_name(np, "fixed-link");
507 if (fixed_link_node) {
508 status.link = 1;
509 status.duplex = of_property_read_bool(fixed_link_node,
510 "full-duplex");
511 if (of_property_read_u32(fixed_link_node, "speed",
512 &status.speed)) {
513 of_node_put(fixed_link_node);
514 return -EINVAL;
515 }
516 status.pause = of_property_read_bool(fixed_link_node, "pause");
517 status.asym_pause = of_property_read_bool(fixed_link_node,
518 "asym-pause");
519 of_node_put(fixed_link_node);
520
521 goto register_phy;
522 }
523
524
525 if (of_property_read_u32_array(np, "fixed-link", fixed_link_prop,
526 ARRAY_SIZE(fixed_link_prop)) == 0) {
527 status.link = 1;
528 status.duplex = fixed_link_prop[1];
529 status.speed = fixed_link_prop[2];
530 status.pause = fixed_link_prop[3];
531 status.asym_pause = fixed_link_prop[4];
532 goto register_phy;
533 }
534
535 return -ENODEV;
536
537register_phy:
538 return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, np));
539}
540EXPORT_SYMBOL(of_phy_register_fixed_link);
541
542void of_phy_deregister_fixed_link(struct device_node *np)
543{
544 struct phy_device *phydev;
545
546 phydev = of_phy_find_device(np);
547 if (!phydev)
548 return;
549
550 fixed_phy_unregister(phydev);
551
552 put_device(&phydev->mdio.dev);
553 phy_device_free(phydev);
554}
555EXPORT_SYMBOL(of_phy_deregister_fixed_link);
556