1/* 2 * Broadcom 53xx RoboSwitch device driver. 3 * 4 * Copyright 2007, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 11 * 12 * $Id: bcmrobo.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 13 */ 14 15 16#include <typedefs.h> 17#include <osl.h> 18#include <bcmutils.h> 19#include <sbutils.h> 20#include <sbconfig.h> 21#include <bcmutils.h> 22#include <bcmendian.h> 23#include <bcmparams.h> 24#include <bcmnvram.h> 25#include <bcmdevs.h> 26#include <bcmrobo.h> 27#include <proto/ethernet.h> 28 29#define ET_ERROR(args) 30#define ET_MSG(args) 31 32/* 33 * Switch can be programmed through SPI interface, which 34 * has a rreg and a wreg functions to read from and write to 35 * registers. 36 */ 37 38/* MII access registers */ 39#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */ 40#define REG_MII_PAGE 0x10 /* MII Page register */ 41#define REG_MII_ADDR 0x11 /* MII Address register */ 42#define REG_MII_DATA0 0x18 /* MII Data register 0 */ 43#define REG_MII_DATA1 0x19 /* MII Data register 1 */ 44#define REG_MII_DATA2 0x1a /* MII Data register 2 */ 45#define REG_MII_DATA3 0x1b /* MII Data register 3 */ 46 47/* Page numbers */ 48#define PAGE_CTRL 0x00 /* Control page */ 49#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */ 50#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */ 51#define PAGE_VLAN 0x34 /* VLAN page */ 52 53/* Control page registers */ 54#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */ 55#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */ 56#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */ 57#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */ 58#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */ 59#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */ 60#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */ 61#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */ 62#define REG_CTRL_MODE 0x0B /* Switch Mode register */ 63#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */ 64#define REG_CTRL_SRST 0x79 /* Software reset control register */ 65 66#define REG_DEVICE_ID 0x30 /* 539x Device id: */ 67#define DEVID5325 0x25 /* 5325 (Not really be we fake it) */ 68#define DEVID5395 0x95 /* 5395 */ 69#define DEVID5397 0x97 /* 5397 */ 70#define DEVID5398 0x98 /* 5398 */ 71 72/* VLAN page registers */ 73#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */ 74#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */ 75#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */ 76#define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */ 77#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */ 78#define REG_VLAN_WRITE 0x08 /* VLAN Write register */ 79#define REG_VLAN_READ 0x0C /* VLAN Read register */ 80#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */ 81#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */ 82#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */ 83#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */ 84#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */ 85#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */ 86#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */ 87#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */ 88#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */ 89#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */ 90 91#define VLAN_NUMVLANS 16 /* # of VLANs */ 92 93 94/* ARL/VLAN Table Access page registers */ 95#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */ 96#define REG_VTBL_MINDX 0x02 /* MAC Address Index */ 97#define REG_VTBL_VINDX 0x08 /* VID Table Index */ 98#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */ 99#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */ 100#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */ 101#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */ 102#define REG_VTBL_SADDR 0x22 /* ARL Search Address */ 103#define REG_VTBL_SRES 0x24 /* ARL Search Result */ 104#define REG_VTBL_SREXT 0x2c /* ARL Search Result */ 105#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */ 106#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */ 107#define REG_VTBL_PREG 0xFF /* Page Register */ 108#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */ 109#define REG_VTBL_INDX 0x61 /* VLAN table address index register */ 110#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */ 111#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */ 112#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */ 113#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */ 114 115/* SPI registers */ 116#define REG_SPI_PAGE 0xff /* SPI Page register */ 117 118/* Access switch registers through GPIO/SPI */ 119 120/* Minimum timing constants */ 121#define SCK_EDGE_TIME 2 /* clock edge duration - 2us */ 122#define MOSI_SETUP_TIME 1 /* input setup duration - 1us */ 123#define SS_SETUP_TIME 1 /* select setup duration - 1us */ 124 125/* misc. constants */ 126#define SPI_MAX_RETRY 100 127 128/* Enable GPIO access to the chip */ 129static void 130gpio_enable(robo_info_t *robo) 131{ 132 /* Enable GPIO outputs with SCK and MOSI low, SS high */ 133 sb_gpioout(robo->sbh, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY); 134 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 135 robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY); 136} 137 138/* Disable GPIO access to the chip */ 139static void 140gpio_disable(robo_info_t *robo) 141{ 142 /* Disable GPIO outputs with all their current values */ 143 sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY); 144} 145 146/* Write a byte stream to the chip thru SPI */ 147static int 148spi_write(robo_info_t *robo, uint8 *buf, uint len) 149{ 150 uint i; 151 uint8 mask; 152 153 /* Byte bang from LSB to MSB */ 154 for (i = 0; i < len; i++) { 155 /* Bit bang from MSB to LSB */ 156 for (mask = 0x80; mask; mask >>= 1) { 157 /* Clock low */ 158 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY); 159 OSL_DELAY(SCK_EDGE_TIME); 160 161 /* Sample on rising edge */ 162 if (mask & buf[i]) 163 sb_gpioout(robo->sbh, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY); 164 else 165 sb_gpioout(robo->sbh, robo->mosi, 0, GPIO_DRV_PRIORITY); 166 OSL_DELAY(MOSI_SETUP_TIME); 167 168 /* Clock high */ 169 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY); 170 OSL_DELAY(SCK_EDGE_TIME); 171 } 172 } 173 174 return 0; 175} 176 177/* Read a byte stream from the chip thru SPI */ 178static int 179spi_read(robo_info_t *robo, uint8 *buf, uint len) 180{ 181 uint i, timeout; 182 uint8 rack, mask, byte; 183 184 /* Timeout after 100 tries without RACK */ 185 for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) { 186 /* Bit bang from MSB to LSB */ 187 for (mask = 0x80, byte = 0; mask; mask >>= 1) { 188 /* Clock low */ 189 sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY); 190 OSL_DELAY(SCK_EDGE_TIME); 191 192 /* Sample on falling edge */ 193 if (sb_gpioin(robo->sbh) & robo->miso) 194 byte |= mask; 195 196 /* Clock high */ 197 sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY); 198 OSL_DELAY(SCK_EDGE_TIME); 199 } 200 /* RACK when bit 0 is high */ 201 if (!rack) { 202 rack = (byte & 1); 203 timeout--; 204 continue; 205 } 206 /* Byte bang from LSB to MSB */ 207 buf[i] = byte; 208 i++; 209 } 210 211 if (timeout == 0) { 212 ET_ERROR(("spi_read: timeout")); 213 return -1; 214 } 215 216 return 0; 217} 218 219/* Enable/disable SPI access */ 220static void 221spi_select(robo_info_t *robo, uint8 spi) 222{ 223 if (spi) { 224 /* Enable SPI access */ 225 sb_gpioout(robo->sbh, robo->ss, 0, GPIO_DRV_PRIORITY); 226 } else { 227 /* Disable SPI access */ 228 sb_gpioout(robo->sbh, robo->ss, robo->ss, GPIO_DRV_PRIORITY); 229 } 230 OSL_DELAY(SS_SETUP_TIME); 231} 232 233 234/* Select chip and page */ 235static void 236spi_goto(robo_info_t *robo, uint8 page) 237{ 238 uint8 reg8 = REG_SPI_PAGE; /* page select register */ 239 uint8 cmd8; 240 241 /* Issue the command only when we are on a different page */ 242 if (robo->page == page) 243 return; 244 245 robo->page = page; 246 247 /* Enable SPI access */ 248 spi_select(robo, 1); 249 250 /* Select new page with CID 0 */ 251 cmd8 = ((6 << 4) | /* normal SPI */ 252 1); /* write */ 253 spi_write(robo, &cmd8, 1); 254 spi_write(robo, ®8, 1); 255 spi_write(robo, &page, 1); 256 257 /* Disable SPI access */ 258 spi_select(robo, 0); 259} 260 261/* Write register thru SPI */ 262static int 263spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len) 264{ 265 int status = 0; 266 uint8 cmd8; 267 union { 268 uint8 val8; 269 uint16 val16; 270 uint32 val32; 271 } bytes; 272 273 /* validate value length and buffer address */ 274 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) || 275 (len == 4 && !((int)val & 3))); 276 277 /* Select chip and page */ 278 spi_goto(robo, page); 279 280 /* Enable SPI access */ 281 spi_select(robo, 1); 282 283 /* Write with CID 0 */ 284 cmd8 = ((6 << 4) | /* normal SPI */ 285 1); /* write */ 286 spi_write(robo, &cmd8, 1); 287 spi_write(robo, &addr, 1); 288 switch (len) { 289 case 1: 290 bytes.val8 = *(uint8 *)val; 291 break; 292 case 2: 293 bytes.val16 = htol16(*(uint16 *)val); 294 break; 295 case 4: 296 bytes.val32 = htol32(*(uint32 *)val); 297 break; 298 } 299 spi_write(robo, (uint8 *)val, len); 300 301 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr, 302 *(uint16 *)val, len)); 303 /* Disable SPI access */ 304 spi_select(robo, 0); 305 return status; 306} 307 308/* Read register thru SPI in fast SPI mode */ 309static int 310spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len) 311{ 312 int status = 0; 313 uint8 cmd8; 314 union { 315 uint8 val8; 316 uint16 val16; 317 uint32 val32; 318 } bytes; 319 320 /* validate value length and buffer address */ 321 ASSERT(len == 1 || (len == 2 && !((int)val & 1)) || 322 (len == 4 && !((int)val & 3))); 323 324 /* Select chip and page */ 325 spi_goto(robo, page); 326 327 /* Enable SPI access */ 328 spi_select(robo, 1); 329 330 /* Fast SPI read with CID 0 and byte offset 0 */ 331 cmd8 = (1 << 4); /* fast SPI */ 332 spi_write(robo, &cmd8, 1); 333 spi_write(robo, &addr, 1); 334 status = spi_read(robo, (uint8 *)&bytes, len); 335 switch (len) { 336 case 1: 337 *(uint8 *)val = bytes.val8; 338 break; 339 case 2: 340 *(uint16 *)val = ltoh16(bytes.val16); 341 break; 342 case 4: 343 *(uint32 *)val = ltoh32(bytes.val32); 344 break; 345 } 346 347 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr, 348 *(uint16 *)val, len)); 349 350 /* Disable SPI access */ 351 spi_select(robo, 0); 352 return status; 353} 354 355/* SPI/gpio interface functions */ 356static dev_ops_t spigpio = { 357 gpio_enable, 358 gpio_disable, 359 spi_wreg, 360 spi_rreg, 361 "SPI (GPIO)" 362}; 363 364 365/* Access switch registers through MII (MDC/MDIO) */ 366 367#define MII_MAX_RETRY 100 368 369/* Write register thru MDC/MDIO */ 370static int 371mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) 372{ 373 uint16 cmd16, val16; 374 void *h = robo->h; 375 int i; 376 uint8 *ptr = (uint8 *)val; 377 378 /* validate value length and buffer address */ 379 ASSERT(len == 1 || len == 6 || len == 8 || 380 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); 381 382 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, 383 *(uint16 *)val, len)); 384 385 /* set page number - MII register 0x10 */ 386 if (robo->page != page) { 387 cmd16 = ((page << 8) | /* page number */ 388 1); /* mdc/mdio access enable */ 389 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); 390 robo->page = page; 391 } 392 393 switch (len) { 394 case 8: 395 val16 = ptr[7]; 396 val16 = ((val16 << 8) | ptr[6]); 397 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16); 398 /* FALLTHRU */ 399 400 case 6: 401 val16 = ptr[5]; 402 val16 = ((val16 << 8) | ptr[4]); 403 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16); 404 val16 = ptr[3]; 405 val16 = ((val16 << 8) | ptr[2]); 406 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16); 407 val16 = ptr[1]; 408 val16 = ((val16 << 8) | ptr[0]); 409 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); 410 break; 411 412 case 4: 413 val16 = (uint16)((*(uint32 *)val) >> 16); 414 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16); 415 val16 = (uint16)(*(uint32 *)val); 416 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); 417 break; 418 419 case 2: 420 val16 = *(uint16 *)val; 421 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); 422 break; 423 424 case 1: 425 val16 = *(uint8 *)val; 426 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); 427 break; 428 } 429 430 /* set register address - MII register 0x11 */ 431 cmd16 = ((reg << 8) | /* register address */ 432 1); /* opcode write */ 433 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); 434 435 /* is operation finished? */ 436 for (i = MII_MAX_RETRY; i > 0; i --) { 437 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR); 438 if ((val16 & 3) == 0) 439 break; 440 } 441 442 /* timed out */ 443 if (!i) { 444 ET_ERROR(("mii_wreg: timeout")); 445 return -1; 446 } 447 return 0; 448} 449 450/* Read register thru MDC/MDIO */ 451static int 452mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) 453{ 454 uint16 cmd16, val16; 455 void *h = robo->h; 456 int i; 457 uint8 *ptr = (uint8 *)val; 458 459 /* validate value length and buffer address */ 460 ASSERT(len == 1 || len == 6 || len == 8 || 461 ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); 462 463 /* set page number - MII register 0x10 */ 464 if (robo->page != page) { 465 cmd16 = ((page << 8) | /* page number */ 466 1); /* mdc/mdio access enable */ 467 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); 468 robo->page = page; 469 } 470 471 /* set register address - MII register 0x11 */ 472 cmd16 = ((reg << 8) | /* register address */ 473 2); /* opcode read */ 474 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); 475 476 /* is operation finished? */ 477 for (i = MII_MAX_RETRY; i > 0; i --) { 478 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR); 479 if ((val16 & 3) == 0) 480 break; 481 } 482 /* timed out */ 483 if (!i) { 484 ET_ERROR(("mii_rreg: timeout")); 485 return -1; 486 } 487 488 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, val16, len)); 489 490 switch (len) { 491 case 8: 492 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3); 493 ptr[7] = (val16 >> 8); 494 ptr[6] = (val16 & 0xff); 495 /* FALLTHRU */ 496 497 case 6: 498 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2); 499 ptr[5] = (val16 >> 8); 500 ptr[4] = (val16 & 0xff); 501 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1); 502 ptr[3] = (val16 >> 8); 503 ptr[2] = (val16 & 0xff); 504 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); 505 ptr[1] = (val16 >> 8); 506 ptr[0] = (val16 & 0xff); 507 break; 508 509 case 4: 510 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1); 511 *(uint32 *)val = (((uint32)val16) << 16); 512 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); 513 *(uint32 *)val |= val16; 514 break; 515 516 case 2: 517 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); 518 *(uint16 *)val = val16; 519 break; 520 521 case 1: 522 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); 523 *(uint8 *)val = (uint8)(val16 & 0xff); 524 break; 525 } 526 527 return 0; 528} 529 530/* MII interface functions */ 531static dev_ops_t mdcmdio = { 532 NULL, 533 NULL, 534 mii_wreg, 535 mii_rreg, 536 "MII (MDC/MDIO)" 537}; 538 539/* High level switch configuration functions. */ 540 541/* Get access to the RoboSwitch */ 542robo_info_t * 543bcm_robo_attach(sb_t *sbh, void *h, char *vars, miird_f miird, miiwr_f miiwr) 544{ 545 robo_info_t *robo; 546 uint32 reset, idx; 547 548 /* Allocate and init private state */ 549 if (!(robo = MALLOC(sb_osh(sbh), sizeof(robo_info_t)))) { 550 ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(sb_osh(sbh)))); 551 return NULL; 552 } 553 bzero(robo, sizeof(robo_info_t)); 554 555 robo->h = h; 556 robo->sbh = sbh; 557 robo->vars = vars; 558 robo->miird = miird; 559 robo->miiwr = miiwr; 560 robo->page = -1; 561 562 /* Trigger external reset by nvram variable existance */ 563 if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) != 564 GPIO_PIN_NOTDEFINED) { 565 /* 566 * Reset sequence: RESET low(50ms)->high(20ms) 567 * 568 * We have to perform a full sequence for we don't know how long 569 * it has been from power on till now. 570 */ 571 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset)); 572 reset = 1 << reset; 573 574 /* Keep RESET low for 50 ms */ 575 sb_gpioout(robo->sbh, reset, 0, GPIO_DRV_PRIORITY); 576 sb_gpioouten(robo->sbh, reset, reset, GPIO_DRV_PRIORITY); 577 bcm_mdelay(50); 578 579 /* Keep RESET high for at least 20 ms */ 580 sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY); 581 bcm_mdelay(20); 582 } else { 583 /* In case we need it */ 584 idx = sb_coreidx(robo->sbh); 585 586 if (sb_setcore(robo->sbh, SB_ROBO, 0)) { 587 /* If we have an internal robo core, reset it using sb_core_reset */ 588 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__)); 589 sb_core_reset(robo->sbh, 0, 0); 590 } 591 592 sb_setcoreidx(robo->sbh, idx); 593 } 594 595 if (miird && miiwr) { 596 uint16 tmp; 597 int rc, retry_count = 0; 598 599 /* Read the PHY ID */ 600 tmp = miird(h, PSEUDO_PHYAD, 2); 601 if (tmp != 0xffff) { 602 do { 603 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \ 604 &robo->devid, sizeof(uint16)); 605 if (rc != 0) 606 break; 607 retry_count++; 608 } while ((robo->devid == 0) && (retry_count < 10)); 609 610 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \ 611 rc ? "un" : "", robo->devid)); 612 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__)); 613 robo->ops = &mdcmdio; 614 if ((rc != 0) || (robo->devid == 0)) { 615 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__)); 616 robo->devid = DEVID5325; 617 } 618 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid)); 619 } 620 } 621 622 if ((robo->devid == DEVID5395) || 623 (robo->devid == DEVID5397) || 624 (robo->devid == DEVID5398)) { 625 uint8 srst_ctrl; 626 627 /* If it is a 539x switch, use the soft reset register */ 628 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__)); 629 630 /* Reset the 539x switch core and register file */ 631 srst_ctrl = 0x83; 632 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8)); 633 srst_ctrl = 0x00; 634 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8)); 635 } 636 637 if (!robo->ops) { 638 int mosi, miso, ss, sck; 639 640 robo->ops = &spigpio; 641 robo->devid = DEVID5325; 642 643 /* Init GPIO mapping. Default 2, 3, 4, 5 */ 644 ss = getgpiopin(vars, "robo_ss", 2); 645 if (ss == GPIO_PIN_NOTDEFINED) { 646 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use")); 647 goto error; 648 } 649 robo->ss = 1 << ss; 650 sck = getgpiopin(vars, "robo_sck", 3); 651 if (sck == GPIO_PIN_NOTDEFINED) { 652 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use")); 653 goto error; 654 } 655 robo->sck = 1 << sck; 656 mosi = getgpiopin(vars, "robo_mosi", 4); 657 if (mosi == GPIO_PIN_NOTDEFINED) { 658 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use")); 659 goto error; 660 } 661 robo->mosi = 1 << mosi; 662 miso = getgpiopin(vars, "robo_miso", 5); 663 if (miso == GPIO_PIN_NOTDEFINED) { 664 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use")); 665 goto error; 666 } 667 robo->miso = 1 << miso; 668 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__, 669 ss, sck, mosi, miso)); 670 } 671 672 /* sanity check */ 673 ASSERT(robo->ops); 674 ASSERT(robo->ops->write_reg); 675 ASSERT(robo->ops->read_reg); 676 ASSERT((robo->devid == DEVID5325) || 677 (robo->devid == DEVID5395) || 678 (robo->devid == DEVID5397) || 679 (robo->devid == DEVID5398)); 680 681 return robo; 682 683error: 684 bcm_robo_detach(robo); 685 return NULL; 686} 687 688/* Release access to the RoboSwitch */ 689void 690bcm_robo_detach(robo_info_t *robo) 691{ 692 MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t)); 693} 694 695/* Enable the device and set it to a known good state */ 696int 697bcm_robo_enable_device(robo_info_t *robo) 698{ 699 uint8 reg_offset, reg_val; 700 int ret = 0; 701 702 /* Enable management interface access */ 703 if (robo->ops->enable_mgmtif) 704 robo->ops->enable_mgmtif(robo); 705 706 if (robo->devid == DEVID5398) { 707 /* Disable unused ports: port 6 and 7 */ 708 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) { 709 /* Set bits [1:0] to disable RX and TX */ 710 reg_val = 0x03; 711 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, ®_val, 712 sizeof(reg_val)); 713 } 714 } 715 716 if (robo->devid == DEVID5325) { 717 /* Must put the switch into Reverse MII mode! */ 718 719 /* MII port state override (page 0 register 14) */ 720 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, sizeof(reg_val)); 721 722 /* Bit 4 enables reverse MII mode */ 723 if (!(reg_val & (1 << 4))) { 724 /* Enable RvMII */ 725 reg_val |= (1 << 4); 726 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, 727 sizeof(reg_val)); 728 729 /* Read back */ 730 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, 731 sizeof(reg_val)); 732 if (!(reg_val & (1 << 4))) { 733 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n")); 734 ret = -1; 735 } 736 } 737 } 738 739 /* Disable management interface access */ 740 if (robo->ops->disable_mgmtif) 741 robo->ops->disable_mgmtif(robo); 742 743 return ret; 744} 745 746/* Port flags */ 747#define FLAG_TAGGED 't' /* output tagged (external ports only) */ 748#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */ 749#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */ 750 751/* port descriptor */ 752typedef struct { 753 uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */ 754 uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */ 755 uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */ 756 uint8 cpu; /* is this cpu port? */ 757} pdesc_t; 758 759pdesc_t pdesc97[] = { 760 /* 5395/5397/5398 is 0 ~ 7. port 8 is IMP port. */ 761 /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0}, 762 /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0}, 763 /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0}, 764 /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0}, 765 /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0}, 766 /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0}, 767 /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0}, 768 /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0}, 769 /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1}, 770}; 771 772pdesc_t pdesc25[] = { 773 /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0}, 774 /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0}, 775 /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0}, 776 /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0}, 777 /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0}, 778 /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1}, 779}; 780 781/* Configure the VLANs */ 782int 783bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr) 784{ 785 uint8 val8; 786 uint16 val16; 787 uint32 val32; 788 pdesc_t *pdesc; 789 int pdescsz; 790 uint16 vid; 791 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 }; 792 793 /* Enable management interface access */ 794 if (robo->ops->enable_mgmtif) 795 robo->ops->enable_mgmtif(robo); 796 797 /* setup global vlan configuration */ 798 /* VLAN Control 0 Register (Page 0x34, Address 0) */ 799 val8 = ((1 << 7) | /* enable 802.1Q VLAN */ 800 (3 << 5)); /* individual VLAN learning mode */ 801 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); 802 803 /* VLAN Control 1 Register (Page 0x34, Address 1) */ 804 val8 = ((1 << 2) | /* enable RSV multicast V Fwdmap */ 805 (1 << 3)); /* enable RSV multicast V Untagmap */ 806 if (robo->devid == DEVID5325) 807 val8 |= (1 << 1); /* enable RSV multicast V Tagging */ 808 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); 809 810 arl_entry[0] = mac_addr[5]; 811 arl_entry[1] = mac_addr[4]; 812 arl_entry[2] = mac_addr[3]; 813 arl_entry[3] = mac_addr[2]; 814 arl_entry[4] = mac_addr[1]; 815 arl_entry[5] = mac_addr[0]; 816 817 if (robo->devid == DEVID5325) { 818 /* Init the entry 1 of the bin */ 819 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \ 820 arl_entry1, sizeof(arl_entry1)); 821 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \ 822 arl_entry1, 1); 823 824 /* Init the entry 0 of the bin */ 825 arl_entry[6] = 0x8; /* Port Id: MII */ 826 arl_entry[7] = 0xc0; /* Static Entry, Valid */ 827 828 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \ 829 arl_entry, sizeof(arl_entry)); 830 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \ 831 arl_entry, ETHER_ADDR_LEN); 832 833 /* VLAN Control 4 Register (Page 0x34, Address 4) */ 834 val8 = (1 << 6); /* drop frame with VID violation */ 835 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); 836 837 /* VLAN Control 5 Register (Page 0x34, Address 5) */ 838 val8 = (1 << 3); /* drop frame when miss V table */ 839 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); 840 841 pdesc = pdesc25; 842 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t); 843 } else { 844 /* Initialize the MAC Addr Index Register */ 845 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \ 846 arl_entry, ETHER_ADDR_LEN); 847 848 pdesc = pdesc97; 849 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); 850 } 851 852 /* setup each vlan. max. 16 vlans. */ 853 /* force vlan id to be equal to vlan number */ 854 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { 855 char vlanports[] = "vlanXXXXports"; 856 char port[] = "XXXX", *ports, *next, *cur; 857 uint32 untag = 0; 858 uint32 member = 0; 859 int pid, len; 860 861 /* no members if VLAN id is out of limitation */ 862 if (vid > VLAN_MAXVID) 863 goto vlan_setup; 864 865 /* get vlan member ports from nvram */ 866 sprintf(vlanports, "vlan%dports", vid); 867 ports = getvar(robo->vars, vlanports); 868 869 /* In 539x vid == 0 us invalid?? */ 870 if ((robo->devid != DEVID5325) && (vid == 0)) { 871 if (ports) 872 ET_ERROR(("VID 0 is set in nvram, Ignoring\n")); 873 continue; 874 } 875 876 /* disable this vlan if not defined */ 877 if (!ports) 878 goto vlan_setup; 879 880 /* 881 * setup each port in the vlan. cpu port needs special handing 882 * (with or without output tagging) to support linux/pmon/cfe. 883 */ 884 for (cur = ports; cur; cur = next) { 885 /* tokenize the port list */ 886 while (*cur == ' ') 887 cur ++; 888 next = bcmstrstr(cur, " "); 889 len = next ? next - cur : strlen(cur); 890 if (!len) 891 break; 892 if (len > sizeof(port) - 1) 893 len = sizeof(port) - 1; 894 strncpy(port, cur, len); 895 port[len] = 0; 896 897 /* make sure port # is within the range */ 898 pid = bcm_atoi(port); 899 if (pid >= pdescsz) { 900 ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out " 901 "of range[0-%d]\n", pid, vid, pdescsz)); 902 continue; 903 } 904 905 /* build VLAN registers values */ 906#ifndef _CFE_ 907 if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) || 908 (pdesc[pid].cpu && strchr(port, FLAG_UNTAG))) 909#endif 910 untag |= pdesc[pid].untag; 911 912 member |= pdesc[pid].member; 913 914 /* set port tag - applies to untagged ingress frames */ 915 /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */ 916#ifdef _CFE_ 917#define FL FLAG_LAN 918#else 919#define FL FLAG_UNTAG 920#endif /* _CFE_ */ 921 if (!pdesc[pid].cpu || strchr(port, FL)) { 922 val16 = ((0 << 13) | /* priority - always 0 */ 923 vid); /* vlan id */ 924 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr, 925 &val16, sizeof(val16)); 926 } 927 } 928 929 /* Add static ARL entries */ 930 if (robo->devid == DEVID5325) { 931 val8 = vid; 932 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \ 933 &val8, sizeof(val8)); 934 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \ 935 &val8, sizeof(val8)); 936 937 /* Write the entry */ 938 val8 = 0x80; 939 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \ 940 &val8, sizeof(val8)); 941 /* Wait for write to complete */ 942 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \ 943 &val8, sizeof(val8)), ((val8 & 0x80) != 0)), 944 100 /* usec */); 945 } else { 946 /* Set the VLAN Id in VLAN ID Index Register */ 947 val8 = vid; 948 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \ 949 &val8, sizeof(val8)); 950 951 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0 952 * Register. 953 */ 954 arl_entry[6] = vid; 955 arl_entry[7] = 0x0; 956 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \ 957 arl_entry, sizeof(arl_entry)); 958 959 /* Set the Static bit , Valid bit and Port ID fields in 960 * ARL Table Data Entry 0 Register 961 */ 962 val16 = 0xc008; 963 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \ 964 &val16, sizeof(val16)); 965 966 /* Clear the ARL_R/W bit and set the START/DONE bit in 967 * the ARL Read/Write Control Register. 968 */ 969 val8 = 0x80; 970 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \ 971 &val8, sizeof(val8)); 972 /* Wait for write to complete */ 973 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \ 974 &val8, sizeof(val8)), ((val8 & 0x80) != 0)), 975 100 /* usec */); 976 } 977 978vlan_setup: 979 /* setup VLAN ID and VLAN memberships */ 980 981 val32 = (untag | /* untag enable */ 982 member); /* vlan members */ 983 if (robo->devid == DEVID5325) { 984 val32 |= ((1 << 20) | /* valid write */ 985 ((vid >> 4) << 12)); /* vlan id bit[11:4] */ 986 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */ 987 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32, 988 sizeof(val32)); 989 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */ 990 val16 = ((1 << 13) | /* start command */ 991 (1 << 12) | /* write state */ 992 vid); /* vlan id */ 993 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16, 994 sizeof(val16)); 995 } else { 996 uint8 vtble, vtbli, vtbla; 997 998 if (robo->devid == DEVID5395) { 999 vtble = REG_VTBL_ENTRY_5395; 1000 vtbli = REG_VTBL_INDX_5395; 1001 vtbla = REG_VTBL_ACCESS_5395; 1002 } else { 1003 vtble = REG_VTBL_ENTRY; 1004 vtbli = REG_VTBL_INDX; 1005 vtbla = REG_VTBL_ACCESS; 1006 } 1007 1008 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ 1009 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32, 1010 sizeof(val32)); 1011 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */ 1012 val16 = vid; /* vlan id */ 1013 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, 1014 sizeof(val16)); 1015 1016 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ 1017 val8 = ((1 << 7) | /* start command */ 1018 0); /* write */ 1019 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, 1020 sizeof(val8)); 1021 } 1022 } 1023 1024 if (robo->devid == DEVID5325) { 1025 /* setup priority mapping - applies to tagged ingress frames */ 1026 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */ 1027 val32 = ((0 << 0) | /* 0 -> 0 */ 1028 (1 << 3) | /* 1 -> 1 */ 1029 (2 << 6) | /* 2 -> 2 */ 1030 (3 << 9) | /* 3 -> 3 */ 1031 (4 << 12) | /* 4 -> 4 */ 1032 (5 << 15) | /* 5 -> 5 */ 1033 (6 << 18) | /* 6 -> 6 */ 1034 (7 << 21)); /* 7 -> 7 */ 1035 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32)); 1036 } 1037 1038 /* Disable management interface access */ 1039 if (robo->ops->disable_mgmtif) 1040 robo->ops->disable_mgmtif(robo); 1041 1042 return 0; 1043} 1044 1045/* Enable switching/forwarding */ 1046int 1047bcm_robo_enable_switch(robo_info_t *robo) 1048{ 1049 int i, max_port_ind, ret = 0; 1050 uint8 val8; 1051 uint32 aging; 1052 1053 /* Enable management interface access */ 1054 if (robo->ops->enable_mgmtif) 1055 robo->ops->enable_mgmtif(robo); 1056 1057 /* Switch Mode register (Page 0, Address 0x0B) */ 1058 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); 1059 1060 /* Bit 1 enables switching/forwarding */ 1061 if (!(val8 & (1 << 1))) { 1062 /* Set unmanaged mode */ 1063 val8 &= (~(1 << 0)); 1064 1065 /* Enable forwarding */ 1066 val8 |= (1 << 1); 1067 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); 1068 1069 /* Read back */ 1070 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); 1071 if (!(val8 & (1 << 1))) { 1072 ET_ERROR(("robo_enable_switch: enabling forwarding failed\n")); 1073 ret = -1; 1074 } 1075 1076 /* No spanning tree for unmanaged mode */ 1077 val8 = 0; 1078 max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4); 1079 for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) { 1080 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); 1081 } 1082 } 1083 1084 /* Disable management interface access */ 1085 if (robo->ops->disable_mgmtif) 1086 robo->ops->disable_mgmtif(robo); 1087 1088 aging = 0x10; /* set to 16s. default is 768s. */ 1089 robo->ops->write_reg(robo, 0x02, 0x06, &aging, sizeof(aging)); 1090 1091 return ret; 1092} 1093 1094