blob: 82db533c4ec1c98505ef6eb333c0e0fae1510e84 [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>
14#include <i2c.h>
15#include <net/dsa.h>
16
17#include <asm-generic/gpio.h>
18
Karsten Wiese2890a802023-06-28 16:54:45 +020019/* Used with variable features to indicate capabilities. */
20#define NEW_XMII BIT(1)
21#define IS_9893 BIT(2)
22
Tim Harvey06dea1e2021-06-30 16:50:08 -070023/* Global registers */
24
25/* Chip ID */
26#define REG_CHIP_ID0__1 0x0000
27
28/* Operation control */
29#define REG_SW_OPERATION 0x0300
30#define SW_RESET BIT(1)
31#define SW_START BIT(0)
32
33/* Port Specific Registers */
34#define PORT_CTRL_ADDR(port, addr) ((addr) | (((port) + 1) << 12))
35
36/* Port Control */
37#define REG_PORT_XMII_CTRL_1 0x0301
38#define PORT_MII_NOT_1GBIT BIT(6)
39#define PORT_MII_SEL_EDGE BIT(5)
40#define PORT_RGMII_ID_IG_ENABLE BIT(4)
41#define PORT_RGMII_ID_EG_ENABLE BIT(3)
42#define PORT_MII_MAC_MODE BIT(2)
43#define PORT_MII_SEL_M 0x3
44#define PORT_RGMII_SEL 0x0
45#define PORT_RMII_SEL 0x1
46#define PORT_GMII_SEL 0x2
47#define PORT_MII_SEL 0x3
Karsten Wiese2890a802023-06-28 16:54:45 +020048/* S1 */
49#define PORT_MII_1000MBIT_S1 BIT(6)
50/* S1 */
51#define PORT_MII_SEL_S1 0x0
52#define PORT_RMII_SEL_S1 0x1
53#define PORT_GMII_SEL_S1 0x2
54#define PORT_RGMII_SEL_S1 0x3
Tim Harvey06dea1e2021-06-30 16:50:08 -070055
56/* Port MSTP State Register */
57#define REG_PORT_MSTP_STATE 0x0b04
58#define PORT_TX_ENABLE BIT(2)
59#define PORT_RX_ENABLE BIT(1)
60#define PORT_LEARN_DISABLE BIT(0)
61
62/* MMD */
63#define REG_PORT_PHY_MMD_SETUP 0x011A
64#define PORT_MMD_OP_MODE_M 0x3
65#define PORT_MMD_OP_MODE_S 14
66#define PORT_MMD_OP_INDEX 0
67#define PORT_MMD_OP_DATA_NO_INCR 1
68#define PORT_MMD_OP_DATA_INCR_RW 2
69#define PORT_MMD_OP_DATA_INCR_W 3
70#define PORT_MMD_DEVICE_ID_M 0x1F
71#define MMD_SETUP(mode, dev) (((u16)(mode) << PORT_MMD_OP_MODE_S) | (dev))
72#define REG_PORT_PHY_MMD_INDEX_DATA 0x011C
73
Romain Naoura4ee6942024-10-08 09:54:29 +020074/**
75 * struct ksz_phy_ops - low-level KSZ bus operations
76 */
77struct ksz_phy_ops {
78 /* read() - Read bytes from the device
79 *
80 * @udev: bus device
81 * @reg: register offset
82 * @val: data read
83 * @len: Number of bytes to read
84 *
85 * @return: 0 on success, negative on failure
86 */
87 int (*read)(struct udevice *udev, u32 reg, u8 *val, int len);
88
89 /* write() - Write bytes to the device
90 *
91 * @udev: bus device
92 * @reg: register offset
93 * @val: data to write
94 * @len: Number of bytes to write
95 *
96 * @return: 0 on success, negative on failure
97 */
98 int (*write)(struct udevice *udev, u32 reg, u8 *val, int len);
99};
100
Tim Harvey06dea1e2021-06-30 16:50:08 -0700101struct ksz_dsa_priv {
102 struct udevice *dev;
Romain Naoura4ee6942024-10-08 09:54:29 +0200103 struct ksz_phy_ops *phy_ops;
Karsten Wiese2890a802023-06-28 16:54:45 +0200104
105 u32 features; /* chip specific features */
Tim Harvey06dea1e2021-06-30 16:50:08 -0700106};
107
Romain Naoura4ee6942024-10-08 09:54:29 +0200108static inline int ksz_i2c_read(struct udevice *dev, u32 reg, u8 *val, int len)
109{
110 return dm_i2c_read(dev, reg, val, len);
111}
112
113static inline int ksz_i2c_write(struct udevice *dev, u32 reg, u8 *val, int len)
114{
115 return dm_i2c_write(dev, reg, val, len);
116}
117
118static struct ksz_phy_ops phy_i2c_ops = {
119 .read = ksz_i2c_read,
120 .write = ksz_i2c_write,
121};
122
Tim Harvey06dea1e2021-06-30 16:50:08 -0700123static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
124{
Romain Naoura4ee6942024-10-08 09:54:29 +0200125 struct ksz_dsa_priv *priv = dev_get_priv(dev);
126 struct ksz_phy_ops *phy_ops = priv->phy_ops;
127
128 int ret = phy_ops->read(dev, reg, val, 1);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700129
130 dev_dbg(dev, "%s 0x%04x<<0x%02x\n", __func__, reg, *val);
131
132 return ret;
133}
134
135static inline int ksz_pread8(struct udevice *dev, int port, int reg, u8 *val)
136{
137 return ksz_read8(dev, PORT_CTRL_ADDR(port, reg), val);
138}
139
140static inline int ksz_write8(struct udevice *dev, u32 reg, u8 val)
141{
Romain Naoura4ee6942024-10-08 09:54:29 +0200142 struct ksz_dsa_priv *priv = dev_get_priv(dev);
143 struct ksz_phy_ops *phy_ops = priv->phy_ops;
144
Tim Harvey06dea1e2021-06-30 16:50:08 -0700145 dev_dbg(dev, "%s 0x%04x>>0x%02x\n", __func__, reg, val);
Romain Naoura4ee6942024-10-08 09:54:29 +0200146 return phy_ops->write(dev, reg, &val, 1);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700147}
148
149static inline int ksz_pwrite8(struct udevice *dev, int port, int reg, u8 val)
150{
151 return ksz_write8(dev, PORT_CTRL_ADDR(port, reg), val);
152}
153
154static inline int ksz_write16(struct udevice *dev, u32 reg, u16 val)
155{
Romain Naoura4ee6942024-10-08 09:54:29 +0200156 struct ksz_dsa_priv *priv = dev_get_priv(dev);
157 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700158 u8 buf[2];
159
160 buf[1] = val & 0xff;
161 buf[0] = val >> 8;
162 dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
163
Romain Naoura4ee6942024-10-08 09:54:29 +0200164 return phy_ops->write(dev, reg, buf, 2);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700165}
166
167static inline int ksz_pwrite16(struct udevice *dev, int port, int reg, u16 val)
168{
169 return ksz_write16(dev, PORT_CTRL_ADDR(port, reg), val);
170}
171
172static inline int ksz_read16(struct udevice *dev, u32 reg, u16 *val)
173{
Romain Naoura4ee6942024-10-08 09:54:29 +0200174 struct ksz_dsa_priv *priv = dev_get_priv(dev);
175 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700176 u8 buf[2];
177 int ret;
178
Romain Naoura4ee6942024-10-08 09:54:29 +0200179 ret = phy_ops->read(dev, reg, buf, 2);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700180 *val = (buf[0] << 8) | buf[1];
181 dev_dbg(dev, "%s 0x%04x<<0x%04x\n", __func__, reg, *val);
182
183 return ret;
184}
185
186static inline int ksz_pread16(struct udevice *dev, int port, int reg, u16 *val)
187{
188 return ksz_read16(dev, PORT_CTRL_ADDR(port, reg), val);
189}
190
191static inline int ksz_read32(struct udevice *dev, u32 reg, u32 *val)
192{
Romain Naoura4ee6942024-10-08 09:54:29 +0200193 struct ksz_dsa_priv *priv = dev_get_priv(dev);
194 struct ksz_phy_ops *phy_ops = priv->phy_ops;
195
196 return phy_ops->read(dev, reg, (u8 *)val, 4);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700197}
198
199static inline int ksz_pread32(struct udevice *dev, int port, int reg, u32 *val)
200{
201 return ksz_read32(dev, PORT_CTRL_ADDR(port, reg), val);
202}
203
204static inline int ksz_write32(struct udevice *dev, u32 reg, u32 val)
205{
Romain Naoura4ee6942024-10-08 09:54:29 +0200206 struct ksz_dsa_priv *priv = dev_get_priv(dev);
207 struct ksz_phy_ops *phy_ops = priv->phy_ops;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700208 u8 buf[4];
209
210 buf[3] = val & 0xff;
211 buf[2] = (val >> 24) & 0xff;
212 buf[1] = (val >> 16) & 0xff;
213 buf[0] = (val >> 8) & 0xff;
214 dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
215
Romain Naoura4ee6942024-10-08 09:54:29 +0200216 return phy_ops->write(dev, reg, buf, 4);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700217}
218
219static inline int ksz_pwrite32(struct udevice *dev, int port, int reg, u32 val)
220{
221 return ksz_write32(dev, PORT_CTRL_ADDR(port, reg), val);
222}
223
224static __maybe_unused void ksz_port_mmd_read(struct udevice *dev, int port,
225 u8 addr, u16 reg, u16 *val)
226{
227 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
228 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg);
229 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
230 ksz_pread16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
231 dev_dbg(dev, "%s P%d 0x%02x:0x%04x<<0x%04x\n", __func__, port + 1, addr, reg, *val);
232}
233
234static void ksz_port_mmd_write(struct udevice *dev, int port, u8 addr, u16 reg, u16 val)
235{
236 dev_dbg(dev, "%s P%d 0x%02x:0x%04x>>0x%04x\n", __func__, port + 1, addr, addr, val);
237 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
238 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, addr);
239 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
240 ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
241}
242
243/* Apply PHY settings to address errata listed in KSZ9477, KSZ9897, KSZ9896, KSZ9567
244 * Silicon Errata and Data Sheet Clarification documents
245 */
246static void ksz_phy_errata_setup(struct udevice *dev, int port)
247{
248 dev_dbg(dev, "%s P%d\n", __func__, port + 1);
249
250 /* Register settings are needed to improve PHY receive performance */
251 ksz_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
252 ksz_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
253 ksz_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
254 ksz_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
255 ksz_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
256 ksz_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
257 ksz_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
258
259 /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
260 ksz_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
261
262 /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
263 ksz_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
264
265 /* Register settings are required to meet data sheet supply current specifications */
266 ksz_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
267 ksz_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
268 ksz_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
269 ksz_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
270 ksz_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
271 ksz_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
272 ksz_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
273 ksz_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
274 ksz_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
275 ksz_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
276 ksz_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
277 ksz_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
278 ksz_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
279}
280
281/*
282 * mii bus driver
283 */
284#define KSZ_MDIO_CHILD_DRV_NAME "ksz_mdio"
285
286struct ksz_mdio_priv {
287 struct ksz_dsa_priv *ksz;
288};
289
290static int dm_ksz_mdio_read(struct udevice *dev, int addr, int devad, int reg)
291{
292 struct ksz_mdio_priv *priv = dev_get_priv(dev);
293 struct ksz_dsa_priv *ksz = priv->ksz;
294 u16 val = 0xffff;
295
296 ksz_pread16(ksz->dev, addr, 0x100 + (reg << 1), &val);
297 dev_dbg(ksz->dev, "%s P%d reg=0x%04x:0x%04x<<0x%04x\n", __func__,
298 addr + 1, reg, 0x100 + (reg << 1), val);
299
300 return val;
301};
302
303static int dm_ksz_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 val)
304{
305 struct ksz_mdio_priv *priv = dev_get_priv(dev);
306 struct ksz_dsa_priv *ksz = priv->ksz;
307
308 dev_dbg(ksz->dev, "%s P%d reg=0x%04x:%04x>>0x%04x\n",
309 __func__, addr + 1, reg, 0x100 + (reg << 1), val);
310 ksz_pwrite16(ksz->dev, addr, 0x100 + (reg << 1), val);
311
312 return 0;
313}
314
315static const struct mdio_ops ksz_mdio_ops = {
316 .read = dm_ksz_mdio_read,
317 .write = dm_ksz_mdio_write,
318};
319
320static int ksz_mdio_bind(struct udevice *dev)
321{
322 char name[16];
323 static int num_devices;
324
325 dev_dbg(dev, "%s\n", __func__);
326 sprintf(name, "ksz-mdio-%d", num_devices++);
327 device_set_name(dev, name);
328
329 return 0;
330}
331
332static int ksz_mdio_probe(struct udevice *dev)
333{
334 struct ksz_mdio_priv *priv = dev_get_priv(dev);
335
336 dev_dbg(dev, "%s\n", __func__);
Romain Naour8eb44ec2024-10-08 09:54:25 +0200337 priv->ksz = dev_get_priv(dev->parent);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700338
339 return 0;
340}
341
342static const struct udevice_id ksz_mdio_ids[] = {
343 { .compatible = "microchip,ksz-mdio" },
344 { }
345};
346
347U_BOOT_DRIVER(ksz_mdio) = {
348 .name = KSZ_MDIO_CHILD_DRV_NAME,
349 .id = UCLASS_MDIO,
350 .of_match = ksz_mdio_ids,
351 .bind = ksz_mdio_bind,
352 .probe = ksz_mdio_probe,
353 .ops = &ksz_mdio_ops,
354 .priv_auto = sizeof(struct ksz_mdio_priv),
355 .plat_auto = sizeof(struct mdio_perdev_priv),
356};
357
Karsten Wiese2890a802023-06-28 16:54:45 +0200358static void ksz9477_set_gbit(struct ksz_dsa_priv *priv, bool gbit, u8 *data)
359{
360 if (priv->features & NEW_XMII) {
361 if (gbit)
362 *data &= ~PORT_MII_NOT_1GBIT;
363 else
364 *data |= PORT_MII_NOT_1GBIT;
365 } else {
366 if (gbit)
367 *data |= PORT_MII_1000MBIT_S1;
368 else
369 *data &= ~PORT_MII_1000MBIT_S1;
370 }
371}
372
373static void ksz9477_set_xmii(struct ksz_dsa_priv *priv, int mode, u8 *data)
374{
375 u8 xmii;
376
377 if (priv->features & NEW_XMII) {
378 switch (mode) {
379 case 0:
380 xmii = PORT_MII_SEL;
381 break;
382 case 1:
383 xmii = PORT_RMII_SEL;
384 break;
385 case 2:
386 xmii = PORT_GMII_SEL;
387 break;
388 default:
389 xmii = PORT_RGMII_SEL;
390 break;
391 }
392 } else {
393 switch (mode) {
394 case 0:
395 xmii = PORT_MII_SEL_S1;
396 break;
397 case 1:
398 xmii = PORT_RMII_SEL_S1;
399 break;
400 case 2:
401 xmii = PORT_GMII_SEL_S1;
402 break;
403 default:
404 xmii = PORT_RGMII_SEL_S1;
405 break;
406 }
407 }
408 *data &= ~PORT_MII_SEL_M;
409 *data |= xmii;
410}
411
Tim Harvey06dea1e2021-06-30 16:50:08 -0700412static int ksz_port_setup(struct udevice *dev, int port,
413 phy_interface_t interface)
414{
415 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
Romain Naour8f62e922024-10-08 09:54:24 +0200416 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700417 u8 data8;
418
419 dev_dbg(dev, "%s P%d %s\n", __func__, port + 1,
420 (port == pdata->cpu_port) ? "cpu" : "");
421
422 if (port != pdata->cpu_port) {
Karsten Wiese2890a802023-06-28 16:54:45 +0200423 if (priv->features & NEW_XMII)
424 /* phy port: config errata and leds */
425 ksz_phy_errata_setup(dev, port);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700426 } else {
427 /* cpu port: configure MAC interface mode */
428 ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
429 dev_dbg(dev, "%s P%d cpu interface %s\n", __func__, port + 1,
430 phy_string_for_interface(interface));
431 switch (interface) {
432 case PHY_INTERFACE_MODE_MII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200433 ksz9477_set_xmii(priv, 0, &data8);
434 ksz9477_set_gbit(priv, false, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700435 break;
436 case PHY_INTERFACE_MODE_RMII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200437 ksz9477_set_xmii(priv, 1, &data8);
438 ksz9477_set_gbit(priv, false, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700439 break;
440 case PHY_INTERFACE_MODE_GMII:
Karsten Wiese2890a802023-06-28 16:54:45 +0200441 ksz9477_set_xmii(priv, 2, &data8);
442 ksz9477_set_gbit(priv, true, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700443 break;
444 default:
Karsten Wiese2890a802023-06-28 16:54:45 +0200445 ksz9477_set_xmii(priv, 3, &data8);
446 ksz9477_set_gbit(priv, true, &data8);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700447 data8 &= ~PORT_RGMII_ID_IG_ENABLE;
448 data8 &= ~PORT_RGMII_ID_EG_ENABLE;
449 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
450 interface == PHY_INTERFACE_MODE_RGMII_RXID)
451 data8 |= PORT_RGMII_ID_IG_ENABLE;
452 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
453 interface == PHY_INTERFACE_MODE_RGMII_TXID)
454 data8 |= PORT_RGMII_ID_EG_ENABLE;
Karsten Wiese2890a802023-06-28 16:54:45 +0200455 if (priv->features & IS_9893)
456 data8 &= ~PORT_MII_MAC_MODE;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700457 break;
458 }
459 ksz_write8(dev, PORT_CTRL_ADDR(port, REG_PORT_XMII_CTRL_1), data8);
460 }
461
462 return 0;
463}
464
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800465static int ksz_port_probe(struct udevice *dev, int port, struct phy_device *phy)
466{
467 int supported = PHY_GBIT_FEATURES;
468
469 /* configure phy */
470 phy->supported &= supported;
471 phy->advertising &= supported;
472
473 return phy_config(phy);
474}
475
Tim Harvey06dea1e2021-06-30 16:50:08 -0700476static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy)
477{
478 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
479 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700480 u8 data8;
481 int ret;
482
483 dev_dbg(dev, "%s P%d 0x%x %s\n", __func__, port + 1, phy->phy_id,
484 phy_string_for_interface(phy->interface));
485
486 /* setup this port */
487 ret = ksz_port_setup(dev, port, phy->interface);
488 if (ret) {
489 dev_err(dev, "port setup failed: %d\n", ret);
490 return ret;
491 }
492
493 /* enable port forwarding for this port */
494 ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
495 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
496 data8 |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
497 ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
498
499 /* if cpu master we are done */
500 if (port == pdata->cpu_port)
501 return 0;
502
Tim Harvey06dea1e2021-06-30 16:50:08 -0700503 /* start switch */
504 ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
505 data8 |= SW_START;
506 ksz_write8(priv->dev, REG_SW_OPERATION, data8);
507
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800508 return phy_startup(phy);
Tim Harvey06dea1e2021-06-30 16:50:08 -0700509}
510
511static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *phy)
512{
513 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
514 struct ksz_dsa_priv *priv = dev_get_priv(dev);
515 u8 data8;
516
517 dev_dbg(dev, "%s P%d 0x%x\n", __func__, port + 1, phy->phy_id);
518
519 /* can't disable CPU port without re-configuring/re-starting switch */
520 if (port == pdata->cpu_port)
521 return;
522
523 /* disable port */
524 ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
525 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
526 data8 |= PORT_LEARN_DISABLE;
527 ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
528
529 /*
530 * we don't call phy_shutdown here to avoid waiting next time we use
531 * the port, but the downside is that remote side will think we're
532 * actively processing traffic although we are not.
533 */
534}
535
Tim Harvey06dea1e2021-06-30 16:50:08 -0700536static const struct dsa_ops ksz_dsa_ops = {
Tim Harvey4b4fa9b2023-02-07 15:37:18 -0800537 .port_probe = ksz_port_probe,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700538 .port_enable = ksz_port_enable,
539 .port_disable = ksz_port_disable,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700540};
541
542static int ksz_probe_mdio(struct udevice *dev)
543{
544 ofnode node, mdios;
545 int ret;
546
547 mdios = dev_read_subnode(dev, "mdios");
548 if (ofnode_valid(mdios)) {
549 ofnode_for_each_subnode(node, mdios) {
550 const char *name = ofnode_get_name(node);
551 struct udevice *pdev;
552
553 ret = device_bind_driver_to_node(dev,
554 KSZ_MDIO_CHILD_DRV_NAME,
555 name, node, &pdev);
556 if (ret)
557 dev_err(dev, "failed to probe %s: %d\n", name, ret);
558 }
559 }
560
561 return 0;
562}
563
Romain Naoura4ee6942024-10-08 09:54:29 +0200564static void ksz_ops_register(struct udevice *dev, struct ksz_phy_ops *ops)
565{
566 struct ksz_dsa_priv *priv = dev_get_priv(dev);
567
568 priv->phy_ops = ops;
569}
570
571static bool dsa_ksz_check_ops(struct ksz_phy_ops *phy_ops)
572{
573 if (!phy_ops || !phy_ops->read || !phy_ops->write)
574 return false;
575
576 return true;
577}
578
Romain Naour5d006952024-10-08 09:54:30 +0200579static int ksz_probe(struct udevice *dev)
Tim Harvey06dea1e2021-06-30 16:50:08 -0700580{
581 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
582 struct ksz_dsa_priv *priv = dev_get_priv(dev);
Romain Naour73cb1f42024-10-08 09:54:28 +0200583 enum uclass_id parent_id = UCLASS_INVALID;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700584 int i, ret;
585 u8 data8;
586 u32 id;
587
Romain Naour73cb1f42024-10-08 09:54:28 +0200588 parent_id = device_get_uclass_id(dev_get_parent(dev));
589 switch (parent_id) {
590 case UCLASS_I2C: {
Romain Naoura4ee6942024-10-08 09:54:29 +0200591 ksz_ops_register(dev, &phy_i2c_ops);
592
Romain Naour73cb1f42024-10-08 09:54:28 +0200593 ret = i2c_set_chip_offset_len(dev, 2);
594 if (ret) {
595 printf("i2c_set_chip_offset_len failed: %d\n", ret);
596 return ret;
597 }
598 break;
599 }
600 default:
601 dev_err(dev, "invalid parent bus (%s)\n",
602 uclass_get_name(parent_id));
603 return -EINVAL;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700604 }
605
Romain Naoura4ee6942024-10-08 09:54:29 +0200606 if (!dsa_ksz_check_ops(priv->phy_ops)) {
607 printf("Driver bug. No bus ops defined\n");
608 return -EINVAL;
609 }
610
Tim Harvey06dea1e2021-06-30 16:50:08 -0700611 /* default config */
612 priv->dev = dev;
613
614 /* chip level reset */
615 ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
616 data8 |= SW_RESET;
617 ksz_write8(priv->dev, REG_SW_OPERATION, data8);
618
619 /* read chip id */
620 ret = ksz_read32(dev, REG_CHIP_ID0__1, &id);
621 if (ret)
622 return ret;
623 id = __swab32(id);
624 dev_dbg(dev, "%s id=0x%08x\n", __func__, id);
625 switch (id & 0xffffff00) {
626 case 0x00947700:
627 puts("KSZ9477S: ");
628 break;
629 case 0x00956700:
630 puts("KSZ9567R: ");
631 break;
Romain Naoure86de9e2024-10-08 09:54:26 +0200632 case 0x00989600:
633 puts("KSZ9896C: ");
634 break;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700635 case 0x00989700:
636 puts("KSZ9897S: ");
637 break;
Karsten Wiese2890a802023-06-28 16:54:45 +0200638 case 0x00989300:
639 puts("KSZ9893R: ");
640 break;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700641 default:
642 dev_err(dev, "invalid chip id: 0x%08x\n", id);
643 return -EINVAL;
644 }
Karsten Wiese2890a802023-06-28 16:54:45 +0200645 if ((id & 0xf00) == 0x300)
646 priv->features |= IS_9893;
647 else
648 priv->features |= NEW_XMII;
Tim Harvey06dea1e2021-06-30 16:50:08 -0700649
650 /* probe mdio bus */
651 ret = ksz_probe_mdio(dev);
652 if (ret)
653 return ret;
654
655 /* disable ports by default */
656 for (i = 0; i < pdata->num_ports; i++) {
657 ksz_pread8(priv->dev, i, REG_PORT_MSTP_STATE, &data8);
658 data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
659 ksz_pwrite8(priv->dev, i, REG_PORT_MSTP_STATE, data8);
660 }
661
Tim Harvey06dea1e2021-06-30 16:50:08 -0700662 return 0;
663};
664
Romain Naoura4ce9272024-10-08 09:54:27 +0200665static const struct udevice_id ksz_ids[] = {
Tim Harvey06dea1e2021-06-30 16:50:08 -0700666 { .compatible = "microchip,ksz9897" },
667 { .compatible = "microchip,ksz9477" },
668 { .compatible = "microchip,ksz9567" },
Karsten Wiese2890a802023-06-28 16:54:45 +0200669 { .compatible = "microchip,ksz9893" },
Romain Naoure86de9e2024-10-08 09:54:26 +0200670 { .compatible = "microchip,ksz9896" },
Tim Harvey06dea1e2021-06-30 16:50:08 -0700671 { }
672};
673
674U_BOOT_DRIVER(ksz) = {
675 .name = "ksz-switch",
676 .id = UCLASS_DSA,
Romain Naoura4ce9272024-10-08 09:54:27 +0200677 .of_match = ksz_ids,
Romain Naour5d006952024-10-08 09:54:30 +0200678 .probe = ksz_probe,
Tim Harvey06dea1e2021-06-30 16:50:08 -0700679 .ops = &ksz_dsa_ops,
680 .priv_auto = sizeof(struct ksz_dsa_priv),
681};