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