K2.6 patches and update.
[tomato.git] / release / src-rt / shared / bcmrobo.c
blobad354de24443ca5a9726b0d3ca5a88109fbe8eff
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 VID_MAP_DBG
45 #define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \
46 ((len) == 2) ? *((uint16 *)(var)) : \
47 *((uint32 *)(var)))
50 * Switch can be programmed through SPI interface, which
51 * has a rreg and a wreg functions to read from and write to
52 * registers.
55 /* MII access registers */
56 #define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
57 #define REG_MII_CTRL 0x00 /* 53115 MII control register */
58 #define REG_MII_PAGE 0x10 /* MII Page register */
59 #define REG_MII_ADDR 0x11 /* MII Address register */
60 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
61 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
62 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
63 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
64 #define REG_MII_AUX_STATUS2 0x1b /* Auxiliary status 2 register */
65 #define REG_MII_AUTO_PWRDOWN 0x1c /* 53115 Auto power down register */
66 #define REG_MII_BRCM_TEST 0x1f /* Broadcom test register */
68 /* Page numbers */
69 #define PAGE_CTRL 0x00 /* Control page */
70 #define PAGE_STATUS 0x01 /* Status page */
71 #define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
72 #define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
73 #define PAGE_VLAN 0x34 /* VLAN page */
74 #define PAGE_JUMBO 0x40 /* JUMBO frame 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 */
90 #define REG_CTRL_MIIP5O 0x5d /* 53115: Port State Override register for port 5 */
92 /* Management/Mirroring Registers */
93 #define REG_MMR_ATCR 0x06 /* Aging Time Control register */
94 #define REG_MMR_MCCR 0x10 /* Mirror Capture Control register */
95 #define REG_MMR_IMCR 0x12 /* Ingress Mirror Control register */
97 /* Status Page Registers */
98 #define REG_STATUS_LINK 0x00 /* Link Status Summary */
99 #define REG_STATUS_REV 0x50 /* Revision Register */
101 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
103 /* JUMBO Control Register */
104 #define REG_JUMBO_CTRL 0x01
105 #define REG_JUMBO_SIZE 0x05
107 /* VLAN page registers */
108 #define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
109 #define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
110 #define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
111 #define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
112 #define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
113 #define REG_VLAN_ACCESS_5365 0x08 /* 5365 VLAN Table Access register */
114 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
115 #define REG_VLAN_WRITE_5365 0x0A /* 5365 VLAN Write register */
116 #define REG_VLAN_READ 0x0C /* VLAN Read register */
117 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
118 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
119 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
120 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
121 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
122 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
123 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
124 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
125 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
126 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
128 #define VLAN_NUMVLANS 16 /* # of VLANs */
131 /* ARL/VLAN Table Access page registers */
132 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
133 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
134 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
135 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
136 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
137 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
138 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
139 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
140 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
141 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
142 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
143 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
144 #define REG_VTBL_PREG 0xFF /* Page Register */
145 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
146 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
147 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
148 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
149 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
150 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
152 #ifndef _CFE_
153 /* SPI registers */
154 #define REG_SPI_PAGE 0xff /* SPI Page register */
156 /* Access switch registers through GPIO/SPI */
158 /* Minimum timing constants */
159 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
160 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
161 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
163 /* misc. constants */
164 #define SPI_MAX_RETRY 100
166 /* Enable GPIO access to the chip */
167 static void
168 gpio_enable(robo_info_t *robo)
170 /* Enable GPIO outputs with SCK and MOSI low, SS high */
171 si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
172 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi,
173 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
176 /* Disable GPIO access to the chip */
177 static void
178 gpio_disable(robo_info_t *robo)
180 /* Disable GPIO outputs with all their current values */
181 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
184 /* Write a byte stream to the chip thru SPI */
185 static int
186 spi_write(robo_info_t *robo, uint8 *buf, uint len)
188 uint i;
189 uint8 mask;
191 /* Byte bang from LSB to MSB */
192 for (i = 0; i < len; i++) {
193 /* Bit bang from MSB to LSB */
194 for (mask = 0x80; mask; mask >>= 1) {
195 /* Clock low */
196 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
197 OSL_DELAY(SCK_EDGE_TIME);
199 /* Sample on rising edge */
200 if (mask & buf[i])
201 si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
202 else
203 si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY);
204 OSL_DELAY(MOSI_SETUP_TIME);
206 /* Clock high */
207 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
208 OSL_DELAY(SCK_EDGE_TIME);
212 return 0;
215 /* Read a byte stream from the chip thru SPI */
216 static int
217 spi_read(robo_info_t *robo, uint8 *buf, uint len)
219 uint i, timeout;
220 uint8 rack, mask, byte;
222 /* Timeout after 100 tries without RACK */
223 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
224 /* Bit bang from MSB to LSB */
225 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
226 /* Clock low */
227 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
228 OSL_DELAY(SCK_EDGE_TIME);
230 /* Sample on falling edge */
231 if (si_gpioin(robo->sih) & robo->miso)
232 byte |= mask;
234 /* Clock high */
235 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
236 OSL_DELAY(SCK_EDGE_TIME);
238 /* RACK when bit 0 is high */
239 if (!rack) {
240 rack = (byte & 1);
241 timeout--;
242 continue;
244 /* Byte bang from LSB to MSB */
245 buf[i] = byte;
246 i++;
249 if (timeout == 0) {
250 ET_ERROR(("spi_read: timeout"));
251 return -1;
254 return 0;
257 /* Enable/disable SPI access */
258 static void
259 spi_select(robo_info_t *robo, uint8 spi)
261 if (spi) {
262 /* Enable SPI access */
263 si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY);
264 } else {
265 /* Disable SPI access */
266 si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
268 OSL_DELAY(SS_SETUP_TIME);
272 /* Select chip and page */
273 static void
274 spi_goto(robo_info_t *robo, uint8 page)
276 uint8 reg8 = REG_SPI_PAGE; /* page select register */
277 uint8 cmd8;
279 /* Issue the command only when we are on a different page */
280 if (robo->page == page)
281 return;
283 robo->page = page;
285 /* Enable SPI access */
286 spi_select(robo, 1);
288 /* Select new page with CID 0 */
289 cmd8 = ((6 << 4) | /* normal SPI */
290 1); /* write */
291 spi_write(robo, &cmd8, 1);
292 spi_write(robo, &reg8, 1);
293 spi_write(robo, &page, 1);
295 /* Disable SPI access */
296 spi_select(robo, 0);
299 /* Write register thru SPI */
300 static int
301 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
303 int status = 0;
304 uint8 cmd8;
305 union {
306 uint8 val8;
307 uint16 val16;
308 uint32 val32;
309 } bytes;
311 /* validate value length and buffer address */
312 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
313 (len == 4 && !((int)val & 3)));
315 /* Select chip and page */
316 spi_goto(robo, page);
318 /* Enable SPI access */
319 spi_select(robo, 1);
321 /* Write with CID 0 */
322 cmd8 = ((6 << 4) | /* normal SPI */
323 1); /* write */
324 spi_write(robo, &cmd8, 1);
325 spi_write(robo, &addr, 1);
326 switch (len) {
327 case 1:
328 bytes.val8 = *(uint8 *)val;
329 break;
330 case 2:
331 bytes.val16 = htol16(*(uint16 *)val);
332 break;
333 case 4:
334 bytes.val32 = htol32(*(uint32 *)val);
335 break;
337 spi_write(robo, (uint8 *)val, len);
339 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
340 *(uint16 *)val, len));
341 /* Disable SPI access */
342 spi_select(robo, 0);
343 return status;
346 /* Read register thru SPI in fast SPI mode */
347 static int
348 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
350 int status = 0;
351 uint8 cmd8;
352 union {
353 uint8 val8;
354 uint16 val16;
355 uint32 val32;
356 } bytes;
358 /* validate value length and buffer address */
359 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
360 (len == 4 && !((int)val & 3)));
362 /* Select chip and page */
363 spi_goto(robo, page);
365 /* Enable SPI access */
366 spi_select(robo, 1);
368 /* Fast SPI read with CID 0 and byte offset 0 */
369 cmd8 = (1 << 4); /* fast SPI */
370 spi_write(robo, &cmd8, 1);
371 spi_write(robo, &addr, 1);
372 status = spi_read(robo, (uint8 *)&bytes, len);
373 switch (len) {
374 case 1:
375 *(uint8 *)val = bytes.val8;
376 break;
377 case 2:
378 *(uint16 *)val = ltoh16(bytes.val16);
379 break;
380 case 4:
381 *(uint32 *)val = ltoh32(bytes.val32);
382 break;
385 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
386 *(uint16 *)val, len));
388 /* Disable SPI access */
389 spi_select(robo, 0);
390 return status;
393 /* SPI/gpio interface functions */
394 static dev_ops_t spigpio = {
395 gpio_enable,
396 gpio_disable,
397 spi_wreg,
398 spi_rreg,
399 "SPI (GPIO)"
401 #endif /* _CFE_ */
404 /* Access switch registers through MII (MDC/MDIO) */
406 #define MII_MAX_RETRY 100
408 /* Write register thru MDC/MDIO */
409 static int
410 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
412 uint16 cmd16, val16;
413 void *h = robo->h;
414 int i;
415 uint8 *ptr = (uint8 *)val;
417 /* validate value length and buffer address */
418 ASSERT(len == 1 || len == 6 || len == 8 ||
419 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
421 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
422 VARG(val, len), len));
424 /* set page number - MII register 0x10 */
425 if (robo->page != page) {
426 cmd16 = ((page << 8) | /* page number */
427 1); /* mdc/mdio access enable */
428 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
429 robo->page = page;
432 switch (len) {
433 case 8:
434 val16 = ptr[7];
435 val16 = ((val16 << 8) | ptr[6]);
436 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
437 /* FALLTHRU */
439 case 6:
440 val16 = ptr[5];
441 val16 = ((val16 << 8) | ptr[4]);
442 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
443 val16 = ptr[3];
444 val16 = ((val16 << 8) | ptr[2]);
445 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
446 val16 = ptr[1];
447 val16 = ((val16 << 8) | ptr[0]);
448 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
449 break;
451 case 4:
452 val16 = (uint16)((*(uint32 *)val) >> 16);
453 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
454 val16 = (uint16)(*(uint32 *)val);
455 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
456 break;
458 case 2:
459 val16 = *(uint16 *)val;
460 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
461 break;
463 case 1:
464 val16 = *(uint8 *)val;
465 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
466 break;
469 /* set register address - MII register 0x11 */
470 cmd16 = ((reg << 8) | /* register address */
471 1); /* opcode write */
472 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
474 /* is operation finished? */
475 for (i = MII_MAX_RETRY; i > 0; i --) {
476 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
477 if ((val16 & 3) == 0)
478 break;
481 /* timed out */
482 if (!i) {
483 ET_ERROR(("mii_wreg: timeout"));
484 return -1;
486 return 0;
489 /* Read register thru MDC/MDIO */
490 static int
491 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
493 uint16 cmd16, val16;
494 void *h = robo->h;
495 int i;
496 uint8 *ptr = (uint8 *)val;
498 /* validate value length and buffer address */
499 ASSERT(len == 1 || len == 6 || len == 8 ||
500 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
502 /* set page number - MII register 0x10 */
503 if (robo->page != page) {
504 cmd16 = ((page << 8) | /* page number */
505 1); /* mdc/mdio access enable */
506 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
507 robo->page = page;
510 /* set register address - MII register 0x11 */
511 cmd16 = ((reg << 8) | /* register address */
512 2); /* opcode read */
513 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
515 /* is operation finished? */
516 for (i = MII_MAX_RETRY; i > 0; i --) {
517 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
518 if ((val16 & 3) == 0)
519 break;
521 /* timed out */
522 if (!i) {
523 ET_ERROR(("mii_rreg: timeout"));
524 return -1;
527 switch (len) {
528 case 8:
529 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
530 ptr[7] = (val16 >> 8);
531 ptr[6] = (val16 & 0xff);
532 /* FALLTHRU */
534 case 6:
535 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
536 ptr[5] = (val16 >> 8);
537 ptr[4] = (val16 & 0xff);
538 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
539 ptr[3] = (val16 >> 8);
540 ptr[2] = (val16 & 0xff);
541 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
542 ptr[1] = (val16 >> 8);
543 ptr[0] = (val16 & 0xff);
544 break;
546 case 4:
547 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
548 *(uint32 *)val = (((uint32)val16) << 16);
549 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
550 *(uint32 *)val |= val16;
551 break;
553 case 2:
554 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
555 *(uint16 *)val = val16;
556 break;
558 case 1:
559 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
560 *(uint8 *)val = (uint8)(val16 & 0xff);
561 break;
564 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
565 VARG(val, len), len));
567 return 0;
570 /* MII interface functions */
571 static dev_ops_t mdcmdio = {
572 NULL,
573 NULL,
574 mii_wreg,
575 mii_rreg,
576 "MII (MDC/MDIO)"
579 /* High level switch configuration functions. */
581 /* Get access to the RoboSwitch */
582 robo_info_t *
583 bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr)
585 robo_info_t *robo;
586 uint32 reset, idx;
587 #ifndef _CFE_
588 char *et1port, *et1phyaddr;
589 int mdcport = 0, phyaddr = 0, lan_portenable = 0;
590 #endif /* _CFE_ */
592 /* Allocate and init private state */
593 if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) {
594 ET_ERROR(("robo_attach: out of memory, malloced %d bytes",
595 MALLOCED(si_osh(sih))));
596 return NULL;
598 bzero(robo, sizeof(robo_info_t));
600 robo->h = h;
601 robo->sih = sih;
602 robo->vars = vars;
603 robo->miird = miird;
604 robo->miiwr = miiwr;
605 robo->page = -1;
607 #ifndef _CFE_
608 /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when
609 * romboot CFE loads linux over WAN port and Linux enables LAN ports later
611 if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) !=
612 GPIO_PIN_NOTDEFINED) {
613 lan_portenable = 1 << lan_portenable;
614 si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
615 si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
616 bcm_mdelay(5);
618 #endif /* _CFE_ */
620 /* Trigger external reset by nvram variable existance */
621 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
622 GPIO_PIN_NOTDEFINED) {
624 * Reset sequence: RESET low(50ms)->high(20ms)
626 * We have to perform a full sequence for we don't know how long
627 * it has been from power on till now.
629 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
630 reset = 1 << reset;
632 /* Keep RESET low for 50 ms */
633 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
634 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
635 bcm_mdelay(50);
637 /* Keep RESET high for at least 20 ms */
638 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
639 bcm_mdelay(20);
640 } else {
641 /* In case we need it */
642 idx = si_coreidx(sih);
644 if (si_setcore(sih, ROBO_CORE_ID, 0)) {
645 /* If we have an internal robo core, reset it using si_core_reset */
646 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
647 si_core_reset(sih, 0, 0);
648 robo->corerev = si_corerev(sih);
650 else if (sih->chip == BCM5356_CHIP_ID) {
651 /* Testing chipid is a temporary hack. We need to really
652 * figure out how to treat non-cores in ai chips.
654 robo->corerev = 3;
656 else {
657 mii_rreg(robo, PAGE_STATUS, REG_STATUS_REV, &robo->corerev, 1);
659 si_setcoreidx(sih, idx);
660 ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev));
663 if (miird && miiwr) {
664 uint16 tmp;
665 int rc, retry_count = 0;
667 /* Read the PHY ID */
668 tmp = miird(h, PSEUDO_PHYAD, 2);
670 /* WAR: Enable mdc/mdio access to the switch registers. Unless
671 * a write to bit 0 of pseudo phy register 16 is done we are
672 * unable to talk to the switch on a customer ref design.
674 if (tmp == 0xffff) {
675 miiwr(h, PSEUDO_PHYAD, 16, 1);
676 tmp = miird(h, PSEUDO_PHYAD, 2);
679 if (tmp != 0xffff) {
680 do {
681 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID,
682 &robo->devid, sizeof(uint16));
683 if (rc != 0)
684 break;
685 retry_count++;
686 } while ((robo->devid == 0) && (retry_count < 10));
688 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n",
689 __FUNCTION__, rc ? "un" : "", robo->devid));
690 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
691 robo->ops = &mdcmdio;
692 if ((rc != 0) || (robo->devid == 0)) {
693 ET_MSG(("%s: error reading devid, assuming 5325e\n",
694 __FUNCTION__));
695 robo->devid = DEVID5325;
698 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
701 if ((robo->devid == DEVID5395) ||
702 (robo->devid == DEVID5397) ||
703 (robo->devid == DEVID5398)) {
704 uint8 srst_ctrl;
706 /* If it is a 539x switch, use the soft reset register */
707 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
709 /* Reset the 539x switch core and register file */
710 srst_ctrl = 0x83;
711 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
712 bcm_mdelay(500); /* Gemtek: for reset issue */
713 srst_ctrl = 0x00;
714 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
717 /* Enable switch leds */
718 if (sih->chip == BCM5356_CHIP_ID) {
719 si_pmu_chipcontrol(sih, 2, (1 << 25), (1 << 25));
720 } else if ((sih->chip == BCM5357_CHIP_ID) || (sih->chip == BCM53572_CHIP_ID)) {
721 uint32 led_gpios = 0;
722 char *var;
724 if ((sih->chippkg != BCM47186_PKG_ID) && (sih->chippkg != BCM47188_PKG_ID))
725 led_gpios = 0x1f;
726 var = getvar(vars, "et_swleds");
727 if (var)
728 led_gpios = bcm_strtoul(var, NULL, 0);
729 if (led_gpios)
730 si_pmu_chipcontrol(sih, 2, (0x3ff << 8), (led_gpios << 8));
733 #ifndef _CFE_
734 if (!robo->ops) {
735 int mosi, miso, ss, sck;
737 robo->ops = &spigpio;
738 robo->devid = DEVID5325;
740 /* Init GPIO mapping. Default 2, 3, 4, 5 */
741 ss = getgpiopin(vars, "robo_ss", 2);
742 if (ss == GPIO_PIN_NOTDEFINED) {
743 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
744 goto error;
746 robo->ss = 1 << ss;
747 sck = getgpiopin(vars, "robo_sck", 3);
748 if (sck == GPIO_PIN_NOTDEFINED) {
749 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
750 goto error;
752 robo->sck = 1 << sck;
753 mosi = getgpiopin(vars, "robo_mosi", 4);
754 if (mosi == GPIO_PIN_NOTDEFINED) {
755 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
756 goto error;
758 robo->mosi = 1 << mosi;
759 miso = getgpiopin(vars, "robo_miso", 5);
760 if (miso == GPIO_PIN_NOTDEFINED) {
761 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
762 goto error;
764 robo->miso = 1 << miso;
765 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
766 ss, sck, mosi, miso));
768 #endif /* _CFE_ */
770 /* sanity check */
771 ASSERT(robo->ops);
772 ASSERT(robo->ops->write_reg);
773 ASSERT(robo->ops->read_reg);
774 ASSERT((robo->devid == DEVID5325) ||
775 (robo->devid == DEVID5395) ||
776 (robo->devid == DEVID5397) ||
777 (robo->devid == DEVID5398) ||
778 (robo->devid == DEVID53115) ||
779 (robo->devid == DEVID53125));
781 #ifndef _CFE_
782 /* nvram variable switch_mode controls the power save mode on the switch
783 * set the default value in the beginning
785 robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual");
786 robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto");
788 /* Determining what all phys need to be included in
789 * power save operation
791 et1port = getvar(vars, "et1mdcport");
792 if (et1port)
793 mdcport = bcm_atoi(et1port);
795 et1phyaddr = getvar(vars, "et1phyaddr");
796 if (et1phyaddr)
797 phyaddr = bcm_atoi(et1phyaddr);
799 if ((mdcport == 0) && (phyaddr == 4))
800 /* For 5325F switch we need to do only phys 0-3 */
801 robo->pwrsave_phys = 0xf;
802 else
803 /* By default all 5 phys are put into power save if there is no link */
804 robo->pwrsave_phys = 0x1f;
805 #endif /* _CFE_ */
807 #ifdef PLC
808 /* See if one of the ports is connected to plc chipset */
809 robo->plc_hw = (getvar(vars, "plc_vifs") != NULL);
810 #endif /* PLC */
812 return robo;
814 #ifndef _CFE_
815 error:
816 bcm_robo_detach(robo);
817 return NULL;
818 #endif /* _CFE_ */
821 /* Release access to the RoboSwitch */
822 void
823 bcm_robo_detach(robo_info_t *robo)
825 MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
828 /* Enable the device and set it to a known good state */
830 bcm_robo_enable_device(robo_info_t *robo)
832 uint8 reg_offset, reg_val;
833 int ret = 0;
834 #ifdef PLC
835 uint32 val32;
836 #endif /* PLC */
838 /* Enable management interface access */
839 if (robo->ops->enable_mgmtif)
840 robo->ops->enable_mgmtif(robo);
842 if (robo->devid == DEVID5398) {
843 /* Disable unused ports: port 6 and 7 */
844 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
845 /* Set bits [1:0] to disable RX and TX */
846 reg_val = 0x03;
847 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
848 sizeof(reg_val));
852 if (robo->devid == DEVID5325) {
853 /* Must put the switch into Reverse MII mode! */
855 /* MII port state override (page 0 register 14) */
856 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
858 /* Bit 4 enables reverse MII mode */
859 if (!(reg_val & (1 << 4))) {
860 /* Enable RvMII */
861 reg_val |= (1 << 4);
862 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
863 sizeof(reg_val));
865 /* Read back */
866 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
867 sizeof(reg_val));
868 if (!(reg_val & (1 << 4))) {
869 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
870 ret = -1;
875 #ifdef PLC
876 if (robo->plc_hw) {
877 val32 = 0x100002;
878 robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_ATCR, &val32, sizeof(val32));
880 #endif /* PLC */
882 /* Disable management interface access */
883 if (robo->ops->disable_mgmtif)
884 robo->ops->disable_mgmtif(robo);
886 return ret;
889 /* Port flags */
890 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
891 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
892 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
894 /* port descriptor */
895 typedef struct {
896 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
897 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
898 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
899 uint8 cpu; /* is this cpu port? */
900 } pdesc_t;
902 pdesc_t pdesc97[] = {
903 /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */
904 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
905 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
906 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
907 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
908 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
909 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
910 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
911 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
912 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
915 pdesc_t pdesc25[] = {
916 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
917 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
918 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
919 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
920 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
921 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
924 /* Configure the VLANs */
926 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
928 uint8 val8;
929 uint16 val16;
930 uint32 val32;
931 pdesc_t *pdesc;
932 int pdescsz;
933 uint16 vid, vid0;
934 uint16 vid_map;
935 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
937 /* Enable management interface access */
938 if (robo->ops->enable_mgmtif)
939 robo->ops->enable_mgmtif(robo);
941 /* setup global vlan configuration */
942 /* VLAN Control 0 Register (Page 0x34, Address 0) */
943 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
944 val8 |= ((1 << 7) | /* enable 802.1Q VLAN */
945 (3 << 5)); /* individual VLAN learning mode */
946 if (robo->devid == DEVID5325)
947 val8 &= ~(1 << 1); /* must clear reserved bit 1 */
948 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
949 /* VLAN Control 1 Register (Page 0x34, Address 1) */
950 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
951 val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */
952 (1 << 3)); /* enable RSV multicast V Untagmap */
953 if ((robo->devid == DEVID5325) &&
954 ((robo->sih->chip != BCM5357_CHIP_ID) || (robo->sih->chippkg != BCM5358_PKG_ID)))
955 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
956 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
958 /* Jumbo Frame control refister (Page 0x40, Address 0x01) */
959 /* Added by Yen */
960 robo->ops->read_reg(robo, PAGE_JUMBO, REG_JUMBO_CTRL, &val16, sizeof(val16));
961 val16 &= ~((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 8));
962 if (nvram_match("jumbo_frame_enable", "1"))
963 val16 |= ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 8));
964 robo->ops->write_reg(robo, PAGE_JUMBO, REG_JUMBO_CTRL, &val16, sizeof(val16));
966 arl_entry[0] = mac_addr[5];
967 arl_entry[1] = mac_addr[4];
968 arl_entry[2] = mac_addr[3];
969 arl_entry[3] = mac_addr[2];
970 arl_entry[4] = mac_addr[1];
971 arl_entry[5] = mac_addr[0];
973 if (robo->devid == DEVID5325) {
974 /* Init the entry 1 of the bin */
975 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1,
976 arl_entry1, sizeof(arl_entry1));
977 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1,
978 arl_entry1, 1);
980 /* Init the entry 0 of the bin */
981 arl_entry[6] = 0x8; /* Port Id: MII */
982 arl_entry[7] = 0xc0; /* Static Entry, Valid */
984 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
985 arl_entry, sizeof(arl_entry));
986 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
987 arl_entry, ETHER_ADDR_LEN);
989 /* VLAN Control 4 Register (Page 0x34, Address 4) */
990 val8 = (1 << 6); /* drop frame with VID violation */
991 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
993 /* VLAN Control 5 Register (Page 0x34, Address 5) */
994 val8 = (1 << 3); /* drop frame when miss V table */
995 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
997 pdesc = pdesc25;
998 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
999 } else {
1000 /* Initialize the MAC Addr Index Register */
1001 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
1002 arl_entry, ETHER_ADDR_LEN);
1004 pdesc = pdesc97;
1005 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1008 vid0 = getintvar(robo->vars, "vlan0tag");
1009 #ifdef VID_MAP_DBG
1010 (KERN_EMERG "bcmrobo: vlan0tag/vid0=%d\n", vid0 );
1011 #endif
1013 /* setup each vlan. max. 16 vlans. */
1014 /* force vlan id to be equal to vlan number */
1015 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1016 char vlanports[] = "vlanXXXXports";
1017 char port[] = "XXXX", *ports, *next, *cur, *nvvid;
1018 char vlanvid[] = "vlanXXXXvid";
1019 uint32 untag = 0;
1020 uint32 member = 0;
1021 int pid, len;
1023 /* no members if VLAN id is out of limitation */
1024 if (vid > VLAN_MAXVID)
1025 goto vlan_setup;
1027 /* vlan ID mapping */
1028 vid_map = vid0 | vid;
1029 sprintf(vlanvid, "vlan%dvid", vid);
1030 nvvid = getvar(robo->vars, vlanvid);
1032 if (nvvid != NULL) {
1033 vid_map = bcm_atoi(nvvid);
1034 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vid0 | vid;
1037 /* get vlan member ports from nvram */
1038 sprintf(vlanports, "vlan%dports", vid);
1039 ports = getvar(robo->vars, vlanports);
1041 #ifdef VID_MAP_DBG
1042 printk(KERN_EMERG "bcmrobo: VLAN %d mapped to VID %d, ports='%s', %s='%s'\n",
1043 vid, vid_map, (ports != NULL)? ports: "(unset)",
1044 vlanvid, (nvvid != NULL)? nvvid: "(unset)" );
1045 #endif
1047 /* In 539x vid == 0 us invalid?? */
1048 if ((robo->devid != DEVID5325) && (robo->devid != DEVID5397) && (vid == 0)) {
1049 if (ports)
1050 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
1051 continue;
1054 /* Gemtek: to distinguish switch 5397 and 5395 */
1055 if ((robo->devid == DEVID5395) && (vid == 1)) {
1056 sprintf(vlanports, "vlan0ports");
1057 ports = getvar(robo->vars, vlanports);
1058 if (!ports || (*ports == 0) || !strcmp(ports, " ")) {
1059 ET_ERROR(("BCM5395: already booted, use internal fixup\n"));
1060 sprintf(vlanports, "vlan1ports");
1061 ports = getvar(robo->vars, vlanports);
1063 else {
1064 ET_ERROR(("Configure vlan1 (%s) instead of vlan0 for BCM5395\n", ports));
1068 /* disable this vlan if not defined */
1069 if (!ports)
1070 goto vlan_setup;
1073 * setup each port in the vlan. cpu port needs special handing
1074 * (with or without output tagging) to support linux/pmon/cfe.
1076 for (cur = ports; cur; cur = next) {
1077 /* tokenize the port list */
1078 while (*cur == ' ')
1079 cur ++;
1080 next = bcmstrstr(cur, " ");
1081 len = next ? next - cur : strlen(cur);
1082 if (!len)
1083 break;
1084 if (len > sizeof(port) - 1)
1085 len = sizeof(port) - 1;
1086 strncpy(port, cur, len);
1087 port[len] = 0;
1089 /* make sure port # is within the range */
1090 pid = bcm_atoi(port);
1091 if (pid >= pdescsz) {
1092 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
1093 "of range[0-%d]\n", pid, vid, pdescsz));
1094 continue;
1097 /* build VLAN registers values */
1098 #ifndef _CFE_
1099 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1100 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
1101 #endif
1102 untag |= pdesc[pid].untag;
1104 member |= pdesc[pid].member;
1106 /* set port tag - applies to untagged ingress frames */
1107 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
1108 #ifdef _CFE_
1109 #define FL FLAG_LAN
1110 #else
1111 #define FL FLAG_UNTAG
1112 #endif /* _CFE_ */
1113 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1114 strchr(port, FL)) {
1115 val16 = ((0 << 13) | /* priority - always 0 */
1116 vid_map); /* vlan id */
1117 #ifdef VID_MAP_DBG
1118 printk( KERN_EMERG "bcmrobo(map A) ->%d/%d\n", vid_map, pid);
1119 #endif
1120 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
1121 &val16, sizeof(val16));
1125 /* Add static ARL entries */
1126 if (robo->devid == DEVID5325) {
1127 val8 = vid;
1128 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0,
1129 &val8, sizeof(val8));
1130 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1131 &val8, sizeof(val8));
1133 /* Write the entry */
1134 val8 = 0x80;
1135 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1136 &val8, sizeof(val8));
1137 /* Wait for write to complete */
1138 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1139 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1140 100 /* usec */);
1141 } else {
1142 /* Set the VLAN Id in VLAN ID Index Register */
1143 val8 = vid;
1144 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1145 &val8, sizeof(val8));
1147 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1148 * Register.
1150 arl_entry[6] = (vid_map & 0xff);
1151 arl_entry[7] = (vid_map >> 8);
1152 #ifdef VID_MAP_DBG
1153 printk( KERN_EMERG "bcmrobo(map B) ->%d (%d/%d)\n",
1154 vid_map, arl_entry[6], arl_entry[7] );
1155 #endif
1156 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
1157 arl_entry, sizeof(arl_entry));
1159 /* Set the Static bit , Valid bit and Port ID fields in
1160 * ARL Table Data Entry 0 Register
1162 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1163 val32 = 0x18008;
1164 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1165 &val32, sizeof(val32));
1166 } else {
1167 val16 = 0xc008;
1168 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1169 &val16, sizeof(val16));
1172 /* Clear the ARL_R/W bit and set the START/DONE bit in
1173 * the ARL Read/Write Control Register.
1175 val8 = 0x80;
1176 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1177 &val8, sizeof(val8));
1178 /* Wait for write to complete */
1179 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1180 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1181 100 /* usec */);
1184 vlan_setup:
1185 /* setup VLAN ID and VLAN memberships */
1187 val32 = (untag | /* untag enable */
1188 member); /* vlan members */
1189 if (robo->sih->chip == BCM5365_CHIP_ID) {
1190 /* VLAN Write Register (Page 0x34, Address 0x0A) */
1191 val32 = ((1 << 14) | /* valid write */
1192 (untag << 1) | /* untag enable */
1193 member); /* vlan members */
1194 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE_5365, &val32,
1195 sizeof(val32));
1196 /* VLAN Table Access Register (Page 0x34, Address 0x08) */
1197 val16 = ((1 << 13) | /* start command */
1198 (1 << 12) | /* write state */
1199 vid_map); /* vlan id */
1200 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS_5365, &val16,
1201 sizeof(val16));
1202 } else if (robo->devid == DEVID5325) {
1203 if (robo->corerev < 3) {
1204 val32 |= ((1 << 20) | /* valid write */
1205 ((vid0 >> 4) << 12)); /* vlan id bit[11:4] */
1206 } else {
1207 val32 |= ((1 << 24) | /* valid write */
1208 (vid_map << 12)); /* vlan id bit[11:4] */
1210 ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32));
1212 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1213 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1214 sizeof(val32));
1215 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1216 val16 = ((1 << 13) | /* start command */
1217 (1 << 12) | /* write state */
1218 vid_map); /* vlan id */
1219 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1220 sizeof(val16));
1221 #ifdef VID_MAP_DBG
1222 printk( KERN_EMERG "bcmrobo(map C/DEVID5325) ->%d\n", vid_map );
1223 #endif
1224 } else {
1225 uint8 vtble, vtbli, vtbla;
1227 if ((robo->devid == DEVID5395) ||
1228 (robo->devid == DEVID53115) ||
1229 (robo->devid == DEVID53125)) {
1230 vtble = REG_VTBL_ENTRY_5395;
1231 vtbli = REG_VTBL_INDX_5395;
1232 vtbla = REG_VTBL_ACCESS_5395;
1233 } else {
1234 vtble = REG_VTBL_ENTRY;
1235 vtbli = REG_VTBL_INDX;
1236 vtbla = REG_VTBL_ACCESS;
1239 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1240 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1241 sizeof(val32));
1242 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1243 val16 = vid_map; /* vlan id */
1244 #ifdef VID_MAP_DBG
1245 printk( KERN_EMERG "bcmrobo(map C) ->%d\n", vid_map );
1246 #endif
1247 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1248 sizeof(val16));
1250 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1251 val8 = ((1 << 7) | /* start command */
1252 0); /* write */
1253 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1254 sizeof(val8));
1258 if (robo->devid == DEVID5325) {
1259 /* setup priority mapping - applies to tagged ingress frames */
1260 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1261 val32 = ((0 << 0) | /* 0 -> 0 */
1262 (1 << 3) | /* 1 -> 1 */
1263 (2 << 6) | /* 2 -> 2 */
1264 (3 << 9) | /* 3 -> 3 */
1265 (4 << 12) | /* 4 -> 4 */
1266 (5 << 15) | /* 5 -> 5 */
1267 (6 << 18) | /* 6 -> 6 */
1268 (7 << 21)); /* 7 -> 7 */
1269 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1272 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1273 /* Configure the priority system to use to determine the TC of
1274 * ingress frames. Use DiffServ TC mapping, otherwise 802.1p
1275 * TC mapping, otherwise MAC based TC mapping.
1277 val8 = ((0 << 6) | /* Disable port based QoS */
1278 (2 << 2)); /* QoS priority selection */
1279 robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8));
1281 /* Configure tx queues scheduling mechanism */
1282 val8 = (3 << 0); /* Strict priority */
1283 robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8));
1285 /* Enable 802.1p Priority to TC mapping for individual ports */
1286 val16 = 0x11f;
1287 robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16));
1289 /* Configure the TC to COS mapping. This determines the egress
1290 * transmit queue.
1292 val16 = ((1 << 0) | /* Pri 0 mapped to TXQ 1 */
1293 (0 << 2) | /* Pri 1 mapped to TXQ 0 */
1294 (0 << 4) | /* Pri 2 mapped to TXQ 0 */
1295 (1 << 6) | /* Pri 3 mapped to TXQ 1 */
1296 (2 << 8) | /* Pri 4 mapped to TXQ 2 */
1297 (2 << 10) | /* Pri 5 mapped to TXQ 2 */
1298 (3 << 12) | /* Pri 6 mapped to TXQ 3 */
1299 (3 << 14)); /* Pri 7 mapped to TXQ 3 */
1300 robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16));
1303 /* Disable management interface access */
1304 if (robo->ops->disable_mgmtif)
1305 robo->ops->disable_mgmtif(robo);
1307 return 0;
1310 /* Enable switching/forwarding */
1312 bcm_robo_enable_switch(robo_info_t *robo)
1314 int i, max_port_ind, ret = 0;
1315 uint8 val8;
1317 /* Enable management interface access */
1318 if (robo->ops->enable_mgmtif)
1319 robo->ops->enable_mgmtif(robo);
1321 /* Switch Mode register (Page 0, Address 0x0B) */
1322 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1324 /* Bit 1 enables switching/forwarding */
1325 if (!(val8 & (1 << 1))) {
1326 /* Set unmanaged mode */
1327 val8 &= (~(1 << 0));
1329 /* Enable forwarding */
1330 val8 |= (1 << 1);
1331 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1333 /* Read back */
1334 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1335 if (!(val8 & (1 << 1))) {
1336 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1337 ret = -1;
1340 /* No spanning tree for unmanaged mode */
1341 val8 = 0;
1342 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 :
1343 (robo->devid == DEVID53115) ? REG_CTRL_PORT5 : REG_CTRL_PORT4);
1344 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1345 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1348 /* No spanning tree on IMP port too */
1349 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8));
1352 if (robo->devid == DEVID53125) {
1353 /* Over ride IMP port status to make it link by default */
1354 val8 = 0;
1355 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1356 val8 |= 0x81; /* Make Link pass and override it. */
1357 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1360 if (robo->sih->chip == BCM5365_CHIP_ID) {
1361 /* Enable WAN port (#0) on the asus wl-500g deluxe boxes */
1362 val8 = 0;
1363 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0, &val8, sizeof(val8));
1366 /* Disable management interface access */
1367 if (robo->ops->disable_mgmtif)
1368 robo->ops->disable_mgmtif(robo);
1370 return ret;
1373 #ifdef BCMDBG
1374 void
1375 robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b)
1377 uint8 val8;
1378 uint16 val16;
1379 uint32 val32;
1380 pdesc_t *pdesc;
1381 int pdescsz;
1382 int i;
1384 bcm_bprintf(b, "%s:\n", robo->ops->desc);
1385 if (robo->miird == NULL) {
1386 bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n",
1387 robo->ss, robo->sck, robo->mosi, robo->miso);
1390 /* Enable management interface access */
1391 if (robo->ops->enable_mgmtif)
1392 robo->ops->enable_mgmtif(robo);
1394 /* Dump registers interested */
1395 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1396 bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8);
1397 if (robo->devid == DEVID5325) {
1398 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1399 bcm_bprintf(b, "(0x00,0x0E)MII port state override regsiter: 0x%02x\n", val8);
1401 if (robo->miird == NULL)
1402 goto exit;
1403 if (robo->devid == DEVID5325) {
1404 pdesc = pdesc25;
1405 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1406 } else {
1407 pdesc = pdesc97;
1408 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1411 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1412 bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8);
1413 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1414 bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8);
1415 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1416 if (robo->devid == DEVID5325) {
1417 bcm_bprintf(b, "(0x34,0x04)VLAN control 4 register: 0x%02x\n", val8);
1418 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1419 bcm_bprintf(b, "(0x34,0x05)VLAN control 5 register: 0x%02x\n", val8);
1421 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1422 bcm_bprintf(b, "(0x34,0x20)Prio Re-map: 0x%08x\n", val32);
1424 for (i = 0; i <= VLAN_MAXVID; i++) {
1425 val16 = (1 << 13) /* start command */
1426 | i; /* vlan id */
1427 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1428 sizeof(val16));
1429 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_READ, &val32, sizeof(val32));
1430 bcm_bprintf(b, "(0x34,0xc)VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1431 i, (val32 & 0x0fc0) >> 6, (val32 & 0x003f));
1434 } else {
1435 for (i = 0; i <= VLAN_MAXVID; i++) {
1436 /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62) */
1437 val16 = i; /* vlan id */
1438 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_INDX, &val16,
1439 sizeof(val16));
1440 /* VLAN Table Access Register (Page 0x34, Address 0x60) */
1441 val8 = ((1 << 7) | /* start command */
1442 1); /* read */
1443 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ACCESS, &val8,
1444 sizeof(val8));
1445 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66) */
1446 robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_ENTRY, &val32,
1447 sizeof(val32));
1448 bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1449 i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff));
1452 for (i = 0; i < pdescsz; i++) {
1453 robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16));
1454 bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16);
1457 exit:
1458 /* Disable management interface access */
1459 if (robo->ops->disable_mgmtif)
1460 robo->ops->disable_mgmtif(robo);
1462 #endif /* BCMDBG */
1464 #ifndef _CFE_
1466 * Update the power save configuration for ports that changed link status.
1468 void
1469 robo_power_save_mode_update(robo_info_t *robo)
1471 uint phy;
1473 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1474 if (robo->pwrsave_mode_auto & (1 << phy)) {
1475 ET_MSG(("%s: set port %d to auto mode\n",
1476 __FUNCTION__, phy));
1477 robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy);
1481 return;
1484 static int32
1485 robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy)
1487 uint16 val16;
1489 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1490 /* For 53115 0x1C is the MII address of the auto power
1491 * down register. Bit 5 is enabling the mode
1492 * bits has the following purpose
1493 * 15 - write enable 10-14 shadow register select 01010 for
1494 * auto power 6-9 reserved 5 auto power mode enable
1495 * 4 sleep timer select : 1 means 5.4 sec
1496 * 0-3 wake up timer select: 0xF 1.26 sec
1498 val16 = 0xa800;
1499 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, val16);
1500 } else if (robo->sih->chip == BCM5356_CHIP_ID) {
1501 /* To disable auto power down mode
1502 * clear bit 5 of Aux Status 2 register
1503 * (Shadow reg 0x1b). Shadow register
1504 * access is enabled by writing
1505 * 1 to bit 7 of MII register 0x1f.
1507 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1508 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1509 (val16 | (1 << 7)));
1511 /* Disable auto power down by clearing
1512 * bit 5 of to Aux Status 2 reg.
1514 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1515 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1516 (val16 & ~(1 << 5)));
1518 /* Undo shadow access */
1519 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1520 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1521 (val16 & ~(1 << 7)));
1522 } else
1523 return -1;
1525 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_AUTO;
1527 return 0;
1530 static int32
1531 robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy)
1533 uint8 val8;
1534 uint16 val16;
1536 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125) ||
1537 (robo->sih->chip == BCM5356_CHIP_ID)) {
1538 /* For 53115 0x0 is the MII control register
1539 * Bit 11 is the power down mode bit
1541 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1542 val16 &= 0xf7ff;
1543 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16);
1544 } else if (robo->devid == DEVID5325) {
1545 if (phy == 0)
1546 return -1;
1547 /* For 5325 page 0x00 address 0x0F is the power down
1548 * mode register. Bits 1-4 determines which of the
1549 * phys are enabled for this mode
1551 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1552 &val8, sizeof(val8));
1553 val8 &= ~(0x1 << phy);
1554 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1555 &val8, sizeof(val8));
1556 } else
1557 return -1;
1559 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_MANUAL;
1561 return 0;
1565 * Function which periodically checks the power save mode on the switch
1567 int32
1568 robo_power_save_toggle(robo_info_t *robo, int32 normal)
1570 int32 phy;
1571 uint16 link_status;
1574 /* read the link status of all ports */
1575 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1576 &link_status, sizeof(uint16));
1577 link_status &= 0x1f;
1579 /* Take the phys out of the manual mode first so that link status
1580 * can be checked. Once out of that mode check the link status
1581 * and if any of the link is up do not put that phy into
1582 * manual power save mode
1584 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1585 /* When auto+manual modes are enabled we toggle between
1586 * manual and auto modes. When only manual mode is enabled
1587 * we toggle between manual and normal modes. When only
1588 * auto mode is enabled there is no need to do anything
1589 * here since auto mode is one time config.
1591 if ((robo->pwrsave_phys & (1 << phy)) &&
1592 (robo->pwrsave_mode_manual & (1 << phy))) {
1593 if (!normal) {
1594 /* Take the port out of the manual mode */
1595 robo_power_save_mode_clear_manual(robo, phy);
1596 } else {
1597 /* If the link is down put it back to manual else
1598 * remain in the current state
1600 if (!(link_status & (1 << phy))) {
1601 ET_MSG(("%s: link down, set port %d to man mode\n",
1602 __FUNCTION__, phy));
1603 robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy);
1609 return 0;
1613 * Switch the ports to normal mode.
1615 static int32
1616 robo_power_save_mode_normal(robo_info_t *robo, int32 phy)
1618 int32 error = 0;
1620 /* If the phy in the power save mode come out of it */
1621 switch (robo->pwrsave_mode_phys[phy]) {
1622 case ROBO_PWRSAVE_AUTO_MANUAL:
1623 case ROBO_PWRSAVE_AUTO:
1624 error = robo_power_save_mode_clear_auto(robo, phy);
1625 if ((error == -1) ||
1626 (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO))
1627 break;
1629 case ROBO_PWRSAVE_MANUAL:
1630 error = robo_power_save_mode_clear_manual(robo, phy);
1631 break;
1633 default:
1634 break;
1637 return error;
1641 * Switch all the inactive ports to auto power down mode.
1643 static int32
1644 robo_power_save_mode_auto(robo_info_t *robo, int32 phy)
1646 uint16 val16;
1648 /* If the switch supports auto power down enable that */
1649 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1650 /* For 53115 0x1C is the MII address of the auto power
1651 * down register. Bit 5 is enabling the mode
1652 * bits has the following purpose
1653 * 15 - write enable 10-14 shadow register select 01010 for
1654 * auto power 6-9 reserved 5 auto power mode enable
1655 * 4 sleep timer select : 1 means 5.4 sec
1656 * 0-3 wake up timer select: 0xF 1.26 sec
1658 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA83F);
1659 } else if (robo->sih->chip == BCM5356_CHIP_ID) {
1660 /* To enable auto power down mode set bit 5 of
1661 * Auxillary Status 2 register (Shadow reg 0x1b)
1662 * Shadow register access is enabled by writing
1663 * 1 to bit 7 of MII register 0x1f.
1665 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1666 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1667 (val16 | (1 << 7)));
1669 /* Enable auto power down by writing to Auxillary
1670 * Status 2 reg.
1672 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1673 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1674 (val16 | (1 << 5)));
1676 /* Undo shadow access */
1677 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1678 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1679 (val16 & ~(1 << 7)));
1680 } else
1681 return -1;
1683 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_AUTO;
1685 return 0;
1689 * Switch all the inactive ports to manual power down mode.
1691 static int32
1692 robo_power_save_mode_manual(robo_info_t *robo, int32 phy)
1694 uint8 val8;
1695 uint16 val16;
1697 /* For both 5325 and 53115 the link status register is the same */
1698 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1699 &val16, sizeof(val16));
1700 if (val16 & (0x1 << phy))
1701 return 0;
1703 /* If the switch supports manual power down enable that */
1704 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125) ||
1705 (robo->sih->chip == BCM5356_CHIP_ID)) {
1706 /* For 53115 0x0 is the MII control register bit 11 is the
1707 * power down mode bit
1709 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1710 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16 | 0x800);
1711 } else if (robo->devid == DEVID5325) {
1712 if (phy == 0)
1713 return -1;
1714 /* For 5325 page 0x00 address 0x0F is the power down mode
1715 * register. Bits 1-4 determines which of the phys are enabled
1716 * for this mode
1718 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1719 sizeof(val8));
1720 val8 |= (1 << phy);
1721 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
1722 sizeof(val8));
1723 } else
1724 return -1;
1726 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_MANUAL;
1728 return 0;
1732 * Set power save modes on the robo switch
1734 int32
1735 robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy)
1737 int32 error = -1;
1739 if (phy > MAX_NO_PHYS) {
1740 ET_ERROR(("Passed parameter phy is out of range\n"));
1741 return -1;
1744 /* Enable management interface access */
1745 if (robo->ops->enable_mgmtif)
1746 robo->ops->enable_mgmtif(robo);
1748 switch (mode) {
1749 case ROBO_PWRSAVE_NORMAL:
1750 /* If the phy in the power save mode come out of it */
1751 error = robo_power_save_mode_normal(robo, phy);
1752 break;
1754 case ROBO_PWRSAVE_AUTO_MANUAL:
1755 /* If the switch supports auto and manual power down
1756 * enable both of them
1758 case ROBO_PWRSAVE_AUTO:
1759 error = robo_power_save_mode_auto(robo, phy);
1760 if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO))
1761 break;
1763 case ROBO_PWRSAVE_MANUAL:
1764 error = robo_power_save_mode_manual(robo, phy);
1765 break;
1767 default:
1768 break;
1771 /* Disable management interface access */
1772 if (robo->ops->disable_mgmtif)
1773 robo->ops->disable_mgmtif(robo);
1775 return error;
1779 * Get the current power save mode of the switch ports.
1781 int32
1782 robo_power_save_mode_get(robo_info_t *robo, int32 phy)
1784 ASSERT(robo);
1786 if (phy >= MAX_NO_PHYS)
1787 return -1;
1789 return robo->pwrsave_mode_phys[phy];
1793 * Configure the power save mode for the switch ports.
1795 int32
1796 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy)
1798 int32 error;
1800 ASSERT(robo);
1802 if (phy >= MAX_NO_PHYS)
1803 return -1;
1805 error = robo_power_save_mode(robo, mode, phy);
1807 if (error)
1808 return error;
1810 if (mode == ROBO_PWRSAVE_NORMAL) {
1811 robo->pwrsave_mode_manual &= ~(1 << phy);
1812 robo->pwrsave_mode_auto &= ~(1 << phy);
1813 } else if (mode == ROBO_PWRSAVE_AUTO) {
1814 robo->pwrsave_mode_auto |= (1 << phy);
1815 robo->pwrsave_mode_manual &= ~(1 << phy);
1816 robo_power_save_mode_clear_manual(robo, phy);
1817 } else if (mode == ROBO_PWRSAVE_MANUAL) {
1818 robo->pwrsave_mode_manual |= (1 << phy);
1819 robo->pwrsave_mode_auto &= ~(1 << phy);
1820 robo_power_save_mode_clear_auto(robo, phy);
1821 } else {
1822 robo->pwrsave_mode_auto |= (1 << phy);
1823 robo->pwrsave_mode_manual |= (1 << phy);
1826 return 0;
1828 #endif /* _CFE_ */
1830 #ifdef PLC
1831 void
1832 robo_plc_hw_init(robo_info_t *robo)
1834 uint8 val8;
1836 ASSERT(robo);
1838 if (!robo->plc_hw)
1839 return;
1841 /* Enable management interface access */
1842 if (robo->ops->enable_mgmtif)
1843 robo->ops->enable_mgmtif(robo);
1845 if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) {
1846 /* Fix the duplex mode and speed for Port 5 */
1847 val8 = ((1 << 6) | (1 << 2) | 3);
1848 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIP5O, &val8, sizeof(val8));
1849 } else if ((robo->sih->chip == BCM5357_CHIP_ID) &&
1850 (robo->sih->chippkg == BCM5358_PKG_ID)) {
1851 /* Fix the duplex mode and speed for Port 4 (MII port). Force
1852 * full duplex mode, enable flow control and set speed to 100.
1854 si_pmu_chipcontrol(robo->sih, 2, (1 << 1) | (1 << 2) | (1 << 3),
1855 (1 << 1) | (1 << 2) | (1 << 3));
1858 /* Disable management interface access */
1859 if (robo->ops->disable_mgmtif)
1860 robo->ops->disable_mgmtif(robo);
1862 ET_MSG(("%s: Configured PLC MII interface\n", __FUNCTION__));
1864 #endif /* PLC */