blob: 7ebbe19766024d11004c23ef081ee0bb39f56e21 [file] [log] [blame]
Tim Harvey06dea1e2021-06-30 16:50:08 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2020
4 * Tim Harvey, Gateworks Corporation
5 */
6
7#include <dm.h>
8#include <dm/device_compat.h>
9#include <dm/device-internal.h>
10#include <dm/lists.h>
11#include <eth_phy.h>
12#include <linux/delay.h>
13#include <miiphy.h>
Romain Naour9d3bde32024-10-08 09:54:31 +020014#if CONFIG_IS_ENABLED(DM_I2C)
15# include <i2c.h>
16#endif
Romain Naour98a124d2024-10-08 09:54:32 +020017#if CONFIG_IS_ENABLED(DM_SPI)
18# include <spi.h>
19#endif
Tim Harvey06dea1e2021-06-30 16:50:08 -070020#include <net/dsa.h>
21
22#include <asm-generic/gpio.h>
23
Karsten Wiese2890a802023-06-28 16:54:45 +020024/* Used with variable features to indicate capabilities. */
25#define NEW_XMII BIT(1)
26#define IS_9893 BIT(2)
27
Tim Harvey06dea1e2021-06-30 16:50:08 -070028/* Global registers */
29
30/* Chip ID */
31#define REG_CHIP_ID0__1 0x0000
32
33/* Operation control */
34#define REG_SW_OPERATION 0x0300
35#define SW_RESET BIT(1)
36#define SW_START BIT(0)
37
38/* Port Specific Registers */
39#define PORT_CTRL_ADDR(port, addr) ((addr) | (((port) + 1) << 12))
40
41/* Port Control */
42#define REG_PORT_XMII_CTRL_1 0x0301
43#define PORT_MII_NOT_1GBIT BIT(6)
44#define PORT_MII_SEL_EDGE BIT(5)
45#define PORT_RGMII_ID_IG_ENABLE BIT(4)
46#define PORT_RGMII_ID_EG_ENABLE BIT(3)
47#define PORT_MII_MAC_MODE BIT(2)
48#define PORT_MII_SEL_M 0x3
49#define PORT_RGMII_SEL 0x0
50#define PORT_RMII_SEL 0x1
51#define PORT_GMII_SEL 0x2
52#define PORT_MII_SEL 0x3
Karsten Wiese2890a802023-06-28 16:54:45 +020053/* S1 */
54#define PORT_MII_1000MBIT_S1 BIT(6)
55/* S1 */
56#define PORT_MII_SEL_S1 0x0
57#define PORT_RMII_SEL_S1 0x1
58#define PORT_GMII_SEL_S1 0x2
59#define PORT_RGMII_SEL_S1 0x3
Tim Harvey06dea1e2021-06-30 16:50:08 -070060
61/* Port MSTP State Register */
62#define REG_PORT_MSTP_STATE 0x0b04
63#define PORT_TX_ENABLE BIT(2)
64#define PORT_RX_ENABLE BIT(1)
65#define PORT_LEARN_DISABLE BIT(0)
66
67/* MMD */
68#define REG_PORT_PHY_MMD_SETUP 0x011A
69#define PORT_MMD_OP_MODE_M 0x3
70#define PORT_MMD_OP_MODE_S 14
71#define PORT_MMD_OP_INDEX 0
72#define PORT_MMD_OP_DATA_NO_INCR 1
73#define PORT_MMD_OP_DATA_INCR_RW 2
74#define PORT_MMD_OP_DATA_INCR_W 3
75#define PORT_MMD_DEVICE_ID_M 0x1F
76#define MMD_SETUP(mode, dev) (((u16)(mode) << PORT_MMD_OP_MODE_S) | (dev))
77#define REG_PORT_PHY_MMD_INDEX_DATA 0x011C
78
Romain Naour98a124d2024-10-08 09:54:32 +020079/* SPI specific define (opcodes) */
80#define KSZ_SPI_OP_RD 3
81#define KSZ_SPI_OP_WR 2
82
83#define KSZ9477_SPI_ADDR_SHIFT 24
84#define KSZ9477_SPI_ADDR_ALIGN 3
85#define KSZ9477_SPI_TURNAROUND_SHIFT 5
86
Romain Naoura4ee6942024-10-08 09:54:29 +020087/**
88 * struct ksz_phy_ops - low-level KSZ bus operations
89 */
90struct ksz_phy_ops {
91 /* read() - Read bytes from the device
92 *
93 * @udev: bus device
94 * @reg: register offset
95 * @val: data read
96 * @len: Number of bytes to read
97 *
98 * @return: 0 on success, negative on failure
99 */
100 int (*read)(struct udevice *udev, u32 reg, u8 *val, int len);
101
102 /* write() - Write bytes to the device
103 *
104 * @udev: bus device
105 * @reg: register offset
106 * @val: data to write
107 * @len: Number of bytes to write
108 *
109 * @return: 0 on success, negative on failure
110 */
111 int (*write)(struct udevice *udev, u32 reg, u8 *val, int len);
112};
113
Tim Harvey06dea1e2021-06-30 16:50:08 -0700114struct ksz_dsa_priv {
115 struct udevice *dev;
Romain Naoura4ee6942024-10-08 09:54:29 +0200116 struct ksz_phy_ops *phy_ops;
Karsten Wiese2890a802023-06-28 16:54:45 +0200117
118 u32 features; /* chip specific features */
Tim Harvey06dea1e2021-06-30 16:50:08 -0700119};
120
Romain Naour9d3bde32024-10-08 09:54:31 +0200121#if CONFIG_IS_ENABLED(DM_I2C)
Romain Naoura4ee6942024-10-08 09:54:29 +0200122static inline int ksz_i2c_read(struct udevice *dev, u32 reg, u8 *val, int len)
123{
124 return dm_i2c_read(dev, reg, val, len);
125}
126
127static inline int ksz_i2c_write(struct udevice *dev, u32 reg, u8 *val, int len)
128{
129 return dm_i2c_write(dev, reg, val, len);
130}
131
132static struct ksz_phy_ops phy_i2c_ops = {
133 .read = ksz_i2c_read,
134 .write = ksz_i2c_write,
135};
Romain Naour9d3bde32024-10-08 09:54:31 +0200136#endif
Romain Naoura4ee6942024-10-08 09:54:29 +0200137
Romain Naour98a124d2024-10-08 09:54:32 +0200138#if CONFIG_IS_ENABLED(DM_SPI)
139/**
140 * ksz_spi_xfer() - only used for 8/16/32 bits bus access
141 *
142 * @dev: The SPI slave device which will be sending/receiving the data.
143 * @reg: register address.
144 * @out: Pointer to a string of bits to send out. The bits are
145 * held in a byte array and are sent MSB first.
146 * @in: Pointer to a string of bits that will be filled in.
147 * @len: number of bytes to read.
148 *
149 * Return: 0 on success, not 0 on failure
150 */
151static int ksz_spi_xfer(struct udevice *dev, u32 reg, const u8 *out,
152 u8 *in, u16 len)
153{
154 int ret;
155 u32 addr = 0;
156 u8 opcode;
157
158 if (in && out) {
159 printf("%s: can't do full duplex\n", __func__);
160 return -EINVAL;
161 }
162
163 if (len > 4 || len == 0) {
164 printf("%s: only 8/16/32 bits bus access supported\n",
165 __func__);
166 return -EINVAL;
167 }
168
169 ret = dm_spi_claim_bus(dev);
170 if (ret < 0) {
171 printf("%s: could not claim bus\n", __func__);
172 return ret;
173 }
174
175 opcode = (in ? KSZ_SPI_OP_RD : KSZ_SPI_OP_WR);
176
177 /* The actual device address space is 16 bits (A15 - A0),
178 * so the values of address bits A23 - A16 in the SPI
179 * command/address phase are “don't care”.
180 */
181 addr |= opcode << (KSZ9477_SPI_ADDR_SHIFT + KSZ9477_SPI_TURNAROUND_SHIFT);
182 addr |= reg << KSZ9477_SPI_TURNAROUND_SHIFT;
183
184 addr = __swab32(addr);
185
186 ret = dm_spi_xfer(dev, 32, &addr, NULL, SPI_XFER_BEGIN);
187 if (ret) {
188 printf("%s ERROR: dm_spi_xfer addr (%u)\n", __func__, ret);
189 goto release_bus;
190 }
191
192 ret = dm_spi_xfer(dev, len * 8, out, in, SPI_XFER_END);
193 if (ret) {
194 printf("%s ERROR: dm_spi_xfer data (%u)\n", __func__, ret);
195 goto release_bus;
196 }
197
198release_bus:
199 /* If an error occurred, release the chip by deasserting the CS */
200 if (ret < 0)
201 dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END);
202
203 dm_spi_release_bus(dev);
204
205 return ret;
206}
207
208static inline int ksz_spi_read(struct udevice *dev, u32 reg, u8 *val, int len)
209{
210 return ksz_spi_xfer(dev, reg, NULL, val, len);
211}
212
213static inline int ksz_spi_write(struct udevice *dev, u32 reg, u8 *val, int len)
214{
215 return ksz_spi_xfer(dev, reg, val, NULL, len);
216}
217
218static struct ksz_phy_ops phy_spi_ops = {
219 .read = ksz_spi_read,
220 .write = ksz_spi_write,
221};
222#endif
223
Tim Harvey06dea1e2021-06-30 16:50:08 -0700224static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
225{
Romain Naoura4ee6942024-10-08 09:54:29 +0200226 struct ksz_dsa_priv *priv = dev_get_priv(dev);
227 struct ksz_phy_ops *phy_ops = priv->phy_ops;
228
229 int ret = phy_ops->read(dev, reg, val, 1);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700230
231 dev_dbg(dev, "%s 0x%04x<<0x%02x\n", __func__, reg, *val);
232
233 return ret;
234}
235
236static inline int ksz_pread8(struct udevice *dev, int port, int reg, u8 *val)
237{
238 return ksz_read8(dev, PORT_CTRL_ADDR(port, reg), val);
239}
240
241static inline int ksz_write8(struct udevice *dev, u32 reg, u8 val)
242{
Romain Naoura4ee6942024-10-08 09:54:29 +0200243 struct ksz_dsa_priv *priv = dev_get_priv(dev);
244 struct ksz_phy_ops *phy_ops = priv->phy_ops;
245
Tim Harvey06dea1e2021-06-30 16:50:08 -0700246 dev_dbg(dev, "%s 0x%04x>>0x%02x\n", __func__, reg, val);
Romain Naoura4ee6942024-10-08 09:54:29 +0200247 return phy_ops->write(dev, reg, &val, 1);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700248}
249
250static inline int ksz_pwrite8(struct udevice *dev, int port, int reg, u8 val)
251{
252 return ksz_write8(dev, PORT_CTRL_ADDR(port, reg), val);
253}
254
255static inline int ksz_write16(struct udevice *dev, u32 reg, u16 val)
256{
Romain Naoura4ee6942024-10-08 09:54:29 +0200257 struct ksz_dsa_priv *priv = dev_get_priv(dev);
258 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700259 u8 buf[2];
260
261 buf[1] = val & 0xff;
262 buf[0] = val >> 8;
263 dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
264
Romain Naoura4ee6942024-10-08 09:54:29 +0200265 return phy_ops->write(dev, reg, buf, 2);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700266}
267
268static inline int ksz_pwrite16(struct udevice *dev, int port, int reg, u16 val)
269{
270 return ksz_write16(dev, PORT_CTRL_ADDR(port, reg), val);
271}
272
273static inline int ksz_read16(struct udevice *dev, u32 reg, u16 *val)
274{
Romain Naoura4ee6942024-10-08 09:54:29 +0200275 struct ksz_dsa_priv *priv = dev_get_priv(dev);
276 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700277 u8 buf[2];
278 int ret;
279
Romain Naoura4ee6942024-10-08 09:54:29 +0200280 ret = phy_ops->read(dev, reg, buf, 2);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700281 *val = (buf[0] << 8) | buf[1];
282 dev_dbg(dev, "%s 0x%04x<<0x%04x\n", __func__, reg, *val);
283
284 return ret;
285}
286
287static inline int ksz_pread16(struct udevice *dev, int port, int reg, u16 *val)
288{
289 return ksz_read16(dev, PORT_CTRL_ADDR(port, reg), val);
290}
291
292static inline int ksz_read32(struct udevice *dev, u32 reg, u32 *val)
293{
Romain Naoura4ee6942024-10-08 09:54:29 +0200294 struct ksz_dsa_priv *priv = dev_get_priv(dev);
295 struct ksz_phy_ops *phy_ops = priv->phy_ops;
296
297 return phy_ops->read(dev, reg, (u8 *)val, 4);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700298}
299
300static inline int ksz_pread32(struct udevice *dev, int port, int reg, u32 *val)
301{
302 return ksz_read32(dev, PORT_CTRL_ADDR(port, reg), val);
303}
304
305static inline int ksz_write32(struct udevice *dev, u32 reg, u32 val)
306{
Romain Naoura4ee6942024-10-08 09:54:29 +0200307 struct ksz_dsa_priv *priv = dev_get_priv(dev);
308 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700309 u8 buf[4];
310
311 buf[3] = val & 0xff;
312 buf[2] = (val >> 24) & 0xff;
313 buf[1] = (val >> 16) & 0xff;
314 buf[0] = (val >> 8) & 0xff;
315 dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
316
Romain Naoura4ee6942024-10-08 09:54:29 +0200317 return phy_ops->write(dev, reg, buf, 4);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700318}
319
320static inline int ksz_pwrite32(struct udevice *dev, int port, int reg, u32 val)
321{
322 return ksz_write32(dev, PORT_CTRL_ADDR(port, reg), val);
323}
324
325static __maybe_unused void ksz_port_mmd_read(struct udevice *dev, int port,
326 u8 addr, u16 reg, u16 *val)
327{
328 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
329 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg);
330 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
331 ksz_pread16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
332 dev_dbg(dev, "%s P%d 0x%02x:0x%04x<<0x%04x\n", __func__, port + 1, addr, reg, *val);
333}
334
335static void ksz_port_mmd_write(struct udevice *dev, int port, u8 addr, u16 reg, u16 val)
336{
337 dev_dbg(dev, "%s P%d 0x%02x:0x%04x>>0x%04x\n", __func__, port + 1, addr, addr, val);
338 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
339 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, addr);
340 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
341 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
342}
343
344/* Apply PHY settings to address errata listed in KSZ9477, KSZ9897, KSZ9896, KSZ9567
345 * Silicon Errata and Data Sheet Clarification documents
346 */
347static void ksz_phy_errata_setup(struct udevice *dev, int port)
348{
349 dev_dbg(dev, "%s P%d\n", __func__, port + 1);
350
351 /* Register settings are needed to improve PHY receive performance */
352 ksz_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
353 ksz_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
354 ksz_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
355 ksz_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
356 ksz_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
357 ksz_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
358 ksz_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
359
360 /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
361 ksz_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
362
363 /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
364 ksz_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
365
366 /* Register settings are required to meet data sheet supply current specifications */
367 ksz_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
368 ksz_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
369 ksz_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
370 ksz_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
371 ksz_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
372 ksz_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
373 ksz_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
374 ksz_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
375 ksz_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
376 ksz_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
377 ksz_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
378 ksz_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
379 ksz_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
380}
381
382/*
383 * mii bus driver
384 */
385#define KSZ_MDIO_CHILD_DRV_NAME "ksz_mdio"
386
387struct ksz_mdio_priv {
388 struct ksz_dsa_priv *ksz;
389};
390
391static int dm_ksz_mdio_read(struct udevice *dev, int addr, int devad, int reg)
392{
393 struct ksz_mdio_priv *priv = dev_get_priv(dev);
394 struct ksz_dsa_priv *ksz = priv->ksz;
395 u16 val = 0xffff;
396
397 ksz_pread16(ksz->dev, addr, 0x100 + (reg << 1), &val);
398 dev_dbg(ksz->dev, "%s P%d reg=0x%04x:0x%04x<<0x%04x\n", __func__,
399 addr + 1, reg, 0x100 + (reg << 1), val);
400
401 return val;
402};
403
404static int dm_ksz_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 val)
405{
406 struct ksz_mdio_priv *priv = dev_get_priv(dev);
407 struct ksz_dsa_priv *ksz = priv->ksz;
408
409 dev_dbg(ksz->dev, "%s P%d reg=0x%04x:%04x>>0x%04x\n",
410 __func__, addr + 1, reg, 0x100 + (reg << 1), val);
411 ksz_pwrite16(ksz->dev, addr, 0x100 + (reg << 1), val);
412
413 return 0;
414}
415
416static const struct mdio_ops ksz_mdio_ops = {
417 .read = dm_ksz_mdio_read,
418 .write = dm_ksz_mdio_write,
419};
420
421static int ksz_mdio_bind(struct udevice *dev)
422{
423 char name[16];
424 static int num_devices;
425
426 dev_dbg(dev, "%s\n", __func__);
427 sprintf(name, "ksz-mdio-%d", num_devices++);
428 device_set_name(dev, name);
429
430 return 0;
431}
432
433static int ksz_mdio_probe(struct udevice *dev)
434{
435 struct ksz_mdio_priv *priv = dev_get_priv(dev);
436
437 dev_dbg(dev, "%s\n", __func__);
Romain Naour8eb44ec2024-10-08 09:54:25 +0200438 priv->ksz = dev_get_priv(dev->parent);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700439
440 return 0;
441}
442
443static const struct udevice_id ksz_mdio_ids[] = {
444 { .compatible = "microchip,ksz-mdio" },
445 { }
446};
447
448U_BOOT_DRIVER(ksz_mdio) = {
449 .name = KSZ_MDIO_CHILD_DRV_NAME,
450 .id = UCLASS_MDIO,
451 .of_match = ksz_mdio_ids,
452 .bind = ksz_mdio_bind,
453 .probe = ksz_mdio_probe,
454 .ops = &ksz_mdio_ops,
455 .priv_auto = sizeof(struct ksz_mdio_priv),
456 .plat_auto = sizeof(struct mdio_perdev_priv),
457};
458
Karsten Wiese2890a802023-06-28 16:54:45 +0200459static void ksz9477_set_gbit(struct ksz_dsa_priv *priv, bool gbit, u8 *data)
460{
461 if (priv->features & NEW_XMII) {
462 if (gbit)
463 *data &= ~PORT_MII_NOT_1GBIT;
464 else
465 *data |= PORT_MII_NOT_1GBIT;
466 } else {
467 if (gbit)
468 *data |= PORT_MII_1000MBIT_S1;
469 else
470 *data &= ~PORT_MII_1000MBIT_S1;
471 }
472}
473
474static void ksz9477_set_xmii(struct ksz_dsa_priv *priv, int mode, u8 *data)
475{
476 u8 xmii;
477
478 if (priv->features & NEW_XMII) {
479 switch (mode) {
480 case 0:
481 xmii = PORT_MII_SEL;
482 break;
483 case 1:
484 xmii = PORT_RMII_SEL;
485 break;
486 case 2:
487 xmii = PORT_GMII_SEL;
488 break;
489 default:
490 xmii = PORT_RGMII_SEL;
491 break;
492 }
493 } else {
494 switch (mode) {
495 case 0:
496 xmii = PORT_MII_SEL_S1;
497 break;
498 case 1:
499 xmii = PORT_RMII_SEL_S1;
500 break;
501 case 2:
502 xmii = PORT_GMII_SEL_S1;
503 break;
504 default:
505 xmii = PORT_RGMII_SEL_S1;
506 break;
507 }
508 }
509 *data &= ~PORT_MII_SEL_M;
510 *data |= xmii;
511}
512
Tim Harvey06dea1e2021-06-30 16:50:08 -0700513static int ksz_port_setup(struct udevice *dev, int port,
514 phy_interface_t interface)
515{
516 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
Romain Naour8f62e922024-10-08 09:54:24 +0200517 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700518 u8 data8;
519
520 dev_dbg(dev, "%s P%d %s\n", __func__, port + 1,
521 (port == pdata->cpu_port) ? "cpu" : "");
522
523 if (port != pdata->cpu_port) {
Karsten Wiese2890a802023-06-28 16:54:45 +0200524 if (priv->features & NEW_XMII)
525 /* phy port: config errata and leds */
526 ksz_phy_errata_setup(dev, port);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700527 } else {
528 /* cpu port: configure MAC interface mode */
529 ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
530 dev_dbg(dev, "%s P%d cpu interface %s\n", __func__, port + 1,
531 phy_string_for_interface(interface));
532 switch (interface) {
533 case PHY_INTERFACE_MODE_MII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200534 ksz9477_set_xmii(priv, 0, &data8);
535 ksz9477_set_gbit(priv, false, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700536 break;
537 case PHY_INTERFACE_MODE_RMII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200538 ksz9477_set_xmii(priv, 1, &data8);
539 ksz9477_set_gbit(priv, false, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700540 break;
541 case PHY_INTERFACE_MODE_GMII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200542 ksz9477_set_xmii(priv, 2, &data8);
543 ksz9477_set_gbit(priv, true, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700544 break;
545 default:
Karsten Wiese2890a802023-06-28 16:54:45 +0200546 ksz9477_set_xmii(priv, 3, &data8);
547 ksz9477_set_gbit(priv, true, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700548 data8 &= ~PORT_RGMII_ID_IG_ENABLE;
549 data8 &= ~PORT_RGMII_ID_EG_ENABLE;
550 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
551 interface == PHY_INTERFACE_MODE_RGMII_RXID)
552 data8 |= PORT_RGMII_ID_IG_ENABLE;
553 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
554 interface == PHY_INTERFACE_MODE_RGMII_TXID)
555 data8 |= PORT_RGMII_ID_EG_ENABLE;
Karsten Wiese2890a802023-06-28 16:54:45 +0200556 if (priv->features & IS_9893)
557 data8 &= ~PORT_MII_MAC_MODE;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700558 break;
559 }
560 ksz_write8(dev, PORT_CTRL_ADDR(port, REG_PORT_XMII_CTRL_1), data8);
561 }
562
563 return 0;
564}
565
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800566static int ksz_port_probe(struct udevice *dev, int port, struct phy_device *phy)
567{
568 int supported = PHY_GBIT_FEATURES;
569
570 /* configure phy */
571 phy->supported &= supported;
572 phy->advertising &= supported;
573
574 return phy_config(phy);
575}
576
Tim Harvey06dea1e2021-06-30 16:50:08 -0700577static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy)
578{
579 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
580 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700581 u8 data8;
582 int ret;
583
584 dev_dbg(dev, "%s P%d 0x%x %s\n", __func__, port + 1, phy->phy_id,
585 phy_string_for_interface(phy->interface));
586
587 /* setup this port */
588 ret = ksz_port_setup(dev, port, phy->interface);
589 if (ret) {
590 dev_err(dev, "port setup failed: %d\n", ret);
591 return ret;
592 }
593
594 /* enable port forwarding for this port */
595 ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
596 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
597 data8 |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
598 ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
599
600 /* if cpu master we are done */
601 if (port == pdata->cpu_port)
602 return 0;
603
Tim Harvey06dea1e2021-06-30 16:50:08 -0700604 /* start switch */
605 ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
606 data8 |= SW_START;
607 ksz_write8(priv->dev, REG_SW_OPERATION, data8);
608
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800609 return phy_startup(phy);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700610}
611
612static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *phy)
613{
614 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
615 struct ksz_dsa_priv *priv = dev_get_priv(dev);
616 u8 data8;
617
618 dev_dbg(dev, "%s P%d 0x%x\n", __func__, port + 1, phy->phy_id);
619
620 /* can't disable CPU port without re-configuring/re-starting switch */
621 if (port == pdata->cpu_port)
622 return;
623
624 /* disable port */
625 ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
626 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
627 data8 |= PORT_LEARN_DISABLE;
628 ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
629
630 /*
631 * we don't call phy_shutdown here to avoid waiting next time we use
632 * the port, but the downside is that remote side will think we're
633 * actively processing traffic although we are not.
634 */
635}
636
Tim Harvey06dea1e2021-06-30 16:50:08 -0700637static const struct dsa_ops ksz_dsa_ops = {
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800638 .port_probe = ksz_port_probe,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700639 .port_enable = ksz_port_enable,
640 .port_disable = ksz_port_disable,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700641};
642
643static int ksz_probe_mdio(struct udevice *dev)
644{
645 ofnode node, mdios;
646 int ret;
647
648 mdios = dev_read_subnode(dev, "mdios");
649 if (ofnode_valid(mdios)) {
650 ofnode_for_each_subnode(node, mdios) {
651 const char *name = ofnode_get_name(node);
652 struct udevice *pdev;
653
654 ret = device_bind_driver_to_node(dev,
655 KSZ_MDIO_CHILD_DRV_NAME,
656 name, node, &pdev);
657 if (ret)
658 dev_err(dev, "failed to probe %s: %d\n", name, ret);
659 }
660 }
661
662 return 0;
663}
664
Romain Naoura4ee6942024-10-08 09:54:29 +0200665static void ksz_ops_register(struct udevice *dev, struct ksz_phy_ops *ops)
666{
667 struct ksz_dsa_priv *priv = dev_get_priv(dev);
668
669 priv->phy_ops = ops;
670}
671
672static bool dsa_ksz_check_ops(struct ksz_phy_ops *phy_ops)
673{
674 if (!phy_ops || !phy_ops->read || !phy_ops->write)
675 return false;
676
677 return true;
678}
679
Romain Naour5d006952024-10-08 09:54:30 +0200680static int ksz_probe(struct udevice *dev)
Tim Harvey06dea1e2021-06-30 16:50:08 -0700681{
682 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
683 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Romain Naour73cb1f42024-10-08 09:54:28 +0200684 enum uclass_id parent_id = UCLASS_INVALID;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700685 int i, ret;
686 u8 data8;
687 u32 id;
688
Romain Naour73cb1f42024-10-08 09:54:28 +0200689 parent_id = device_get_uclass_id(dev_get_parent(dev));
690 switch (parent_id) {
Romain Naour9d3bde32024-10-08 09:54:31 +0200691#if CONFIG_IS_ENABLED(DM_I2C)
Romain Naour73cb1f42024-10-08 09:54:28 +0200692 case UCLASS_I2C: {
Romain Naoura4ee6942024-10-08 09:54:29 +0200693 ksz_ops_register(dev, &phy_i2c_ops);
694
Romain Naour73cb1f42024-10-08 09:54:28 +0200695 ret = i2c_set_chip_offset_len(dev, 2);
696 if (ret) {
697 printf("i2c_set_chip_offset_len failed: %d\n", ret);
698 return ret;
699 }
700 break;
701 }
Romain Naour9d3bde32024-10-08 09:54:31 +0200702#endif
Romain Naour98a124d2024-10-08 09:54:32 +0200703#if CONFIG_IS_ENABLED(DM_SPI)
704 case UCLASS_SPI: {
705 ksz_ops_register(dev, &phy_spi_ops);
706 break;
707 }
708#endif
Romain Naour73cb1f42024-10-08 09:54:28 +0200709 default:
710 dev_err(dev, "invalid parent bus (%s)\n",
711 uclass_get_name(parent_id));
712 return -EINVAL;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700713 }
714
Romain Naoura4ee6942024-10-08 09:54:29 +0200715 if (!dsa_ksz_check_ops(priv->phy_ops)) {
716 printf("Driver bug. No bus ops defined\n");
717 return -EINVAL;
718 }
719
Tim Harvey06dea1e2021-06-30 16:50:08 -0700720 /* default config */
721 priv->dev = dev;
722
723 /* chip level reset */
724 ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
725 data8 |= SW_RESET;
726 ksz_write8(priv->dev, REG_SW_OPERATION, data8);
727
728 /* read chip id */
729 ret = ksz_read32(dev, REG_CHIP_ID0__1, &id);
730 if (ret)
731 return ret;
732 id = __swab32(id);
733 dev_dbg(dev, "%s id=0x%08x\n", __func__, id);
734 switch (id & 0xffffff00) {
735 case 0x00947700:
736 puts("KSZ9477S: ");
737 break;
738 case 0x00956700:
739 puts("KSZ9567R: ");
740 break;
Romain Naoure86de9e2024-10-08 09:54:26 +0200741 case 0x00989600:
742 puts("KSZ9896C: ");
743 break;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700744 case 0x00989700:
745 puts("KSZ9897S: ");
746 break;
Karsten Wiese2890a802023-06-28 16:54:45 +0200747 case 0x00989300:
748 puts("KSZ9893R: ");
749 break;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700750 default:
751 dev_err(dev, "invalid chip id: 0x%08x\n", id);
752 return -EINVAL;
753 }
Karsten Wiese2890a802023-06-28 16:54:45 +0200754 if ((id & 0xf00) == 0x300)
755 priv->features |= IS_9893;
756 else
757 priv->features |= NEW_XMII;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700758
759 /* probe mdio bus */
760 ret = ksz_probe_mdio(dev);
761 if (ret)
762 return ret;
763
764 /* disable ports by default */
765 for (i = 0; i < pdata->num_ports; i++) {
766 ksz_pread8(priv->dev, i, REG_PORT_MSTP_STATE, &data8);
767 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
768 ksz_pwrite8(priv->dev, i, REG_PORT_MSTP_STATE, data8);
769 }
770
Tim Harvey06dea1e2021-06-30 16:50:08 -0700771 return 0;
772};
773
Romain Naoura4ce9272024-10-08 09:54:27 +0200774static const struct udevice_id ksz_ids[] = {
Tim Harvey06dea1e2021-06-30 16:50:08 -0700775 { .compatible = "microchip,ksz9897" },
776 { .compatible = "microchip,ksz9477" },
777 { .compatible = "microchip,ksz9567" },
Karsten Wiese2890a802023-06-28 16:54:45 +0200778 { .compatible = "microchip,ksz9893" },
Romain Naoure86de9e2024-10-08 09:54:26 +0200779 { .compatible = "microchip,ksz9896" },
Tim Harvey06dea1e2021-06-30 16:50:08 -0700780 { }
781};
782
783U_BOOT_DRIVER(ksz) = {
784 .name = "ksz-switch",
785 .id = UCLASS_DSA,
Romain Naoura4ce9272024-10-08 09:54:27 +0200786 .of_match = ksz_ids,
Romain Naour5d006952024-10-08 09:54:30 +0200787 .probe = ksz_probe,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700788 .ops = &ksz_dsa_ops,
789 .priv_auto = sizeof(struct ksz_dsa_priv),
790};