diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2009-04-25 08:52:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-27 05:53:46 -0400 |
commit | fa94f6d93c5382810ff41f010f12ca8698fc775e (patch) | |
tree | 177e38a91f53221e0b15f8b5ed6b0ae66f6ffc52 | |
parent | 4dea547fef1ba23f9d23f5e7f5218187a7dcf1b3 (diff) |
phylib: add *_direct() variants of phy_connect and phy_attach functions
Add phy_connect_direct() and phy_attach_direct() functions so that
drivers can use a pointer to the phy_device instead of trying to determine
the phy's bus_id string.
This patch is useful for OF device tree descriptions of phy devices where
the driver doesn't need or know what the bus_id value in order to get a
phy_device pointer.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/phy_device.c | 118 | ||||
-rw-r--r-- | include/linux/phy.h | 5 |
2 files changed, 90 insertions, 33 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9352ca8fa2cc..a2ece89622d6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -292,6 +292,33 @@ void phy_prepare_link(struct phy_device *phydev, | |||
292 | } | 292 | } |
293 | 293 | ||
294 | /** | 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 | */ | ||
302 | int 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 | } | ||
319 | EXPORT_SYMBOL(phy_connect_direct); | ||
320 | |||
321 | /** | ||
295 | * phy_connect - connect an ethernet device to a PHY device | 322 | * phy_connect - connect an ethernet device to a PHY device |
296 | * @dev: the network device to connect | 323 | * @dev: the network device to connect |
297 | * @bus_id: the id string of the PHY device to connect | 324 | * @bus_id: the id string of the PHY device to connect |
@@ -312,18 +339,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, | |||
312 | phy_interface_t interface) | 339 | phy_interface_t interface) |
313 | { | 340 | { |
314 | struct phy_device *phydev; | 341 | struct phy_device *phydev; |
342 | struct device *d; | ||
343 | int rc; | ||
315 | 344 | ||
316 | phydev = phy_attach(dev, bus_id, flags, interface); | 345 | /* Search the list of PHY devices on the mdio bus for the |
317 | 346 | * PHY with the requested name */ | |
318 | if (IS_ERR(phydev)) | 347 | d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); |
319 | return phydev; | 348 | if (!d) { |
320 | 349 | pr_err("PHY %s not found\n", bus_id); | |
321 | phy_prepare_link(phydev, handler); | 350 | return ERR_PTR(-ENODEV); |
322 | 351 | } | |
323 | phy_start_machine(phydev, NULL); | 352 | phydev = to_phy_device(d); |
324 | 353 | ||
325 | if (phydev->irq > 0) | 354 | rc = phy_connect_direct(dev, phydev, handler, flags, interface); |
326 | phy_start_interrupts(phydev); | 355 | if (rc) |
356 | return ERR_PTR(rc); | ||
327 | 357 | ||
328 | return phydev; | 358 | return phydev; |
329 | } | 359 | } |
@@ -347,9 +377,9 @@ void phy_disconnect(struct phy_device *phydev) | |||
347 | EXPORT_SYMBOL(phy_disconnect); | 377 | EXPORT_SYMBOL(phy_disconnect); |
348 | 378 | ||
349 | /** | 379 | /** |
350 | * 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 |
351 | * @dev: network device to attach | 381 | * @dev: network device to attach |
352 | * @bus_id: PHY device to attach | 382 | * @phydev: Pointer to phy_device to attach |
353 | * @flags: PHY device's dev_flags | 383 | * @flags: PHY device's dev_flags |
354 | * @interface: PHY device's interface | 384 | * @interface: PHY device's interface |
355 | * | 385 | * |
@@ -360,22 +390,10 @@ EXPORT_SYMBOL(phy_disconnect); | |||
360 | * the attaching device, and given a callback for link status | 390 | * the attaching device, and given a callback for link status |
361 | * change. The phy_device is returned to the attaching driver. | 391 | * change. The phy_device is returned to the attaching driver. |
362 | */ | 392 | */ |
363 | struct phy_device *phy_attach(struct net_device *dev, | 393 | int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, |
364 | const char *bus_id, u32 flags, phy_interface_t interface) | 394 | u32 flags, phy_interface_t interface) |
365 | { | 395 | { |
366 | struct bus_type *bus = &mdio_bus_type; | 396 | struct device *d = &phydev->dev; |
367 | struct phy_device *phydev; | ||
368 | struct device *d; | ||
369 | |||
370 | /* Search the list of PHY devices on the mdio bus for the | ||
371 | * PHY with the requested name */ | ||
372 | d = bus_find_device_by_name(bus, NULL, bus_id); | ||
373 | if (d) { | ||
374 | phydev = to_phy_device(d); | ||
375 | } else { | ||
376 | printk(KERN_ERR "%s not found\n", bus_id); | ||
377 | return ERR_PTR(-ENODEV); | ||
378 | } | ||
379 | 397 | ||
380 | /* Assume that if there is no driver, that it doesn't | 398 | /* Assume that if there is no driver, that it doesn't |
381 | * exist, and we should use the genphy driver. */ | 399 | * exist, and we should use the genphy driver. */ |
@@ -388,13 +406,12 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
388 | err = device_bind_driver(d); | 406 | err = device_bind_driver(d); |
389 | 407 | ||
390 | if (err) | 408 | if (err) |
391 | return ERR_PTR(err); | 409 | return err; |
392 | } | 410 | } |
393 | 411 | ||
394 | if (phydev->attached_dev) { | 412 | if (phydev->attached_dev) { |
395 | printk(KERN_ERR "%s: %s already attached\n", | 413 | dev_err(&dev->dev, "PHY already attached\n"); |
396 | dev->name, bus_id); | 414 | return -EBUSY; |
397 | return ERR_PTR(-EBUSY); | ||
398 | } | 415 | } |
399 | 416 | ||
400 | phydev->attached_dev = dev; | 417 | phydev->attached_dev = dev; |
@@ -412,13 +429,48 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
412 | err = phy_scan_fixups(phydev); | 429 | err = phy_scan_fixups(phydev); |
413 | 430 | ||
414 | if (err < 0) | 431 | if (err < 0) |
415 | return ERR_PTR(err); | 432 | return err; |
416 | 433 | ||
417 | err = phydev->drv->config_init(phydev); | 434 | err = phydev->drv->config_init(phydev); |
418 | 435 | ||
419 | if (err < 0) | 436 | if (err < 0) |
420 | return ERR_PTR(err); | 437 | return err; |
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | EXPORT_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 | */ | ||
454 | struct 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); | ||
421 | } | 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); | ||
422 | 474 | ||
423 | return phydev; | 475 | return phydev; |
424 | } | 476 | } |
diff --git a/include/linux/phy.h b/include/linux/phy.h index bf0b5f112dc7..c216e4e503b3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -447,8 +447,13 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); | |||
447 | int phy_device_register(struct phy_device *phy); | 447 | int phy_device_register(struct phy_device *phy); |
448 | int phy_clear_interrupt(struct phy_device *phydev); | 448 | int phy_clear_interrupt(struct phy_device *phydev); |
449 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); | 449 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); |
450 | int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, | ||
451 | u32 flags, phy_interface_t interface); | ||
450 | struct phy_device * phy_attach(struct net_device *dev, | 452 | struct phy_device * phy_attach(struct net_device *dev, |
451 | const char *bus_id, u32 flags, phy_interface_t interface); | 453 | const char *bus_id, u32 flags, phy_interface_t interface); |
454 | int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, | ||
455 | void (*handler)(struct net_device *), u32 flags, | ||
456 | phy_interface_t interface); | ||
452 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, | 457 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, |
453 | void (*handler)(struct net_device *), u32 flags, | 458 | void (*handler)(struct net_device *), u32 flags, |
454 | phy_interface_t interface); | 459 | phy_interface_t interface); |