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