[PATCH v3 4/5] phy: core: Add managed phy bulk data helper functions
COOLING8d
From: Inochi Amaoto <inochiama@gmail.com>
Date: 2026-09-23 02:34:17
Also in:
linux-phy, lkml
Subsystem:
generic phy framework, the rest · Maintainers:
Vinod Koul, Linus Torvalds
Revision v3 of 3 in this series.
Revisions (3)
- v2 [diff vs current]
- v3 current
- v4 [diff vs current]
Add device managed variants of the phy bulk helper functions. So the driver can benefit from automatically managed phy handles. Signed-off-by: Inochi Amaoto <inochiama@gmail.com> --- drivers/phy/phy-core.c | 73 +++++++++++++++++++++++++++++++++++++++++ include/linux/phy/phy.h | 19 +++++++++++ 2 files changed, 92 insertions(+)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 5b76c006575b..a588fba33313 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c@@ -1145,6 +1145,79 @@ static void phy_bulk_put_all(struct device *dev, unsigned int num_phys, kfree(phys); } +struct phy_bulk_devres { + struct phy_bulk_data *phys; + unsigned int num_phys; +}; + +static void devm_phy_bulk_release_all(struct device *dev, void *res) +{ + struct phy_bulk_devres *devres = res; + + phy_bulk_put_all(dev, devres->num_phys, devres->phys); +} + +/** + * devm_phy_bulk_get_all() - managed lookup of all PHYs requested by a device + * @dev: device that requests the PHYs + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * The function calls devm_of_phy_bulk_get_all() directly, but sets the + * @np parameter to dev_of_node(dev). + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int devm_phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys) +{ + return devm_of_phy_bulk_get_all(dev, dev_of_node(dev), phys); +} +EXPORT_SYMBOL_GPL(devm_phy_bulk_get_all); + +/** + * devm_of_phy_bulk_get_all() - managed lookup of all PHYs from a device node + * @dev: device that requests the PHYs + * @np: device node containing the PHY references + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * Gets all PHYs from the specified device node, associates the allocated array + * and PHY references with @dev, and creates a device link for each PHY. They + * are automatically released on driver detach. + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int devm_of_phy_bulk_get_all(struct device *dev, struct device_node *np, + struct phy_bulk_data **phys) +{ + struct phy_bulk_devres *devres; + int ret; + + *phys = NULL; + + if (!np) + return 0; + + devres = devres_alloc(devm_phy_bulk_release_all, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret = of_phy_bulk_get_all(np, &devres->phys); + if (ret > 0) { + for (int i = 0; i < ret; i++) + phy_add_device_link(dev, devres->phys[i].phy); + *phys = devres->phys; + devres->num_phys = ret; + devres_add(dev, devres); + } else { + devres_free(devres); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_phy_bulk_get_all); + /** * phy_bulk_init() - initialize multiple PHYs * @num_phys: number of entries in the phys array
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 77d9d74682b7..e60e42eb7e0b 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h@@ -322,6 +322,9 @@ void devm_of_phy_provider_unregister(struct device *dev, int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id); void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id); +int devm_phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys); +int devm_of_phy_bulk_get_all(struct device *dev, struct device_node *np, + struct phy_bulk_data **phys); int phy_bulk_init(unsigned int num_phys, struct phy_bulk_data *phys); int phy_bulk_exit(unsigned int num_phys, struct phy_bulk_data *phys); int phy_bulk_power_on(unsigned int num_phys, struct phy_bulk_data *phys);
@@ -511,6 +514,22 @@ static inline struct phy *devm_of_phy_get_by_index(struct device *dev, return ERR_PTR(-ENOSYS); } +static inline int devm_of_phy_bulk_get_all(struct device *dev, + struct device_node *np, + struct phy_bulk_data **phys) +{ + if (phys) + *phys = NULL; + + return 0; +} + +static inline int devm_phy_bulk_get_all(struct device *dev, + struct phy_bulk_data **phys) +{ + return devm_of_phy_bulk_get_all(dev, dev_of_node(dev), phys); +} + static inline int phy_bulk_check_disabled(unsigned int num_phys, struct phy_bulk_data *phys) {
--
2.55.0