dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / shared / bcmrobo.c
blob6884929683c3ed1f54081c8e6897e29c26e2dfe6
1 /*
2 * Broadcom 53xx RoboSwitch device driver.
4 * Copyright 2007, 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.
12 * $Id$
16 #include <typedefs.h>
17 #include <osl.h>
18 #include <bcmutils.h>
19 #include <sbutils.h>
20 #include <sbconfig.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>
29 #define ET_ERROR(args)
30 #define ET_MSG(args)
31 //#define VID_MAP_DBG
34 * Switch can be programmed through SPI interface, which
35 * has a rreg and a wreg functions to read from and write to
36 * registers.
39 /* MII access registers */
40 #define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
41 #define REG_MII_PAGE 0x10 /* MII Page register */
42 #define REG_MII_ADDR 0x11 /* MII Address register */
43 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
44 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
45 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
46 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
48 /* Page numbers */
49 #define PAGE_CTRL 0x00 /* Control page */
50 #define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
51 #define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
52 #define PAGE_VLAN 0x34 /* VLAN page */
54 /* Control page registers */
55 #define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
56 #define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
57 #define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
58 #define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
59 #define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
60 #define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
61 #define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
62 #define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
63 #define REG_CTRL_MODE 0x0B /* Switch Mode register */
64 #define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
65 #define REG_CTRL_SRST 0x79 /* Software reset control register */
67 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
68 #define DEVID5325 0x25 /* 5325 (Not really be we fake it) */
69 #define DEVID5395 0x95 /* 5395 */
70 #define DEVID5397 0x97 /* 5397 */
71 #define DEVID5398 0x98 /* 5398 */
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_ACCESS_5365 0x08 /* 5365 VLAN Table Access register */
80 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
81 #define REG_VLAN_WRITE_5365 0x0A /* 5365 VLAN Write register */
82 #define REG_VLAN_READ 0x0C /* VLAN Read register */
83 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
84 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
85 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
86 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
87 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
88 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
89 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
90 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
91 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
92 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
94 #define VLAN_NUMVLANS 16 /* # of VLANs */
97 /* ARL/VLAN Table Access page registers */
98 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
99 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
100 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
101 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
102 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
103 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
104 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
105 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
106 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
107 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
108 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
109 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
110 #define REG_VTBL_PREG 0xFF /* Page Register */
111 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
112 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
113 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
114 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
115 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
116 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
118 /* SPI registers */
119 #define REG_SPI_PAGE 0xff /* SPI Page register */
121 /* Access switch registers through GPIO/SPI */
123 /* Minimum timing constants */
124 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
125 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
126 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
128 /* misc. constants */
129 #define SPI_MAX_RETRY 100
131 /* Enable GPIO access to the chip */
132 static void
133 gpio_enable(robo_info_t *robo)
135 /* Enable GPIO outputs with SCK and MOSI low, SS high */
136 sb_gpioout(robo->sbh, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
137 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi,
138 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
141 /* Disable GPIO access to the chip */
142 static void
143 gpio_disable(robo_info_t *robo)
145 /* Disable GPIO outputs with all their current values */
146 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
149 /* Write a byte stream to the chip thru SPI */
150 static int
151 spi_write(robo_info_t *robo, uint8 *buf, uint len)
153 uint i;
154 uint8 mask;
156 /* Byte bang from LSB to MSB */
157 for (i = 0; i < len; i++) {
158 /* Bit bang from MSB to LSB */
159 for (mask = 0x80; mask; mask >>= 1) {
160 /* Clock low */
161 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
162 OSL_DELAY(SCK_EDGE_TIME);
164 /* Sample on rising edge */
165 if (mask & buf[i])
166 sb_gpioout(robo->sbh, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
167 else
168 sb_gpioout(robo->sbh, robo->mosi, 0, GPIO_DRV_PRIORITY);
169 OSL_DELAY(MOSI_SETUP_TIME);
171 /* Clock high */
172 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
173 OSL_DELAY(SCK_EDGE_TIME);
177 return 0;
180 /* Read a byte stream from the chip thru SPI */
181 static int
182 spi_read(robo_info_t *robo, uint8 *buf, uint len)
184 uint i, timeout;
185 uint8 rack, mask, byte;
187 /* Timeout after 100 tries without RACK */
188 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
189 /* Bit bang from MSB to LSB */
190 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
191 /* Clock low */
192 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
193 OSL_DELAY(SCK_EDGE_TIME);
195 /* Sample on falling edge */
196 if (sb_gpioin(robo->sbh) & robo->miso)
197 byte |= mask;
199 /* Clock high */
200 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
201 OSL_DELAY(SCK_EDGE_TIME);
203 /* RACK when bit 0 is high */
204 if (!rack) {
205 rack = (byte & 1);
206 timeout--;
207 continue;
209 /* Byte bang from LSB to MSB */
210 buf[i] = byte;
211 i++;
214 if (timeout == 0) {
215 ET_ERROR(("spi_read: timeout"));
216 return -1;
219 return 0;
222 /* Enable/disable SPI access */
223 static void
224 spi_select(robo_info_t *robo, uint8 spi)
226 if (spi) {
227 /* Enable SPI access */
228 sb_gpioout(robo->sbh, robo->ss, 0, GPIO_DRV_PRIORITY);
229 } else {
230 /* Disable SPI access */
231 sb_gpioout(robo->sbh, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
233 OSL_DELAY(SS_SETUP_TIME);
237 /* Select chip and page */
238 static void
239 spi_goto(robo_info_t *robo, uint8 page)
241 uint8 reg8 = REG_SPI_PAGE; /* page select register */
242 uint8 cmd8;
244 /* Issue the command only when we are on a different page */
245 if (robo->page == page)
246 return;
248 robo->page = page;
250 /* Enable SPI access */
251 spi_select(robo, 1);
253 /* Select new page with CID 0 */
254 cmd8 = ((6 << 4) | /* normal SPI */
255 1); /* write */
256 spi_write(robo, &cmd8, 1);
257 spi_write(robo, &reg8, 1);
258 spi_write(robo, &page, 1);
260 /* Disable SPI access */
261 spi_select(robo, 0);
264 /* Write register thru SPI */
265 static int
266 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
268 int status = 0;
269 uint8 cmd8;
270 union {
271 uint8 val8;
272 uint16 val16;
273 uint32 val32;
274 } bytes;
276 /* validate value length and buffer address */
277 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
278 (len == 4 && !((int)val & 3)));
280 /* Select chip and page */
281 spi_goto(robo, page);
283 /* Enable SPI access */
284 spi_select(robo, 1);
286 /* Write with CID 0 */
287 cmd8 = ((6 << 4) | /* normal SPI */
288 1); /* write */
289 spi_write(robo, &cmd8, 1);
290 spi_write(robo, &addr, 1);
291 switch (len) {
292 case 1:
293 bytes.val8 = *(uint8 *)val;
294 break;
295 case 2:
296 bytes.val16 = htol16(*(uint16 *)val);
297 break;
298 case 4:
299 bytes.val32 = htol32(*(uint32 *)val);
300 break;
302 spi_write(robo, (uint8 *)val, len);
304 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
305 *(uint16 *)val, len));
306 /* Disable SPI access */
307 spi_select(robo, 0);
308 return status;
311 /* Read register thru SPI in fast SPI mode */
312 static int
313 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
315 int status = 0;
316 uint8 cmd8;
317 union {
318 uint8 val8;
319 uint16 val16;
320 uint32 val32;
321 } bytes;
323 /* validate value length and buffer address */
324 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
325 (len == 4 && !((int)val & 3)));
327 /* Select chip and page */
328 spi_goto(robo, page);
330 /* Enable SPI access */
331 spi_select(robo, 1);
333 /* Fast SPI read with CID 0 and byte offset 0 */
334 cmd8 = (1 << 4); /* fast SPI */
335 spi_write(robo, &cmd8, 1);
336 spi_write(robo, &addr, 1);
337 status = spi_read(robo, (uint8 *)&bytes, len);
338 switch (len) {
339 case 1:
340 *(uint8 *)val = bytes.val8;
341 break;
342 case 2:
343 *(uint16 *)val = ltoh16(bytes.val16);
344 break;
345 case 4:
346 *(uint32 *)val = ltoh32(bytes.val32);
347 break;
350 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
351 *(uint16 *)val, len));
353 /* Disable SPI access */
354 spi_select(robo, 0);
355 return status;
358 /* SPI/gpio interface functions */
359 static dev_ops_t spigpio = {
360 gpio_enable,
361 gpio_disable,
362 spi_wreg,
363 spi_rreg,
364 "SPI (GPIO)"
368 /* Access switch registers through MII (MDC/MDIO) */
370 #define MII_MAX_RETRY 100
372 /* Write register thru MDC/MDIO */
373 static int
374 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
376 uint16 cmd16, val16;
377 void *h = robo->h;
378 int i;
379 uint8 *ptr = (uint8 *)val;
381 /* validate value length and buffer address */
382 ASSERT(len == 1 || len == 6 || len == 8 ||
383 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
385 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
386 *(uint16 *)val, len));
388 /* set page number - MII register 0x10 */
389 if (robo->page != page) {
390 cmd16 = ((page << 8) | /* page number */
391 1); /* mdc/mdio access enable */
392 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
393 robo->page = page;
396 switch (len) {
397 case 8:
398 val16 = ptr[7];
399 val16 = ((val16 << 8) | ptr[6]);
400 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
401 /* FALLTHRU */
403 case 6:
404 val16 = ptr[5];
405 val16 = ((val16 << 8) | ptr[4]);
406 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
407 val16 = ptr[3];
408 val16 = ((val16 << 8) | ptr[2]);
409 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
410 val16 = ptr[1];
411 val16 = ((val16 << 8) | ptr[0]);
412 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
413 break;
415 case 4:
416 val16 = (uint16)((*(uint32 *)val) >> 16);
417 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
418 val16 = (uint16)(*(uint32 *)val);
419 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
420 break;
422 case 2:
423 val16 = *(uint16 *)val;
424 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
425 break;
427 case 1:
428 val16 = *(uint8 *)val;
429 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
430 break;
433 /* set register address - MII register 0x11 */
434 cmd16 = ((reg << 8) | /* register address */
435 1); /* opcode write */
436 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
438 /* is operation finished? */
439 for (i = MII_MAX_RETRY; i > 0; i --) {
440 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
441 if ((val16 & 3) == 0)
442 break;
445 /* timed out */
446 if (!i) {
447 ET_ERROR(("mii_wreg: timeout"));
448 return -1;
450 return 0;
453 /* Read register thru MDC/MDIO */
454 static int
455 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
457 uint16 cmd16, val16;
458 void *h = robo->h;
459 int i;
460 uint8 *ptr = (uint8 *)val;
462 /* validate value length and buffer address */
463 ASSERT(len == 1 || len == 6 || len == 8 ||
464 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
466 /* set page number - MII register 0x10 */
467 if (robo->page != page) {
468 cmd16 = ((page << 8) | /* page number */
469 1); /* mdc/mdio access enable */
470 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
471 robo->page = page;
474 /* set register address - MII register 0x11 */
475 cmd16 = ((reg << 8) | /* register address */
476 2); /* opcode read */
477 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
479 /* is operation finished? */
480 for (i = MII_MAX_RETRY; i > 0; i --) {
481 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
482 if ((val16 & 3) == 0)
483 break;
485 /* timed out */
486 if (!i) {
487 ET_ERROR(("mii_rreg: timeout"));
488 return -1;
491 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, val16, len));
493 switch (len) {
494 case 8:
495 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
496 ptr[7] = (val16 >> 8);
497 ptr[6] = (val16 & 0xff);
498 /* FALLTHRU */
500 case 6:
501 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
502 ptr[5] = (val16 >> 8);
503 ptr[4] = (val16 & 0xff);
504 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
505 ptr[3] = (val16 >> 8);
506 ptr[2] = (val16 & 0xff);
507 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
508 ptr[1] = (val16 >> 8);
509 ptr[0] = (val16 & 0xff);
510 break;
512 case 4:
513 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
514 *(uint32 *)val = (((uint32)val16) << 16);
515 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
516 *(uint32 *)val |= val16;
517 break;
519 case 2:
520 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
521 *(uint16 *)val = val16;
522 break;
524 case 1:
525 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
526 *(uint8 *)val = (uint8)(val16 & 0xff);
527 break;
530 return 0;
533 /* MII interface functions */
534 static dev_ops_t mdcmdio = {
535 NULL,
536 NULL,
537 mii_wreg,
538 mii_rreg,
539 "MII (MDC/MDIO)"
542 /* High level switch configuration functions. */
544 /* Get access to the RoboSwitch */
545 robo_info_t *
546 bcm_robo_attach(sb_t *sbh, void *h, char *vars, miird_f miird, miiwr_f miiwr)
548 robo_info_t *robo;
549 uint32 reset, idx;
551 /* Allocate and init private state */
552 if (!(robo = MALLOC(sb_osh(sbh), sizeof(robo_info_t)))) {
553 ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(sb_osh(sbh))));
554 return NULL;
556 bzero(robo, sizeof(robo_info_t));
558 robo->h = h;
559 robo->sbh = sbh;
560 robo->vars = vars;
561 robo->miird = miird;
562 robo->miiwr = miiwr;
563 robo->page = -1;
565 /* Trigger external reset by nvram variable existance */
566 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
567 GPIO_PIN_NOTDEFINED) {
569 * Reset sequence: RESET low(50ms)->high(20ms)
571 * We have to perform a full sequence for we don't know how long
572 * it has been from power on till now.
574 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
575 reset = 1 << reset;
577 /* Keep RESET low for 50 ms */
578 sb_gpioout(robo->sbh, reset, 0, GPIO_DRV_PRIORITY);
579 sb_gpioouten(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
580 bcm_mdelay(50);
582 /* Keep RESET high for at least 20 ms */
583 sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
584 bcm_mdelay(20);
585 } else {
586 /* In case we need it */
587 idx = sb_coreidx(robo->sbh);
589 if (sb_setcore(robo->sbh, SB_ROBO, 0)) {
590 /* If we have an internal robo core, reset it using sb_core_reset */
591 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
592 sb_core_reset(robo->sbh, 0, 0);
595 sb_setcoreidx(robo->sbh, idx);
598 if (miird && miiwr) {
599 uint16 tmp;
600 int rc, retry_count = 0;
602 /* Read the PHY ID */
603 tmp = miird(h, PSEUDO_PHYAD, 2);
604 if (tmp != 0xffff) {
605 do {
606 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
607 &robo->devid, sizeof(uint16));
608 if (rc != 0)
609 break;
610 retry_count++;
611 } while ((robo->devid == 0) && (retry_count < 10));
613 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
614 rc ? "un" : "", robo->devid));
615 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
616 robo->ops = &mdcmdio;
617 if ((rc != 0) || (robo->devid == 0)) {
618 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
619 robo->devid = DEVID5325;
621 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
625 if ((robo->devid == DEVID5395) ||
626 (robo->devid == DEVID5397) ||
627 (robo->devid == DEVID5398)) {
628 uint8 srst_ctrl;
630 /* If it is a 539x switch, use the soft reset register */
631 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
633 /* Reset the 539x switch core and register file */
634 srst_ctrl = 0x83;
635 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
636 srst_ctrl = 0x00;
637 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
640 if (!robo->ops) {
641 int mosi, miso, ss, sck;
643 robo->ops = &spigpio;
644 robo->devid = DEVID5325;
646 /* Init GPIO mapping. Default 2, 3, 4, 5 */
647 ss = getgpiopin(vars, "robo_ss", 2);
648 if (ss == GPIO_PIN_NOTDEFINED) {
649 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
650 goto error;
652 robo->ss = 1 << ss;
653 sck = getgpiopin(vars, "robo_sck", 3);
654 if (sck == GPIO_PIN_NOTDEFINED) {
655 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
656 goto error;
658 robo->sck = 1 << sck;
659 mosi = getgpiopin(vars, "robo_mosi", 4);
660 if (mosi == GPIO_PIN_NOTDEFINED) {
661 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
662 goto error;
664 robo->mosi = 1 << mosi;
665 miso = getgpiopin(vars, "robo_miso", 5);
666 if (miso == GPIO_PIN_NOTDEFINED) {
667 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
668 goto error;
670 robo->miso = 1 << miso;
671 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
672 ss, sck, mosi, miso));
675 /* sanity check */
676 ASSERT(robo->ops);
677 ASSERT(robo->ops->write_reg);
678 ASSERT(robo->ops->read_reg);
679 ASSERT((robo->devid == DEVID5325) ||
680 (robo->devid == DEVID5395) ||
681 (robo->devid == DEVID5397) ||
682 (robo->devid == DEVID5398));
684 return robo;
686 error:
687 bcm_robo_detach(robo);
688 return NULL;
691 /* Release access to the RoboSwitch */
692 void
693 bcm_robo_detach(robo_info_t *robo)
695 MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
698 /* Enable the device and set it to a known good state */
700 bcm_robo_enable_device(robo_info_t *robo)
702 uint8 reg_offset, reg_val;
703 int ret = 0;
705 /* Enable management interface access */
706 if (robo->ops->enable_mgmtif)
707 robo->ops->enable_mgmtif(robo);
709 if (robo->devid == DEVID5398) {
710 /* Disable unused ports: port 6 and 7 */
711 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
712 /* Set bits [1:0] to disable RX and TX */
713 reg_val = 0x03;
714 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
715 sizeof(reg_val));
719 if (robo->devid == DEVID5325) {
720 /* Must put the switch into Reverse MII mode! */
722 /* MII port state override (page 0 register 14) */
723 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
725 /* Bit 4 enables reverse MII mode */
726 if (!(reg_val & (1 << 4))) {
727 /* Enable RvMII */
728 reg_val |= (1 << 4);
729 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
730 sizeof(reg_val));
732 /* Read back */
733 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
734 sizeof(reg_val));
735 if (!(reg_val & (1 << 4))) {
736 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
737 ret = -1;
742 /* Disable management interface access */
743 if (robo->ops->disable_mgmtif)
744 robo->ops->disable_mgmtif(robo);
746 return ret;
749 /* Port flags */
750 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
751 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
752 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
754 /* port descriptor */
755 typedef struct {
756 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
757 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
758 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
759 uint8 cpu; /* is this cpu port? */
760 } pdesc_t;
762 pdesc_t pdesc97[] = {
763 /* 5395/5397/5398 is 0 ~ 7. port 8 is IMP port. */
764 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
765 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
766 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
767 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
768 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
769 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
770 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
771 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
772 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
775 pdesc_t pdesc25[] = {
776 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
777 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
778 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
779 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
780 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
781 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
784 /* Configure the VLANs */
786 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
788 uint8 val8;
789 uint16 val16;
790 uint32 val32;
791 pdesc_t *pdesc;
792 int pdescsz;
793 uint16 vid, vid0, vid_map;
794 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
796 /* Enable management interface access */
797 if (robo->ops->enable_mgmtif)
798 robo->ops->enable_mgmtif(robo);
800 /* setup global vlan configuration */
801 /* VLAN Control 0 Register (Page 0x34, Address 0) */
802 val8 = ((1 << 7) | /* enable 802.1Q VLAN */
803 (3 << 5)); /* individual VLAN learning mode */
804 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
806 /* VLAN Control 1 Register (Page 0x34, Address 1) */
807 val8 = ((1 << 2) | /* enable RSV multicast V Fwdmap */
808 (1 << 3)); /* enable RSV multicast V Untagmap */
809 if (robo->devid == DEVID5325)
810 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
811 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
813 arl_entry[0] = mac_addr[5];
814 arl_entry[1] = mac_addr[4];
815 arl_entry[2] = mac_addr[3];
816 arl_entry[3] = mac_addr[2];
817 arl_entry[4] = mac_addr[1];
818 arl_entry[5] = mac_addr[0];
820 if (robo->devid == DEVID5325) {
821 /* Init the entry 1 of the bin */
822 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
823 arl_entry1, sizeof(arl_entry1));
824 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
825 arl_entry1, 1);
827 /* Init the entry 0 of the bin */
828 arl_entry[6] = 0x8; /* Port Id: MII */
829 arl_entry[7] = 0xc0; /* Static Entry, Valid */
831 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
832 arl_entry, sizeof(arl_entry));
833 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
834 arl_entry, ETHER_ADDR_LEN);
836 /* VLAN Control 4 Register (Page 0x34, Address 4) */
837 val8 = (1 << 6); /* drop frame with VID violation */
838 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
840 /* VLAN Control 5 Register (Page 0x34, Address 5) */
841 val8 = (1 << 3); /* drop frame when miss V table */
842 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
844 pdesc = pdesc25;
845 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
846 } else {
847 /* Initialize the MAC Addr Index Register */
848 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
849 arl_entry, ETHER_ADDR_LEN);
851 pdesc = pdesc97;
852 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
855 vid0 = getintvar(robo->vars, "vlan0tag");
856 #ifdef VID_MAP_DBG
857 printk(KERN_EMERG "bcmrobo: vlan0tag/vid0=%d\n", vid0 );
858 #endif
860 /* setup each vlan. max. 16 vlans. */
861 /* force vlan id to be equal to vlan number */
862 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
863 char vlanports[] = "vlanXXXXports";
864 char vlanvid[] = "vlanXXXXvid";
865 char port[] = "XXXX", *ports, *next, *cur, *nvvid;
867 uint32 untag = 0;
868 uint32 member = 0;
869 int pid, len;
871 /* no members if VLAN id is out of limitation */
872 if (vid > VLAN_MAXVID)
873 goto vlan_setup;
875 /* vlan ID mapping */
876 vid_map = vid0 | vid;
877 sprintf(vlanvid, "vlan%dvid", vid);
878 nvvid = getvar(robo->vars, vlanvid);
880 if (nvvid != NULL) {
881 vid_map = bcm_atoi(nvvid);
882 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vid0 | vid;
885 /* get vlan member ports from nvram */
886 sprintf(vlanports, "vlan%dports", vid);
887 ports = getvar(robo->vars, vlanports);
889 #ifdef VID_MAP_DBG
890 printk(KERN_EMERG "bcmrobo: VLAN %d mapped to VID %d, ports='%s', %s='%s'\n",
891 vid, vid_map, (ports != NULL)? ports: "(unset)",
892 vlanvid, (nvvid != NULL)? nvvid: "(unset)" );
893 #endif
895 /* In 539x vid == 0 us invalid?? */
896 if ((robo->devid != DEVID5325) && (vid == 0)) {
897 if (ports)
898 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
899 continue;
902 /* disable this vlan if not defined */
903 if (!ports)
904 goto vlan_setup;
907 * setup each port in the vlan. cpu port needs special handing
908 * (with or without output tagging) to support linux/pmon/cfe.
910 for (cur = ports; cur; cur = next) {
911 /* tokenize the port list */
912 while (*cur == ' ')
913 cur ++;
914 next = bcmstrstr(cur, " ");
915 len = next ? next - cur : strlen(cur);
916 if (!len)
917 break;
918 if (len > sizeof(port) - 1)
919 len = sizeof(port) - 1;
920 strncpy(port, cur, len);
921 port[len] = 0;
923 /* make sure port # is within the range */
924 pid = bcm_atoi(port);
925 if (pid >= pdescsz) {
926 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
927 "of range[0-%d]\n", pid, vid, pdescsz));
928 continue;
931 /* build VLAN registers values */
932 #ifndef _CFE_
933 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
934 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
935 #endif
936 untag |= pdesc[pid].untag;
938 member |= pdesc[pid].member;
940 /* set port tag - applies to untagged ingress frames */
941 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
942 #ifdef _CFE_
943 #define FL FLAG_LAN
944 #else
945 #define FL FLAG_UNTAG
946 #endif /* _CFE_ */
947 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
948 strchr(port, FL)) {
949 val16 = ((0 << 13) | /* priority - always 0 */
950 vid_map); /* vlan id */
951 #ifdef VID_MAP_DBG
952 printk( KERN_EMERG "bcmrobo(map A) ->%d/%d\n", vid_map, pid);
953 #endif
954 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
955 &val16, sizeof(val16));
959 /* Add static ARL entries */
960 if (robo->devid == DEVID5325) {
961 val8 = vid;
962 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
963 &val8, sizeof(val8));
964 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
965 &val8, sizeof(val8));
967 /* Write the entry */
968 val8 = 0x80;
969 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
970 &val8, sizeof(val8));
971 /* Wait for write to complete */
972 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
973 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
974 100 /* usec */);
975 } else {
976 /* Set the VLAN Id in VLAN ID Index Register */
977 val8 = vid;
978 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
979 &val8, sizeof(val8));
981 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
982 * Register.
984 arl_entry[6] = (vid_map & 0xff);
985 arl_entry[7] = (vid_map >> 8);
986 #ifdef VID_MAP_DBG
987 printk( KERN_EMERG "bcmrobo(map B) ->%d (%d/%d)\n",
988 vid_map, arl_entry[6], arl_entry[7] );
989 #endif
990 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
991 arl_entry, sizeof(arl_entry));
993 /* Set the Static bit , Valid bit and Port ID fields in
994 * ARL Table Data Entry 0 Register
996 val16 = 0xc008;
997 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
998 &val16, sizeof(val16));
1000 /* Clear the ARL_R/W bit and set the START/DONE bit in
1001 * the ARL Read/Write Control Register.
1003 val8 = 0x80;
1004 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1005 &val8, sizeof(val8));
1006 /* Wait for write to complete */
1007 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1008 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1009 100 /* usec */);
1012 vlan_setup:
1013 /* setup VLAN ID and VLAN memberships */
1015 val32 = (untag | /* untag enable */
1016 member); /* vlan members */
1017 if (sb_chip(robo->sbh) == BCM5365_CHIP_ID)
1019 /* VLAN Write Register (Page 0x34, Address 0x0A) */
1020 val32 = ((1 << 14) | /* valid write */
1021 (untag << 1) | /* untag enable */
1022 member); /* vlan members */
1023 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE_5365, &val32,
1024 sizeof(val32));
1025 /* VLAN Table Access Register (Page 0x34, Address 0x08) */
1026 val16 = ((1 << 13) | /* start command */
1027 (1 << 12) | /* write state */
1028 vid_map); /* vlan id */
1029 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS_5365, &val16,
1030 sizeof(val16));
1031 #ifdef VID_MAP_DBG
1032 printk( KERN_EMERG "bcmrobo(map C/DEVID5365) ->%d\n", vid_map );
1033 #endif
1034 } else if (robo->devid == DEVID5325) {
1035 val32 |= ((1 << 20) | /* valid write */
1036 ((vid0 >> 4) << 12)); /* vlan id bit[11:4] */
1037 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1038 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1039 sizeof(val32));
1040 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1041 val16 = ((1 << 13) | /* start command */
1042 (1 << 12) | /* write state */
1043 vid_map); /* vlan id */
1044 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1045 sizeof(val16));
1046 #ifdef VID_MAP_DBG
1047 printk( KERN_EMERG "bcmrobo(map C/DEVID5325) ->%d\n", vid_map );
1048 #endif
1049 } else {
1050 uint8 vtble, vtbli, vtbla;
1052 if (robo->devid == DEVID5395) {
1053 vtble = REG_VTBL_ENTRY_5395;
1054 vtbli = REG_VTBL_INDX_5395;
1055 vtbla = REG_VTBL_ACCESS_5395;
1056 } else {
1057 vtble = REG_VTBL_ENTRY;
1058 vtbli = REG_VTBL_INDX;
1059 vtbla = REG_VTBL_ACCESS;
1062 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1063 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1064 sizeof(val32));
1065 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1066 val16 = vid_map; /* vlan id */
1067 #ifdef VID_MAP_DBG
1068 printk( KERN_EMERG "bcmrobo(map C) ->%d\n", vid_map );
1069 #endif
1070 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1071 sizeof(val16));
1073 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1074 val8 = ((1 << 7) | /* start command */
1075 0); /* write */
1076 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1077 sizeof(val8));
1081 if (robo->devid == DEVID5325) {
1082 /* setup priority mapping - applies to tagged ingress frames */
1083 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1084 val32 = ((0 << 0) | /* 0 -> 0 */
1085 (1 << 3) | /* 1 -> 1 */
1086 (2 << 6) | /* 2 -> 2 */
1087 (3 << 9) | /* 3 -> 3 */
1088 (4 << 12) | /* 4 -> 4 */
1089 (5 << 15) | /* 5 -> 5 */
1090 (6 << 18) | /* 6 -> 6 */
1091 (7 << 21)); /* 7 -> 7 */
1092 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1095 /* Disable management interface access */
1096 if (robo->ops->disable_mgmtif)
1097 robo->ops->disable_mgmtif(robo);
1099 return 0;
1102 /* Enable switching/forwarding */
1104 bcm_robo_enable_switch(robo_info_t *robo)
1106 int i, max_port_ind, ret = 0;
1107 uint8 val8;
1109 /* Enable management interface access */
1110 if (robo->ops->enable_mgmtif)
1111 robo->ops->enable_mgmtif(robo);
1113 /* Switch Mode register (Page 0, Address 0x0B) */
1114 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1116 /* Bit 1 enables switching/forwarding */
1117 if (!(val8 & (1 << 1))) {
1118 /* Set unmanaged mode */
1119 val8 &= (~(1 << 0));
1121 /* Enable forwarding */
1122 val8 |= (1 << 1);
1123 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1125 /* Read back */
1126 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1127 if (!(val8 & (1 << 1))) {
1128 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1129 ret = -1;
1132 /* No spanning tree for unmanaged mode */
1133 val8 = 0;
1134 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
1135 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1136 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1140 /* Enable WAN port (#0) on the asus wl-500g deluxe boxes */
1141 if (sb_chip(robo->sbh) == BCM5365_CHIP_ID) {
1142 val8 = 0;
1143 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0, &val8, sizeof(val8));
1146 /* Disable management interface access */
1147 if (robo->ops->disable_mgmtif)
1148 robo->ops->disable_mgmtif(robo);
1150 return ret;