allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / shared / bcmrobo.c
blob8035c902a20f2a19912fe2e89379537ac4792ea5
1 /*
2 * Broadcom 53xx RoboSwitch device driver.
4 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: bcmrobo.c 336121 2012-05-31 23:04:23Z $
22 #include <bcm_cfg.h>
23 #include <typedefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <hndsoc.h>
28 #include <bcmutils.h>
29 #include <bcmendian.h>
30 #include <bcmparams.h>
31 #include <bcmnvram.h>
32 #include <bcmdevs.h>
33 #include <bcmrobo.h>
34 #include <proto/ethernet.h>
35 #include <hndpmu.h>
37 #ifdef BCMDBG
38 #define ET_ERROR(args) printf args
39 #else /* BCMDBG */
40 #define ET_ERROR(args)
41 #endif /* BCMDBG */
42 #define ET_MSG(args)
44 #define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \
45 ((len) == 2) ? *((uint16 *)(var)) : \
46 *((uint32 *)(var)))
49 * Switch can be programmed through SPI interface, which
50 * has a rreg and a wreg functions to read from and write to
51 * registers.
54 /* MII access registers */
55 #define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
56 #define REG_MII_CTRL 0x00 /* 53115 MII control register */
57 #define REG_MII_CLAUSE_45_CTL1 0xd /* 53125 MII Clause 45 control 1 */
58 #define REG_MII_CLAUSE_45_CTL2 0xe /* 53125 MII Clause 45 control 2 */
59 #define REG_MII_PAGE 0x10 /* MII Page register */
60 #define REG_MII_ADDR 0x11 /* MII Address register */
61 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
62 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
63 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
64 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
65 #define REG_MII_AUX_STATUS2 0x1b /* Auxiliary status 2 register */
66 #define REG_MII_AUTO_PWRDOWN 0x1c /* 53115 Auto power down register */
67 #define REG_MII_BRCM_TEST 0x1f /* Broadcom test register */
69 /* Page numbers */
70 #define PAGE_CTRL 0x00 /* Control page */
71 #define PAGE_STATUS 0x01 /* Status page */
72 #define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
73 #define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
74 #define PAGE_VLAN 0x34 /* VLAN page */
76 /* Control page registers */
77 #define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
78 #define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
79 #define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
80 #define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
81 #define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
82 #define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
83 #define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
84 #define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
85 #define REG_CTRL_IMP 0x08 /* IMP port traffic control register */
86 #define REG_CTRL_MODE 0x0B /* Switch Mode register */
87 #define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
88 #define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */
89 #define REG_CTRL_SRST 0x79 /* Software reset control register */
91 /* Status Page Registers */
92 #define REG_STATUS_LINK 0x00 /* Link Status Summary */
93 #define REG_STATUS_REV 0x50 /* Revision Register */
95 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
97 /* VLAN page registers */
98 #define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
99 #define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
100 #define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
101 #define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
102 #define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
103 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
104 #define REG_VLAN_READ 0x0C /* VLAN Read register */
105 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
106 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
107 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
108 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
109 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
110 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
111 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
112 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
113 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
114 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
116 #define VLAN_NUMVLANS 16 /* # of VLANs */
119 /* ARL/VLAN Table Access page registers */
120 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
121 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
122 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
123 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
124 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
125 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
126 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
127 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
128 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
129 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
130 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
131 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
132 #define REG_VTBL_PREG 0xFF /* Page Register */
133 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
134 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
135 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
136 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
137 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
138 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
140 #ifndef _CFE_
141 /* SPI registers */
142 #define REG_SPI_PAGE 0xff /* SPI Page register */
144 /* Access switch registers through GPIO/SPI */
146 /* Minimum timing constants */
147 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
148 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
149 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
151 /* misc. constants */
152 #define SPI_MAX_RETRY 100
154 /* Enable GPIO access to the chip */
155 static void
156 gpio_enable(robo_info_t *robo)
158 /* Enable GPIO outputs with SCK and MOSI low, SS high */
159 si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
160 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi,
161 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
164 /* Disable GPIO access to the chip */
165 static void
166 gpio_disable(robo_info_t *robo)
168 /* Disable GPIO outputs with all their current values */
169 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
172 /* Write a byte stream to the chip thru SPI */
173 static int
174 spi_write(robo_info_t *robo, uint8 *buf, uint len)
176 uint i;
177 uint8 mask;
179 /* Byte bang from LSB to MSB */
180 for (i = 0; i < len; i++) {
181 /* Bit bang from MSB to LSB */
182 for (mask = 0x80; mask; mask >>= 1) {
183 /* Clock low */
184 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
185 OSL_DELAY(SCK_EDGE_TIME);
187 /* Sample on rising edge */
188 if (mask & buf[i])
189 si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
190 else
191 si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY);
192 OSL_DELAY(MOSI_SETUP_TIME);
194 /* Clock high */
195 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
196 OSL_DELAY(SCK_EDGE_TIME);
200 return 0;
203 /* Read a byte stream from the chip thru SPI */
204 static int
205 spi_read(robo_info_t *robo, uint8 *buf, uint len)
207 uint i, timeout;
208 uint8 rack, mask, byte;
210 /* Timeout after 100 tries without RACK */
211 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
212 /* Bit bang from MSB to LSB */
213 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
214 /* Clock low */
215 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
216 OSL_DELAY(SCK_EDGE_TIME);
218 /* Sample on falling edge */
219 if (si_gpioin(robo->sih) & robo->miso)
220 byte |= mask;
222 /* Clock high */
223 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
224 OSL_DELAY(SCK_EDGE_TIME);
226 /* RACK when bit 0 is high */
227 if (!rack) {
228 rack = (byte & 1);
229 timeout--;
230 continue;
232 /* Byte bang from LSB to MSB */
233 buf[i] = byte;
234 i++;
237 if (timeout == 0) {
238 ET_ERROR(("spi_read: timeout"));
239 return -1;
242 return 0;
245 /* Enable/disable SPI access */
246 static void
247 spi_select(robo_info_t *robo, uint8 spi)
249 if (spi) {
250 /* Enable SPI access */
251 si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY);
252 } else {
253 /* Disable SPI access */
254 si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
256 OSL_DELAY(SS_SETUP_TIME);
260 /* Select chip and page */
261 static void
262 spi_goto(robo_info_t *robo, uint8 page)
264 uint8 reg8 = REG_SPI_PAGE; /* page select register */
265 uint8 cmd8;
267 /* Issue the command only when we are on a different page */
268 if (robo->page == page)
269 return;
271 robo->page = page;
273 /* Enable SPI access */
274 spi_select(robo, 1);
276 /* Select new page with CID 0 */
277 cmd8 = ((6 << 4) | /* normal SPI */
278 1); /* write */
279 spi_write(robo, &cmd8, 1);
280 spi_write(robo, &reg8, 1);
281 spi_write(robo, &page, 1);
283 /* Disable SPI access */
284 spi_select(robo, 0);
287 /* Write register thru SPI */
288 static int
289 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
291 int status = 0;
292 uint8 cmd8;
293 union {
294 uint8 val8;
295 uint16 val16;
296 uint32 val32;
297 } bytes;
299 /* validate value length and buffer address */
300 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
301 (len == 4 && !((int)val & 3)));
303 /* Select chip and page */
304 spi_goto(robo, page);
306 /* Enable SPI access */
307 spi_select(robo, 1);
309 /* Write with CID 0 */
310 cmd8 = ((6 << 4) | /* normal SPI */
311 1); /* write */
312 spi_write(robo, &cmd8, 1);
313 spi_write(robo, &addr, 1);
314 switch (len) {
315 case 1:
316 bytes.val8 = *(uint8 *)val;
317 break;
318 case 2:
319 bytes.val16 = htol16(*(uint16 *)val);
320 break;
321 case 4:
322 bytes.val32 = htol32(*(uint32 *)val);
323 break;
325 spi_write(robo, (uint8 *)val, len);
327 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
328 *(uint16 *)val, len));
329 /* Disable SPI access */
330 spi_select(robo, 0);
331 return status;
334 /* Read register thru SPI in fast SPI mode */
335 static int
336 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
338 int status = 0;
339 uint8 cmd8;
340 union {
341 uint8 val8;
342 uint16 val16;
343 uint32 val32;
344 } bytes;
346 /* validate value length and buffer address */
347 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
348 (len == 4 && !((int)val & 3)));
350 /* Select chip and page */
351 spi_goto(robo, page);
353 /* Enable SPI access */
354 spi_select(robo, 1);
356 /* Fast SPI read with CID 0 and byte offset 0 */
357 cmd8 = (1 << 4); /* fast SPI */
358 spi_write(robo, &cmd8, 1);
359 spi_write(robo, &addr, 1);
360 status = spi_read(robo, (uint8 *)&bytes, len);
361 switch (len) {
362 case 1:
363 *(uint8 *)val = bytes.val8;
364 break;
365 case 2:
366 *(uint16 *)val = ltoh16(bytes.val16);
367 break;
368 case 4:
369 *(uint32 *)val = ltoh32(bytes.val32);
370 break;
373 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
374 *(uint16 *)val, len));
376 /* Disable SPI access */
377 spi_select(robo, 0);
378 return status;
381 /* SPI/gpio interface functions */
382 static dev_ops_t spigpio = {
383 gpio_enable,
384 gpio_disable,
385 spi_wreg,
386 spi_rreg,
387 "SPI (GPIO)"
389 #endif /* _CFE_ */
392 /* Access switch registers through MII (MDC/MDIO) */
394 #define MII_MAX_RETRY 100
396 /* Write register thru MDC/MDIO */
397 static int
398 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
400 uint16 cmd16, val16;
401 void *h = robo->h;
402 int i;
403 uint8 *ptr = (uint8 *)val;
405 /* validate value length and buffer address */
406 ASSERT(len == 1 || len == 6 || len == 8 ||
407 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
409 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
410 VARG(val, len), len));
412 /* set page number - MII register 0x10 */
413 if (robo->page != page) {
414 cmd16 = ((page << 8) | /* page number */
415 1); /* mdc/mdio access enable */
416 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
417 robo->page = page;
420 switch (len) {
421 case 8:
422 val16 = ptr[7];
423 val16 = ((val16 << 8) | ptr[6]);
424 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
425 /* FALLTHRU */
427 case 6:
428 val16 = ptr[5];
429 val16 = ((val16 << 8) | ptr[4]);
430 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
431 val16 = ptr[3];
432 val16 = ((val16 << 8) | ptr[2]);
433 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
434 val16 = ptr[1];
435 val16 = ((val16 << 8) | ptr[0]);
436 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
437 break;
439 case 4:
440 val16 = (uint16)((*(uint32 *)val) >> 16);
441 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
442 val16 = (uint16)(*(uint32 *)val);
443 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
444 break;
446 case 2:
447 val16 = *(uint16 *)val;
448 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
449 break;
451 case 1:
452 val16 = *(uint8 *)val;
453 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
454 break;
457 /* set register address - MII register 0x11 */
458 cmd16 = ((reg << 8) | /* register address */
459 1); /* opcode write */
460 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
462 /* is operation finished? */
463 for (i = MII_MAX_RETRY; i > 0; i --) {
464 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
465 if ((val16 & 3) == 0)
466 break;
469 /* timed out */
470 if (!i) {
471 ET_ERROR(("mii_wreg: timeout"));
472 return -1;
474 return 0;
477 /* Read register thru MDC/MDIO */
478 static int
479 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
481 uint16 cmd16, val16;
482 void *h = robo->h;
483 int i;
484 uint8 *ptr = (uint8 *)val;
486 /* validate value length and buffer address */
487 ASSERT(len == 1 || len == 6 || len == 8 ||
488 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
490 /* set page number - MII register 0x10 */
491 if (robo->page != page) {
492 cmd16 = ((page << 8) | /* page number */
493 1); /* mdc/mdio access enable */
494 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
495 robo->page = page;
498 /* set register address - MII register 0x11 */
499 cmd16 = ((reg << 8) | /* register address */
500 2); /* opcode read */
501 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
503 /* is operation finished? */
504 for (i = MII_MAX_RETRY; i > 0; i --) {
505 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
506 if ((val16 & 3) == 0)
507 break;
509 /* timed out */
510 if (!i) {
511 ET_ERROR(("mii_rreg: timeout"));
512 return -1;
515 switch (len) {
516 case 8:
517 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
518 ptr[7] = (val16 >> 8);
519 ptr[6] = (val16 & 0xff);
520 /* FALLTHRU */
522 case 6:
523 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
524 ptr[5] = (val16 >> 8);
525 ptr[4] = (val16 & 0xff);
526 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
527 ptr[3] = (val16 >> 8);
528 ptr[2] = (val16 & 0xff);
529 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
530 ptr[1] = (val16 >> 8);
531 ptr[0] = (val16 & 0xff);
532 break;
534 case 4:
535 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
536 *(uint32 *)val = (((uint32)val16) << 16);
537 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
538 *(uint32 *)val |= val16;
539 break;
541 case 2:
542 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
543 *(uint16 *)val = val16;
544 break;
546 case 1:
547 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
548 *(uint8 *)val = (uint8)(val16 & 0xff);
549 break;
552 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
553 VARG(val, len), len));
555 return 0;
558 /* MII interface functions */
559 static dev_ops_t mdcmdio = {
560 NULL,
561 NULL,
562 mii_wreg,
563 mii_rreg,
564 "MII (MDC/MDIO)"
567 /* High level switch configuration functions. */
569 /* Get access to the RoboSwitch */
570 robo_info_t *
571 bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr)
573 robo_info_t *robo;
574 uint32 reset, idx;
575 #ifndef _CFE_
576 const char *et1port, *et1phyaddr;
577 int mdcport = 0, phyaddr = 0;
578 #endif /* _CFE_ */
579 int lan_portenable = 0;
581 /* Allocate and init private state */
582 if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) {
583 ET_ERROR(("robo_attach: out of memory, malloced %d bytes",
584 MALLOCED(si_osh(sih))));
585 return NULL;
587 bzero(robo, sizeof(robo_info_t));
589 robo->h = h;
590 robo->sih = sih;
591 robo->vars = vars;
592 robo->miird = miird;
593 robo->miiwr = miiwr;
594 robo->page = -1;
596 /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when
597 * romboot CFE loads linux over WAN port and Linux enables LAN ports later
599 if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) !=
600 GPIO_PIN_NOTDEFINED) {
601 lan_portenable = 1 << lan_portenable;
602 si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
603 si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
604 bcm_mdelay(5);
607 /* Trigger external reset by nvram variable existance */
608 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
609 GPIO_PIN_NOTDEFINED) {
611 * Reset sequence: RESET low(50ms)->high(20ms)
613 * We have to perform a full sequence for we don't know how long
614 * it has been from power on till now.
616 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
617 reset = 1 << reset;
619 /* Keep RESET low for 50 ms */
620 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
621 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
622 bcm_mdelay(50);
624 /* Keep RESET high for at least 20 ms */
625 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
626 bcm_mdelay(20);
627 } else {
628 /* In case we need it */
629 idx = si_coreidx(sih);
631 if (si_setcore(sih, ROBO_CORE_ID, 0)) {
632 /* If we have an internal robo core, reset it using si_core_reset */
633 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
634 si_core_reset(sih, 0, 0);
635 robo->corerev = si_corerev(sih);
637 else if (sih->chip == BCM5356_CHIP_ID) {
638 /* Testing chipid is a temporary hack. We need to really
639 * figure out how to treat non-cores in ai chips.
641 robo->corerev = 3;
643 else {
644 mii_rreg(robo, PAGE_STATUS, REG_STATUS_REV, &robo->corerev, 1);
646 si_setcoreidx(sih, idx);
647 ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev));
650 if (miird && miiwr) {
651 uint16 tmp;
652 int rc, retry_count = 0;
654 /* Read the PHY ID */
655 tmp = miird(h, PSEUDO_PHYAD, 2);
657 /* WAR: Enable mdc/mdio access to the switch registers. Unless
658 * a write to bit 0 of pseudo phy register 16 is done we are
659 * unable to talk to the switch on a customer ref design.
661 if (tmp == 0xffff) {
662 miiwr(h, PSEUDO_PHYAD, 16, 1);
663 tmp = miird(h, PSEUDO_PHYAD, 2);
666 if (tmp != 0xffff) {
667 do {
668 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID,
669 &robo->devid, sizeof(uint16));
670 if (rc != 0)
671 break;
672 retry_count++;
673 } while ((robo->devid == 0) && (retry_count < 10));
675 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n",
676 __FUNCTION__, rc ? "un" : "", robo->devid));
677 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
678 robo->ops = &mdcmdio;
679 if ((rc != 0) || (robo->devid == 0)) {
680 ET_MSG(("%s: error reading devid, assuming 5325e\n",
681 __FUNCTION__));
682 robo->devid = DEVID5325;
685 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
688 if ((robo->devid == DEVID5395) ||
689 (robo->devid == DEVID5397) ||
690 (robo->devid == DEVID5398)) {
691 uint8 srst_ctrl;
693 /* If it is a 539x switch, use the soft reset register */
694 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
696 /* Reset the 539x switch core and register file */
697 srst_ctrl = 0x83;
698 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
699 srst_ctrl = 0x00;
700 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
703 /* Enable switch leds */
704 if (sih->chip == BCM5356_CHIP_ID) {
705 si_pmu_chipcontrol(sih, 2, (1 << 25), (1 << 25));
706 /* also enable fast MII clocks */
707 si_pmu_chipcontrol(sih, 0, (1 << 1), (1 << 1));
708 } else if ((sih->chip == BCM5357_CHIP_ID) || (sih->chip == BCM53572_CHIP_ID)) {
709 uint32 led_gpios = 0;
710 const char *var;
712 if (((sih->chip == BCM5357_CHIP_ID) && (sih->chippkg != BCM47186_PKG_ID)) ||
713 ((sih->chip == BCM53572_CHIP_ID) && (sih->chippkg != BCM47188_PKG_ID)))
714 led_gpios = 0x1f;
715 var = getvar(vars, "et_swleds");
716 if (var)
717 led_gpios = bcm_strtoul(var, NULL, 0);
718 if (led_gpios)
719 si_pmu_chipcontrol(sih, 2, (0x3ff << 8), (led_gpios << 8));
722 #ifndef _CFE_
723 if (!robo->ops) {
724 int mosi, miso, ss, sck;
726 robo->ops = &spigpio;
727 robo->devid = DEVID5325;
729 /* Init GPIO mapping. Default 2, 3, 4, 5 */
730 ss = getgpiopin(vars, "robo_ss", 2);
731 if (ss == GPIO_PIN_NOTDEFINED) {
732 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
733 goto error;
735 robo->ss = 1 << ss;
736 sck = getgpiopin(vars, "robo_sck", 3);
737 if (sck == GPIO_PIN_NOTDEFINED) {
738 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
739 goto error;
741 robo->sck = 1 << sck;
742 mosi = getgpiopin(vars, "robo_mosi", 4);
743 if (mosi == GPIO_PIN_NOTDEFINED) {
744 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
745 goto error;
747 robo->mosi = 1 << mosi;
748 miso = getgpiopin(vars, "robo_miso", 5);
749 if (miso == GPIO_PIN_NOTDEFINED) {
750 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
751 goto error;
753 robo->miso = 1 << miso;
754 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
755 ss, sck, mosi, miso));
757 #endif /* _CFE_ */
759 /* sanity check */
760 ASSERT(robo->ops);
761 ASSERT(robo->ops->write_reg);
762 ASSERT(robo->ops->read_reg);
763 ASSERT((robo->devid == DEVID5325) ||
764 (robo->devid == DEVID5395) ||
765 (robo->devid == DEVID5397) ||
766 (robo->devid == DEVID5398) ||
767 (robo->devid == DEVID53115) ||
768 (robo->devid == DEVID53125));
770 #ifndef _CFE_
771 /* nvram variable switch_mode controls the power save mode on the switch
772 * set the default value in the beginning
774 robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual");
775 robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto");
777 /* Determining what all phys need to be included in
778 * power save operation
780 et1port = getvar(vars, "et1mdcport");
781 if (et1port)
782 mdcport = bcm_atoi(et1port);
784 et1phyaddr = getvar(vars, "et1phyaddr");
785 if (et1phyaddr)
786 phyaddr = bcm_atoi(et1phyaddr);
788 if ((mdcport == 0) && (phyaddr == 4))
789 /* For 5325F switch we need to do only phys 0-3 */
790 robo->pwrsave_phys = 0xf;
791 else
792 /* By default all 5 phys are put into power save if there is no link */
793 robo->pwrsave_phys = 0x1f;
794 #endif /* _CFE_ */
796 return robo;
798 #ifndef _CFE_
799 error:
800 bcm_robo_detach(robo);
801 return NULL;
802 #endif /* _CFE_ */
805 /* Release access to the RoboSwitch */
806 void
807 bcm_robo_detach(robo_info_t *robo)
809 MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
812 /* Enable the device and set it to a known good state */
814 bcm_robo_enable_device(robo_info_t *robo)
816 uint8 reg_offset, reg_val;
817 int ret = 0;
819 /* Enable management interface access */
820 if (robo->ops->enable_mgmtif)
821 robo->ops->enable_mgmtif(robo);
823 if (robo->devid == DEVID5398) {
824 /* Disable unused ports: port 6 and 7 */
825 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
826 /* Set bits [1:0] to disable RX and TX */
827 reg_val = 0x03;
828 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
829 sizeof(reg_val));
833 if (robo->devid == DEVID5325) {
834 /* Must put the switch into Reverse MII mode! */
836 /* MII port state override (page 0 register 14) */
837 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
839 /* Bit 4 enables reverse MII mode */
840 if (!(reg_val & (1 << 4))) {
841 /* Enable RvMII */
842 reg_val |= (1 << 4);
843 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
844 sizeof(reg_val));
846 /* Read back */
847 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
848 sizeof(reg_val));
849 if (!(reg_val & (1 << 4))) {
850 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
851 ret = -1;
856 /* Disable management interface access */
857 if (robo->ops->disable_mgmtif)
858 robo->ops->disable_mgmtif(robo);
860 return ret;
863 /* Port flags */
864 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
865 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
866 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
868 /* port descriptor */
869 typedef struct {
870 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
871 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
872 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
873 uint8 cpu; /* is this cpu port? */
874 } pdesc_t;
876 pdesc_t pdesc97[] = {
877 /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */
878 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
879 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
880 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
881 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
882 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
883 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
884 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
885 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
886 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
889 pdesc_t pdesc25[] = {
890 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
891 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
892 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
893 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
894 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
895 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
898 /* Configure the VLANs */
900 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
902 uint8 val8;
903 uint16 val16;
904 uint32 val32;
905 pdesc_t *pdesc;
906 int pdescsz;
907 uint16 vid;
908 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
910 /* Enable management interface access */
911 if (robo->ops->enable_mgmtif)
912 robo->ops->enable_mgmtif(robo);
914 /* setup global vlan configuration */
915 /* VLAN Control 0 Register (Page 0x34, Address 0) */
916 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
917 val8 |= ((1 << 7) | /* enable 802.1Q VLAN */
918 (3 << 5)); /* individual VLAN learning mode */
919 if (robo->devid == DEVID5325)
920 val8 &= ~(1 << 1); /* must clear reserved bit 1 */
921 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
922 /* VLAN Control 1 Register (Page 0x34, Address 1) */
923 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
924 val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */
925 (1 << 3)); /* enable RSV multicast V Untagmap */
926 if (robo->devid == DEVID5325)
927 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
928 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
930 arl_entry[0] = mac_addr[5];
931 arl_entry[1] = mac_addr[4];
932 arl_entry[2] = mac_addr[3];
933 arl_entry[3] = mac_addr[2];
934 arl_entry[4] = mac_addr[1];
935 arl_entry[5] = mac_addr[0];
937 if (robo->devid == DEVID5325) {
938 /* Init the entry 1 of the bin */
939 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1,
940 arl_entry1, sizeof(arl_entry1));
941 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1,
942 arl_entry1, 1);
944 /* Init the entry 0 of the bin */
945 arl_entry[6] = 0x8; /* Port Id: MII */
946 arl_entry[7] = 0xc0; /* Static Entry, Valid */
948 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
949 arl_entry, sizeof(arl_entry));
950 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
951 arl_entry, ETHER_ADDR_LEN);
953 /* VLAN Control 4 Register (Page 0x34, Address 4) */
954 val8 = (1 << 6); /* drop frame with VID violation */
955 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
957 /* VLAN Control 5 Register (Page 0x34, Address 5) */
958 val8 = (1 << 3); /* drop frame when miss V table */
959 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
961 pdesc = pdesc25;
962 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
963 } else {
964 /* Initialize the MAC Addr Index Register */
965 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
966 arl_entry, ETHER_ADDR_LEN);
968 pdesc = pdesc97;
969 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
972 /* setup each vlan. max. 16 vlans. */
973 /* force vlan id to be equal to vlan number */
974 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
975 char vlanports[] = "vlanXXXXports";
976 char port[] = "XXXX", *next;
977 const char *ports, *cur;
978 uint32 untag = 0;
979 uint32 member = 0;
980 int pid, len;
982 /* no members if VLAN id is out of limitation */
983 if (vid > VLAN_MAXVID)
984 goto vlan_setup;
986 /* get vlan member ports from nvram */
987 sprintf(vlanports, "vlan%dports", vid);
988 ports = getvar(robo->vars, vlanports);
990 /* In 539x vid == 0 us invalid?? */
991 if ((robo->devid != DEVID5325) && (vid == 0)) {
992 if (ports)
993 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
994 continue;
997 /* disable this vlan if not defined */
998 if (!ports)
999 goto vlan_setup;
1002 * setup each port in the vlan. cpu port needs special handing
1003 * (with or without output tagging) to support linux/pmon/cfe.
1005 for (cur = ports; cur; cur = next) {
1006 /* tokenize the port list */
1007 while (*cur == ' ')
1008 cur ++;
1009 next = bcmstrstr(cur, " ");
1010 len = next ? next - cur : strlen(cur);
1011 if (!len)
1012 break;
1013 if (len > sizeof(port) - 1)
1014 len = sizeof(port) - 1;
1015 strncpy(port, cur, len);
1016 port[len] = 0;
1018 /* make sure port # is within the range */
1019 pid = bcm_atoi(port);
1020 if (pid >= pdescsz) {
1021 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
1022 "of range[0-%d]\n", pid, vid, pdescsz));
1023 continue;
1026 /* build VLAN registers values */
1027 #ifndef _CFE_
1028 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1029 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
1030 #endif
1031 untag |= pdesc[pid].untag;
1033 member |= pdesc[pid].member;
1035 /* set port tag - applies to untagged ingress frames */
1036 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
1037 #ifdef _CFE_
1038 #define FL FLAG_LAN
1039 #else
1040 #define FL FLAG_UNTAG
1041 #endif /* _CFE_ */
1042 if (!pdesc[pid].cpu || strchr(port, FL)) {
1043 val16 = ((0 << 13) | /* priority - always 0 */
1044 vid); /* vlan id */
1045 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
1046 &val16, sizeof(val16));
1050 /* Add static ARL entries */
1051 if (robo->devid == DEVID5325) {
1052 val8 = vid;
1053 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0,
1054 &val8, sizeof(val8));
1055 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1056 &val8, sizeof(val8));
1058 /* Write the entry */
1059 val8 = 0x80;
1060 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1061 &val8, sizeof(val8));
1062 /* Wait for write to complete */
1063 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1064 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1065 100 /* usec */);
1066 } else {
1067 /* Set the VLAN Id in VLAN ID Index Register */
1068 val8 = vid;
1069 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1070 &val8, sizeof(val8));
1072 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1073 * Register.
1075 arl_entry[6] = vid;
1076 arl_entry[7] = 0x0;
1077 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
1078 arl_entry, sizeof(arl_entry));
1080 /* Set the Static bit , Valid bit and Port ID fields in
1081 * ARL Table Data Entry 0 Register
1083 val16 = 0xc008;
1084 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1085 &val16, sizeof(val16));
1087 /* Clear the ARL_R/W bit and set the START/DONE bit in
1088 * the ARL Read/Write Control Register.
1090 val8 = 0x80;
1091 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1092 &val8, sizeof(val8));
1093 /* Wait for write to complete */
1094 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1095 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1096 100 /* usec */);
1099 vlan_setup:
1100 /* setup VLAN ID and VLAN memberships */
1102 val32 = (untag | /* untag enable */
1103 member); /* vlan members */
1104 if (robo->devid == DEVID5325) {
1105 if (robo->corerev < 3) {
1106 val32 |= ((1 << 20) | /* valid write */
1107 ((vid >> 4) << 12)); /* vlan id bit[11:4] */
1108 } else {
1109 val32 |= ((1 << 24) | /* valid write */
1110 (vid << 12)); /* vlan id bit[11:4] */
1112 ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32));
1114 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1115 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1116 sizeof(val32));
1117 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1118 val16 = ((1 << 13) | /* start command */
1119 (1 << 12) | /* write state */
1120 vid); /* vlan id */
1121 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1122 sizeof(val16));
1123 } else {
1124 uint8 vtble, vtbli, vtbla;
1126 if ((robo->devid == DEVID5395) ||
1127 (robo->devid == DEVID53115) ||
1128 (robo->devid == DEVID53125)) {
1129 vtble = REG_VTBL_ENTRY_5395;
1130 vtbli = REG_VTBL_INDX_5395;
1131 vtbla = REG_VTBL_ACCESS_5395;
1132 } else {
1133 vtble = REG_VTBL_ENTRY;
1134 vtbli = REG_VTBL_INDX;
1135 vtbla = REG_VTBL_ACCESS;
1138 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1139 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1140 sizeof(val32));
1141 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1142 val16 = vid; /* vlan id */
1143 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1144 sizeof(val16));
1146 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1147 val8 = ((1 << 7) | /* start command */
1148 0); /* write */
1149 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1150 sizeof(val8));
1154 if (robo->devid == DEVID5325) {
1155 /* setup priority mapping - applies to tagged ingress frames */
1156 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1157 val32 = ((0 << 0) | /* 0 -> 0 */
1158 (1 << 3) | /* 1 -> 1 */
1159 (2 << 6) | /* 2 -> 2 */
1160 (3 << 9) | /* 3 -> 3 */
1161 (4 << 12) | /* 4 -> 4 */
1162 (5 << 15) | /* 5 -> 5 */
1163 (6 << 18) | /* 6 -> 6 */
1164 (7 << 21)); /* 7 -> 7 */
1165 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1168 if (robo->devid == DEVID53115) {
1169 /* Configure the priority system to use to determine the TC of
1170 * ingress frames. Use DiffServ TC mapping, otherwise 802.1p
1171 * TC mapping, otherwise MAC based TC mapping.
1173 val8 = ((0 << 6) | /* Disable port based QoS */
1174 (2 << 2)); /* QoS priority selection */
1175 robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8));
1177 /* Configure tx queues scheduling mechanism */
1178 val8 = (3 << 0); /* Strict priority */
1179 robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8));
1181 /* Enable 802.1p Priority to TC mapping for individual ports */
1182 val16 = 0x11f;
1183 robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16));
1185 /* Configure the TC to COS mapping. This determines the egress
1186 * transmit queue.
1188 val16 = ((1 << 0) | /* Pri 0 mapped to TXQ 1 */
1189 (0 << 2) | /* Pri 1 mapped to TXQ 0 */
1190 (0 << 4) | /* Pri 2 mapped to TXQ 0 */
1191 (1 << 6) | /* Pri 3 mapped to TXQ 1 */
1192 (2 << 8) | /* Pri 4 mapped to TXQ 2 */
1193 (2 << 10) | /* Pri 5 mapped to TXQ 2 */
1194 (3 << 12) | /* Pri 6 mapped to TXQ 3 */
1195 (3 << 14)); /* Pri 7 mapped to TXQ 3 */
1196 robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16));
1199 /* Drop reserved bit, if any */
1200 robo->ops->read_reg(robo, PAGE_CTRL, 0x2f, &val8, sizeof(val8));
1201 if (/*((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) &&*/
1202 val8 & (1 << 1)) {
1203 val8 &= ~(1 << 1);
1204 robo->ops->write_reg(robo, PAGE_CTRL, 0x2f, &val8, sizeof(val8));
1207 /* Disable management interface access */
1208 if (robo->ops->disable_mgmtif)
1209 robo->ops->disable_mgmtif(robo);
1211 return 0;
1214 /* Enable switching/forwarding */
1216 bcm_robo_enable_switch(robo_info_t *robo)
1218 int i, max_port_ind, ret = 0;
1219 uint8 val8;
1221 /* Enable management interface access */
1222 if (robo->ops->enable_mgmtif)
1223 robo->ops->enable_mgmtif(robo);
1225 /* Switch Mode register (Page 0, Address 0x0B) */
1226 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1228 /* Bit 1 enables switching/forwarding */
1229 if (!(val8 & (1 << 1))) {
1230 /* Set unmanaged mode */
1231 val8 &= (~(1 << 0));
1233 /* Enable forwarding */
1234 val8 |= (1 << 1);
1235 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1237 /* Read back */
1238 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1239 if (!(val8 & (1 << 1))) {
1240 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1241 ret = -1;
1244 /* No spanning tree for unmanaged mode */
1245 val8 = 0;
1246 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
1247 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1248 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1251 /* No spanning tree on IMP port too */
1252 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8));
1255 if (robo->devid == DEVID53125) {
1256 /* Over ride IMP port status to make it link by default */
1257 val8 = 0;
1258 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1259 val8 |= 0xb1; /* Make Link pass and override it. */
1260 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1261 /* Init the EEE feature */
1262 robo_eee_advertise_init(robo);
1265 /* Disable management interface access */
1266 if (robo->ops->disable_mgmtif)
1267 robo->ops->disable_mgmtif(robo);
1269 return ret;
1272 #ifdef BCMDBG
1273 void
1274 robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b)
1276 uint8 val8;
1277 uint16 val16;
1278 uint32 val32;
1279 pdesc_t *pdesc;
1280 int pdescsz;
1281 int i;
1283 bcm_bprintf(b, "%s:\n", robo->ops->desc);
1284 if (robo->miird == NULL) {
1285 bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n",
1286 robo->ss, robo->sck, robo->mosi, robo->miso);
1289 /* Enable management interface access */
1290 if (robo->ops->enable_mgmtif)
1291 robo->ops->enable_mgmtif(robo);
1293 /* Dump registers interested */
1294 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1295 bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8);
1296 if (robo->devid == DEVID5325) {
1297 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1298 bcm_bprintf(b, "(0x00,0x0E)MII port state override regsiter: 0x%02x\n", val8);
1300 if (robo->miird == NULL)
1301 goto exit;
1302 if (robo->devid == DEVID5325) {
1303 pdesc = pdesc25;
1304 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1305 } else {
1306 pdesc = pdesc97;
1307 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1310 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1311 bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8);
1312 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1313 bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8);
1314 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1315 if (robo->devid == DEVID5325) {
1316 bcm_bprintf(b, "(0x34,0x04)VLAN control 4 register: 0x%02x\n", val8);
1317 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1318 bcm_bprintf(b, "(0x34,0x05)VLAN control 5 register: 0x%02x\n", val8);
1320 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1321 bcm_bprintf(b, "(0x34,0x20)Prio Re-map: 0x%08x\n", val32);
1323 for (i = 0; i <= VLAN_MAXVID; i++) {
1324 val16 = (1 << 13) /* start command */
1325 | i; /* vlan id */
1326 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1327 sizeof(val16));
1328 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_READ, &val32, sizeof(val32));
1329 bcm_bprintf(b, "(0x34,0xc)VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1330 i, (val32 & 0x0fc0) >> 6, (val32 & 0x003f));
1333 } else {
1334 for (i = 0; i <= VLAN_MAXVID; i++) {
1335 /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62) */
1336 val16 = i; /* vlan id */
1337 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_INDX, &val16,
1338 sizeof(val16));
1339 /* VLAN Table Access Register (Page 0x34, Address 0x60) */
1340 val8 = ((1 << 7) | /* start command */
1341 1); /* read */
1342 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ACCESS, &val8,
1343 sizeof(val8));
1344 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66) */
1345 robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_ENTRY, &val32,
1346 sizeof(val32));
1347 bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1348 i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff));
1351 for (i = 0; i < pdescsz; i++) {
1352 robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16));
1353 bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16);
1356 exit:
1357 /* Disable management interface access */
1358 if (robo->ops->disable_mgmtif)
1359 robo->ops->disable_mgmtif(robo);
1361 #endif /* BCMDBG */
1363 #ifndef _CFE_
1365 * Update the power save configuration for ports that changed link status.
1367 void
1368 robo_power_save_mode_update(robo_info_t *robo)
1370 uint phy;
1372 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1373 if (robo->pwrsave_mode_auto & (1 << phy)) {
1374 ET_MSG(("%s: set port %d to auto mode\n",
1375 __FUNCTION__, phy));
1376 robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy);
1380 return;
1383 static int32
1384 robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy)
1386 uint16 val16;
1388 if (robo->devid == DEVID53115) {
1389 /* For 53115 0x1C is the MII address of the auto power
1390 * down register. Bit 5 is enabling the mode
1391 * bits has the following purpose
1392 * 15 - write enable 10-14 shadow register select 01010 for
1393 * auto power 6-9 reserved 5 auto power mode enable
1394 * 4 sleep timer select : 1 means 5.4 sec
1395 * 0-3 wake up timer select: 0xF 1.26 sec
1397 val16 = 0xa800;
1398 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, val16);
1399 } else if ((robo->sih->chip == BCM5356_CHIP_ID) || (robo->sih->chip == BCM5357_CHIP_ID)) {
1400 /* To disable auto power down mode
1401 * clear bit 5 of Aux Status 2 register
1402 * (Shadow reg 0x1b). Shadow register
1403 * access is enabled by writing
1404 * 1 to bit 7 of MII register 0x1f.
1406 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1407 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1408 (val16 | (1 << 7)));
1410 /* Disable auto power down by clearing
1411 * bit 5 of to Aux Status 2 reg.
1413 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1414 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1415 (val16 & ~(1 << 5)));
1417 /* Undo shadow access */
1418 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1419 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1420 (val16 & ~(1 << 7)));
1421 } else
1422 return -1;
1424 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_AUTO;
1426 return 0;
1429 static int32
1430 robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy)
1432 uint8 val8;
1433 uint16 val16;
1435 if ((robo->devid == DEVID53115) ||
1436 (robo->sih->chip == BCM5356_CHIP_ID)) {
1437 /* For 53115 0x0 is the MII control register
1438 * Bit 11 is the power down mode bit
1440 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1441 val16 &= 0xf7ff;
1442 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16);
1443 } else if (robo->devid == DEVID5325) {
1444 if ((robo->sih->chip == BCM5357_CHIP_ID) ||
1445 (robo->sih->chip == BCM4749_CHIP_ID) ||
1446 (robo->sih->chip == BCM53572_CHIP_ID)) {
1447 robo->miiwr(robo->h, phy, 0x1f, 0x8b);
1448 robo->miiwr(robo->h, phy, 0x14, 0x0008);
1449 robo->miiwr(robo->h, phy, 0x10, 0x0400);
1450 robo->miiwr(robo->h, phy, 0x11, 0x0000);
1451 robo->miiwr(robo->h, phy, 0x1f, 0x0b);
1452 } else {
1453 if (phy == 0)
1454 return -1;
1455 /* For 5325 page 0x00 address 0x0F is the power down
1456 * mode register. Bits 1-4 determines which of the
1457 * phys are enabled for this mode
1459 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1460 &val8, sizeof(val8));
1461 val8 &= ~(0x1 << phy);
1462 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1463 &val8, sizeof(val8));
1465 } else
1466 return -1;
1468 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_MANUAL;
1470 return 0;
1474 * Function which periodically checks the power save mode on the switch
1476 int32
1477 robo_power_save_toggle(robo_info_t *robo, int32 normal)
1479 int32 phy;
1480 uint16 link_status;
1483 /* read the link status of all ports */
1484 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1485 &link_status, sizeof(uint16));
1486 link_status &= 0x1f;
1488 /* Take the phys out of the manual mode first so that link status
1489 * can be checked. Once out of that mode check the link status
1490 * and if any of the link is up do not put that phy into
1491 * manual power save mode
1493 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1494 /* When auto+manual modes are enabled we toggle between
1495 * manual and auto modes. When only manual mode is enabled
1496 * we toggle between manual and normal modes. When only
1497 * auto mode is enabled there is no need to do anything
1498 * here since auto mode is one time config.
1500 if ((robo->pwrsave_phys & (1 << phy)) &&
1501 (robo->pwrsave_mode_manual & (1 << phy))) {
1502 if (!normal) {
1503 /* Take the port out of the manual mode */
1504 robo_power_save_mode_clear_manual(robo, phy);
1505 } else {
1506 /* If the link is down put it back to manual else
1507 * remain in the current state
1509 if (!(link_status & (1 << phy))) {
1510 ET_MSG(("%s: link down, set port %d to man mode\n",
1511 __FUNCTION__, phy));
1512 robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy);
1518 return 0;
1522 * Switch the ports to normal mode.
1524 static int32
1525 robo_power_save_mode_normal(robo_info_t *robo, int32 phy)
1527 int32 error = 0;
1529 /* If the phy in the power save mode come out of it */
1530 switch (robo->pwrsave_mode_phys[phy]) {
1531 case ROBO_PWRSAVE_AUTO_MANUAL:
1532 case ROBO_PWRSAVE_AUTO:
1533 error = robo_power_save_mode_clear_auto(robo, phy);
1534 if ((error == -1) ||
1535 (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO))
1536 break;
1538 case ROBO_PWRSAVE_MANUAL:
1539 error = robo_power_save_mode_clear_manual(robo, phy);
1540 break;
1542 default:
1543 break;
1546 return error;
1550 * Switch all the inactive ports to auto power down mode.
1552 static int32
1553 robo_power_save_mode_auto(robo_info_t *robo, int32 phy)
1555 uint16 val16;
1557 /* If the switch supports auto power down enable that */
1558 if (robo->devid == DEVID53115) {
1559 /* For 53115 0x1C is the MII address of the auto power
1560 * down register. Bit 5 is enabling the mode
1561 * bits has the following purpose
1562 * 15 - write enable 10-14 shadow register select 01010 for
1563 * auto power 6-9 reserved 5 auto power mode enable
1564 * 4 sleep timer select : 1 means 5.4 sec
1565 * 0-3 wake up timer select: 0xF 1.26 sec
1567 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA83F);
1568 } else if ((robo->sih->chip == BCM5356_CHIP_ID) || (robo->sih->chip == BCM5357_CHIP_ID)) {
1569 /* To enable auto power down mode set bit 5 of
1570 * Auxillary Status 2 register (Shadow reg 0x1b)
1571 * Shadow register access is enabled by writing
1572 * 1 to bit 7 of MII register 0x1f.
1574 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1575 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1576 (val16 | (1 << 7)));
1578 /* Enable auto power down by writing to Auxillary
1579 * Status 2 reg.
1581 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1582 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1583 (val16 | (1 << 5)));
1585 /* Undo shadow access */
1586 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1587 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1588 (val16 & ~(1 << 7)));
1589 } else
1590 return -1;
1592 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_AUTO;
1594 return 0;
1598 * Switch all the inactive ports to manual power down mode.
1600 static int32
1601 robo_power_save_mode_manual(robo_info_t *robo, int32 phy)
1603 uint8 val8;
1604 uint16 val16;
1606 /* For both 5325 and 53115 the link status register is the same */
1607 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1608 &val16, sizeof(val16));
1609 if (val16 & (0x1 << phy))
1610 return 0;
1612 /* If the switch supports manual power down enable that */
1613 if ((robo->devid == DEVID53115) ||
1614 (robo->sih->chip == BCM5356_CHIP_ID)) {
1615 /* For 53115 0x0 is the MII control register bit 11 is the
1616 * power down mode bit
1618 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1619 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16 | 0x800);
1620 } else if (robo->devid == DEVID5325) {
1621 if ((robo->sih->chip == BCM5357_CHIP_ID) ||
1622 (robo->sih->chip == BCM4749_CHIP_ID)||
1623 (robo->sih->chip == BCM53572_CHIP_ID)) {
1624 robo->miiwr(robo->h, phy, 0x1f, 0x8b);
1625 robo->miiwr(robo->h, phy, 0x14, 0x6000);
1626 robo->miiwr(robo->h, phy, 0x10, 0x700);
1627 robo->miiwr(robo->h, phy, 0x11, 0x1000);
1628 robo->miiwr(robo->h, phy, 0x1f, 0x0b);
1629 } else {
1630 if (phy == 0)
1631 return -1;
1632 /* For 5325 page 0x00 address 0x0F is the power down mode
1633 * register. Bits 1-4 determines which of the phys are enabled
1634 * for this mode
1636 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1637 sizeof(val8));
1638 val8 |= (1 << phy);
1639 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1640 sizeof(val8));
1642 } else
1643 return -1;
1645 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_MANUAL;
1647 return 0;
1651 * Set power save modes on the robo switch
1653 int32
1654 robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy)
1656 int32 error = -1;
1658 if (phy > MAX_NO_PHYS) {
1659 ET_ERROR(("Passed parameter phy is out of range\n"));
1660 return -1;
1663 /* Enable management interface access */
1664 if (robo->ops->enable_mgmtif)
1665 robo->ops->enable_mgmtif(robo);
1667 switch (mode) {
1668 case ROBO_PWRSAVE_NORMAL:
1669 /* If the phy in the power save mode come out of it */
1670 error = robo_power_save_mode_normal(robo, phy);
1671 break;
1673 case ROBO_PWRSAVE_AUTO_MANUAL:
1674 /* If the switch supports auto and manual power down
1675 * enable both of them
1677 case ROBO_PWRSAVE_AUTO:
1678 error = robo_power_save_mode_auto(robo, phy);
1679 if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO))
1680 break;
1682 case ROBO_PWRSAVE_MANUAL:
1683 error = robo_power_save_mode_manual(robo, phy);
1684 break;
1686 default:
1687 break;
1690 /* Disable management interface access */
1691 if (robo->ops->disable_mgmtif)
1692 robo->ops->disable_mgmtif(robo);
1694 return error;
1698 * Get the current power save mode of the switch ports.
1700 int32
1701 robo_power_save_mode_get(robo_info_t *robo, int32 phy)
1703 ASSERT(robo);
1705 if (phy >= MAX_NO_PHYS)
1706 return -1;
1708 return robo->pwrsave_mode_phys[phy];
1712 * Configure the power save mode for the switch ports.
1714 int32
1715 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy)
1717 int32 error;
1719 ASSERT(robo);
1721 if (phy >= MAX_NO_PHYS)
1722 return -1;
1724 error = robo_power_save_mode(robo, mode, phy);
1726 if (error)
1727 return error;
1729 if (mode == ROBO_PWRSAVE_NORMAL) {
1730 robo->pwrsave_mode_manual &= ~(1 << phy);
1731 robo->pwrsave_mode_auto &= ~(1 << phy);
1732 } else if (mode == ROBO_PWRSAVE_AUTO) {
1733 robo->pwrsave_mode_auto |= (1 << phy);
1734 robo->pwrsave_mode_manual &= ~(1 << phy);
1735 robo_power_save_mode_clear_manual(robo, phy);
1736 } else if (mode == ROBO_PWRSAVE_MANUAL) {
1737 robo->pwrsave_mode_manual |= (1 << phy);
1738 robo->pwrsave_mode_auto &= ~(1 << phy);
1739 robo_power_save_mode_clear_auto(robo, phy);
1740 } else {
1741 robo->pwrsave_mode_auto |= (1 << phy);
1742 robo->pwrsave_mode_manual |= (1 << phy);
1745 return 0;
1747 #endif /* _CFE_ */
1749 /* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */
1751 static void
1752 robo_link_down(robo_info_t *robo, int32 phy)
1754 if (robo->devid != DEVID53125)
1755 return;
1757 printf("robo_link_down: applying EEE WAR for 53125 port %d link-down\n", phy);
1759 robo->miiwr(robo->h, phy, 0x18, 0x0c00);
1760 robo->miiwr(robo->h, phy, 0x17, 0x001a);
1761 robo->miiwr(robo->h, phy, 0x15, 0x0007);
1762 robo->miiwr(robo->h, phy, 0x18, 0x0400);
1765 static void
1766 robo_link_up(robo_info_t *robo, int32 phy)
1768 if (robo->devid != DEVID53125)
1769 return;
1771 printf("robo_link_down: applying EEE WAR for 53125 port %d link-up\n", phy);
1773 robo->miiwr(robo->h, phy, 0x18, 0x0c00);
1774 robo->miiwr(robo->h, phy, 0x17, 0x001a);
1775 robo->miiwr(robo->h, phy, 0x15, 0x0003);
1776 robo->miiwr(robo->h, phy, 0x18, 0x0400);
1779 void
1780 robo_watchdog(robo_info_t *robo)
1782 int32 phy;
1783 uint16 link_status;
1784 static int first = 1;
1786 if (robo->devid != DEVID53125)
1787 return;
1789 if (!robo->eee_status)
1790 return;
1792 /* read the link status of all ports */
1793 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1794 &link_status, sizeof(uint16));
1795 link_status &= 0x1f;
1796 if (first || (link_status != robo->prev_status)) {
1797 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1798 if (first) {
1799 if (!(link_status & (1 << phy)))
1800 robo_link_down(robo, phy);
1801 } else if ((link_status & (1 << phy)) != (robo->prev_status & (1 << phy))) {
1802 if (!(link_status & (1 << phy)))
1803 robo_link_down(robo, phy);
1804 else
1805 robo_link_up(robo, phy);
1808 robo->prev_status = link_status;
1809 first = 0;
1813 void
1814 robo_eee_advertise_init(robo_info_t *robo)
1816 uint16 val16;
1817 int32 phy;
1819 ASSERT(robo);
1821 val16 = 0;
1822 robo->ops->read_reg(robo, 0x92, 0x00, &val16, sizeof(val16));
1823 if (val16 == 0x1f) {
1824 robo->eee_status = TRUE;
1825 printf("bcm_robo_enable_switch: EEE is enabled\n");
1826 } else {
1827 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1828 /* select DEVAD 7 */
1829 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007);
1830 /* select register 3Ch */
1831 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c);
1832 /* read command */
1833 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0xc007);
1834 /* read data */
1835 val16 = robo->miird(robo->h, phy, REG_MII_CLAUSE_45_CTL2);
1836 val16 &= ~0x6;
1837 /* select DEVAD 7 */
1838 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007);
1839 /* select register 3Ch */
1840 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c);
1841 /* write command */
1842 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x4007);
1843 /* write data */
1844 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, val16);
1846 robo->eee_status = FALSE;
1847 printf("bcm_robo_enable_switch: EEE is disabled\n");