1/* 2 * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core. 3 * 4 * This file implements the chip-specific routines 5 * for Broadcom HNBU Sonics SiliconBackplane enet cores. 6 * 7 * Copyright 2007, Broadcom Corporation 8 * All Rights Reserved. 9 * 10 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 11 * the contents of this file may not be disclosed to third parties, copied 12 * or duplicated in any form, in whole or in part, without the prior 13 * written permission of Broadcom Corporation. 14 * $Id: etc47xx.c,v 1.1.1.1 2008/10/15 03:25:54 james26_jang Exp $ 15 */ 16 17#include <typedefs.h> 18#include <osl.h> 19#include <bcmdefs.h> 20#include <bcmendian.h> 21#include <bcmutils.h> 22#include <bcmdevs.h> 23#include <proto/ethernet.h> 24#include <sbutils.h> 25#include <sbhnddma.h> 26#include <hnddma.h> 27#include <et_dbg.h> 28#include <sbconfig.h> 29#include <bcmenet47xx.h> 30#include <et_export.h> /* for et_phyxx() routines */ 31 32#ifdef ETROBO 33#include <bcmrobo.h> 34#endif /* ETROBO */ 35#ifdef ETADM 36#include <etc_adm.h> 37#endif /* ETADM */ 38 39struct bcm4xxx; /* forward declaration */ 40#define ch_t struct bcm4xxx 41#include <etc.h> 42 43/* private chip state */ 44struct bcm4xxx { 45 void *et; /* pointer to et private state */ 46 etc_info_t *etc; /* pointer to etc public state */ 47 48 bcmenetregs_t *regs; /* pointer to chip registers */ 49 osl_t *osh; /* os handle */ 50 51 void *etphy; /* pointer to et for shared mdc/mdio contortion */ 52 53 uint32 intstatus; /* saved interrupt condition bits */ 54 uint32 intmask; /* current software interrupt mask */ 55 56 hnddma_t *di; /* dma engine software state */ 57 58 bool mibgood; /* true once mib registers have been cleared */ 59 sb_t *sbh; /* sb utils handle */ 60 61 char *vars; /* sprom name=value */ 62 uint vars_size; 63 64 void *adm; /* optional admtek private data */ 65}; 66 67/* local prototypes */ 68static bool chipid(uint vendor, uint device); 69static void *chipattach(etc_info_t *etc, void *osh, void *regsva); 70static void chipdetach(ch_t *ch); 71static void chipreset(ch_t *ch); 72static void chipinit(ch_t *ch, bool full); 73static bool chiptx(ch_t *ch, void *p); 74static void *chiprx(ch_t *ch); 75static void chiprxfill(ch_t *ch); 76static int chipgetintrevents(ch_t *ch, bool in_isr); 77static bool chiperrors(ch_t *ch); 78static void chipintrson(ch_t *ch); 79static void chipintrsoff(ch_t *ch); 80static void chiptxreclaim(ch_t *ch, bool all); 81static void chiprxreclaim(ch_t *ch); 82static void chipstatsupd(ch_t *ch); 83static void chipenablepme(ch_t *ch); 84static void chipdisablepme(ch_t *ch); 85static void chipphyreset(ch_t *ch, uint phyaddr); 86static void chipphyinit(ch_t *ch, uint phyaddr); 87static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg); 88static void chipdump(ch_t *ch, struct bcmstrbuf *b); 89static void chiplongname(ch_t *ch, char *buf, uint bufsize); 90static void chipduplexupd(ch_t *ch); 91static void chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex); 92static void chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v); 93static void chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v); 94static void chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v); 95static void chipphyforce(struct bcm4xxx *ch, uint phyaddr); 96static void chipphyadvertise(struct bcm4xxx *ch, uint phyaddr); 97 98/* chip interrupt bit error summary */ 99#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) 100#define DEF_INTMASK (I_XI | I_RI | I_ERRORS) 101 102struct chops bcm47xx_et_chops = { 103 chipid, 104 chipattach, 105 chipdetach, 106 chipreset, 107 chipinit, 108 chiptx, 109 chiprx, 110 chiprxfill, 111 chipgetintrevents, 112 chiperrors, 113 chipintrson, 114 chipintrsoff, 115 chiptxreclaim, 116 chiprxreclaim, 117 chipstatsupd, 118 chipenablepme, 119 chipdisablepme, 120 chipphyreset, 121 chipphyrd, 122 chipphywr, 123 chipdump, 124 chiplongname, 125 chipduplexupd 126}; 127 128static uint devices[] = { 129 BCM47XX_ENET_ID, 130 BCM4402_ENET_ID, 131 BCM4401_ENET_ID, 132 0x0000 }; 133 134static bool 135chipid(uint vendor, uint device) 136{ 137 int i; 138 139 if (vendor != VENDOR_BROADCOM) 140 return (FALSE); 141 142 for (i = 0; devices[i]; i++) { 143 if (device == devices[i]) 144 return (TRUE); 145 } 146 return (FALSE); 147} 148 149static void* 150chipattach(etc_info_t *etc, void *osh, void *regsva) 151{ 152 struct bcm4xxx *ch; 153 bcmenetregs_t *regs; 154 uint i; 155 char name[16]; 156 char *var; 157 uint boardflags, boardtype; 158 159 ET_TRACE(("et%d: chipattach: regsva 0x%x\n", etc->unit, (uint)regsva)); 160 161 if ((ch = (struct bcm4xxx*) MALLOC(osh, sizeof(struct bcm4xxx))) == NULL) { 162 ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit, 163 MALLOCED(osh))); 164 return (NULL); 165 } 166 bzero((char*)ch, sizeof(struct bcm4xxx)); 167 168 ch->etc = etc; 169 ch->et = etc->et; 170 ch->osh = osh; 171 172 /* get sb handle */ 173 if ((ch->sbh = sb_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars, 174 &ch->vars_size)) == NULL) { 175 ET_ERROR(("et%d: chipattach: sb_attach error\n", etc->unit)); 176 goto fail; 177 } 178 179 /* We used to have an assert here like: 180 * sb_coreid(ch->sbh) == SB_ENET 181 * but srom-less systems and simulators don't have a way to 182 * provide a default bar0window so we were relying on nvram 183 * variables. At some point we decided that we could do away 184 * with that since the wireless driver was simply doing a 185 * setcore in attach. So we need to do the same here for 186 * the ethernet. 187 */ 188 if ((regs = (bcmenetregs_t*)sb_setcore(ch->sbh, SB_ENET, etc->unit)) == NULL) { 189 ET_ERROR(("et%d: chipattach: Could not setcore to the ENET core\n", etc->unit)); 190 goto fail; 191 } 192 193 ch->regs = regs; 194 etc->chip = sb_chip(ch->sbh); 195 etc->chiprev = sb_chiprev(ch->sbh); 196 etc->nicmode = !(sb_bus(ch->sbh) == SB_BUS); 197 etc->coreunit = sb_coreunit(ch->sbh); 198 etc->boardflags = getintvar(ch->vars, "boardflags"); 199 200 boardflags = etc->boardflags; 201 boardtype = sb_boardtype(ch->sbh); 202 203 /* configure pci core */ 204 sb_pci_setup(ch->sbh, (1 << sb_coreidx(ch->sbh))); 205 206 /* reset the enet core */ 207 chipreset(ch); 208 209 /* dma attach */ 210 sprintf(name, "et%d", etc->coreunit); 211 if ((ch->di = dma_attach(osh, name, ch->sbh, 212 (void *)®s->dmaregs.xmt, (void *)®s->dmaregs.rcv, 213 NTXD, NRXD, RXBUFSZ, NRXBUFPOST, HWRXOFF, 214 &et_msg_level)) == NULL) { 215 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit)); 216 goto fail; 217 } 218 etc->txavail = (uint*) dma_getvar(ch->di, "&txavail"); 219 220 /* get our local ether addr */ 221 sprintf(name, "et%dmacaddr", etc->coreunit); 222 var = getvar(ch->vars, name); 223 if (var == NULL) { 224 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name)); 225 goto fail; 226 } 227 bcm_ether_atoe(var, &etc->perm_etheraddr); 228 229 if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { 230 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var)); 231 goto fail; 232 } 233 bcopy((char*)&etc->perm_etheraddr, (char*)&etc->cur_etheraddr, ETHER_ADDR_LEN); 234 235 /* 236 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" . 237 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>". 238 */ 239 240 /* get our phyaddr value */ 241 sprintf(name, "et%dphyaddr", etc->coreunit); 242 var = getvar(ch->vars, name); 243 if (var == NULL) { 244 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name)); 245 goto fail; 246 } 247 etc->phyaddr = bcm_atoi(var) & EPHY_MASK; 248 249 /* nvram says no phy is present */ 250 if (etc->phyaddr == EPHY_NONE) { 251 ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit)); 252 goto fail; 253 } 254 255 /* get our mdc/mdio port number */ 256 sprintf(name, "et%dmdcport", etc->coreunit); 257 var = getvar(ch->vars, name); 258 if (var == NULL) { 259 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name)); 260 goto fail; 261 } 262 etc->mdcport = bcm_atoi(var); 263 264 /* set default sofware intmask */ 265 ch->intmask = DEF_INTMASK; 266 267 /* 268 * GPIO bits 2 and 6 on bcm94710r1 and bcm94710dev reset the 269 * external phys to a known good state. bcm94710r4 uses only 270 * GPIO 6 but GPIO 2 is not connected. Just reset both of them 271 * whenever this function is called. 272 */ 273 if ((boardtype == BCM94710D_BOARD) || 274 (boardtype == BCM94710AP_BOARD) || 275 (boardtype == BCM94710R1_BOARD) || 276 (boardtype == BCM94710R4_BOARD)) { 277 sb_gpioout(ch->sbh, 0x44, 0, GPIO_DRV_PRIORITY); 278 sb_gpioouten(ch->sbh, 0x44, 0x44, GPIO_DRV_PRIORITY); 279 /* Hold phys in reset for a nice long 2 ms */ 280 for (i = 0; i < 2; i++) 281 OSL_DELAY(1000); 282 sb_gpioout(ch->sbh, 0x44, 0x44, GPIO_DRV_PRIORITY); 283 sb_gpioouten(ch->sbh, 0x44, 0, GPIO_DRV_PRIORITY); 284 } 285 286 /* 287 * For the 5222 dual phy shared mdio contortion, our phy is 288 * on someone elses mdio pins. This other enet enet 289 * may not yet be attached so we must defer the et_phyfind(). 290 */ 291 /* if local phy: reset it once now */ 292 if (etc->mdcport == etc->coreunit) 293 chipphyreset(ch, etc->phyaddr); 294 295#ifdef ETROBO 296 /* 297 * Broadcom Robo ethernet switch. 298 */ 299 if (((boardflags & BFL_ENETROBO) || 300 (boardtype == BCM94710AP_BOARD) || 301 (boardtype == BCM94702MN_BOARD)) && 302 (etc->phyaddr == EPHY_NOREG)) { 303 /* Attach to the switch */ 304 if (!(etc->robo = bcm_robo_attach(ch->sbh, ch, ch->vars, 305 (miird_f)bcm47xx_et_chops.phyrd, 306 (miiwr_f)bcm47xx_et_chops.phywr))) { 307 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit)); 308 goto fail; 309 } 310 /* Enable the switch and set it to a known good state */ 311 if (bcm_robo_enable_device(etc->robo)) { 312 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit)); 313 goto fail; 314 } 315 /* Configure the switch to do VLAN */ 316 if ((boardflags & BFL_ENETVLAN) && 317 bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) { 318 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit)); 319 goto fail; 320 } 321 /* Enable switching/forwarding */ 322 if (bcm_robo_enable_switch(etc->robo)) { 323 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit)); 324 goto fail; 325 } 326 } 327#endif /* ETROBO */ 328 329#ifdef ETADM 330 /* 331 * ADMtek ethernet switch. 332 */ 333 if (boardflags & BFL_ENETADM) { 334 /* Attach to the device */ 335 if (!(ch->adm = adm_attach(ch->sbh, ch->vars))) { 336 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc->unit)); 337 goto fail; 338 } 339 /* Enable the external switch and set it to a known good state */ 340 if (adm_enable_device(ch->adm)) { 341 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc->unit)); 342 goto fail; 343 } 344 /* Configure the switch */ 345 if ((boardflags & BFL_ENETVLAN) && adm_config_vlan(ch->adm)) { 346 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc->unit)); 347 goto fail; 348 } 349 } 350#endif /* ETADM */ 351 352 return ((void*) ch); 353 354fail: 355 chipdetach(ch); 356 return (NULL); 357} 358 359static void 360chipdetach(struct bcm4xxx *ch) 361{ 362 ET_TRACE(("et%d: chipdetach\n", ch->etc->unit)); 363 364 if (ch == NULL) 365 return; 366 367#ifdef ETROBO 368 /* free robo state */ 369 if (ch->etc->robo) 370 bcm_robo_detach(ch->etc->robo); 371#endif /* ETROBO */ 372 373#ifdef ETADM 374 /* free ADMtek state */ 375 if (ch->adm) 376 adm_detach(ch->adm); 377#endif /* ETADM */ 378 379 /* free dma state */ 380 dma_detach(ch->di); 381 ch->di = NULL; 382 383 /* put the core back into reset */ 384 if (ch->sbh) 385 sb_core_disable(ch->sbh, 0); 386 387 /* free sb handle */ 388 sb_detach(ch->sbh); 389 ch->sbh = NULL; 390 391 /* free vars */ 392 if (ch->vars) 393 MFREE(ch->osh, ch->vars, ch->vars_size); 394 395 /* free chip private state */ 396 MFREE(ch->osh, ch, sizeof(struct bcm4xxx)); 397} 398 399static void 400chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize) 401{ 402 char *s; 403 404 switch (ch->etc->deviceid) { 405 case BCM4402_ENET_ID: 406 s = "Broadcom BCM4402 10/100 Mbps Ethernet Controller"; 407 break; 408 case BCM47XX_ENET_ID: 409 default: 410 s = "Broadcom BCM47xx 10/100 Mbps Ethernet Controller"; 411 break; 412 } 413 414 strncpy(buf, s, bufsize); 415 buf[bufsize - 1] = '\0'; 416} 417 418static void 419chipdump(struct bcm4xxx *ch, struct bcmstrbuf *b) 420{ 421} 422 423 424#define MDC_RATIO 5000000 425 426static void 427chipreset(struct bcm4xxx *ch) 428{ 429 bcmenetregs_t *regs; 430 uint32 clk, mdc; 431 432 ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); 433 434 regs = ch->regs; 435 436 if (!sb_iscoreup(ch->sbh)) { 437 if (!ch->etc->nicmode) 438 sb_pci_setup(ch->sbh, (1 << sb_coreidx(ch->sbh))); 439 /* power on reset: reset the enet core */ 440 sb_core_reset(ch->sbh, 0, 0); 441 goto chipinreset; 442 } 443 444 /* read counters before resetting the chip */ 445 if (ch->mibgood) 446 chipstatsupd(ch); 447 448 /* reset the tx dma engine */ 449 if (ch->di) 450 dma_txreset(ch->di); 451 452 /* set emac into loopback mode to ensure no rx traffic */ 453 W_REG(ch->osh, ®s->rxconfig, ERC_LE); 454 OSL_DELAY(1); 455 456 /* reset the rx dma engine */ 457 if (ch->di) 458 dma_rxreset(ch->di); 459 460 ASSERT(!((ch->etc->deviceid == BCM4402_ENET_ID) && (ch->etc->chiprev == 0))); 461 462 /* reset core */ 463 sb_core_reset(ch->sbh, 0, 0); 464 465chipinreset: 466 467 /* must clear mib registers by hand */ 468 W_REG(ch->osh, ®s->mibcontrol, EMC_RZ); 469 (void) R_REG(ch->osh, ®s->mib.tx_broadcast_pkts); 470 (void) R_REG(ch->osh, ®s->mib.tx_multicast_pkts); 471 (void) R_REG(ch->osh, ®s->mib.tx_len_64); 472 (void) R_REG(ch->osh, ®s->mib.tx_len_65_to_127); 473 (void) R_REG(ch->osh, ®s->mib.tx_len_128_to_255); 474 (void) R_REG(ch->osh, ®s->mib.tx_len_256_to_511); 475 (void) R_REG(ch->osh, ®s->mib.tx_len_512_to_1023); 476 (void) R_REG(ch->osh, ®s->mib.tx_len_1024_to_max); 477 (void) R_REG(ch->osh, ®s->mib.tx_jabber_pkts); 478 (void) R_REG(ch->osh, ®s->mib.tx_oversize_pkts); 479 (void) R_REG(ch->osh, ®s->mib.tx_fragment_pkts); 480 (void) R_REG(ch->osh, ®s->mib.tx_underruns); 481 (void) R_REG(ch->osh, ®s->mib.tx_total_cols); 482 (void) R_REG(ch->osh, ®s->mib.tx_single_cols); 483 (void) R_REG(ch->osh, ®s->mib.tx_multiple_cols); 484 (void) R_REG(ch->osh, ®s->mib.tx_excessive_cols); 485 (void) R_REG(ch->osh, ®s->mib.tx_late_cols); 486 (void) R_REG(ch->osh, ®s->mib.tx_defered); 487 (void) R_REG(ch->osh, ®s->mib.tx_carrier_lost); 488 (void) R_REG(ch->osh, ®s->mib.tx_pause_pkts); 489 (void) R_REG(ch->osh, ®s->mib.rx_broadcast_pkts); 490 (void) R_REG(ch->osh, ®s->mib.rx_multicast_pkts); 491 (void) R_REG(ch->osh, ®s->mib.rx_len_64); 492 (void) R_REG(ch->osh, ®s->mib.rx_len_65_to_127); 493 (void) R_REG(ch->osh, ®s->mib.rx_len_128_to_255); 494 (void) R_REG(ch->osh, ®s->mib.rx_len_256_to_511); 495 (void) R_REG(ch->osh, ®s->mib.rx_len_512_to_1023); 496 (void) R_REG(ch->osh, ®s->mib.rx_len_1024_to_max); 497 (void) R_REG(ch->osh, ®s->mib.rx_jabber_pkts); 498 (void) R_REG(ch->osh, ®s->mib.rx_oversize_pkts); 499 (void) R_REG(ch->osh, ®s->mib.rx_fragment_pkts); 500 (void) R_REG(ch->osh, ®s->mib.rx_missed_pkts); 501 (void) R_REG(ch->osh, ®s->mib.rx_crc_align_errs); 502 (void) R_REG(ch->osh, ®s->mib.rx_undersize); 503 (void) R_REG(ch->osh, ®s->mib.rx_crc_errs); 504 (void) R_REG(ch->osh, ®s->mib.rx_align_errs); 505 (void) R_REG(ch->osh, ®s->mib.rx_symbol_errs); 506 (void) R_REG(ch->osh, ®s->mib.rx_pause_pkts); 507 (void) R_REG(ch->osh, ®s->mib.rx_nonpause_pkts); 508 ch->mibgood = TRUE; 509 510 /* 511 * We want the phy registers to be accessible even when 512 * the driver is "downed" so initialize MDC preamble, frequency, 513 * and whether internal or external phy here. 514 */ 515 /* default: 100Mhz SB clock and external phy */ 516 W_REG(ch->osh, ®s->mdiocontrol, 0x94); 517 if (ch->etc->deviceid == BCM47XX_ENET_ID) { 518 /* 47xx chips: find out the clock */ 519 if ((clk = sb_clock(ch->sbh)) != 0) { 520 mdc = 0x80 | ((clk + (MDC_RATIO / 2)) / MDC_RATIO); 521 W_REG(ch->osh, ®s->mdiocontrol, mdc); 522 } else { 523 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, " 524 "using 100Mhz\n", 525 ch->etc->unit)); 526 } 527 } else if (ch->etc->deviceid == BCM4402_ENET_ID) { 528 /* 4402 has 62.5Mhz SB clock and internal phy */ 529 W_REG(ch->osh, ®s->mdiocontrol, 0x8d); 530 } 531 532 /* some chips have internal phy, some don't */ 533 if (!(R_REG(ch->osh, ®s->devcontrol) & DC_IP)) { 534 W_REG(ch->osh, ®s->enetcontrol, EC_EP); 535 } else if (R_REG(ch->osh, ®s->devcontrol) & DC_ER) { 536 AND_REG(ch->osh, ®s->devcontrol, ~DC_ER); 537 OSL_DELAY(100); 538 chipphyinit(ch, ch->etc->phyaddr); 539 } 540 541 /* clear persistent sw intstatus */ 542 ch->intstatus = 0; 543} 544 545/* 546 * Initialize all the chip registers. If dma mode, init tx and rx dma engines 547 * but leave the devcontrol tx and rx (fifos) disabled. 548 */ 549static void 550chipinit(struct bcm4xxx *ch, bool full) 551{ 552 etc_info_t *etc; 553 bcmenetregs_t *regs; 554 uint idx; 555 uint i; 556 557 regs = ch->regs; 558 etc = ch->etc; 559 idx = 0; 560 561 ET_TRACE(("et%d: chipinit\n", etc->unit)); 562 563 /* Do timeout fixup */ 564 sb_core_tofixup(ch->sbh); 565 566 /* enable crc32 generation */ 567 OR_REG(ch->osh, ®s->emaccontrol, EMC_CG); 568 569 /* enable one rx interrupt per received frame */ 570 W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); 571 572 /* enable 802.3x tx flow control (honor received PAUSE frames) */ 573 W_REG(ch->osh, ®s->rxconfig, ERC_FE | ERC_UF); 574 575 /* initialize CAM */ 576 if (etc->promisc || (R_REG(ch->osh, ®s->rxconfig) & ERC_CA)) 577 OR_REG(ch->osh, ®s->rxconfig, ERC_PE); 578 else { 579 /* our local address */ 580 chipwrcam(ch, &etc->cur_etheraddr, idx++); 581 582 /* allmulti or a list of discrete multicast addresses */ 583 if (etc->allmulti) 584 OR_REG(ch->osh, ®s->rxconfig, ERC_AM); 585 else if (etc->nmulticast) { 586 for (i = 0; i < etc->nmulticast; i++) 587 chipwrcam(ch, &etc->multicast[i], idx++); 588 } 589 590 /* enable cam */ 591 OR_REG(ch->osh, ®s->camcontrol, CC_CE); 592 } 593 594 /* optionally enable mac-level loopback */ 595 if (etc->loopbk) 596 OR_REG(ch->osh, ®s->rxconfig, ERC_LE); 597 598 /* set max frame lengths - account for possible vlan tag */ 599 W_REG(ch->osh, ®s->rxmaxlength, ETHER_MAX_LEN + 32); 600 W_REG(ch->osh, ®s->txmaxlength, ETHER_MAX_LEN + 32); 601 602 /* set tx watermark */ 603 W_REG(ch->osh, ®s->txwatermark, 56); 604 605 /* 606 * Optionally, disable phy autonegotiation and force our speed/duplex 607 * or constrain our advertised capabilities. 608 */ 609 if (etc->forcespeed != ET_AUTO) 610 chipphyforce(ch, etc->phyaddr); 611 else if (etc->advertise && etc->needautoneg) 612 chipphyadvertise(ch, etc->phyaddr); 613 614 if (full) { 615 /* initialize the tx and rx dma channels */ 616 dma_txinit(ch->di); 617 dma_rxinit(ch->di); 618 619 /* post dma receive buffers */ 620 dma_rxfill(ch->di); 621 622 /* lastly, enable interrupts */ 623 et_intrson(etc->et); 624 } 625 else 626 dma_rxenable(ch->di); 627 628 /* turn on the emac */ 629 OR_REG(ch->osh, ®s->enetcontrol, EC_EE); 630} 631 632/* dma transmit */ 633static bool 634chiptx(struct bcm4xxx *ch, void *p0) 635{ 636 int error; 637 638 ET_TRACE(("et%d: chiptx\n", ch->etc->unit)); 639 ET_LOG("et%d: chiptx", ch->etc->unit, 0); 640 641 error = dma_txfast(ch->di, p0, TRUE); 642 643 if (error) { 644 ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit)); 645 ch->etc->txnobuf++; 646 return FALSE; 647 } 648 return TRUE; 649} 650 651/* reclaim completed transmit descriptors and packets */ 652static void 653chiptxreclaim(struct bcm4xxx *ch, bool forceall) 654{ 655 ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit)); 656 dma_txreclaim(ch->di, forceall); 657 ch->intstatus &= ~I_XI; 658} 659 660/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */ 661static void* 662chiprx(struct bcm4xxx *ch) 663{ 664 void *p; 665 666 ET_TRACE(("et%d: chiprx\n", ch->etc->unit)); 667 ET_LOG("et%d: chiprx", ch->etc->unit, 0); 668 669 if ((p = dma_rx(ch->di)) == NULL) 670 ch->intstatus &= ~I_RI; 671 672 return (p); 673} 674 675/* reclaim completed dma receive descriptors and packets */ 676static void 677chiprxreclaim(struct bcm4xxx *ch) 678{ 679 ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit)); 680 dma_rxreclaim(ch->di); 681 ch->intstatus &= ~I_RI; 682} 683 684/* allocate and post dma receive buffers */ 685static void 686chiprxfill(struct bcm4xxx *ch) 687{ 688 ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit)); 689 ET_LOG("et%d: chiprx", ch->etc->unit, 0); 690 dma_rxfill(ch->di); 691} 692 693/* get current and pending interrupt events */ 694static int 695chipgetintrevents(struct bcm4xxx *ch, bool in_isr) 696{ 697 bcmenetregs_t *regs; 698 uint32 intstatus; 699 int events; 700 701 regs = ch->regs; 702 events = 0; 703 704 /* read the interrupt status register */ 705 intstatus = R_REG(ch->osh, ®s->intstatus); 706 707 /* defer unsolicited interrupts */ 708 intstatus &= (in_isr ? ch->intmask : DEF_INTMASK); 709 710 /* clear non-error interrupt conditions */ 711 if (intstatus != 0) { 712 W_REG(ch->osh, ®s->intstatus, intstatus); 713 events = INTR_NEW; 714 } 715 716 /* or new bits into persistent intstatus */ 717 intstatus = (ch->intstatus |= intstatus); 718 719 /* return if no events */ 720 if (intstatus == 0) 721 return (0); 722 723 /* convert chip-specific intstatus bits into generic intr event bits */ 724 if (intstatus & I_RI) 725 events |= INTR_RX; 726 if (intstatus & I_XI) 727 events |= INTR_TX; 728 if (intstatus & I_ERRORS) 729 events |= INTR_ERROR; 730 if (intstatus & I_TO) 731 events |= INTR_TO; 732 733 return (events); 734} 735 736/* enable chip interrupts */ 737static void 738chipintrson(struct bcm4xxx *ch) 739{ 740 ch->intmask = DEF_INTMASK; 741 W_REG(ch->osh, &ch->regs->intmask, ch->intmask); 742} 743 744/* disable chip interrupts */ 745static void 746chipintrsoff(struct bcm4xxx *ch) 747{ 748 W_REG(ch->osh, &ch->regs->intmask, 0); 749 (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */ 750 ch->intmask = 0; 751} 752 753/* return true of caller should re-initialize, otherwise false */ 754static bool 755chiperrors(struct bcm4xxx *ch) 756{ 757 uint32 intstatus; 758 etc_info_t *etc; 759 760 etc = ch->etc; 761 762 intstatus = ch->intstatus; 763 ch->intstatus &= ~(I_ERRORS); 764 765 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus)); 766 767 if (intstatus & I_PC) { 768 ET_ERROR(("et%d: descriptor error\n", etc->unit)); 769 etc->dmade++; 770 } 771 772 if (intstatus & I_PD) { 773 ET_ERROR(("et%d: data error\n", etc->unit)); 774 etc->dmada++; 775 } 776 777 if (intstatus & I_DE) { 778 ET_ERROR(("et%d: descriptor protocol error\n", etc->unit)); 779 etc->dmape++; 780 } 781 /* NOTE : this ie NOT an error. It becomes an error only 782 * when the rx fifo overflows 783 */ 784 if (intstatus & I_RU) { 785 ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit)); 786 etc->rxdmauflo++; 787 } 788 789 if (intstatus & I_RO) { 790 ET_ERROR(("et%d: receive fifo overflow\n", etc->unit)); 791 etc->rxoflo++; 792 } 793 794 if (intstatus & I_XU) { 795 ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit)); 796 etc->txuflo++; 797 } 798 /* if overflows or decriptors underflow, don't report it 799 * as an error and provoque a reset 800 */ 801 if (intstatus & ~(I_RU) & I_ERRORS) 802 return (TRUE); 803 return FALSE; 804} 805 806static void 807chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex) 808{ 809 uint32 w; 810 811 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0); 812 813 w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8) 814 | ea->octet[5]; 815 W_REG(ch->osh, &ch->regs->camdatalo, w); 816 w = CD_V | (ea->octet[0] << 8) | ea->octet[1]; 817 W_REG(ch->osh, &ch->regs->camdatahi, w); 818 W_REG(ch->osh, &ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR)); 819 820 /* spin until done */ 821 SPINWAIT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB), 100); 822 823 /* 824 * This assertion is usually caused by the phy not providing a clock 825 * to the bottom portion of the mac.. 826 */ 827 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB) == 0); 828} 829 830static void 831chipstatsupd(struct bcm4xxx *ch) 832{ 833 etc_info_t *etc; 834 bcmenetregs_t *regs; 835 836 etc = ch->etc; 837 regs = ch->regs; 838 839 /* 840 * mib counters are clear-on-read. 841 * Don't bother using the pkt and octet counters since they are only 842 * 16bits and wrap too quickly to be useful. 843 */ 844 etc->mib.tx_broadcast_pkts += R_REG(ch->osh, ®s->mib.tx_broadcast_pkts); 845 etc->mib.tx_multicast_pkts += R_REG(ch->osh, ®s->mib.tx_multicast_pkts); 846 etc->mib.tx_len_64 += R_REG(ch->osh, ®s->mib.tx_len_64); 847 etc->mib.tx_len_65_to_127 += R_REG(ch->osh, ®s->mib.tx_len_65_to_127); 848 etc->mib.tx_len_128_to_255 += R_REG(ch->osh, ®s->mib.tx_len_128_to_255); 849 etc->mib.tx_len_256_to_511 += R_REG(ch->osh, ®s->mib.tx_len_256_to_511); 850 etc->mib.tx_len_512_to_1023 += R_REG(ch->osh, ®s->mib.tx_len_512_to_1023); 851 etc->mib.tx_len_1024_to_max += R_REG(ch->osh, ®s->mib.tx_len_1024_to_max); 852 etc->mib.tx_jabber_pkts += R_REG(ch->osh, ®s->mib.tx_jabber_pkts); 853 etc->mib.tx_oversize_pkts += R_REG(ch->osh, ®s->mib.tx_oversize_pkts); 854 etc->mib.tx_fragment_pkts += R_REG(ch->osh, ®s->mib.tx_fragment_pkts); 855 etc->mib.tx_underruns += R_REG(ch->osh, ®s->mib.tx_underruns); 856 etc->mib.tx_total_cols += R_REG(ch->osh, ®s->mib.tx_total_cols); 857 etc->mib.tx_single_cols += R_REG(ch->osh, ®s->mib.tx_single_cols); 858 etc->mib.tx_multiple_cols += R_REG(ch->osh, ®s->mib.tx_multiple_cols); 859 etc->mib.tx_excessive_cols += R_REG(ch->osh, ®s->mib.tx_excessive_cols); 860 etc->mib.tx_late_cols += R_REG(ch->osh, ®s->mib.tx_late_cols); 861 etc->mib.tx_defered += R_REG(ch->osh, ®s->mib.tx_defered); 862 etc->mib.tx_carrier_lost += R_REG(ch->osh, ®s->mib.tx_carrier_lost); 863 etc->mib.tx_pause_pkts += R_REG(ch->osh, ®s->mib.tx_pause_pkts); 864 etc->mib.rx_broadcast_pkts += R_REG(ch->osh, ®s->mib.rx_broadcast_pkts); 865 etc->mib.rx_multicast_pkts += R_REG(ch->osh, ®s->mib.rx_multicast_pkts); 866 etc->mib.rx_len_64 += R_REG(ch->osh, ®s->mib.rx_len_64); 867 etc->mib.rx_len_65_to_127 += R_REG(ch->osh, ®s->mib.rx_len_65_to_127); 868 etc->mib.rx_len_128_to_255 += R_REG(ch->osh, ®s->mib.rx_len_128_to_255); 869 etc->mib.rx_len_256_to_511 += R_REG(ch->osh, ®s->mib.rx_len_256_to_511); 870 etc->mib.rx_len_512_to_1023 += R_REG(ch->osh, ®s->mib.rx_len_512_to_1023); 871 etc->mib.rx_len_1024_to_max += R_REG(ch->osh, ®s->mib.rx_len_1024_to_max); 872 etc->mib.rx_jabber_pkts += R_REG(ch->osh, ®s->mib.rx_jabber_pkts); 873 etc->mib.rx_oversize_pkts += R_REG(ch->osh, ®s->mib.rx_oversize_pkts); 874 etc->mib.rx_fragment_pkts += R_REG(ch->osh, ®s->mib.rx_fragment_pkts); 875 etc->mib.rx_missed_pkts += R_REG(ch->osh, ®s->mib.rx_missed_pkts); 876 etc->mib.rx_crc_align_errs += R_REG(ch->osh, ®s->mib.rx_crc_align_errs); 877 etc->mib.rx_undersize += R_REG(ch->osh, ®s->mib.rx_undersize); 878 etc->mib.rx_crc_errs += R_REG(ch->osh, ®s->mib.rx_crc_errs); 879 etc->mib.rx_align_errs += R_REG(ch->osh, ®s->mib.rx_align_errs); 880 etc->mib.rx_symbol_errs += R_REG(ch->osh, ®s->mib.rx_symbol_errs); 881 etc->mib.rx_pause_pkts += R_REG(ch->osh, ®s->mib.rx_pause_pkts); 882 etc->mib.rx_nonpause_pkts += R_REG(ch->osh, ®s->mib.rx_nonpause_pkts); 883 884 /* 885 * Aggregate transmit and receive errors that probably resulted 886 * in the loss of a frame are computed on the fly. 887 * 888 * We seem to get lots of tx_carrier_lost errors when flipping 889 * speed modes so don't count these as tx errors. 890 * 891 * Arbitrarily lump the non-specific dma errors as tx errors. 892 */ 893 etc->txerror = etc->mib.tx_jabber_pkts + etc->mib.tx_oversize_pkts 894 + etc->mib.tx_underruns + etc->mib.tx_excessive_cols 895 + etc->mib.tx_late_cols + etc->txnobuf + etc->dmade 896 + etc->dmada + etc->dmape + etc->txuflo + etc->txnobuf; 897 etc->rxerror = etc->mib.rx_jabber_pkts + etc->mib.rx_oversize_pkts 898 + etc->mib.rx_missed_pkts + etc->mib.rx_crc_align_errs 899 + etc->mib.rx_undersize + etc->mib.rx_crc_errs 900 + etc->mib.rx_align_errs + etc->mib.rx_symbol_errs 901 + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen; 902} 903 904static void 905chipenablepme(struct bcm4xxx *ch) 906{ 907 bcmenetregs_t *regs; 908 909 regs = ch->regs; 910 911 /* enable chip wakeup pattern matching */ 912 OR_REG(ch->osh, ®s->devcontrol, DC_PM); 913 914 /* enable sonics bus PME */ 915 sb_coreflags(ch->sbh, SBTML_PE, SBTML_PE); 916} 917 918static void 919chipdisablepme(struct bcm4xxx *ch) 920{ 921 bcmenetregs_t *regs; 922 923 regs = ch->regs; 924 925 AND_REG(ch->osh, ®s->devcontrol, ~DC_PM); 926 sb_coreflags(ch->sbh, SBTML_PE, 0); 927} 928 929static void 930chipduplexupd(struct bcm4xxx *ch) 931{ 932 uint32 txcontrol; 933 934 txcontrol = R_REG(ch->osh, &ch->regs->txcontrol); 935 if (ch->etc->duplex && !(txcontrol & EXC_FD)) 936 OR_REG(ch->osh, &ch->regs->txcontrol, EXC_FD); 937 else if (!ch->etc->duplex && (txcontrol & EXC_FD)) 938 AND_REG(ch->osh, &ch->regs->txcontrol, ~EXC_FD); 939} 940 941static uint16 942chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg) 943{ 944 bcmenetregs_t *regs; 945 946 ASSERT(phyaddr < MAXEPHY); 947 948 /* 949 * BCM5222 dualphy shared mdio contortion. 950 * remote phy: another emac controls our phy. 951 */ 952 if (ch->etc->mdcport != ch->etc->coreunit) { 953 if (ch->etphy == NULL) { 954 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport); 955 956 /* first time reset */ 957 if (ch->etphy) 958 chipphyreset(ch, ch->etc->phyaddr); 959 } 960 if (ch->etphy) 961 return (et_phyrd(ch->etphy, phyaddr, reg)); 962 else 963 return (0xffff); 964 } 965 966 /* local phy: our emac controls our phy */ 967 968 regs = ch->regs; 969 970 /* clear mii_int */ 971 W_REG(ch->osh, ®s->emacintstatus, EI_MII); 972 973 /* issue the read */ 974 W_REG(ch->osh, ®s->mdiodata, (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT) 975 | (reg << MD_RA_SHIFT) | MD_TA_VALID)); 976 977 /* wait for it to complete */ 978 SPINWAIT(((R_REG(ch->osh, ®s->emacintstatus) & EI_MII) == 0), 100); 979 if ((R_REG(ch->osh, ®s->emacintstatus) & EI_MII) == 0) { 980 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit)); 981 } 982 983 return (R_REG(ch->osh, ®s->mdiodata) & MD_DATA_MASK); 984} 985 986static void 987chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v) 988{ 989 bcmenetregs_t *regs; 990 991 ASSERT(phyaddr < MAXEPHY); 992 993 /* 994 * BCM5222 dualphy shared mdio contortion. 995 * remote phy: another emac controls our phy. 996 */ 997 if (ch->etc->mdcport != ch->etc->coreunit) { 998 if (ch->etphy == NULL) 999 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport); 1000 if (ch->etphy) 1001 et_phywr(ch->etphy, phyaddr, reg, v); 1002 return; 1003 } 1004 1005 /* local phy: our emac controls our phy */ 1006 1007 regs = ch->regs; 1008 1009 /* clear mii_int */ 1010 W_REG(ch->osh, ®s->emacintstatus, EI_MII); 1011 ASSERT((R_REG(ch->osh, ®s->emacintstatus) & EI_MII) == 0); 1012 1013 /* issue the write */ 1014 W_REG(ch->osh, ®s->mdiodata, (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT) 1015 | (reg << MD_RA_SHIFT) | MD_TA_VALID | v)); 1016 1017 /* wait for it to complete */ 1018 SPINWAIT(((R_REG(ch->osh, ®s->emacintstatus) & EI_MII) == 0), 100); 1019 if ((R_REG(ch->osh, ®s->emacintstatus) & EI_MII) == 0) { 1020 ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit)); 1021 } 1022} 1023 1024static void 1025chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v) 1026{ 1027 uint16 tmp; 1028 1029 tmp = chipphyrd(ch, phyaddr, reg); 1030 tmp |= v; 1031 chipphywr(ch, phyaddr, reg, tmp); 1032} 1033 1034static void 1035chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v) 1036{ 1037 uint16 tmp; 1038 1039 tmp = chipphyrd(ch, phyaddr, reg); 1040 tmp &= v; 1041 chipphywr(ch, phyaddr, reg, tmp); 1042} 1043 1044static void 1045chipphyreset(struct bcm4xxx *ch, uint phyaddr) 1046{ 1047 ASSERT(phyaddr < MAXEPHY); 1048 1049 if (phyaddr == EPHY_NOREG) 1050 return; 1051 1052 chipphywr(ch, phyaddr, 0, CTL_RESET); 1053 OSL_DELAY(100); 1054 if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { 1055 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); 1056 } 1057 1058 chipphyinit(ch, phyaddr); 1059} 1060 1061static void 1062chipphyinit(struct bcm4xxx *ch, uint phyaddr) 1063{ 1064 uint phyid = 0; 1065 1066 /* enable activity led */ 1067 chipphyand(ch, phyaddr, 26, 0x7fff); 1068 1069 /* enable traffic meter led mode */ 1070 chipphyor(ch, phyaddr, 27, (1 << 6)); 1071 1072 phyid = chipphyrd(ch, phyaddr, 0x2); 1073 phyid |= chipphyrd(ch, phyaddr, 0x3) << 16; 1074 if (phyid == 0x55210022) { 1075 chipphywr(ch, phyaddr, 30, (uint16) (chipphyrd(ch, phyaddr, 30) | 0x3000)); 1076 chipphywr(ch, phyaddr, 22, (uint16) (chipphyrd(ch, phyaddr, 22) & 0xffdf)); 1077 } 1078} 1079 1080static void 1081chipphyforce(struct bcm4xxx *ch, uint phyaddr) 1082{ 1083 etc_info_t *etc; 1084 uint16 ctl; 1085 1086 ASSERT(phyaddr < MAXEPHY); 1087 1088 if (phyaddr == EPHY_NOREG) 1089 return; 1090 1091 etc = ch->etc; 1092 1093 if (etc->forcespeed == ET_AUTO) 1094 return; 1095 1096 ctl = chipphyrd(ch, phyaddr, 0); 1097 ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX); 1098 1099 switch (etc->forcespeed) { 1100 case ET_10HALF: 1101 break; 1102 1103 case ET_10FULL: 1104 ctl |= CTL_DUPLEX; 1105 break; 1106 1107 case ET_100HALF: 1108 ctl |= CTL_SPEED; 1109 break; 1110 1111 case ET_100FULL: 1112 ctl |= (CTL_SPEED | CTL_DUPLEX); 1113 break; 1114 } 1115 1116 chipphywr(ch, phyaddr, 0, ctl); 1117} 1118 1119/* set selected capability bits in autonegotiation advertisement */ 1120static void 1121chipphyadvertise(struct bcm4xxx *ch, uint phyaddr) 1122{ 1123 etc_info_t *etc; 1124 uint16 adv; 1125 1126 ASSERT(phyaddr < MAXEPHY); 1127 1128 if (phyaddr == EPHY_NOREG) 1129 return; 1130 1131 etc = ch->etc; 1132 1133 if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg) 1134 return; 1135 1136 ASSERT(etc->advertise); 1137 1138 /* reset our advertised capabilitity bits */ 1139 adv = chipphyrd(ch, phyaddr, 4); 1140 adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); 1141 adv |= etc->advertise; 1142 chipphywr(ch, phyaddr, 4, adv); 1143 1144 /* restart autonegotiation */ 1145 chipphyor(ch, phyaddr, 0, CTL_RESTART); 1146 1147 etc->needautoneg = FALSE; 1148} 1149