root/src/linux/brcm/linux-2.6.23/brcm/shared/bcmrobo.c

Revision 13789, 35.1 kB (checked in by eko, 7 months ago)

try this bcmrobo update

Line 
1 /*
2  * Broadcom 53xx RoboSwitch device driver.
3  *
4  * Copyright (C) 2008, Broadcom Corporation
5  * All Rights Reserved.
6  *
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id: bcmrobo.c,v 1.16.2.3.8.3 2009/01/01 00:39:36 Exp $
13  */
14
15
16 #include <typedefs.h>
17 #include <osl.h>
18 #include <bcmutils.h>
19 #include <siutils.h>
20 #include <hndsoc.h>
21 #include <bcmutils.h>
22 #include <bcmendian.h>
23 #include <bcmparams.h>
24 #include <bcmnvram.h>
25 #include <bcmdevs.h>
26 #include <bcmrobo.h>
27 #include <proto/ethernet.h>
28
29 #define ET_ERROR(args)
30 #define ET_MSG(args)
31
32 #define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \
33                         ((len) == 2) ? *((uint16 *)(var)) : \
34                         *((uint32 *)(var)))
35
36 /*
37  * Switch can be programmed through SPI interface, which
38  * has a rreg and a wreg functions to read from and write to
39  * registers.
40  */
41
42 /* MII access registers */
43 #define PSEUDO_PHYAD    0x1E    /* MII Pseudo PHY address */
44 #define REG_MII_PAGE    0x10    /* MII Page register */
45 #define REG_MII_ADDR    0x11    /* MII Address register */
46 #define REG_MII_DATA0   0x18    /* MII Data register 0 */
47 #define REG_MII_DATA1   0x19    /* MII Data register 1 */
48 #define REG_MII_DATA2   0x1a    /* MII Data register 2 */
49 #define REG_MII_DATA3   0x1b    /* MII Data register 3 */
50
51 /* Page numbers */
52 #define PAGE_CTRL       0x00    /* Control page */
53 #define PAGE_MMR        0x02    /* 5397 Management/Mirroring page */
54 #define PAGE_VTBL       0x05    /* ARL/VLAN Table access page */
55 #define PAGE_VLAN       0x34    /* VLAN page */
56
57 /* Control page registers */
58 #define REG_CTRL_PORT0  0x00    /* Port 0 traffic control register */
59 #define REG_CTRL_PORT1  0x01    /* Port 1 traffic control register */
60 #define REG_CTRL_PORT2  0x02    /* Port 2 traffic control register */
61 #define REG_CTRL_PORT3  0x03    /* Port 3 traffic control register */
62 #define REG_CTRL_PORT4  0x04    /* Port 4 traffic control register */
63 #define REG_CTRL_PORT5  0x05    /* Port 5 traffic control register */
64 #define REG_CTRL_PORT6  0x06    /* Port 6 traffic control register */
65 #define REG_CTRL_PORT7  0x07    /* Port 7 traffic control register */
66 #define REG_CTRL_IMP    0x08    /* IMP port traffic control register */
67 #define REG_CTRL_MODE   0x0B    /* Switch Mode register */
68 #define REG_CTRL_MIIPO  0x0E    /* 5325: MII Port Override register */
69 #define REG_CTRL_SRST   0x79    /* Software reset control register */
70
71 #define REG_DEVICE_ID   0x30    /* 539x Device id: */
72
73 /* VLAN page registers */
74 #define REG_VLAN_CTRL0  0x00    /* VLAN Control 0 register */
75 #define REG_VLAN_CTRL1  0x01    /* VLAN Control 1 register */
76 #define REG_VLAN_CTRL4  0x04    /* VLAN Control 4 register */
77 #define REG_VLAN_CTRL5  0x05    /* VLAN Control 5 register */
78 #define REG_VLAN_ACCESS 0x06    /* VLAN Table Access register */
79 #define REG_VLAN_WRITE  0x08    /* VLAN Write register */
80 #define REG_VLAN_READ   0x0C    /* VLAN Read register */
81 #define REG_VLAN_PTAG0  0x10    /* VLAN Default Port Tag register - port 0 */
82 #define REG_VLAN_PTAG1  0x12    /* VLAN Default Port Tag register - port 1 */
83 #define REG_VLAN_PTAG2  0x14    /* VLAN Default Port Tag register - port 2 */
84 #define REG_VLAN_PTAG3  0x16    /* VLAN Default Port Tag register - port 3 */
85 #define REG_VLAN_PTAG4  0x18    /* VLAN Default Port Tag register - port 4 */
86 #define REG_VLAN_PTAG5  0x1a    /* VLAN Default Port Tag register - port 5 */
87 #define REG_VLAN_PTAG6  0x1c    /* VLAN Default Port Tag register - port 6 */
88 #define REG_VLAN_PTAG7  0x1e    /* VLAN Default Port Tag register - port 7 */
89 #define REG_VLAN_PTAG8  0x20    /* 539x: VLAN Default Port Tag register - IMP port */
90 #define REG_VLAN_PMAP   0x20    /* 5325: VLAN Priority Re-map register */
91
92 #define VLAN_NUMVLANS   16      /* # of VLANs */
93
94
95 /* ARL/VLAN Table Access page registers */
96 #define REG_VTBL_CTRL           0x00    /* ARL Read/Write Control */
97 #define REG_VTBL_MINDX          0x02    /* MAC Address Index */
98 #define REG_VTBL_VINDX          0x08    /* VID Table Index */
99 #define REG_VTBL_ARL_E0         0x10    /* ARL Entry 0 */
100 #define REG_VTBL_ARL_E1         0x18    /* ARL Entry 1 */
101 #define REG_VTBL_DAT_E0         0x18    /* ARL Table Data Entry 0 */
102 #define REG_VTBL_SCTRL          0x20    /* ARL Search Control */
103 #define REG_VTBL_SADDR          0x22    /* ARL Search Address */
104 #define REG_VTBL_SRES           0x24    /* ARL Search Result */
105 #define REG_VTBL_SREXT          0x2c    /* ARL Search Result */
106 #define REG_VTBL_VID_E0         0x30    /* VID Entry 0 */
107 #define REG_VTBL_VID_E1         0x32    /* VID Entry 1 */
108 #define REG_VTBL_PREG           0xFF    /* Page Register */
109 #define REG_VTBL_ACCESS         0x60    /* VLAN table access register */
110 #define REG_VTBL_INDX           0x61    /* VLAN table address index register */
111 #define REG_VTBL_ENTRY          0x63    /* VLAN table entry register */
112 #define REG_VTBL_ACCESS_5395    0x80    /* VLAN table access register */
113 #define REG_VTBL_INDX_5395      0x81    /* VLAN table address index register */
114 #define REG_VTBL_ENTRY_5395     0x83    /* VLAN table entry register */
115
116 /* SPI registers */
117 #define REG_SPI_PAGE    0xff    /* SPI Page register */
118
119 /* Access switch registers through GPIO/SPI */
120
121 /* Minimum timing constants */
122 #define SCK_EDGE_TIME   2       /* clock edge duration - 2us */
123 #define MOSI_SETUP_TIME 1       /* input setup duration - 1us */
124 #define SS_SETUP_TIME   1       /* select setup duration - 1us */
125
126 /* misc. constants */
127 #define SPI_MAX_RETRY   100
128
129 /* Enable GPIO access to the chip */
130 static void
131 gpio_enable(robo_info_t *robo)
132 {
133         /* Enable GPIO outputs with SCK and MOSI low, SS high */
134         si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
135         si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi,
136                      robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
137 }
138
139 /* Disable GPIO access to the chip */
140 static void
141 gpio_disable(robo_info_t *robo)
142 {
143         /* Disable GPIO outputs with all their current values */
144         si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
145 }
146
147 /* Write a byte stream to the chip thru SPI */
148 static int
149 spi_write(robo_info_t *robo, uint8 *buf, uint len)
150 {
151         uint i;
152         uint8 mask;
153
154         /* Byte bang from LSB to MSB */
155         for (i = 0; i < len; i++) {
156                 /* Bit bang from MSB to LSB */
157                 for (mask = 0x80; mask; mask >>= 1) {
158                         /* Clock low */
159                         si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
160                         OSL_DELAY(SCK_EDGE_TIME);
161
162                         /* Sample on rising edge */
163                         if (mask & buf[i])
164                                 si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
165                         else
166                                 si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY);
167                         OSL_DELAY(MOSI_SETUP_TIME);
168
169                         /* Clock high */
170                         si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
171                         OSL_DELAY(SCK_EDGE_TIME);
172                 }
173         }
174
175         return 0;
176 }
177
178 /* Read a byte stream from the chip thru SPI */
179 static int
180 spi_read(robo_info_t *robo, uint8 *buf, uint len)
181 {
182         uint i, timeout;
183         uint8 rack, mask, byte;
184
185         /* Timeout after 100 tries without RACK */
186         for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
187                 /* Bit bang from MSB to LSB */
188                 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
189                         /* Clock low */
190                         si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
191                         OSL_DELAY(SCK_EDGE_TIME);
192
193                         /* Sample on falling edge */
194                         if (si_gpioin(robo->sih) & robo->miso)
195                                 byte |= mask;
196
197                         /* Clock high */
198                         si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
199                         OSL_DELAY(SCK_EDGE_TIME);
200                 }
201                 /* RACK when bit 0 is high */
202                 if (!rack) {
203                         rack = (byte & 1);
204                         timeout--;
205                         continue;
206                 }
207                 /* Byte bang from LSB to MSB */
208                 buf[i] = byte;
209                 i++;
210         }
211
212         if (timeout == 0) {
213                 ET_ERROR(("spi_read: timeout"));
214                 return -1;
215         }
216
217         return 0;
218 }
219
220 /* Enable/disable SPI access */
221 static void
222 spi_select(robo_info_t *robo, uint8 spi)
223 {
224         if (spi) {
225                 /* Enable SPI access */
226                 si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY);
227         } else {
228                 /* Disable SPI access */
229                 si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
230         }
231         OSL_DELAY(SS_SETUP_TIME);
232 }
233
234
235 /* Select chip and page */
236 static void
237 spi_goto(robo_info_t *robo, uint8 page)
238 {
239         uint8 reg8 = REG_SPI_PAGE;      /* page select register */
240         uint8 cmd8;
241
242         /* Issue the command only when we are on a different page */
243         if (robo->page == page)
244                 return;
245
246         robo->page = page;
247
248         /* Enable SPI access */
249         spi_select(robo, 1);
250
251         /* Select new page with CID 0 */
252         cmd8 = ((6 << 4) |              /* normal SPI */
253                 1);                     /* write */
254         spi_write(robo, &cmd8, 1);
255         spi_write(robo, &reg8, 1);
256         spi_write(robo, &page, 1);
257
258         /* Disable SPI access */
259         spi_select(robo, 0);
260 }
261
262 /* Write register thru SPI */
263 static int
264 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
265 {
266         int status = 0;
267         uint8 cmd8;
268         union {
269                 uint8 val8;
270                 uint16 val16;
271                 uint32 val32;
272         } bytes;
273
274         /* validate value length and buffer address */
275         ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
276                (len == 4 && !((int)val & 3)));
277
278         /* Select chip and page */
279         spi_goto(robo, page);
280
281         /* Enable SPI access */
282         spi_select(robo, 1);
283
284         /* Write with CID 0 */
285         cmd8 = ((6 << 4) |              /* normal SPI */
286                 1);                     /* write */
287         spi_write(robo, &cmd8, 1);
288         spi_write(robo, &addr, 1);
289         switch (len) {
290         case 1:
291                 bytes.val8 = *(uint8 *)val;
292                 break;
293         case 2:
294                 bytes.val16 = htol16(*(uint16 *)val);
295                 break;
296         case 4:
297                 bytes.val32 = htol32(*(uint32 *)val);
298                 break;
299         }
300         spi_write(robo, (uint8 *)val, len);
301
302         ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
303                 *(uint16 *)val, len));
304         /* Disable SPI access */
305         spi_select(robo, 0);
306         return status;
307 }
308
309 /* Read register thru SPI in fast SPI mode */
310 static int
311 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
312 {
313         int status = 0;
314         uint8 cmd8;
315         union {
316                 uint8 val8;
317                 uint16 val16;
318                 uint32 val32;
319         } bytes;
320
321         /* validate value length and buffer address */
322         ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
323                (len == 4 && !((int)val & 3)));
324
325         /* Select chip and page */
326         spi_goto(robo, page);
327
328         /* Enable SPI access */
329         spi_select(robo, 1);
330
331         /* Fast SPI read with CID 0 and byte offset 0 */
332         cmd8 = (1 << 4);                /* fast SPI */
333         spi_write(robo, &cmd8, 1);
334         spi_write(robo, &addr, 1);
335         status = spi_read(robo, (uint8 *)&bytes, len);
336         switch (len) {
337         case 1:
338                 *(uint8 *)val = bytes.val8;
339                 break;
340         case 2:
341                 *(uint16 *)val = ltoh16(bytes.val16);
342                 break;
343         case 4:
344                 *(uint32 *)val = ltoh32(bytes.val32);
345                 break;
346         }
347
348         ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
349                 *(uint16 *)val, len));
350
351         /* Disable SPI access */
352         spi_select(robo, 0);
353         return status;
354 }
355
356 /* SPI/gpio interface functions */
357 static dev_ops_t spigpio = {
358         gpio_enable,
359         gpio_disable,
360         spi_wreg,
361         spi_rreg,
362         "SPI (GPIO)"
363 };
364
365
366 /* Access switch registers through MII (MDC/MDIO) */
367
368 #define MII_MAX_RETRY   100
369
370 /* Write register thru MDC/MDIO */
371 static int
372 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
373 {
374         uint16 cmd16, val16;
375         void *h = robo->h;
376         int i;
377         uint8 *ptr = (uint8 *)val;
378
379         /* validate value length and buffer address */
380         ASSERT(len == 1 || len == 6 || len == 8 ||
381                ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
382
383         ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
384                VARG(val, len), len));
385
386         /* set page number - MII register 0x10 */
387         if (robo->page != page) {
388                 cmd16 = ((page << 8) |          /* page number */
389                          1);                    /* mdc/mdio access enable */
390                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
391                 robo->page = page;
392         }
393
394         switch (len) {
395         case 8:
396                 val16 = ptr[7];
397                 val16 = ((val16 << 8) | ptr[6]);
398                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
399                 /* FALLTHRU */
400
401         case 6:
402                 val16 = ptr[5];
403                 val16 = ((val16 << 8) | ptr[4]);
404                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
405                 val16 = ptr[3];
406                 val16 = ((val16 << 8) | ptr[2]);
407                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
408                 val16 = ptr[1];
409                 val16 = ((val16 << 8) | ptr[0]);
410                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
411                 break;
412
413         case 4:
414                 val16 = (uint16)((*(uint32 *)val) >> 16);
415                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
416                 val16 = (uint16)(*(uint32 *)val);
417                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
418                 break;
419
420         case 2:
421                 val16 = *(uint16 *)val;
422                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
423                 break;
424
425         case 1:
426                 val16 = *(uint8 *)val;
427                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
428                 break;
429         }
430
431         /* set register address - MII register 0x11 */
432         cmd16 = ((reg << 8) |           /* register address */
433                  1);            /* opcode write */
434         robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
435
436         /* is operation finished? */
437         for (i = MII_MAX_RETRY; i > 0; i --) {
438                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
439                 if ((val16 & 3) == 0)
440                         break;
441         }
442
443         /* timed out */
444         if (!i) {
445                 ET_ERROR(("mii_wreg: timeout"));
446                 return -1;
447         }
448         return 0;
449 }
450
451 /* Read register thru MDC/MDIO */
452 static int
453 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
454 {
455         uint16 cmd16, val16;
456         void *h = robo->h;
457         int i;
458         uint8 *ptr = (uint8 *)val;
459
460         /* validate value length and buffer address */
461         ASSERT(len == 1 || len == 6 || len == 8 ||
462                ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
463
464         /* set page number - MII register 0x10 */
465         if (robo->page != page) {
466                 cmd16 = ((page << 8) |          /* page number */
467                          1);                    /* mdc/mdio access enable */
468                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
469                 robo->page = page;
470         }
471
472         /* set register address - MII register 0x11 */
473         cmd16 = ((reg << 8) |           /* register address */
474                  2);                    /* opcode read */
475         robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
476
477         /* is operation finished? */
478         for (i = MII_MAX_RETRY; i > 0; i --) {
479                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
480                 if ((val16 & 3) == 0)
481                         break;
482         }
483         /* timed out */
484         if (!i) {
485                 ET_ERROR(("mii_rreg: timeout"));
486                 return -1;
487         }
488
489         switch (len) {
490         case 8:
491                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
492                 ptr[7] = (val16 >> 8);
493                 ptr[6] = (val16 & 0xff);
494                 /* FALLTHRU */
495
496         case 6:
497                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
498                 ptr[5] = (val16 >> 8);
499                 ptr[4] = (val16 & 0xff);
500                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
501                 ptr[3] = (val16 >> 8);
502                 ptr[2] = (val16 & 0xff);
503                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
504                 ptr[1] = (val16 >> 8);
505                 ptr[0] = (val16 & 0xff);
506                 break;
507
508         case 4:
509                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
510                 *(uint32 *)val = (((uint32)val16) << 16);
511                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
512                 *(uint32 *)val |= val16;
513                 break;
514
515         case 2:
516                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
517                 *(uint16 *)val = val16;
518                 break;
519
520         case 1:
521                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
522                 *(uint8 *)val = (uint8)(val16 & 0xff);
523                 break;
524         }
525
526         ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
527                VARG(val, len), len));
528
529         return 0;
530 }
531
532 /* MII interface functions */
533 static dev_ops_t mdcmdio = {
534         NULL,
535         NULL,
536         mii_wreg,
537         mii_rreg,
538         "MII (MDC/MDIO)"
539 };
540
541 static int iswrt610nv1=0;
542
543 /* High level switch configuration functions. */
544
545 /* Get access to the RoboSwitch */
546 robo_info_t *
547 bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr)
548 {
549         robo_info_t *robo;
550         uint32 reset, idx;
551         int rreset=8;
552
553         /* Allocate and init private state */
554         if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) {
555                 ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(si_osh(sih))));
556                 return NULL;
557         }
558         bzero(robo, sizeof(robo_info_t));
559
560         robo->h = h;
561         robo->sih = sih;
562         robo->vars = vars;
563         robo->miird = miird;
564         robo->miiwr = miiwr;
565         robo->page = -1;
566         char *boothwmodel = nvram_get("boot_hw_model");
567         char *boothwver = nvram_get("boot_hw_ver");
568         if (boothwmodel==NULL || strcmp(boothwmodel,"WRT300N"))rreset = GPIO_PIN_NOTDEFINED;
569
570         /* Trigger external reset by nvram variable existance */
571         if ((reset = getgpiopin(robo->vars, "robo_reset", rreset)) !=
572             GPIO_PIN_NOTDEFINED) {
573                 /*
574                  * Reset sequence: RESET low(50ms)->high(20ms)
575                  *
576                  * We have to perform a full sequence for we don't know how long
577                  * it has been from power on till now.
578                  */
579                 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
580                 reset = 1 << reset;
581
582                 /* Keep RESET low for 50 ms */
583                 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
584                 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
585                 bcm_mdelay(50);
586
587                 /* Keep RESET high for at least 20 ms */
588                 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
589                 bcm_mdelay(20);
590         } else {
591                 /* In case we need it */
592                 idx = si_coreidx(sih);
593
594                 if (si_setcore(sih, ROBO_CORE_ID, 0)) {
595                         /* If we have an internal robo core, reset it using si_core_reset */
596                         ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
597                         si_core_reset(sih, 0, 0);
598                         robo->corerev = si_corerev(sih);
599                 }
600                 else if (sih->chip == BCM5356_CHIP_ID) {
601                         /* Testing chipid is a temporary hack. We need to really
602                          * figure out how to treat non-cores in ai chips.
603                          */
604                         robo->corerev = 3;
605                 }
606                 si_setcoreidx(sih, idx);
607                 ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev));
608         }
609
610         if (miird && miiwr) {
611                 uint16 tmp;
612                 int rc, retry_count = 0;
613
614                 /* Read the PHY ID */
615                 tmp = miird(h, PSEUDO_PHYAD, 2);
616
617                 /* WAR: Enable mdc/mdio access to the switch registers. Unless
618                  * a write to bit 0 of pseudo phy register 16 is done we are
619                  * unable to talk to the switch on a customer ref design.
620                  */
621                 if (boothwmodel!=NULL && !strcmp(boothwmodel,"WRT610N")
622                         && boothwver!=NULL && !strcmp(boothwver,"1.0"))
623                 {
624                 if (tmp == 0xffff) {
625                         miiwr(h, PSEUDO_PHYAD, 16, 1);
626                         tmp = miird(h, PSEUDO_PHYAD, 2);
627                 }
628                 }
629
630                 if (tmp != 0xffff) {
631                         do {
632                                 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
633                                               &robo->devid, sizeof(uint16));
634                                 if (rc != 0)
635                                         break;
636                                 retry_count++;
637                         } while ((robo->devid == 0) && (retry_count < 10));
638
639                         ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
640                         rc ? "un" : "", robo->devid));
641                         ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
642                         robo->ops = &mdcmdio;
643                         if ((rc != 0) || (robo->devid == 0)) {
644                                 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
645                                 robo->devid = DEVID5325;
646                         }
647                 }
648                 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
649         }
650                 if (robo->devid == DEVID5395)
651                         nvram_set("switch_type", "BCM5395");
652                 else if(robo->devid == DEVID5397)
653                         nvram_set("switch_type", "BCM5397");
654                 else if(robo->devid == DEVID5325)
655                         nvram_set("switch_type", "BCM5325");
656                 else if(robo->devid == DEVID53115)
657                         nvram_set("switch_type", "BCM53115S");
658                 else
659                         nvram_set("switch_type", "unknown");                                           
660                 if (boothwmodel!=NULL && !strcmp(boothwmodel,"WRT610N")
661                         && boothwver!=NULL && !strcmp(boothwver,"1.0"))
662                 iswrt610nv1=1;
663
664         if (!iswrt610nv1)
665         if ((robo->devid == DEVID5395) ||
666             (robo->devid == DEVID5397) ||
667             (robo->devid == DEVID5398)) { /*-- wuzh add for Chip 53115S 2008-3-21 --*/
668                 uint8 srst_ctrl;
669
670                 /* If it is a 539x switch, use the soft reset register */
671                 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
672
673                 /* Reset the 539x switch core and register file */
674                 srst_ctrl = 0x83;
675                 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
676                 bcm_mdelay(500);
677                 srst_ctrl = 0x00;
678                 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
679         }
680
681         if (!robo->ops) {
682                 int mosi, miso, ss, sck;
683
684                 robo->ops = &spigpio;
685                 robo->devid = DEVID5325;
686
687                 /* Init GPIO mapping. Default 2, 3, 4, 5 */
688                 ss = getgpiopin(vars, "robo_ss", 2);
689                 if (ss == GPIO_PIN_NOTDEFINED) {
690                         ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
691                         goto error;
692                 }
693                 robo->ss = 1 << ss;
694                 sck = getgpiopin(vars, "robo_sck", 3);
695                 if (sck == GPIO_PIN_NOTDEFINED) {
696                         ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
697                         goto error;
698                 }
699                 robo->sck = 1 << sck;
700                 mosi = getgpiopin(vars, "robo_mosi", 4);
701                 if (mosi == GPIO_PIN_NOTDEFINED) {
702                         ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
703                         goto error;
704                 }
705                 robo->mosi = 1 << mosi;
706                 miso = getgpiopin(vars, "robo_miso", 5);
707                 if (miso == GPIO_PIN_NOTDEFINED) {
708                         ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
709                         goto error;
710                 }
711                 robo->miso = 1 << miso;
712                 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
713                         ss, sck, mosi, miso));
714         }
715
716         /* sanity check */
717         ASSERT(robo->ops);
718         ASSERT(robo->ops->write_reg);
719         ASSERT(robo->ops->read_reg);
720         ASSERT((robo->devid == DEVID5325) ||
721                (robo->devid == DEVID5395) ||
722                (robo->devid == DEVID5397) ||
723                (robo->devid == DEVID5398) ||
724                (robo->devid == DEVID53115));
725
726         return robo;
727
728 error:
729         bcm_robo_detach(robo);
730         return NULL;
731 }
732
733 /* Release access to the RoboSwitch */
734 void
735 bcm_robo_detach(robo_info_t *robo)
736 {
737         MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
738 }
739
740 /* Enable the device and set it to a known good state */
741 int
742 bcm_robo_enable_device(robo_info_t *robo)
743 {
744         uint8 reg_offset, reg_val;
745         int ret = 0;
746
747         /* Enable management interface access */
748         if (robo->ops->enable_mgmtif)
749                 robo->ops->enable_mgmtif(robo);
750
751         if (robo->devid == DEVID5398) {
752                 /* Disable unused ports: port 6 and 7 */
753                 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
754                         /* Set bits [1:0] to disable RX and TX */
755                         reg_val = 0x03;
756                         robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
757                                              sizeof(reg_val));
758                 }
759         }
760
761         if (robo->devid == DEVID5325) {
762                 /* Must put the switch into Reverse MII mode! */
763
764                 /* MII port state override (page 0 register 14) */
765                 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
766
767                 /* Bit 4 enables reverse MII mode */
768                 if (!(reg_val & (1 << 4))) {
769                         /* Enable RvMII */
770                         reg_val |= (1 << 4);
771                         robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
772                                              sizeof(reg_val));
773
774                         /* Read back */
775                         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
776                                             sizeof(reg_val));
777                         if (!(reg_val & (1 << 4))) {
778                                 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
779                                 ret = -1;
780                         }
781                 }
782         }
783
784         /* Disable management interface access */
785         if (robo->ops->disable_mgmtif)
786                 robo->ops->disable_mgmtif(robo);
787
788         return ret;
789 }
790
791 /* Port flags */
792 #define FLAG_TAGGED     't'     /* output tagged (external ports only) */
793 #define FLAG_UNTAG      'u'     /* input & output untagged (CPU port only, for OS (linux, ...) */
794 #define FLAG_LAN        '*'     /* input & output untagged (CPU port only, for CFE */
795
796 /* port descriptor */
797 typedef struct {
798         uint32 untag;   /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
799         uint32 member;  /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
800         uint8 ptagr;    /* port tag register address (Page 0x34 Address 0x10-0x1F) */
801         uint8 cpu;      /* is this cpu port? */
802 } pdesc_t;
803
804 pdesc_t pdesc97[] = {
805         /* 5395/5397/5398/53115S is 0 ~ 7.  port 8 is IMP port. */
806         /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
807         /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
808         /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
809         /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
810         /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
811         /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
812         /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
813         /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
814         /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
815 };
816
817 pdesc_t pdesc25[] = {
818         /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
819         /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
820         /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
821         /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
822         /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
823         /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
824 };
825
826 /* Configure the VLANs */
827 int
828 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
829 {
830         uint8 val8;
831         uint16 val16;
832         uint32 val32;
833         pdesc_t *pdesc;
834         int pdescsz;
835         uint16 vid;
836         uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
837
838         /* Enable management interface access */
839         if (robo->ops->enable_mgmtif)
840                 robo->ops->enable_mgmtif(robo);
841
842         /* setup global vlan configuration */
843         /* VLAN Control 0 Register (Page 0x34, Address 0) */
844         robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
845         val8 |= ((1 << 7) |             /* enable 802.1Q VLAN */
846                  (3 << 5));             /* individual VLAN learning mode */
847         if (robo->devid == DEVID5325)
848                 val8 &= ~(1 << 1);      /* must clear reserved bit 1 */
849         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
850
851         /* VLAN Control 1 Register (Page 0x34, Address 1) */
852         robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
853         val8 |= ((1 << 2) |             /* enable RSV multicast V Fwdmap */
854                  (1 << 3));             /* enable RSV multicast V Untagmap */
855         if (robo->devid == DEVID5325)
856                 val8 |= (1 << 1);       /* enable RSV multicast V Tagging */
857         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
858
859         arl_entry[0] = mac_addr[5];
860         arl_entry[1] = mac_addr[4];
861         arl_entry[2] = mac_addr[3];
862         arl_entry[3] = mac_addr[2];
863         arl_entry[4] = mac_addr[1];
864         arl_entry[5] = mac_addr[0];
865
866         if (robo->devid == DEVID5325) {
867                 /* Init the entry 1 of the bin */
868                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
869                                      arl_entry1, sizeof(arl_entry1));
870                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
871                                      arl_entry1, 1);
872
873                 /* Init the entry 0 of the bin */
874                 arl_entry[6] = 0x8;             /* Port Id: MII */
875                 arl_entry[7] = 0xc0;    /* Static Entry, Valid */
876
877                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
878                                      arl_entry, sizeof(arl_entry));
879                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
880                                      arl_entry, ETHER_ADDR_LEN);
881
882                 /* VLAN Control 4 Register (Page 0x34, Address 4) */
883                 val8 = (1 << 6);                /* drop frame with VID violation */
884                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
885
886                 /* VLAN Control 5 Register (Page 0x34, Address 5) */
887                 val8 = (1 << 3);                /* drop frame when miss V table */
888                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
889
890                 pdesc = pdesc25;
891                 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
892         } else {
893                 /* Initialize the MAC Addr Index Register */
894                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
895                                      arl_entry, ETHER_ADDR_LEN);
896
897                 pdesc = pdesc97;
898                 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
899         }
900
901         /* setup each vlan. max. 16 vlans. */
902         /* force vlan id to be equal to vlan number */
903         for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
904                 char vlanports[] = "vlanXXXXports";
905                 char port[] = "XXXX", *ports, *next, *cur;
906                 uint32 untag = 0;
907                 uint32 member = 0;
908                 int pid, len;
909
910                 /* no members if VLAN id is out of limitation */
911                 if (vid > VLAN_MAXVID)
912                         goto vlan_setup;
913
914                 /* get vlan member ports from nvram */
915                 sprintf(vlanports, "vlan%dports", vid);
916                 ports = getvar(robo->vars, vlanports);
917
918
919                 if ((robo->devid != DEVID5325) && (robo->devid != DEVID5397) && (vid == 0)) {
920                         if (ports)
921                                 printk(KERN_EMERG "VID 0 is set in nvram, Ignoring\n");
922                        
923                         continue;
924 //                  vid = 1;
925                 }
926
927                 if ((DEVID5395 == robo->devid) && (1 == vid)) {
928                         /* get vlan member ports from nvram */
929                         sprintf(vlanports, "vlan0ports");
930                         ports = getvar(robo->vars, vlanports);
931                         if (!ports || !strcmp(ports," "))
932                             {
933                             printk(KERN_EMERG "dd-wrt already booted, use internal fixup\n");
934                             sprintf(vlanports, "vlan1ports");
935                             ports = getvar(robo->vars, vlanports);
936                             }
937                        
938                         printk(KERN_EMERG "configure vlan1 (%s) instead of vlan0 for BCM5395\n",ports);
939                 }               
940
941
942                 /* disable this vlan if not defined */
943                 if (!ports)
944                         goto vlan_setup;
945
946                 /*
947                  * setup each port in the vlan. cpu port needs special handing
948                  * (with or without output tagging) to support linux/pmon/cfe.
949                  */
950                 for (cur = ports; cur; cur = next) {
951                         /* tokenize the port list */
952                         while (*cur == ' ')
953                                 cur ++;
954                         next = bcmstrstr(cur, " ");
955                         len = next ? next - cur : strlen(cur);
956                         if (!len)
957                                 break;
958                         if (len > sizeof(port) - 1)
959                                 len = sizeof(port) - 1;
960                         strncpy(port, cur, len);
961                         port[len] = 0;
962
963                         /* make sure port # is within the range */
964                         pid = bcm_atoi(port);
965                         if (pid >= pdescsz) {
966                                 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
967                                           "of range[0-%d]\n", pid, vid, pdescsz));
968                                 continue;
969                         }
970
971                         /* build VLAN registers values */
972 #ifndef _CFE_
973                         if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
974                             (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
975 #endif
976                                 untag |= pdesc[pid].untag;
977
978                         member |= pdesc[pid].member;
979
980                         /* set port tag - applies to untagged ingress frames */
981                         /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
982 #ifdef  _CFE_
983 #define FL      FLAG_LAN
984 #else
985 #define FL      FLAG_UNTAG
986 #endif /* _CFE_ */
987                         if (!pdesc[pid].cpu || strchr(port, FL)) {
988                                 val16 = ((0 << 13) |            /* priority - always 0 */
989                                          vid);                  /* vlan id */
990                                 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
991                                                      &val16, sizeof(val16));
992                         }
993                 }
994
995                 /* Add static ARL entries */
996                 if (robo->devid == DEVID5325) {
997                         val8 = vid;
998                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
999                                              &val8, sizeof(val8));
1000                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1001                                              &val8, sizeof(val8));
1002
1003                         /* Write the entry */
1004                         val8 = 0x80;
1005                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1006                                              &val8, sizeof(val8));
1007                         /* Wait for write to complete */
1008                         SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1009                                  &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1010                                  100 /* usec */);
1011                 } else {
1012                         /* Set the VLAN Id in VLAN ID Index Register */
1013                         val8 = vid;
1014                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1015                                              &val8, sizeof(val8));
1016
1017                         /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1018                          * Register.
1019                          */
1020                         arl_entry[6] = vid;
1021                         arl_entry[7] = 0x0;
1022                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1023                                              arl_entry, sizeof(arl_entry));
1024
1025                         /* Set the Static bit , Valid bit and Port ID fields in
1026                          * ARL Table Data Entry 0 Register
1027                          */
1028                         val16 = 0xc008;
1029                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
1030                                              &val16, sizeof(val16));
1031
1032                         /* Clear the ARL_R/W bit and set the START/DONE bit in
1033                          * the ARL Read/Write Control Register.
1034                          */
1035                         val8 = 0x80;
1036                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1037                                              &val8, sizeof(val8));
1038                         /* Wait for write to complete */
1039                         SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1040                                  &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1041                                  100 /* usec */);
1042                 }
1043
1044 vlan_setup:
1045                 /* setup VLAN ID and VLAN memberships */
1046
1047                 val32 = (untag |                        /* untag enable */
1048                          member);                       /* vlan members */
1049                 if (robo->devid == DEVID5325) {
1050                         if (robo->corerev < 3) {
1051                                 val32 |= ((1 << 20) |           /* valid write */
1052                                           ((vid >> 4) << 12));  /* vlan id bit[11:4] */
1053                         } else {
1054                                 val32 |= ((1 << 24) |           /* valid write */
1055                                           (vid << 12)); /* vlan id bit[11:4] */
1056                         }
1057                         ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32));
1058
1059                         /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1060                         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1061                                              sizeof(val32));
1062                         /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1063                         val16 = ((1 << 13) |    /* start command */
1064                                  (1 << 12) |    /* write state */
1065                                  vid);          /* vlan id */
1066                         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1067                                              sizeof(val16));
1068                 } else {
1069                         uint8 vtble, vtbli, vtbla;
1070
1071                         if ((robo->devid == DEVID5395) || (robo->devid == DEVID53115)) {
1072                                 vtble = REG_VTBL_ENTRY_5395;
1073                                 vtbli = REG_VTBL_INDX_5395;
1074                                 vtbla = REG_VTBL_ACCESS_5395;
1075                         } else {
1076                                 vtble = REG_VTBL_ENTRY;
1077                                 vtbli = REG_VTBL_INDX;
1078                                 vtbla = REG_VTBL_ACCESS;
1079                         }
1080
1081                         /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1082                         robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1083                                              sizeof(val32));
1084                         /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1085                         val16 = vid;        /* vlan id */
1086                         robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1087                                              sizeof(val16));
1088
1089                         /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1090                         val8 = ((1 << 7) |      /* start command */
1091                                 0);             /* write */
1092                         robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1093                                              sizeof(val8));
1094                 }
1095         }
1096
1097         if (robo->devid == DEVID5325) {
1098                 /* setup priority mapping - applies to tagged ingress frames */
1099                 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1100                 val32 = ((0 << 0) |     /* 0 -> 0 */
1101                          (1 << 3) |     /* 1 -> 1 */
1102                          (2 << 6) |     /* 2 -> 2 */
1103                          (3 << 9) |     /* 3 -> 3 */
1104                          (4 << 12) |    /* 4 -> 4 */
1105                          (5 << 15) |    /* 5 -> 5 */
1106                          (6 << 18) |    /* 6 -> 6 */
1107                          (7 << 21));    /* 7 -> 7 */
1108                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1109         }
1110        
1111         if (robo->devid == DEVID53115) {
1112                 /* Configure the priority system to use to determine the TC of
1113                  * ingress frames. Use DiffServ TC mapping, otherwise 802.1p
1114                  * TC mapping, otherwise MAC based TC mapping.
1115                  */
1116                 val8 = ((0 << 6) |              /* Disable port based QoS */
1117                         (2 << 2));              /* QoS priority selection */
1118                 robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8));
1119
1120                 /* Configure tx queues scheduling mechanism */
1121                 val8 = (3 << 0);                /* Strict priority */
1122                 robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8));
1123
1124                 /* Enable 802.1p Priority to TC mapping for individual ports */
1125                 val16 = 0x11f;
1126                 robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16));
1127
1128                 /* Configure the TC to COS mapping. This determines the egress
1129                  * transmit queue.
1130                  */
1131                 val16 = ((1 << 0)  |    /* Pri 0 mapped to TXQ 1 */
1132                          (0 << 2)  |    /* Pri 1 mapped to TXQ 0 */
1133                          (0 << 4)  |    /* Pri 2 mapped to TXQ 0 */
1134                          (1 << 6)  |    /* Pri 3 mapped to TXQ 1 */
1135                          (2 << 8)  |    /* Pri 4 mapped to TXQ 2 */
1136                          (2 << 10) |    /* Pri 5 mapped to TXQ 2 */
1137                          (3 << 12) |    /* Pri 6 mapped to TXQ 3 */
1138                          (3 << 14));    /* Pri 7 mapped to TXQ 3 */
1139                 robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16));
1140         }
1141
1142         /* Disable management interface access */
1143         if (robo->ops->disable_mgmtif)
1144                 robo->ops->disable_mgmtif(robo);
1145
1146         return 0;
1147 }
1148
1149 /* Enable switching/forwarding */
1150 int
1151 bcm_robo_enable_switch(robo_info_t *robo)
1152 {
1153         int i, max_port_ind, ret = 0;
1154         uint8 val8;
1155         uint16 mode16;
1156         char *boot=nvram_get("boot_hw_model");
1157
1158         /* Enable management interface access */
1159         if (robo->ops->enable_mgmtif)
1160                 robo->ops->enable_mgmtif(robo);
1161
1162         /* Switch Mode register (Page 0, Address 0x0B) */
1163         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1164
1165         /* Bit 1 enables switching/forwarding */
1166         if (!(val8 & (1 << 1))) {
1167                 /* Set unmanaged mode */
1168                 val8 &= (~(1 << 0));
1169
1170                 /* Enable forwarding */
1171                 val8 |= (1 << 1);
1172                 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1173
1174                 /* Read back */
1175                 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1176                 if (!(val8 & (1 << 1))) {
1177                         ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1178                         ret = -1;
1179                 }
1180
1181                 /* No spanning tree for unmanaged mode */
1182                 val8 = 0;
1183                 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
1184                 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1185                         robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1186                 }
1187
1188                 /* No spanning tree on IMP port too */
1189                 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8));
1190         }
1191
1192 char *boardnum=nvram_get("boardnum");
1193 char *boardtype=nvram_get("boardtype");
1194 char *cardbus=nvram_get("cardbus");
1195
1196 if (boardnum!=NULL && boardtype!=NULL && cardbus!=NULL)
1197 if (!strcmp(boardnum,"42") && !strcmp(boardtype,"0x478") && !strcmp(cardbus,"1") && (!boot || (strcmp(boot, "WRT300N") && strcmp(boot, "WRT610N"))))
1198     {
1199         printk(KERN_EMERG "Enable WRT350 LED fix\n");
1200         /* WAN port LED */
1201         mode16 = 0x1f;
1202         robo->ops->write_reg(robo, PAGE_CTRL, 0x16, &mode16, 2);   
1203     }
1204
1205         /* Disable management interface access */
1206         if (robo->ops->disable_mgmtif)
1207                 robo->ops->disable_mgmtif(robo);
1208
1209         return ret;
1210 }
Note: See TracBrowser for help on using the browser.