xref: /freebsd-13-stable/sys/mips/nlm/board.c (revision 3bc80996974a61a4223eae4c1ccd47b6ee32a48a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * NETLOGIC_BSD */
31 
32 #include <sys/cdefs.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/mutex.h>
39 
40 #include <net/ethernet.h>
41 
42 #include <mips/nlm/hal/mips-extns.h>
43 #include <mips/nlm/hal/haldefs.h>
44 #include <mips/nlm/hal/iomap.h>
45 #include <mips/nlm/hal/fmn.h>
46 #include <mips/nlm/hal/pic.h>
47 #include <mips/nlm/hal/sys.h>
48 #include <mips/nlm/hal/nae.h>
49 #include <mips/nlm/hal/uart.h>
50 #include <mips/nlm/hal/poe.h>
51 
52 #include <mips/nlm/xlp.h>
53 #include <mips/nlm/board.h>
54 #include <mips/nlm/msgring.h>
55 
56 static uint8_t board_eeprom_buf[EEPROM_SIZE];
57 static int board_eeprom_set;
58 
59 struct xlp_board_info xlp_board_info;
60 
61 struct vfbid_tbl {
62 	int vfbid;
63 	int dest_vc;
64 };
65 
66 /* XXXJC : this should be derived from msg thread mask */
67 static struct vfbid_tbl nlm_vfbid[] = {
68 	/* NULL FBID should map to cpu0 to detect NAE send msg errors */
69 	{127,   0}, /* NAE <-> NAE mappings */
70 	{51, 1019}, {50, 1018}, {49, 1017}, {48, 1016},
71 	{47, 1015}, {46, 1014}, {45, 1013}, {44, 1012},
72 	{43, 1011}, {42, 1010}, {41, 1009}, {40, 1008},
73 	{39, 1007}, {38, 1006}, {37, 1005}, {36, 1004},
74 	{35, 1003}, {34, 1002}, {33, 1001}, {32, 1000},
75 	/* NAE <-> CPU mappings, freeback got to vc 3 of each thread */
76 	{31,  127}, {30,  123}, {29,  119}, {28,  115},
77 	{27,  111}, {26,  107}, {25,  103}, {24,   99},
78 	{23,   95}, {22,   91}, {21,   87}, {20,   83},
79 	{19,   79}, {18,   75}, {17,   71}, {16,   67},
80 	{15,   63}, {14,   59}, {13,   55}, {12,   51},
81 	{11,   47}, {10,   43}, { 9,   39}, { 8,   35},
82 	{ 7,   31}, { 6,   27}, { 5,   23}, { 4,   19},
83 	{ 3,   15}, { 2,   11}, { 1,    7}, { 0,    3},
84 };
85 
86 static struct vfbid_tbl nlm3xx_vfbid[] = {
87 	/* NULL FBID should map to cpu0 to detect NAE send msg errors */
88 	{127,   0}, /* NAE <-> NAE mappings */
89 	{39,  503}, {38,  502}, {37,  501}, {36,  500},
90 	{35,  499}, {34,  498}, {33,  497}, {32,  496},
91 	/* NAE <-> CPU mappings, freeback got to vc 3 of each thread */
92 	{31,  127}, {30,  123}, {29,  119}, {28,  115},
93 	{27,  111}, {26,  107}, {25,  103}, {24,   99},
94 	{23,   95}, {22,   91}, {21,   87}, {20,   83},
95 	{19,   79}, {18,   75}, {17,   71}, {16,   67},
96 	{15,   63}, {14,   59}, {13,   55}, {12,   51},
97 	{11,   47}, {10,   43}, { 9,   39}, { 8,   35},
98 	{ 7,   31}, { 6,   27}, { 5,   23}, { 4,   19},
99 	{ 3,   15}, { 2,   11}, { 1,    7}, { 0,    3},
100 };
101 
102 int
nlm_get_vfbid_mapping(int vfbid)103 nlm_get_vfbid_mapping(int vfbid)
104 {
105 	int i, nentries;
106 	struct vfbid_tbl *p;
107 
108 	if (nlm_is_xlp3xx()) {
109 		nentries = nitems(nlm3xx_vfbid);
110 		p = nlm3xx_vfbid;
111 	} else {
112 		nentries = nitems(nlm_vfbid);
113 		p = nlm_vfbid;
114 	}
115 
116 	for (i = 0; i < nentries; i++) {
117 		if (p[i].vfbid == vfbid)
118 		    return (p[i].dest_vc);
119 	}
120 
121 	return (-1);
122 }
123 
124 int
nlm_get_poe_distvec(int vec,uint32_t * distvec)125 nlm_get_poe_distvec(int vec, uint32_t *distvec)
126 {
127 
128 	if (vec != 0)
129 		return (-1);  /* we support just vec 0 */
130 	nlm_calc_poe_distvec(xlp_msg_thread_mask, 0, 0, 0,
131 	    0x1 << XLPGE_RX_VC, distvec);
132 	return (0);
133 }
134 
135 /*
136  * All our knowledge of chip and board that cannot be detected by probing
137  * at run-time goes here
138  */
139 
140 void
xlpge_get_macaddr(uint8_t * macaddr)141 xlpge_get_macaddr(uint8_t *macaddr)
142 {
143 
144 	if (board_eeprom_set == 0) {
145 		/* No luck, take some reasonable value */
146 		macaddr[0] = 0x00; macaddr[1] = 0x0f; macaddr[2] = 0x30;
147 		macaddr[3] = 0x20; macaddr[4] = 0x0d; macaddr[5] = 0x5b;
148 	} else
149 		memcpy(macaddr, &board_eeprom_buf[EEPROM_MACADDR_OFFSET],
150 		    ETHER_ADDR_LEN);
151 }
152 
153 static void
nlm_setup_port_defaults(struct xlp_port_ivars * p)154 nlm_setup_port_defaults(struct xlp_port_ivars *p)
155 {
156 	p->loopback_mode = 0;
157 	p->num_channels = 1;
158 	p->free_desc_sizes = 2048;
159 	p->vlan_pri_en = 0;
160 	p->hw_parser_en = 1;
161 	p->ieee1588_userval = 0;
162 	p->ieee1588_ptpoff = 0;
163 	p->ieee1588_tmr1 = 0;
164 	p->ieee1588_tmr2 = 0;
165 	p->ieee1588_tmr3 = 0;
166 	p->ieee1588_inc_intg = 0;
167 	p->ieee1588_inc_den = 1;
168 	p->ieee1588_inc_num = 1;
169 
170 	if (nlm_is_xlp3xx()) {
171 		p->stg2_fifo_size = XLP3XX_STG2_FIFO_SZ;
172 		p->eh_fifo_size = XLP3XX_EH_FIFO_SZ;
173 		p->frout_fifo_size = XLP3XX_FROUT_FIFO_SZ;
174 		p->ms_fifo_size = XLP3XX_MS_FIFO_SZ;
175 		p->pkt_fifo_size = XLP3XX_PKT_FIFO_SZ;
176 		p->pktlen_fifo_size = XLP3XX_PKTLEN_FIFO_SZ;
177 		p->max_stg2_offset = XLP3XX_MAX_STG2_OFFSET;
178 		p->max_eh_offset = XLP3XX_MAX_EH_OFFSET;
179 		p->max_frout_offset = XLP3XX_MAX_FREE_OUT_OFFSET;
180 		p->max_ms_offset = XLP3XX_MAX_MS_OFFSET;
181 		p->max_pmem_offset = XLP3XX_MAX_PMEM_OFFSET;
182 		p->stg1_2_credit = XLP3XX_STG1_2_CREDIT;
183 		p->stg2_eh_credit = XLP3XX_STG2_EH_CREDIT;
184 		p->stg2_frout_credit = XLP3XX_STG2_FROUT_CREDIT;
185 		p->stg2_ms_credit = XLP3XX_STG2_MS_CREDIT;
186 	} else {
187 		p->stg2_fifo_size = XLP8XX_STG2_FIFO_SZ;
188 		p->eh_fifo_size = XLP8XX_EH_FIFO_SZ;
189 		p->frout_fifo_size = XLP8XX_FROUT_FIFO_SZ;
190 		p->ms_fifo_size = XLP8XX_MS_FIFO_SZ;
191 		p->pkt_fifo_size = XLP8XX_PKT_FIFO_SZ;
192 		p->pktlen_fifo_size = XLP8XX_PKTLEN_FIFO_SZ;
193 		p->max_stg2_offset = XLP8XX_MAX_STG2_OFFSET;
194 		p->max_eh_offset = XLP8XX_MAX_EH_OFFSET;
195 		p->max_frout_offset = XLP8XX_MAX_FREE_OUT_OFFSET;
196 		p->max_ms_offset = XLP8XX_MAX_MS_OFFSET;
197 		p->max_pmem_offset = XLP8XX_MAX_PMEM_OFFSET;
198 		p->stg1_2_credit = XLP8XX_STG1_2_CREDIT;
199 		p->stg2_eh_credit = XLP8XX_STG2_EH_CREDIT;
200 		p->stg2_frout_credit = XLP8XX_STG2_FROUT_CREDIT;
201 		p->stg2_ms_credit = XLP8XX_STG2_MS_CREDIT;
202 	}
203 
204 	switch (p->type) {
205 	case SGMIIC:
206 		p->num_free_descs = 52;
207 		p->iface_fifo_size = 13;
208 		p->rxbuf_size = 128;
209 		p->rx_slots_reqd = SGMII_CAL_SLOTS;
210 		p->tx_slots_reqd = SGMII_CAL_SLOTS;
211 		if (nlm_is_xlp3xx())
212 		    p->pseq_fifo_size = 30;
213 		else
214 		    p->pseq_fifo_size = 62;
215 		break;
216 	case ILC:
217 		p->num_free_descs = 150;
218 		p->rxbuf_size = 944;
219 		p->rx_slots_reqd = IL8_CAL_SLOTS;
220 		p->tx_slots_reqd = IL8_CAL_SLOTS;
221 		p->pseq_fifo_size = 225;
222 		p->iface_fifo_size = 55;
223 		break;
224 	case XAUIC:
225 	default:
226 		p->num_free_descs = 150;
227 		p->rxbuf_size = 944;
228 		p->rx_slots_reqd = XAUI_CAL_SLOTS;
229 		p->tx_slots_reqd = XAUI_CAL_SLOTS;
230 		if (nlm_is_xlp3xx()) {
231 		    p->pseq_fifo_size = 120;
232 		    p->iface_fifo_size = 52;
233 		} else {
234 		    p->pseq_fifo_size = 225;
235 		    p->iface_fifo_size = 55;
236 		}
237 		break;
238 	}
239 }
240 
241 /* XLP 8XX evaluation boards have the following phy-addr
242  * assignment. There are two external mdio buses in XLP --
243  * bus 0 and bus 1. The management ports (16 and 17) are
244  * on mdio bus 0 while blocks/complexes[0 to 3] are all
245  * on mdio bus 1. The phy_addr on bus 0 (mgmt ports 16
246  * and 17) match the port numbers.
247  * These are the details:
248  * block  port   phy_addr   mdio_bus
249  * ====================================
250  * 0         0     4          1
251  * 0         1     7          1
252  * 0         2     6          1
253  * 0         3     5          1
254  * 1         0     8          1
255  * 1         1     11         1
256  * 1         2     10         1
257  * 1         3     9          1
258  * 2         0     0          1
259  * 2         1     3          1
260  * 2         2     2          1
261  * 2         3     1          1
262  * 3         0     12         1
263  * 3         1     15         1
264  * 3         2     14         1
265  * 3         3     13         1
266  *
267  * 4         0     16         0
268  * 4         1     17         0
269  *
270  * The XLP 3XX evaluation boards have the following phy-addr
271  * assignments.
272  * block  port   phy_addr   mdio_bus
273  * ====================================
274  * 0         0     4          0
275  * 0         1     7          0
276  * 0         2     6          0
277  * 0         3     5          0
278  * 1         0     8          0
279  * 1         1     11         0
280  * 1         2     10         0
281  * 1         3     9          0
282  */
283 static void
nlm_board_get_phyaddr(int block,int port,int * phyaddr)284 nlm_board_get_phyaddr(int block, int port, int *phyaddr)
285 {
286 	switch (block) {
287 	case 0: switch (port) {
288 		case 0: *phyaddr = 4; break;
289 		case 1: *phyaddr = 7; break;
290 		case 2: *phyaddr = 6; break;
291 		case 3: *phyaddr = 5; break;
292 		}
293 		break;
294 	case 1: switch (port) {
295 		case 0: *phyaddr = 8; break;
296 		case 1: *phyaddr = 11; break;
297 		case 2: *phyaddr = 10; break;
298 		case 3: *phyaddr = 9; break;
299 		}
300 		break;
301 	case 2: switch (port) {
302 		case 0: *phyaddr = 0; break;
303 		case 1: *phyaddr = 3; break;
304 		case 2: *phyaddr = 2; break;
305 		case 3: *phyaddr = 1; break;
306 		}
307 		break;
308 	case 3: switch (port) {
309 		case 0: *phyaddr = 12; break;
310 		case 1: *phyaddr = 15; break;
311 		case 2: *phyaddr = 14; break;
312 		case 3: *phyaddr = 13; break;
313 		}
314 		break;
315 	case 4: switch (port) { /* management SGMII */
316 		case 0: *phyaddr = 16; break;
317 		case 1: *phyaddr = 17; break;
318 		}
319 		break;
320 	}
321 }
322 
323 static void
nlm_print_processor_info(void)324 nlm_print_processor_info(void)
325 {
326 	uint32_t procid;
327 	int prid, rev;
328 	char *chip, *revstr;
329 
330 	procid = mips_rd_prid();
331 	prid = (procid >> 8) & 0xff;
332 	rev = procid & 0xff;
333 
334 	switch (prid) {
335 	case CHIP_PROCESSOR_ID_XLP_8XX:
336 		chip = "XLP 832";
337 		break;
338 	case CHIP_PROCESSOR_ID_XLP_3XX:
339 		chip = "XLP 3xx";
340 		break;
341 	case CHIP_PROCESSOR_ID_XLP_432:
342 	case CHIP_PROCESSOR_ID_XLP_416:
343 		chip = "XLP 4xx";
344 		break;
345 	default:
346 		chip = "XLP ?xx";
347 		break;
348 	}
349 	switch (rev) {
350 	case 0:
351 		revstr = "A0"; break;
352 	case 1:
353 		revstr = "A1"; break;
354 	case 2:
355 		revstr = "A2"; break;
356 	case 3:
357 		revstr = "B0"; break;
358 	case 4:
359 		revstr = "B1"; break;
360 	default:
361 		revstr = "??"; break;
362 	}
363 
364 	printf("Processor info:\n");
365 	printf("  Netlogic %s %s [%x]\n", chip, revstr, procid);
366 }
367 
368 /*
369  * All our knowledge of chip and board that cannot be detected by probing
370  * at run-time goes here
371  */
372 static int
nlm_setup_xlp_board(int node)373 nlm_setup_xlp_board(int node)
374 {
375 	struct xlp_board_info	*boardp;
376 	struct xlp_node_info	*nodep;
377 	struct xlp_nae_ivars	*naep;
378 	struct xlp_block_ivars	*blockp;
379 	struct xlp_port_ivars	*portp;
380 	uint64_t cpldbase, nae_pcibase;
381 	int	block, port, rv, dbtype, usecpld = 0, evp = 0, svp = 0;
382 	uint8_t *b;
383 
384 	/* start with a clean slate */
385 	boardp = &xlp_board_info;
386 	if (boardp->nodemask == 0)
387 		memset(boardp, 0, sizeof(xlp_board_info));
388 	boardp->nodemask |= (1 << node);
389 	nlm_print_processor_info();
390 
391 	b =  board_eeprom_buf;
392 	rv = nlm_board_eeprom_read(node, EEPROM_I2CBUS, EEPROM_I2CADDR, 0, b,
393 	    EEPROM_SIZE);
394 	if (rv == 0) {
395 		board_eeprom_set = 1;
396 		printf("Board info (EEPROM on i2c@%d at %#X):\n",
397 		    EEPROM_I2CBUS, EEPROM_I2CADDR);
398 		printf("  Model:      %7.7s %2.2s\n", &b[16], &b[24]);
399 		printf("  Serial #:   %3.3s-%2.2s\n", &b[27], &b[31]);
400 		printf("  MAC addr:   %02x:%02x:%02x:%02x:%02x:%02x\n",
401 		    b[2], b[3], b[4], b[5], b[6], b[7]);
402 	} else
403 		printf("Board Info: Error on EEPROM read (i2c@%d %#X).\n",
404 		    EEPROM_I2CBUS, EEPROM_I2CADDR);
405 
406 	nae_pcibase = nlm_get_nae_pcibase(node);
407 	nodep = &boardp->nodes[node];
408 	naep = &nodep->nae_ivars;
409 	naep->node = node;
410 
411 	/* frequency at which network block runs */
412 	naep->freq = 500;
413 
414 	/* CRC16 polynomial used for flow table generation */
415 	naep->flow_crc_poly = 0xffff;
416 	naep->hw_parser_en = 1;
417 	naep->prepad_en = 1;
418 	naep->prepad_size = 3; /* size in 16 byte units */
419 	naep->ieee_1588_en = 1;
420 
421 	naep->ilmask = 0x0;	/* set this based on daughter card */
422 	naep->xauimask = 0x0;	/* set this based on daughter card */
423 	naep->sgmiimask = 0x0;	/* set this based on daughter card */
424 	naep->nblocks = nae_num_complex(nae_pcibase);
425 	if (strncmp(&b[16], "PCIE", 4) == 0) {
426 		usecpld = 0; /* XLP PCIe card */
427 		/* Broadcom's XLP PCIe card has the following
428 		 * blocks fixed.
429 		 * blk 0-XAUI, 1-XAUI, 4-SGMII(one port) */
430 		naep->blockmask = 0x13;
431 	} else if (strncmp(&b[16], "MB-EVP", 6) == 0) {
432 		usecpld = 1; /* XLP non-PCIe card which has CPLD */
433 		evp = 1;
434 		naep->blockmask = (1 << naep->nblocks) - 1;
435 	} else if ((strncmp(&b[16], "MB-S", 4) == 0) ||
436 	    (strncmp(&b[16], "MB_S", 4) == 0)) {
437 		usecpld = 1; /* XLP non-PCIe card which has CPLD */
438 		svp = 1;
439 		/* 3xx chip reports one block extra which is a bug */
440 		naep->nblocks = naep->nblocks - 1;
441 		naep->blockmask = (1 << naep->nblocks) - 1;
442 	} else {
443 		printf("ERROR!!! Board type:%7s didn't match any board"
444 		    " type we support\n", &b[16]);
445 		return (-1);
446 	}
447 	cpldbase = nlm_board_cpld_base(node, XLP_EVB_CPLD_CHIPSELECT);
448 
449 	/* pretty print network config */
450 	printf("Network config");
451 	if (usecpld)
452 		printf("(from CPLD@%d):\n", XLP_EVB_CPLD_CHIPSELECT);
453 	else
454 		printf("(defaults):\n");
455 	printf("  NAE@%d Blocks: ", node);
456 	for (block = 0; block < naep->nblocks; block++) {
457 		char *s = "???";
458 
459 		if ((naep->blockmask & (1 << block)) == 0)
460 			continue;
461 		blockp = &naep->block_ivars[block];
462 		blockp->block = block;
463 		if (usecpld)
464 			dbtype = nlm_board_cpld_dboard_type(cpldbase, block);
465 		else
466 			dbtype = DCARD_XAUI;  /* default XAUI */
467 
468 		/* XLP PCIe cards */
469 		if ((!evp && !svp) && ((block == 2) || (block == 3)))
470 			dbtype = DCARD_NOT_PRSNT;
471 
472 		if (block == 4) {
473 			/* management block 4 on 8xx or XLP PCIe */
474 			blockp->type = SGMIIC;
475 			if (evp)
476 				blockp->portmask = 0x3;
477 			else
478 				blockp->portmask = 0x1;
479 			naep->sgmiimask |= (1 << block);
480 		} else {
481 			switch (dbtype) {
482 			case DCARD_ILAKEN:
483 				blockp->type = ILC;
484 				blockp->portmask = 0x1;
485 				naep->ilmask |= (1 << block);
486 				break;
487 			case DCARD_SGMII:
488 				blockp->type = SGMIIC;
489 				blockp->portmask = 0xf;
490 				naep->sgmiimask |= (1 << block);
491 				break;
492 			case DCARD_XAUI:
493 				blockp->type = XAUIC;
494 				blockp->portmask = 0x1;
495 				naep->xauimask |= (1 << block);
496 				break;
497 			default: /* DCARD_NOT_PRSNT */
498 				blockp->type = UNKNOWN;
499 				blockp->portmask = 0;
500 				break;
501 			}
502 		}
503 		if (blockp->type != UNKNOWN) {
504 			for (port = 0; port < PORTS_PER_CMPLX; port++) {
505 				if ((blockp->portmask & (1 << port)) == 0)
506 					continue;
507 				portp = &blockp->port_ivars[port];
508 				nlm_board_get_phyaddr(block, port,
509 				    &portp->phy_addr);
510 				if (svp || (block == 4))
511 					portp->mdio_bus = 0;
512 				else
513 					portp->mdio_bus = 1;
514 				portp->port = port;
515 				portp->block = block;
516 				portp->node = node;
517 				portp->type = blockp->type;
518 				nlm_setup_port_defaults(portp);
519 			}
520 		}
521 		switch (blockp->type) {
522 		case SGMIIC : s = "SGMII"; break;
523 		case XAUIC  : s = "XAUI"; break;
524 		case ILC    : s = "IL"; break;
525 		}
526 		printf(" [%d %s]", block, s);
527 	}
528 	printf("\n");
529 	return (0);
530 }
531 
nlm_board_info_setup(void)532 int nlm_board_info_setup(void)
533 {
534 	if (nlm_setup_xlp_board(0) != 0)
535 		return (-1);
536 	return (0);
537 }
538