]> Git Repo - linux.git/blob - drivers/net/dsa/realtek/rtl83xx.c
Linux 6.14-rc3
[linux.git] / drivers / net / dsa / realtek / rtl83xx.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <linux/module.h>
4 #include <linux/regmap.h>
5 #include <linux/of_mdio.h>
6
7 #include "realtek.h"
8 #include "rtl83xx.h"
9
10 /**
11  * rtl83xx_lock() - Locks the mutex used by regmaps
12  * @ctx: realtek_priv pointer
13  *
14  * This function is passed to regmap to be used as the lock function.
15  * It is also used externally to block regmap before executing multiple
16  * operations that must happen in sequence (which will use
17  * realtek_priv.map_nolock instead).
18  *
19  * Context: Can sleep. Holds priv->map_lock lock.
20  * Return: nothing
21  */
22 void rtl83xx_lock(void *ctx)
23 {
24         struct realtek_priv *priv = ctx;
25
26         mutex_lock(&priv->map_lock);
27 }
28 EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, "REALTEK_DSA");
29
30 /**
31  * rtl83xx_unlock() - Unlocks the mutex used by regmaps
32  * @ctx: realtek_priv pointer
33  *
34  * This function unlocks the lock acquired by rtl83xx_lock.
35  *
36  * Context: Releases priv->map_lock lock.
37  * Return: nothing
38  */
39 void rtl83xx_unlock(void *ctx)
40 {
41         struct realtek_priv *priv = ctx;
42
43         mutex_unlock(&priv->map_lock);
44 }
45 EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, "REALTEK_DSA");
46
47 static int rtl83xx_user_mdio_read(struct mii_bus *bus, int addr, int regnum)
48 {
49         struct realtek_priv *priv = bus->priv;
50
51         return priv->ops->phy_read(priv, addr, regnum);
52 }
53
54 static int rtl83xx_user_mdio_write(struct mii_bus *bus, int addr, int regnum,
55                                    u16 val)
56 {
57         struct realtek_priv *priv = bus->priv;
58
59         return priv->ops->phy_write(priv, addr, regnum, val);
60 }
61
62 /**
63  * rtl83xx_setup_user_mdio() - register the user mii bus driver
64  * @ds: DSA switch associated with this user_mii_bus
65  *
66  * Registers the MDIO bus for built-in Ethernet PHYs, and associates it with
67  * the mandatory 'mdio' child OF node of the switch.
68  *
69  * Context: Can sleep.
70  * Return: 0 on success, negative value for failure.
71  */
72 int rtl83xx_setup_user_mdio(struct dsa_switch *ds)
73 {
74         struct realtek_priv *priv = ds->priv;
75         struct device_node *mdio_np;
76         struct mii_bus *bus;
77         int ret = 0;
78
79         mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
80         if (!mdio_np) {
81                 dev_err(priv->dev, "no MDIO bus node\n");
82                 return -ENODEV;
83         }
84
85         bus = devm_mdiobus_alloc(priv->dev);
86         if (!bus) {
87                 ret = -ENOMEM;
88                 goto err_put_node;
89         }
90
91         bus->priv = priv;
92         bus->name = "Realtek user MII";
93         bus->read = rtl83xx_user_mdio_read;
94         bus->write = rtl83xx_user_mdio_write;
95         snprintf(bus->id, MII_BUS_ID_SIZE, "%s:user_mii", dev_name(priv->dev));
96         bus->parent = priv->dev;
97
98         ret = devm_of_mdiobus_register(priv->dev, bus, mdio_np);
99         if (ret) {
100                 dev_err(priv->dev, "unable to register MDIO bus %s\n",
101                         bus->id);
102                 goto err_put_node;
103         }
104
105         priv->user_mii_bus = bus;
106
107 err_put_node:
108         of_node_put(mdio_np);
109
110         return ret;
111 }
112 EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, "REALTEK_DSA");
113
114 /**
115  * rtl83xx_probe() - probe a Realtek switch
116  * @dev: the device being probed
117  * @interface_info: specific management interface info.
118  *
119  * This function initializes realtek_priv and reads data from the device tree
120  * node. The switch is hard resetted if a method is provided.
121  *
122  * Context: Can sleep.
123  * Return: Pointer to the realtek_priv or ERR_PTR() in case of failure.
124  *
125  * The realtek_priv pointer does not need to be freed as it is controlled by
126  * devres.
127  */
128 struct realtek_priv *
129 rtl83xx_probe(struct device *dev,
130               const struct realtek_interface_info *interface_info)
131 {
132         const struct realtek_variant *var;
133         struct realtek_priv *priv;
134         struct regmap_config rc = {
135                 .reg_bits = 10, /* A4..A0 R4..R0 */
136                 .val_bits = 16,
137                 .reg_stride = 1,
138                 .max_register = 0xffff,
139                 .reg_format_endian = REGMAP_ENDIAN_BIG,
140                 .reg_read = interface_info->reg_read,
141                 .reg_write = interface_info->reg_write,
142                 .cache_type = REGCACHE_NONE,
143                 .lock = rtl83xx_lock,
144                 .unlock = rtl83xx_unlock,
145         };
146         int ret;
147
148         var = of_device_get_match_data(dev);
149         if (!var)
150                 return ERR_PTR(-EINVAL);
151
152         priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
153                             GFP_KERNEL);
154         if (!priv)
155                 return ERR_PTR(-ENOMEM);
156
157         mutex_init(&priv->map_lock);
158
159         rc.lock_arg = priv;
160         priv->map = devm_regmap_init(dev, NULL, priv, &rc);
161         if (IS_ERR(priv->map)) {
162                 ret = PTR_ERR(priv->map);
163                 dev_err(dev, "regmap init failed: %d\n", ret);
164                 return ERR_PTR(ret);
165         }
166
167         rc.disable_locking = true;
168         priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
169         if (IS_ERR(priv->map_nolock)) {
170                 ret = PTR_ERR(priv->map_nolock);
171                 dev_err(dev, "regmap init failed: %d\n", ret);
172                 return ERR_PTR(ret);
173         }
174
175         /* Link forward and backward */
176         priv->dev = dev;
177         priv->variant = var;
178         priv->ops = var->ops;
179         priv->chip_data = (void *)priv + sizeof(*priv);
180
181         spin_lock_init(&priv->lock);
182
183         priv->leds_disabled = of_property_read_bool(dev->of_node,
184                                                     "realtek,disable-leds");
185
186         /* TODO: if power is software controlled, set up any regulators here */
187         priv->reset_ctl = devm_reset_control_get_optional(dev, NULL);
188         if (IS_ERR(priv->reset_ctl))
189                 return dev_err_cast_probe(dev, priv->reset_ctl,
190                                           "failed to get reset control\n");
191
192         priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
193         if (IS_ERR(priv->reset)) {
194                 dev_err(dev, "failed to get RESET GPIO\n");
195                 return ERR_CAST(priv->reset);
196         }
197
198         dev_set_drvdata(dev, priv);
199
200         if (priv->reset_ctl || priv->reset) {
201                 rtl83xx_reset_assert(priv);
202                 dev_dbg(dev, "asserted RESET\n");
203                 msleep(REALTEK_HW_STOP_DELAY);
204                 rtl83xx_reset_deassert(priv);
205                 msleep(REALTEK_HW_START_DELAY);
206                 dev_dbg(dev, "deasserted RESET\n");
207         }
208
209         return priv;
210 }
211 EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, "REALTEK_DSA");
212
213 /**
214  * rtl83xx_register_switch() - detects and register a switch
215  * @priv: realtek_priv pointer
216  *
217  * This function first checks the switch chip ID and register a DSA
218  * switch.
219  *
220  * Context: Can sleep. Takes and releases priv->map_lock.
221  * Return: 0 on success, negative value for failure.
222  */
223 int rtl83xx_register_switch(struct realtek_priv *priv)
224 {
225         struct dsa_switch *ds = &priv->ds;
226         int ret;
227
228         ret = priv->ops->detect(priv);
229         if (ret) {
230                 dev_err_probe(priv->dev, ret, "unable to detect switch\n");
231                 return ret;
232         }
233
234         ds->priv = priv;
235         ds->dev = priv->dev;
236         ds->ops = priv->variant->ds_ops;
237         ds->phylink_mac_ops = priv->variant->phylink_mac_ops;
238         ds->num_ports = priv->num_ports;
239
240         ret = dsa_register_switch(ds);
241         if (ret) {
242                 dev_err_probe(priv->dev, ret, "unable to register switch\n");
243                 return ret;
244         }
245
246         return 0;
247 }
248 EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, "REALTEK_DSA");
249
250 /**
251  * rtl83xx_unregister_switch() - unregister a switch
252  * @priv: realtek_priv pointer
253  *
254  * This function unregister a DSA switch.
255  *
256  * Context: Can sleep.
257  * Return: Nothing.
258  */
259 void rtl83xx_unregister_switch(struct realtek_priv *priv)
260 {
261         struct dsa_switch *ds = &priv->ds;
262
263         dsa_unregister_switch(ds);
264 }
265 EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, "REALTEK_DSA");
266
267 /**
268  * rtl83xx_shutdown() - shutdown a switch
269  * @priv: realtek_priv pointer
270  *
271  * This function shuts down the DSA switch and cleans the platform driver data,
272  * to prevent realtek_{smi,mdio}_remove() from running afterwards, which is
273  * possible if the parent bus implements its own .shutdown() as .remove().
274  *
275  * Context: Can sleep.
276  * Return: Nothing.
277  */
278 void rtl83xx_shutdown(struct realtek_priv *priv)
279 {
280         struct dsa_switch *ds = &priv->ds;
281
282         dsa_switch_shutdown(ds);
283
284         dev_set_drvdata(priv->dev, NULL);
285 }
286 EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, "REALTEK_DSA");
287
288 /**
289  * rtl83xx_remove() - Cleanup a realtek switch driver
290  * @priv: realtek_priv pointer
291  *
292  * Placehold for common cleanup procedures.
293  *
294  * Context: Any
295  * Return: nothing
296  */
297 void rtl83xx_remove(struct realtek_priv *priv)
298 {
299 }
300 EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, "REALTEK_DSA");
301
302 void rtl83xx_reset_assert(struct realtek_priv *priv)
303 {
304         int ret;
305
306         ret = reset_control_assert(priv->reset_ctl);
307         if (ret)
308                 dev_warn(priv->dev,
309                          "Failed to assert the switch reset control: %pe\n",
310                          ERR_PTR(ret));
311
312         gpiod_set_value(priv->reset, true);
313 }
314
315 void rtl83xx_reset_deassert(struct realtek_priv *priv)
316 {
317         int ret;
318
319         ret = reset_control_deassert(priv->reset_ctl);
320         if (ret)
321                 dev_warn(priv->dev,
322                          "Failed to deassert the switch reset control: %pe\n",
323                          ERR_PTR(ret));
324
325         gpiod_set_value(priv->reset, false);
326 }
327
328 MODULE_AUTHOR("Luiz Angelo Daros de Luca <[email protected]>");
329 MODULE_AUTHOR("Linus Walleij <[email protected]>");
330 MODULE_DESCRIPTION("Realtek DSA switches common module");
331 MODULE_LICENSE("GPL");
This page took 0.049074 seconds and 4 git commands to generate.