kernel: backport ipeth CDC NCM support
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 790-12-v6.4-net-dsa-mt7530-introduce-separate-MDIO-driver.patch
1 From 5313432ca1e1a0677ad7b4f17a7e0186473f47aa Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Mon, 3 Apr 2023 02:19:13 +0100
4 Subject: [PATCH 12/48] net: dsa: mt7530: introduce separate MDIO driver
5
6 Split MT7530 switch driver into a common part and a part specific
7 for MDIO connected switches and multi-chip modules.
8 Move MDIO-specific functions to newly introduced mt7530-mdio.c while
9 keeping the common parts in mt7530.c.
10 Introduce new Kconfig symbol CONFIG_NET_DSA_MT7530_MDIO which is
11 implied by CONFIG_NET_DSA_MT7530.
12
13 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
14 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
16 ---
17 MAINTAINERS | 1 +
18 drivers/net/dsa/Kconfig | 18 ++-
19 drivers/net/dsa/Makefile | 1 +
20 drivers/net/dsa/mt7530-mdio.c | 271 ++++++++++++++++++++++++++++++++++
21 drivers/net/dsa/mt7530.c | 264 +--------------------------------
22 drivers/net/dsa/mt7530.h | 6 +
23 6 files changed, 302 insertions(+), 259 deletions(-)
24 create mode 100644 drivers/net/dsa/mt7530-mdio.c
25
26 --- a/MAINTAINERS
27 +++ b/MAINTAINERS
28 @@ -13069,6 +13069,7 @@ M: Landen Chao <Landen.Chao@mediatek.com
29 M: DENG Qingfang <dqfext@gmail.com>
30 L: netdev@vger.kernel.org
31 S: Maintained
32 +F: drivers/net/dsa/mt7530-mdio.c
33 F: drivers/net/dsa/mt7530.*
34 F: net/dsa/tag_mtk.c
35
36 --- a/drivers/net/dsa/Kconfig
37 +++ b/drivers/net/dsa/Kconfig
38 @@ -34,13 +34,25 @@ config NET_DSA_LANTIQ_GSWIP
39 the xrx200 / VR9 SoC.
40
41 config NET_DSA_MT7530
42 - tristate "MediaTek MT753x and MT7621 Ethernet switch support"
43 + tristate "MediaTek MT7530 and MT7531 Ethernet switch support"
44 select NET_DSA_TAG_MTK
45 + imply NET_DSA_MT7530_MDIO
46 + help
47 + This enables support for the MediaTek MT7530 and MT7531 Ethernet
48 + switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
49 + MT7621ST and MT7623AI SoCs, and built-in switch in MT7988 SoC are
50 + supported as well.
51 +
52 +config NET_DSA_MT7530_MDIO
53 + tristate "MediaTek MT7530 MDIO interface driver"
54 + depends on NET_DSA_MT7530
55 select MEDIATEK_GE_PHY
56 select PCS_MTK_LYNXI
57 help
58 - This enables support for the MediaTek MT7530, MT7531, and MT7621
59 - Ethernet switch chips.
60 + This enables support for the MediaTek MT7530 and MT7531 switch
61 + chips which are connected via MDIO, as well as multi-chip
62 + module MT7530 which can be found in the MT7621AT, MT7621DAT,
63 + MT7621ST and MT7623AI SoCs.
64
65 config NET_DSA_MV88E6060
66 tristate "Marvell 88E6060 ethernet switch chip support"
67 --- a/drivers/net/dsa/Makefile
68 +++ b/drivers/net/dsa/Makefile
69 @@ -7,6 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi
70 endif
71 obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
72 obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
73 +obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
74 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
75 obj-$(CONFIG_NET_DSA_RZN1_A5PSW) += rzn1_a5psw.o
76 obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
77 --- /dev/null
78 +++ b/drivers/net/dsa/mt7530-mdio.c
79 @@ -0,0 +1,271 @@
80 +// SPDX-License-Identifier: GPL-2.0-only
81 +
82 +#include <linux/gpio/consumer.h>
83 +#include <linux/mdio.h>
84 +#include <linux/module.h>
85 +#include <linux/pcs/pcs-mtk-lynxi.h>
86 +#include <linux/of_irq.h>
87 +#include <linux/of_mdio.h>
88 +#include <linux/of_net.h>
89 +#include <linux/of_platform.h>
90 +#include <linux/regmap.h>
91 +#include <linux/reset.h>
92 +#include <linux/regulator/consumer.h>
93 +#include <net/dsa.h>
94 +
95 +#include "mt7530.h"
96 +
97 +static int
98 +mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
99 +{
100 + struct mii_bus *bus = context;
101 + u16 page, r, lo, hi;
102 + int ret;
103 +
104 + page = (reg >> 6) & 0x3ff;
105 + r = (reg >> 2) & 0xf;
106 + lo = val & 0xffff;
107 + hi = val >> 16;
108 +
109 + /* MT7530 uses 31 as the pseudo port */
110 + ret = bus->write(bus, 0x1f, 0x1f, page);
111 + if (ret < 0)
112 + return ret;
113 +
114 + ret = bus->write(bus, 0x1f, r, lo);
115 + if (ret < 0)
116 + return ret;
117 +
118 + ret = bus->write(bus, 0x1f, 0x10, hi);
119 + return ret;
120 +}
121 +
122 +static int
123 +mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
124 +{
125 + struct mii_bus *bus = context;
126 + u16 page, r, lo, hi;
127 + int ret;
128 +
129 + page = (reg >> 6) & 0x3ff;
130 + r = (reg >> 2) & 0xf;
131 +
132 + /* MT7530 uses 31 as the pseudo port */
133 + ret = bus->write(bus, 0x1f, 0x1f, page);
134 + if (ret < 0)
135 + return ret;
136 +
137 + lo = bus->read(bus, 0x1f, r);
138 + hi = bus->read(bus, 0x1f, 0x10);
139 +
140 + *val = (hi << 16) | (lo & 0xffff);
141 +
142 + return 0;
143 +}
144 +
145 +static void
146 +mt7530_mdio_regmap_lock(void *mdio_lock)
147 +{
148 + mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
149 +}
150 +
151 +static void
152 +mt7530_mdio_regmap_unlock(void *mdio_lock)
153 +{
154 + mutex_unlock(mdio_lock);
155 +}
156 +
157 +static const struct regmap_bus mt7530_regmap_bus = {
158 + .reg_write = mt7530_regmap_write,
159 + .reg_read = mt7530_regmap_read,
160 +};
161 +
162 +static int
163 +mt7531_create_sgmii(struct mt7530_priv *priv)
164 +{
165 + struct regmap_config *mt7531_pcs_config[2];
166 + struct phylink_pcs *pcs;
167 + struct regmap *regmap;
168 + int i, ret = 0;
169 +
170 + for (i = 0; i < 2; i++) {
171 + mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
172 + sizeof(struct regmap_config),
173 + GFP_KERNEL);
174 + if (!mt7531_pcs_config[i]) {
175 + ret = -ENOMEM;
176 + break;
177 + }
178 +
179 + mt7531_pcs_config[i]->name = i ? "port6" : "port5";
180 + mt7531_pcs_config[i]->reg_bits = 16;
181 + mt7531_pcs_config[i]->val_bits = 32;
182 + mt7531_pcs_config[i]->reg_stride = 4;
183 + mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
184 + mt7531_pcs_config[i]->max_register = 0x17c;
185 + mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
186 + mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
187 + mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
188 +
189 + regmap = devm_regmap_init(priv->dev,
190 + &mt7530_regmap_bus, priv->bus,
191 + mt7531_pcs_config[i]);
192 + if (IS_ERR(regmap)) {
193 + ret = PTR_ERR(regmap);
194 + break;
195 + }
196 + pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
197 + MT7531_PHYA_CTRL_SIGNAL3, 0);
198 + if (!pcs) {
199 + ret = -ENXIO;
200 + break;
201 + }
202 + priv->ports[5 + i].sgmii_pcs = pcs;
203 + }
204 +
205 + if (ret && i)
206 + mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
207 +
208 + return ret;
209 +}
210 +
211 +static const struct of_device_id mt7530_of_match[] = {
212 + { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
213 + { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
214 + { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
215 + { /* sentinel */ },
216 +};
217 +MODULE_DEVICE_TABLE(of, mt7530_of_match);
218 +
219 +static int
220 +mt7530_probe(struct mdio_device *mdiodev)
221 +{
222 + static struct regmap_config *regmap_config;
223 + struct mt7530_priv *priv;
224 + struct device_node *dn;
225 + int ret;
226 +
227 + dn = mdiodev->dev.of_node;
228 +
229 + priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
230 + if (!priv)
231 + return -ENOMEM;
232 +
233 + priv->bus = mdiodev->bus;
234 + priv->dev = &mdiodev->dev;
235 +
236 + ret = mt7530_probe_common(priv);
237 + if (ret)
238 + return ret;
239 +
240 + /* Use medatek,mcm property to distinguish hardware type that would
241 + * cause a little bit differences on power-on sequence.
242 + * Not MCM that indicates switch works as the remote standalone
243 + * integrated circuit so the GPIO pin would be used to complete
244 + * the reset, otherwise memory-mapped register accessing used
245 + * through syscon provides in the case of MCM.
246 + */
247 + priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
248 + if (priv->mcm) {
249 + dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
250 +
251 + priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
252 + if (IS_ERR(priv->rstc)) {
253 + dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
254 + return PTR_ERR(priv->rstc);
255 + }
256 + } else {
257 + priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
258 + GPIOD_OUT_LOW);
259 + if (IS_ERR(priv->reset)) {
260 + dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
261 + return PTR_ERR(priv->reset);
262 + }
263 + }
264 +
265 + if (priv->id == ID_MT7530) {
266 + priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
267 + if (IS_ERR(priv->core_pwr))
268 + return PTR_ERR(priv->core_pwr);
269 +
270 + priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
271 + if (IS_ERR(priv->io_pwr))
272 + return PTR_ERR(priv->io_pwr);
273 + }
274 +
275 + regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
276 + GFP_KERNEL);
277 + if (!regmap_config)
278 + return -ENOMEM;
279 +
280 + regmap_config->reg_bits = 16;
281 + regmap_config->val_bits = 32;
282 + regmap_config->reg_stride = 4;
283 + regmap_config->max_register = MT7530_CREV;
284 + regmap_config->disable_locking = true;
285 + priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
286 + priv->bus, regmap_config);
287 + if (IS_ERR(priv->regmap))
288 + return PTR_ERR(priv->regmap);
289 +
290 + if (priv->id == ID_MT7531) {
291 + ret = mt7531_create_sgmii(priv);
292 + if (ret)
293 + return ret;
294 + }
295 +
296 + return dsa_register_switch(priv->ds);
297 +}
298 +
299 +static void
300 +mt7530_remove(struct mdio_device *mdiodev)
301 +{
302 + struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
303 + int ret = 0, i;
304 +
305 + if (!priv)
306 + return;
307 +
308 + ret = regulator_disable(priv->core_pwr);
309 + if (ret < 0)
310 + dev_err(priv->dev,
311 + "Failed to disable core power: %d\n", ret);
312 +
313 + ret = regulator_disable(priv->io_pwr);
314 + if (ret < 0)
315 + dev_err(priv->dev, "Failed to disable io pwr: %d\n",
316 + ret);
317 +
318 + mt7530_remove_common(priv);
319 +
320 + for (i = 0; i < 2; ++i)
321 + mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
322 +}
323 +
324 +static void mt7530_shutdown(struct mdio_device *mdiodev)
325 +{
326 + struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
327 +
328 + if (!priv)
329 + return;
330 +
331 + dsa_switch_shutdown(priv->ds);
332 +
333 + dev_set_drvdata(&mdiodev->dev, NULL);
334 +}
335 +
336 +static struct mdio_driver mt7530_mdio_driver = {
337 + .probe = mt7530_probe,
338 + .remove = mt7530_remove,
339 + .shutdown = mt7530_shutdown,
340 + .mdiodrv.driver = {
341 + .name = "mt7530-mdio",
342 + .of_match_table = mt7530_of_match,
343 + },
344 +};
345 +
346 +mdio_module_driver(mt7530_mdio_driver);
347 +
348 +MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
349 +MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)");
350 +MODULE_LICENSE("GPL");
351 --- a/drivers/net/dsa/mt7530.c
352 +++ b/drivers/net/dsa/mt7530.c
353 @@ -14,7 +14,6 @@
354 #include <linux/of_mdio.h>
355 #include <linux/of_net.h>
356 #include <linux/of_platform.h>
357 -#include <linux/pcs/pcs-mtk-lynxi.h>
358 #include <linux/phylink.h>
359 #include <linux/regmap.h>
360 #include <linux/regulator/consumer.h>
361 @@ -192,31 +191,6 @@ core_clear(struct mt7530_priv *priv, u32
362 }
363
364 static int
365 -mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
366 -{
367 - struct mii_bus *bus = context;
368 - u16 page, r, lo, hi;
369 - int ret;
370 -
371 - page = (reg >> 6) & 0x3ff;
372 - r = (reg >> 2) & 0xf;
373 - lo = val & 0xffff;
374 - hi = val >> 16;
375 -
376 - /* MT7530 uses 31 as the pseudo port */
377 - ret = bus->write(bus, 0x1f, 0x1f, page);
378 - if (ret < 0)
379 - return ret;
380 -
381 - ret = bus->write(bus, 0x1f, r, lo);
382 - if (ret < 0)
383 - return ret;
384 -
385 - ret = bus->write(bus, 0x1f, 0x10, hi);
386 - return ret;
387 -}
388 -
389 -static int
390 mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
391 {
392 int ret;
393 @@ -230,29 +204,6 @@ mt7530_mii_write(struct mt7530_priv *pri
394 return ret;
395 }
396
397 -static int
398 -mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
399 -{
400 - struct mii_bus *bus = context;
401 - u16 page, r, lo, hi;
402 - int ret;
403 -
404 - page = (reg >> 6) & 0x3ff;
405 - r = (reg >> 2) & 0xf;
406 -
407 - /* MT7530 uses 31 as the pseudo port */
408 - ret = bus->write(bus, 0x1f, 0x1f, page);
409 - if (ret < 0)
410 - return ret;
411 -
412 - lo = bus->read(bus, 0x1f, r);
413 - hi = bus->read(bus, 0x1f, 0x10);
414 -
415 - *val = (hi << 16) | (lo & 0xffff);
416 -
417 - return 0;
418 -}
419 -
420 static u32
421 mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
422 {
423 @@ -3008,72 +2959,6 @@ static const struct phylink_pcs_ops mt75
424 .pcs_an_restart = mt7530_pcs_an_restart,
425 };
426
427 -static void
428 -mt7530_mdio_regmap_lock(void *mdio_lock)
429 -{
430 - mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
431 -}
432 -
433 -static void
434 -mt7530_mdio_regmap_unlock(void *mdio_lock)
435 -{
436 - mutex_unlock(mdio_lock);
437 -}
438 -
439 -static const struct regmap_bus mt7530_regmap_bus = {
440 - .reg_write = mt7530_regmap_write,
441 - .reg_read = mt7530_regmap_read,
442 -};
443 -
444 -static int
445 -mt7531_create_sgmii(struct mt7530_priv *priv)
446 -{
447 - struct regmap_config *mt7531_pcs_config[2];
448 - struct phylink_pcs *pcs;
449 - struct regmap *regmap;
450 - int i, ret = 0;
451 -
452 - for (i = 0; i < 2; i++) {
453 - mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
454 - sizeof(struct regmap_config),
455 - GFP_KERNEL);
456 - if (!mt7531_pcs_config[i]) {
457 - ret = -ENOMEM;
458 - break;
459 - }
460 -
461 - mt7531_pcs_config[i]->name = i ? "port6" : "port5";
462 - mt7531_pcs_config[i]->reg_bits = 16;
463 - mt7531_pcs_config[i]->val_bits = 32;
464 - mt7531_pcs_config[i]->reg_stride = 4;
465 - mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
466 - mt7531_pcs_config[i]->max_register = 0x17c;
467 - mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
468 - mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
469 - mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
470 -
471 - regmap = devm_regmap_init(priv->dev,
472 - &mt7530_regmap_bus, priv->bus,
473 - mt7531_pcs_config[i]);
474 - if (IS_ERR(regmap)) {
475 - ret = PTR_ERR(regmap);
476 - break;
477 - }
478 - pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
479 - MT7531_PHYA_CTRL_SIGNAL3, 0);
480 - if (!pcs) {
481 - ret = -ENXIO;
482 - break;
483 - }
484 - priv->ports[5 + i].sgmii_pcs = pcs;
485 - }
486 -
487 - if (ret && i)
488 - mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
489 -
490 - return ret;
491 -}
492 -
493 static int
494 mt753x_setup(struct dsa_switch *ds)
495 {
496 @@ -3132,7 +3017,7 @@ static int mt753x_set_mac_eee(struct dsa
497 return 0;
498 }
499
500 -static const struct dsa_switch_ops mt7530_switch_ops = {
501 +const struct dsa_switch_ops mt7530_switch_ops = {
502 .get_tag_protocol = mtk_get_tag_protocol,
503 .setup = mt753x_setup,
504 .get_strings = mt7530_get_strings,
505 @@ -3166,8 +3051,9 @@ static const struct dsa_switch_ops mt753
506 .get_mac_eee = mt753x_get_mac_eee,
507 .set_mac_eee = mt753x_set_mac_eee,
508 };
509 +EXPORT_SYMBOL_GPL(mt7530_switch_ops);
510
511 -static const struct mt753x_info mt753x_table[] = {
512 +const struct mt753x_info mt753x_table[] = {
513 [ID_MT7621] = {
514 .id = ID_MT7621,
515 .pcs_ops = &mt7530_pcs_ops,
516 @@ -3200,16 +3086,9 @@ static const struct mt753x_info mt753x_t
517 .mac_port_config = mt7531_mac_config,
518 },
519 };
520 +EXPORT_SYMBOL_GPL(mt753x_table);
521
522 -static const struct of_device_id mt7530_of_match[] = {
523 - { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
524 - { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
525 - { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
526 - { /* sentinel */ },
527 -};
528 -MODULE_DEVICE_TABLE(of, mt7530_of_match);
529 -
530 -static int
531 +int
532 mt7530_probe_common(struct mt7530_priv *priv)
533 {
534 struct device *dev = priv->dev;
535 @@ -3246,88 +3125,9 @@ mt7530_probe_common(struct mt7530_priv *
536
537 return 0;
538 }
539 +EXPORT_SYMBOL_GPL(mt7530_probe_common);
540
541 -static int
542 -mt7530_probe(struct mdio_device *mdiodev)
543 -{
544 - static struct regmap_config *regmap_config;
545 - struct mt7530_priv *priv;
546 - struct device_node *dn;
547 - int ret;
548 -
549 - dn = mdiodev->dev.of_node;
550 -
551 - priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
552 - if (!priv)
553 - return -ENOMEM;
554 -
555 - priv->bus = mdiodev->bus;
556 - priv->dev = &mdiodev->dev;
557 -
558 - ret = mt7530_probe_common(priv);
559 - if (ret)
560 - return ret;
561 -
562 - /* Use medatek,mcm property to distinguish hardware type that would
563 - * cause a little bit differences on power-on sequence.
564 - * Not MCM that indicates switch works as the remote standalone
565 - * integrated circuit so the GPIO pin would be used to complete
566 - * the reset, otherwise memory-mapped register accessing used
567 - * through syscon provides in the case of MCM.
568 - */
569 - priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
570 - if (priv->mcm) {
571 - dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
572 -
573 - priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
574 - if (IS_ERR(priv->rstc)) {
575 - dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
576 - return PTR_ERR(priv->rstc);
577 - }
578 - } else {
579 - priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
580 - GPIOD_OUT_LOW);
581 - if (IS_ERR(priv->reset)) {
582 - dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
583 - return PTR_ERR(priv->reset);
584 - }
585 - }
586 -
587 - if (priv->id == ID_MT7530) {
588 - priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
589 - if (IS_ERR(priv->core_pwr))
590 - return PTR_ERR(priv->core_pwr);
591 -
592 - priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
593 - if (IS_ERR(priv->io_pwr))
594 - return PTR_ERR(priv->io_pwr);
595 - }
596 -
597 - regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
598 - GFP_KERNEL);
599 - if (!regmap_config)
600 - return -ENOMEM;
601 -
602 - regmap_config->reg_bits = 16;
603 - regmap_config->val_bits = 32;
604 - regmap_config->reg_stride = 4;
605 - regmap_config->max_register = MT7530_CREV;
606 - regmap_config->disable_locking = true;
607 - priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
608 - priv->bus, regmap_config);
609 - if (IS_ERR(priv->regmap))
610 - return PTR_ERR(priv->regmap);
611 -
612 - if (priv->id == ID_MT7531) {
613 - ret = mt7531_create_sgmii(priv);
614 - if (ret)
615 - return ret;
616 - }
617 -
618 - return dsa_register_switch(priv->ds);
619 -}
620 -
621 -static void
622 +void
623 mt7530_remove_common(struct mt7530_priv *priv)
624 {
625 if (priv->irq)
626 @@ -3337,55 +3137,7 @@ mt7530_remove_common(struct mt7530_priv
627
628 mutex_destroy(&priv->reg_mutex);
629 }
630 -
631 -static void
632 -mt7530_remove(struct mdio_device *mdiodev)
633 -{
634 - struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
635 - int ret = 0, i;
636 -
637 - if (!priv)
638 - return;
639 -
640 - ret = regulator_disable(priv->core_pwr);
641 - if (ret < 0)
642 - dev_err(priv->dev,
643 - "Failed to disable core power: %d\n", ret);
644 -
645 - ret = regulator_disable(priv->io_pwr);
646 - if (ret < 0)
647 - dev_err(priv->dev, "Failed to disable io pwr: %d\n",
648 - ret);
649 -
650 - mt7530_remove_common(priv);
651 -
652 - for (i = 0; i < 2; ++i)
653 - mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
654 -}
655 -
656 -static void mt7530_shutdown(struct mdio_device *mdiodev)
657 -{
658 - struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
659 -
660 - if (!priv)
661 - return;
662 -
663 - dsa_switch_shutdown(priv->ds);
664 -
665 - dev_set_drvdata(&mdiodev->dev, NULL);
666 -}
667 -
668 -static struct mdio_driver mt7530_mdio_driver = {
669 - .probe = mt7530_probe,
670 - .remove = mt7530_remove,
671 - .shutdown = mt7530_shutdown,
672 - .mdiodrv.driver = {
673 - .name = "mt7530",
674 - .of_match_table = mt7530_of_match,
675 - },
676 -};
677 -
678 -mdio_module_driver(mt7530_mdio_driver);
679 +EXPORT_SYMBOL_GPL(mt7530_remove_common);
680
681 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
682 MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
683 --- a/drivers/net/dsa/mt7530.h
684 +++ b/drivers/net/dsa/mt7530.h
685 @@ -834,4 +834,10 @@ static inline void INIT_MT7530_DUMMY_POL
686 p->reg = reg;
687 }
688
689 +int mt7530_probe_common(struct mt7530_priv *priv);
690 +void mt7530_remove_common(struct mt7530_priv *priv);
691 +
692 +extern const struct dsa_switch_ops mt7530_switch_ops;
693 +extern const struct mt753x_info mt753x_table[];
694 +
695 #endif /* __MT7530_H */