GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / bcmrobo.c
blob11995936b2f777f97d21d3bc5b85b2b0197918ad
1 /*
2 * Broadcom 53xx RoboSwitch device driver.
4 * Copyright (C) 2012, 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 393355 2013-03-27 07:07:02Z $
22 #include <bcm_cfg.h>
23 #include <typedefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <sbchipc.h>
28 #include <hndsoc.h>
29 #include <bcmutils.h>
30 #include <bcmendian.h>
31 #include <bcmparams.h>
32 #include <bcmnvram.h>
33 #include <bcmdevs.h>
34 #include <bcmrobo.h>
35 #include <proto/ethernet.h>
36 #include <hndpmu.h>
38 #ifdef BCMDBG
39 #define ET_ERROR(args) printf args
40 #else /* BCMDBG */
41 #define ET_ERROR(args)
42 #endif /* BCMDBG */
43 #define ET_MSG(args)
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_CLAUSE_45_CTL1 0xd /* 53125 MII Clause 45 control 1 */
59 #define REG_MII_CLAUSE_45_CTL2 0xe /* 53125 MII Clause 45 control 2 */
60 #define REG_MII_PAGE 0x10 /* MII Page register */
61 #define REG_MII_ADDR 0x11 /* MII Address register */
62 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
63 #define REG_MII_DATA1 0x19 /* MII Data register 1 */
64 #define REG_MII_DATA2 0x1a /* MII Data register 2 */
65 #define REG_MII_DATA3 0x1b /* MII Data register 3 */
66 #define REG_MII_AUX_STATUS2 0x1b /* Auxiliary status 2 register */
67 #define REG_MII_AUTO_PWRDOWN 0x1c /* 53115 Auto power down register */
68 #define REG_MII_BRCM_TEST 0x1f /* Broadcom test register */
70 /* Page numbers */
71 #define PAGE_CTRL 0x00 /* Control page */
72 #define PAGE_STATUS 0x01 /* Status page */
73 #define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
74 #define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
75 #define PAGE_VLAN 0x34 /* VLAN page */
77 /* Control page registers */
78 #define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
79 #define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
80 #define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
81 #define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
82 #define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
83 #define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
84 #define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
85 #define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
86 #define REG_CTRL_IMP 0x08 /* IMP port traffic control register */
87 #define REG_CTRL_MODE 0x0B /* Switch Mode register */
88 #define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
89 #define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */
90 #define REG_CTRL_SRST 0x79 /* Software reset control register */
91 #ifdef PLC
92 #define REG_CTRL_MIIP5O 0x5d /* 53115: Port State Override register for port 5 */
94 /* Management/Mirroring Registers */
95 #define REG_MMR_ATCR 0x06 /* Aging Time Control register */
96 #define REG_MMR_MCCR 0x10 /* Mirror Capture Control register */
97 #define REG_MMR_IMCR 0x12 /* Ingress Mirror Control register */
98 #endif /* PLC */
100 /* Status Page Registers */
101 #define REG_STATUS_LINK 0x00 /* Link Status Summary */
102 #define REG_STATUS_REV 0x50 /* Revision Register */
104 #define REG_DEVICE_ID 0x30 /* 539x Device id: */
106 /* VLAN page registers */
107 #define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
108 #define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
109 #define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
110 #define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
111 #define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
112 #define REG_VLAN_WRITE 0x08 /* VLAN Write register */
113 #define REG_VLAN_READ 0x0C /* VLAN Read register */
114 #define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
115 #define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
116 #define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
117 #define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
118 #define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
119 #define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
120 #define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
121 #define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
122 #define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
123 #define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
125 #define VLAN_NUMVLANS 16 /* # of VLANs */
128 /* ARL/VLAN Table Access page registers */
129 #define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
130 #define REG_VTBL_MINDX 0x02 /* MAC Address Index */
131 #define REG_VTBL_VINDX 0x08 /* VID Table Index */
132 #define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
133 #define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
134 #define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
135 #define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
136 #define REG_VTBL_SADDR 0x22 /* ARL Search Address */
137 #define REG_VTBL_SRES 0x24 /* ARL Search Result */
138 #define REG_VTBL_SREXT 0x2c /* ARL Search Result */
139 #define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
140 #define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
141 #define REG_VTBL_PREG 0xFF /* Page Register */
142 #define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
143 #define REG_VTBL_INDX 0x61 /* VLAN table address index register */
144 #define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
145 #define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
146 #define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
147 #define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
149 #ifndef _CFE_
150 /* SPI registers */
151 #define REG_SPI_PAGE 0xff /* SPI Page register */
153 /* Access switch registers through GPIO/SPI */
155 /* Minimum timing constants */
156 #define SCK_EDGE_TIME 2 /* clock edge duration - 2us */
157 #define MOSI_SETUP_TIME 1 /* input setup duration - 1us */
158 #define SS_SETUP_TIME 1 /* select setup duration - 1us */
160 /* misc. constants */
161 #define SPI_MAX_RETRY 100
163 /* Enable GPIO access to the chip */
164 static void
165 gpio_enable(robo_info_t *robo)
167 /* Enable GPIO outputs with SCK and MOSI low, SS high */
168 si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
169 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi,
170 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
173 /* Disable GPIO access to the chip */
174 static void
175 gpio_disable(robo_info_t *robo)
177 /* Disable GPIO outputs with all their current values */
178 si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
181 /* Write a byte stream to the chip thru SPI */
182 static int
183 spi_write(robo_info_t *robo, uint8 *buf, uint len)
185 uint i;
186 uint8 mask;
188 /* Byte bang from LSB to MSB */
189 for (i = 0; i < len; i++) {
190 /* Bit bang from MSB to LSB */
191 for (mask = 0x80; mask; mask >>= 1) {
192 /* Clock low */
193 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
194 OSL_DELAY(SCK_EDGE_TIME);
196 /* Sample on rising edge */
197 if (mask & buf[i])
198 si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
199 else
200 si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY);
201 OSL_DELAY(MOSI_SETUP_TIME);
203 /* Clock high */
204 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
205 OSL_DELAY(SCK_EDGE_TIME);
209 return 0;
212 /* Read a byte stream from the chip thru SPI */
213 static int
214 spi_read(robo_info_t *robo, uint8 *buf, uint len)
216 uint i, timeout;
217 uint8 rack, mask, byte;
219 /* Timeout after 100 tries without RACK */
220 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
221 /* Bit bang from MSB to LSB */
222 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
223 /* Clock low */
224 si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY);
225 OSL_DELAY(SCK_EDGE_TIME);
227 /* Sample on falling edge */
228 if (si_gpioin(robo->sih) & robo->miso)
229 byte |= mask;
231 /* Clock high */
232 si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
233 OSL_DELAY(SCK_EDGE_TIME);
235 /* RACK when bit 0 is high */
236 if (!rack) {
237 rack = (byte & 1);
238 timeout--;
239 continue;
241 /* Byte bang from LSB to MSB */
242 buf[i] = byte;
243 i++;
246 if (timeout == 0) {
247 ET_ERROR(("spi_read: timeout"));
248 return -1;
251 return 0;
254 /* Enable/disable SPI access */
255 static void
256 spi_select(robo_info_t *robo, uint8 spi)
258 if (spi) {
259 /* Enable SPI access */
260 si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY);
261 } else {
262 /* Disable SPI access */
263 si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
265 OSL_DELAY(SS_SETUP_TIME);
269 /* Select chip and page */
270 static void
271 spi_goto(robo_info_t *robo, uint8 page)
273 uint8 reg8 = REG_SPI_PAGE; /* page select register */
274 uint8 cmd8;
276 /* Issue the command only when we are on a different page */
277 if (robo->page == page)
278 return;
280 robo->page = page;
282 /* Enable SPI access */
283 spi_select(robo, 1);
285 /* Select new page with CID 0 */
286 cmd8 = ((6 << 4) | /* normal SPI */
287 1); /* write */
288 spi_write(robo, &cmd8, 1);
289 spi_write(robo, &reg8, 1);
290 spi_write(robo, &page, 1);
292 /* Disable SPI access */
293 spi_select(robo, 0);
296 /* Write register thru SPI */
297 static int
298 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
300 int status = 0;
301 uint8 cmd8;
302 union {
303 uint8 val8;
304 uint16 val16;
305 uint32 val32;
306 } bytes;
308 /* validate value length and buffer address */
309 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
310 (len == 4 && !((int)val & 3)));
312 /* Select chip and page */
313 spi_goto(robo, page);
315 /* Enable SPI access */
316 spi_select(robo, 1);
318 /* Write with CID 0 */
319 cmd8 = ((6 << 4) | /* normal SPI */
320 1); /* write */
321 spi_write(robo, &cmd8, 1);
322 spi_write(robo, &addr, 1);
323 switch (len) {
324 case 1:
325 bytes.val8 = *(uint8 *)val;
326 break;
327 case 2:
328 bytes.val16 = htol16(*(uint16 *)val);
329 break;
330 case 4:
331 bytes.val32 = htol32(*(uint32 *)val);
332 break;
334 spi_write(robo, (uint8 *)val, len);
336 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
337 *(uint16 *)val, len));
338 /* Disable SPI access */
339 spi_select(robo, 0);
340 return status;
343 /* Read register thru SPI in fast SPI mode */
344 static int
345 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
347 int status = 0;
348 uint8 cmd8;
349 union {
350 uint8 val8;
351 uint16 val16;
352 uint32 val32;
353 } bytes;
355 /* validate value length and buffer address */
356 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
357 (len == 4 && !((int)val & 3)));
359 /* Select chip and page */
360 spi_goto(robo, page);
362 /* Enable SPI access */
363 spi_select(robo, 1);
365 /* Fast SPI read with CID 0 and byte offset 0 */
366 cmd8 = (1 << 4); /* fast SPI */
367 spi_write(robo, &cmd8, 1);
368 spi_write(robo, &addr, 1);
369 status = spi_read(robo, (uint8 *)&bytes, len);
370 switch (len) {
371 case 1:
372 *(uint8 *)val = bytes.val8;
373 break;
374 case 2:
375 *(uint16 *)val = ltoh16(bytes.val16);
376 break;
377 case 4:
378 *(uint32 *)val = ltoh32(bytes.val32);
379 break;
382 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
383 *(uint16 *)val, len));
385 /* Disable SPI access */
386 spi_select(robo, 0);
387 return status;
390 /* SPI/gpio interface functions */
391 static dev_ops_t spigpio = {
392 gpio_enable,
393 gpio_disable,
394 spi_wreg,
395 spi_rreg,
396 "SPI (GPIO)"
398 #endif /* _CFE_ */
401 /* Access switch registers through MII (MDC/MDIO) */
403 #define MII_MAX_RETRY 100
405 /* Write register thru MDC/MDIO */
406 static int
407 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
409 uint16 cmd16, val16;
410 void *h = robo->h;
411 int i;
412 uint8 *ptr = (uint8 *)val;
414 /* validate value length and buffer address */
415 ASSERT(len == 1 || len == 6 || len == 8 ||
416 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
418 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
419 VARG(val, len), len));
421 /* set page number - MII register 0x10 */
422 if (robo->page != page) {
423 cmd16 = ((page << 8) | /* page number */
424 1); /* mdc/mdio access enable */
425 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
426 robo->page = page;
429 switch (len) {
430 case 8:
431 val16 = ptr[7];
432 val16 = ((val16 << 8) | ptr[6]);
433 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
434 /* FALLTHRU */
436 case 6:
437 val16 = ptr[5];
438 val16 = ((val16 << 8) | ptr[4]);
439 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
440 val16 = ptr[3];
441 val16 = ((val16 << 8) | ptr[2]);
442 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
443 val16 = ptr[1];
444 val16 = ((val16 << 8) | ptr[0]);
445 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
446 break;
448 case 4:
449 val16 = (uint16)((*(uint32 *)val) >> 16);
450 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
451 val16 = (uint16)(*(uint32 *)val);
452 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
453 break;
455 case 2:
456 val16 = *(uint16 *)val;
457 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
458 break;
460 case 1:
461 val16 = *(uint8 *)val;
462 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
463 break;
466 /* set register address - MII register 0x11 */
467 cmd16 = ((reg << 8) | /* register address */
468 1); /* opcode write */
469 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
471 /* is operation finished? */
472 for (i = MII_MAX_RETRY; i > 0; i --) {
473 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
474 if ((val16 & 3) == 0)
475 break;
478 /* timed out */
479 if (!i) {
480 ET_ERROR(("mii_wreg: timeout"));
481 return -1;
483 return 0;
486 /* Read register thru MDC/MDIO */
487 static int
488 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
490 uint16 cmd16, val16;
491 void *h = robo->h;
492 int i;
493 uint8 *ptr = (uint8 *)val;
495 /* validate value length and buffer address */
496 ASSERT(len == 1 || len == 6 || len == 8 ||
497 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
499 /* set page number - MII register 0x10 */
500 if (robo->page != page) {
501 cmd16 = ((page << 8) | /* page number */
502 1); /* mdc/mdio access enable */
503 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
504 robo->page = page;
507 /* set register address - MII register 0x11 */
508 cmd16 = ((reg << 8) | /* register address */
509 2); /* opcode read */
510 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
512 /* is operation finished? */
513 for (i = MII_MAX_RETRY; i > 0; i --) {
514 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
515 if ((val16 & 3) == 0)
516 break;
518 /* timed out */
519 if (!i) {
520 ET_ERROR(("mii_rreg: timeout"));
521 return -1;
524 switch (len) {
525 case 8:
526 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
527 ptr[7] = (val16 >> 8);
528 ptr[6] = (val16 & 0xff);
529 /* FALLTHRU */
531 case 6:
532 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
533 ptr[5] = (val16 >> 8);
534 ptr[4] = (val16 & 0xff);
535 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
536 ptr[3] = (val16 >> 8);
537 ptr[2] = (val16 & 0xff);
538 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
539 ptr[1] = (val16 >> 8);
540 ptr[0] = (val16 & 0xff);
541 break;
543 case 4:
544 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
545 *(uint32 *)val = (((uint32)val16) << 16);
546 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
547 *(uint32 *)val |= val16;
548 break;
550 case 2:
551 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
552 *(uint16 *)val = val16;
553 break;
555 case 1:
556 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
557 *(uint8 *)val = (uint8)(val16 & 0xff);
558 break;
561 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
562 VARG(val, len), len));
564 return 0;
567 /* MII interface functions */
568 static dev_ops_t mdcmdio = {
569 NULL,
570 NULL,
571 mii_wreg,
572 mii_rreg,
573 "MII (MDC/MDIO)"
578 * BCM4707, 4708 and 4709 use ChipcommonB Switch Register Access Bridge Registers (SRAB)
579 * to access the switch registers
582 #ifdef ROBO_SRAB
583 #define SRAB_ENAB() (1)
584 #define NS_CHIPCB_SRAB 0x18007000 /* NorthStar Chip Common B SRAB base */
585 #define SET_ROBO_SRABREGS(robo) ((robo)->srabregs = \
586 (srabregs_t *)REG_MAP(NS_CHIPCB_SRAB, SI_CORE_SIZE))
587 #define SET_ROBO_SRABOPS(robo) ((robo)->ops = &srab)
588 #else
589 #define SRAB_ENAB() (0)
590 #define SET_ROBO_SRABREGS(robo)
591 #define SET_ROBO_SRABOPS(robo)
592 #endif /* ROBO_SRAB */
594 #ifdef ROBO_SRAB
595 #define SRAB_MAX_RETRY 1000
596 static int
597 srab_request_grant(robo_info_t *robo)
599 int i, ret = 0;
600 uint32 val32;
602 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls);
603 val32 |= CFG_F_rcareq_MASK;
604 W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32);
606 /* Wait for command complete */
607 for (i = SRAB_MAX_RETRY * 10; i > 0; i --) {
608 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls);
609 if ((val32 & CFG_F_rcagnt_MASK))
610 break;
613 /* timed out */
614 if (!i) {
615 ET_ERROR(("srab_request_grant: timeout"));
616 ret = -1;
619 return ret;
622 static void
623 srab_release_grant(robo_info_t *robo)
625 uint32 val32;
627 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls);
628 val32 &= ~CFG_F_rcareq_MASK;
629 W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32);
632 static int
633 srab_interface_reset(robo_info_t *robo)
635 int i, ret = 0;
636 uint32 val32;
638 /* Wait for switch initialization complete */
639 for (i = SRAB_MAX_RETRY * 10; i > 0; i --) {
640 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls);
641 if ((val32 & CFG_F_sw_init_done_MASK))
642 break;
645 /* timed out */
646 if (!i) {
647 ET_ERROR(("srab_interface_reset: timeout sw_init_done"));
648 ret = -1;
651 /* Set the SRAU reset bit */
652 W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, CFG_F_sra_rst_MASK);
654 /* Wait for it to auto-clear */
655 for (i = SRAB_MAX_RETRY * 10; i > 0; i --) {
656 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat);
657 if ((val32 & CFG_F_sra_rst_MASK) == 0)
658 break;
661 /* timed out */
662 if (!i) {
663 ET_ERROR(("srab_interface_reset: timeout sra_rst"));
664 ret |= -2;
667 return ret;
670 static int
671 srab_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
673 uint16 val16;
674 uint32 val32;
675 uint32 val_h = 0, val_l = 0;
676 int i, ret = 0;
677 uint8 *ptr = (uint8 *)val;
679 /* validate value length and buffer address */
680 ASSERT(len == 1 || len == 6 || len == 8 ||
681 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
683 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
684 VARG(val, len), len));
686 srab_request_grant(robo);
688 /* Load the value to write */
689 switch (len) {
690 case 8:
691 val16 = ptr[7];
692 val16 = ((val16 << 8) | ptr[6]);
693 val_h = val16 << 16;
694 /* FALLTHRU */
696 case 6:
697 val16 = ptr[5];
698 val16 = ((val16 << 8) | ptr[4]);
699 val_h |= val16;
701 val16 = ptr[3];
702 val16 = ((val16 << 8) | ptr[2]);
703 val_l = val16 << 16;
704 val16 = ptr[1];
705 val16 = ((val16 << 8) | ptr[0]);
706 val_l |= val16;
707 break;
709 case 4:
710 val_l = *(uint32 *)val;
711 break;
713 case 2:
714 val_l = *(uint16 *)val;
715 break;
717 case 1:
718 val_l = *(uint8 *)val;
719 break;
721 W_REG(si_osh(robo->sih), &robo->srabregs->wd_h, val_h);
722 W_REG(si_osh(robo->sih), &robo->srabregs->wd_l, val_l);
724 /* We don't need this variable */
725 if (robo->page != page)
726 robo->page = page;
728 /* Issue the write command */
729 val32 = ((page << CFG_F_sra_page_R)
730 | (reg << CFG_F_sra_offset_R)
731 | CFG_F_sra_gordyn_MASK
732 | CFG_F_sra_write_MASK);
733 W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32);
735 /* Wait for command complete */
736 for (i = SRAB_MAX_RETRY; i > 0; i --) {
737 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat);
738 if ((val32 & CFG_F_sra_gordyn_MASK) == 0)
739 break;
742 /* timed out */
743 if (!i) {
744 ET_ERROR(("srab_wreg: timeout"));
745 srab_interface_reset(robo);
746 ret = -1;
749 srab_release_grant(robo);
751 return ret;
754 static int
755 srab_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
757 uint32 val32;
758 uint32 val_h = 0, val_l = 0;
759 int i, ret = 0;
760 uint8 *ptr = (uint8 *)val;
762 /* validate value length and buffer address */
763 ASSERT(len == 1 || len == 6 || len == 8 ||
764 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
766 srab_request_grant(robo);
768 /* We don't need this variable */
769 if (robo->page != page)
770 robo->page = page;
772 /* Assemble read command */
773 srab_request_grant(robo);
775 val32 = ((page << CFG_F_sra_page_R)
776 | (reg << CFG_F_sra_offset_R)
777 | CFG_F_sra_gordyn_MASK);
778 W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32);
780 /* is operation finished? */
781 for (i = SRAB_MAX_RETRY; i > 0; i --) {
782 val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat);
783 if ((val32 & CFG_F_sra_gordyn_MASK) == 0)
784 break;
787 /* timed out */
788 if (!i) {
789 ET_ERROR(("srab_read: timeout"));
790 srab_interface_reset(robo);
791 ret = -1;
792 goto err;
795 /* Didn't time out, read and return the value */
796 val_h = R_REG(si_osh(robo->sih), &robo->srabregs->rd_h);
797 val_l = R_REG(si_osh(robo->sih), &robo->srabregs->rd_l);
799 switch (len) {
800 case 8:
801 ptr[7] = (val_h >> 24);
802 ptr[6] = ((val_h >> 16) & 0xff);
803 /* FALLTHRU */
805 case 6:
806 ptr[5] = ((val_h >> 8) & 0xff);
807 ptr[4] = (val_h & 0xff);
808 ptr[3] = (val_l >> 24);
809 ptr[2] = ((val_l >> 16) & 0xff);
810 ptr[1] = ((val_l >> 8) & 0xff);
811 ptr[0] = (val_l & 0xff);
812 break;
814 case 4:
815 *(uint32 *)val = val_l;
816 break;
818 case 2:
819 *(uint16 *)val = (uint16)(val_l & 0xffff);
820 break;
822 case 1:
823 *(uint8 *)val = (uint8)(val_l & 0xff);
824 break;
827 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg,
828 VARG(val, len), len));
830 err:
831 srab_release_grant(robo);
833 return ret;
836 /* SRAB interface functions */
837 static dev_ops_t srab = {
838 NULL,
839 NULL,
840 srab_wreg,
841 srab_rreg,
842 "SRAB"
844 #else
845 #define srab_interface_reset(a) do {} while (0)
846 #define srab_rreg(a, b, c, d, e) 0
847 #endif /* ROBO_SRAB */
849 /* High level switch configuration functions. */
851 /* Get access to the RoboSwitch */
852 robo_info_t *
853 bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr)
855 robo_info_t *robo;
856 uint32 reset, idx;
857 #ifndef _CFE_
858 const char *et1port, *et1phyaddr;
859 int mdcport = 0, phyaddr = 0;
860 #endif /* _CFE_ */
861 int lan_portenable = 0;
862 int rc;
864 /* Allocate and init private state */
865 if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) {
866 ET_ERROR(("robo_attach: out of memory, malloced %d bytes",
867 MALLOCED(si_osh(sih))));
868 return NULL;
870 bzero(robo, sizeof(robo_info_t));
872 robo->h = h;
873 robo->sih = sih;
874 robo->vars = vars;
875 robo->miird = miird;
876 robo->miiwr = miiwr;
877 robo->page = -1;
879 if (SRAB_ENAB() && BCM4707_CHIP(sih->chip)) {
880 SET_ROBO_SRABREGS(robo);
883 /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when
884 * romboot CFE loads linux over WAN port and Linux enables LAN ports later
886 if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) !=
887 GPIO_PIN_NOTDEFINED) {
888 lan_portenable = 1 << lan_portenable;
889 si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
890 si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY);
891 bcm_mdelay(5);
894 /* Trigger external reset by nvram variable existance */
895 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
896 GPIO_PIN_NOTDEFINED) {
898 * Reset sequence: RESET low(50ms)->high(20ms)
900 * We have to perform a full sequence for we don't know how long
901 * it has been from power on till now.
903 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
904 reset = 1 << reset;
906 /* Keep RESET low for 50 ms */
907 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
908 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
909 bcm_mdelay(50);
911 /* Keep RESET high for at least 20 ms */
912 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
913 bcm_mdelay(20);
914 } else {
915 /* In case we need it */
916 idx = si_coreidx(sih);
918 if (si_setcore(sih, ROBO_CORE_ID, 0)) {
919 /* If we have an internal robo core, reset it using si_core_reset */
920 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
921 si_core_reset(sih, 0, 0);
922 robo->corerev = si_corerev(sih);
924 else if (sih->chip == BCM5356_CHIP_ID) {
925 /* Testing chipid is a temporary hack. We need to really
926 * figure out how to treat non-cores in ai chips.
928 robo->corerev = 3;
930 else if (SRAB_ENAB() && BCM4707_CHIP(sih->chip)) {
931 srab_interface_reset(robo);
932 rc = srab_rreg(robo, PAGE_MMR, REG_VERSION_ID, &robo->corerev, 1);
934 else {
935 mii_rreg(robo, PAGE_STATUS, REG_STATUS_REV, &robo->corerev, 1);
937 si_setcoreidx(sih, idx);
938 ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev));
941 if (SRAB_ENAB() && BCM4707_CHIP(sih->chip)) {
942 rc = srab_rreg(robo, PAGE_MMR, REG_DEVICE_ID, &robo->devid, sizeof(uint32));
944 ET_MSG(("%s: devid read %ssuccesfully via srab: 0x%x\n",
945 __FUNCTION__, rc ? "un" : "", robo->devid));
947 SET_ROBO_SRABOPS(robo);
948 if ((rc != 0) || (robo->devid == 0)) {
949 ET_ERROR(("%s: error reading devid\n", __FUNCTION__));
950 MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
951 return NULL;
953 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
955 else if (miird && miiwr) {
956 uint16 tmp;
957 int retry_count = 0;
959 /* Read the PHY ID */
960 tmp = miird(h, PSEUDO_PHYAD, 2);
962 /* WAR: Enable mdc/mdio access to the switch registers. Unless
963 * a write to bit 0 of pseudo phy register 16 is done we are
964 * unable to talk to the switch on a customer ref design.
966 if (tmp == 0xffff) {
967 miiwr(h, PSEUDO_PHYAD, 16, 1);
968 tmp = miird(h, PSEUDO_PHYAD, 2);
971 if (tmp != 0xffff) {
972 do {
973 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID,
974 &robo->devid, sizeof(uint16));
975 if (rc != 0)
976 break;
977 retry_count++;
978 } while ((robo->devid == 0) && (retry_count < 10));
980 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n",
981 __FUNCTION__, rc ? "un" : "", robo->devid));
982 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
983 robo->ops = &mdcmdio;
984 if ((rc != 0) || (robo->devid == 0)) {
985 ET_MSG(("%s: error reading devid, assuming 5325e\n",
986 __FUNCTION__));
987 robo->devid = DEVID5325;
990 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
993 if ((robo->devid == DEVID5395) ||
994 (robo->devid == DEVID5397) ||
995 (robo->devid == DEVID5398)) {
996 uint8 srst_ctrl;
998 /* If it is a 539x switch, use the soft reset register */
999 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
1001 /* Reset the 539x switch core and register file */
1002 srst_ctrl = 0x83;
1003 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
1004 srst_ctrl = 0x00;
1005 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
1008 /* Enable switch leds */
1009 if (sih->chip == BCM5356_CHIP_ID) {
1010 if (PMUCTL_ENAB(sih)) {
1011 si_pmu_chipcontrol(sih, 2, (1 << 25), (1 << 25));
1012 /* also enable fast MII clocks */
1013 si_pmu_chipcontrol(sih, 0, (1 << 1), (1 << 1));
1015 } else if ((sih->chip == BCM5357_CHIP_ID) || (sih->chip == BCM53572_CHIP_ID)) {
1016 uint32 led_gpios = 0;
1017 const char *var;
1019 if (((sih->chip == BCM5357_CHIP_ID) && (sih->chippkg != BCM47186_PKG_ID)) ||
1020 ((sih->chip == BCM53572_CHIP_ID) && (sih->chippkg != BCM47188_PKG_ID)))
1021 led_gpios = 0x1f;
1022 var = getvar(vars, "et_swleds");
1023 if (var)
1024 led_gpios = bcm_strtoul(var, NULL, 0);
1025 if (PMUCTL_ENAB(sih) && led_gpios)
1026 si_pmu_chipcontrol(sih, 2, (0x3ff << 8), (led_gpios << 8));
1029 #ifndef _CFE_
1030 if (!robo->ops) {
1031 int mosi, miso, ss, sck;
1033 robo->ops = &spigpio;
1034 robo->devid = DEVID5325;
1036 /* Init GPIO mapping. Default 2, 3, 4, 5 */
1037 ss = getgpiopin(vars, "robo_ss", 2);
1038 if (ss == GPIO_PIN_NOTDEFINED) {
1039 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
1040 goto error;
1042 robo->ss = 1 << ss;
1043 sck = getgpiopin(vars, "robo_sck", 3);
1044 if (sck == GPIO_PIN_NOTDEFINED) {
1045 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
1046 goto error;
1048 robo->sck = 1 << sck;
1049 mosi = getgpiopin(vars, "robo_mosi", 4);
1050 if (mosi == GPIO_PIN_NOTDEFINED) {
1051 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
1052 goto error;
1054 robo->mosi = 1 << mosi;
1055 miso = getgpiopin(vars, "robo_miso", 5);
1056 if (miso == GPIO_PIN_NOTDEFINED) {
1057 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
1058 goto error;
1060 robo->miso = 1 << miso;
1061 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
1062 ss, sck, mosi, miso));
1064 #endif /* _CFE_ */
1066 /* sanity check */
1067 ASSERT(robo->ops);
1068 ASSERT(robo->ops->write_reg);
1069 ASSERT(robo->ops->read_reg);
1070 ASSERT((robo->devid == DEVID5325) ||
1071 (robo->devid == DEVID5395) ||
1072 (robo->devid == DEVID5397) ||
1073 (robo->devid == DEVID5398) ||
1074 (robo->devid == DEVID53115) ||
1075 (robo->devid == DEVID53125) ||
1076 ROBO_IS_BCM5301X(robo->devid));
1078 #ifndef _CFE_
1079 /* nvram variable switch_mode controls the power save mode on the switch
1080 * set the default value in the beginning
1082 robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual");
1083 robo->pwrsave_sleep_time = getintvar(robo->vars, "switch_pwrsave_sleep");
1084 if (robo->pwrsave_sleep_time == 0)
1085 robo->pwrsave_sleep_time = PWRSAVE_SLEEP_TIME;
1086 robo->pwrsave_wake_time = getintvar(robo->vars, "switch_pwrsave_wake");
1087 if (robo->pwrsave_wake_time == 0)
1088 robo->pwrsave_wake_time = PWRSAVE_WAKE_TIME;
1089 robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto");
1091 /* Determining what all phys need to be included in
1092 * power save operation
1094 et1port = getvar(vars, "et1mdcport");
1095 if (et1port)
1096 mdcport = bcm_atoi(et1port);
1098 et1phyaddr = getvar(vars, "et1phyaddr");
1099 if (et1phyaddr)
1100 phyaddr = bcm_atoi(et1phyaddr);
1102 if ((mdcport == 0) && (phyaddr == 4))
1103 /* For 5325F switch we need to do only phys 0-3 */
1104 robo->pwrsave_phys = 0xf;
1105 else
1106 /* By default all 5 phys are put into power save if there is no link */
1107 robo->pwrsave_phys = 0x1f;
1108 #endif /* _CFE_ */
1110 #ifdef PLC
1111 /* See if one of the ports is connected to plc chipset */
1112 robo->plc_hw = (getvar(vars, "plc_vifs") != NULL);
1113 #endif /* PLC */
1115 return robo;
1117 #ifndef _CFE_
1118 error:
1119 bcm_robo_detach(robo);
1120 return NULL;
1121 #endif /* _CFE_ */
1124 /* Release access to the RoboSwitch */
1125 void
1126 bcm_robo_detach(robo_info_t *robo)
1128 if (SRAB_ENAB() && robo->srabregs)
1129 REG_UNMAP(robo->srabregs);
1131 MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t));
1134 /* Enable the device and set it to a known good state */
1136 bcm_robo_enable_device(robo_info_t *robo)
1138 uint8 reg_offset, reg_val;
1139 int ret = 0;
1140 #ifdef PLC
1141 uint32 val32;
1142 #endif /* PLC */
1144 /* Enable management interface access */
1145 if (robo->ops->enable_mgmtif)
1146 robo->ops->enable_mgmtif(robo);
1148 if (robo->devid == DEVID5398) {
1149 /* Disable unused ports: port 6 and 7 */
1150 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
1151 /* Set bits [1:0] to disable RX and TX */
1152 reg_val = 0x03;
1153 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
1154 sizeof(reg_val));
1158 if (robo->devid == DEVID5325) {
1159 /* Must put the switch into Reverse MII mode! */
1161 /* MII port state override (page 0 register 14) */
1162 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
1164 /* Bit 4 enables reverse MII mode */
1165 if (!(reg_val & (1 << 4))) {
1166 /* Enable RvMII */
1167 reg_val |= (1 << 4);
1168 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
1169 sizeof(reg_val));
1171 /* Read back */
1172 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
1173 sizeof(reg_val));
1174 if (!(reg_val & (1 << 4))) {
1175 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
1176 ret = -1;
1181 #ifdef PLC
1182 if (robo->plc_hw) {
1183 val32 = 0x100002;
1184 robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_ATCR, &val32, sizeof(val32));
1186 #endif /* PLC */
1188 /* Disable management interface access */
1189 if (robo->ops->disable_mgmtif)
1190 robo->ops->disable_mgmtif(robo);
1192 return ret;
1195 /* Port flags */
1196 #define FLAG_TAGGED 't' /* output tagged (external ports only) */
1197 #define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */
1198 #define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */
1200 /* port descriptor */
1201 typedef struct {
1202 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
1203 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
1204 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */
1205 uint8 cpu; /* is this cpu port? */
1206 } pdesc_t;
1208 pdesc_t pdesc97[] = {
1209 /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */
1210 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
1211 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
1212 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
1213 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
1214 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
1215 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
1216 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
1217 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
1218 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
1221 pdesc_t pdesc25[] = {
1222 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
1223 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
1224 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
1225 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
1226 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
1227 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
1230 /* Find the first vlanXXXXports which the last port include '*' or 'u' */
1231 static void
1232 robo_cpu_port_upd(robo_info_t *robo, pdesc_t *pdesc, int pdescsz)
1234 int vid;
1236 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1237 char vlanports[] = "vlanXXXXports";
1238 char port[] = "XXXX", *next;
1239 const char *ports, *cur;
1240 int pid, len;
1242 /* no members if VLAN id is out of limitation */
1243 if (vid > VLAN_MAXVID)
1244 return;
1246 /* get vlan member ports from nvram */
1247 sprintf(vlanports, "vlan%dports", vid);
1248 ports = getvar(robo->vars, vlanports);
1249 if (!ports)
1250 continue;
1252 /* search last port include '*' or 'u' */
1253 for (cur = ports; cur; cur = next) {
1254 /* tokenize the port list */
1255 while (*cur == ' ')
1256 cur ++;
1257 next = bcmstrstr(cur, " ");
1258 len = next ? next - cur : strlen(cur);
1259 if (!len)
1260 break;
1261 if (len > sizeof(port) - 1)
1262 len = sizeof(port) - 1;
1263 strncpy(port, cur, len);
1264 port[len] = 0;
1266 /* make sure port # is within the range */
1267 pid = bcm_atoi(port);
1268 if (pid >= pdescsz) {
1269 ET_ERROR(("robo_cpu_upd: port %d in vlan%dports is out "
1270 "of range[0-%d]\n", pid, vid, pdescsz));
1271 continue;
1274 if (strchr(port, FLAG_LAN) || strchr(port, FLAG_UNTAG)) {
1275 /* Change it and return */
1276 pdesc[pid].cpu = 1;
1277 return;
1283 /* Configure the VLANs */
1285 bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr)
1287 uint8 val8;
1288 uint16 val16;
1289 uint32 val32;
1290 pdesc_t *pdesc;
1291 int pdescsz;
1292 uint16 vid;
1293 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
1295 /* Enable management interface access */
1296 if (robo->ops->enable_mgmtif)
1297 robo->ops->enable_mgmtif(robo);
1299 /* setup global vlan configuration */
1300 /* VLAN Control 0 Register (Page 0x34, Address 0) */
1301 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1302 val8 |= ((1 << 7) | /* enable 802.1Q VLAN */
1303 (3 << 5)); /* individual VLAN learning mode */
1304 if (robo->devid == DEVID5325)
1305 val8 &= ~(1 << 1); /* must clear reserved bit 1 */
1306 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1307 /* VLAN Control 1 Register (Page 0x34, Address 1) */
1308 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1309 val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */
1310 (1 << 3)); /* enable RSV multicast V Untagmap */
1311 if (robo->devid == DEVID5325)
1312 val8 |= (1 << 1); /* enable RSV multicast V Tagging */
1313 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1315 arl_entry[0] = mac_addr[5];
1316 arl_entry[1] = mac_addr[4];
1317 arl_entry[2] = mac_addr[3];
1318 arl_entry[3] = mac_addr[2];
1319 arl_entry[4] = mac_addr[1];
1320 arl_entry[5] = mac_addr[0];
1322 if (robo->devid == DEVID5325) {
1323 /* Init the entry 1 of the bin */
1324 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1,
1325 arl_entry1, sizeof(arl_entry1));
1326 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1,
1327 arl_entry1, 1);
1329 /* Init the entry 0 of the bin */
1330 arl_entry[6] = 0x8; /* Port Id: MII */
1331 arl_entry[7] = 0xc0; /* Static Entry, Valid */
1333 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
1334 arl_entry, sizeof(arl_entry));
1335 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
1336 arl_entry, ETHER_ADDR_LEN);
1338 /* VLAN Control 4 Register (Page 0x34, Address 4) */
1339 val8 = (1 << 6); /* drop frame with VID violation */
1340 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1342 /* VLAN Control 5 Register (Page 0x34, Address 5) */
1343 val8 = (1 << 3); /* drop frame when miss V table */
1344 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1346 pdesc = pdesc25;
1347 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1348 } else {
1349 /* Initialize the MAC Addr Index Register */
1350 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX,
1351 arl_entry, ETHER_ADDR_LEN);
1353 pdesc = pdesc97;
1354 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1356 if (SRAB_ENAB() && ROBO_IS_BCM5301X(robo->devid))
1357 robo_cpu_port_upd(robo, pdesc97, pdescsz);
1360 /* setup each vlan. max. 16 vlans. */
1361 /* force vlan id to be equal to vlan number */
1362 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1363 char vlanports[] = "vlanXXXXports";
1364 char port[] = "XXXX", *next;
1365 const char *ports, *cur;
1366 uint32 untag = 0;
1367 uint32 member = 0;
1368 int pid, len;
1370 /* no members if VLAN id is out of limitation */
1371 if (vid > VLAN_MAXVID)
1372 goto vlan_setup;
1374 /* get vlan member ports from nvram */
1375 sprintf(vlanports, "vlan%dports", vid);
1376 ports = getvar(robo->vars, vlanports);
1378 /* In 539x vid == 0 us invalid?? */
1379 if ((robo->devid != DEVID5325) && (vid == 0)) {
1380 if (ports)
1381 ET_ERROR(("VID 0 is set in nvram, Ignoring\n"));
1382 continue;
1385 /* disable this vlan if not defined */
1386 if (!ports)
1387 goto vlan_setup;
1390 * setup each port in the vlan. cpu port needs special handing
1391 * (with or without output tagging) to support linux/pmon/cfe.
1393 for (cur = ports; cur; cur = next) {
1394 /* tokenize the port list */
1395 while (*cur == ' ')
1396 cur ++;
1397 next = bcmstrstr(cur, " ");
1398 len = next ? next - cur : strlen(cur);
1399 if (!len)
1400 break;
1401 if (len > sizeof(port) - 1)
1402 len = sizeof(port) - 1;
1403 strncpy(port, cur, len);
1404 port[len] = 0;
1406 /* make sure port # is within the range */
1407 pid = bcm_atoi(port);
1408 if (pid >= pdescsz) {
1409 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out "
1410 "of range[0-%d]\n", pid, vid, pdescsz));
1411 continue;
1414 /* build VLAN registers values */
1415 #ifndef _CFE_
1416 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) ||
1417 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG)))
1418 #endif
1419 untag |= pdesc[pid].untag;
1421 member |= pdesc[pid].member;
1423 /* set port tag - applies to untagged ingress frames */
1424 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */
1425 #ifdef _CFE_
1426 #define FL FLAG_LAN
1427 #else
1428 #define FL FLAG_UNTAG
1429 #endif /* _CFE_ */
1430 if (!pdesc[pid].cpu || strchr(port, FL)) {
1431 val16 = ((0 << 13) | /* priority - always 0 */
1432 vid); /* vlan id */
1433 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr,
1434 &val16, sizeof(val16));
1438 /* Add static ARL entries */
1439 if (robo->devid == DEVID5325) {
1440 val8 = vid;
1441 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0,
1442 &val8, sizeof(val8));
1443 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1444 &val8, sizeof(val8));
1446 /* Write the entry */
1447 val8 = 0x80;
1448 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1449 &val8, sizeof(val8));
1450 /* Wait for write to complete */
1451 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1452 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1453 100 /* usec */);
1454 } else {
1455 /* Set the VLAN Id in VLAN ID Index Register */
1456 val8 = vid;
1457 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX,
1458 &val8, sizeof(val8));
1460 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1461 * Register.
1463 arl_entry[6] = vid;
1464 arl_entry[7] = 0x0;
1465 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0,
1466 arl_entry, sizeof(arl_entry));
1468 /* Set the Static bit , Valid bit and Port ID fields in
1469 * ARL Table Data Entry 0 Register
1471 val16 = 0xc008;
1472 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0,
1473 &val16, sizeof(val16));
1475 /* Clear the ARL_R/W bit and set the START/DONE bit in
1476 * the ARL Read/Write Control Register.
1478 val8 = 0x80;
1479 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1480 &val8, sizeof(val8));
1481 /* Wait for write to complete */
1482 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL,
1483 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1484 100 /* usec */);
1487 vlan_setup:
1488 /* setup VLAN ID and VLAN memberships */
1490 val32 = (untag | /* untag enable */
1491 member); /* vlan members */
1492 if (robo->devid == DEVID5325) {
1493 if (robo->corerev < 3) {
1494 val32 |= ((1 << 20) | /* valid write */
1495 ((vid >> 4) << 12)); /* vlan id bit[11:4] */
1496 } else {
1497 val32 |= ((1 << 24) | /* valid write */
1498 (vid << 12)); /* vlan id bit[11:4] */
1500 ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32));
1502 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1503 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1504 sizeof(val32));
1505 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1506 val16 = ((1 << 13) | /* start command */
1507 (1 << 12) | /* write state */
1508 vid); /* vlan id */
1509 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1510 sizeof(val16));
1511 } else {
1512 uint8 vtble, vtbli, vtbla;
1514 if ((robo->devid == DEVID5395) ||
1515 (robo->devid == DEVID53115) ||
1516 (robo->devid == DEVID53125) ||
1517 ROBO_IS_BCM5301X(robo->devid)) {
1518 vtble = REG_VTBL_ENTRY_5395;
1519 vtbli = REG_VTBL_INDX_5395;
1520 vtbla = REG_VTBL_ACCESS_5395;
1521 } else {
1522 vtble = REG_VTBL_ENTRY;
1523 vtbli = REG_VTBL_INDX;
1524 vtbla = REG_VTBL_ACCESS;
1527 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1528 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1529 sizeof(val32));
1530 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1531 val16 = vid; /* vlan id */
1532 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1533 sizeof(val16));
1535 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1536 val8 = ((1 << 7) | /* start command */
1537 0); /* write */
1538 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1539 sizeof(val8));
1543 if (robo->devid == DEVID5325) {
1544 /* setup priority mapping - applies to tagged ingress frames */
1545 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
1546 val32 = ((0 << 0) | /* 0 -> 0 */
1547 (1 << 3) | /* 1 -> 1 */
1548 (2 << 6) | /* 2 -> 2 */
1549 (3 << 9) | /* 3 -> 3 */
1550 (4 << 12) | /* 4 -> 4 */
1551 (5 << 15) | /* 5 -> 5 */
1552 (6 << 18) | /* 6 -> 6 */
1553 (7 << 21)); /* 7 -> 7 */
1554 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1557 if (robo->devid == DEVID53115) {
1558 /* Configure the priority system to use to determine the TC of
1559 * ingress frames. Use DiffServ TC mapping, otherwise 802.1p
1560 * TC mapping, otherwise MAC based TC mapping.
1562 val8 = ((0 << 6) | /* Disable port based QoS */
1563 (2 << 2)); /* QoS priority selection */
1564 robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8));
1566 /* Configure tx queues scheduling mechanism */
1567 val8 = (3 << 0); /* Strict priority */
1568 robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8));
1570 /* Enable 802.1p Priority to TC mapping for individual ports */
1571 val16 = 0x11f;
1572 robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16));
1574 /* Configure the TC to COS mapping. This determines the egress
1575 * transmit queue.
1577 val16 = ((1 << 0) | /* Pri 0 mapped to TXQ 1 */
1578 (0 << 2) | /* Pri 1 mapped to TXQ 0 */
1579 (0 << 4) | /* Pri 2 mapped to TXQ 0 */
1580 (1 << 6) | /* Pri 3 mapped to TXQ 1 */
1581 (2 << 8) | /* Pri 4 mapped to TXQ 2 */
1582 (2 << 10) | /* Pri 5 mapped to TXQ 2 */
1583 (3 << 12) | /* Pri 6 mapped to TXQ 3 */
1584 (3 << 14)); /* Pri 7 mapped to TXQ 3 */
1585 robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16));
1588 /* Disable management interface access */
1589 if (robo->ops->disable_mgmtif)
1590 robo->ops->disable_mgmtif(robo);
1592 return 0;
1595 /* Enable switching/forwarding */
1597 bcm_robo_enable_switch(robo_info_t *robo)
1599 int i, max_port_ind, ret = 0;
1600 uint8 val8;
1602 /* Enable management interface access */
1603 if (robo->ops->enable_mgmtif)
1604 robo->ops->enable_mgmtif(robo);
1606 /* Switch Mode register (Page 0, Address 0x0B) */
1607 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1609 /* Bit 1 enables switching/forwarding */
1610 if (!(val8 & (1 << 1))) {
1611 /* Set unmanaged mode */
1612 val8 &= (~(1 << 0));
1614 /* Enable forwarding */
1615 val8 |= (1 << 1);
1616 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1618 /* Read back */
1619 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1620 if (!(val8 & (1 << 1))) {
1621 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n"));
1622 ret = -1;
1625 /* No spanning tree for unmanaged mode */
1626 val8 = 0;
1627 if (robo->devid == DEVID5398 || ROBO_IS_BCM5301X(robo->devid))
1628 max_port_ind = REG_CTRL_PORT7;
1629 else
1630 max_port_ind = REG_CTRL_PORT4;
1632 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
1633 if (ROBO_IS_BCM5301X(robo->devid) && i == REG_CTRL_PORT6)
1634 continue;
1635 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1638 /* No spanning tree on IMP port too */
1639 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8));
1642 if (robo->devid == DEVID53125) {
1643 /* Over ride IMP port status to make it link by default */
1644 val8 = 0;
1645 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1646 val8 |= 0xb1; /* Make Link pass and override it. */
1647 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1648 /* Init the EEE feature */
1649 robo_eee_advertise_init(robo);
1652 if (SRAB_ENAB() && ROBO_IS_BCM5301X(robo->devid)) {
1653 int pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1654 uint8 gmiiport;
1657 * Port N GMII Port States Override Register (Page 0x00, address Offset: 0x0e,
1658 * 0x58-0x5d and 0x5f ) SPEED/ DUPLEX_MODE/ LINK_STS
1660 #ifdef CFG_SIM
1661 /* Over ride Port0 ~ Port4 status to make it link by default */
1662 /* (Port0 ~ Port4) LINK_STS bit default is 0x1(link up), do it anyway */
1663 for (i = REG_CTRL_PORT0_GMIIPO; i <= REG_CTRL_PORT4_GMIIPO; i++) {
1664 val8 = 0;
1665 robo->ops->read_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1666 val8 |= 0x71; /* Make it link by default. */
1667 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
1669 #endif
1671 /* Find the first cpu port and do software override */
1672 for (i = 0; i < pdescsz; i++) {
1673 /* Port 6 is not able to use */
1674 if (i == 6 || !pdesc97[i].cpu)
1675 continue;
1677 if (i == pdescsz - 1)
1678 gmiiport = REG_CTRL_MIIPO;
1679 else
1680 gmiiport = REG_CTRL_PORT0_GMIIPO + i;
1682 /* Software override port speed and link up */
1683 val8 = 0;
1684 robo->ops->read_reg(robo, PAGE_CTRL, gmiiport, &val8, sizeof(val8));
1685 /* (GMII_SPEED_UP_2G|SW_OVERRIDE|TXFLOW_CNTL|RXFLOW_CNTL|LINK_STS) */
1686 val8 |= 0xf1;
1687 robo->ops->write_reg(robo, PAGE_CTRL, gmiiport, &val8, sizeof(val8));
1688 break;
1692 /* Drop reserved bit, if any */
1693 robo->ops->read_reg(robo, PAGE_CTRL, 0x2f, &val8, sizeof(val8));
1694 if (robo->devid != DEVID5325 && val8 & (1 << 1)) {
1695 val8 &= ~(1 << 1);
1696 robo->ops->write_reg(robo, PAGE_CTRL, 0x2f, &val8, sizeof(val8));
1699 /* Disable management interface access */
1700 if (robo->ops->disable_mgmtif)
1701 robo->ops->disable_mgmtif(robo);
1703 return ret;
1706 #ifdef BCMDBG
1707 void
1708 robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b)
1710 uint8 val8;
1711 uint16 val16;
1712 uint32 val32;
1713 pdesc_t *pdesc;
1714 int pdescsz;
1715 int i;
1717 bcm_bprintf(b, "%s:\n", robo->ops->desc);
1718 if (robo->miird == NULL) {
1719 bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n",
1720 robo->ss, robo->sck, robo->mosi, robo->miso);
1723 /* Enable management interface access */
1724 if (robo->ops->enable_mgmtif)
1725 robo->ops->enable_mgmtif(robo);
1727 /* Dump registers interested */
1728 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1729 bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8);
1730 if (robo->devid == DEVID5325) {
1731 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8));
1732 bcm_bprintf(b, "(0x00,0x0E)MII port state override regsiter: 0x%02x\n", val8);
1734 if (robo->miird == NULL)
1735 goto exit;
1736 if (robo->devid == DEVID5325) {
1737 pdesc = pdesc25;
1738 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1739 } else {
1740 pdesc = pdesc97;
1741 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1744 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1745 bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8);
1746 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1747 bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8);
1748 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1749 if (robo->devid == DEVID5325) {
1750 bcm_bprintf(b, "(0x34,0x04)VLAN control 4 register: 0x%02x\n", val8);
1751 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1752 bcm_bprintf(b, "(0x34,0x05)VLAN control 5 register: 0x%02x\n", val8);
1754 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
1755 bcm_bprintf(b, "(0x34,0x20)Prio Re-map: 0x%08x\n", val32);
1757 for (i = 0; i <= VLAN_MAXVID; i++) {
1758 val16 = (1 << 13) /* start command */
1759 | i; /* vlan id */
1760 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1761 sizeof(val16));
1762 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_READ, &val32, sizeof(val32));
1763 bcm_bprintf(b, "(0x34,0xc)VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1764 i, (val32 & 0x0fc0) >> 6, (val32 & 0x003f));
1767 } else {
1768 uint8 vtble, vtbli, vtbla;
1770 if ((robo->devid == DEVID5395) ||
1771 (robo->devid == DEVID53115) ||
1772 (robo->devid == DEVID53125) ||
1773 ROBO_IS_BCM5301X(robo->devid)) {
1774 vtble = REG_VTBL_ENTRY_5395;
1775 vtbli = REG_VTBL_INDX_5395;
1776 vtbla = REG_VTBL_ACCESS_5395;
1777 } else {
1778 vtble = REG_VTBL_ENTRY;
1779 vtbli = REG_VTBL_INDX;
1780 vtbla = REG_VTBL_ACCESS;
1783 for (i = 0; i <= VLAN_MAXVID; i++) {
1785 * VLAN Table Address Index Register
1786 * (Page 0x05, Address 0x61-0x62/0x81-0x82)
1788 val16 = i; /* vlan id */
1789 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1790 sizeof(val16));
1791 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1792 val8 = ((1 << 7) | /* start command */
1793 1); /* read */
1794 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1795 sizeof(val8));
1796 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1797 robo->ops->read_reg(robo, PAGE_VTBL, vtble, &val32,
1798 sizeof(val32));
1799 bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n",
1800 i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff));
1803 for (i = 0; i < pdescsz; i++) {
1804 robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16));
1805 bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16);
1808 exit:
1809 /* Disable management interface access */
1810 if (robo->ops->disable_mgmtif)
1811 robo->ops->disable_mgmtif(robo);
1813 #endif /* BCMDBG */
1815 #ifndef _CFE_
1817 * Update the power save configuration for ports that changed link status.
1819 void
1820 robo_power_save_mode_update(robo_info_t *robo)
1822 uint phy;
1824 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1825 if (robo->pwrsave_mode_auto & (1 << phy)) {
1826 ET_MSG(("%s: set port %d to auto mode\n",
1827 __FUNCTION__, phy));
1828 robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy);
1832 return;
1835 static int32
1836 robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy)
1838 uint16 val16;
1840 if (robo->devid == DEVID53115) {
1841 /* For 53115 0x1C is the MII address of the auto power
1842 * down register. Bit 5 is enabling the mode
1843 * bits has the following purpose
1844 * 15 - write enable 10-14 shadow register select 01010 for
1845 * auto power 6-9 reserved 5 auto power mode enable
1846 * 4 sleep timer select : 1 means 5.4 sec
1847 * 0-3 wake up timer select: 0xF 1.26 sec
1849 val16 = 0xa800;
1850 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, val16);
1851 } else if ((robo->sih->chip == BCM5356_CHIP_ID) || (robo->sih->chip == BCM5357_CHIP_ID)) {
1852 /* To disable auto power down mode
1853 * clear bit 5 of Aux Status 2 register
1854 * (Shadow reg 0x1b). Shadow register
1855 * access is enabled by writing
1856 * 1 to bit 7 of MII register 0x1f.
1858 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1859 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1860 (val16 | (1 << 7)));
1862 /* Disable auto power down by clearing
1863 * bit 5 of to Aux Status 2 reg.
1865 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
1866 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
1867 (val16 & ~(1 << 5)));
1869 /* Undo shadow access */
1870 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
1871 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
1872 (val16 & ~(1 << 7)));
1873 } else
1874 return -1;
1876 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_AUTO;
1878 return 0;
1881 static int32
1882 robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy)
1884 uint8 val8;
1885 uint16 val16;
1887 if ((robo->devid == DEVID53115) ||
1888 (robo->sih->chip == BCM5356_CHIP_ID)) {
1889 /* For 53115 0x0 is the MII control register
1890 * Bit 11 is the power down mode bit
1892 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
1893 val16 &= 0xf7ff;
1894 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16);
1895 } else if (ROBO_IS_BCM5301X(robo->devid)) {
1896 robo->ops->read_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16));
1897 val16 &= 0xf7ff;
1898 robo->ops->write_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16));
1899 } else if (robo->devid == DEVID5325) {
1900 if ((robo->sih->chip == BCM5357_CHIP_ID) ||
1901 (robo->sih->chip == BCM4749_CHIP_ID) ||
1902 (robo->sih->chip == BCM53572_CHIP_ID)) {
1903 robo->miiwr(robo->h, phy, 0x1f, 0x8b);
1904 robo->miiwr(robo->h, phy, 0x14, 0x0008);
1905 robo->miiwr(robo->h, phy, 0x10, 0x0400);
1906 robo->miiwr(robo->h, phy, 0x11, 0x0000);
1907 robo->miiwr(robo->h, phy, 0x1f, 0x0b);
1908 } else {
1909 if (phy == 0)
1910 return -1;
1911 /* For 5325 page 0x00 address 0x0F is the power down
1912 * mode register. Bits 1-4 determines which of the
1913 * phys are enabled for this mode
1915 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1916 &val8, sizeof(val8));
1917 val8 &= ~(0x1 << phy);
1918 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN,
1919 &val8, sizeof(val8));
1921 } else
1922 return -1;
1924 robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_MANUAL;
1926 return 0;
1930 * Function which periodically checks the power save mode on the switch
1932 int32
1933 robo_power_save_toggle(robo_info_t *robo, int32 normal)
1935 int32 phy;
1936 uint16 link_status;
1939 /* read the link status of all ports */
1940 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
1941 &link_status, sizeof(uint16));
1942 link_status &= 0x1f;
1944 /* Take the phys out of the manual mode first so that link status
1945 * can be checked. Once out of that mode check the link status
1946 * and if any of the link is up do not put that phy into
1947 * manual power save mode
1949 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
1950 /* When auto+manual modes are enabled we toggle between
1951 * manual and auto modes. When only manual mode is enabled
1952 * we toggle between manual and normal modes. When only
1953 * auto mode is enabled there is no need to do anything
1954 * here since auto mode is one time config.
1956 if ((robo->pwrsave_phys & (1 << phy)) &&
1957 (robo->pwrsave_mode_manual & (1 << phy))) {
1958 if (!normal) {
1959 /* Take the port out of the manual mode */
1960 robo_power_save_mode_clear_manual(robo, phy);
1961 } else {
1962 /* If the link is down put it back to manual else
1963 * remain in the current state
1965 if (!(link_status & (1 << phy))) {
1966 ET_MSG(("%s: link down, set port %d to man mode\n",
1967 __FUNCTION__, phy));
1968 robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy);
1974 return 0;
1978 * Switch the ports to normal mode.
1980 static int32
1981 robo_power_save_mode_normal(robo_info_t *robo, int32 phy)
1983 int32 error = 0;
1985 /* If the phy in the power save mode come out of it */
1986 switch (robo->pwrsave_mode_phys[phy]) {
1987 case ROBO_PWRSAVE_AUTO_MANUAL:
1988 case ROBO_PWRSAVE_AUTO:
1989 error = robo_power_save_mode_clear_auto(robo, phy);
1990 if ((error == -1) ||
1991 (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO))
1992 break;
1994 case ROBO_PWRSAVE_MANUAL:
1995 error = robo_power_save_mode_clear_manual(robo, phy);
1996 break;
1998 default:
1999 break;
2002 return error;
2006 * Switch all the inactive ports to auto power down mode.
2008 static int32
2009 robo_power_save_mode_auto(robo_info_t *robo, int32 phy)
2011 uint16 val16;
2013 /* If the switch supports auto power down enable that */
2014 if (robo->devid == DEVID53115) {
2015 /* For 53115 0x1C is the MII address of the auto power
2016 * down register. Bit 5 is enabling the mode
2017 * bits has the following purpose
2018 * 15 - write enable 10-14 shadow register select 01010 for
2019 * auto power 6-9 reserved 5 auto power mode enable
2020 * 4 sleep timer select : 1 means 5.4 sec
2021 * 0-3 wake up timer select: 0xF 1.26 sec
2023 robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA83F);
2024 } else if ((robo->sih->chip == BCM5356_CHIP_ID) || (robo->sih->chip == BCM5357_CHIP_ID)) {
2025 /* To enable auto power down mode set bit 5 of
2026 * Auxillary Status 2 register (Shadow reg 0x1b)
2027 * Shadow register access is enabled by writing
2028 * 1 to bit 7 of MII register 0x1f.
2030 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
2031 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
2032 (val16 | (1 << 7)));
2034 /* Enable auto power down by writing to Auxillary
2035 * Status 2 reg.
2037 val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2);
2038 robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2,
2039 (val16 | (1 << 5)));
2041 /* Undo shadow access */
2042 val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST);
2043 robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST,
2044 (val16 & ~(1 << 7)));
2045 } else
2046 return -1;
2048 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_AUTO;
2050 return 0;
2054 * Switch all the inactive ports to manual power down mode.
2056 static int32
2057 robo_power_save_mode_manual(robo_info_t *robo, int32 phy)
2059 uint8 val8;
2060 uint16 val16;
2062 /* For both 5325 and 53115 the link status register is the same */
2063 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
2064 &val16, sizeof(val16));
2065 if (val16 & (0x1 << phy))
2066 return 0;
2068 /* If the switch supports manual power down enable that */
2069 if ((robo->devid == DEVID53115) ||
2070 (robo->sih->chip == BCM5356_CHIP_ID)) {
2071 /* For 53115 0x0 is the MII control register bit 11 is the
2072 * power down mode bit
2074 val16 = robo->miird(robo->h, phy, REG_MII_CTRL);
2075 robo->miiwr(robo->h, phy, REG_MII_CTRL, val16 | 0x800);
2076 } else if (ROBO_IS_BCM5301X(robo->devid)) {
2077 robo->ops->read_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16));
2078 val16 |= 0x800;
2079 robo->ops->write_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16));
2080 } else if (robo->devid == DEVID5325) {
2081 if ((robo->sih->chip == BCM5357_CHIP_ID) ||
2082 (robo->sih->chip == BCM4749_CHIP_ID)||
2083 (robo->sih->chip == BCM53572_CHIP_ID)) {
2084 robo->miiwr(robo->h, phy, 0x1f, 0x8b);
2085 robo->miiwr(robo->h, phy, 0x14, 0x6000);
2086 robo->miiwr(robo->h, phy, 0x10, 0x700);
2087 robo->miiwr(robo->h, phy, 0x11, 0x1000);
2088 robo->miiwr(robo->h, phy, 0x1f, 0x0b);
2089 } else {
2090 if (phy == 0)
2091 return -1;
2092 /* For 5325 page 0x00 address 0x0F is the power down mode
2093 * register. Bits 1-4 determines which of the phys are enabled
2094 * for this mode
2096 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
2097 sizeof(val8));
2098 val8 |= (1 << phy);
2099 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8,
2100 sizeof(val8));
2102 } else
2103 return -1;
2105 robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_MANUAL;
2107 return 0;
2111 * Set power save modes on the robo switch
2113 int32
2114 robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy)
2116 int32 error = -1;
2118 if (phy > MAX_NO_PHYS) {
2119 ET_ERROR(("Passed parameter phy is out of range\n"));
2120 return -1;
2123 /* Enable management interface access */
2124 if (robo->ops->enable_mgmtif)
2125 robo->ops->enable_mgmtif(robo);
2127 switch (mode) {
2128 case ROBO_PWRSAVE_NORMAL:
2129 /* If the phy in the power save mode come out of it */
2130 error = robo_power_save_mode_normal(robo, phy);
2131 break;
2133 case ROBO_PWRSAVE_AUTO_MANUAL:
2134 /* If the switch supports auto and manual power down
2135 * enable both of them
2137 case ROBO_PWRSAVE_AUTO:
2138 error = robo_power_save_mode_auto(robo, phy);
2139 if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO))
2140 break;
2142 case ROBO_PWRSAVE_MANUAL:
2143 error = robo_power_save_mode_manual(robo, phy);
2144 break;
2146 default:
2147 break;
2150 /* Disable management interface access */
2151 if (robo->ops->disable_mgmtif)
2152 robo->ops->disable_mgmtif(robo);
2154 return error;
2158 * Get the current power save mode of the switch ports.
2160 int32
2161 robo_power_save_mode_get(robo_info_t *robo, int32 phy)
2163 ASSERT(robo);
2165 if (phy >= MAX_NO_PHYS)
2166 return -1;
2168 return robo->pwrsave_mode_phys[phy];
2172 * Configure the power save mode for the switch ports.
2174 int32
2175 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy)
2177 int32 error;
2179 ASSERT(robo);
2181 if (phy >= MAX_NO_PHYS)
2182 return -1;
2184 error = robo_power_save_mode(robo, mode, phy);
2186 if (error)
2187 return error;
2189 if (mode == ROBO_PWRSAVE_NORMAL) {
2190 robo->pwrsave_mode_manual &= ~(1 << phy);
2191 robo->pwrsave_mode_auto &= ~(1 << phy);
2192 } else if (mode == ROBO_PWRSAVE_AUTO) {
2193 robo->pwrsave_mode_auto |= (1 << phy);
2194 robo->pwrsave_mode_manual &= ~(1 << phy);
2195 robo_power_save_mode_clear_manual(robo, phy);
2196 } else if (mode == ROBO_PWRSAVE_MANUAL) {
2197 robo->pwrsave_mode_manual |= (1 << phy);
2198 robo->pwrsave_mode_auto &= ~(1 << phy);
2199 robo_power_save_mode_clear_auto(robo, phy);
2200 } else {
2201 robo->pwrsave_mode_auto |= (1 << phy);
2202 robo->pwrsave_mode_manual |= (1 << phy);
2205 return 0;
2207 #endif /* _CFE_ */
2209 #ifdef PLC
2210 void
2211 robo_plc_hw_init(robo_info_t *robo)
2213 uint8 val8;
2215 ASSERT(robo);
2217 if (!robo->plc_hw)
2218 return;
2220 /* Enable management interface access */
2221 if (robo->ops->enable_mgmtif)
2222 robo->ops->enable_mgmtif(robo);
2224 if (robo->devid == DEVID53115) {
2225 /* Fix the duplex mode and speed for Port 5 */
2226 val8 = ((1 << 6) | (1 << 2) | 3);
2227 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIP5O, &val8, sizeof(val8));
2228 } else if ((robo->sih->chip == BCM5357_CHIP_ID) &&
2229 (robo->sih->chippkg == BCM5358_PKG_ID)) {
2230 /* Fix the duplex mode and speed for Port 4 (MII port). Force
2231 * full duplex mode and set speed to 100.
2233 si_pmu_chipcontrol(robo->sih, 2, (1 << 1) | (1 << 2), (1 << 1) | (1 << 2));
2236 /* Disable management interface access */
2237 if (robo->ops->disable_mgmtif)
2238 robo->ops->disable_mgmtif(robo);
2240 ET_MSG(("%s: Configured PLC MII interface\n", __FUNCTION__));
2242 #endif /* PLC */
2244 /* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */
2246 static void
2247 robo_link_down(robo_info_t *robo, int32 phy)
2249 if (robo->devid != DEVID53125)
2250 return;
2252 printf("robo_link_down: applying EEE WAR for 53125 port %d link-down\n", phy);
2254 robo->miiwr(robo->h, phy, 0x18, 0x0c00);
2255 robo->miiwr(robo->h, phy, 0x17, 0x001a);
2256 robo->miiwr(robo->h, phy, 0x15, 0x0007);
2257 robo->miiwr(robo->h, phy, 0x18, 0x0400);
2260 static void
2261 robo_link_up(robo_info_t *robo, int32 phy)
2263 if (robo->devid != DEVID53125)
2264 return;
2266 printf("robo_link_down: applying EEE WAR for 53125 port %d link-up\n", phy);
2268 robo->miiwr(robo->h, phy, 0x18, 0x0c00);
2269 robo->miiwr(robo->h, phy, 0x17, 0x001a);
2270 robo->miiwr(robo->h, phy, 0x15, 0x0003);
2271 robo->miiwr(robo->h, phy, 0x18, 0x0400);
2274 void
2275 robo_watchdog(robo_info_t *robo)
2277 int32 phy;
2278 uint16 link_status;
2279 static int first = 1;
2281 if (robo->devid != DEVID53125)
2282 return;
2284 if (!robo->eee_status)
2285 return;
2287 /* read the link status of all ports */
2288 robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK,
2289 &link_status, sizeof(uint16));
2290 link_status &= 0x1f;
2291 if (first || (link_status != robo->prev_status)) {
2292 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
2293 if (first) {
2294 if (!(link_status & (1 << phy)))
2295 robo_link_down(robo, phy);
2296 } else if ((link_status & (1 << phy)) != (robo->prev_status & (1 << phy))) {
2297 if (!(link_status & (1 << phy)))
2298 robo_link_down(robo, phy);
2299 else
2300 robo_link_up(robo, phy);
2303 robo->prev_status = link_status;
2304 first = 0;
2308 void
2309 robo_eee_advertise_init(robo_info_t *robo)
2311 uint16 val16;
2312 int32 phy;
2314 ASSERT(robo);
2316 val16 = 0;
2317 robo->ops->read_reg(robo, 0x92, 0x00, &val16, sizeof(val16));
2318 if (val16 == 0x1f) {
2319 robo->eee_status = TRUE;
2320 printf("bcm_robo_enable_switch: EEE is enabled\n");
2321 } else {
2322 for (phy = 0; phy < MAX_NO_PHYS; phy++) {
2323 /* select DEVAD 7 */
2324 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007);
2325 /* select register 3Ch */
2326 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c);
2327 /* read command */
2328 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0xc007);
2329 /* read data */
2330 val16 = robo->miird(robo->h, phy, REG_MII_CLAUSE_45_CTL2);
2331 val16 &= ~0x6;
2332 /* select DEVAD 7 */
2333 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007);
2334 /* select register 3Ch */
2335 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c);
2336 /* write command */
2337 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x4007);
2338 /* write data */
2339 robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, val16);
2341 robo->eee_status = FALSE;
2342 printf("bcm_robo_enable_switch: EEE is disabled\n");