mtd: fix build with GCC 14
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch
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
5
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.
10
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.
15
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".
19
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>
23 ---
24 drivers/net/phy/phy_device.c | 96 ++++++++++++++++++++++++++++++++++++
25 include/linux/phy.h | 6 +++
26 2 files changed, 102 insertions(+)
27
28 --- a/drivers/net/phy/phy_device.c
29 +++ b/drivers/net/phy/phy_device.c
30 @@ -1648,6 +1648,7 @@ int phy_package_join(struct phy_device *
31 shared->priv_size = priv_size;
32 }
33 shared->base_addr = base_addr;
34 + shared->np = NULL;
35 refcount_set(&shared->refcnt, 1);
36 bus->shared[base_addr] = shared;
37 } else {
38 @@ -1671,6 +1672,63 @@ err_unlock:
39 EXPORT_SYMBOL_GPL(phy_package_join);
40
41 /**
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
45 + *
46 + * This is a variant of phy_package_join for PHY package defined in DT.
47 + *
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.
51 + *
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.
55 + *
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.
60 + */
61 +int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
62 +{
63 + struct device_node *node = phydev->mdio.dev.of_node;
64 + struct device_node *package_node;
65 + u32 base_addr;
66 + int ret;
67 +
68 + if (!node)
69 + return -EINVAL;
70 +
71 + package_node = of_get_parent(node);
72 + if (!package_node)
73 + return -EINVAL;
74 +
75 + if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
76 + ret = -EINVAL;
77 + goto exit;
78 + }
79 +
80 + if (of_property_read_u32(package_node, "reg", &base_addr)) {
81 + ret = -EINVAL;
82 + goto exit;
83 + }
84 +
85 + ret = phy_package_join(phydev, base_addr, priv_size);
86 + if (ret)
87 + goto exit;
88 +
89 + phydev->shared->np = package_node;
90 +
91 + return 0;
92 +exit:
93 + of_node_put(package_node);
94 + return ret;
95 +}
96 +EXPORT_SYMBOL_GPL(of_phy_package_join);
97 +
98 +/**
99 * phy_package_leave - leave a common PHY group
100 * @phydev: target phy_device struct
101 *
102 @@ -1686,6 +1744,10 @@ void phy_package_leave(struct phy_device
103 if (!shared)
104 return;
105
106 + /* Decrease the node refcount on leave if present */
107 + if (shared->np)
108 + of_node_put(shared->np);
109 +
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 @@ -1739,6 +1801,40 @@ int devm_phy_package_join(struct device
114 EXPORT_SYMBOL_GPL(devm_phy_package_join);
115
116 /**
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
121 + *
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.
125 + */
126 +int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
127 + size_t priv_size)
128 +{
129 + struct phy_device **ptr;
130 + int ret;
131 +
132 + ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
133 + GFP_KERNEL);
134 + if (!ptr)
135 + return -ENOMEM;
136 +
137 + ret = of_phy_package_join(phydev, priv_size);
138 +
139 + if (!ret) {
140 + *ptr = phydev;
141 + devres_add(dev, ptr);
142 + } else {
143 + devres_free(ptr);
144 + }
145 +
146 + return ret;
147 +}
148 +EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
149 +
150 +/**
151 * phy_detach - detach a PHY device from its network device
152 * @phydev: target phy_device struct
153 *
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 {
165 */
166 struct phy_package_shared {
167 u8 base_addr;
168 + /* With PHY package defined in DT this points to the PHY package node */
169 + struct device_node *np;
170 refcount_t refcnt;
171 unsigned long flags;
172 size_t priv_size;
173 @@ -1793,9 +1796,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,
182 + size_t priv_size);
183
184 #if IS_ENABLED(CONFIG_PHYLIB)
185 int __init mdio_bus_init(void);