diff options
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r-- | drivers/phy/phy-core.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 6c738376daff..623b71c54b3e 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -274,8 +274,8 @@ int phy_power_off(struct phy *phy) | |||
274 | EXPORT_SYMBOL_GPL(phy_power_off); | 274 | EXPORT_SYMBOL_GPL(phy_power_off); |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * of_phy_get() - lookup and obtain a reference to a phy by phandle | 277 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle |
278 | * @dev: device that requests this phy | 278 | * @np: device_node for which to get the phy |
279 | * @index: the index of the phy | 279 | * @index: the index of the phy |
280 | * | 280 | * |
281 | * Returns the phy associated with the given phandle value, | 281 | * Returns the phy associated with the given phandle value, |
@@ -284,20 +284,17 @@ EXPORT_SYMBOL_GPL(phy_power_off); | |||
284 | * not yet loaded. This function uses of_xlate call back function provided | 284 | * not yet loaded. This function uses of_xlate call back function provided |
285 | * while registering the phy_provider to find the phy instance. | 285 | * while registering the phy_provider to find the phy instance. |
286 | */ | 286 | */ |
287 | static struct phy *of_phy_get(struct device *dev, int index) | 287 | static struct phy *_of_phy_get(struct device_node *np, int index) |
288 | { | 288 | { |
289 | int ret; | 289 | int ret; |
290 | struct phy_provider *phy_provider; | 290 | struct phy_provider *phy_provider; |
291 | struct phy *phy = NULL; | 291 | struct phy *phy = NULL; |
292 | struct of_phandle_args args; | 292 | struct of_phandle_args args; |
293 | 293 | ||
294 | ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", | 294 | ret = of_parse_phandle_with_args(np, "phys", "#phy-cells", |
295 | index, &args); | 295 | index, &args); |
296 | if (ret) { | 296 | if (ret) |
297 | dev_dbg(dev, "failed to get phy in %s node\n", | ||
298 | dev->of_node->full_name); | ||
299 | return ERR_PTR(-ENODEV); | 297 | return ERR_PTR(-ENODEV); |
300 | } | ||
301 | 298 | ||
302 | mutex_lock(&phy_provider_mutex); | 299 | mutex_lock(&phy_provider_mutex); |
303 | phy_provider = of_phy_provider_lookup(args.np); | 300 | phy_provider = of_phy_provider_lookup(args.np); |
@@ -317,6 +314,36 @@ err0: | |||
317 | } | 314 | } |
318 | 315 | ||
319 | /** | 316 | /** |
317 | * of_phy_get() - lookup and obtain a reference to a phy using a device_node. | ||
318 | * @np: device_node for which to get the phy | ||
319 | * @con_id: name of the phy from device's point of view | ||
320 | * | ||
321 | * Returns the phy driver, after getting a refcount to it; or | ||
322 | * -ENODEV if there is no such phy. The caller is responsible for | ||
323 | * calling phy_put() to release that count. | ||
324 | */ | ||
325 | struct phy *of_phy_get(struct device_node *np, const char *con_id) | ||
326 | { | ||
327 | struct phy *phy = NULL; | ||
328 | int index = 0; | ||
329 | |||
330 | if (con_id) | ||
331 | index = of_property_match_string(np, "phy-names", con_id); | ||
332 | |||
333 | phy = _of_phy_get(np, index); | ||
334 | if (IS_ERR(phy)) | ||
335 | return phy; | ||
336 | |||
337 | if (!try_module_get(phy->ops->owner)) | ||
338 | return ERR_PTR(-EPROBE_DEFER); | ||
339 | |||
340 | get_device(&phy->dev); | ||
341 | |||
342 | return phy; | ||
343 | } | ||
344 | EXPORT_SYMBOL_GPL(of_phy_get); | ||
345 | |||
346 | /** | ||
320 | * phy_put() - release the PHY | 347 | * phy_put() - release the PHY |
321 | * @phy: the phy returned by phy_get() | 348 | * @phy: the phy returned by phy_get() |
322 | * | 349 | * |
@@ -407,7 +434,7 @@ struct phy *phy_get(struct device *dev, const char *string) | |||
407 | if (dev->of_node) { | 434 | if (dev->of_node) { |
408 | index = of_property_match_string(dev->of_node, "phy-names", | 435 | index = of_property_match_string(dev->of_node, "phy-names", |
409 | string); | 436 | string); |
410 | phy = of_phy_get(dev, index); | 437 | phy = _of_phy_get(dev->of_node, index); |
411 | } else { | 438 | } else { |
412 | phy = phy_lookup(dev, string); | 439 | phy = phy_lookup(dev, string); |
413 | } | 440 | } |
@@ -499,6 +526,37 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string) | |||
499 | EXPORT_SYMBOL_GPL(devm_phy_optional_get); | 526 | EXPORT_SYMBOL_GPL(devm_phy_optional_get); |
500 | 527 | ||
501 | /** | 528 | /** |
529 | * devm_of_phy_get() - lookup and obtain a reference to a phy. | ||
530 | * @dev: device that requests this phy | ||
531 | * @np: node containing the phy | ||
532 | * @con_id: name of the phy from device's point of view | ||
533 | * | ||
534 | * Gets the phy using of_phy_get(), and associates a device with it using | ||
535 | * devres. On driver detach, release function is invoked on the devres data, | ||
536 | * then, devres data is freed. | ||
537 | */ | ||
538 | struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | ||
539 | const char *con_id) | ||
540 | { | ||
541 | struct phy **ptr, *phy; | ||
542 | |||
543 | ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
544 | if (!ptr) | ||
545 | return ERR_PTR(-ENOMEM); | ||
546 | |||
547 | phy = of_phy_get(np, con_id); | ||
548 | if (!IS_ERR(phy)) { | ||
549 | *ptr = phy; | ||
550 | devres_add(dev, ptr); | ||
551 | } else { | ||
552 | devres_free(ptr); | ||
553 | } | ||
554 | |||
555 | return phy; | ||
556 | } | ||
557 | EXPORT_SYMBOL_GPL(devm_of_phy_get); | ||
558 | |||
559 | /** | ||
502 | * phy_create() - create a new phy | 560 | * phy_create() - create a new phy |
503 | * @dev: device that is creating the new phy | 561 | * @dev: device that is creating the new phy |
504 | * @ops: function pointers for performing phy operations | 562 | * @ops: function pointers for performing phy operations |