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