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