1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017
4  * Broadcom
5  * Florian Fainelli <f.fainelli@gmail.com>
6  */
7 
8 /*
9  * PHY driver for Broadcom BCM53xx (roboswitch) Ethernet switches.
10  *
11  * This driver configures the b53 for basic use as a PHY. The switch supports
12  * vendor tags and VLAN configuration that can affect the switching decisions.
13  * This driver uses a simple configuration in which all ports are only allowed
14  * to send frames to the CPU port and receive frames from the CPU port this
15  * providing port isolation (no cross talk).
16  *
17  * The configuration determines which PHY ports to activate using the
18  * CONFIG_B53_PHY_PORTS bitmask. Set bit N will active port N and so on.
19  *
20  * This driver was written primarily for the Lamobo R1 platform using a BCM53152
21  * switch but the BCM53xx being largely register compatible, extending it to
22  * cover other switches would be trivial.
23  */
24 
25 #include <common.h>
26 #include <command.h>
27 #include <linux/bitops.h>
28 #include <linux/delay.h>
29 
30 #include <errno.h>
31 #include <malloc.h>
32 #include <miiphy.h>
33 #include <netdev.h>
34 
35 /* Pseudo-PHY address (non configurable) to access internal registers */
36 #define BRCM_PSEUDO_PHY_ADDR		30
37 
38 /* Maximum number of ports possible */
39 #define B53_N_PORTS			9
40 
41 #define B53_CTRL_PAGE			0x00 /* Control */
42 #define B53_MGMT_PAGE			0x02 /* Management Mode */
43 /* Port VLAN Page */
44 #define B53_PVLAN_PAGE			0x31
45 
46 /* Control Page registers */
47 #define B53_PORT_CTRL(i)		(0x00 + (i))
48 #define   PORT_CTRL_RX_DISABLE		BIT(0)
49 #define   PORT_CTRL_TX_DISABLE		BIT(1)
50 #define   PORT_CTRL_RX_BCST_EN		BIT(2) /* Broadcast RX (P8 only) */
51 #define   PORT_CTRL_RX_MCST_EN		BIT(3) /* Multicast RX (P8 only) */
52 #define   PORT_CTRL_RX_UCST_EN		BIT(4) /* Unicast RX (P8 only) */
53 
54 /* Switch Mode Control Register (8 bit) */
55 #define B53_SWITCH_MODE			0x0b
56 #define   SM_SW_FWD_MODE		BIT(0)	/* 1 = Managed Mode */
57 #define   SM_SW_FWD_EN			BIT(1)	/* Forwarding Enable */
58 
59 /* IMP Port state override register (8 bit) */
60 #define B53_PORT_OVERRIDE_CTRL		0x0e
61 #define   PORT_OVERRIDE_LINK		BIT(0)
62 #define   PORT_OVERRIDE_FULL_DUPLEX	BIT(1) /* 0 = Half Duplex */
63 #define   PORT_OVERRIDE_SPEED_S		2
64 #define   PORT_OVERRIDE_SPEED_10M	(0 << PORT_OVERRIDE_SPEED_S)
65 #define   PORT_OVERRIDE_SPEED_100M	(1 << PORT_OVERRIDE_SPEED_S)
66 #define   PORT_OVERRIDE_SPEED_1000M	(2 << PORT_OVERRIDE_SPEED_S)
67 /* BCM5325 only */
68 #define   PORT_OVERRIDE_RV_MII_25	BIT(4)
69 #define   PORT_OVERRIDE_RX_FLOW		BIT(4)
70 #define   PORT_OVERRIDE_TX_FLOW		BIT(5)
71 /* BCM5301X only, requires setting 1000M */
72 #define   PORT_OVERRIDE_SPEED_2000M	BIT(6)
73 #define   PORT_OVERRIDE_EN		BIT(7) /* Use the register contents */
74 
75 #define B53_RGMII_CTRL_IMP		0x60
76 #define   RGMII_CTRL_ENABLE_GMII	BIT(7)
77 #define   RGMII_CTRL_TIMING_SEL		BIT(2)
78 #define   RGMII_CTRL_DLL_RXC		BIT(1)
79 #define   RGMII_CTRL_DLL_TXC		BIT(0)
80 
81 /* Switch control (8 bit) */
82 #define B53_SWITCH_CTRL			0x22
83 #define  B53_MII_DUMB_FWDG_EN		BIT(6)
84 
85 /* Software reset register (8 bit) */
86 #define B53_SOFTRESET			0x79
87 #define   SW_RST			BIT(7)
88 #define   EN_CH_RST			BIT(6)
89 #define   EN_SW_RST			BIT(4)
90 
91 /* Fast Aging Control register (8 bit) */
92 #define B53_FAST_AGE_CTRL		0x88
93 #define   FAST_AGE_STATIC		BIT(0)
94 #define   FAST_AGE_DYNAMIC		BIT(1)
95 #define   FAST_AGE_PORT			BIT(2)
96 #define   FAST_AGE_VLAN			BIT(3)
97 #define   FAST_AGE_STP			BIT(4)
98 #define   FAST_AGE_MC			BIT(5)
99 #define   FAST_AGE_DONE			BIT(7)
100 
101 /* Port VLAN mask (16 bit) IMP port is always 8, also on 5325 & co */
102 #define B53_PVLAN_PORT_MASK(i)		((i) * 2)
103 
104 /* MII registers */
105 #define REG_MII_PAGE    0x10    /* MII Page register */
106 #define REG_MII_ADDR    0x11    /* MII Address register */
107 #define REG_MII_DATA0   0x18    /* MII Data register 0 */
108 #define REG_MII_DATA1   0x19    /* MII Data register 1 */
109 #define REG_MII_DATA2   0x1a    /* MII Data register 2 */
110 #define REG_MII_DATA3   0x1b    /* MII Data register 3 */
111 
112 #define REG_MII_PAGE_ENABLE     BIT(0)
113 #define REG_MII_ADDR_WRITE      BIT(0)
114 #define REG_MII_ADDR_READ       BIT(1)
115 
116 struct b53_device {
117 	struct mii_dev	*bus;
118 	unsigned int cpu_port;
119 };
120 
b53_mdio_op(struct mii_dev * bus,u8 page,u8 reg,u16 op)121 static int b53_mdio_op(struct mii_dev *bus, u8 page, u8 reg, u16 op)
122 {
123 	int ret;
124 	int i;
125 	u16 v;
126 
127 	/* set page number */
128 	v = (page << 8) | REG_MII_PAGE_ENABLE;
129 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
130 			 REG_MII_PAGE, v);
131 	if (ret)
132 		return ret;
133 
134 	/* set register address */
135 	v = (reg << 8) | op;
136 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
137 			 REG_MII_ADDR, v);
138 	if (ret)
139 		return ret;
140 
141 	/* check if operation completed */
142 	for (i = 0; i < 5; ++i) {
143 		v = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
144 			      REG_MII_ADDR);
145 		if (!(v & (REG_MII_ADDR_WRITE | REG_MII_ADDR_READ)))
146 			break;
147 
148 		udelay(100);
149 	}
150 
151 	if (i == 5)
152 		return -EIO;
153 
154 	return 0;
155 }
156 
b53_mdio_read8(struct mii_dev * bus,u8 page,u8 reg,u8 * val)157 static int b53_mdio_read8(struct mii_dev *bus, u8 page, u8 reg, u8 *val)
158 {
159 	int ret;
160 
161 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
162 	if (ret)
163 		return ret;
164 
165 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
166 			 REG_MII_DATA0) & 0xff;
167 
168 	return 0;
169 }
170 
b53_mdio_read16(struct mii_dev * bus,u8 page,u8 reg,u16 * val)171 static int b53_mdio_read16(struct mii_dev *bus, u8 page, u8 reg, u16 *val)
172 {
173 	int ret;
174 
175 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
176 	if (ret)
177 		return ret;
178 
179 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
180 			 REG_MII_DATA0);
181 
182 	return 0;
183 }
184 
b53_mdio_read32(struct mii_dev * bus,u8 page,u8 reg,u32 * val)185 static int b53_mdio_read32(struct mii_dev *bus, u8 page, u8 reg, u32 *val)
186 {
187 	int ret;
188 
189 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
190 	if (ret)
191 		return ret;
192 
193 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
194 			 REG_MII_DATA0);
195 	*val |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
196 			  REG_MII_DATA1) << 16;
197 
198 	return 0;
199 }
200 
b53_mdio_read48(struct mii_dev * bus,u8 page,u8 reg,u64 * val)201 static int b53_mdio_read48(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
202 {
203 	u64 temp = 0;
204 	int i;
205 	int ret;
206 
207 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
208 	if (ret)
209 		return ret;
210 
211 	for (i = 2; i >= 0; i--) {
212 		temp <<= 16;
213 		temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
214 				  REG_MII_DATA0 + i);
215 	}
216 
217 	*val = temp;
218 
219 	return 0;
220 }
221 
b53_mdio_read64(struct mii_dev * bus,u8 page,u8 reg,u64 * val)222 static int b53_mdio_read64(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
223 {
224 	u64 temp = 0;
225 	int i;
226 	int ret;
227 
228 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
229 	if (ret)
230 		return ret;
231 
232 	for (i = 3; i >= 0; i--) {
233 		temp <<= 16;
234 		temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
235 				  REG_MII_DATA0 + i);
236 	}
237 
238 	*val = temp;
239 
240 	return 0;
241 }
242 
b53_mdio_write8(struct mii_dev * bus,u8 page,u8 reg,u8 value)243 static int b53_mdio_write8(struct mii_dev *bus, u8 page, u8 reg, u8 value)
244 {
245 	int ret;
246 
247 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
248 			 REG_MII_DATA0, value);
249 	if (ret)
250 		return ret;
251 
252 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
253 }
254 
b53_mdio_write16(struct mii_dev * bus,u8 page,u8 reg,u16 value)255 static int b53_mdio_write16(struct mii_dev *bus, u8 page, u8 reg,
256 			    u16 value)
257 {
258 	int ret;
259 
260 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
261 			 REG_MII_DATA0, value);
262 	if (ret)
263 		return ret;
264 
265 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
266 }
267 
b53_mdio_write32(struct mii_dev * bus,u8 page,u8 reg,u32 value)268 static int b53_mdio_write32(struct mii_dev *bus, u8 page, u8 reg,
269 			    u32 value)
270 {
271 	unsigned int i;
272 	u32 temp = value;
273 
274 	for (i = 0; i < 2; i++) {
275 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
276 				     MDIO_DEVAD_NONE,
277 				     REG_MII_DATA0 + i, temp & 0xffff);
278 		if (ret)
279 			return ret;
280 		temp >>= 16;
281 	}
282 
283 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
284 }
285 
b53_mdio_write48(struct mii_dev * bus,u8 page,u8 reg,u64 value)286 static int b53_mdio_write48(struct mii_dev *bus, u8 page, u8 reg,
287 			    u64 value)
288 {
289 	unsigned int i;
290 	u64 temp = value;
291 
292 	for (i = 0; i < 3; i++) {
293 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
294 				     MDIO_DEVAD_NONE,
295 				     REG_MII_DATA0 + i, temp & 0xffff);
296 		if (ret)
297 			return ret;
298 		temp >>= 16;
299 	}
300 
301 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
302 }
303 
b53_mdio_write64(struct mii_dev * bus,u8 page,u8 reg,u64 value)304 static int b53_mdio_write64(struct mii_dev *bus, u8 page, u8 reg,
305 			    u64 value)
306 {
307 	unsigned int i;
308 	u64 temp = value;
309 
310 	for (i = 0; i < 4; i++) {
311 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
312 				     MDIO_DEVAD_NONE,
313 				     REG_MII_DATA0 + i, temp & 0xffff);
314 		if (ret)
315 			return ret;
316 		temp >>= 16;
317 	}
318 
319 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
320 }
321 
b53_read8(struct b53_device * dev,u8 page,u8 reg,u8 * value)322 static inline int b53_read8(struct b53_device *dev, u8 page,
323 			    u8 reg, u8 *value)
324 {
325 	return b53_mdio_read8(dev->bus, page, reg, value);
326 }
327 
b53_read16(struct b53_device * dev,u8 page,u8 reg,u16 * value)328 static inline int b53_read16(struct b53_device *dev, u8 page,
329 			     u8 reg, u16 *value)
330 {
331 	return b53_mdio_read16(dev->bus, page, reg, value);
332 }
333 
b53_read32(struct b53_device * dev,u8 page,u8 reg,u32 * value)334 static inline int b53_read32(struct b53_device *dev, u8 page,
335 			     u8 reg, u32 *value)
336 {
337 	return b53_mdio_read32(dev->bus, page, reg, value);
338 }
339 
b53_read48(struct b53_device * dev,u8 page,u8 reg,u64 * value)340 static inline int b53_read48(struct b53_device *dev, u8 page,
341 			     u8 reg, u64 *value)
342 {
343 	return b53_mdio_read48(dev->bus, page, reg, value);
344 }
345 
b53_read64(struct b53_device * dev,u8 page,u8 reg,u64 * value)346 static inline int b53_read64(struct b53_device *dev, u8 page,
347 			     u8 reg, u64 *value)
348 {
349 	return b53_mdio_read64(dev->bus, page, reg, value);
350 }
351 
b53_write8(struct b53_device * dev,u8 page,u8 reg,u8 value)352 static inline int b53_write8(struct b53_device *dev, u8 page,
353 			     u8 reg, u8 value)
354 {
355 	return b53_mdio_write8(dev->bus, page, reg, value);
356 }
357 
b53_write16(struct b53_device * dev,u8 page,u8 reg,u16 value)358 static inline int b53_write16(struct b53_device *dev, u8 page,
359 			      u8 reg, u16 value)
360 {
361 	return b53_mdio_write16(dev->bus, page, reg, value);
362 }
363 
b53_write32(struct b53_device * dev,u8 page,u8 reg,u32 value)364 static inline int b53_write32(struct b53_device *dev, u8 page,
365 			      u8 reg, u32 value)
366 {
367 	return b53_mdio_write32(dev->bus, page, reg, value);
368 }
369 
b53_write48(struct b53_device * dev,u8 page,u8 reg,u64 value)370 static inline int b53_write48(struct b53_device *dev, u8 page,
371 			      u8 reg, u64 value)
372 {
373 	return b53_mdio_write48(dev->bus, page, reg, value);
374 }
375 
b53_write64(struct b53_device * dev,u8 page,u8 reg,u64 value)376 static inline int b53_write64(struct b53_device *dev, u8 page,
377 			      u8 reg, u64 value)
378 {
379 	return b53_mdio_write64(dev->bus, page, reg, value);
380 }
381 
b53_flush_arl(struct b53_device * dev,u8 mask)382 static int b53_flush_arl(struct b53_device *dev, u8 mask)
383 {
384 	unsigned int i;
385 
386 	b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
387 		   FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask);
388 
389 	for (i = 0; i < 10; i++) {
390 		u8 fast_age_ctrl;
391 
392 		b53_read8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
393 			  &fast_age_ctrl);
394 
395 		if (!(fast_age_ctrl & FAST_AGE_DONE))
396 			goto out;
397 
398 		mdelay(1);
399 	}
400 
401 	return -ETIMEDOUT;
402 out:
403 	/* Only age dynamic entries (default behavior) */
404 	b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, FAST_AGE_DYNAMIC);
405 	return 0;
406 }
407 
b53_switch_reset(struct phy_device * phydev)408 static int b53_switch_reset(struct phy_device *phydev)
409 {
410 	struct b53_device *dev = phydev->priv;
411 	unsigned int timeout = 1000;
412 	u8 mgmt;
413 	u8 reg;
414 
415 	b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
416 	reg |= SW_RST | EN_SW_RST | EN_CH_RST;
417 	b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, reg);
418 
419 	do {
420 		b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
421 		if (!(reg & SW_RST))
422 			break;
423 
424 		mdelay(1);
425 	} while (timeout-- > 0);
426 
427 	if (timeout == 0)
428 		return -ETIMEDOUT;
429 
430 	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
431 
432 	if (!(mgmt & SM_SW_FWD_EN)) {
433 		mgmt &= ~SM_SW_FWD_MODE;
434 		mgmt |= SM_SW_FWD_EN;
435 
436 		b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
437 		b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
438 
439 		if (!(mgmt & SM_SW_FWD_EN)) {
440 			printf("Failed to enable switch!\n");
441 			return -EINVAL;
442 		}
443 	}
444 
445 	/* Include IMP port in dumb forwarding mode when no tagging protocol
446 	 * is configured
447 	 */
448 	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt);
449 	mgmt |= B53_MII_DUMB_FWDG_EN;
450 	b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
451 
452 	return b53_flush_arl(dev, FAST_AGE_STATIC);
453 }
454 
b53_enable_cpu_port(struct phy_device * phydev)455 static void b53_enable_cpu_port(struct phy_device *phydev)
456 {
457 	struct b53_device *dev = phydev->priv;
458 	u8 port_ctrl;
459 
460 	port_ctrl = PORT_CTRL_RX_BCST_EN |
461 		    PORT_CTRL_RX_MCST_EN |
462 		    PORT_CTRL_RX_UCST_EN;
463 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(dev->cpu_port), port_ctrl);
464 
465 	port_ctrl = PORT_OVERRIDE_EN | PORT_OVERRIDE_LINK |
466 		    PORT_OVERRIDE_FULL_DUPLEX | PORT_OVERRIDE_SPEED_1000M;
467 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, port_ctrl);
468 
469 	b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_IMP, &port_ctrl);
470 }
471 
b53_imp_vlan_setup(struct b53_device * dev,int cpu_port)472 static void b53_imp_vlan_setup(struct b53_device *dev, int cpu_port)
473 {
474 	unsigned int port;
475 	u16 pvlan;
476 
477 	/* Enable the IMP port to be in the same VLAN as the other ports
478 	 * on a per-port basis such that we only have Port i and IMP in
479 	 * the same VLAN.
480 	 */
481 	for (port = 0; port < B53_N_PORTS; port++) {
482 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
483 			continue;
484 
485 		b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
486 			   &pvlan);
487 		pvlan |= BIT(cpu_port);
488 		b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
489 			    pvlan);
490 	}
491 }
492 
b53_port_enable(struct phy_device * phydev,unsigned int port)493 static int b53_port_enable(struct phy_device *phydev, unsigned int port)
494 {
495 	struct b53_device *dev = phydev->priv;
496 	unsigned int cpu_port = dev->cpu_port;
497 	u16 pvlan;
498 
499 	/* Clear the Rx and Tx disable bits and set to no spanning tree */
500 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0);
501 
502 	/* Set this port, and only this one to be in the default VLAN */
503 	b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
504 	pvlan &= ~0x1ff;
505 	pvlan |= BIT(port);
506 	b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
507 
508 	b53_imp_vlan_setup(dev, cpu_port);
509 
510 	return 0;
511 }
512 
b53_switch_init(struct phy_device * phydev)513 static int b53_switch_init(struct phy_device *phydev)
514 {
515 	static int init;
516 	int ret;
517 
518 	if (init)
519 		return 0;
520 
521 	ret = b53_switch_reset(phydev);
522 	if (ret < 0)
523 		return ret;
524 
525 	b53_enable_cpu_port(phydev);
526 
527 	init = 1;
528 
529 	return 0;
530 }
531 
b53_probe(struct phy_device * phydev)532 static int b53_probe(struct phy_device *phydev)
533 {
534 	struct b53_device *dev;
535 	int ret;
536 
537 	dev = malloc(sizeof(*dev));
538 	if (!dev)
539 		return -ENOMEM;
540 
541 	memset(dev, 0, sizeof(*dev));
542 
543 	phydev->priv = dev;
544 	dev->bus = phydev->bus;
545 	dev->cpu_port = CONFIG_B53_CPU_PORT;
546 
547 	ret = b53_switch_reset(phydev);
548 	if (ret < 0)
549 		return ret;
550 
551 	return 0;
552 }
553 
b53_phy_config(struct phy_device * phydev)554 static int b53_phy_config(struct phy_device *phydev)
555 {
556 	unsigned int port;
557 	int res;
558 
559 	res = b53_switch_init(phydev);
560 	if (res < 0)
561 		return res;
562 
563 	for (port = 0; port < B53_N_PORTS; port++) {
564 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
565 			continue;
566 
567 		res = b53_port_enable(phydev, port);
568 		if (res < 0) {
569 			printf("Error enabling port %i\n", port);
570 			continue;
571 		}
572 
573 		res = genphy_config_aneg(phydev);
574 		if (res < 0) {
575 			printf("Error setting PHY %i autoneg\n", port);
576 			continue;
577 		}
578 
579 		res = 0;
580 	}
581 
582 	return res;
583 }
584 
b53_phy_startup(struct phy_device * phydev)585 static int b53_phy_startup(struct phy_device *phydev)
586 {
587 	unsigned int port;
588 	int res;
589 
590 	for (port = 0; port < B53_N_PORTS; port++) {
591 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
592 			continue;
593 
594 		phydev->addr = port;
595 
596 		res = genphy_startup(phydev);
597 		if (res < 0)
598 			continue;
599 		else
600 			break;
601 	}
602 
603 	/* Since we are connected directly to the switch, hardcode the link
604 	 * parameters to match those of the CPU port configured in
605 	 * b53_enable_cpu_port, we cannot be dependent on the user-facing port
606 	 * settings (e.g: 100Mbits/sec would not work here)
607 	 */
608 	phydev->speed = 1000;
609 	phydev->duplex = 1;
610 	phydev->link = 1;
611 
612 	return 0;
613 }
614 
615 static struct phy_driver b53_driver = {
616 	.name = "Broadcom BCM53125",
617 	.uid = 0x03625c00,
618 	.mask = 0xfffffc00,
619 	.features = PHY_GBIT_FEATURES,
620 	.probe = b53_probe,
621 	.config = b53_phy_config,
622 	.startup = b53_phy_startup,
623 	.shutdown = &genphy_shutdown,
624 };
625 
phy_b53_init(void)626 int phy_b53_init(void)
627 {
628 	phy_register(&b53_driver);
629 
630 	return 0;
631 }
632 
do_b53_reg_read(const char * name,int argc,char * const argv[])633 int do_b53_reg_read(const char *name, int argc, char *const argv[])
634 {
635 	u8 page, offset, width;
636 	struct mii_dev *bus;
637 	int ret = -EINVAL;
638 	u64 value64 = 0;
639 	u32 value32 = 0;
640 	u16 value16 = 0;
641 	u8 value8 = 0;
642 
643 	bus = miiphy_get_dev_by_name(name);
644 	if (!bus) {
645 		printf("unable to find MDIO bus: %s\n", name);
646 		return ret;
647 	}
648 
649 	page = simple_strtoul(argv[1], NULL, 16);
650 	offset = simple_strtoul(argv[2], NULL, 16);
651 	width = simple_strtoul(argv[3], NULL, 10);
652 
653 	switch (width) {
654 	case 8:
655 		ret = b53_mdio_read8(bus, page, offset, &value8);
656 		printf("page=0x%02x, offset=0x%02x, value=0x%02x\n",
657 		       page, offset, value8);
658 		break;
659 	case 16:
660 		ret = b53_mdio_read16(bus, page, offset, &value16);
661 		printf("page=0x%02x, offset=0x%02x, value=0x%04x\n",
662 		       page, offset, value16);
663 		break;
664 	case 32:
665 		ret = b53_mdio_read32(bus, page, offset, &value32);
666 		printf("page=0x%02x, offset=0x%02x, value=0x%08x\n",
667 		       page, offset, value32);
668 		break;
669 	case 48:
670 		ret = b53_mdio_read48(bus, page, offset, &value64);
671 		printf("page=0x%02x, offset=0x%02x, value=0x%012llx\n",
672 		       page, offset, value64);
673 		break;
674 	case 64:
675 		ret = b53_mdio_read48(bus, page, offset, &value64);
676 		printf("page=0x%02x, offset=0x%02x, value=0x%016llx\n",
677 		       page, offset, value64);
678 		break;
679 	default:
680 		printf("Unsupported width: %d\n", width);
681 		break;
682 	}
683 
684 	return ret;
685 }
686 
do_b53_reg_write(const char * name,int argc,char * const argv[])687 int do_b53_reg_write(const char *name, int argc, char *const argv[])
688 {
689 	u8 page, offset, width;
690 	struct mii_dev *bus;
691 	int ret = -EINVAL;
692 	u64 value64 = 0;
693 	u32 value = 0;
694 
695 	bus = miiphy_get_dev_by_name(name);
696 	if (!bus) {
697 		printf("unable to find MDIO bus: %s\n", name);
698 		return ret;
699 	}
700 
701 	page = simple_strtoul(argv[1], NULL, 16);
702 	offset = simple_strtoul(argv[2], NULL, 16);
703 	width = simple_strtoul(argv[3], NULL, 10);
704 	if (width == 48 || width == 64)
705 		value64 = simple_strtoull(argv[4], NULL, 16);
706 	else
707 		value = simple_strtoul(argv[4], NULL, 16);
708 
709 	switch (width) {
710 	case 8:
711 		ret = b53_mdio_write8(bus, page, offset, value & 0xff);
712 		break;
713 	case 16:
714 		ret = b53_mdio_write16(bus, page, offset, value);
715 		break;
716 	case 32:
717 		ret = b53_mdio_write32(bus, page, offset, value);
718 		break;
719 	case 48:
720 		ret = b53_mdio_write48(bus, page, offset, value64);
721 		break;
722 	case 64:
723 		ret = b53_mdio_write64(bus, page, offset, value64);
724 		break;
725 	default:
726 		printf("Unsupported width: %d\n", width);
727 		break;
728 	}
729 
730 	return ret;
731 }
732 
do_b53_reg(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])733 int do_b53_reg(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
734 {
735 	const char *cmd, *mdioname;
736 	int ret = 0;
737 
738 	if (argc < 2)
739 		return cmd_usage(cmdtp);
740 
741 	cmd = argv[1];
742 	--argc;
743 	++argv;
744 
745 	if (!strcmp(cmd, "write")) {
746 		if (argc < 4)
747 			return cmd_usage(cmdtp);
748 		mdioname = argv[1];
749 		--argc;
750 		++argv;
751 		ret = do_b53_reg_write(mdioname, argc, argv);
752 	} else if (!strcmp(cmd, "read")) {
753 		if (argc < 5)
754 			return cmd_usage(cmdtp);
755 		mdioname = argv[1];
756 		--argc;
757 		++argv;
758 		ret = do_b53_reg_read(mdioname, argc, argv);
759 	} else {
760 		return cmd_usage(cmdtp);
761 	}
762 
763 	return ret;
764 }
765 
766 U_BOOT_CMD(b53_reg, 7, 1, do_b53_reg,
767 	   "Broadcom B53 switch register access",
768 	   "write mdioname page (hex) offset (hex) width (dec) value (hex)\n"
769 	   "read mdioname page (hex) offset (hex) width (dec)\n"
770 	  );
771