Resync with broadcom drivers 5.100.138.20 and utilities.
[tomato.git] / release / src-rt / shared / bcmrobo.c
blob346e105a8fd53db939b59f98ea402df86eb840ef
1 /*
2 * Broadcom 53xx RoboSwitch device driver.
4 * Copyright (C) 2010, 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,v 1.35.10.5 2010-10-14 22:36:02 Exp $
22 #include <typedefs.h>
23 #include <osl.h>
24 #include <bcmutils.h>
25 #include <siutils.h>
26 #include <hndsoc.h>
27 #include <bcmutils.h>
28 #include <bcmendian.h>
29 #include <bcmparams.h>
30 #include <bcmnvram.h>
31 #include <bcmdevs.h>
32 #include <bcmrobo.h>
33 #include <proto/ethernet.h>
34 #include <hndpmu.h>
36 #ifdef BCMDBG
37 #define ET_ERROR(args) printf args
38 #else /* BCMDBG */
39 #define ET_ERROR(args)
40 #endif /* BCMDBG */
41 #define ET_MSG(args)
43 #define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \
44 ((len) == 2) ? *((uint16 *)(var)) : \
45 *((uint32 *)(var)))
48 * Switch can be programmed through SPI interface, which
49 * has a rreg and a wreg functions to read from and write to
50 * registers.
53 /* MII access registers */
54 #define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
55 #define REG_MII_CTRL 0x00 /* 53115 MII control register */
56 #define REG_MII_PAGE 0x10 /* MII Page register */
57 #define REG_MII_ADDR 0x11 /* MII Address register */
58 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
59 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
60 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
61 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
62 #define REG_MII_AUX_STATUS2 0x1b /* Auxiliary status 2 register */
63 #define REG_MII_AUTO_PWRDOWN 0x1c /* 53115 Auto power down register */
64 #define REG_MII_BRCM_TEST 0x1f /* Broadcom test register */
66 /* Page numbers */
67 #define PAGE_CTRL 0x00 /* Control page */
68 #define PAGE_STATUS 0x01 /* Status page */
69 #define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
70 #define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
71 #define PAGE_VLAN 0x34 /* VLAN page */
72 #define PAGE_JUMBO 0x40 /* JUMBO frame page */
74 /* Control page registers */
75 #define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
76 #define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
77 #define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
78 #define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
79 #define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
80 #define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
81 #define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
82 #define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
83 #define REG_CTRL_IMP 0x08 /* IMP port traffic control register */
84 #define REG_CTRL_MODE 0x0B /* Switch Mode register */
85 #define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
86 #define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */
87 #define REG_CTRL_SRST 0x79 /* Software reset control register */
88 #define REG_CTRL_MIIP5O 0x5d /* 53115: Port State Override register for port 5 */
90 /* Management/Mirroring Registers */
91 #define REG_MMR_ATCR 0x06 /* Aging Time Control register */
92 #define REG_MMR_MCCR 0x10 /* Mirror Capture Control register */
93 #define REG_MMR_IMCR 0x12 /* Ingress Mirror Control register */
95 /* Status Page Registers */
96 #define REG_STATUS_LINK 0x00 /* Link Status Summary */
97 #define REG_STATUS_REV 0x50 /* Revision Register */
99 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
101 /* JUMBO Control Register */
102 #define REG_JUMBO_CTRL 0x01
103 #define REG_JUMBO_SIZE 0x05
105 /* VLAN page registers */
106 #define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
107 #define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
108 #define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
109 #define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
110 #define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
111 #define REG_VLAN_ACCESS_5365 0x08 /* 5365 VLAN Table Access register */
112 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
113 #define REG_VLAN_WRITE_5365 0x0A /* 5365 VLAN Write register */
114 #define REG_VLAN_READ 0x0C /* VLAN Read register */
115 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
116 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
117 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
118 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
119 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
120 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
121 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
122 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
123 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
124 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
126 #define VLAN_NUMVLANS 16 /* # of VLANs */
129 /* ARL/VLAN Table Access page registers */
130 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
131 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
132 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
133 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
134 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
135 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
136 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
137 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
138 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
139 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
140 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
141 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
142 #define REG_VTBL_PREG 0xFF /* Page Register */
143 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
144 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
145 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
146 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
147 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
148 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
150 #ifndef _CFE_
151 /* SPI registers */
152 #define REG_SPI_PAGE 0xff /* SPI Page register */
154 /* Access switch registers through GPIO/SPI */
156 /* Minimum timing constants */
157 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
158 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
159 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
161 /* misc. constants */
162 #define SPI_MAX_RETRY 100
164 /* Enable GPIO access to the chip */
165 static void
166 gpio_enable(robo_info_t *robo)
168 /* Enable GPIO outputs with SCK and MOSI low, SS high */
169 si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
170 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi,
171 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
174 /* Disable GPIO access to the chip */
175 static void
176 gpio_disable(robo_info_t *robo)
178 /* Disable GPIO outputs with all their current values */
179 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
182 /* Write a byte stream to the chip thru SPI */
183 static int
184 spi_write(robo_info_t *robo, uint8 *buf, uint len)
186 uint i;
187 uint8 mask;
189 /* Byte bang from LSB to MSB */
190 for (i = 0; i < len; i++) {
191 /* Bit bang from MSB to LSB */
192 for (mask = 0x80; mask; mask >>= 1) {
193 /* Clock low */
194 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
195 OSL_DELAY(SCK_EDGE_TIME);
197 /* Sample on rising edge */
198 if (mask & buf[i])
199 si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
200 else
201 si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY);
202 OSL_DELAY(MOSI_SETUP_TIME);
204 /* Clock high */
205 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
206 OSL_DELAY(SCK_EDGE_TIME);
210 return 0;
213 /* Read a byte stream from the chip thru SPI */
214 static int
215 spi_read(robo_info_t *robo, uint8 *buf, uint len)
217 uint i, timeout;
218 uint8 rack, mask, byte;
220 /* Timeout after 100 tries without RACK */
221 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
222 /* Bit bang from MSB to LSB */
223 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
224 /* Clock low */
225 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
226 OSL_DELAY(SCK_EDGE_TIME);
228 /* Sample on falling edge */
229 if (si_gpioin(robo->sih) & robo->miso)
230 byte |= mask;
232 /* Clock high */
233 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
234 OSL_DELAY(SCK_EDGE_TIME);
236 /* RACK when bit 0 is high */
237 if (!rack) {
238 rack = (byte & 1);
239 timeout--;
240 continue;
242 /* Byte bang from LSB to MSB */
243 buf[i] = byte;
244 i++;
247 if (timeout == 0) {
248 ET_ERROR(("spi_read: timeout"));
249 return -1;
252 return 0;
255 /* Enable/disable SPI access */
256 static void
257 spi_select(robo_info_t *robo, uint8 spi)
259 if (spi) {
260 /* Enable SPI access */
261 si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY);
262 } else {
263 /* Disable SPI access */
264 si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
266 OSL_DELAY(SS_SETUP_TIME);
270 /* Select chip and page */
271 static void
272 spi_goto(robo_info_t *robo, uint8 page)
274 uint8 reg8 = REG_SPI_PAGE; /* page select register */
275 uint8 cmd8;
277 /* Issue the command only when we are on a different page */
278 if (robo->page == page)
279 return;
281 robo->page = page;
283 /* Enable SPI access */
284 spi_select(robo, 1);
286 /* Select new page with CID 0 */
287 cmd8 = ((6 << 4) | /* normal SPI */
288 1); /* write */
289 spi_write(robo, &cmd8, 1);
290 spi_write(robo, &reg8, 1);
291 spi_write(robo, &page, 1);
293 /* Disable SPI access */
294 spi_select(robo, 0);
297 /* Write register thru SPI */
298 static int
299 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
301 int status = 0;
302 uint8 cmd8;
303 union {
304 uint8 val8;
305 uint16 val16;
306 uint32 val32;
307 } bytes;
309 /* validate value length and buffer address */
310 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
311 (len == 4 && !((int)val & 3)));
313 /* Select chip and page */
314 spi_goto(robo, page);
316 /* Enable SPI access */
317 spi_select(robo, 1);
319 /* Write with CID 0 */
320 cmd8 = ((6 << 4) | /* normal SPI */
321 1); /* write */
322 spi_write(robo, &cmd8, 1);
323 spi_write(robo, &addr, 1);
324 switch (len) {
325 case 1:
326 bytes.val8 = *(uint8 *)val;
327 break;
328 case 2:
329 bytes.val16 = htol16(*(uint16 *)val);
330 break;
331 case 4:
332 bytes.val32 = htol32(*(uint32 *)val);
333 break;
335 spi_write(robo, (uint8 *)val, len);
337 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
338 *(uint16 *)val, len));
339 /* Disable SPI access */
340 spi_select(robo, 0);
341 return status;
344 /* Read register thru SPI in fast SPI mode */
345 static int
346 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
348 int status = 0;
349 uint8 cmd8;
350 union {
351 uint8 val8;
352 uint16 val16;
353 uint32 val32;
354 } bytes;
356 /* validate value length and buffer address */
357 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
358 (len == 4 && !((int)val & 3)));
360 /* Select chip and page */
361 spi_goto(robo, page);
363 /* Enable SPI access */
364 spi_select(robo, 1);
366 /* Fast SPI read with CID 0 and byte offset 0 */
367 cmd8 = (1 << 4); /* fast SPI */
368 spi_write(robo, &cmd8, 1);
369 spi_write(robo, &addr, 1);
370 status = spi_read(robo, (uint8 *)&bytes, len);
371 switch (len) {
372 case 1:
373 *(uint8 *)val = bytes.val8;
374 break;
375 case 2:
376 *(uint16 *)val = ltoh16(bytes.val16);
377 break;
378 case 4:
379 *(uint32 *)val = ltoh32(bytes.val32);
380 break;
383 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
384 *(uint16 *)val, len));
386 /* Disable SPI access */
387 spi_select(robo, 0);
388 return status;
391 /* SPI/gpio interface functions */
392 static dev_ops_t spigpio = {
393 gpio_enable,
394 gpio_disable,
395 spi_wreg,
396 spi_rreg,
397 "SPI (GPIO)"
399 #endif /* _CFE_ */
402 /* Access switch registers through MII (MDC/MDIO) */
404 #define MII_MAX_RETRY 100
406 /* Write register thru MDC/MDIO */
407 static int
408 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
410 uint16 cmd16, val16;
411 void *h = robo->h;
412 int i;
413 uint8 *ptr = (uint8 *)val;
415 /* validate value length and buffer address */
416 ASSERT(len == 1 || len == 6 || len == 8 ||
417 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
419 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
420 VARG(val, len), len));
422 /* set page number - MII register 0x10 */
423 if (robo->page != page) {
424 cmd16 = ((page << 8) | /* page number */
425 1); /* mdc/mdio access enable */
426 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
427 robo->page = page;
430 switch (len) {
431 case 8:
432 val16 = ptr[7];
433 val16 = ((val16 << 8) | ptr[6]);
434 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
435 /* FALLTHRU */
437 case 6:
438 val16 = ptr[5];
439 val16 = ((val16 << 8) | ptr[4]);
440 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
441 val16 = ptr[3];
442 val16 = ((val16 << 8) | ptr[2]);
443 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
444 val16 = ptr[1];
445 val16 = ((val16 << 8) | ptr[0]);
446 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
447 break;
449 case 4:
450 val16 = (uint16)((*(uint32 *)val) >> 16);
451 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
452 val16 = (uint16)(*(uint32 *)val);
453 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
454 break;
456 case 2:
457 val16 = *(uint16 *)val;
458 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
459 break;
461 case 1:
462 val16 = *(uint8 *)val;
463 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
464 break;
467 /* set register address - MII register 0x11 */
468 cmd16 = ((reg << 8) | /* register address */
469 1); /* opcode write */
470 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
472 /* is operation finished? */
473 for (i = MII_MAX_RETRY; i > 0; i --) {
474 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
475 if ((val16 & 3) == 0)
476 break;
479 /* timed out */
480 if (!i) {
481 ET_ERROR(("mii_wreg: timeout"));
482 return -1;
484 return 0;
487 /* Read register thru MDC/MDIO */
488 static int
489 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
491 uint16 cmd16, val16;
492 void *h = robo->h;
493 int i;
494 uint8 *ptr = (uint8 *)val;
496 /* validate value length and buffer address */
497 ASSERT(len == 1 || len == 6 || len == 8 ||
498 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
500 /* set page number - MII register 0x10 */
501 if (robo->page != page) {
502 cmd16 = ((page << 8) | /* page number */
503 1); /* mdc/mdio access enable */
504 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
505 robo->page = page;
508 /* set register address - MII register 0x11 */
509 cmd16 = ((reg << 8) | /* register address */
510 2); /* opcode read */
511 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
513 /* is operation finished? */
514 for (i = MII_MAX_RETRY; i > 0; i --) {
515 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
516 if ((val16 & 3) == 0)
517 break;
519 /* timed out */
520 if (!i) {
521 ET_ERROR(("mii_rreg: timeout"));
522 return -1;
525 switch (len) {
526 case 8:
527 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
528 ptr[7] = (val16 >> 8);
529 ptr[6] = (val16 & 0xff);
530 /* FALLTHRU */
532 case 6:
533 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
534 ptr[5] = (val16 >> 8);
535 ptr[4] = (val16 & 0xff);
536 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
537 ptr[3] = (val16 >> 8);
538 ptr[2] = (val16 & 0xff);
539 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
540 ptr[1] = (val16 >> 8);
541 ptr[0] = (val16 & 0xff);
542 break;
544 case 4:
545 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
546 *(uint32 *)val = (((uint32)val16) << 16);
547 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
548 *(uint32 *)val |= val16;
549 break;
551 case 2:
552 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
553 *(uint16 *)val = val16;
554 break;
556 case 1:
557 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
558 *(uint8 *)val = (uint8)(val16 & 0xff);
559 break;
562 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
563 VARG(val, len), len));
565 return 0;
568 /* MII interface functions */
569 static dev_ops_t mdcmdio = {
570 NULL,
571 NULL,
572 mii_wreg,
573 mii_rreg,
574 "MII (MDC/MDIO)"
577 /* High level switch configuration functions. */
579 /* Get access to the RoboSwitch */
580 robo_info_t *
581 bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr)
583 robo_info_t *robo;
584 uint32 reset, idx;
585 #ifndef _CFE_
586 char *et1port, *et1phyaddr;
587 int mdcport = 0, phyaddr = 0, lan_portenable = 0;
588 #endif /* _CFE_ */
590 /* Allocate and init private state */
591 if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) {
592 ET_ERROR(("robo_attach: out of memory, malloced %d bytes",
593 MALLOCED(si_osh(sih))));
594 return NULL;
596 bzero(robo, sizeof(robo_info_t));
598 robo->h = h;
599 robo->sih = sih;
600 robo->vars = vars;
601 robo->miird = miird;
602 robo->miiwr = miiwr;
603 robo->page = -1;
605 #ifndef _CFE_
606 /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when
607 * romboot CFE loads linux over WAN port and Linux enables LAN ports later
609 if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) !=
610 GPIO_PIN_NOTDEFINED) {
611 lan_portenable = 1 << lan_portenable;
612 si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
613 si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
614 bcm_mdelay(5);
616 #endif /* _CFE_ */
618 /* Trigger external reset by nvram variable existance */
619 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
620 GPIO_PIN_NOTDEFINED) {
622 * Reset sequence: RESET low(50ms)->high(20ms)
624 * We have to perform a full sequence for we don't know how long
625 * it has been from power on till now.
627 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
628 reset = 1 << reset;
630 /* Keep RESET low for 50 ms */
631 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
632 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
633 bcm_mdelay(50);
635 /* Keep RESET high for at least 20 ms */
636 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
637 bcm_mdelay(20);
638 } else {
639 /* In case we need it */
640 idx = si_coreidx(sih);
642 if (si_setcore(sih, ROBO_CORE_ID, 0)) {
643 /* If we have an internal robo core, reset it using si_core_reset */
644 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
645 si_core_reset(sih, 0, 0);
646 robo->corerev = si_corerev(sih);
648 else if (sih->chip == BCM5356_CHIP_ID) {
649 /* Testing chipid is a temporary hack. We need to really
650 * figure out how to treat non-cores in ai chips.
652 robo->corerev = 3;
654 else {
655 mii_rreg(robo, PAGE_STATUS, REG_STATUS_REV, &robo->corerev, 1);
657 si_setcoreidx(sih, idx);
658 ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev));
661 if (miird && miiwr) {
662 uint16 tmp;
663 int rc, retry_count = 0;
665 /* Read the PHY ID */
666 tmp = miird(h, PSEUDO_PHYAD, 2);
668 /* WAR: Enable mdc/mdio access to the switch registers. Unless
669 * a write to bit 0 of pseudo phy register 16 is done we are
670 * unable to talk to the switch on a customer ref design.
672 if (tmp == 0xffff) {
673 miiwr(h, PSEUDO_PHYAD, 16, 1);
674 tmp = miird(h, PSEUDO_PHYAD, 2);
677 if (tmp != 0xffff) {
678 do {
679 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID,
680 &robo->devid, sizeof(uint16));
681 if (rc != 0)
682 break;
683 retry_count++;
684 } while ((robo->devid == 0) && (retry_count < 10));
686 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n",
687 __FUNCTION__, rc ? "un" : "", robo->devid));
688 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
689 robo->ops = &mdcmdio;
690 if ((rc != 0) || (robo->devid == 0)) {
691 ET_MSG(("%s: error reading devid, assuming 5325e\n",
692 __FUNCTION__));
693 robo->devid = DEVID5325;
696 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
699 if ((robo->devid == DEVID5395) ||
700 (robo->devid == DEVID5397) ||
701 (robo->devid == DEVID5398)) {
702 uint8 srst_ctrl;
704 /* If it is a 539x switch, use the soft reset register */
705 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
707 /* Reset the 539x switch core and register file */
708 srst_ctrl = 0x83;
709 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
710 bcm_mdelay(500); /* Gemtek: for reset issue */
711 srst_ctrl = 0x00;
712 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
715 /* Enable switch leds */
716 if (sih->chip == BCM5356_CHIP_ID) {
717 si_pmu_chipcontrol(sih, 2, (1 << 25), (1 << 25));
718 } else if ((sih->chip == BCM5357_CHIP_ID) || (sih->chip == BCM53572_CHIP_ID)) {
719 uint32 led_gpios = 0;
720 char *var;
722 if ((sih->chippkg != BCM47186_PKG_ID) && (sih->chippkg != BCM47188_PKG_ID))
723 led_gpios = 0x1f;
724 var = getvar(vars, "et_swleds");
725 if (var)
726 led_gpios = bcm_strtoul(var, NULL, 0);
727 if (led_gpios)
728 si_pmu_chipcontrol(sih, 2, (0x3ff << 8), (led_gpios << 8));
731 #ifndef _CFE_
732 if (!robo->ops) {
733 int mosi, miso, ss, sck;
735 robo->ops = &spigpio;
736 robo->devid = DEVID5325;
738 /* Init GPIO mapping. Default 2, 3, 4, 5 */
739 ss = getgpiopin(vars, "robo_ss", 2);
740 if (ss == GPIO_PIN_NOTDEFINED) {
741 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
742 goto error;
744 robo->ss = 1 << ss;
745 sck = getgpiopin(vars, "robo_sck", 3);
746 if (sck == GPIO_PIN_NOTDEFINED) {
747 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
748 goto error;
750 robo->sck = 1 << sck;
751 mosi = getgpiopin(vars, "robo_mosi", 4);
752 if (mosi == GPIO_PIN_NOTDEFINED) {
753 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
754 goto error;
756 robo->mosi = 1 << mosi;
757 miso = getgpiopin(vars, "robo_miso", 5);
758 if (miso == GPIO_PIN_NOTDEFINED) {
759 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
760 goto error;
762 robo->miso = 1 << miso;
763 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
764 ss, sck, mosi, miso));
766 #endif /* _CFE_ */
768 /* sanity check */
769 ASSERT(robo->ops);
770 ASSERT(robo->ops->write_reg);
771 ASSERT(robo->ops->read_reg);
772 ASSERT((robo->devid == DEVID5325) ||
773 (robo->devid == DEVID5395) ||
774 (robo->devid == DEVID5397) ||
775 (robo->devid == DEVID5398) ||
776 (robo->devid == DEVID53115) ||
777 (robo->devid == DEVID53125));
779 #ifndef _CFE_
780 /* nvram variable switch_mode controls the power save mode on the switch
781 * set the default value in the beginning
783 robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual");
784 robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto");
786 /* Determining what all phys need to be included in
787 * power save operation
789 et1port = getvar(vars, "et1mdcport");
790 if (et1port)
791 mdcport = bcm_atoi(et1port);
793 et1phyaddr = getvar(vars, "et1phyaddr");
794 if (et1phyaddr)
795 phyaddr = bcm_atoi(et1phyaddr);
797 if ((mdcport == 0) && (phyaddr == 4))
798 /* For 5325F switch we need to do only phys 0-3 */
799 robo->pwrsave_phys = 0xf;
800 else
801 /* By default all 5 phys are put into power save if there is no link */
802 robo->pwrsave_phys = 0x1f;
803 #endif /* _CFE_ */
805 #ifdef PLC
806 /* See if one of the ports is connected to plc chipset */
807 robo->plc_hw = (getvar(vars, "plc_vifs") != NULL);
808 #endif /* PLC */
810 return robo;
812 #ifndef _CFE_
813 error:
814 bcm_robo_detach(robo);
815 return NULL;
816 #endif /* _CFE_ */
819 /* Release access to the RoboSwitch */
820 void
821 bcm_robo_detach(robo_info_t *robo)
823 MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
826 /* Enable the device and set it to a known good state */
828 bcm_robo_enable_device(robo_info_t *robo)
830 uint8 reg_offset, reg_val;
831 int ret = 0;
832 #ifdef PLC
833 uint32 val32;
834 #endif /* PLC */
836 /* Enable management interface access */
837 if (robo->ops->enable_mgmtif)
838 robo->ops->enable_mgmtif(robo);
840 if (robo->devid == DEVID5398) {
841 /* Disable unused ports: port 6 and 7 */
842 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
843 /* Set bits [1:0] to disable RX and TX */
844 reg_val = 0x03;
845 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
846 sizeof(reg_val));
850 if (robo->devid == DEVID5325) {
851 /* Must put the switch into Reverse MII mode! */
853 /* MII port state override (page 0 register 14) */
854 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
856 /* Bit 4 enables reverse MII mode */
857 if (!(reg_val & (1 << 4))) {
858 /* Enable RvMII */
859 reg_val |= (1 << 4);
860 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
861 sizeof(reg_val));
863 /* Read back */
864 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
865 sizeof(reg_val));
866 if (!(reg_val & (1 << 4))) {
867 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
868 ret = -1;
873 #ifdef PLC
874 if (robo->plc_hw) {
875 val32 = 0x100002;
876 robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_ATCR, &val32, sizeof(val32));
878 #endif /* PLC */
880 /* Disable management interface access */
881 if (robo->ops->disable_mgmtif)
882 robo->ops->disable_mgmtif(robo);
884 return ret;
887 /* Port flags */
888 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
889 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
890 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
892 /* port descriptor */
893 typedef struct {
894 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
895 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
896 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
897 uint8 cpu; /* is this cpu port? */
898 } pdesc_t;
900 pdesc_t pdesc97[] = {
901 /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */
902 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
903 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
904 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
905 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
906 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
907 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
908 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
909 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
910 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
913 pdesc_t pdesc25[] = {
914 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
915 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
916 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
917 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
918 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
919 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
922 /* Configure the VLANs */
924 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
926 uint8 val8;
927 uint16 val16;
928 uint32 val32;
929 pdesc_t *pdesc;
930 int pdescsz;
931 uint16 vid, vid0;
932 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
934 /* Enable management interface access */
935 if (robo->ops->enable_mgmtif)
936 robo->ops->enable_mgmtif(robo);
938 /* setup global vlan configuration */
939 /* VLAN Control 0 Register (Page 0x34, Address 0) */
940 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
941 val8 |= ((1 << 7) | /* enable 802.1Q VLAN */
942 (3 << 5)); /* individual VLAN learning mode */
943 if (robo->devid == DEVID5325)
944 val8 &= ~(1 << 1); /* must clear reserved bit 1 */
945 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
946 /* VLAN Control 1 Register (Page 0x34, Address 1) */
947 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
948 val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */
949 (1 << 3)); /* enable RSV multicast V Untagmap */
950 if ((robo->devid == DEVID5325) &&
951 ((robo->sih->chip != BCM5357_CHIP_ID) || (robo->sih->chippkg != BCM5358_PKG_ID)))
952 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
953 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
955 /* Jumbo Frame control refister (Page 0x40, Address 0x01) */
956 /* Added by Yen */
957 robo->ops->read_reg(robo, PAGE_JUMBO, REG_JUMBO_CTRL, &val16, sizeof(val16));
958 val16 &= ~((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 8));
959 if (nvram_match("jumbo_frame_enable", "1"))
960 val16 |= ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 8));
961 robo->ops->write_reg(robo, PAGE_JUMBO, REG_JUMBO_CTRL, &val16, sizeof(val16));
963 arl_entry[0] = mac_addr[5];
964 arl_entry[1] = mac_addr[4];
965 arl_entry[2] = mac_addr[3];
966 arl_entry[3] = mac_addr[2];
967 arl_entry[4] = mac_addr[1];
968 arl_entry[5] = mac_addr[0];
970 if (robo->devid == DEVID5325) {
971 /* Init the entry 1 of the bin */
972 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1,
973 arl_entry1, sizeof(arl_entry1));
974 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1,
975 arl_entry1, 1);
977 /* Init the entry 0 of the bin */
978 arl_entry[6] = 0x8; /* Port Id: MII */
979 arl_entry[7] = 0xc0; /* Static Entry, Valid */
981 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
982 arl_entry, sizeof(arl_entry));
983 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
984 arl_entry, ETHER_ADDR_LEN);
986 /* VLAN Control 4 Register (Page 0x34, Address 4) */
987 val8 = (1 << 6); /* drop frame with VID violation */
988 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
990 /* VLAN Control 5 Register (Page 0x34, Address 5) */
991 val8 = (1 << 3); /* drop frame when miss V table */
992 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
994 pdesc = pdesc25;
995 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
996 } else {
997 /* Initialize the MAC Addr Index Register */
998 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
999 arl_entry, ETHER_ADDR_LEN);
1001 pdesc = pdesc97;
1002 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1005 vid0 = getintvar(robo->vars, "vlan0tag");
1007 /* setup each vlan. max. 16 vlans. */
1008 /* force vlan id to be equal to vlan number */
1009 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1010 char vlanports[] = "vlanXXXXports";
1011 char port[] = "XXXX", *ports, *next, *cur;
1012 uint32 untag = 0;
1013 uint32 member = 0;
1014 int pid, len;
1016 /* no members if VLAN id is out of limitation */
1017 if (vid > VLAN_MAXVID)
1018 goto vlan_setup;
1020 /* get vlan member ports from nvram */
1021 sprintf(vlanports, "vlan%dports", vid);
1022 ports = getvar(robo->vars, vlanports);
1024 /* In 539x vid == 0 us invalid?? */
1025 if ((robo->devid != DEVID5325) && (robo->devid != DEVID5397) && (vid == 0)) {
1026 if (ports)
1027 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
1028 continue;
1031 /* Gemtek: to distinguish switch 5397 and 5395 */
1032 if ((robo->devid == DEVID5395) && (vid == 1)) {
1033 sprintf(vlanports, "vlan0ports");
1034 ports = getvar(robo->vars, vlanports);
1035 if (!ports || (*ports == 0) || !strcmp(ports, " ")) {
1036 ET_ERROR(("BCM5395: already booted, use internal fixup\n"));
1037 sprintf(vlanports, "vlan1ports");
1038 ports = getvar(robo->vars, vlanports);
1040 else {
1041 ET_ERROR(("Configure vlan1 (%s) instead of vlan0 for BCM5395\n", ports));
1045 /* disable this vlan if not defined */
1046 if (!ports)
1047 goto vlan_setup;
1050 * setup each port in the vlan. cpu port needs special handing
1051 * (with or without output tagging) to support linux/pmon/cfe.
1053 for (cur = ports; cur; cur = next) {
1054 /* tokenize the port list */
1055 while (*cur == ' ')
1056 cur ++;
1057 next = bcmstrstr(cur, " ");
1058 len = next ? next - cur : strlen(cur);
1059 if (!len)
1060 break;
1061 if (len > sizeof(port) - 1)
1062 len = sizeof(port) - 1;
1063 strncpy(port, cur, len);
1064 port[len] = 0;
1066 /* make sure port # is within the range */
1067 pid = bcm_atoi(port);
1068 if (pid >= pdescsz) {
1069 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
1070 "of range[0-%d]\n", pid, vid, pdescsz));
1071 continue;
1074 /* build VLAN registers values */
1075 #ifndef _CFE_
1076 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1077 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
1078 #endif
1079 untag |= pdesc[pid].untag;
1081 member |= pdesc[pid].member;
1083 /* set port tag - applies to untagged ingress frames */
1084 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
1085 #ifdef _CFE_
1086 #define FL FLAG_LAN
1087 #else
1088 #define FL FLAG_UNTAG
1089 #endif /* _CFE_ */
1090 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1091 strchr(port, FL)) {
1092 val16 = ((0 << 13) | /* priority - always 0 */
1093 vid0 | vid); /* vlan id */
1094 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
1095 &val16, sizeof(val16));
1099 /* Add static ARL entries */
1100 if (robo->devid == DEVID5325) {
1101 val8 = vid;
1102 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0,
1103 &val8, sizeof(val8));
1104 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1105 &val8, sizeof(val8));
1107 /* Write the entry */
1108 val8 = 0x80;
1109 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1110 &val8, sizeof(val8));
1111 /* Wait for write to complete */
1112 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1113 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1114 100 /* usec */);
1115 } else {
1116 /* Set the VLAN Id in VLAN ID Index Register */
1117 val8 = vid;
1118 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1119 &val8, sizeof(val8));
1121 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1122 * Register.
1124 arl_entry[6] = vid;
1125 arl_entry[7] = 0x0;
1126 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
1127 arl_entry, sizeof(arl_entry));
1129 /* Set the Static bit , Valid bit and Port ID fields in
1130 * ARL Table Data Entry 0 Register
1132 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1133 val32 = 0x18008;
1134 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1135 &val32, sizeof(val32));
1136 } else {
1137 val16 = 0xc008;
1138 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1139 &val16, sizeof(val16));
1142 /* Clear the ARL_R/W bit and set the START/DONE bit in
1143 * the ARL Read/Write Control Register.
1145 val8 = 0x80;
1146 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1147 &val8, sizeof(val8));
1148 /* Wait for write to complete */
1149 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1150 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1151 100 /* usec */);
1154 vlan_setup:
1155 /* setup VLAN ID and VLAN memberships */
1157 val32 = (untag | /* untag enable */
1158 member); /* vlan members */
1159 if (robo->sih->chip == BCM5365_CHIP_ID) {
1160 /* VLAN Write Register (Page 0x34, Address 0x0A) */
1161 val32 = ((1 << 14) | /* valid write */
1162 (untag << 1) | /* untag enable */
1163 member); /* vlan members */
1164 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE_5365, &val32,
1165 sizeof(val32));
1166 /* VLAN Table Access Register (Page 0x34, Address 0x08) */
1167 val16 = ((1 << 13) | /* start command */
1168 (1 << 12) | /* write state */
1169 vid0 | vid); /* vlan id */
1170 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS_5365, &val16,
1171 sizeof(val16));
1172 } else if (robo->devid == DEVID5325) {
1173 if (robo->corerev < 3) {
1174 val32 |= ((1 << 20) | /* valid write */
1175 ((vid0 >> 4) << 12)); /* vlan id bit[11:4] */
1176 } else {
1177 val32 |= ((1 << 24) | /* valid write */
1178 ((vid0 | vid) << 12)); /* vlan id bit[11:4] */
1180 ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32));
1182 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1183 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1184 sizeof(val32));
1185 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1186 val16 = ((1 << 13) | /* start command */
1187 (1 << 12) | /* write state */
1188 vid0 | vid); /* vlan id */
1189 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1190 sizeof(val16));
1191 } else {
1192 uint8 vtble, vtbli, vtbla;
1194 if ((robo->devid == DEVID5395) ||
1195 (robo->devid == DEVID53115) ||
1196 (robo->devid == DEVID53125)) {
1197 vtble = REG_VTBL_ENTRY_5395;
1198 vtbli = REG_VTBL_INDX_5395;
1199 vtbla = REG_VTBL_ACCESS_5395;
1200 } else {
1201 vtble = REG_VTBL_ENTRY;
1202 vtbli = REG_VTBL_INDX;
1203 vtbla = REG_VTBL_ACCESS;
1206 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1207 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1208 sizeof(val32));
1209 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1210 val16 = vid0 | vid; /* vlan id */
1211 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1212 sizeof(val16));
1214 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1215 val8 = ((1 << 7) | /* start command */
1216 0); /* write */
1217 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1218 sizeof(val8));
1222 if (robo->devid == DEVID5325) {
1223 /* setup priority mapping - applies to tagged ingress frames */
1224 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1225 val32 = ((0 << 0) | /* 0 -> 0 */
1226 (1 << 3) | /* 1 -> 1 */
1227 (2 << 6) | /* 2 -> 2 */
1228 (3 << 9) | /* 3 -> 3 */
1229 (4 << 12) | /* 4 -> 4 */
1230 (5 << 15) | /* 5 -> 5 */
1231 (6 << 18) | /* 6 -> 6 */
1232 (7 << 21)); /* 7 -> 7 */
1233 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1236 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1237 /* Configure the priority system to use to determine the TC of
1238 * ingress frames. Use DiffServ TC mapping, otherwise 802.1p
1239 * TC mapping, otherwise MAC based TC mapping.
1241 val8 = ((0 << 6) | /* Disable port based QoS */
1242 (2 << 2)); /* QoS priority selection */
1243 robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8));
1245 /* Configure tx queues scheduling mechanism */
1246 val8 = (3 << 0); /* Strict priority */
1247 robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8));
1249 /* Enable 802.1p Priority to TC mapping for individual ports */
1250 val16 = 0x11f;
1251 robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16));
1253 /* Configure the TC to COS mapping. This determines the egress
1254 * transmit queue.
1256 val16 = ((1 << 0) | /* Pri 0 mapped to TXQ 1 */
1257 (0 << 2) | /* Pri 1 mapped to TXQ 0 */
1258 (0 << 4) | /* Pri 2 mapped to TXQ 0 */
1259 (1 << 6) | /* Pri 3 mapped to TXQ 1 */
1260 (2 << 8) | /* Pri 4 mapped to TXQ 2 */
1261 (2 << 10) | /* Pri 5 mapped to TXQ 2 */
1262 (3 << 12) | /* Pri 6 mapped to TXQ 3 */
1263 (3 << 14)); /* Pri 7 mapped to TXQ 3 */
1264 robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16));
1267 /* Disable management interface access */
1268 if (robo->ops->disable_mgmtif)
1269 robo->ops->disable_mgmtif(robo);
1271 return 0;
1274 /* Enable switching/forwarding */
1276 bcm_robo_enable_switch(robo_info_t *robo)
1278 int i, max_port_ind, ret = 0;
1279 uint8 val8;
1281 /* Enable management interface access */
1282 if (robo->ops->enable_mgmtif)
1283 robo->ops->enable_mgmtif(robo);
1285 /* Switch Mode register (Page 0, Address 0x0B) */
1286 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1288 /* Bit 1 enables switching/forwarding */
1289 if (!(val8 & (1 << 1))) {
1290 /* Set unmanaged mode */
1291 val8 &= (~(1 << 0));
1293 /* Enable forwarding */
1294 val8 |= (1 << 1);
1295 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1297 /* Read back */
1298 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1299 if (!(val8 & (1 << 1))) {
1300 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1301 ret = -1;
1304 /* No spanning tree for unmanaged mode */
1305 val8 = 0;
1306 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 :
1307 (robo->devid == DEVID53115) ? REG_CTRL_PORT5 : REG_CTRL_PORT4);
1308 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1309 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1312 /* No spanning tree on IMP port too */
1313 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8));
1316 if (robo->devid == DEVID53125) {
1317 /* Over ride IMP port status to make it link by default */
1318 val8 = 0;
1319 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1320 val8 |= 0x81; /* Make Link pass and override it. */
1321 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1324 if (robo->sih->chip == BCM5365_CHIP_ID) {
1325 /* Enable WAN port (#0) on the asus wl-500g deluxe boxes */
1326 val8 = 0;
1327 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0, &val8, sizeof(val8));
1330 /* Disable management interface access */
1331 if (robo->ops->disable_mgmtif)
1332 robo->ops->disable_mgmtif(robo);
1334 return ret;
1337 #ifdef BCMDBG
1338 void
1339 robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b)
1341 uint8 val8;
1342 uint16 val16;
1343 uint32 val32;
1344 pdesc_t *pdesc;
1345 int pdescsz;
1346 int i;
1348 bcm_bprintf(b, "%s:\n", robo->ops->desc);
1349 if (robo->miird == NULL) {
1350 bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n",
1351 robo->ss, robo->sck, robo->mosi, robo->miso);
1354 /* Enable management interface access */
1355 if (robo->ops->enable_mgmtif)
1356 robo->ops->enable_mgmtif(robo);
1358 /* Dump registers interested */
1359 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1360 bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8);
1361 if (robo->devid == DEVID5325) {
1362 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1363 bcm_bprintf(b, "(0x00,0x0E)MII port state override regsiter: 0x%02x\n", val8);
1365 if (robo->miird == NULL)
1366 goto exit;
1367 if (robo->devid == DEVID5325) {
1368 pdesc = pdesc25;
1369 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1370 } else {
1371 pdesc = pdesc97;
1372 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1375 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1376 bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8);
1377 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1378 bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8);
1379 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1380 if (robo->devid == DEVID5325) {
1381 bcm_bprintf(b, "(0x34,0x04)VLAN control 4 register: 0x%02x\n", val8);
1382 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1383 bcm_bprintf(b, "(0x34,0x05)VLAN control 5 register: 0x%02x\n", val8);
1385 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1386 bcm_bprintf(b, "(0x34,0x20)Prio Re-map: 0x%08x\n", val32);
1388 for (i = 0; i <= VLAN_MAXVID; i++) {
1389 val16 = (1 << 13) /* start command */
1390 | i; /* vlan id */
1391 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1392 sizeof(val16));
1393 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_READ, &val32, sizeof(val32));
1394 bcm_bprintf(b, "(0x34,0xc)VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1395 i, (val32 & 0x0fc0) >> 6, (val32 & 0x003f));
1398 } else {
1399 for (i = 0; i <= VLAN_MAXVID; i++) {
1400 /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62) */
1401 val16 = i; /* vlan id */
1402 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_INDX, &val16,
1403 sizeof(val16));
1404 /* VLAN Table Access Register (Page 0x34, Address 0x60) */
1405 val8 = ((1 << 7) | /* start command */
1406 1); /* read */
1407 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ACCESS, &val8,
1408 sizeof(val8));
1409 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66) */
1410 robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_ENTRY, &val32,
1411 sizeof(val32));
1412 bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1413 i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff));
1416 for (i = 0; i < pdescsz; i++) {
1417 robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16));
1418 bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16);
1421 exit:
1422 /* Disable management interface access */
1423 if (robo->ops->disable_mgmtif)
1424 robo->ops->disable_mgmtif(robo);
1426 #endif /* BCMDBG */
1428 #ifndef _CFE_
1430 * Update the power save configuration for ports that changed link status.
1432 void
1433 robo_power_save_mode_update(robo_info_t *robo)
1435 uint phy;
1437 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1438 if (robo->pwrsave_mode_auto & (1 << phy)) {
1439 ET_MSG(("%s: set port %d to auto mode\n",
1440 __FUNCTION__, phy));
1441 robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy);
1445 return;
1448 static int32
1449 robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy)
1451 uint16 val16;
1453 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1454 /* For 53115 0x1C is the MII address of the auto power
1455 * down register. Bit 5 is enabling the mode
1456 * bits has the following purpose
1457 * 15 - write enable 10-14 shadow register select 01010 for
1458 * auto power 6-9 reserved 5 auto power mode enable
1459 * 4 sleep timer select : 1 means 5.4 sec
1460 * 0-3 wake up timer select: 0xF 1.26 sec
1462 val16 = 0xa800;
1463 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, val16);
1464 } else if (robo->sih->chip == BCM5356_CHIP_ID) {
1465 /* To disable auto power down mode
1466 * clear bit 5 of Aux Status 2 register
1467 * (Shadow reg 0x1b). Shadow register
1468 * access is enabled by writing
1469 * 1 to bit 7 of MII register 0x1f.
1471 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1472 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1473 (val16 | (1 << 7)));
1475 /* Disable auto power down by clearing
1476 * bit 5 of to Aux Status 2 reg.
1478 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1479 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1480 (val16 & ~(1 << 5)));
1482 /* Undo shadow access */
1483 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1484 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1485 (val16 & ~(1 << 7)));
1486 } else
1487 return -1;
1489 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_AUTO;
1491 return 0;
1494 static int32
1495 robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy)
1497 uint8 val8;
1498 uint16 val16;
1500 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125) ||
1501 (robo->sih->chip == BCM5356_CHIP_ID)) {
1502 /* For 53115 0x0 is the MII control register
1503 * Bit 11 is the power down mode bit
1505 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1506 val16 &= 0xf7ff;
1507 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16);
1508 } else if (robo->devid == DEVID5325) {
1509 if (phy == 0)
1510 return -1;
1511 /* For 5325 page 0x00 address 0x0F is the power down
1512 * mode register. Bits 1-4 determines which of the
1513 * phys are enabled for this mode
1515 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1516 &val8, sizeof(val8));
1517 val8 &= ~(0x1 << phy);
1518 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1519 &val8, sizeof(val8));
1520 } else
1521 return -1;
1523 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_MANUAL;
1525 return 0;
1529 * Function which periodically checks the power save mode on the switch
1531 int32
1532 robo_power_save_toggle(robo_info_t *robo, int32 normal)
1534 int32 phy;
1535 uint16 link_status;
1538 /* read the link status of all ports */
1539 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1540 &link_status, sizeof(uint16));
1541 link_status &= 0x1f;
1543 /* Take the phys out of the manual mode first so that link status
1544 * can be checked. Once out of that mode check the link status
1545 * and if any of the link is up do not put that phy into
1546 * manual power save mode
1548 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1549 /* When auto+manual modes are enabled we toggle between
1550 * manual and auto modes. When only manual mode is enabled
1551 * we toggle between manual and normal modes. When only
1552 * auto mode is enabled there is no need to do anything
1553 * here since auto mode is one time config.
1555 if ((robo->pwrsave_phys & (1 << phy)) &&
1556 (robo->pwrsave_mode_manual & (1 << phy))) {
1557 if (!normal) {
1558 /* Take the port out of the manual mode */
1559 robo_power_save_mode_clear_manual(robo, phy);
1560 } else {
1561 /* If the link is down put it back to manual else
1562 * remain in the current state
1564 if (!(link_status & (1 << phy))) {
1565 ET_MSG(("%s: link down, set port %d to man mode\n",
1566 __FUNCTION__, phy));
1567 robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy);
1573 return 0;
1577 * Switch the ports to normal mode.
1579 static int32
1580 robo_power_save_mode_normal(robo_info_t *robo, int32 phy)
1582 int32 error = 0;
1584 /* If the phy in the power save mode come out of it */
1585 switch (robo->pwrsave_mode_phys[phy]) {
1586 case ROBO_PWRSAVE_AUTO_MANUAL:
1587 case ROBO_PWRSAVE_AUTO:
1588 error = robo_power_save_mode_clear_auto(robo, phy);
1589 if ((error == -1) ||
1590 (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO))
1591 break;
1593 case ROBO_PWRSAVE_MANUAL:
1594 error = robo_power_save_mode_clear_manual(robo, phy);
1595 break;
1597 default:
1598 break;
1601 return error;
1605 * Switch all the inactive ports to auto power down mode.
1607 static int32
1608 robo_power_save_mode_auto(robo_info_t *robo, int32 phy)
1610 uint16 val16;
1612 /* If the switch supports auto power down enable that */
1613 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1614 /* For 53115 0x1C is the MII address of the auto power
1615 * down register. Bit 5 is enabling the mode
1616 * bits has the following purpose
1617 * 15 - write enable 10-14 shadow register select 01010 for
1618 * auto power 6-9 reserved 5 auto power mode enable
1619 * 4 sleep timer select : 1 means 5.4 sec
1620 * 0-3 wake up timer select: 0xF 1.26 sec
1622 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA83F);
1623 } else if (robo->sih->chip == BCM5356_CHIP_ID) {
1624 /* To enable auto power down mode set bit 5 of
1625 * Auxillary Status 2 register (Shadow reg 0x1b)
1626 * Shadow register access is enabled by writing
1627 * 1 to bit 7 of MII register 0x1f.
1629 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1630 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1631 (val16 | (1 << 7)));
1633 /* Enable auto power down by writing to Auxillary
1634 * Status 2 reg.
1636 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1637 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1638 (val16 | (1 << 5)));
1640 /* Undo shadow access */
1641 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1642 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1643 (val16 & ~(1 << 7)));
1644 } else
1645 return -1;
1647 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_AUTO;
1649 return 0;
1653 * Switch all the inactive ports to manual power down mode.
1655 static int32
1656 robo_power_save_mode_manual(robo_info_t *robo, int32 phy)
1658 uint8 val8;
1659 uint16 val16;
1661 /* For both 5325 and 53115 the link status register is the same */
1662 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1663 &val16, sizeof(val16));
1664 if (val16 & (0x1 << phy))
1665 return 0;
1667 /* If the switch supports manual power down enable that */
1668 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125) ||
1669 (robo->sih->chip == BCM5356_CHIP_ID)) {
1670 /* For 53115 0x0 is the MII control register bit 11 is the
1671 * power down mode bit
1673 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1674 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16 | 0x800);
1675 } else if (robo->devid == DEVID5325) {
1676 if (phy == 0)
1677 return -1;
1678 /* For 5325 page 0x00 address 0x0F is the power down mode
1679 * register. Bits 1-4 determines which of the phys are enabled
1680 * for this mode
1682 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1683 sizeof(val8));
1684 val8 |= (1 << phy);
1685 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1686 sizeof(val8));
1687 } else
1688 return -1;
1690 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_MANUAL;
1692 return 0;
1696 * Set power save modes on the robo switch
1698 int32
1699 robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy)
1701 int32 error = -1;
1703 if (phy > MAX_NO_PHYS) {
1704 ET_ERROR(("Passed parameter phy is out of range\n"));
1705 return -1;
1708 /* Enable management interface access */
1709 if (robo->ops->enable_mgmtif)
1710 robo->ops->enable_mgmtif(robo);
1712 switch (mode) {
1713 case ROBO_PWRSAVE_NORMAL:
1714 /* If the phy in the power save mode come out of it */
1715 error = robo_power_save_mode_normal(robo, phy);
1716 break;
1718 case ROBO_PWRSAVE_AUTO_MANUAL:
1719 /* If the switch supports auto and manual power down
1720 * enable both of them
1722 case ROBO_PWRSAVE_AUTO:
1723 error = robo_power_save_mode_auto(robo, phy);
1724 if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO))
1725 break;
1727 case ROBO_PWRSAVE_MANUAL:
1728 error = robo_power_save_mode_manual(robo, phy);
1729 break;
1731 default:
1732 break;
1735 /* Disable management interface access */
1736 if (robo->ops->disable_mgmtif)
1737 robo->ops->disable_mgmtif(robo);
1739 return error;
1743 * Get the current power save mode of the switch ports.
1745 int32
1746 robo_power_save_mode_get(robo_info_t *robo, int32 phy)
1748 ASSERT(robo);
1750 if (phy >= MAX_NO_PHYS)
1751 return -1;
1753 return robo->pwrsave_mode_phys[phy];
1757 * Configure the power save mode for the switch ports.
1759 int32
1760 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy)
1762 int32 error;
1764 ASSERT(robo);
1766 if (phy >= MAX_NO_PHYS)
1767 return -1;
1769 error = robo_power_save_mode(robo, mode, phy);
1771 if (error)
1772 return error;
1774 if (mode == ROBO_PWRSAVE_NORMAL) {
1775 robo->pwrsave_mode_manual &= ~(1 << phy);
1776 robo->pwrsave_mode_auto &= ~(1 << phy);
1777 } else if (mode == ROBO_PWRSAVE_AUTO) {
1778 robo->pwrsave_mode_auto |= (1 << phy);
1779 robo->pwrsave_mode_manual &= ~(1 << phy);
1780 robo_power_save_mode_clear_manual(robo, phy);
1781 } else if (mode == ROBO_PWRSAVE_MANUAL) {
1782 robo->pwrsave_mode_manual |= (1 << phy);
1783 robo->pwrsave_mode_auto &= ~(1 << phy);
1784 robo_power_save_mode_clear_auto(robo, phy);
1785 } else {
1786 robo->pwrsave_mode_auto |= (1 << phy);
1787 robo->pwrsave_mode_manual |= (1 << phy);
1790 return 0;
1792 #endif /* _CFE_ */
1794 #ifdef PLC
1795 void
1796 robo_plc_hw_init(robo_info_t *robo)
1798 uint8 val8;
1800 ASSERT(robo);
1802 if (!robo->plc_hw)
1803 return;
1805 /* Enable management interface access */
1806 if (robo->ops->enable_mgmtif)
1807 robo->ops->enable_mgmtif(robo);
1809 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1810 /* Fix the duplex mode and speed for Port 5 */
1811 val8 = ((1 << 6) | (1 << 2) | 3);
1812 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIP5O, &val8, sizeof(val8));
1813 } else if ((robo->sih->chip == BCM5357_CHIP_ID) &&
1814 (robo->sih->chippkg == BCM5358_PKG_ID)) {
1815 /* Fix the duplex mode and speed for Port 4 (MII port). Force
1816 * full duplex mode, enable flow control and set speed to 100.
1818 si_pmu_chipcontrol(robo->sih, 2, (1 << 1) | (1 << 2) | (1 << 3),
1819 (1 << 1) | (1 << 2) | (1 << 3));
1822 /* Disable management interface access */
1823 if (robo->ops->disable_mgmtif)
1824 robo->ops->disable_mgmtif(robo);
1826 ET_MSG(("%s: Configured PLC MII interface\n", __FUNCTION__));
1828 #endif /* PLC */