xref: /linux/drivers/net/phy/phy_package.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
161dc9caeSHeiner Kallweit // SPDX-License-Identifier: GPL-2.0-or-later
261dc9caeSHeiner Kallweit /*
361dc9caeSHeiner Kallweit  * PHY package support
461dc9caeSHeiner Kallweit  */
561dc9caeSHeiner Kallweit 
661dc9caeSHeiner Kallweit #include <linux/of.h>
761dc9caeSHeiner Kallweit #include <linux/phy.h>
861dc9caeSHeiner Kallweit 
92c8cd978SHeiner Kallweit #include "phylib.h"
10e7f984e9SHeiner Kallweit #include "phylib-internal.h"
112c8cd978SHeiner Kallweit 
12*a4002849SHeiner Kallweit /**
13*a4002849SHeiner Kallweit  * struct phy_package_shared - Shared information in PHY packages
14*a4002849SHeiner Kallweit  * @base_addr: Base PHY address of PHY package used to combine PHYs
15*a4002849SHeiner Kallweit  *   in one package and for offset calculation of phy_package_read/write
16*a4002849SHeiner Kallweit  * @np: Pointer to the Device Node if PHY package defined in DT
17*a4002849SHeiner Kallweit  * @refcnt: Number of PHYs connected to this shared data
18*a4002849SHeiner Kallweit  * @flags: Initialization of PHY package
19*a4002849SHeiner Kallweit  * @priv_size: Size of the shared private data @priv
20*a4002849SHeiner Kallweit  * @priv: Driver private data shared across a PHY package
21*a4002849SHeiner Kallweit  *
22*a4002849SHeiner Kallweit  * Represents a shared structure between different phydev's in the same
23*a4002849SHeiner Kallweit  * package, for example a quad PHY. See phy_package_join() and
24*a4002849SHeiner Kallweit  * phy_package_leave().
25*a4002849SHeiner Kallweit  */
26*a4002849SHeiner Kallweit struct phy_package_shared {
27*a4002849SHeiner Kallweit 	u8 base_addr;
28*a4002849SHeiner Kallweit 	/* With PHY package defined in DT this points to the PHY package node */
29*a4002849SHeiner Kallweit 	struct device_node *np;
30*a4002849SHeiner Kallweit 	refcount_t refcnt;
31*a4002849SHeiner Kallweit 	unsigned long flags;
32*a4002849SHeiner Kallweit 	size_t priv_size;
33*a4002849SHeiner Kallweit 
34*a4002849SHeiner Kallweit 	/* private data pointer */
35*a4002849SHeiner Kallweit 	/* note that this pointer is shared between different phydevs and
36*a4002849SHeiner Kallweit 	 * the user has to take care of appropriate locking. It is allocated
37*a4002849SHeiner Kallweit 	 * and freed automatically by phy_package_join() and
38*a4002849SHeiner Kallweit 	 * phy_package_leave().
39*a4002849SHeiner Kallweit 	 */
40*a4002849SHeiner Kallweit 	void *priv;
41*a4002849SHeiner Kallweit };
42*a4002849SHeiner Kallweit 
phy_package_get_node(struct phy_device * phydev)432c8cd978SHeiner Kallweit struct device_node *phy_package_get_node(struct phy_device *phydev)
442c8cd978SHeiner Kallweit {
452c8cd978SHeiner Kallweit 	return phydev->shared->np;
462c8cd978SHeiner Kallweit }
472c8cd978SHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_get_node);
482c8cd978SHeiner Kallweit 
phy_package_get_priv(struct phy_device * phydev)492c8cd978SHeiner Kallweit void *phy_package_get_priv(struct phy_device *phydev)
502c8cd978SHeiner Kallweit {
512c8cd978SHeiner Kallweit 	return phydev->shared->priv;
522c8cd978SHeiner Kallweit }
532c8cd978SHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_get_priv);
542c8cd978SHeiner Kallweit 
phy_package_address(struct phy_device * phydev,unsigned int addr_offset)55e7f984e9SHeiner Kallweit int phy_package_address(struct phy_device *phydev, unsigned int addr_offset)
56e7f984e9SHeiner Kallweit {
57e7f984e9SHeiner Kallweit 	struct phy_package_shared *shared = phydev->shared;
58e7f984e9SHeiner Kallweit 	u8 base_addr = shared->base_addr;
59e7f984e9SHeiner Kallweit 
60e7f984e9SHeiner Kallweit 	if (addr_offset >= PHY_MAX_ADDR - base_addr)
61e7f984e9SHeiner Kallweit 		return -EIO;
62e7f984e9SHeiner Kallweit 
63e7f984e9SHeiner Kallweit 	/* we know that addr will be in the range 0..31 and thus the
64e7f984e9SHeiner Kallweit 	 * implicit cast to a signed int is not a problem.
65e7f984e9SHeiner Kallweit 	 */
66e7f984e9SHeiner Kallweit 	return base_addr + addr_offset;
67e7f984e9SHeiner Kallweit }
68e7f984e9SHeiner Kallweit 
__phy_package_read(struct phy_device * phydev,unsigned int addr_offset,u32 regnum)69e7f984e9SHeiner Kallweit int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset,
70e7f984e9SHeiner Kallweit 		       u32 regnum)
71e7f984e9SHeiner Kallweit {
72e7f984e9SHeiner Kallweit 	int addr = phy_package_address(phydev, addr_offset);
73e7f984e9SHeiner Kallweit 
74e7f984e9SHeiner Kallweit 	if (addr < 0)
75e7f984e9SHeiner Kallweit 		return addr;
76e7f984e9SHeiner Kallweit 
77e7f984e9SHeiner Kallweit 	return __mdiobus_read(phydev->mdio.bus, addr, regnum);
78e7f984e9SHeiner Kallweit }
79e7f984e9SHeiner Kallweit EXPORT_SYMBOL_GPL(__phy_package_read);
80e7f984e9SHeiner Kallweit 
__phy_package_write(struct phy_device * phydev,unsigned int addr_offset,u32 regnum,u16 val)81e7f984e9SHeiner Kallweit int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset,
82e7f984e9SHeiner Kallweit 			u32 regnum, u16 val)
83e7f984e9SHeiner Kallweit {
84e7f984e9SHeiner Kallweit 	int addr = phy_package_address(phydev, addr_offset);
85e7f984e9SHeiner Kallweit 
86e7f984e9SHeiner Kallweit 	if (addr < 0)
87e7f984e9SHeiner Kallweit 		return addr;
88e7f984e9SHeiner Kallweit 
89e7f984e9SHeiner Kallweit 	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
90e7f984e9SHeiner Kallweit }
91e7f984e9SHeiner Kallweit EXPORT_SYMBOL_GPL(__phy_package_write);
92e7f984e9SHeiner Kallweit 
__phy_package_set_once(struct phy_device * phydev,unsigned int b)93e7f984e9SHeiner Kallweit static bool __phy_package_set_once(struct phy_device *phydev, unsigned int b)
94e7f984e9SHeiner Kallweit {
95e7f984e9SHeiner Kallweit 	struct phy_package_shared *shared = phydev->shared;
96e7f984e9SHeiner Kallweit 
97e7f984e9SHeiner Kallweit 	if (!shared)
98e7f984e9SHeiner Kallweit 		return false;
99e7f984e9SHeiner Kallweit 
100e7f984e9SHeiner Kallweit 	return !test_and_set_bit(b, &shared->flags);
101e7f984e9SHeiner Kallweit }
102e7f984e9SHeiner Kallweit 
phy_package_init_once(struct phy_device * phydev)103e7f984e9SHeiner Kallweit bool phy_package_init_once(struct phy_device *phydev)
104e7f984e9SHeiner Kallweit {
105e7f984e9SHeiner Kallweit 	return __phy_package_set_once(phydev, 0);
106e7f984e9SHeiner Kallweit }
107e7f984e9SHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_init_once);
108e7f984e9SHeiner Kallweit 
phy_package_probe_once(struct phy_device * phydev)109e7f984e9SHeiner Kallweit bool phy_package_probe_once(struct phy_device *phydev)
110e7f984e9SHeiner Kallweit {
111e7f984e9SHeiner Kallweit 	return __phy_package_set_once(phydev, 1);
112e7f984e9SHeiner Kallweit }
113e7f984e9SHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_probe_once);
114e7f984e9SHeiner Kallweit 
11561dc9caeSHeiner Kallweit /**
11661dc9caeSHeiner Kallweit  * phy_package_join - join a common PHY group
11761dc9caeSHeiner Kallweit  * @phydev: target phy_device struct
11861dc9caeSHeiner Kallweit  * @base_addr: cookie and base PHY address of PHY package for offset
11961dc9caeSHeiner Kallweit  *   calculation of global register access
12061dc9caeSHeiner Kallweit  * @priv_size: if non-zero allocate this amount of bytes for private data
12161dc9caeSHeiner Kallweit  *
12261dc9caeSHeiner Kallweit  * This joins a PHY group and provides a shared storage for all phydevs in
12361dc9caeSHeiner Kallweit  * this group. This is intended to be used for packages which contain
12461dc9caeSHeiner Kallweit  * more than one PHY, for example a quad PHY transceiver.
12561dc9caeSHeiner Kallweit  *
12661dc9caeSHeiner Kallweit  * The base_addr parameter serves as cookie which has to have the same values
12761dc9caeSHeiner Kallweit  * for all members of one group and as the base PHY address of the PHY package
12861dc9caeSHeiner Kallweit  * for offset calculation to access generic registers of a PHY package.
12961dc9caeSHeiner Kallweit  * Usually, one of the PHY addresses of the different PHYs in the package
13061dc9caeSHeiner Kallweit  * provides access to these global registers.
13161dc9caeSHeiner Kallweit  * The address which is given here, will be used in the phy_package_read()
13261dc9caeSHeiner Kallweit  * and phy_package_write() convenience functions as base and added to the
13361dc9caeSHeiner Kallweit  * passed offset in those functions.
13461dc9caeSHeiner Kallweit  *
13561dc9caeSHeiner Kallweit  * This will set the shared pointer of the phydev to the shared storage.
13661dc9caeSHeiner Kallweit  * If this is the first call for a this cookie the shared storage will be
13761dc9caeSHeiner Kallweit  * allocated. If priv_size is non-zero, the given amount of bytes are
13861dc9caeSHeiner Kallweit  * allocated for the priv member.
13961dc9caeSHeiner Kallweit  *
14061dc9caeSHeiner Kallweit  * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
14161dc9caeSHeiner Kallweit  * with the same cookie but a different priv_size is an error.
14261dc9caeSHeiner Kallweit  */
phy_package_join(struct phy_device * phydev,int base_addr,size_t priv_size)14361dc9caeSHeiner Kallweit int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)
14461dc9caeSHeiner Kallweit {
14561dc9caeSHeiner Kallweit 	struct mii_bus *bus = phydev->mdio.bus;
14661dc9caeSHeiner Kallweit 	struct phy_package_shared *shared;
14761dc9caeSHeiner Kallweit 	int ret;
14861dc9caeSHeiner Kallweit 
14961dc9caeSHeiner Kallweit 	if (base_addr < 0 || base_addr >= PHY_MAX_ADDR)
15061dc9caeSHeiner Kallweit 		return -EINVAL;
15161dc9caeSHeiner Kallweit 
15261dc9caeSHeiner Kallweit 	mutex_lock(&bus->shared_lock);
15361dc9caeSHeiner Kallweit 	shared = bus->shared[base_addr];
15461dc9caeSHeiner Kallweit 	if (!shared) {
15561dc9caeSHeiner Kallweit 		ret = -ENOMEM;
15661dc9caeSHeiner Kallweit 		shared = kzalloc(sizeof(*shared), GFP_KERNEL);
15761dc9caeSHeiner Kallweit 		if (!shared)
15861dc9caeSHeiner Kallweit 			goto err_unlock;
15961dc9caeSHeiner Kallweit 		if (priv_size) {
16061dc9caeSHeiner Kallweit 			shared->priv = kzalloc(priv_size, GFP_KERNEL);
16161dc9caeSHeiner Kallweit 			if (!shared->priv)
16261dc9caeSHeiner Kallweit 				goto err_free;
16361dc9caeSHeiner Kallweit 			shared->priv_size = priv_size;
16461dc9caeSHeiner Kallweit 		}
16561dc9caeSHeiner Kallweit 		shared->base_addr = base_addr;
16661dc9caeSHeiner Kallweit 		shared->np = NULL;
16761dc9caeSHeiner Kallweit 		refcount_set(&shared->refcnt, 1);
16861dc9caeSHeiner Kallweit 		bus->shared[base_addr] = shared;
16961dc9caeSHeiner Kallweit 	} else {
17061dc9caeSHeiner Kallweit 		ret = -EINVAL;
17161dc9caeSHeiner Kallweit 		if (priv_size && priv_size != shared->priv_size)
17261dc9caeSHeiner Kallweit 			goto err_unlock;
17361dc9caeSHeiner Kallweit 		refcount_inc(&shared->refcnt);
17461dc9caeSHeiner Kallweit 	}
17561dc9caeSHeiner Kallweit 	mutex_unlock(&bus->shared_lock);
17661dc9caeSHeiner Kallweit 
17761dc9caeSHeiner Kallweit 	phydev->shared = shared;
17861dc9caeSHeiner Kallweit 
17961dc9caeSHeiner Kallweit 	return 0;
18061dc9caeSHeiner Kallweit 
18161dc9caeSHeiner Kallweit err_free:
18261dc9caeSHeiner Kallweit 	kfree(shared);
18361dc9caeSHeiner Kallweit err_unlock:
18461dc9caeSHeiner Kallweit 	mutex_unlock(&bus->shared_lock);
18561dc9caeSHeiner Kallweit 	return ret;
18661dc9caeSHeiner Kallweit }
18761dc9caeSHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_join);
18861dc9caeSHeiner Kallweit 
18961dc9caeSHeiner Kallweit /**
19061dc9caeSHeiner Kallweit  * of_phy_package_join - join a common PHY group in PHY package
19161dc9caeSHeiner Kallweit  * @phydev: target phy_device struct
19261dc9caeSHeiner Kallweit  * @priv_size: if non-zero allocate this amount of bytes for private data
19361dc9caeSHeiner Kallweit  *
19461dc9caeSHeiner Kallweit  * This is a variant of phy_package_join for PHY package defined in DT.
19561dc9caeSHeiner Kallweit  *
19661dc9caeSHeiner Kallweit  * The parent node of the @phydev is checked as a valid PHY package node
19761dc9caeSHeiner Kallweit  * structure (by matching the node name "ethernet-phy-package") and the
19861dc9caeSHeiner Kallweit  * base_addr for the PHY package is passed to phy_package_join.
19961dc9caeSHeiner Kallweit  *
20061dc9caeSHeiner Kallweit  * With this configuration the shared struct will also have the np value
20161dc9caeSHeiner Kallweit  * filled to use additional DT defined properties in PHY specific
20261dc9caeSHeiner Kallweit  * probe_once and config_init_once PHY package OPs.
20361dc9caeSHeiner Kallweit  *
20461dc9caeSHeiner Kallweit  * Returns < 0 on error, 0 on success. Esp. calling phy_package_join()
20561dc9caeSHeiner Kallweit  * with the same cookie but a different priv_size is an error. Or a parent
20661dc9caeSHeiner Kallweit  * node is not detected or is not valid or doesn't match the expected node
20761dc9caeSHeiner Kallweit  * name for PHY package.
20861dc9caeSHeiner Kallweit  */
of_phy_package_join(struct phy_device * phydev,size_t priv_size)20961dc9caeSHeiner Kallweit int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
21061dc9caeSHeiner Kallweit {
21161dc9caeSHeiner Kallweit 	struct device_node *node = phydev->mdio.dev.of_node;
21261dc9caeSHeiner Kallweit 	struct device_node *package_node;
21361dc9caeSHeiner Kallweit 	u32 base_addr;
21461dc9caeSHeiner Kallweit 	int ret;
21561dc9caeSHeiner Kallweit 
21661dc9caeSHeiner Kallweit 	if (!node)
21761dc9caeSHeiner Kallweit 		return -EINVAL;
21861dc9caeSHeiner Kallweit 
21961dc9caeSHeiner Kallweit 	package_node = of_get_parent(node);
22061dc9caeSHeiner Kallweit 	if (!package_node)
22161dc9caeSHeiner Kallweit 		return -EINVAL;
22261dc9caeSHeiner Kallweit 
22361dc9caeSHeiner Kallweit 	if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
22461dc9caeSHeiner Kallweit 		ret = -EINVAL;
22561dc9caeSHeiner Kallweit 		goto exit;
22661dc9caeSHeiner Kallweit 	}
22761dc9caeSHeiner Kallweit 
22861dc9caeSHeiner Kallweit 	if (of_property_read_u32(package_node, "reg", &base_addr)) {
22961dc9caeSHeiner Kallweit 		ret = -EINVAL;
23061dc9caeSHeiner Kallweit 		goto exit;
23161dc9caeSHeiner Kallweit 	}
23261dc9caeSHeiner Kallweit 
23361dc9caeSHeiner Kallweit 	ret = phy_package_join(phydev, base_addr, priv_size);
23461dc9caeSHeiner Kallweit 	if (ret)
23561dc9caeSHeiner Kallweit 		goto exit;
23661dc9caeSHeiner Kallweit 
23761dc9caeSHeiner Kallweit 	phydev->shared->np = package_node;
23861dc9caeSHeiner Kallweit 
23961dc9caeSHeiner Kallweit 	return 0;
24061dc9caeSHeiner Kallweit exit:
24161dc9caeSHeiner Kallweit 	of_node_put(package_node);
24261dc9caeSHeiner Kallweit 	return ret;
24361dc9caeSHeiner Kallweit }
24461dc9caeSHeiner Kallweit EXPORT_SYMBOL_GPL(of_phy_package_join);
24561dc9caeSHeiner Kallweit 
24661dc9caeSHeiner Kallweit /**
24761dc9caeSHeiner Kallweit  * phy_package_leave - leave a common PHY group
24861dc9caeSHeiner Kallweit  * @phydev: target phy_device struct
24961dc9caeSHeiner Kallweit  *
25061dc9caeSHeiner Kallweit  * This leaves a PHY group created by phy_package_join(). If this phydev
25161dc9caeSHeiner Kallweit  * was the last user of the shared data between the group, this data is
25261dc9caeSHeiner Kallweit  * freed. Resets the phydev->shared pointer to NULL.
25361dc9caeSHeiner Kallweit  */
phy_package_leave(struct phy_device * phydev)25461dc9caeSHeiner Kallweit void phy_package_leave(struct phy_device *phydev)
25561dc9caeSHeiner Kallweit {
25661dc9caeSHeiner Kallweit 	struct phy_package_shared *shared = phydev->shared;
25761dc9caeSHeiner Kallweit 	struct mii_bus *bus = phydev->mdio.bus;
25861dc9caeSHeiner Kallweit 
25961dc9caeSHeiner Kallweit 	if (!shared)
26061dc9caeSHeiner Kallweit 		return;
26161dc9caeSHeiner Kallweit 
26261dc9caeSHeiner Kallweit 	/* Decrease the node refcount on leave if present */
26361dc9caeSHeiner Kallweit 	if (shared->np)
26461dc9caeSHeiner Kallweit 		of_node_put(shared->np);
26561dc9caeSHeiner Kallweit 
26661dc9caeSHeiner Kallweit 	if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
26761dc9caeSHeiner Kallweit 		bus->shared[shared->base_addr] = NULL;
26861dc9caeSHeiner Kallweit 		mutex_unlock(&bus->shared_lock);
26961dc9caeSHeiner Kallweit 		kfree(shared->priv);
27061dc9caeSHeiner Kallweit 		kfree(shared);
27161dc9caeSHeiner Kallweit 	}
27261dc9caeSHeiner Kallweit 
27361dc9caeSHeiner Kallweit 	phydev->shared = NULL;
27461dc9caeSHeiner Kallweit }
27561dc9caeSHeiner Kallweit EXPORT_SYMBOL_GPL(phy_package_leave);
27661dc9caeSHeiner Kallweit 
devm_phy_package_leave(struct device * dev,void * res)27761dc9caeSHeiner Kallweit static void devm_phy_package_leave(struct device *dev, void *res)
27861dc9caeSHeiner Kallweit {
27961dc9caeSHeiner Kallweit 	phy_package_leave(*(struct phy_device **)res);
28061dc9caeSHeiner Kallweit }
28161dc9caeSHeiner Kallweit 
28261dc9caeSHeiner Kallweit /**
28361dc9caeSHeiner Kallweit  * devm_phy_package_join - resource managed phy_package_join()
28461dc9caeSHeiner Kallweit  * @dev: device that is registering this PHY package
28561dc9caeSHeiner Kallweit  * @phydev: target phy_device struct
28661dc9caeSHeiner Kallweit  * @base_addr: cookie and base PHY address of PHY package for offset
28761dc9caeSHeiner Kallweit  *   calculation of global register access
28861dc9caeSHeiner Kallweit  * @priv_size: if non-zero allocate this amount of bytes for private data
28961dc9caeSHeiner Kallweit  *
29061dc9caeSHeiner Kallweit  * Managed phy_package_join(). Shared storage fetched by this function,
29161dc9caeSHeiner Kallweit  * phy_package_leave() is automatically called on driver detach. See
29261dc9caeSHeiner Kallweit  * phy_package_join() for more information.
29361dc9caeSHeiner Kallweit  */
devm_phy_package_join(struct device * dev,struct phy_device * phydev,int base_addr,size_t priv_size)29461dc9caeSHeiner Kallweit int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
29561dc9caeSHeiner Kallweit 			  int base_addr, size_t priv_size)
29661dc9caeSHeiner Kallweit {
29761dc9caeSHeiner Kallweit 	struct phy_device **ptr;
29861dc9caeSHeiner Kallweit 	int ret;
29961dc9caeSHeiner Kallweit 
30061dc9caeSHeiner Kallweit 	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
30161dc9caeSHeiner Kallweit 			   GFP_KERNEL);
30261dc9caeSHeiner Kallweit 	if (!ptr)
30361dc9caeSHeiner Kallweit 		return -ENOMEM;
30461dc9caeSHeiner Kallweit 
30561dc9caeSHeiner Kallweit 	ret = phy_package_join(phydev, base_addr, priv_size);
30661dc9caeSHeiner Kallweit 
30761dc9caeSHeiner Kallweit 	if (!ret) {
30861dc9caeSHeiner Kallweit 		*ptr = phydev;
30961dc9caeSHeiner Kallweit 		devres_add(dev, ptr);
31061dc9caeSHeiner Kallweit 	} else {
31161dc9caeSHeiner Kallweit 		devres_free(ptr);
31261dc9caeSHeiner Kallweit 	}
31361dc9caeSHeiner Kallweit 
31461dc9caeSHeiner Kallweit 	return ret;
31561dc9caeSHeiner Kallweit }
31661dc9caeSHeiner Kallweit EXPORT_SYMBOL_GPL(devm_phy_package_join);
31761dc9caeSHeiner Kallweit 
31861dc9caeSHeiner Kallweit /**
31961dc9caeSHeiner Kallweit  * devm_of_phy_package_join - resource managed of_phy_package_join()
32061dc9caeSHeiner Kallweit  * @dev: device that is registering this PHY package
32161dc9caeSHeiner Kallweit  * @phydev: target phy_device struct
32261dc9caeSHeiner Kallweit  * @priv_size: if non-zero allocate this amount of bytes for private data
32361dc9caeSHeiner Kallweit  *
32461dc9caeSHeiner Kallweit  * Managed of_phy_package_join(). Shared storage fetched by this function,
32561dc9caeSHeiner Kallweit  * phy_package_leave() is automatically called on driver detach. See
32661dc9caeSHeiner Kallweit  * of_phy_package_join() for more information.
32761dc9caeSHeiner Kallweit  */
devm_of_phy_package_join(struct device * dev,struct phy_device * phydev,size_t priv_size)32861dc9caeSHeiner Kallweit int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
32961dc9caeSHeiner Kallweit 			     size_t priv_size)
33061dc9caeSHeiner Kallweit {
33161dc9caeSHeiner Kallweit 	struct phy_device **ptr;
33261dc9caeSHeiner Kallweit 	int ret;
33361dc9caeSHeiner Kallweit 
33461dc9caeSHeiner Kallweit 	ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
33561dc9caeSHeiner Kallweit 			   GFP_KERNEL);
33661dc9caeSHeiner Kallweit 	if (!ptr)
33761dc9caeSHeiner Kallweit 		return -ENOMEM;
33861dc9caeSHeiner Kallweit 
33961dc9caeSHeiner Kallweit 	ret = of_phy_package_join(phydev, priv_size);
34061dc9caeSHeiner Kallweit 
34161dc9caeSHeiner Kallweit 	if (!ret) {
34261dc9caeSHeiner Kallweit 		*ptr = phydev;
34361dc9caeSHeiner Kallweit 		devres_add(dev, ptr);
34461dc9caeSHeiner Kallweit 	} else {
34561dc9caeSHeiner Kallweit 		devres_free(ptr);
34661dc9caeSHeiner Kallweit 	}
34761dc9caeSHeiner Kallweit 
34861dc9caeSHeiner Kallweit 	return ret;
34961dc9caeSHeiner Kallweit }
35061dc9caeSHeiner Kallweit EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
351