1 // SPDX-License-Identifier: GPL-2.0+
4 * Gateworks Corporation <www.gateworks.com>
5 * Tim Harvey <tharvey@gateworks.com>
8 * Elecsys Corporation <www.elecsyscorp.com>
9 * Kevin Smith <kevin.smith@elecsyscorp.com>
13 * Marvell Semiconductor <www.marvell.com>
14 * Prafulla Wadaskar <prafulla@marvell.com>
18 * DSA driver for mv88e6xxx ethernet switches.
20 * This driver configures the mv88e6xxx for basic use as a DSA switch.
22 * This driver was adapted from drivers/net/phy/mv88e61xx and tested
23 * on the mv88e6176 via an SGMII interface.
27 #include <dm/device.h>
28 #include <dm/device_compat.h>
29 #include <dm/device-internal.h>
31 #include <dm/of_extra.h>
32 #include <linux/delay.h>
36 /* Device addresses */
37 #define DEVADDR_PHY(p) (p)
38 #define DEVADDR_SERDES 0x0F
40 /* SMI indirection registers for multichip addressing mode */
41 #define SMI_CMD_REG 0x00
42 #define SMI_DATA_REG 0x01
44 /* Global registers */
45 #define GLOBAL1_STATUS 0x00
46 #define GLOBAL1_CTRL 0x04
48 /* Global 2 registers */
49 #define GLOBAL2_REG_PHY_CMD 0x18
50 #define GLOBAL2_REG_PHY_DATA 0x19
51 #define GLOBAL2_REG_SCRATCH 0x1A
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
60 #define PHY_REG_PAGE 0x16
62 /* Phy page numbers */
63 #define PHY_PAGE_COPPER 0
64 #define PHY_PAGE_SERDES 1
67 #define GLOBAL1_CTRL_SWRESET BIT(15)
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
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
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))
99 #define PORT_REG_CTRL_PSTATE_SHIFT 0
100 #define PORT_REG_CTRL_PSTATE_MASK 3
103 #define PORT_REG_CTRL_PSTATE_DISABLED 0
104 #define PORT_REG_CTRL_PSTATE_FORWARD 3
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.
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)
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
142 struct mv88e6xxx_priv {
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 */
151 /* Wait for the current SMI indirect command to complete */
152 static int mv88e6xxx_smi_wait(struct udevice *dev, int smi_addr)
158 val = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_CMD_REG);
159 if (val >= 0 && (val & SMI_BUSY) == 0)
165 dev_err(dev, "SMI busy timeout\n");
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.
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.
185 static int mv88e6xxx_reg_read(struct udevice *dev, int addr, int reg)
187 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
188 int smi_addr = priv->smi_addr;
191 /* In single-chip mode, the device can be addressed directly */
193 return dm_mdio_read(dev->parent, addr, MDIO_DEVAD_NONE, reg);
195 /* Wait for the bus to become free */
196 res = mv88e6xxx_smi_wait(dev, smi_addr);
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));
206 /* Wait for the read command to complete */
207 res = mv88e6xxx_smi_wait(dev, smi_addr);
212 res = dm_mdio_read(dev->parent, smi_addr, MDIO_DEVAD_NONE, SMI_DATA_REG);
219 /* See the comment above mv88e6xxx_reg_read */
220 static int mv88e6xxx_reg_write(struct udevice *dev, int addr, int reg, u16 val)
222 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
223 int smi_addr = priv->smi_addr;
226 /* In single-chip mode, the device can be addressed directly */
228 return dm_mdio_write(dev->parent, addr, MDIO_DEVAD_NONE, reg, val);
230 /* Wait for the bus to become free */
231 res = mv88e6xxx_smi_wait(dev, smi_addr);
235 /* Set the data to write */
236 res = dm_mdio_write(dev->parent, smi_addr, MDIO_DEVAD_NONE,
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));
247 /* Wait for the write command to complete */
248 res = mv88e6xxx_smi_wait(dev, smi_addr);
255 static int mv88e6xxx_phy_wait(struct udevice *dev)
257 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
262 val = mv88e6xxx_reg_read(dev, priv->global2, GLOBAL2_REG_PHY_CMD);
263 if (val >= 0 && (val & SMI_BUSY) == 0)
272 static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad, int reg)
274 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
277 /* Issue command to read */
278 res = mv88e6xxx_reg_write(dev, priv->global2,
280 SMI_CMD_READ(phyad, reg));
282 /* Wait for data to be read */
283 res = mv88e6xxx_phy_wait(dev);
287 /* Read retrieved data */
288 return mv88e6xxx_reg_read(dev, priv->global2,
289 GLOBAL2_REG_PHY_DATA);
292 static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
293 int devad, int reg, u16 data)
295 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
298 /* Set the data to write */
299 res = mv88e6xxx_reg_write(dev, priv->global2,
300 GLOBAL2_REG_PHY_DATA, data);
303 /* Issue the write command */
304 res = mv88e6xxx_reg_write(dev, priv->global2,
306 SMI_CMD_WRITE(phyad, reg));
310 /* Wait for command to complete */
311 return mv88e6xxx_phy_wait(dev);
314 /* Wrapper function to make calls to phy_read_indirect simpler */
315 static int mv88e6xxx_phy_read(struct udevice *dev, int phy, int reg)
317 return mv88e6xxx_phy_read_indirect(dev, DEVADDR_PHY(phy),
318 MDIO_DEVAD_NONE, reg);
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)
324 return mv88e6xxx_phy_write_indirect(dev, DEVADDR_PHY(phy),
325 MDIO_DEVAD_NONE, reg, val);
328 static int mv88e6xxx_port_read(struct udevice *dev, u8 port, u8 reg)
330 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
332 return mv88e6xxx_reg_read(dev, priv->port_reg_base + port, reg);
335 static int mv88e6xxx_port_write(struct udevice *dev, u8 port, u8 reg, u16 val)
337 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
339 return mv88e6xxx_reg_write(dev, priv->port_reg_base + port, reg, val);
342 static int mv88e6xxx_set_page(struct udevice *dev, u8 phy, u8 page)
344 return mv88e6xxx_phy_write(dev, phy, PHY_REG_PAGE, page);
347 static int mv88e6xxx_get_switch_id(struct udevice *dev)
351 res = mv88e6xxx_port_read(dev, 0, PORT_REG_SWITCH_ID);
353 dev_err(dev, "Failed to read switch ID: %d\n", res);
359 static bool mv88e6xxx_6352_family(struct udevice *dev)
361 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
364 case PORT_SWITCH_ID_6172:
365 case PORT_SWITCH_ID_6176:
366 case PORT_SWITCH_ID_6240:
367 case PORT_SWITCH_ID_6352:
373 static int mv88e6xxx_get_cmode(struct udevice *dev, u8 port)
377 res = mv88e6xxx_port_read(dev, port, PORT_REG_STATUS);
380 return res & PORT_REG_STATUS_CMODE_MASK;
383 static int mv88e6xxx_switch_reset(struct udevice *dev)
385 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
390 /* Disable all ports */
391 for (port = 0; port < priv->port_count; port++) {
392 val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
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);
402 /* Wait 2 ms for queues to drain */
406 val = mv88e6xxx_reg_read(dev, priv->global1, GLOBAL1_CTRL);
409 val |= GLOBAL1_CTRL_SWRESET;
410 val = mv88e6xxx_reg_write(dev, priv->global1, GLOBAL1_CTRL, val);
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))
427 static int mv88e6xxx_serdes_init(struct udevice *dev)
431 val = mv88e6xxx_set_page(dev, DEVADDR_SERDES, PHY_PAGE_SERDES);
435 /* Power up serdes module */
436 val = mv88e6xxx_phy_read(dev, DEVADDR_SERDES, MII_BMCR);
439 val &= ~(BMCR_PDOWN);
440 val = mv88e6xxx_phy_write(dev, DEVADDR_SERDES, MII_BMCR, val);
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!
455 static int mv88e6xxx_priv_reg_offs_pre_init(struct udevice *dev)
457 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
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).
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;
474 * Now try via port registers with device address 0x08
475 * (88E6020 and compatible switches).
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;
485 dev_warn(dev, "%s Unknown ID 0x%x\n", __func__, priv->id);
490 static int mv88e6xxx_mdio_read(struct udevice *dev, int addr, int devad, int reg)
492 return mv88e6xxx_phy_read_indirect(dev->parent, DEVADDR_PHY(addr),
493 MDIO_DEVAD_NONE, reg);
496 static int mv88e6xxx_mdio_write(struct udevice *dev, int addr, int devad,
499 return mv88e6xxx_phy_write_indirect(dev->parent, DEVADDR_PHY(addr),
500 MDIO_DEVAD_NONE, reg, val);
503 static const struct mdio_ops mv88e6xxx_mdio_ops = {
504 .read = mv88e6xxx_mdio_read,
505 .write = mv88e6xxx_mdio_write,
508 static int mv88e6xxx_mdio_bind(struct udevice *dev)
511 static int num_devices;
513 sprintf(name, "mv88e6xxx-mdio-%d", num_devices++);
514 device_set_name(dev, name);
519 U_BOOT_DRIVER(mv88e6xxx_mdio) = {
520 .name = "mv88e6xxx_mdio",
522 .ops = &mv88e6xxx_mdio_ops,
523 .bind = mv88e6xxx_mdio_bind,
524 .plat_auto = sizeof(struct mdio_perdev_priv),
527 static int mv88e6xxx_port_probe(struct udevice *dev, int port, struct phy_device *phy)
529 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
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;
539 supported = PHY_GBIT_FEATURES;
543 phy->supported &= supported;
544 phy->advertising &= supported;
546 return phy_config(phy);
549 static int mv88e6xxx_port_enable(struct udevice *dev, int port, struct phy_device *phy)
553 dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
554 phy->phy_id, phy_string_for_interface(phy->interface));
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);
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");
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;
583 val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
584 PORT_REG_PHYS_CTRL_LINK_FORCE;
586 ret = mv88e6xxx_port_write(dev, port, PORT_REG_PHYS_CTRL, val);
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);
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)
604 case PHY_INTERFACE_MODE_1000BASEX:
605 if (val != PORT_REG_STATUS_CMODE_1000BASE_X)
610 dev_err(dev, "Mismatched PHY mode %s on port %d!\n",
611 phy_string_for_interface(phy->interface), port);
618 val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL);
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);
627 return phy_startup(phy);
630 static void mv88e6xxx_port_disable(struct udevice *dev, int port, struct phy_device *phy)
634 dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port,
635 phy->phy_id, phy_string_for_interface(phy->interface));
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);
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,
649 /* bind and probe the switch mdios */
650 static int mv88e6xxx_probe_mdio(struct udevice *dev)
652 struct udevice *mdev;
657 /* bind phy ports of mdio child node to mv88e6xxx_mdio device */
658 node = dev_read_subnode(dev, "mdio");
659 if (!ofnode_valid(node))
662 name = ofnode_get_name(node);
663 ret = device_bind_driver_to_node(dev,
667 dev_err(dev, "failed to bind %s: %d\n", name, ret);
669 /* need to probe it as there is no compatible to do so */
670 ret = uclass_get_device_by_ofnode(UCLASS_MDIO, node, &mdev);
672 dev_err(dev, "failed to probe %s: %d\n", name, ret);
678 static int mv88e6xxx_probe(struct udevice *dev)
680 struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
681 struct mv88e6xxx_priv *priv = dev_get_priv(dev);
684 if (ofnode_valid(dev_ofnode(dev)) &&
685 !ofnode_is_enabled(dev_ofnode(dev))) {
686 dev_dbg(dev, "switch disabled\n");
690 /* probe internal mdio bus */
691 ret = mv88e6xxx_probe_mdio(dev);
695 ret = mv88e6xxx_priv_reg_offs_pre_init(dev);
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);
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;
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;
722 ret = mv88e6xxx_switch_reset(dev);
726 if (mv88e6xxx_6352_family(dev)) {
727 val = mv88e6xxx_get_cmode(dev, dsa_pdata->cpu_port);
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);
743 static const struct udevice_id mv88e6xxx_ids[] = {
744 { .compatible = "marvell,mv88e6085" },
748 U_BOOT_DRIVER(mv88e6xxx) = {
751 .of_match = mv88e6xxx_ids,
752 .probe = mv88e6xxx_probe,
753 .ops = &mv88e6xxx_dsa_ops,
754 .priv_auto = sizeof(struct mv88e6xxx_priv),