net: add MV88E6xxx DSA driver
[platform/kernel/u-boot.git] / drivers / net / mv88e6xxx.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2022
4  * Gateworks Corporation <www.gateworks.com>
5  * Tim Harvey <tharvey@gateworks.com>
6  *
7  * (C) Copyright 2015
8  * Elecsys Corporation <www.elecsyscorp.com>
9  * Kevin Smith <kevin.smith@elecsyscorp.com>
10  *
11  * Original driver:
12  * (C) Copyright 2009
13  * Marvell Semiconductor <www.marvell.com>
14  * Prafulla Wadaskar <prafulla@marvell.com>
15  */
16
17 /*
18  * DSA driver for mv88e6xxx ethernet switches.
19  *
20  * This driver configures the mv88e6xxx for basic use as a DSA switch.
21  *
22  * This driver was adapted from drivers/net/phy/mv88e61xx and tested
23  * on the mv88e6176 via an SGMII interface.
24  */
25
26 #include <common.h>
27 #include <dm/device.h>
28 #include <dm/device_compat.h>
29 #include <dm/device-internal.h>
30 #include <dm/lists.h>
31 #include <dm/of_extra.h>
32 #include <linux/delay.h>
33 #include <miiphy.h>
34 #include <net/dsa.h>
35
36 /* Device addresses */
37 #define DEVADDR_PHY(p)                  (p)
38 #define DEVADDR_SERDES                  0x0F
39
40 /* SMI indirection registers for multichip addressing mode */
41 #define SMI_CMD_REG                     0x00
42 #define SMI_DATA_REG                    0x01
43
44 /* Global registers */
45 #define GLOBAL1_STATUS                  0x00
46 #define GLOBAL1_CTRL                    0x04
47
48 /* Global 2 registers */
49 #define GLOBAL2_REG_PHY_CMD             0x18
50 #define GLOBAL2_REG_PHY_DATA            0x19
51 #define GLOBAL2_REG_SCRATCH             0x1A
52
53 /* Port registers */
54 #define PORT_REG_STATUS                 0x00
55 #define PORT_REG_PHYS_CTRL              0x01
56 #define PORT_REG_SWITCH_ID              0x03
57 #define PORT_REG_CTRL                   0x04
58
59 /* Phy registers */
60 #define PHY_REG_PAGE                    0x16
61
62 /* Phy page numbers */
63 #define PHY_PAGE_COPPER                 0
64 #define PHY_PAGE_SERDES                 1
65
66 /* Register fields */
67 #define GLOBAL1_CTRL_SWRESET            BIT(15)
68
69 #define PORT_REG_STATUS_SPEED_SHIFT     8
70 #define PORT_REG_STATUS_SPEED_10        0
71 #define PORT_REG_STATUS_SPEED_100       1
72 #define PORT_REG_STATUS_SPEED_1000      2
73
74 #define PORT_REG_STATUS_CMODE_MASK              0xF
75 #define PORT_REG_STATUS_CMODE_SGMII             0xa
76 #define PORT_REG_STATUS_CMODE_1000BASE_X        0x9
77 #define PORT_REG_STATUS_CMODE_100BASE_X         0x8
78 #define PORT_REG_STATUS_CMODE_RGMII             0x7
79 #define PORT_REG_STATUS_CMODE_RMII              0x5
80 #define PORT_REG_STATUS_CMODE_RMII_PHY          0x4
81 #define PORT_REG_STATUS_CMODE_GMII              0x3
82 #define PORT_REG_STATUS_CMODE_MII               0x2
83 #define PORT_REG_STATUS_CMODE_MIIPHY            0x1
84
85 #define PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK    BIT(15)
86 #define PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK    BIT(14)
87 #define PORT_REG_PHYS_CTRL_PCS_AN_EN    BIT(10)
88 #define PORT_REG_PHYS_CTRL_PCS_AN_RST   BIT(9)
89 #define PORT_REG_PHYS_CTRL_FC_VALUE     BIT(7)
90 #define PORT_REG_PHYS_CTRL_FC_FORCE     BIT(6)
91 #define PORT_REG_PHYS_CTRL_LINK_VALUE   BIT(5)
92 #define PORT_REG_PHYS_CTRL_LINK_FORCE   BIT(4)
93 #define PORT_REG_PHYS_CTRL_DUPLEX_VALUE BIT(3)
94 #define PORT_REG_PHYS_CTRL_DUPLEX_FORCE BIT(2)
95 #define PORT_REG_PHYS_CTRL_SPD1000      BIT(1)
96 #define PORT_REG_PHYS_CTRL_SPD100       BIT(0)
97 #define PORT_REG_PHYS_CTRL_SPD_MASK     (BIT(1) | BIT(0))
98
99 #define PORT_REG_CTRL_PSTATE_SHIFT      0
100 #define PORT_REG_CTRL_PSTATE_MASK       3
101
102 /* Field values */
103 #define PORT_REG_CTRL_PSTATE_DISABLED   0
104 #define PORT_REG_CTRL_PSTATE_FORWARD    3
105
106 /*
107  * Macros for building commands for indirect addressing modes.  These are valid
108  * for both the indirect multichip addressing mode and the PHY indirection
109  * required for the writes to any PHY register.
110  */
111 #define SMI_BUSY                        BIT(15)
112 #define SMI_CMD_CLAUSE_22               BIT(12)
113 #define SMI_CMD_CLAUSE_22_OP_READ       (2 << 10)
114 #define SMI_CMD_CLAUSE_22_OP_WRITE      (1 << 10)
115 #define SMI_CMD_ADDR_SHIFT              5
116 #define SMI_CMD_ADDR_MASK               0x1f
117 #define SMI_CMD_REG_SHIFT               0
118 #define SMI_CMD_REG_MASK                0x1f
119 #define SMI_CMD_READ(addr, reg) \
120         (SMI_BUSY | SMI_CMD_CLAUSE_22 | SMI_CMD_CLAUSE_22_OP_READ) | \
121         (((addr) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
122         (((reg) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
123 #define SMI_CMD_WRITE(addr, reg) \
124         (SMI_BUSY | SMI_CMD_CLAUSE_22 | SMI_CMD_CLAUSE_22_OP_WRITE) | \
125         (((addr) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
126         (((reg) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
127
128 /* ID register values for different switch models */
129 #define PORT_SWITCH_ID_6020             0x0200
130 #define PORT_SWITCH_ID_6070             0x0700
131 #define PORT_SWITCH_ID_6071             0x0710
132 #define PORT_SWITCH_ID_6096             0x0980
133 #define PORT_SWITCH_ID_6097             0x0990
134 #define PORT_SWITCH_ID_6172             0x1720
135 #define PORT_SWITCH_ID_6176             0x1760
136 #define PORT_SWITCH_ID_6220             0x2200
137 #define PORT_SWITCH_ID_6240             0x2400
138 #define PORT_SWITCH_ID_6250             0x2500
139 #define PORT_SWITCH_ID_6320             0x1150
140 #define PORT_SWITCH_ID_6352             0x3520
141
142 struct mv88e6xxx_priv {
143         int smi_addr;
144         int id;
145         int port_count;         /* Number of switch ports */
146         int port_reg_base;      /* Base of the switch port registers */
147         u8 global1;     /* Offset of Switch Global 1 registers */
148         u8 global2;     /* Offset of Switch Global 2 registers */
149 };
150
151 /* Wait for the current SMI indirect command to complete */
152 static int mv88e6xxx_smi_wait(struct udevice *dev, int smi_addr)
153 {
154         int val;
155         u32 timeout = 100;
156
157         do {
158                 val = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG);
159                 if (val >= 0 && (val & SMI_BUSY) == 0)
160                         return 0;
161
162                 mdelay(1);
163         } while (--timeout);
164
165         dev_err(dev, "SMI busy timeout\n");
166         return -ETIMEDOUT;
167 }
168
169 /*
170  * The mv88e6xxx has three types of addresses: the smi bus address, the device
171  * address, and the register address.  The smi bus address distinguishes it on
172  * the smi bus from other PHYs or switches.  The device address determines
173  * which on-chip register set you are reading/writing (the various PHYs, their
174  * associated ports, or global configuration registers).  The register address
175  * is the offset of the register you are reading/writing.
176  *
177  * When the mv88e6xxx is hardware configured to have address zero, it behaves in
178  * single-chip addressing mode, where it responds to all SMI addresses, using
179  * the smi address as its device address.  This obviously only works when this
180  * is the only chip on the SMI bus.  This allows the driver to access device
181  * registers without using indirection.  When the chip is configured to a
182  * non-zero address, it only responds to that SMI address and requires indirect
183  * writes to access the different device addresses.
184  */
185 static int mv88e6xxx_reg_read(struct udevice *dev, int addr, int reg)
186 {
187         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
188         int smi_addr = priv->smi_addr;
189         int res;
190
191         /* In single-chip mode, the device can be addressed directly */
192         if (smi_addr == 0)
193                 return dm_mdio_read(dev->parent, addr, MDIO_DEVAD_NONE, reg);
194
195         /* Wait for the bus to become free */
196         res = mv88e6xxx_smi_wait(dev, smi_addr);
197         if (res < 0)
198                 return res;
199
200         /* Issue the read command */
201         res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG,
202                             SMI_CMD_READ(addr, reg));
203         if (res < 0)
204                 return res;
205
206         /* Wait for the read command to complete */
207         res = mv88e6xxx_smi_wait(dev, smi_addr);
208         if (res < 0)
209                 return res;
210
211         /* Read the data */
212         res = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_DATA_REG);
213         if (res < 0)
214                 return res;
215
216         return res & 0xffff;
217 }
218
219 /* See the comment above mv88e6xxx_reg_read */
220 static int mv88e6xxx_reg_write(struct udevice *dev, int addr, int reg, u16 val)
221 {
222         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
223         int smi_addr = priv->smi_addr;
224         int res;
225
226         /* In single-chip mode, the device can be addressed directly */
227         if (smi_addr == 0)
228                 return dm_mdio_write(dev->parent, addr, MDIO_DEVAD_NONE, reg, val);
229
230         /* Wait for the bus to become free */
231         res = mv88e6xxx_smi_wait(dev, smi_addr);
232         if (res < 0)
233                 return res;
234
235         /* Set the data to write */
236         res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE,
237                             SMI_DATA_REG, val);
238         if (res < 0)
239                 return res;
240
241         /* Issue the write command */
242         res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG,
243                             SMI_CMD_WRITE(addr, reg));
244         if (res < 0)
245                 return res;
246
247         /* Wait for the write command to complete */
248         res = mv88e6xxx_smi_wait(dev, smi_addr);
249         if (res < 0)
250                 return res;
251
252         return 0;
253 }
254
255 static int mv88e6xxx_phy_wait(struct udevice *dev)
256 {
257         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
258         int val;
259         u32 timeout = 100;
260
261         do {
262                 val = mv88e6xxx_reg_read(dev, priv->global2, GLOBAL2_REG_PHY_CMD);
263                 if (val >= 0 && (val & SMI_BUSY) == 0)
264                         return 0;
265
266                 mdelay(1);
267         } while (--timeout);
268
269         return -ETIMEDOUT;
270 }
271
272 static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad, int reg)
273 {
274         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
275         int res;
276
277         /* Issue command to read */
278         res = mv88e6xxx_reg_write(dev, priv->global2,
279                                   GLOBAL2_REG_PHY_CMD,
280                                   SMI_CMD_READ(phyad, reg));
281
282         /* Wait for data to be read */
283         res = mv88e6xxx_phy_wait(dev);
284         if (res < 0)
285                 return res;
286
287         /* Read retrieved data */
288         return mv88e6xxx_reg_read(dev, priv->global2,
289                                   GLOBAL2_REG_PHY_DATA);
290 }
291
292 static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
293                                         int devad, int reg, u16 data)
294 {
295         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
296         int res;
297
298         /* Set the data to write */
299         res = mv88e6xxx_reg_write(dev, priv->global2,
300                                   GLOBAL2_REG_PHY_DATA, data);
301         if (res < 0)
302                 return res;
303         /* Issue the write command */
304         res = mv88e6xxx_reg_write(dev, priv->global2,
305                                   GLOBAL2_REG_PHY_CMD,
306                                   SMI_CMD_WRITE(phyad, reg));
307         if (res < 0)
308                 return res;
309
310         /* Wait for command to complete */
311         return mv88e6xxx_phy_wait(dev);
312 }
313
314 /* Wrapper function to make calls to phy_read_indirect simpler */
315 static int mv88e6xxx_phy_read(struct udevice *dev, int phy, int reg)
316 {
317         return mv88e6xxx_phy_read_indirect(dev, DEVADDR_PHY(phy),
318                                            MDIO_DEVAD_NONE, reg);
319 }
320
321 /* Wrapper function to make calls to phy_write_indirect simpler */
322 static int mv88e6xxx_phy_write(struct udevice *dev, int phy, int reg, u16 val)
323 {
324         return mv88e6xxx_phy_write_indirect(dev, DEVADDR_PHY(phy),
325                                             MDIO_DEVAD_NONE, reg, val);
326 }
327
328 static int mv88e6xxx_port_read(struct udevice *dev, u8 port, u8 reg)
329 {
330         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
331
332         return mv88e6xxx_reg_read(dev, priv->port_reg_base + port, reg);
333 }
334
335 static int mv88e6xxx_port_write(struct udevice *dev, u8 port, u8 reg, u16 val)
336 {
337         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
338
339         return mv88e6xxx_reg_write(dev, priv->port_reg_base + port, reg, val);
340 }
341
342 static int mv88e6xxx_set_page(struct udevice *dev, u8 phy, u8 page)
343 {
344         return mv88e6xxx_phy_write(dev, phy, PHY_REG_PAGE, page);
345 }
346
347 static int mv88e6xxx_get_switch_id(struct udevice *dev)
348 {
349         int res;
350
351         res = mv88e6xxx_port_read(dev, 0, PORT_REG_SWITCH_ID);
352         if (res < 0) {
353                 dev_err(dev, "Failed to read switch ID: %d\n", res);
354                 return res;
355         }
356         return res & 0xfff0;
357 }
358
359 static bool mv88e6xxx_6352_family(struct udevice *dev)
360 {
361         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
362
363         switch (priv->id) {
364         case PORT_SWITCH_ID_6172:
365         case PORT_SWITCH_ID_6176:
366         case PORT_SWITCH_ID_6240:
367         case PORT_SWITCH_ID_6352:
368                 return true;
369         }
370         return false;
371 }
372
373 static int mv88e6xxx_get_cmode(struct udevice *dev, u8 port)
374 {
375         int res;
376
377         res = mv88e6xxx_port_read(dev, port, PORT_REG_STATUS);
378         if (res < 0)
379                 return res;
380         return res & PORT_REG_STATUS_CMODE_MASK;
381 }
382
383 static int mv88e6xxx_switch_reset(struct udevice *dev)
384 {
385         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
386         int time_ms;
387         int val;
388         u8 port;
389
390         /* Disable all ports */
391         for (port = 0; port < priv->port_count; port++) {
392                 val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
393                 if (val < 0)
394                         return val;
395                 val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
396                 val |= (PORT_REG_CTRL_PSTATE_DISABLED << PORT_REG_CTRL_PSTATE_SHIFT);
397                 val = mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
398                 if (val < 0)
399                         return val;
400         }
401
402         /* Wait 2 ms for queues to drain */
403         udelay(2000);
404
405         /* Reset switch */
406         val = mv88e6xxx_reg_read(dev, priv->global1, GLOBAL1_CTRL);
407         if (val < 0)
408                 return val;
409         val |= GLOBAL1_CTRL_SWRESET;
410         val = mv88e6xxx_reg_write(dev, priv->global1, GLOBAL1_CTRL, val);
411         if (val < 0)
412                 return val;
413
414         /* Wait up to 1 second for switch to reset complete */
415         for (time_ms = 1000; time_ms; time_ms--) {
416                 val = mv88e6xxx_reg_read(dev, priv->global1, GLOBAL1_CTRL);
417                 if (val >= 0 && ((val & GLOBAL1_CTRL_SWRESET) == 0))
418                         break;
419                 udelay(1000);
420         }
421         if (!time_ms)
422                 return -ETIMEDOUT;
423
424         return 0;
425 }
426
427 static int mv88e6xxx_serdes_init(struct udevice *dev)
428 {
429         int val;
430
431         val = mv88e6xxx_set_page(dev, DEVADDR_SERDES, PHY_PAGE_SERDES);
432         if (val < 0)
433                 return val;
434
435         /* Power up serdes module */
436         val = mv88e6xxx_phy_read(dev, DEVADDR_SERDES, MII_BMCR);
437         if (val < 0)
438                 return val;
439         val &= ~(BMCR_PDOWN);
440         val = mv88e6xxx_phy_write(dev, DEVADDR_SERDES, MII_BMCR, val);
441         if (val < 0)
442                 return val;
443
444         return 0;
445 }
446
447 /*
448  * This function is used to pre-configure the required register
449  * offsets, so that the indirect register access to the PHY registers
450  * is possible. This is necessary to be able to read the PHY ID
451  * while driver probing or in get_phy_id(). The globalN register
452  * offsets must be initialized correctly for a detected switch,
453  * otherwise detection of the PHY ID won't work!
454  */
455 static int mv88e6xxx_priv_reg_offs_pre_init(struct udevice *dev)
456 {
457         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
458
459         /*
460          * Initial 'port_reg_base' value must be an offset of existing
461          * port register, then reading the ID should succeed. First, try
462          * to read via port registers with device address 0x10 (88E6096
463          * and compatible switches).
464          */
465         priv->port_reg_base = 0x10;
466         priv->id = mv88e6xxx_get_switch_id(dev);
467         if (priv->id != 0xfff0) {
468                 priv->global1 = 0x1B;
469                 priv->global2 = 0x1C;
470                 return 0;
471         }
472
473         /*
474          * Now try via port registers with device address 0x08
475          * (88E6020 and compatible switches).
476          */
477         priv->port_reg_base = 0x08;
478         priv->id = mv88e6xxx_get_switch_id(dev);
479         if (priv->id != 0xfff0) {
480                 priv->global1 = 0x0F;
481                 priv->global2 = 0x07;
482                 return 0;
483         }
484
485         dev_warn(dev, "%s Unknown ID 0x%x\n", __func__, priv->id);
486
487         return -ENODEV;
488 }
489
490 static int mv88e6xxx_mdio_read(struct udevice *dev, int addr, int devad, int reg)
491 {
492         return mv88e6xxx_phy_read_indirect(dev->parent, DEVADDR_PHY(addr),
493                                            MDIO_DEVAD_NONE, reg);
494 }
495
496 static int mv88e6xxx_mdio_write(struct udevice *dev, int addr, int devad,
497                                 int reg, u16 val)
498 {
499         return mv88e6xxx_phy_write_indirect(dev->parent, DEVADDR_PHY(addr),
500                                             MDIO_DEVAD_NONE, reg, val);
501 }
502
503 static const struct mdio_ops mv88e6xxx_mdio_ops = {
504         .read = mv88e6xxx_mdio_read,
505         .write = mv88e6xxx_mdio_write,
506 };
507
508 static int mv88e6xxx_mdio_bind(struct udevice *dev)
509 {
510         char name[32];
511         static int num_devices;
512
513         sprintf(name, "mv88e6xxx-mdio-%d", num_devices++);
514         device_set_name(dev, name);
515
516         return 0;
517 }
518
519 U_BOOT_DRIVER(mv88e6xxx_mdio) = {
520         .name           = "mv88e6xxx_mdio",
521         .id             = UCLASS_MDIO,
522         .ops            = &mv88e6xxx_mdio_ops,
523         .bind           = mv88e6xxx_mdio_bind,
524         .plat_auto      = sizeof(struct mdio_perdev_priv),
525 };
526
527 static int mv88e6xxx_port_probe(struct udevice *dev, int port, struct phy_device *phy)
528 {
529         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
530         int supported;
531
532         switch (priv->id) {
533         case PORT_SWITCH_ID_6020:
534         case PORT_SWITCH_ID_6070:
535         case PORT_SWITCH_ID_6071:
536                 supported = PHY_BASIC_FEATURES | SUPPORTED_MII;
537                 break;
538         default:
539                 supported = PHY_GBIT_FEATURES;
540                 break;
541         }
542
543         phy->supported &= supported;
544         phy->advertising &= supported;
545
546         return phy_config(phy);
547 }
548
549 static int mv88e6xxx_port_enable(struct udevice *dev, int port, struct phy_device *phy)
550 {
551         int val, ret;
552
553         dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
554                 phy->phy_id, phy_string_for_interface(phy->interface));
555
556         if (phy->phy_id == PHY_FIXED_ID) {
557                 /* Physical Control register: Table 62 */
558                 val = mv88e6xxx_port_read(dev, port, PORT_REG_PHYS_CTRL);
559
560                 /* configure RGMII delays for fixed link */
561                 switch (phy->interface) {
562                 case PHY_INTERFACE_MODE_RGMII:
563                 case PHY_INTERFACE_MODE_RGMII_ID:
564                 case PHY_INTERFACE_MODE_RGMII_RXID:
565                 case PHY_INTERFACE_MODE_RGMII_TXID:
566                         dev_dbg(dev, "configure internal RGMII delays\n");
567
568                         /* RGMII delays */
569                         val &= ~(PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK ||
570                                  PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK);
571                         if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
572                             phy->interface == PHY_INTERFACE_MODE_RGMII_RXID)
573                                 val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK;
574                         if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
575                             phy->interface == PHY_INTERFACE_MODE_RGMII_TXID)
576                                 val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK;
577                         break;
578                 default:
579                         break;
580                 }
581
582                 /* Force Link */
583                 val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
584                        PORT_REG_PHYS_CTRL_LINK_FORCE;
585
586                 ret = mv88e6xxx_port_write(dev, port, PORT_REG_PHYS_CTRL, val);
587                 if (ret < 0)
588                         return ret;
589
590                 if (mv88e6xxx_6352_family(dev)) {
591                         /* validate interface type */
592                         dev_dbg(dev, "validate interface type\n");
593                         val = mv88e6xxx_get_cmode(dev, port);
594                         if (val < 0)
595                                 return val;
596                         switch (phy->interface) {
597                         case PHY_INTERFACE_MODE_RGMII:
598                         case PHY_INTERFACE_MODE_RGMII_RXID:
599                         case PHY_INTERFACE_MODE_RGMII_TXID:
600                         case PHY_INTERFACE_MODE_RGMII_ID:
601                                 if (val != PORT_REG_STATUS_CMODE_RGMII)
602                                         goto mismatch;
603                                 break;
604                         case PHY_INTERFACE_MODE_1000BASEX:
605                                 if (val != PORT_REG_STATUS_CMODE_1000BASE_X)
606                                         goto mismatch;
607                                 break;
608 mismatch:
609                         default:
610                                 dev_err(dev, "Mismatched PHY mode %s on port %d!\n",
611                                         phy_string_for_interface(phy->interface), port);
612                                 break;
613                         }
614                 }
615         }
616
617         /* enable port */
618         val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
619         if (val < 0)
620                 return val;
621         val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
622         val |= (PORT_REG_CTRL_PSTATE_FORWARD << PORT_REG_CTRL_PSTATE_SHIFT);
623         val = mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
624         if (val < 0)
625                 return val;
626
627         return phy_startup(phy);
628 }
629
630 static void mv88e6xxx_port_disable(struct udevice *dev, int port, struct phy_device *phy)
631 {
632         int val;
633
634         dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
635                 phy->phy_id, phy_string_for_interface(phy->interface));
636
637         val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
638         val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT);
639         val |= (PORT_REG_CTRL_PSTATE_DISABLED << PORT_REG_CTRL_PSTATE_SHIFT);
640         mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val);
641 }
642
643 static const struct dsa_ops mv88e6xxx_dsa_ops = {
644         .port_probe = mv88e6xxx_port_probe,
645         .port_enable = mv88e6xxx_port_enable,
646         .port_disable = mv88e6xxx_port_disable,
647 };
648
649 /* bind and probe the switch mdios */
650 static int mv88e6xxx_probe_mdio(struct udevice *dev)
651 {
652         struct udevice *mdev;
653         const char *name;
654         ofnode node;
655         int ret;
656
657         /* bind phy ports of mdio child node to mv88e6xxx_mdio device */
658         node = dev_read_subnode(dev, "mdio");
659         if (!ofnode_valid(node))
660                 return 0;
661
662         name = ofnode_get_name(node);
663         ret = device_bind_driver_to_node(dev,
664                                          "mv88e6xxx_mdio",
665                                          name, node, NULL);
666         if (ret) {
667                 dev_err(dev, "failed to bind %s: %d\n", name, ret);
668         } else {
669                 /* need to probe it as there is no compatible to do so */
670                 ret = uclass_get_device_by_ofnode(UCLASS_MDIO, node, &mdev);
671                 if (ret)
672                         dev_err(dev, "failed to probe %s: %d\n", name, ret);
673         }
674
675         return ret;
676 }
677
678 static int mv88e6xxx_probe(struct udevice *dev)
679 {
680         struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
681         struct mv88e6xxx_priv *priv = dev_get_priv(dev);
682         int val, ret;
683
684         if (ofnode_valid(dev_ofnode(dev)) &&
685             !ofnode_is_enabled(dev_ofnode(dev))) {
686                 dev_dbg(dev, "switch disabled\n");
687                 return -ENODEV;
688         }
689
690         /* probe internal mdio bus */
691         ret = mv88e6xxx_probe_mdio(dev);
692         if (ret)
693                 return ret;
694
695         ret = mv88e6xxx_priv_reg_offs_pre_init(dev);
696         if (ret)
697                 return ret;
698
699         dev_dbg(dev, "ID=0x%x PORT_BASE=0x%02x GLOBAL1=0x%02x GLOBAL2=0x%02x\n",
700                 priv->id, priv->port_reg_base, priv->global1, priv->global2);
701         switch (priv->id) {
702         case PORT_SWITCH_ID_6096:
703         case PORT_SWITCH_ID_6097:
704         case PORT_SWITCH_ID_6172:
705         case PORT_SWITCH_ID_6176:
706         case PORT_SWITCH_ID_6240:
707         case PORT_SWITCH_ID_6352:
708                 priv->port_count = 11;
709                 break;
710         case PORT_SWITCH_ID_6020:
711         case PORT_SWITCH_ID_6070:
712         case PORT_SWITCH_ID_6071:
713         case PORT_SWITCH_ID_6220:
714         case PORT_SWITCH_ID_6250:
715         case PORT_SWITCH_ID_6320:
716                 priv->port_count = 7;
717                 break;
718         default:
719                 return -ENODEV;
720         }
721
722         ret = mv88e6xxx_switch_reset(dev);
723         if (ret < 0)
724                 return ret;
725
726         if (mv88e6xxx_6352_family(dev)) {
727                 val = mv88e6xxx_get_cmode(dev, dsa_pdata->cpu_port);
728                 if (val < 0)
729                         return val;
730                 /* initialize serdes */
731                 if (val == PORT_REG_STATUS_CMODE_100BASE_X ||
732                     val == PORT_REG_STATUS_CMODE_1000BASE_X ||
733                     val == PORT_REG_STATUS_CMODE_SGMII) {
734                         ret = mv88e6xxx_serdes_init(dev);
735                         if (ret < 0)
736                                 return ret;
737                 }
738         }
739
740         return 0;
741 }
742
743 static const struct udevice_id mv88e6xxx_ids[] = {
744         { .compatible = "marvell,mv88e6085" },
745         { }
746 };
747
748 U_BOOT_DRIVER(mv88e6xxx) = {
749         .name           = "mv88e6xxx",
750         .id             = UCLASS_DSA,
751         .of_match       = mv88e6xxx_ids,
752         .probe          = mv88e6xxx_probe,
753         .ops            = &mv88e6xxx_dsa_ops,
754         .priv_auto      = sizeof(struct mv88e6xxx_priv),
755 };