aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c163
1 files changed, 126 insertions, 37 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0a06e4fd37d9..a2ece89622d6 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -39,20 +39,21 @@ MODULE_DESCRIPTION("PHY library");
39MODULE_AUTHOR("Andy Fleming"); 39MODULE_AUTHOR("Andy Fleming");
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41 41
42static struct phy_driver genphy_driver;
43extern int mdio_bus_init(void);
44extern void mdio_bus_exit(void);
45
46void phy_device_free(struct phy_device *phydev) 42void phy_device_free(struct phy_device *phydev)
47{ 43{
48 kfree(phydev); 44 kfree(phydev);
49} 45}
46EXPORT_SYMBOL(phy_device_free);
50 47
51static void phy_device_release(struct device *dev) 48static void phy_device_release(struct device *dev)
52{ 49{
53 phy_device_free(to_phy_device(dev)); 50 phy_device_free(to_phy_device(dev));
54} 51}
55 52
53static struct phy_driver genphy_driver;
54extern int mdio_bus_init(void);
55extern void mdio_bus_exit(void);
56
56static LIST_HEAD(phy_fixup_list); 57static LIST_HEAD(phy_fixup_list);
57static DEFINE_MUTEX(phy_fixup_lock); 58static DEFINE_MUTEX(phy_fixup_lock);
58 59
@@ -166,6 +167,10 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
166 dev->addr = addr; 167 dev->addr = addr;
167 dev->phy_id = phy_id; 168 dev->phy_id = phy_id;
168 dev->bus = bus; 169 dev->bus = bus;
170 dev->dev.parent = bus->parent;
171 dev->dev.bus = &mdio_bus_type;
172 dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
173 dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
169 174
170 dev->state = PHY_DOWN; 175 dev->state = PHY_DOWN;
171 176
@@ -235,6 +240,38 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
235 240
236 return dev; 241 return dev;
237} 242}
243EXPORT_SYMBOL(get_phy_device);
244
245/**
246 * phy_device_register - Register the phy device on the MDIO bus
247 * @phy_device: phy_device structure to be added to the MDIO bus
248 */
249int phy_device_register(struct phy_device *phydev)
250{
251 int err;
252
253 /* Don't register a phy if one is already registered at this
254 * address */
255 if (phydev->bus->phy_map[phydev->addr])
256 return -EINVAL;
257 phydev->bus->phy_map[phydev->addr] = phydev;
258
259 /* Run all of the fixups for this PHY */
260 phy_scan_fixups(phydev);
261
262 err = device_register(&phydev->dev);
263 if (err) {
264 pr_err("phy %d failed to register\n", phydev->addr);
265 goto out;
266 }
267
268 return 0;
269
270 out:
271 phydev->bus->phy_map[phydev->addr] = NULL;
272 return err;
273}
274EXPORT_SYMBOL(phy_device_register);
238 275
239/** 276/**
240 * phy_prepare_link - prepares the PHY layer to monitor link status 277 * phy_prepare_link - prepares the PHY layer to monitor link status
@@ -255,6 +292,33 @@ void phy_prepare_link(struct phy_device *phydev,
255} 292}
256 293
257/** 294/**
295 * phy_connect_direct - connect an ethernet device to a specific phy_device
296 * @dev: the network device to connect
297 * @phydev: the pointer to the phy device
298 * @handler: callback function for state change notifications
299 * @flags: PHY device's dev_flags
300 * @interface: PHY device's interface
301 */
302int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
303 void (*handler)(struct net_device *), u32 flags,
304 phy_interface_t interface)
305{
306 int rc;
307
308 rc = phy_attach_direct(dev, phydev, flags, interface);
309 if (rc)
310 return rc;
311
312 phy_prepare_link(phydev, handler);
313 phy_start_machine(phydev, NULL);
314 if (phydev->irq > 0)
315 phy_start_interrupts(phydev);
316
317 return 0;
318}
319EXPORT_SYMBOL(phy_connect_direct);
320
321/**
258 * phy_connect - connect an ethernet device to a PHY device 322 * phy_connect - connect an ethernet device to a PHY device
259 * @dev: the network device to connect 323 * @dev: the network device to connect
260 * @bus_id: the id string of the PHY device to connect 324 * @bus_id: the id string of the PHY device to connect
@@ -275,18 +339,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
275 phy_interface_t interface) 339 phy_interface_t interface)
276{ 340{
277 struct phy_device *phydev; 341 struct phy_device *phydev;
342 struct device *d;
343 int rc;
278 344
279 phydev = phy_attach(dev, bus_id, flags, interface); 345 /* Search the list of PHY devices on the mdio bus for the
280 346 * PHY with the requested name */
281 if (IS_ERR(phydev)) 347 d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);
282 return phydev; 348 if (!d) {
283 349 pr_err("PHY %s not found\n", bus_id);
284 phy_prepare_link(phydev, handler); 350 return ERR_PTR(-ENODEV);
285 351 }
286 phy_start_machine(phydev, NULL); 352 phydev = to_phy_device(d);
287 353
288 if (phydev->irq > 0) 354 rc = phy_connect_direct(dev, phydev, handler, flags, interface);
289 phy_start_interrupts(phydev); 355 if (rc)
356 return ERR_PTR(rc);
290 357
291 return phydev; 358 return phydev;
292} 359}
@@ -310,9 +377,9 @@ void phy_disconnect(struct phy_device *phydev)
310EXPORT_SYMBOL(phy_disconnect); 377EXPORT_SYMBOL(phy_disconnect);
311 378
312/** 379/**
313 * phy_attach - attach a network device to a particular PHY device 380 * phy_attach_direct - attach a network device to a given PHY device pointer
314 * @dev: network device to attach 381 * @dev: network device to attach
315 * @bus_id: PHY device to attach 382 * @phydev: Pointer to phy_device to attach
316 * @flags: PHY device's dev_flags 383 * @flags: PHY device's dev_flags
317 * @interface: PHY device's interface 384 * @interface: PHY device's interface
318 * 385 *
@@ -323,22 +390,10 @@ EXPORT_SYMBOL(phy_disconnect);
323 * the attaching device, and given a callback for link status 390 * the attaching device, and given a callback for link status
324 * change. The phy_device is returned to the attaching driver. 391 * change. The phy_device is returned to the attaching driver.
325 */ 392 */
326struct phy_device *phy_attach(struct net_device *dev, 393int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
327 const char *bus_id, u32 flags, phy_interface_t interface) 394 u32 flags, phy_interface_t interface)
328{ 395{
329 struct bus_type *bus = &mdio_bus_type; 396 struct device *d = &phydev->dev;
330 struct phy_device *phydev;
331 struct device *d;
332
333 /* Search the list of PHY devices on the mdio bus for the
334 * PHY with the requested name */
335 d = bus_find_device_by_name(bus, NULL, bus_id);
336 if (d) {
337 phydev = to_phy_device(d);
338 } else {
339 printk(KERN_ERR "%s not found\n", bus_id);
340 return ERR_PTR(-ENODEV);
341 }
342 397
343 /* Assume that if there is no driver, that it doesn't 398 /* Assume that if there is no driver, that it doesn't
344 * exist, and we should use the genphy driver. */ 399 * exist, and we should use the genphy driver. */
@@ -351,13 +406,12 @@ struct phy_device *phy_attach(struct net_device *dev,
351 err = device_bind_driver(d); 406 err = device_bind_driver(d);
352 407
353 if (err) 408 if (err)
354 return ERR_PTR(err); 409 return err;
355 } 410 }
356 411
357 if (phydev->attached_dev) { 412 if (phydev->attached_dev) {
358 printk(KERN_ERR "%s: %s already attached\n", 413 dev_err(&dev->dev, "PHY already attached\n");
359 dev->name, bus_id); 414 return -EBUSY;
360 return ERR_PTR(-EBUSY);
361 } 415 }
362 416
363 phydev->attached_dev = dev; 417 phydev->attached_dev = dev;
@@ -375,14 +429,49 @@ struct phy_device *phy_attach(struct net_device *dev,
375 err = phy_scan_fixups(phydev); 429 err = phy_scan_fixups(phydev);
376 430
377 if (err < 0) 431 if (err < 0)
378 return ERR_PTR(err); 432 return err;
379 433
380 err = phydev->drv->config_init(phydev); 434 err = phydev->drv->config_init(phydev);
381 435
382 if (err < 0) 436 if (err < 0)
383 return ERR_PTR(err); 437 return err;
384 } 438 }
385 439
440 return 0;
441}
442EXPORT_SYMBOL(phy_attach_direct);
443
444/**
445 * phy_attach - attach a network device to a particular PHY device
446 * @dev: network device to attach
447 * @bus_id: Bus ID of PHY device to attach
448 * @flags: PHY device's dev_flags
449 * @interface: PHY device's interface
450 *
451 * Description: Same as phy_attach_direct() except that a PHY bus_id
452 * string is passed instead of a pointer to a struct phy_device.
453 */
454struct phy_device *phy_attach(struct net_device *dev,
455 const char *bus_id, u32 flags, phy_interface_t interface)
456{
457 struct bus_type *bus = &mdio_bus_type;
458 struct phy_device *phydev;
459 struct device *d;
460 int rc;
461
462 /* Search the list of PHY devices on the mdio bus for the
463 * PHY with the requested name */
464 d = bus_find_device_by_name(bus, NULL, bus_id);
465 if (!d) {
466 pr_err("PHY %s not found\n", bus_id);
467 return ERR_PTR(-ENODEV);
468 }
469 phydev = to_phy_device(d);
470
471 rc = phy_attach_direct(dev, phydev, flags, interface);
472 if (rc)
473 return ERR_PTR(rc);
474
386 return phydev; 475 return phydev;
387} 476}
388EXPORT_SYMBOL(phy_attach); 477EXPORT_SYMBOL(phy_attach);