Support for BCM5365.
[tomato.git] / release / src / shared / bcmrobo.c
blob9ecf77cfe38618ef407aee804809ff5c32ed7323
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)
33 * Switch can be programmed through SPI interface, which
34 * has a rreg and a wreg functions to read from and write to
35 * registers.
38 /* MII access registers */
39 #define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
40 #define REG_MII_PAGE 0x10 /* MII Page register */
41 #define REG_MII_ADDR 0x11 /* MII Address register */
42 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
43 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
44 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
45 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
47 /* Page numbers */
48 #define PAGE_CTRL 0x00 /* Control page */
49 #define PAGE_STATUS 0x01 /* Status page */ /*Foxconn added by EricHuang, 09/27/2006*/
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 /* Foxconn added start by EricHuang, 09/27/2006 */
68 /* Status page registers */
69 #define REG_LINK_SUM 0x00 /* Link Status summary register, 16-bit */
70 #define REG_SPEED_SUM 0x04 /* Port speed summary register, 16-bit */
71 #define REG_DUPLEX_SUM 0x06 /* Duplex status summary register, 16-bit */
72 /* Foxconn added end by EricHuang, 09/27/2006 */
74 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
75 #define DEVID5325 0x25 /* 5325 (Not really be we fake it) */
76 #define DEVID5395 0x95 /* 5395 */
77 #define DEVID5397 0x97 /* 5397 */
78 #define DEVID5398 0x98 /* 5398 */
80 /* VLAN page registers */
81 #define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
82 #define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
83 #define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
84 #define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
85 #define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
86 #define REG_VLAN_ACCESS_5365 0x08 /* 5365 VLAN Table Access register */
87 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
88 #define REG_VLAN_WRITE_5365 0x0A /* 5365 VLAN Write register */
89 #define REG_VLAN_READ 0x0C /* VLAN Read register */
90 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
91 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
92 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
93 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
94 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
95 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
96 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
97 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
98 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
99 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
101 #define VLAN_NUMVLANS 16 /* # of VLANs */
104 /* ARL/VLAN Table Access page registers */
105 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
106 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
107 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
108 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
109 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
110 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
111 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
112 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
113 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
114 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
115 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
116 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
117 #define REG_VTBL_PREG 0xFF /* Page Register */
118 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
119 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
120 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
121 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
122 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
123 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
125 /* SPI registers */
126 #define REG_SPI_PAGE 0xff /* SPI Page register */
128 /* Access switch registers through GPIO/SPI */
130 /* Minimum timing constants */
131 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
132 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
133 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
135 /* misc. constants */
136 #define SPI_MAX_RETRY 100
138 static robo_info_t *robo_ptr = NULL; /* Foxconn added by EricHuang, 09/27/2006 */
139 #ifdef _CFE_
140 int bcm_robo_check_link_status(void);
141 #endif
143 #ifdef _CFE_
144 extern int lan_led_control(int port, int status);
145 #endif
148 /* Enable GPIO access to the chip */
149 static void
150 gpio_enable(robo_info_t *robo)
152 /* Enable GPIO outputs with SCK and MOSI low, SS high */
153 sb_gpioout(robo->sbh, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
154 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi,
155 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
158 /* Disable GPIO access to the chip */
159 static void
160 gpio_disable(robo_info_t *robo)
162 /* Disable GPIO outputs with all their current values */
163 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
166 /* Write a byte stream to the chip thru SPI */
167 static int
168 spi_write(robo_info_t *robo, uint8 *buf, uint len)
170 uint i;
171 uint8 mask;
173 /* Byte bang from LSB to MSB */
174 for (i = 0; i < len; i++) {
175 /* Bit bang from MSB to LSB */
176 for (mask = 0x80; mask; mask >>= 1) {
177 /* Clock low */
178 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
179 OSL_DELAY(SCK_EDGE_TIME);
181 /* Sample on rising edge */
182 if (mask & buf[i])
183 sb_gpioout(robo->sbh, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
184 else
185 sb_gpioout(robo->sbh, robo->mosi, 0, GPIO_DRV_PRIORITY);
186 OSL_DELAY(MOSI_SETUP_TIME);
188 /* Clock high */
189 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
190 OSL_DELAY(SCK_EDGE_TIME);
194 return 0;
197 /* Read a byte stream from the chip thru SPI */
198 static int
199 spi_read(robo_info_t *robo, uint8 *buf, uint len)
201 uint i, timeout;
202 uint8 rack, mask, byte;
204 /* Timeout after 100 tries without RACK */
205 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
206 /* Bit bang from MSB to LSB */
207 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
208 /* Clock low */
209 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
210 OSL_DELAY(SCK_EDGE_TIME);
212 /* Sample on falling edge */
213 if (sb_gpioin(robo->sbh) & robo->miso)
214 byte |= mask;
216 /* Clock high */
217 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
218 OSL_DELAY(SCK_EDGE_TIME);
220 /* RACK when bit 0 is high */
221 if (!rack) {
222 rack = (byte & 1);
223 timeout--;
224 continue;
226 /* Byte bang from LSB to MSB */
227 buf[i] = byte;
228 i++;
231 if (timeout == 0) {
232 ET_ERROR(("spi_read: timeout"));
233 return -1;
236 return 0;
239 /* Enable/disable SPI access */
240 static void
241 spi_select(robo_info_t *robo, uint8 spi)
243 if (spi) {
244 /* Enable SPI access */
245 sb_gpioout(robo->sbh, robo->ss, 0, GPIO_DRV_PRIORITY);
246 } else {
247 /* Disable SPI access */
248 sb_gpioout(robo->sbh, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
250 OSL_DELAY(SS_SETUP_TIME);
254 /* Select chip and page */
255 static void
256 spi_goto(robo_info_t *robo, uint8 page)
258 uint8 reg8 = REG_SPI_PAGE; /* page select register */
259 uint8 cmd8;
261 /* Issue the command only when we are on a different page */
262 if (robo->page == page)
263 return;
265 robo->page = page;
267 /* Enable SPI access */
268 spi_select(robo, 1);
270 /* Select new page with CID 0 */
271 cmd8 = ((6 << 4) | /* normal SPI */
272 1); /* write */
273 spi_write(robo, &cmd8, 1);
274 spi_write(robo, &reg8, 1);
275 spi_write(robo, &page, 1);
277 /* Disable SPI access */
278 spi_select(robo, 0);
281 /* Write register thru SPI */
282 static int
283 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
285 int status = 0;
286 uint8 cmd8;
287 union {
288 uint8 val8;
289 uint16 val16;
290 uint32 val32;
291 } bytes;
293 /* validate value length and buffer address */
294 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
295 (len == 4 && !((int)val & 3)));
297 /* Select chip and page */
298 spi_goto(robo, page);
300 /* Enable SPI access */
301 spi_select(robo, 1);
303 /* Write with CID 0 */
304 cmd8 = ((6 << 4) | /* normal SPI */
305 1); /* write */
306 spi_write(robo, &cmd8, 1);
307 spi_write(robo, &addr, 1);
308 switch (len) {
309 case 1:
310 bytes.val8 = *(uint8 *)val;
311 break;
312 case 2:
313 bytes.val16 = htol16(*(uint16 *)val);
314 break;
315 case 4:
316 bytes.val32 = htol32(*(uint32 *)val);
317 break;
319 spi_write(robo, (uint8 *)val, len);
321 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
322 *(uint16 *)val, len));
323 /* Disable SPI access */
324 spi_select(robo, 0);
325 return status;
328 /* Read register thru SPI in fast SPI mode */
329 static int
330 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
332 int status = 0;
333 uint8 cmd8;
334 union {
335 uint8 val8;
336 uint16 val16;
337 uint32 val32;
338 } bytes;
340 /* validate value length and buffer address */
341 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
342 (len == 4 && !((int)val & 3)));
344 /* Select chip and page */
345 spi_goto(robo, page);
347 /* Enable SPI access */
348 spi_select(robo, 1);
350 /* Fast SPI read with CID 0 and byte offset 0 */
351 cmd8 = (1 << 4); /* fast SPI */
352 spi_write(robo, &cmd8, 1);
353 spi_write(robo, &addr, 1);
354 status = spi_read(robo, (uint8 *)&bytes, len);
355 switch (len) {
356 case 1:
357 *(uint8 *)val = bytes.val8;
358 break;
359 case 2:
360 *(uint16 *)val = ltoh16(bytes.val16);
361 break;
362 case 4:
363 *(uint32 *)val = ltoh32(bytes.val32);
364 break;
367 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
368 *(uint16 *)val, len));
370 /* Disable SPI access */
371 spi_select(robo, 0);
372 return status;
375 /* SPI/gpio interface functions */
376 static dev_ops_t spigpio = {
377 gpio_enable,
378 gpio_disable,
379 spi_wreg,
380 spi_rreg,
381 "SPI (GPIO)"
385 /* Access switch registers through MII (MDC/MDIO) */
387 #define MII_MAX_RETRY 100
389 /* Write register thru MDC/MDIO */
390 static int
391 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
393 uint16 cmd16, val16;
394 void *h = robo->h;
395 int i;
396 uint8 *ptr = (uint8 *)val;
398 /* validate value length and buffer address */
399 ASSERT(len == 1 || len == 6 || len == 8 ||
400 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
402 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
403 *(uint16 *)val, len));
405 /* set page number - MII register 0x10 */
406 if (robo->page != page) {
407 cmd16 = ((page << 8) | /* page number */
408 1); /* mdc/mdio access enable */
409 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
410 robo->page = page;
413 switch (len) {
414 case 8:
415 val16 = ptr[7];
416 val16 = ((val16 << 8) | ptr[6]);
417 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
418 /* FALLTHRU */
420 case 6:
421 val16 = ptr[5];
422 val16 = ((val16 << 8) | ptr[4]);
423 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
424 val16 = ptr[3];
425 val16 = ((val16 << 8) | ptr[2]);
426 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
427 val16 = ptr[1];
428 val16 = ((val16 << 8) | ptr[0]);
429 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
430 break;
432 case 4:
433 val16 = (uint16)((*(uint32 *)val) >> 16);
434 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
435 val16 = (uint16)(*(uint32 *)val);
436 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
437 break;
439 case 2:
440 val16 = *(uint16 *)val;
441 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
442 break;
444 case 1:
445 val16 = *(uint8 *)val;
446 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
447 break;
450 /* set register address - MII register 0x11 */
451 cmd16 = ((reg << 8) | /* register address */
452 1); /* opcode write */
453 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
455 /* is operation finished? */
456 for (i = MII_MAX_RETRY; i > 0; i --) {
457 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
458 if ((val16 & 3) == 0)
459 break;
462 /* timed out */
463 if (!i) {
464 ET_ERROR(("mii_wreg: timeout"));
465 return -1;
467 return 0;
470 /* Read register thru MDC/MDIO */
471 static int
472 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
474 uint16 cmd16, val16;
475 void *h = robo->h;
476 int i;
477 uint8 *ptr = (uint8 *)val;
479 /* validate value length and buffer address */
480 ASSERT(len == 1 || len == 6 || len == 8 ||
481 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
483 /* set page number - MII register 0x10 */
484 if (robo->page != page) {
485 cmd16 = ((page << 8) | /* page number */
486 1); /* mdc/mdio access enable */
487 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
488 robo->page = page;
491 /* set register address - MII register 0x11 */
492 cmd16 = ((reg << 8) | /* register address */
493 2); /* opcode read */
494 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
496 /* is operation finished? */
497 for (i = MII_MAX_RETRY; i > 0; i --) {
498 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
499 if ((val16 & 3) == 0)
500 break;
502 /* timed out */
503 if (!i) {
504 ET_ERROR(("mii_rreg: timeout"));
505 return -1;
508 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, val16, len));
510 switch (len) {
511 case 8:
512 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
513 ptr[7] = (val16 >> 8);
514 ptr[6] = (val16 & 0xff);
515 /* FALLTHRU */
517 case 6:
518 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
519 ptr[5] = (val16 >> 8);
520 ptr[4] = (val16 & 0xff);
521 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
522 ptr[3] = (val16 >> 8);
523 ptr[2] = (val16 & 0xff);
524 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
525 ptr[1] = (val16 >> 8);
526 ptr[0] = (val16 & 0xff);
527 break;
529 case 4:
530 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
531 *(uint32 *)val = (((uint32)val16) << 16);
532 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
533 *(uint32 *)val |= val16;
534 break;
536 case 2:
537 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
538 *(uint16 *)val = val16;
539 break;
541 case 1:
542 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
543 *(uint8 *)val = (uint8)(val16 & 0xff);
544 break;
547 return 0;
550 /* MII interface functions */
551 static dev_ops_t mdcmdio = {
552 NULL,
553 NULL,
554 mii_wreg,
555 mii_rreg,
556 "MII (MDC/MDIO)"
559 /* High level switch configuration functions. */
561 /* Get access to the RoboSwitch */
562 robo_info_t *
563 bcm_robo_attach(sb_t *sbh, void *h, char *vars, miird_f miird, miiwr_f miiwr)
565 robo_info_t *robo;
566 uint32 reset, idx;
568 /* Allocate and init private state */
569 if (!(robo = MALLOC(sb_osh(sbh), sizeof(robo_info_t)))) {
570 ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(sb_osh(sbh))));
571 return NULL;
573 bzero(robo, sizeof(robo_info_t));
575 robo->h = h;
576 robo->sbh = sbh;
577 robo->vars = vars;
578 robo->miird = miird;
579 robo->miiwr = miiwr;
580 robo->page = -1;
582 /* Trigger external reset by nvram variable existance */
583 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
584 GPIO_PIN_NOTDEFINED) {
586 * Reset sequence: RESET low(50ms)->high(20ms)
588 * We have to perform a full sequence for we don't know how long
589 * it has been from power on till now.
591 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
592 reset = 1 << reset;
594 /* Keep RESET low for 50 ms */
595 sb_gpioout(robo->sbh, reset, 0, GPIO_DRV_PRIORITY);
596 sb_gpioouten(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
597 bcm_mdelay(50);
599 /* Keep RESET high for at least 20 ms */
600 sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
601 bcm_mdelay(20);
602 } else {
603 /* In case we need it */
604 idx = sb_coreidx(robo->sbh);
606 if (sb_setcore(robo->sbh, SB_ROBO, 0)) {
607 /* If we have an internal robo core, reset it using sb_core_reset */
608 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
609 sb_core_reset(robo->sbh, 0, 0);
612 sb_setcoreidx(robo->sbh, idx);
615 if (miird && miiwr) {
616 uint16 tmp;
617 int rc, retry_count = 0;
619 /* Read the PHY ID */
620 tmp = miird(h, PSEUDO_PHYAD, 2);
621 if (tmp != 0xffff) {
622 do {
623 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
624 &robo->devid, sizeof(uint16));
625 if (rc != 0)
626 break;
627 retry_count++;
628 } while ((robo->devid == 0) && (retry_count < 10));
630 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
631 rc ? "un" : "", robo->devid));
632 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
633 robo->ops = &mdcmdio;
634 if ((rc != 0) || (robo->devid == 0)) {
635 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
636 robo->devid = DEVID5325;
638 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
642 if ((robo->devid == DEVID5395) ||
643 (robo->devid == DEVID5397) ||
644 (robo->devid == DEVID5398)) {
645 uint8 srst_ctrl;
647 /* If it is a 539x switch, use the soft reset register */
648 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
650 /* Reset the 539x switch core and register file */
651 srst_ctrl = 0x83;
652 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
653 srst_ctrl = 0x00;
654 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
657 if (!robo->ops) {
658 int mosi, miso, ss, sck;
660 robo->ops = &spigpio;
661 robo->devid = DEVID5325;
663 /* Init GPIO mapping. Default 2, 3, 4, 5 */
664 ss = getgpiopin(vars, "robo_ss", 2);
665 if (ss == GPIO_PIN_NOTDEFINED) {
666 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
667 goto error;
669 robo->ss = 1 << ss;
670 sck = getgpiopin(vars, "robo_sck", 3);
671 if (sck == GPIO_PIN_NOTDEFINED) {
672 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
673 goto error;
675 robo->sck = 1 << sck;
676 mosi = getgpiopin(vars, "robo_mosi", 4);
677 if (mosi == GPIO_PIN_NOTDEFINED) {
678 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
679 goto error;
681 robo->mosi = 1 << mosi;
682 miso = getgpiopin(vars, "robo_miso", 5);
683 if (miso == GPIO_PIN_NOTDEFINED) {
684 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
685 goto error;
687 robo->miso = 1 << miso;
688 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
689 ss, sck, mosi, miso));
692 /* sanity check */
693 ASSERT(robo->ops);
694 ASSERT(robo->ops->write_reg);
695 ASSERT(robo->ops->read_reg);
696 ASSERT((robo->devid == DEVID5325) ||
697 (robo->devid == DEVID5395) ||
698 (robo->devid == DEVID5397) ||
699 (robo->devid == DEVID5398));
701 /* Foxconn added start by EricHuang, 09/27/2006 */
702 /* Store pointer to robo */
703 //#ifndef _CFE_
704 robo_ptr = robo;
705 //#endif
706 /* Foxconn added end by EricHuang, 09/27/2006 */
708 return robo;
710 error:
711 bcm_robo_detach(robo);
712 return NULL;
715 /* Release access to the RoboSwitch */
716 void
717 bcm_robo_detach(robo_info_t *robo)
719 MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
722 /* Enable the device and set it to a known good state */
724 bcm_robo_enable_device(robo_info_t *robo)
726 uint8 reg_offset, reg_val;
727 int ret = 0;
729 /* Enable management interface access */
730 if (robo->ops->enable_mgmtif)
731 robo->ops->enable_mgmtif(robo);
733 if (robo->devid == DEVID5398) {
734 /* Disable unused ports: port 6 and 7 */
735 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
736 /* Set bits [1:0] to disable RX and TX */
737 reg_val = 0x03;
738 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
739 sizeof(reg_val));
743 if (robo->devid == DEVID5325) {
744 /* Must put the switch into Reverse MII mode! */
746 /* MII port state override (page 0 register 14) */
747 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
749 /* Bit 4 enables reverse MII mode */
750 if (!(reg_val & (1 << 4))) {
751 /* Enable RvMII */
752 reg_val |= (1 << 4);
753 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
754 sizeof(reg_val));
756 /* Read back */
757 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
758 sizeof(reg_val));
759 if (!(reg_val & (1 << 4))) {
760 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
761 ret = -1;
766 /* Disable management interface access */
767 if (robo->ops->disable_mgmtif)
768 robo->ops->disable_mgmtif(robo);
770 return ret;
773 /* Port flags */
774 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
775 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
776 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
778 /* port descriptor */
779 typedef struct {
780 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
781 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
782 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
783 uint8 cpu; /* is this cpu port? */
784 } pdesc_t;
786 pdesc_t pdesc97[] = {
787 /* 5395/5397/5398 is 0 ~ 7. port 8 is IMP port. */
788 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
789 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
790 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
791 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
792 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
793 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
794 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
795 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
796 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
799 pdesc_t pdesc25[] = {
800 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
801 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
802 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
803 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
804 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
805 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
808 /* Configure the VLANs */
810 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
812 uint8 val8;
813 uint16 val16;
814 uint32 val32;
815 pdesc_t *pdesc;
816 int pdescsz;
817 uint16 vid;
818 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
820 /* Enable management interface access */
821 if (robo->ops->enable_mgmtif)
822 robo->ops->enable_mgmtif(robo);
824 /* setup global vlan configuration */
825 /* VLAN Control 0 Register (Page 0x34, Address 0) */
826 val8 = ((1 << 7) | /* enable 802.1Q VLAN */
827 (3 << 5)); /* individual VLAN learning mode */
828 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
830 /* VLAN Control 1 Register (Page 0x34, Address 1) */
831 val8 = ((1 << 2) | /* enable RSV multicast V Fwdmap */
832 (1 << 3)); /* enable RSV multicast V Untagmap */
833 if (robo->devid == DEVID5325)
834 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
835 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
837 arl_entry[0] = mac_addr[5];
838 arl_entry[1] = mac_addr[4];
839 arl_entry[2] = mac_addr[3];
840 arl_entry[3] = mac_addr[2];
841 arl_entry[4] = mac_addr[1];
842 arl_entry[5] = mac_addr[0];
844 if (robo->devid == DEVID5325) {
845 /* Init the entry 1 of the bin */
846 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
847 arl_entry1, sizeof(arl_entry1));
848 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
849 arl_entry1, 1);
851 /* Init the entry 0 of the bin */
852 arl_entry[6] = 0x8; /* Port Id: MII */
853 arl_entry[7] = 0xc0; /* Static Entry, Valid */
855 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
856 arl_entry, sizeof(arl_entry));
857 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
858 arl_entry, ETHER_ADDR_LEN);
860 /* VLAN Control 4 Register (Page 0x34, Address 4) */
861 val8 = (1 << 6); /* drop frame with VID violation */
862 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
864 /* VLAN Control 5 Register (Page 0x34, Address 5) */
865 val8 = (1 << 3); /* drop frame when miss V table */
866 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
868 pdesc = pdesc25;
869 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
870 } else {
871 /* Initialize the MAC Addr Index Register */
872 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
873 arl_entry, ETHER_ADDR_LEN);
875 pdesc = pdesc97;
876 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
879 /* setup each vlan. max. 16 vlans. */
880 /* force vlan id to be equal to vlan number */
881 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
882 char vlanports[] = "vlanXXXXports";
883 char port[] = "XXXX", *ports, *next, *cur;
884 uint32 untag = 0;
885 uint32 member = 0;
886 int pid, len;
888 /* no members if VLAN id is out of limitation */
889 if (vid > VLAN_MAXVID)
890 goto vlan_setup;
892 /* get vlan member ports from nvram */
893 sprintf(vlanports, "vlan%dports", vid);
894 ports = getvar(robo->vars, vlanports);
896 /* In 539x vid == 0 us invalid?? */
897 if ((robo->devid != DEVID5325) && (vid == 0)) {
898 if (ports)
899 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
900 continue;
903 /* disable this vlan if not defined */
904 if (!ports)
905 goto vlan_setup;
908 * setup each port in the vlan. cpu port needs special handing
909 * (with or without output tagging) to support linux/pmon/cfe.
911 for (cur = ports; cur; cur = next) {
912 /* tokenize the port list */
913 while (*cur == ' ')
914 cur ++;
915 next = bcmstrstr(cur, " ");
916 len = next ? next - cur : strlen(cur);
917 if (!len)
918 break;
919 if (len > sizeof(port) - 1)
920 len = sizeof(port) - 1;
921 strncpy(port, cur, len);
922 port[len] = 0;
924 /* make sure port # is within the range */
925 pid = bcm_atoi(port);
926 if (pid >= pdescsz) {
927 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
928 "of range[0-%d]\n", pid, vid, pdescsz));
929 continue;
932 /* build VLAN registers values */
933 #ifndef _CFE_
934 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
935 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
936 #endif
937 untag |= pdesc[pid].untag;
939 member |= pdesc[pid].member;
941 /* set port tag - applies to untagged ingress frames */
942 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
943 #ifdef _CFE_
944 #define FL FLAG_LAN
945 #else
946 #define FL FLAG_UNTAG
947 #endif /* _CFE_ */
948 if (!pdesc[pid].cpu || strchr(port, FL)) {
949 val16 = ((0 << 13) | /* priority - always 0 */
950 vid); /* vlan id */
951 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
952 &val16, sizeof(val16));
956 /* Add static ARL entries */
957 if (robo->devid == DEVID5325) {
958 val8 = vid;
959 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
960 &val8, sizeof(val8));
961 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
962 &val8, sizeof(val8));
964 /* Write the entry */
965 val8 = 0x80;
966 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
967 &val8, sizeof(val8));
968 /* Wait for write to complete */
969 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
970 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
971 100 /* usec */);
972 } else {
973 /* Set the VLAN Id in VLAN ID Index Register */
974 val8 = vid;
975 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
976 &val8, sizeof(val8));
978 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
979 * Register.
981 arl_entry[6] = vid;
982 arl_entry[7] = 0x0;
983 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
984 arl_entry, sizeof(arl_entry));
986 /* Set the Static bit , Valid bit and Port ID fields in
987 * ARL Table Data Entry 0 Register
989 val16 = 0xc008;
990 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
991 &val16, sizeof(val16));
993 /* Clear the ARL_R/W bit and set the START/DONE bit in
994 * the ARL Read/Write Control Register.
996 val8 = 0x80;
997 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
998 &val8, sizeof(val8));
999 /* Wait for write to complete */
1000 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1001 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1002 100 /* usec */);
1005 vlan_setup:
1006 /* setup VLAN ID and VLAN memberships */
1008 val32 = (untag | /* untag enable */
1009 member); /* vlan members */
1010 if (sb_chip(robo->sbh) == BCM5365_CHIP_ID)
1012 /* VLAN Write Register (Page 0x34, Address 0x0A) */
1013 val32 = ((1 << 14) | /* valid write */
1014 (untag << 1) | /* untag enable */
1015 member); /* vlan members */
1016 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE_5365, &val32,
1017 sizeof(val32));
1018 /* VLAN Table Access Register (Page 0x34, Address 0x08) */
1019 val16 = ((1 << 13) | /* start command */
1020 (1 << 12) | /* write state */
1021 vid); /* vlan id */
1022 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS_5365, &val16,
1023 sizeof(val16));
1024 } else if (robo->devid == DEVID5325) {
1025 val32 |= ((1 << 20) | /* valid write */
1026 ((vid >> 4) << 12)); /* vlan id bit[11:4] */
1027 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1028 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1029 sizeof(val32));
1030 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1031 val16 = ((1 << 13) | /* start command */
1032 (1 << 12) | /* write state */
1033 vid); /* vlan id */
1034 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1035 sizeof(val16));
1036 } else {
1037 uint8 vtble, vtbli, vtbla;
1039 if (robo->devid == DEVID5395) {
1040 vtble = REG_VTBL_ENTRY_5395;
1041 vtbli = REG_VTBL_INDX_5395;
1042 vtbla = REG_VTBL_ACCESS_5395;
1043 } else {
1044 vtble = REG_VTBL_ENTRY;
1045 vtbli = REG_VTBL_INDX;
1046 vtbla = REG_VTBL_ACCESS;
1049 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1050 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1051 sizeof(val32));
1052 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1053 val16 = vid; /* vlan id */
1054 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1055 sizeof(val16));
1057 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1058 val8 = ((1 << 7) | /* start command */
1059 0); /* write */
1060 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1061 sizeof(val8));
1065 if (robo->devid == DEVID5325) {
1066 /* setup priority mapping - applies to tagged ingress frames */
1067 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1068 val32 = ((0 << 0) | /* 0 -> 0 */
1069 (1 << 3) | /* 1 -> 1 */
1070 (2 << 6) | /* 2 -> 2 */
1071 (3 << 9) | /* 3 -> 3 */
1072 (4 << 12) | /* 4 -> 4 */
1073 (5 << 15) | /* 5 -> 5 */
1074 (6 << 18) | /* 6 -> 6 */
1075 (7 << 21)); /* 7 -> 7 */
1076 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1079 /* Disable management interface access */
1080 if (robo->ops->disable_mgmtif)
1081 robo->ops->disable_mgmtif(robo);
1083 return 0;
1086 /* Enable switching/forwarding */
1088 bcm_robo_enable_switch(robo_info_t *robo)
1090 int i, max_port_ind, ret = 0;
1091 uint8 val8;
1093 /* Enable management interface access */
1094 if (robo->ops->enable_mgmtif)
1095 robo->ops->enable_mgmtif(robo);
1097 /* Switch Mode register (Page 0, Address 0x0B) */
1098 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1100 /* Bit 1 enables switching/forwarding */
1101 if (!(val8 & (1 << 1))) {
1102 /* Set unmanaged mode */
1103 val8 &= (~(1 << 0));
1105 /* Enable forwarding */
1106 val8 |= (1 << 1);
1107 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1109 /* Read back */
1110 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1111 if (!(val8 & (1 << 1))) {
1112 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1113 ret = -1;
1116 /* No spanning tree for unmanaged mode */
1117 val8 = 0;
1118 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
1119 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1120 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1124 /* Enable WAN port (#0) on the asus wl-500g deluxe boxes */
1125 val8 = 0;
1126 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0, &val8, sizeof(val8));
1128 /* Disable management interface access */
1129 if (robo->ops->disable_mgmtif)
1130 robo->ops->disable_mgmtif(robo);
1132 return ret;
1135 /* Foxconn added start by EricHuang, 09/27/2006 */
1136 #ifndef _CFE_
1137 /* WAN/LAN link status monitor */
1138 static void bcm_robo_port_monitor(int gpio, int on_off)
1140 robo_info_t *robo = robo_ptr;
1141 if (robo == NULL)
1142 return;
1144 sb_gpioouten(robo->sbh, (unsigned long) 1 << gpio, (unsigned long) 1 << gpio, GPIO_APP_PRIORITY);
1145 sb_gpioout(robo->sbh, (unsigned long)1 << gpio,(unsigned long) on_off << gpio, GPIO_APP_PRIORITY);
1147 #endif
1149 #ifdef _CFE_
1150 int bcm_robo_check_link_status(void)
1152 robo_info_t *robo = robo_ptr;
1153 uint16 reg_link;
1154 uint32 reg_speed;
1155 int port_speed, port_link;
1156 int i;
1158 if (robo == NULL)
1160 return 0;
1163 /* Read link status summary register */
1164 robo->ops->read_reg(robo, PAGE_STATUS, REG_LINK_SUM, &reg_link, sizeof(reg_link));
1166 /* Read port speed summary register */
1167 robo->ops->read_reg(robo, PAGE_STATUS, REG_SPEED_SUM, &reg_speed, sizeof(reg_speed));
1169 //printf("status:0x%x, speed:0x%x\n", reg_link, reg_speed);
1171 for (i=0; i<5; i++)
1173 port_link = (reg_link >> i) & 0x1;
1174 if (port_link)
1176 port_speed = (reg_speed >> i ) & 0x1;
1177 //printf("PORT %d is up, speed is %d\n", i, port_speed);
1178 /* WAN port: 0 LAN port: 1-4 */
1179 if (i==0)
1181 /* it don't need to check WAN led in bootcode, always amber in color.*/
1182 //lan_led_control(4, !port_speed);
1184 else
1186 lan_led_control(i-1, !port_speed);
1190 return 0;
1192 #endif /* _CFE_ */
1194 #ifndef _CFE_
1195 /* Add Linux API to read link status */
1196 int robo_read_link_status(int lan_wan, int *link, int *speed, int *duplex)
1198 #define ROBO_WAN_PORT 0
1199 #define ROBO_INVALID_PORT_SPEED 0x3
1201 robo_info_t *robo = robo_ptr;
1202 uint16 reg_link, reg_duplex;
1203 uint32 reg_speed;
1204 int port_speed, port_link;
1205 int i;
1207 if (robo == NULL)
1208 return 0;
1211 /* Read link status summary register */
1212 robo->ops->read_reg(robo, PAGE_STATUS, REG_LINK_SUM, &reg_link, sizeof(reg_link));
1214 /* Read port speed summary register */
1215 robo->ops->read_reg(robo, PAGE_STATUS, REG_SPEED_SUM, &reg_speed, sizeof(reg_speed));
1217 /* Read duplex status summary register */
1218 robo->ops->read_reg(robo, PAGE_STATUS, REG_DUPLEX_SUM, &reg_duplex, sizeof(reg_duplex));
1220 if (lan_wan == 0) /*lan status*/
1222 *speed = 0;
1223 *link = (reg_link & 0x1E);
1225 /* Check speed of link "up" ports only */
1226 for (i=1; i<5; i++) {
1227 port_link = (reg_link >> i) & 0x1;
1228 port_speed = (reg_speed >> i) & 0x1;
1229 if (port_link && port_speed > *speed)
1230 *speed = port_speed;
1233 *duplex = reg_duplex & *link;
1235 else /*wan status*/
1237 *link = (reg_link >> ROBO_WAN_PORT) & 0x1;
1238 *speed = (reg_speed >> ROBO_WAN_PORT) & 0x01;
1239 *duplex = (reg_duplex >> ROBO_WAN_PORT) & 0x01;
1242 return 0;
1245 /* disable/enable switch ports */
1246 void robo_enable_port(int port, int on_off)
1248 uint16 val;
1249 robo_info_t *robo = robo_ptr;
1251 if (robo == NULL) return;
1253 val = robo->miird(robo->h, port, 0x1e);
1255 if (on_off == 1)
1257 val &= ~(1 << 3); /* super isolate bit */
1259 else if (on_off == 0) /*disable*/
1261 val |= (1 << 3); /* super isolate bit */
1264 robo->miiwr(robo->h, port, 0x1e, val);
1267 int robo_read_lan_speed(int *speed)
1269 robo_info_t *robo = robo_ptr;
1270 uint32 reg_speed = 0, reg_link = 0;
1272 if (robo == NULL)
1273 return 0;
1275 /* Read port speed summary register */
1276 robo->ops->read_reg(robo, PAGE_STATUS, REG_SPEED_SUM, &reg_speed, sizeof(reg_speed));
1278 /* Read link status summary register */
1279 robo->ops->read_reg(robo, PAGE_STATUS, REG_LINK_SUM, &reg_link, sizeof(reg_link));
1281 *speed = ( reg_speed | ~reg_link); /* if link down, speed returns 1 (100M) */
1282 return 0;
1284 #endif /* ! _CFE_ */