1/*-
2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * NETLOGIC_BSD */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38
39#include <net/ethernet.h>
40
41#include <mips/nlm/hal/mips-extns.h>
42#include <mips/nlm/hal/haldefs.h>
43#include <mips/nlm/hal/iomap.h>
44#include <mips/nlm/hal/fmn.h>
45#include <mips/nlm/hal/pic.h>
46#include <mips/nlm/hal/sys.h>
47#include <mips/nlm/hal/nae.h>
48#include <mips/nlm/hal/uart.h>
49#include <mips/nlm/hal/poe.h>
50
51#include <mips/nlm/xlp.h>
52#include <mips/nlm/board.h>
53#include <mips/nlm/msgring.h>
54
55static uint8_t board_eeprom_buf[EEPROM_SIZE];
56static int board_eeprom_set;
57
58struct xlp_board_info xlp_board_info;
59
60struct vfbid_tbl {
61	int vfbid;
62	int dest_vc;
63};
64
65/* XXXJC : this should be derived from msg thread mask */
66static struct vfbid_tbl nlm_vfbid[] = {
67	/* NULL FBID should map to cpu0 to detect NAE send msg errors */
68	{127,   0}, /* NAE <-> NAE mappings */
69	{51, 1019}, {50, 1018}, {49, 1017}, {48, 1016},
70	{47, 1015}, {46, 1014}, {45, 1013}, {44, 1012},
71	{43, 1011}, {42, 1010}, {41, 1009}, {40, 1008},
72	{39, 1007}, {38, 1006}, {37, 1005}, {36, 1004},
73	{35, 1003}, {34, 1002}, {33, 1001}, {32, 1000},
74	/* NAE <-> CPU mappings, freeback got to vc 3 of each thread */
75	{31,  127}, {30,  123}, {29,  119}, {28,  115},
76	{27,  111}, {26,  107}, {25,  103}, {24,   99},
77	{23,   95}, {22,   91}, {21,   87}, {20,   83},
78	{19,   79}, {18,   75}, {17,   71}, {16,   67},
79	{15,   63}, {14,   59}, {13,   55}, {12,   51},
80	{11,   47}, {10,   43}, { 9,   39}, { 8,   35},
81	{ 7,   31}, { 6,   27}, { 5,   23}, { 4,   19},
82	{ 3,   15}, { 2,   11}, { 1,    7}, { 0,    3},
83};
84
85static struct vfbid_tbl nlm3xx_vfbid[] = {
86	/* NULL FBID should map to cpu0 to detect NAE send msg errors */
87	{127,   0}, /* NAE <-> NAE mappings */
88	{39,  503}, {38,  502}, {37,  501}, {36,  500},
89	{35,  499}, {34,  498}, {33,  497}, {32,  496},
90	/* NAE <-> CPU mappings, freeback got to vc 3 of each thread */
91	{31,  127}, {30,  123}, {29,  119}, {28,  115},
92	{27,  111}, {26,  107}, {25,  103}, {24,   99},
93	{23,   95}, {22,   91}, {21,   87}, {20,   83},
94	{19,   79}, {18,   75}, {17,   71}, {16,   67},
95	{15,   63}, {14,   59}, {13,   55}, {12,   51},
96	{11,   47}, {10,   43}, { 9,   39}, { 8,   35},
97	{ 7,   31}, { 6,   27}, { 5,   23}, { 4,   19},
98	{ 3,   15}, { 2,   11}, { 1,    7}, { 0,    3},
99};
100
101int
102nlm_get_vfbid_mapping(int vfbid)
103{
104	int i, nentries;
105	struct vfbid_tbl *p;
106
107	if (nlm_is_xlp3xx()) {
108		nentries = sizeof(nlm3xx_vfbid)/sizeof(struct vfbid_tbl);
109		p = nlm3xx_vfbid;
110	} else {
111		nentries = sizeof(nlm_vfbid)/sizeof(struct vfbid_tbl);
112		p = nlm_vfbid;
113	}
114
115	for (i = 0; i < nentries; i++) {
116		if (p[i].vfbid == vfbid)
117		    return (p[i].dest_vc);
118	}
119
120	return (-1);
121}
122
123int
124nlm_get_poe_distvec(int vec, uint32_t *distvec)
125{
126
127	if (vec != 0)
128		return (-1);  /* we support just vec 0 */
129	nlm_calc_poe_distvec(xlp_msg_thread_mask, 0, 0, 0,
130	    0x1 << XLPGE_RX_VC, distvec);
131	return (0);
132}
133
134/*
135 * All our knowledge of chip and board that cannot be detected by probing
136 * at run-time goes here
137 */
138
139void
140xlpge_get_macaddr(uint8_t *macaddr)
141{
142
143	if (board_eeprom_set == 0) {
144		/* No luck, take some reasonable value */
145		macaddr[0] = 0x00; macaddr[1] = 0x0f; macaddr[2] = 0x30;
146		macaddr[3] = 0x20; macaddr[4] = 0x0d; macaddr[5] = 0x5b;
147	} else
148		memcpy(macaddr, &board_eeprom_buf[EEPROM_MACADDR_OFFSET],
149		    ETHER_ADDR_LEN);
150}
151
152static void
153nlm_setup_port_defaults(struct xlp_port_ivars *p)
154{
155	p->loopback_mode = 0;
156	p->num_channels = 1;
157	p->free_desc_sizes = 2048;
158	p->vlan_pri_en = 0;
159	p->hw_parser_en = 1;
160	p->ieee1588_userval = 0;
161	p->ieee1588_ptpoff = 0;
162	p->ieee1588_tmr1 = 0;
163	p->ieee1588_tmr2 = 0;
164	p->ieee1588_tmr3 = 0;
165	p->ieee1588_inc_intg = 0;
166	p->ieee1588_inc_den = 1;
167	p->ieee1588_inc_num = 1;
168
169	if (nlm_is_xlp3xx()) {
170		p->stg2_fifo_size = XLP3XX_STG2_FIFO_SZ;
171		p->eh_fifo_size = XLP3XX_EH_FIFO_SZ;
172		p->frout_fifo_size = XLP3XX_FROUT_FIFO_SZ;
173		p->ms_fifo_size = XLP3XX_MS_FIFO_SZ;
174		p->pkt_fifo_size = XLP3XX_PKT_FIFO_SZ;
175		p->pktlen_fifo_size = XLP3XX_PKTLEN_FIFO_SZ;
176		p->max_stg2_offset = XLP3XX_MAX_STG2_OFFSET;
177		p->max_eh_offset = XLP3XX_MAX_EH_OFFSET;
178		p->max_frout_offset = XLP3XX_MAX_FREE_OUT_OFFSET;
179		p->max_ms_offset = XLP3XX_MAX_MS_OFFSET;
180		p->max_pmem_offset = XLP3XX_MAX_PMEM_OFFSET;
181		p->stg1_2_credit = XLP3XX_STG1_2_CREDIT;
182		p->stg2_eh_credit = XLP3XX_STG2_EH_CREDIT;
183		p->stg2_frout_credit = XLP3XX_STG2_FROUT_CREDIT;
184		p->stg2_ms_credit = XLP3XX_STG2_MS_CREDIT;
185	} else {
186		p->stg2_fifo_size = XLP8XX_STG2_FIFO_SZ;
187		p->eh_fifo_size = XLP8XX_EH_FIFO_SZ;
188		p->frout_fifo_size = XLP8XX_FROUT_FIFO_SZ;
189		p->ms_fifo_size = XLP8XX_MS_FIFO_SZ;
190		p->pkt_fifo_size = XLP8XX_PKT_FIFO_SZ;
191		p->pktlen_fifo_size = XLP8XX_PKTLEN_FIFO_SZ;
192		p->max_stg2_offset = XLP8XX_MAX_STG2_OFFSET;
193		p->max_eh_offset = XLP8XX_MAX_EH_OFFSET;
194		p->max_frout_offset = XLP8XX_MAX_FREE_OUT_OFFSET;
195		p->max_ms_offset = XLP8XX_MAX_MS_OFFSET;
196		p->max_pmem_offset = XLP8XX_MAX_PMEM_OFFSET;
197		p->stg1_2_credit = XLP8XX_STG1_2_CREDIT;
198		p->stg2_eh_credit = XLP8XX_STG2_EH_CREDIT;
199		p->stg2_frout_credit = XLP8XX_STG2_FROUT_CREDIT;
200		p->stg2_ms_credit = XLP8XX_STG2_MS_CREDIT;
201	}
202
203	switch (p->type) {
204	case SGMIIC:
205		p->num_free_descs = 52;
206		p->iface_fifo_size = 13;
207		p->rxbuf_size = 128;
208		p->rx_slots_reqd = SGMII_CAL_SLOTS;
209		p->tx_slots_reqd = SGMII_CAL_SLOTS;
210		if (nlm_is_xlp3xx())
211		    p->pseq_fifo_size = 30;
212		else
213		    p->pseq_fifo_size = 62;
214		break;
215	case ILC:
216		p->num_free_descs = 150;
217		p->rxbuf_size = 944;
218		p->rx_slots_reqd = IL8_CAL_SLOTS;
219		p->tx_slots_reqd = IL8_CAL_SLOTS;
220		p->pseq_fifo_size = 225;
221		p->iface_fifo_size = 55;
222		break;
223	case XAUIC:
224	default:
225		p->num_free_descs = 150;
226		p->rxbuf_size = 944;
227		p->rx_slots_reqd = XAUI_CAL_SLOTS;
228		p->tx_slots_reqd = XAUI_CAL_SLOTS;
229		if (nlm_is_xlp3xx()) {
230		    p->pseq_fifo_size = 120;
231		    p->iface_fifo_size = 52;
232		} else {
233		    p->pseq_fifo_size = 225;
234		    p->iface_fifo_size = 55;
235		}
236		break;
237	}
238}
239
240/* XLP 8XX evaluation boards have the following phy-addr
241 * assignment. There are two external mdio buses in XLP --
242 * bus 0 and bus 1. The management ports (16 and 17) are
243 * on mdio bus 0 while blocks/complexes[0 to 3] are all
244 * on mdio bus 1. The phy_addr on bus 0 (mgmt ports 16
245 * and 17) match the port numbers.
246 * These are the details:
247 * block  port   phy_addr   mdio_bus
248 * ====================================
249 * 0         0     4          1
250 * 0         1     7          1
251 * 0         2     6          1
252 * 0         3     5          1
253 * 1         0     8          1
254 * 1         1     11         1
255 * 1         2     10         1
256 * 1         3     9          1
257 * 2         0     0          1
258 * 2         1     3          1
259 * 2         2     2          1
260 * 2         3     1          1
261 * 3         0     12         1
262 * 3         1     15         1
263 * 3         2     14         1
264 * 3         3     13         1
265 *
266 * 4         0     16         0
267 * 4         1     17         0
268 *
269 * The XLP 3XX evaluation boards have the following phy-addr
270 * assignments.
271 * block  port   phy_addr   mdio_bus
272 * ====================================
273 * 0         0     4          0
274 * 0         1     7          0
275 * 0         2     6          0
276 * 0         3     5          0
277 * 1         0     8          0
278 * 1         1     11         0
279 * 1         2     10         0
280 * 1         3     9          0
281 */
282static void
283nlm_board_get_phyaddr(int block, int port, int *phyaddr)
284{
285	switch (block) {
286	case 0: switch (port) {
287		case 0: *phyaddr = 4; break;
288		case 1: *phyaddr = 7; break;
289		case 2: *phyaddr = 6; break;
290		case 3: *phyaddr = 5; break;
291		}
292		break;
293	case 1: switch (port) {
294		case 0: *phyaddr = 8; break;
295		case 1: *phyaddr = 11; break;
296		case 2: *phyaddr = 10; break;
297		case 3: *phyaddr = 9; break;
298		}
299		break;
300	case 2: switch (port) {
301		case 0: *phyaddr = 0; break;
302		case 1: *phyaddr = 3; break;
303		case 2: *phyaddr = 2; break;
304		case 3: *phyaddr = 1; break;
305		}
306		break;
307	case 3: switch (port) {
308		case 0: *phyaddr = 12; break;
309		case 1: *phyaddr = 15; break;
310		case 2: *phyaddr = 14; break;
311		case 3: *phyaddr = 13; break;
312		}
313		break;
314	case 4: switch (port) { /* management SGMII */
315		case 0: *phyaddr = 16; break;
316		case 1: *phyaddr = 17; break;
317		}
318		break;
319	}
320}
321
322
323static void
324nlm_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 */
372static int
373nlm_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
532int nlm_board_info_setup(void)
533{
534	if (nlm_setup_xlp_board(0) != 0)
535		return (-1);
536	return (0);
537}
538