xref: /openbmc/u-boot/drivers/net/vsc9953.c (revision fe91095b799d21428bd39392650ca0b06789776e)
1 /*
2  *  Copyright 2014 Freescale Semiconductor, Inc.
3  *
4  *  SPDX-License-Identifier:      GPL-2.0+
5  *
6  *  Driver for the Vitesse VSC9953 L2 Switch
7  */
8 
9 #include <asm/io.h>
10 #include <asm/fsl_serdes.h>
11 #include <fm_eth.h>
12 #include <fsl_memac.h>
13 #include <errno.h>
14 #include <malloc.h>
15 #include <vsc9953.h>
16 
17 static struct vsc9953_info vsc9953_l2sw = {
18 		.port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
19 		.port[1] = VSC9953_PORT_INFO_INITIALIZER(1),
20 		.port[2] = VSC9953_PORT_INFO_INITIALIZER(2),
21 		.port[3] = VSC9953_PORT_INFO_INITIALIZER(3),
22 		.port[4] = VSC9953_PORT_INFO_INITIALIZER(4),
23 		.port[5] = VSC9953_PORT_INFO_INITIALIZER(5),
24 		.port[6] = VSC9953_PORT_INFO_INITIALIZER(6),
25 		.port[7] = VSC9953_PORT_INFO_INITIALIZER(7),
26 		.port[8] = VSC9953_PORT_INFO_INITIALIZER(8),
27 		.port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
28 };
29 
30 void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
31 {
32 	if (!VSC9953_PORT_CHECK(port_no))
33 		return;
34 
35 	vsc9953_l2sw.port[port_no].bus = bus;
36 }
37 
38 void vsc9953_port_info_set_phy_address(int port_no, int address)
39 {
40 	if (!VSC9953_PORT_CHECK(port_no))
41 		return;
42 
43 	vsc9953_l2sw.port[port_no].phyaddr = address;
44 }
45 
46 void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
47 {
48 	if (!VSC9953_PORT_CHECK(port_no))
49 		return;
50 
51 	vsc9953_l2sw.port[port_no].enet_if = phy_int;
52 }
53 
54 void vsc9953_port_enable(int port_no)
55 {
56 	if (!VSC9953_PORT_CHECK(port_no))
57 		return;
58 
59 	vsc9953_l2sw.port[port_no].enabled = 1;
60 }
61 
62 void vsc9953_port_disable(int port_no)
63 {
64 	if (!VSC9953_PORT_CHECK(port_no))
65 		return;
66 
67 	vsc9953_l2sw.port[port_no].enabled = 0;
68 }
69 
70 static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
71 		int regnum, int value)
72 {
73 	int timeout = 50000;
74 
75 	out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
76 			((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
77 			(0x1 << 1));
78 	asm("sync");
79 
80 	while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
81 		udelay(1);
82 
83 	if (timeout == 0)
84 		debug("Timeout waiting for MDIO write\n");
85 }
86 
87 static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
88 		int regnum)
89 {
90 	int value = 0xFFFF;
91 	int timeout = 50000;
92 
93 	while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
94 		udelay(1);
95 	if (timeout == 0) {
96 		debug("Timeout waiting for MDIO operation to finish\n");
97 		return value;
98 	}
99 
100 	/* Put the address of the phy, and the register
101 	 * number into MIICMD
102 	 */
103 	out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
104 			((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
105 			(0x2 << 1));
106 
107 	timeout = 50000;
108 	/* Wait for the the indication that the read is done */
109 	while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
110 		udelay(1);
111 	if (timeout == 0)
112 		debug("Timeout waiting for MDIO read\n");
113 
114 	/* Grab the value read from the PHY */
115 	value = in_le32(&phyregs->miimdata);
116 
117 	if ((value & 0x00030000) == 0)
118 		return value & 0x0000ffff;
119 
120 	return value;
121 }
122 
123 static int init_phy(struct eth_device *dev)
124 {
125 	struct vsc9953_port_info *l2sw_port = dev->priv;
126 	struct phy_device *phydev = NULL;
127 
128 #ifdef CONFIG_PHYLIB
129 	if (!l2sw_port->bus)
130 		return 0;
131 	phydev = phy_connect(l2sw_port->bus, l2sw_port->phyaddr, dev,
132 			l2sw_port->enet_if);
133 	if (!phydev) {
134 		printf("Failed to connect\n");
135 		return -1;
136 	}
137 
138 	phydev->supported &= SUPPORTED_10baseT_Half |
139 			SUPPORTED_10baseT_Full |
140 			SUPPORTED_100baseT_Half |
141 			SUPPORTED_100baseT_Full |
142 			SUPPORTED_1000baseT_Full;
143 	phydev->advertising = phydev->supported;
144 
145 	l2sw_port->phydev = phydev;
146 
147 	phy_config(phydev);
148 #endif
149 
150 	return 0;
151 }
152 
153 static int vsc9953_port_init(int port_no)
154 {
155 	struct eth_device *dev;
156 
157 	/* Internal ports never have a PHY */
158 	if (VSC9953_INTERNAL_PORT_CHECK(port_no))
159 		return 0;
160 
161 	/* alloc eth device */
162 	dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
163 	if (!dev)
164 		return -ENOMEM;
165 
166 	sprintf(dev->name, "SW@PORT%d", port_no);
167 	dev->priv = &vsc9953_l2sw.port[port_no];
168 	dev->init = NULL;
169 	dev->halt = NULL;
170 	dev->send = NULL;
171 	dev->recv = NULL;
172 
173 	if (init_phy(dev)) {
174 		free(dev);
175 		return -ENODEV;
176 	}
177 
178 	return 0;
179 }
180 
181 void vsc9953_init(bd_t *bis)
182 {
183 	u32 i;
184 	u32 hdx_cfg = 0;
185 	u32 phy_addr = 0;
186 	int timeout;
187 	struct vsc9953_system_reg *l2sys_reg;
188 	struct vsc9953_qsys_reg *l2qsys_reg;
189 	struct vsc9953_dev_gmii *l2dev_gmii_reg;
190 	struct vsc9953_analyzer *l2ana_reg;
191 	struct vsc9953_devcpu_gcb *l2dev_gcb;
192 
193 	l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
194 			VSC9953_DEV_GMII_OFFSET);
195 
196 	l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
197 			VSC9953_ANA_OFFSET);
198 
199 	l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
200 			VSC9953_SYS_OFFSET);
201 
202 	l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
203 			VSC9953_QSYS_OFFSET);
204 
205 	l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
206 			VSC9953_DEVCPU_GCB);
207 
208 	out_le32(&l2dev_gcb->chip_regs.soft_rst,
209 		 VSC9953_SOFT_SWC_RST_ENA);
210 	timeout = 50000;
211 	while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
212 			VSC9953_SOFT_SWC_RST_ENA) && --timeout)
213 		udelay(1); /* busy wait for vsc9953 soft reset */
214 	if (timeout == 0)
215 		debug("Timeout waiting for VSC9953 to reset\n");
216 
217 	out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
218 		 VSC9953_MEM_INIT);
219 
220 	timeout = 50000;
221 	while ((in_le32(&l2sys_reg->sys.reset_cfg) &
222 		VSC9953_MEM_INIT) && --timeout)
223 		udelay(1); /* busy wait for vsc9953 memory init */
224 	if (timeout == 0)
225 		debug("Timeout waiting for VSC9953 memory to initialize\n");
226 
227 	out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
228 			| VSC9953_CORE_ENABLE));
229 
230 	/* VSC9953 Setting to be done once only */
231 	out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
232 
233 	for (i = 0; i < VSC9953_MAX_PORTS; i++) {
234 		if (vsc9953_port_init(i))
235 			printf("Failed to initialize l2switch port %d\n", i);
236 
237 		/* Enable VSC9953 GMII Ports Port ID 0 - 7 */
238 		if (VSC9953_INTERNAL_PORT_CHECK(i)) {
239 			out_le32(&l2ana_reg->pfc[i].pfc_cfg,
240 				 VSC9953_PFC_FC_QSGMII);
241 			out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
242 				 VSC9953_MAC_FC_CFG_QSGMII);
243 		} else {
244 			out_le32(&l2ana_reg->pfc[i].pfc_cfg,
245 				 VSC9953_PFC_FC);
246 			out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
247 				 VSC9953_MAC_FC_CFG);
248 		}
249 		out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
250 			 VSC9953_CLOCK_CFG);
251 		out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
252 			 VSC9953_MAC_ENA_CFG);
253 		out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
254 			 VSC9953_MAC_MODE_CFG);
255 		out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
256 			 VSC9953_MAC_IFG_CFG);
257 		/* mac_hdx_cfg varies with port id*/
258 		hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
259 		out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
260 		out_le32(&l2sys_reg->sys.front_port_mode[i],
261 			 VSC9953_FRONT_PORT_MODE);
262 		setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
263 			     VSC9953_PORT_ENA);
264 		out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
265 			 VSC9953_MAC_MAX_LEN);
266 		out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
267 			 VSC9953_PAUSE_CFG);
268 		/* WAIT FOR 2 us*/
269 		udelay(2);
270 
271 		l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(
272 				(char *)l2dev_gmii_reg
273 				+ T1040_SWITCH_GMII_DEV_OFFSET);
274 
275 		/* Initialize Lynx PHY Wrappers */
276 		phy_addr = 0;
277 		if (vsc9953_l2sw.port[i].enet_if ==
278 				PHY_INTERFACE_MODE_QSGMII)
279 			phy_addr = (i + 0x4) & 0x1F;
280 		else if (vsc9953_l2sw.port[i].enet_if ==
281 				PHY_INTERFACE_MODE_SGMII)
282 			phy_addr = (i + 1) & 0x1F;
283 
284 		if (phy_addr) {
285 			/* SGMII IF mode + AN enable */
286 			vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
287 					   0x14, PHY_SGMII_IF_MODE_AN |
288 					   PHY_SGMII_IF_MODE_SGMII);
289 			/* Dev ability according to SGMII specification */
290 			vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
291 					   0x4, PHY_SGMII_DEV_ABILITY_SGMII);
292 			/* Adjust link timer for SGMII
293 			 * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
294 			 */
295 			vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
296 					   0x13, 0x0003);
297 			vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
298 					   0x12, 0x0d40);
299 			/* Restart AN */
300 			vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
301 					   0x0, PHY_SGMII_CR_DEF_VAL |
302 					   PHY_SGMII_CR_RESET_AN);
303 
304 			timeout = 50000;
305 			while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
306 					phy_addr, 0x01) & 0x0020) && --timeout)
307 				udelay(1); /* wait for AN to complete */
308 			if (timeout == 0)
309 				debug("Timeout waiting for AN to complete\n");
310 		}
311 	}
312 
313 	printf("VSC9953 L2 switch initialized\n");
314 	return;
315 }
316 
317 #ifdef CONFIG_VSC9953_CMD
318 /* Enable/disable status of a VSC9953 port */
319 static void vsc9953_port_status_set(int port_no, u8 enabled)
320 {
321 	struct vsc9953_qsys_reg *l2qsys_reg;
322 
323 	/* Administrative down */
324 	if (!vsc9953_l2sw.port[port_no].enabled)
325 		return;
326 
327 	l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
328 			VSC9953_QSYS_OFFSET);
329 
330 	if (enabled)
331 		setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
332 			     VSC9953_PORT_ENA);
333 	else
334 		clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
335 			     VSC9953_PORT_ENA);
336 }
337 
338 /* Set all VSC9953 ports' status */
339 static void vsc9953_port_all_status_set(u8 enabled)
340 {
341 	int i;
342 
343 	for (i = 0; i < VSC9953_MAX_PORTS; i++)
344 		vsc9953_port_status_set(i, enabled);
345 }
346 
347 /* Start autonegotiation for a VSC9953 PHY */
348 static void vsc9953_phy_autoneg(int port_no)
349 {
350 	if (!vsc9953_l2sw.port[port_no].phydev)
351 		return;
352 
353 	if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
354 			vsc9953_l2sw.port[port_no].phydev))
355 		printf("Failed to start PHY for port %d\n", port_no);
356 }
357 
358 /* Start autonegotiation for all VSC9953 PHYs */
359 static void vsc9953_phy_all_autoneg(void)
360 {
361 	int i;
362 
363 	for (i = 0; i < VSC9953_MAX_PORTS; i++)
364 		vsc9953_phy_autoneg(i);
365 }
366 
367 /* Print a VSC9953 port's configuration */
368 static void vsc9953_port_config_show(int port_no)
369 {
370 	int speed;
371 	int duplex;
372 	int link;
373 	u8 enabled;
374 	u32 val;
375 	struct vsc9953_qsys_reg	*l2qsys_reg;
376 
377 	l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
378 			VSC9953_QSYS_OFFSET);
379 
380 	val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
381 	enabled = vsc9953_l2sw.port[port_no].enabled &&
382 		  (val & VSC9953_PORT_ENA);
383 
384 	/* internal ports (8 and 9) are fixed */
385 	if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
386 		link = 1;
387 		speed = SPEED_2500;
388 		duplex = DUPLEX_FULL;
389 	} else {
390 		if (vsc9953_l2sw.port[port_no].phydev) {
391 			link = vsc9953_l2sw.port[port_no].phydev->link;
392 			speed = vsc9953_l2sw.port[port_no].phydev->speed;
393 			duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
394 		} else {
395 			link = -1;
396 			speed = -1;
397 			duplex = -1;
398 		}
399 	}
400 
401 	printf("%8d ", port_no);
402 	printf("%8s ", enabled == 1 ? "enabled" : "disabled");
403 	printf("%8s ", link == 1 ? "up" : "down");
404 
405 	switch (speed) {
406 	case SPEED_10:
407 		printf("%8d ", 10);
408 		break;
409 	case SPEED_100:
410 		printf("%8d ", 100);
411 		break;
412 	case SPEED_1000:
413 		printf("%8d ", 1000);
414 		break;
415 	case SPEED_2500:
416 		printf("%8d ", 2500);
417 		break;
418 	case SPEED_10000:
419 		printf("%8d ", 10000);
420 		break;
421 	default:
422 		printf("%8s ", "-");
423 	}
424 
425 	printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
426 }
427 
428 /* Print VSC9953 ports' configuration */
429 static void vsc9953_port_all_config_show(void)
430 {
431 	int i;
432 
433 	for (i = 0; i < VSC9953_MAX_PORTS; i++)
434 		vsc9953_port_config_show(i);
435 }
436 
437 /* function to interpret commands starting with "ethsw " */
438 static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
439 {
440 	u8 enable;
441 	u32 port;
442 
443 	if (argc < 4)
444 		return -1;
445 
446 	if (strcmp(argv[1], "port"))
447 		return -1;
448 
449 	if (!strcmp(argv[3], "show")) {
450 		if (!strcmp(argv[2], "all")) {
451 			vsc9953_phy_all_autoneg();
452 			printf("%8s %8s %8s %8s %8s\n",
453 			       "Port", "Status", "Link", "Speed",
454 			       "Duplex");
455 			vsc9953_port_all_config_show();
456 			return 0;
457 		} else {
458 			port = simple_strtoul(argv[2], NULL, 10);
459 			if (!VSC9953_PORT_CHECK(port))
460 				return -1;
461 			vsc9953_phy_autoneg(port);
462 			printf("%8s %8s %8s %8s %8s\n",
463 			       "Port", "Status", "Link", "Speed",
464 			       "Duplex");
465 			vsc9953_port_config_show(port);
466 			return 0;
467 		}
468 	} else if (!strcmp(argv[3], "enable")) {
469 		enable = 1;
470 	} else if (!strcmp(argv[3], "disable")) {
471 		enable = 0;
472 	} else {
473 		return -1;
474 	}
475 
476 	if (!strcmp(argv[2], "all")) {
477 		vsc9953_port_all_status_set(enable);
478 		return 0;
479 	} else {
480 		port = simple_strtoul(argv[2], NULL, 10);
481 		if (!VSC9953_PORT_CHECK(port))
482 			return -1;
483 		vsc9953_port_status_set(port, enable);
484 		return 0;
485 	}
486 
487 	return -1;
488 }
489 
490 U_BOOT_CMD(ethsw, 5, 0, do_ethsw,
491 	   "vsc9953 l2 switch commands",
492 	   "port <port_no> enable|disable\n"
493 	   "    - enable/disable an l2 switch port\n"
494 	   "      port_no=0..9; use \"all\" for all ports\n"
495 	   "ethsw port <port_no> show\n"
496 	   "    - show an l2 switch port's configuration\n"
497 	   "      port_no=0..9; use \"all\" for all ports\n"
498 );
499 #endif /* CONFIG_VSC9953_CMD */
500