]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/nlm/board.c
Dtrace: add toupper()/tolower() and enhancements to lltostr().
[FreeBSD/FreeBSD.git] / sys / mips / nlm / board.c
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
55 static uint8_t board_eeprom_buf[EEPROM_SIZE];
56 static int board_eeprom_set;
57
58 struct xlp_board_info xlp_board_info;
59
60 struct vfbid_tbl {
61         int vfbid;
62         int dest_vc;
63 };
64
65 /* XXXJC : this should be derived from msg thread mask */
66 static 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
85 static 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
101 int
102 nlm_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
123 int
124 nlm_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
139 void
140 xlpge_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
152 static void
153 nlm_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  */
282 static void
283 nlm_board_get_phyaddr(int block, int port, int *mdio, int *phyaddr)
284 {
285
286         /* XXXJC: this is a board feature, check for chip not proper */
287         if (nlm_is_xlp3xx() || (nlm_is_xlp8xx() && block == 4))
288             *mdio = 0;
289         else
290             *mdio = 1;
291
292         switch (block) {
293         case 0: switch (port) {
294                 case 0: *phyaddr = 4; break;
295                 case 1: *phyaddr = 7; break;
296                 case 2: *phyaddr = 6; break;
297                 case 3: *phyaddr = 5; break;
298                 }
299                 break;
300         case 1: switch (port) {
301                 case 0: *phyaddr = 8; break;
302                 case 1: *phyaddr = 11; break;
303                 case 2: *phyaddr = 10; break;
304                 case 3: *phyaddr = 9; break;
305                 }
306                 break;
307         case 2: switch (port) {
308                 case 0: *phyaddr = 0; break;
309                 case 1: *phyaddr = 3; break;
310                 case 2: *phyaddr = 2; break;
311                 case 3: *phyaddr = 1; break;
312                 }
313                 break;
314         case 3: switch (port) {
315                 case 0: *phyaddr = 12; break;
316                 case 1: *phyaddr = 15; break;
317                 case 2: *phyaddr = 14; break;
318                 case 3: *phyaddr = 13; break;
319                 }
320                 break;
321         case 4: switch (port) { /* management SGMII */
322                 case 0: *phyaddr = 16; break;
323                 case 1: *phyaddr = 17; break;
324                 }
325                 break;
326         }
327 }
328
329
330 static void
331 nlm_print_processor_info(void)
332 {
333         uint32_t procid;
334         int prid, rev;
335         char *chip, *revstr;
336
337         procid = mips_rd_prid();
338         prid = (procid >> 8) & 0xff;
339         rev = procid & 0xff;
340
341         switch (prid) {
342         case CHIP_PROCESSOR_ID_XLP_8XX:
343                 chip = "XLP 832";
344                 break;
345         case CHIP_PROCESSOR_ID_XLP_3XX:
346                 chip = "XLP 3xx";
347                 break;
348         case CHIP_PROCESSOR_ID_XLP_432:
349         case CHIP_PROCESSOR_ID_XLP_416:
350                 chip = "XLP 4xx";
351                 break;
352         default:
353                 chip = "XLP ?xx";
354                 break;
355         }
356         switch (rev) {
357         case 0:
358                 revstr = "A0"; break;
359         case 1:
360                 revstr = "A1"; break;
361         case 2:
362                 revstr = "A2"; break;
363         case 3:
364                 revstr = "B0"; break;
365         case 4:
366                 revstr = "B1"; break;
367         default:
368                 revstr = "??"; break;
369         }
370
371         printf("Processor info:\n");
372         printf("  Netlogic %s %s [%x]\n", chip, revstr, procid);
373 }
374
375 /*
376  * All our knowledge of chip and board that cannot be detected by probing 
377  * at run-time goes here
378  */
379 static int
380 nlm_setup_xlp_board(void)
381 {
382         struct xlp_board_info   *boardp;
383         struct xlp_node_info    *nodep;
384         struct xlp_nae_ivars    *naep;
385         struct xlp_block_ivars  *blockp;
386         struct xlp_port_ivars   *portp;
387         uint64_t cpldbase, nae_pcibase;
388         int     node, block, port, rv, dbtype, usecpld;
389         uint8_t *b;
390
391         /* start with a clean slate */
392         boardp = &xlp_board_info;
393         memset(boardp, 0, sizeof(xlp_board_info));
394         boardp->nodemask = 0x1; /* only node 0 */
395         nlm_print_processor_info();
396
397         b =  board_eeprom_buf;
398         rv = nlm_board_eeprom_read(0, EEPROM_I2CBUS, EEPROM_I2CADDR, 0, b,
399             EEPROM_SIZE);
400         if (rv == 0) {
401                 board_eeprom_set = 1;
402                 printf("Board info (EEPROM on i2c@%d at %#X):\n",
403                     EEPROM_I2CBUS, EEPROM_I2CADDR);
404                 printf("  Model:      %7.7s %2.2s\n", &b[16], &b[24]);
405                 printf("  Serial #:   %3.3s-%2.2s\n", &b[27], &b[31]);
406                 printf("  MAC addr:   %02x:%02x:%02x:%02x:%02x:%02x\n",
407                     b[2], b[3], b[4], b[5], b[6], b[7]);
408         } else
409                 printf("Board Info: Error on EEPROM read (i2c@%d %#X).\n",
410                     EEPROM_I2CBUS, EEPROM_I2CADDR);
411
412
413         /* XXXJC: check for boards with right CPLD, for now
414          *        4xx PCI cards don't have CPLD with daughter
415          *        card info */
416         usecpld = !nlm_is_xlp4xx();
417
418         for (node = 0; node < XLP_MAX_NODES; node++) {
419                 if ((boardp->nodemask & (1 << node)) == 0)
420                         continue;
421                 nae_pcibase = nlm_get_nae_pcibase(node);
422                 nodep = &boardp->nodes[node];
423                 naep = &nodep->nae_ivars;
424                 naep->node = node;
425
426                 naep->nblocks = nae_num_complex(nae_pcibase);
427                 /* 3xx chips lie shamelessly about this */
428                 if (nlm_is_xlp3xx())
429                         naep->nblocks = naep->nblocks - 1;
430                 naep->blockmask = (1 << naep->nblocks) - 1;     /* XXXJC: redundant */
431                 naep->xauimask = 0x0;   /* set this based on daughter card */
432                 naep->sgmiimask = 0x0;  /* set this based on daughter card */
433
434                 /* frequency at which network block runs */
435                 naep->freq = 500;
436
437                 /* CRC16 polynomial used for flow table generation */
438                 naep->flow_crc_poly = 0xffff;
439                 naep->hw_parser_en = 1;
440                 naep->prepad_en = 1;
441                 naep->prepad_size = 3; /* size in 16 byte units */
442
443                 naep->ieee_1588_en = 1;
444                 cpldbase = nlm_board_cpld_base(node, XLP_EVB_CPLD_CHIPSELECT);
445
446                 for (block = 0; block < naep->nblocks; block++) {
447                         blockp = &naep->block_ivars[block];
448                         blockp->block = block;
449                         if (usecpld)
450                                 dbtype = nlm_board_cpld_dboard_type(cpldbase,
451                                     block);
452                         else
453                                 dbtype = DCARD_XAUI;  /* default XAUI */
454
455                         if (block == 4) {
456                                 /* management block 4 on 8xx */
457                                 blockp->type = SGMIIC;
458                                 blockp->portmask = 0x3;
459                                 naep->sgmiimask |= (1 << block);
460                         } else {
461                                 switch (dbtype) {
462                                 case DCARD_ILAKEN:
463                                         blockp->type = ILC;
464                                         blockp->portmask = 0x1;
465                                         naep->xauimask |= (1 << block);
466                                         break;
467                                 case DCARD_SGMII:
468                                         blockp->type = SGMIIC;
469                                         blockp->portmask = 0xf;
470                                         naep->sgmiimask |= (1 << block);
471                                         break;
472                                 case DCARD_XAUI:
473                                 default:
474                                         blockp->type = XAUIC;
475                                         blockp->portmask = 0x1;
476                                         naep->xauimask |= (1 << block);
477                                         break;
478                                 }
479                         }
480                         for (port = 0; port < PORTS_PER_CMPLX; port++) {
481                                 if ((blockp->portmask & (1 << port)) == 0)
482                                         continue;
483                                 portp = &blockp->port_ivars[port];
484                                 nlm_board_get_phyaddr(block, port,
485                                     &portp->mdio_bus, &portp->phy_addr);
486                                 portp->port = port;
487                                 portp->block = block;
488                                 portp->node = node;
489                                 portp->type = blockp->type;
490                                 nlm_setup_port_defaults(portp);
491                         }
492                 }
493         }
494
495         /* pretty print network config */
496         printf("Network config");
497         if (usecpld)
498                 printf("(from CPLD@%d):\n", XLP_EVB_CPLD_CHIPSELECT);
499         else
500                 printf("(defaults):\n");
501         for (node = 0; node < XLP_MAX_NODES; node++) {
502                 if ((boardp->nodemask & (1 << node)) == 0)
503                         continue;
504                 nodep = &boardp->nodes[node];
505                 naep = &nodep->nae_ivars;
506                 printf("  NAE@%d Blocks: ", node);
507                 for (block = 0; block < naep->nblocks; block++) {
508                         char *s = "???";
509
510                         blockp = &naep->block_ivars[block];
511                         switch (blockp->type) {
512                                 case SGMIIC : s = "SGMII"; break;
513                                 case XAUIC  : s = "XAUI"; break;
514                                 case ILC    : s = "IL"; break;
515                         }
516                         printf(" [%d %s]", block, s);
517                 }
518                 printf("\n");
519         }
520         return (0);
521 }
522
523 int nlm_board_info_setup(void)
524 {
525         nlm_setup_xlp_board();
526         return (0);
527 }