diff options
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r-- | drivers/phy/phy-core.c | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 3791838f4bd4..7d535dbb63ee 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -367,13 +367,21 @@ static struct phy *_of_phy_get(struct device_node *np, int index) | |||
367 | phy_provider = of_phy_provider_lookup(args.np); | 367 | phy_provider = of_phy_provider_lookup(args.np); |
368 | if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { | 368 | if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { |
369 | phy = ERR_PTR(-EPROBE_DEFER); | 369 | phy = ERR_PTR(-EPROBE_DEFER); |
370 | goto err0; | 370 | goto out_unlock; |
371 | } | ||
372 | |||
373 | if (!of_device_is_available(args.np)) { | ||
374 | dev_warn(phy_provider->dev, "Requested PHY is disabled\n"); | ||
375 | phy = ERR_PTR(-ENODEV); | ||
376 | goto out_put_module; | ||
371 | } | 377 | } |
372 | 378 | ||
373 | phy = phy_provider->of_xlate(phy_provider->dev, &args); | 379 | phy = phy_provider->of_xlate(phy_provider->dev, &args); |
380 | |||
381 | out_put_module: | ||
374 | module_put(phy_provider->owner); | 382 | module_put(phy_provider->owner); |
375 | 383 | ||
376 | err0: | 384 | out_unlock: |
377 | mutex_unlock(&phy_provider_mutex); | 385 | mutex_unlock(&phy_provider_mutex); |
378 | of_node_put(args.np); | 386 | of_node_put(args.np); |
379 | 387 | ||
@@ -623,6 +631,38 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | |||
623 | EXPORT_SYMBOL_GPL(devm_of_phy_get); | 631 | EXPORT_SYMBOL_GPL(devm_of_phy_get); |
624 | 632 | ||
625 | /** | 633 | /** |
634 | * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index. | ||
635 | * @dev: device that requests this phy | ||
636 | * @np: node containing the phy | ||
637 | * @index: index of the phy | ||
638 | * | ||
639 | * Gets the phy using _of_phy_get(), and associates a device with it using | ||
640 | * devres. On driver detach, release function is invoked on the devres data, | ||
641 | * then, devres data is freed. | ||
642 | * | ||
643 | */ | ||
644 | struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||
645 | int index) | ||
646 | { | ||
647 | struct phy **ptr, *phy; | ||
648 | |||
649 | ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
650 | if (!ptr) | ||
651 | return ERR_PTR(-ENOMEM); | ||
652 | |||
653 | phy = _of_phy_get(np, index); | ||
654 | if (!IS_ERR(phy)) { | ||
655 | *ptr = phy; | ||
656 | devres_add(dev, ptr); | ||
657 | } else { | ||
658 | devres_free(ptr); | ||
659 | } | ||
660 | |||
661 | return phy; | ||
662 | } | ||
663 | EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); | ||
664 | |||
665 | /** | ||
626 | * phy_create() - create a new phy | 666 | * phy_create() - create a new phy |
627 | * @dev: device that is creating the new phy | 667 | * @dev: device that is creating the new phy |
628 | * @node: device node of the phy | 668 | * @node: device node of the phy |
@@ -651,16 +691,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
651 | goto free_phy; | 691 | goto free_phy; |
652 | } | 692 | } |
653 | 693 | ||
654 | /* phy-supply */ | ||
655 | phy->pwr = regulator_get_optional(dev, "phy"); | ||
656 | if (IS_ERR(phy->pwr)) { | ||
657 | if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) { | ||
658 | ret = -EPROBE_DEFER; | ||
659 | goto free_ida; | ||
660 | } | ||
661 | phy->pwr = NULL; | ||
662 | } | ||
663 | |||
664 | device_initialize(&phy->dev); | 694 | device_initialize(&phy->dev); |
665 | mutex_init(&phy->mutex); | 695 | mutex_init(&phy->mutex); |
666 | 696 | ||
@@ -674,6 +704,16 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
674 | if (ret) | 704 | if (ret) |
675 | goto put_dev; | 705 | goto put_dev; |
676 | 706 | ||
707 | /* phy-supply */ | ||
708 | phy->pwr = regulator_get_optional(&phy->dev, "phy"); | ||
709 | if (IS_ERR(phy->pwr)) { | ||
710 | ret = PTR_ERR(phy->pwr); | ||
711 | if (ret == -EPROBE_DEFER) | ||
712 | goto put_dev; | ||
713 | |||
714 | phy->pwr = NULL; | ||
715 | } | ||
716 | |||
677 | ret = device_add(&phy->dev); | 717 | ret = device_add(&phy->dev); |
678 | if (ret) | 718 | if (ret) |
679 | goto put_dev; | 719 | goto put_dev; |
@@ -689,9 +729,6 @@ put_dev: | |||
689 | put_device(&phy->dev); /* calls phy_release() which frees resources */ | 729 | put_device(&phy->dev); /* calls phy_release() which frees resources */ |
690 | return ERR_PTR(ret); | 730 | return ERR_PTR(ret); |
691 | 731 | ||
692 | free_ida: | ||
693 | ida_simple_remove(&phy_ida, phy->id); | ||
694 | |||
695 | free_phy: | 732 | free_phy: |
696 | kfree(phy); | 733 | kfree(phy); |
697 | return ERR_PTR(ret); | 734 | return ERR_PTR(ret); |