1 From 471e8fd3afcef5a9f9089f0bd21965ad9ba35c91 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Tue, 6 Feb 2024 18:31:06 +0100
4 Subject: [PATCH 03/10] net: phy: add devm/of_phy_package_join helper
6 Add devm/of_phy_package_join helper to join PHYs in a PHY package. These
7 are variant of the manual phy_package_join with the difference that
8 these will use DT nodes to derive the base_addr instead of manually
9 passing an hardcoded value.
11 An additional value is added in phy_package_shared, "np" to reference
12 the PHY package node pointer in specific PHY driver probe_once and
13 config_init_once functions to make use of additional specific properties
14 defined in the PHY package node in DT.
16 The np value is filled only with of_phy_package_join if a valid PHY
17 package node is found. A valid PHY package node must have the node name
18 set to "ethernet-phy-package".
20 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
21 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
22 Signed-off-by: David S. Miller <davem@davemloft.net>
24 drivers/net/phy/phy_device.c | 96 ++++++++++++++++++++++++++++++++++++
25 include/linux/phy.h | 6 +++
26 2 files changed, 102 insertions(+)
28 --- a/drivers/net/phy/phy_device.c
29 +++ b/drivers/net/phy/phy_device.c
30 @@ -1650,6 +1650,7 @@ int phy_package_join(struct phy_device *
31 shared->priv_size = priv_size;
33 shared->base_addr = base_addr;
35 refcount_set(&shared->refcnt, 1);
36 bus->shared[base_addr] = shared;
38 @@ -1673,6 +1674,63 @@ err_unlock:
39 EXPORT_SYMBOL_GPL(phy_package_join);
42 + * of_phy_package_join - join a common PHY group in PHY package
43 + * @phydev: target phy_device struct
44 + * @priv_size: if non-zero allocate this amount of bytes for private data
46 + * This is a variant of phy_package_join for PHY package defined in DT.
48 + * The parent node of the @phydev is checked as a valid PHY package node
49 + * structure (by matching the node name "ethernet-phy-package") and the
50 + * base_addr for the PHY package is passed to phy_package_join.
52 + * With this configuration the shared struct will also have the np value
53 + * filled to use additional DT defined properties in PHY specific
54 + * probe_once and config_init_once PHY package OPs.
56 + * Returns < 0 on error, 0 on success. Esp. calling phy_package_join()
57 + * with the same cookie but a different priv_size is an error. Or a parent
58 + * node is not detected or is not valid or doesn't match the expected node
59 + * name for PHY package.
61 +int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
63 + struct device_node *node = phydev->mdio.dev.of_node;
64 + struct device_node *package_node;
71 + package_node = of_get_parent(node);
75 + if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
80 + if (of_property_read_u32(package_node, "reg", &base_addr)) {
85 + ret = phy_package_join(phydev, base_addr, priv_size);
89 + phydev->shared->np = package_node;
93 + of_node_put(package_node);
96 +EXPORT_SYMBOL_GPL(of_phy_package_join);
99 * phy_package_leave - leave a common PHY group
100 * @phydev: target phy_device struct
102 @@ -1688,6 +1746,10 @@ void phy_package_leave(struct phy_device
106 + /* Decrease the node refcount on leave if present */
108 + of_node_put(shared->np);
110 if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
111 bus->shared[shared->base_addr] = NULL;
112 mutex_unlock(&bus->shared_lock);
113 @@ -1741,6 +1803,40 @@ int devm_phy_package_join(struct device
114 EXPORT_SYMBOL_GPL(devm_phy_package_join);
117 + * devm_of_phy_package_join - resource managed of_phy_package_join()
118 + * @dev: device that is registering this PHY package
119 + * @phydev: target phy_device struct
120 + * @priv_size: if non-zero allocate this amount of bytes for private data
122 + * Managed of_phy_package_join(). Shared storage fetched by this function,
123 + * phy_package_leave() is automatically called on driver detach. See
124 + * of_phy_package_join() for more information.
126 +int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
129 + struct phy_device **ptr;
132 + ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
137 + ret = of_phy_package_join(phydev, priv_size);
141 + devres_add(dev, ptr);
148 +EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
151 * phy_detach - detach a PHY device from its network device
152 * @phydev: target phy_device struct
154 --- a/include/linux/phy.h
155 +++ b/include/linux/phy.h
156 @@ -321,6 +321,7 @@ struct mdio_bus_stats {
157 * struct phy_package_shared - Shared information in PHY packages
158 * @base_addr: Base PHY address of PHY package used to combine PHYs
159 * in one package and for offset calculation of phy_package_read/write
160 + * @np: Pointer to the Device Node if PHY package defined in DT
161 * @refcnt: Number of PHYs connected to this shared data
162 * @flags: Initialization of PHY package
163 * @priv_size: Size of the shared private data @priv
164 @@ -332,6 +333,8 @@ struct mdio_bus_stats {
166 struct phy_package_shared {
168 + /* With PHY package defined in DT this points to the PHY package node */
169 + struct device_node *np;
173 @@ -1765,9 +1768,12 @@ int phy_ethtool_set_link_ksettings(struc
174 const struct ethtool_link_ksettings *cmd);
175 int phy_ethtool_nway_reset(struct net_device *ndev);
176 int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
177 +int of_phy_package_join(struct phy_device *phydev, size_t priv_size);
178 void phy_package_leave(struct phy_device *phydev);
179 int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
180 int base_addr, size_t priv_size);
181 +int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
184 #if IS_ENABLED(CONFIG_PHYLIB)
185 int __init mdio_bus_init(void);