diff --git a/Documentation/driver-api/phy/phy.rst b/Documentation/driver-api/phy/phy.rst index 8e8b3e8f9523..81785c084f3e 100644 --- a/Documentation/driver-api/phy/phy.rst +++ b/Documentation/driver-api/phy/phy.rst @@ -103,27 +103,31 @@ it. This framework provides the following APIs to get a reference to the PHY. :: struct phy *phy_get(struct device *dev, const char *string); - struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); struct phy *devm_phy_optional_get(struct device *dev, const char *string); + struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, + const char *con_id); + struct phy *devm_of_phy_optional_get(struct device *dev, + struct device_node *np, + const char *con_id); struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, int index); -phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can -be used to get the PHY. In the case of dt boot, the string arguments +phy_get, devm_phy_get and devm_phy_optional_get can be used to get the PHY. +In the case of dt boot, the string arguments should contain the phy name as given in the dt data and in the case of non-dt boot, it should contain the label of the PHY. The two devm_phy_get associates the device with the PHY using devres on successful PHY get. On driver detach, release function is invoked on -the devres data and devres data is freed. phy_optional_get and -devm_phy_optional_get should be used when the phy is optional. These -two functions will never return -ENODEV, but instead returns NULL when -the phy cannot be found.Some generic drivers, such as ehci, may use multiple -phys and for such drivers referencing phy(s) by name(s) does not make sense. In -this case, devm_of_phy_get_by_index can be used to get a phy reference based on -the index. +the devres data and devres data is freed. +The _optional_get variants should be used when the phy is optional. These +functions will never return -ENODEV, but instead return NULL when +the phy cannot be found. +Some generic drivers, such as ehci, may use multiple phys. In this case, +devm_of_phy_get or devm_of_phy_get_by_index can be used to get a phy +reference based on name or index. It should be noted that NULL is a valid phy reference. All phy consumer calls on the NULL phy become NOPs. That is the release calls, diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 9349f841bd06..ddd9d13f1166 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -1152,13 +1152,12 @@ int memac_initialization(struct mac_device *mac_dev, else memac->sgmii_pcs = pcs; - memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); - err = PTR_ERR(memac->serdes); - if (err == -ENODEV || err == -ENOSYS) { + memac->serdes = devm_of_phy_optional_get(mac_dev->dev, mac_node, + "serdes"); + if (!memac->serdes) { dev_dbg(mac_dev->dev, "could not get (optional) serdes\n"); - memac->serdes = NULL; } else if (IS_ERR(memac->serdes)) { - dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); + err = PTR_ERR(memac->serdes); goto _return_fm_mac_free; } diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index cadde20505ba..d64a525cdc9e 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -1147,9 +1147,8 @@ static int lan966x_probe(struct platform_device *pdev) lan966x->ports[p]->config.portmode = phy_mode; lan966x->ports[p]->fwnode = fwnode_handle_get(portnp); - serdes = devm_of_phy_get(lan966x->dev, to_of_node(portnp), NULL); - if (PTR_ERR(serdes) == -ENODEV) - serdes = NULL; + serdes = devm_of_phy_optional_get(lan966x->dev, + to_of_node(portnp), NULL); if (IS_ERR(serdes)) { err = PTR_ERR(serdes); goto cleanup_ports; diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 929f9363e94b..5b8907c663e5 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -1330,12 +1330,9 @@ static struct phy *devm_of_phy_optional_get_index(struct device *dev, if (!name) return ERR_PTR(-ENOMEM); - phy = devm_of_phy_get(dev, np, name); + phy = devm_of_phy_optional_get(dev, np, name); kfree(name); - if (PTR_ERR(phy) == -ENODEV) - phy = NULL; - return phy; } diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index d93ddf1262c5..9951efc03eaa 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -766,27 +766,6 @@ struct phy *phy_get(struct device *dev, const char *string) } EXPORT_SYMBOL_GPL(phy_get); -/** - * phy_optional_get() - lookup and obtain a reference to an optional phy. - * @dev: device that requests this phy - * @string: the phy name as given in the dt data or the name of the controller - * port for non-dt case - * - * Returns the phy driver, after getting a refcount to it; or - * NULL if there is no such phy. The caller is responsible for - * calling phy_put() to release that count. - */ -struct phy *phy_optional_get(struct device *dev, const char *string) -{ - struct phy *phy = phy_get(dev, string); - - if (PTR_ERR(phy) == -ENODEV) - phy = NULL; - - return phy; -} -EXPORT_SYMBOL_GPL(phy_optional_get); - /** * devm_phy_get() - lookup and obtain a reference to a phy. * @dev: device that requests this phy @@ -879,6 +858,36 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, } EXPORT_SYMBOL_GPL(devm_of_phy_get); +/** + * devm_of_phy_optional_get() - lookup and obtain a reference to an optional + * phy. + * @dev: device that requests this phy + * @np: node containing the phy + * @con_id: name of the phy from device's point of view + * + * Gets the phy using of_phy_get(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres data, + * then, devres data is freed. This differs to devm_of_phy_get() in + * that if the phy does not exist, it is not considered an error and + * -ENODEV will not be returned. Instead the NULL phy is returned, + * which can be passed to all other phy consumer calls. + */ +struct phy *devm_of_phy_optional_get(struct device *dev, struct device_node *np, + const char *con_id) +{ + struct phy *phy = devm_of_phy_get(dev, np, con_id); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + if (IS_ERR(phy)) + dev_err_probe(dev, PTR_ERR(phy), "failed to get PHY %pOF:%s", + np, con_id); + + return phy; +} +EXPORT_SYMBOL_GPL(devm_of_phy_optional_get); + /** * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index. * @dev: device that requests this phy diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index a333231616f4..47c9f06c3d84 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -80,19 +80,11 @@ static int exynos_ehci_get_phy(struct device *dev, return -EINVAL; } - phy = devm_of_phy_get(dev, child, NULL); + phy = devm_of_phy_optional_get(dev, child, NULL); exynos_ehci->phy[phy_number] = phy; if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - if (ret == -EPROBE_DEFER) { - of_node_put(child); - return ret; - } else if (ret != -ENOSYS && ret != -ENODEV) { - dev_err(dev, - "Error retrieving usb2 phy: %d\n", ret); - of_node_put(child); - return ret; - } + of_node_put(child); + return PTR_ERR(phy); } } @@ -108,12 +100,10 @@ static int exynos_ehci_phy_enable(struct device *dev) int ret = 0; for (i = 0; ret == 0 && i < PHY_NUMBER; i++) - if (!IS_ERR(exynos_ehci->phy[i])) - ret = phy_power_on(exynos_ehci->phy[i]); + ret = phy_power_on(exynos_ehci->phy[i]); if (ret) for (i--; i >= 0; i--) - if (!IS_ERR(exynos_ehci->phy[i])) - phy_power_off(exynos_ehci->phy[i]); + phy_power_off(exynos_ehci->phy[i]); return ret; } @@ -125,8 +115,7 @@ static void exynos_ehci_phy_disable(struct device *dev) int i; for (i = 0; i < PHY_NUMBER; i++) - if (!IS_ERR(exynos_ehci->phy[i])) - phy_power_off(exynos_ehci->phy[i]); + phy_power_off(exynos_ehci->phy[i]); } static void exynos_setup_vbus_gpio(struct device *dev) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 8d7977fd5d3b..8af17c1ee5cc 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -69,19 +69,11 @@ static int exynos_ohci_get_phy(struct device *dev, return -EINVAL; } - phy = devm_of_phy_get(dev, child, NULL); + phy = devm_of_phy_optional_get(dev, child, NULL); exynos_ohci->phy[phy_number] = phy; if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - if (ret == -EPROBE_DEFER) { - of_node_put(child); - return ret; - } else if (ret != -ENOSYS && ret != -ENODEV) { - dev_err(dev, - "Error retrieving usb2 phy: %d\n", ret); - of_node_put(child); - return ret; - } + of_node_put(child); + return PTR_ERR(phy); } } @@ -97,12 +89,10 @@ static int exynos_ohci_phy_enable(struct device *dev) int ret = 0; for (i = 0; ret == 0 && i < PHY_NUMBER; i++) - if (!IS_ERR(exynos_ohci->phy[i])) - ret = phy_power_on(exynos_ohci->phy[i]); + ret = phy_power_on(exynos_ohci->phy[i]); if (ret) for (i--; i >= 0; i--) - if (!IS_ERR(exynos_ohci->phy[i])) - phy_power_off(exynos_ohci->phy[i]); + phy_power_off(exynos_ohci->phy[i]); return ret; } @@ -114,8 +104,7 @@ static void exynos_ohci_phy_disable(struct device *dev) int i; for (i = 0; i < PHY_NUMBER; i++) - if (!IS_ERR(exynos_ohci->phy[i])) - phy_power_off(exynos_ohci->phy[i]); + phy_power_off(exynos_ohci->phy[i]); } static int exynos_ohci_probe(struct platform_device *pdev) diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index b1413757fcc3..3a570bc59fc7 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -250,11 +250,12 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) phy->attrs.bus_width = bus_width; } struct phy *phy_get(struct device *dev, const char *string); -struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); struct phy *devm_phy_optional_get(struct device *dev, const char *string); struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, const char *con_id); +struct phy *devm_of_phy_optional_get(struct device *dev, struct device_node *np, + const char *con_id); struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, int index); void of_phy_put(struct phy *phy); @@ -426,12 +427,6 @@ static inline struct phy *phy_get(struct device *dev, const char *string) return ERR_PTR(-ENOSYS); } -static inline struct phy *phy_optional_get(struct device *dev, - const char *string) -{ - return ERR_PTR(-ENOSYS); -} - static inline struct phy *devm_phy_get(struct device *dev, const char *string) { return ERR_PTR(-ENOSYS); @@ -450,6 +445,13 @@ static inline struct phy *devm_of_phy_get(struct device *dev, return ERR_PTR(-ENOSYS); } +static inline struct phy *devm_of_phy_optional_get(struct device *dev, + struct device_node *np, + const char *con_id) +{ + return NULL; +} + static inline struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, int index)