SSID: Respect ASCII character Label.
[tomato.git] / release / src / et / sys / etc47xx.c
blobeb0bf7e5aadd43d41b62204ea83cb9b3888aeed2
1 /*
2 * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core.
4 * This file implements the chip-specific routines
5 * for Broadcom HNBU Sonics SiliconBackplane enet cores.
7 * Copyright 2006, 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 2007/03/20 12:22:00 roly Exp $
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 */
32 #ifdef ETROBO
33 #include <bcmrobo.h>
34 #endif /* ETROBO */
35 #ifdef ETADM
36 #include <etc_adm.h>
37 #endif /* ETADM */
39 struct bcm4xxx; /* forward declaration */
40 #define ch_t struct bcm4xxx
41 #include <etc.h>
43 /* private chip state */
44 struct bcm4xxx {
45 void *et; /* pointer to et private state */
46 etc_info_t *etc; /* pointer to etc public state */
48 bcmenetregs_t *regs; /* pointer to chip registers */
49 osl_t *osh; /* os handle */
51 void *etphy; /* pointer to et for shared mdc/mdio contortion */
53 uint32 intstatus; /* saved interrupt condition bits */
54 uint32 intmask; /* current software interrupt mask */
56 hnddma_t *di; /* dma engine software state */
58 bool mibgood; /* true once mib registers have been cleared */
59 sb_t *sbh; /* sb utils handle */
61 char *vars; /* sprom name=value */
62 uint vars_size;
64 void *adm; /* optional admtek private data */
67 /* local prototypes */
68 static bool chipid(uint vendor, uint device);
69 static void *chipattach(etc_info_t *etc, void *osh, void *regsva);
70 static void chipdetach(ch_t *ch);
71 static void chipreset(ch_t *ch);
72 static void chipinit(ch_t *ch, bool full);
73 static bool chiptx(ch_t *ch, void *p);
74 static void *chiprx(ch_t *ch);
75 static void chiprxfill(ch_t *ch);
76 static int chipgetintrevents(ch_t *ch, bool in_isr);
77 static bool chiperrors(ch_t *ch);
78 static void chipintrson(ch_t *ch);
79 static void chipintrsoff(ch_t *ch);
80 static void chiptxreclaim(ch_t *ch, bool all);
81 static void chiprxreclaim(ch_t *ch);
82 static void chipstatsupd(ch_t *ch);
83 static void chipenablepme(ch_t *ch);
84 static void chipdisablepme(ch_t *ch);
85 static void chipphyreset(ch_t *ch, uint phyaddr);
86 static void chipphyinit(ch_t *ch, uint phyaddr);
87 static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg);
88 static void chipdump(ch_t *ch, struct bcmstrbuf *b);
89 static void chiplongname(ch_t *ch, char *buf, uint bufsize);
90 static void chipduplexupd(ch_t *ch);
91 static void chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex);
92 static void chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
93 static void chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
94 static void chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v);
95 static void chipphyforce(struct bcm4xxx *ch, uint phyaddr);
96 static void chipphyadvertise(struct bcm4xxx *ch, uint phyaddr);
98 /* chip interrupt bit error summary */
99 #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU | I_TO)
100 #define DEF_INTMASK (I_XI | I_RI | I_ERRORS)
102 struct 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
128 static uint devices[] = {
129 BCM47XX_ENET_ID,
130 BCM4402_ENET_ID,
131 BCM4401_ENET_ID,
132 0x0000 };
134 static bool
135 chipid(uint vendor, uint device)
137 int i;
139 if (vendor != VENDOR_BROADCOM)
140 return (FALSE);
142 for (i = 0; devices[i]; i++) {
143 if (device == devices[i])
144 return (TRUE);
146 return (FALSE);
149 static void*
150 chipattach(etc_info_t *etc, void *osh, void *regsva)
152 struct bcm4xxx *ch;
153 bcmenetregs_t *regs;
154 uint i;
155 char name[16];
156 char *var;
157 uint boardflags, boardtype;
159 ET_TRACE(("et%d: chipattach: regsva 0x%x\n", etc->unit, (uint)regsva));
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);
166 bzero((char*)ch, sizeof(struct bcm4xxx));
168 ch->etc = etc;
169 ch->et = etc->et;
170 ch->osh = osh;
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;
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.
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;
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");
200 /* set boardflags for 5365 and 5350 */
201 if (etc->chip == BCM5365_CHIP_ID || etc->chip == BCM5350_CHIP_ID)
202 etc->boardflags |= BFL_ENETROBO | BFL_ENETVLAN;
204 boardflags = etc->boardflags;
205 boardtype = sb_boardtype(ch->sbh);
207 /* configure pci core */
208 sb_pci_setup(ch->sbh, (1 << sb_coreidx(ch->sbh)));
210 /* reset the enet core */
211 chipreset(ch);
213 /* dma attach */
214 sprintf(name, "et%d", etc->coreunit);
215 if ((ch->di = dma_attach(osh, name, ch->sbh,
216 (void *)&regs->dmaregs.xmt, (void *)&regs->dmaregs.rcv,
217 NTXD, NRXD, RXBUFSZ, NRXBUFPOST, HWRXOFF,
218 &et_msg_level)) == NULL) {
219 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit));
220 goto fail;
222 etc->txavail = (uint*) dma_getvar(ch->di, "&txavail");
224 /* get our local ether addr */
225 sprintf(name, "et%dmacaddr", etc->coreunit);
226 var = getvar(ch->vars, name);
227 if (var == NULL) {
228 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
229 goto fail;
231 bcm_ether_atoe(var, &etc->perm_etheraddr);
233 if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) {
234 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var));
235 goto fail;
237 bcopy((char*)&etc->perm_etheraddr, (char*)&etc->cur_etheraddr, ETHER_ADDR_LEN);
240 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
241 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
244 /* get our phyaddr value */
245 sprintf(name, "et%dphyaddr", etc->coreunit);
246 var = getvar(ch->vars, name);
247 if (var == NULL) {
248 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
249 goto fail;
251 etc->phyaddr = bcm_atoi(var) & EPHY_MASK;
253 /* nvram says no phy is present */
254 if (etc->phyaddr == EPHY_NONE) {
255 ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit));
256 goto fail;
259 /* get our mdc/mdio port number */
260 sprintf(name, "et%dmdcport", etc->coreunit);
261 var = getvar(ch->vars, name);
262 if (var == NULL) {
263 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
264 goto fail;
266 etc->mdcport = bcm_atoi(var);
268 /* set default sofware intmask */
269 ch->intmask = DEF_INTMASK;
272 * GPIO bits 2 and 6 on bcm94710r1 and bcm94710dev reset the
273 * external phys to a known good state. bcm94710r4 uses only
274 * GPIO 6 but GPIO 2 is not connected. Just reset both of them
275 * whenever this function is called.
277 if ((boardtype == BCM94710D_BOARD) ||
278 (boardtype == BCM94710AP_BOARD) ||
279 (boardtype == BCM94710R1_BOARD) ||
280 (boardtype == BCM94710R4_BOARD)) {
281 sb_gpioout(ch->sbh, 0x44, 0, GPIO_DRV_PRIORITY);
282 sb_gpioouten(ch->sbh, 0x44, 0x44, GPIO_DRV_PRIORITY);
283 /* Hold phys in reset for a nice long 2 ms */
284 for (i = 0; i < 2; i++)
285 OSL_DELAY(1000);
286 sb_gpioout(ch->sbh, 0x44, 0x44, GPIO_DRV_PRIORITY);
287 sb_gpioouten(ch->sbh, 0x44, 0, GPIO_DRV_PRIORITY);
291 * For the 5222 dual phy shared mdio contortion, our phy is
292 * on someone elses mdio pins. This other enet enet
293 * may not yet be attached so we must defer the et_phyfind().
295 /* if local phy: reset it once now */
296 if (etc->mdcport == etc->coreunit)
297 chipphyreset(ch, etc->phyaddr);
299 #ifdef ETROBO
301 * Broadcom Robo ethernet switch.
303 if (((boardflags & BFL_ENETROBO) ||
304 (boardtype == BCM94710AP_BOARD) ||
305 (boardtype == BCM94702MN_BOARD)) &&
306 (etc->phyaddr == EPHY_NOREG)) {
307 /* Attach to the switch */
308 if (!(etc->robo = bcm_robo_attach(ch->sbh, ch, ch->vars,
309 (miird_f)bcm47xx_et_chops.phyrd,
310 (miiwr_f)bcm47xx_et_chops.phywr))) {
311 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit));
312 goto fail;
314 /* Enable the switch and set it to a known good state */
315 if (bcm_robo_enable_device(etc->robo)) {
316 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit));
317 goto fail;
319 /* Configure the switch to do VLAN */
320 if ((boardflags & BFL_ENETVLAN) &&
321 bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) {
322 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit));
323 goto fail;
325 /* Enable switching/forwarding */
326 if (bcm_robo_enable_switch(etc->robo)) {
327 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit));
328 goto fail;
331 #endif /* ETROBO */
333 #ifdef ETADM
335 * ADMtek ethernet switch.
337 if (boardflags & BFL_ENETADM) {
338 /* Attach to the device */
339 if (!(ch->adm = adm_attach(ch->sbh, ch->vars))) {
340 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc->unit));
341 goto fail;
343 /* Enable the external switch and set it to a known good state */
344 if (adm_enable_device(ch->adm)) {
345 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc->unit));
346 goto fail;
348 /* Configure the switch */
349 if ((boardflags & BFL_ENETVLAN) && adm_config_vlan(ch->adm)) {
350 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc->unit));
351 goto fail;
354 #endif /* ETADM */
356 return ((void*) ch);
358 fail:
359 chipdetach(ch);
360 return (NULL);
363 static void
364 chipdetach(struct bcm4xxx *ch)
366 ET_TRACE(("et%d: chipdetach\n", ch->etc->unit));
368 if (ch == NULL)
369 return;
371 #ifdef ETROBO
372 /* free robo state */
373 if (ch->etc->robo)
374 bcm_robo_detach(ch->etc->robo);
375 #endif /* ETROBO */
377 #ifdef ETADM
378 /* free ADMtek state */
379 if (ch->adm)
380 adm_detach(ch->adm);
381 #endif /* ETADM */
383 /* free dma state */
384 dma_detach(ch->di);
385 ch->di = NULL;
387 /* put the core back into reset */
388 if (ch->sbh)
389 sb_core_disable(ch->sbh, 0);
391 /* free sb handle */
392 sb_detach(ch->sbh);
393 ch->sbh = NULL;
395 /* free vars */
396 if (ch->vars)
397 MFREE(ch->osh, ch->vars, ch->vars_size);
399 /* free chip private state */
400 MFREE(ch->osh, ch, sizeof(struct bcm4xxx));
403 static void
404 chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize)
406 char *s;
408 switch (ch->etc->deviceid) {
409 case BCM4402_ENET_ID:
410 s = "Broadcom BCM4402 10/100 Mbps Ethernet Controller";
411 break;
412 case BCM47XX_ENET_ID:
413 default:
414 s = "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
415 break;
418 strncpy(buf, s, bufsize);
419 buf[bufsize - 1] = '\0';
422 static void
423 chipdump(struct bcm4xxx *ch, struct bcmstrbuf *b)
428 #define MDC_RATIO 5000000
430 static void
431 chipreset(struct bcm4xxx *ch)
433 bcmenetregs_t *regs;
434 uint32 clk, mdc;
436 ET_TRACE(("et%d: chipreset\n", ch->etc->unit));
438 regs = ch->regs;
440 if (!sb_iscoreup(ch->sbh)) {
441 if (!ch->etc->nicmode)
442 sb_pci_setup(ch->sbh, (1 << sb_coreidx(ch->sbh)));
443 /* power on reset: reset the enet core */
444 sb_core_reset(ch->sbh, 0, 0);
445 goto chipinreset;
448 /* read counters before resetting the chip */
449 if (ch->mibgood)
450 chipstatsupd(ch);
452 /* reset the tx dma engine */
453 if (ch->di)
454 dma_txreset(ch->di);
456 /* set emac into loopback mode to ensure no rx traffic */
457 W_REG(ch->osh, &regs->rxconfig, ERC_LE);
458 OSL_DELAY(1);
460 /* reset the rx dma engine */
461 if (ch->di)
462 dma_rxreset(ch->di);
464 ASSERT(!((ch->etc->deviceid == BCM4402_ENET_ID) && (ch->etc->chiprev == 0)));
466 /* reset core */
467 sb_core_reset(ch->sbh, 0, 0);
469 chipinreset:
471 /* must clear mib registers by hand */
472 W_REG(ch->osh, &regs->mibcontrol, EMC_RZ);
473 (void) R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
474 (void) R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
475 (void) R_REG(ch->osh, &regs->mib.tx_len_64);
476 (void) R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
477 (void) R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
478 (void) R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
479 (void) R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
480 (void) R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
481 (void) R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
482 (void) R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
483 (void) R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
484 (void) R_REG(ch->osh, &regs->mib.tx_underruns);
485 (void) R_REG(ch->osh, &regs->mib.tx_total_cols);
486 (void) R_REG(ch->osh, &regs->mib.tx_single_cols);
487 (void) R_REG(ch->osh, &regs->mib.tx_multiple_cols);
488 (void) R_REG(ch->osh, &regs->mib.tx_excessive_cols);
489 (void) R_REG(ch->osh, &regs->mib.tx_late_cols);
490 (void) R_REG(ch->osh, &regs->mib.tx_defered);
491 (void) R_REG(ch->osh, &regs->mib.tx_carrier_lost);
492 (void) R_REG(ch->osh, &regs->mib.tx_pause_pkts);
493 (void) R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
494 (void) R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
495 (void) R_REG(ch->osh, &regs->mib.rx_len_64);
496 (void) R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
497 (void) R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
498 (void) R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
499 (void) R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
500 (void) R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
501 (void) R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
502 (void) R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
503 (void) R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
504 (void) R_REG(ch->osh, &regs->mib.rx_missed_pkts);
505 (void) R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
506 (void) R_REG(ch->osh, &regs->mib.rx_undersize);
507 (void) R_REG(ch->osh, &regs->mib.rx_crc_errs);
508 (void) R_REG(ch->osh, &regs->mib.rx_align_errs);
509 (void) R_REG(ch->osh, &regs->mib.rx_symbol_errs);
510 (void) R_REG(ch->osh, &regs->mib.rx_pause_pkts);
511 (void) R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
512 ch->mibgood = TRUE;
515 * We want the phy registers to be accessible even when
516 * the driver is "downed" so initialize MDC preamble, frequency,
517 * and whether internal or external phy here.
519 /* default: 100Mhz SB clock and external phy */
520 W_REG(ch->osh, &regs->mdiocontrol, 0x94);
521 if (ch->etc->deviceid == BCM47XX_ENET_ID) {
522 /* 47xx chips: find out the clock */
523 if ((clk = sb_clock(ch->sbh)) != 0) {
524 mdc = 0x80 | ((clk + (MDC_RATIO / 2)) / MDC_RATIO);
525 W_REG(ch->osh, &regs->mdiocontrol, mdc);
526 } else {
527 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
528 "using 100Mhz\n",
529 ch->etc->unit));
531 } else if (ch->etc->deviceid == BCM4402_ENET_ID) {
532 /* 4402 has 62.5Mhz SB clock and internal phy */
533 W_REG(ch->osh, &regs->mdiocontrol, 0x8d);
536 /* some chips have internal phy, some don't */
537 if (!(R_REG(ch->osh, &regs->devcontrol) & DC_IP)) {
538 W_REG(ch->osh, &regs->enetcontrol, EC_EP);
539 } else if (R_REG(ch->osh, &regs->devcontrol) & DC_ER) {
540 AND_REG(ch->osh, &regs->devcontrol, ~DC_ER);
541 OSL_DELAY(100);
542 chipphyinit(ch, ch->etc->phyaddr);
545 /* clear persistent sw intstatus */
546 ch->intstatus = 0;
550 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
551 * but leave the devcontrol tx and rx (fifos) disabled.
553 static void
554 chipinit(struct bcm4xxx *ch, bool full)
556 etc_info_t *etc;
557 bcmenetregs_t *regs;
558 uint idx;
559 uint i;
561 regs = ch->regs;
562 etc = ch->etc;
563 idx = 0;
565 ET_TRACE(("et%d: chipinit\n", etc->unit));
567 /* Do timeout fixup */
568 sb_core_tofixup(ch->sbh);
570 /* enable crc32 generation */
571 OR_REG(ch->osh, &regs->emaccontrol, EMC_CG);
573 /* enable one rx interrupt per received frame */
574 W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));
576 /* enable 802.3x tx flow control (honor received PAUSE frames) */
577 W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);
579 /* initialize CAM */
580 if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
581 OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
582 else {
583 /* our local address */
584 chipwrcam(ch, &etc->cur_etheraddr, idx++);
586 /* allmulti or a list of discrete multicast addresses */
587 if (etc->allmulti)
588 OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
589 else if (etc->nmulticast) {
590 for (i = 0; i < etc->nmulticast; i++)
591 chipwrcam(ch, &etc->multicast[i], idx++);
594 /* enable cam */
595 OR_REG(ch->osh, &regs->camcontrol, CC_CE);
598 /* optionally enable mac-level loopback */
599 if (etc->loopbk)
600 OR_REG(ch->osh, &regs->rxconfig, ERC_LE);
602 /* set max frame lengths - account for possible vlan tag */
603 W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
604 W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);
606 /* set tx watermark */
607 W_REG(ch->osh, &regs->txwatermark, 56);
609 /* set tx duplex */
610 W_REG(ch->osh, &regs->txcontrol, etc->duplex ? EXC_FD : 0);
613 * Optionally, disable phy autonegotiation and force our speed/duplex
614 * or constrain our advertised capabilities.
616 if (etc->forcespeed != ET_AUTO)
617 chipphyforce(ch, etc->phyaddr);
618 else if (etc->advertise && etc->needautoneg)
619 chipphyadvertise(ch, etc->phyaddr);
621 if (full) {
622 /* initialize the tx and rx dma channels */
623 dma_txinit(ch->di);
624 dma_rxinit(ch->di);
626 /* post dma receive buffers */
627 dma_rxfill(ch->di);
629 /* setup timer interrupt */
630 W_REG(ch->osh, &regs->gptimer, 0);
632 /* lastly, enable interrupts */
633 et_intrson(etc->et);
635 else
636 dma_rxenable(ch->di);
638 /* turn on the emac */
639 OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
642 /* dma transmit */
643 static bool
644 chiptx(struct bcm4xxx *ch, void *p0)
646 int error;
648 ET_TRACE(("et%d: chiptx\n", ch->etc->unit));
649 ET_LOG("et%d: chiptx", ch->etc->unit, 0);
651 error = dma_txfast(ch->di, p0, TRUE);
653 if (error) {
654 ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit));
655 ch->etc->txnobuf++;
656 return FALSE;
658 return TRUE;
661 /* reclaim completed transmit descriptors and packets */
662 static void
663 chiptxreclaim(struct bcm4xxx *ch, bool forceall)
665 ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit));
666 dma_txreclaim(ch->di, forceall);
667 ch->intstatus &= ~I_XI;
670 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
671 static void*
672 chiprx(struct bcm4xxx *ch)
674 void *p;
676 ET_TRACE(("et%d: chiprx\n", ch->etc->unit));
677 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
679 if ((p = dma_rx(ch->di)) == NULL)
680 ch->intstatus &= ~I_RI;
682 return (p);
685 /* reclaim completed dma receive descriptors and packets */
686 static void
687 chiprxreclaim(struct bcm4xxx *ch)
689 ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit));
690 dma_rxreclaim(ch->di);
691 ch->intstatus &= ~I_RI;
694 /* allocate and post dma receive buffers */
695 static void
696 chiprxfill(struct bcm4xxx *ch)
698 ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit));
699 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
700 dma_rxfill(ch->di);
703 /* get current and pending interrupt events */
704 static int
705 chipgetintrevents(struct bcm4xxx *ch, bool in_isr)
707 bcmenetregs_t *regs;
708 uint32 intstatus;
709 int events;
711 regs = ch->regs;
712 events = 0;
714 /* read the interrupt status register */
715 intstatus = R_REG(ch->osh, &regs->intstatus);
717 /* defer unsolicited interrupts */
718 intstatus &= (in_isr ? ch->intmask : DEF_INTMASK);
720 /* clear non-error interrupt conditions */
721 if (intstatus != 0) {
722 W_REG(ch->osh, &regs->intstatus, intstatus);
723 events = INTR_NEW;
726 /* or new bits into persistent intstatus */
727 intstatus = (ch->intstatus |= intstatus);
729 /* return if no events */
730 if (intstatus == 0)
731 return (0);
733 /* convert chip-specific intstatus bits into generic intr event bits */
734 if (intstatus & I_RI)
735 events |= INTR_RX;
736 if (intstatus & I_XI)
737 events |= INTR_TX;
738 if (intstatus & I_ERRORS)
739 events |= INTR_ERROR;
740 if (intstatus & I_TO)
741 events |= INTR_TO;
743 /* check for rx after tx for 3 seconds on the unit 1, */
744 /* schedule reset if it's missing - possible rx stuck */
745 if (ch->etc->chip == BCM4710_CHIP_ID && ch->etc->unit == 1) {
746 if (intstatus & I_RI)
747 W_REG(ch->osh, &regs->gptimer, 0);
748 else if (!R_REG(ch->osh, &regs->gptimer))
749 W_REG(ch->osh, &regs->gptimer, 3 * 125000000);
752 return (events);
755 /* enable chip interrupts */
756 static void
757 chipintrson(struct bcm4xxx *ch)
759 ch->intmask = DEF_INTMASK;
760 W_REG(ch->osh, &ch->regs->intmask, ch->intmask);
763 /* disable chip interrupts */
764 static void
765 chipintrsoff(struct bcm4xxx *ch)
767 W_REG(ch->osh, &ch->regs->intmask, 0);
768 (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */
769 ch->intmask = 0;
772 /* return true of caller should re-initialize, otherwise false */
773 static bool
774 chiperrors(struct bcm4xxx *ch)
776 uint32 intstatus;
777 etc_info_t *etc;
779 etc = ch->etc;
781 intstatus = ch->intstatus;
782 ch->intstatus &= ~(I_ERRORS);
784 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus));
786 if (intstatus & I_PC) {
787 ET_ERROR(("et%d: descriptor error\n", etc->unit));
788 etc->dmade++;
791 if (intstatus & I_PD) {
792 ET_ERROR(("et%d: data error\n", etc->unit));
793 etc->dmada++;
796 if (intstatus & I_DE) {
797 ET_ERROR(("et%d: descriptor protocol error\n", etc->unit));
798 etc->dmape++;
801 if (intstatus & I_RU) {
802 ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit));
803 etc->rxdmauflo++;
806 if (intstatus & I_RO) {
807 ET_ERROR(("et%d: receive fifo overflow\n", etc->unit));
808 etc->rxoflo++;
811 if (intstatus & I_XU) {
812 ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit));
813 etc->txuflo++;
816 if (intstatus & I_TO) {
817 ET_ERROR(("et%d: rx stuck suspected\n", etc->unit));
820 return (TRUE);
823 static void
824 chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
826 uint32 w;
828 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0);
830 w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8)
831 | ea->octet[5];
832 W_REG(ch->osh, &ch->regs->camdatalo, w);
833 w = CD_V | (ea->octet[0] << 8) | ea->octet[1];
834 W_REG(ch->osh, &ch->regs->camdatahi, w);
835 W_REG(ch->osh, &ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR));
837 /* spin until done */
838 SPINWAIT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB), 100);
841 * This assertion is usually caused by the phy not providing a clock
842 * to the bottom portion of the mac..
844 ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB) == 0);
847 static void
848 chipstatsupd(struct bcm4xxx *ch)
850 etc_info_t *etc;
851 bcmenetregs_t *regs;
853 etc = ch->etc;
854 regs = ch->regs;
857 * mib counters are clear-on-read.
858 * Don't bother using the pkt and octet counters since they are only
859 * 16bits and wrap too quickly to be useful.
861 etc->mib.tx_broadcast_pkts += R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
862 etc->mib.tx_multicast_pkts += R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
863 etc->mib.tx_len_64 += R_REG(ch->osh, &regs->mib.tx_len_64);
864 etc->mib.tx_len_65_to_127 += R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
865 etc->mib.tx_len_128_to_255 += R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
866 etc->mib.tx_len_256_to_511 += R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
867 etc->mib.tx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
868 etc->mib.tx_len_1024_to_max += R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
869 etc->mib.tx_jabber_pkts += R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
870 etc->mib.tx_oversize_pkts += R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
871 etc->mib.tx_fragment_pkts += R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
872 etc->mib.tx_underruns += R_REG(ch->osh, &regs->mib.tx_underruns);
873 etc->mib.tx_total_cols += R_REG(ch->osh, &regs->mib.tx_total_cols);
874 etc->mib.tx_single_cols += R_REG(ch->osh, &regs->mib.tx_single_cols);
875 etc->mib.tx_multiple_cols += R_REG(ch->osh, &regs->mib.tx_multiple_cols);
876 etc->mib.tx_excessive_cols += R_REG(ch->osh, &regs->mib.tx_excessive_cols);
877 etc->mib.tx_late_cols += R_REG(ch->osh, &regs->mib.tx_late_cols);
878 etc->mib.tx_defered += R_REG(ch->osh, &regs->mib.tx_defered);
879 etc->mib.tx_carrier_lost += R_REG(ch->osh, &regs->mib.tx_carrier_lost);
880 etc->mib.tx_pause_pkts += R_REG(ch->osh, &regs->mib.tx_pause_pkts);
881 etc->mib.rx_broadcast_pkts += R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
882 etc->mib.rx_multicast_pkts += R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
883 etc->mib.rx_len_64 += R_REG(ch->osh, &regs->mib.rx_len_64);
884 etc->mib.rx_len_65_to_127 += R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
885 etc->mib.rx_len_128_to_255 += R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
886 etc->mib.rx_len_256_to_511 += R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
887 etc->mib.rx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
888 etc->mib.rx_len_1024_to_max += R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
889 etc->mib.rx_jabber_pkts += R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
890 etc->mib.rx_oversize_pkts += R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
891 etc->mib.rx_fragment_pkts += R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
892 etc->mib.rx_missed_pkts += R_REG(ch->osh, &regs->mib.rx_missed_pkts);
893 etc->mib.rx_crc_align_errs += R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
894 etc->mib.rx_undersize += R_REG(ch->osh, &regs->mib.rx_undersize);
895 etc->mib.rx_crc_errs += R_REG(ch->osh, &regs->mib.rx_crc_errs);
896 etc->mib.rx_align_errs += R_REG(ch->osh, &regs->mib.rx_align_errs);
897 etc->mib.rx_symbol_errs += R_REG(ch->osh, &regs->mib.rx_symbol_errs);
898 etc->mib.rx_pause_pkts += R_REG(ch->osh, &regs->mib.rx_pause_pkts);
899 etc->mib.rx_nonpause_pkts += R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
902 * Aggregate transmit and receive errors that probably resulted
903 * in the loss of a frame are computed on the fly.
905 * We seem to get lots of tx_carrier_lost errors when flipping
906 * speed modes so don't count these as tx errors.
908 * Arbitrarily lump the non-specific dma errors as tx errors.
910 etc->txerror = etc->mib.tx_jabber_pkts + etc->mib.tx_oversize_pkts
911 + etc->mib.tx_underruns + etc->mib.tx_excessive_cols
912 + etc->mib.tx_late_cols + etc->txnobuf + etc->dmade
913 + etc->dmada + etc->dmape + etc->txuflo + etc->txnobuf;
914 etc->rxerror = etc->mib.rx_jabber_pkts + etc->mib.rx_oversize_pkts
915 + etc->mib.rx_missed_pkts + etc->mib.rx_crc_align_errs
916 + etc->mib.rx_undersize + etc->mib.rx_crc_errs
917 + etc->mib.rx_align_errs + etc->mib.rx_symbol_errs
918 + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen;
921 static void
922 chipenablepme(struct bcm4xxx *ch)
924 bcmenetregs_t *regs;
926 regs = ch->regs;
928 /* enable chip wakeup pattern matching */
929 OR_REG(ch->osh, &regs->devcontrol, DC_PM);
931 /* enable sonics bus PME */
932 sb_coreflags(ch->sbh, SBTML_PE, SBTML_PE);
935 static void
936 chipdisablepme(struct bcm4xxx *ch)
938 bcmenetregs_t *regs;
940 regs = ch->regs;
942 AND_REG(ch->osh, &regs->devcontrol, ~DC_PM);
943 sb_coreflags(ch->sbh, SBTML_PE, 0);
946 static void
947 chipduplexupd(struct bcm4xxx *ch)
949 uint32 txcontrol;
951 txcontrol = R_REG(ch->osh, &ch->regs->txcontrol);
952 if (ch->etc->duplex && !(txcontrol & EXC_FD))
953 OR_REG(ch->osh, &ch->regs->txcontrol, EXC_FD);
954 else if (!ch->etc->duplex && (txcontrol & EXC_FD))
955 AND_REG(ch->osh, &ch->regs->txcontrol, ~EXC_FD);
958 static uint16
959 chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg)
961 bcmenetregs_t *regs;
963 ASSERT(phyaddr < MAXEPHY);
966 * BCM5222 dualphy shared mdio contortion.
967 * remote phy: another emac controls our phy.
969 if (ch->etc->mdcport != ch->etc->coreunit) {
970 if (ch->etphy == NULL) {
971 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
973 /* first time reset */
974 if (ch->etphy)
975 chipphyreset(ch, ch->etc->phyaddr);
977 if (ch->etphy)
978 return (et_phyrd(ch->etphy, phyaddr, reg));
979 else
980 return (0xffff);
983 /* local phy: our emac controls our phy */
985 regs = ch->regs;
987 /* clear mii_int */
988 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
990 /* issue the read */
991 W_REG(ch->osh, &regs->mdiodata, (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT)
992 | (reg << MD_RA_SHIFT) | MD_TA_VALID));
994 /* wait for it to complete */
995 SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
996 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
997 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
1000 return (R_REG(ch->osh, &regs->mdiodata) & MD_DATA_MASK);
1003 static void
1004 chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1006 bcmenetregs_t *regs;
1008 ASSERT(phyaddr < MAXEPHY);
1011 * BCM5222 dualphy shared mdio contortion.
1012 * remote phy: another emac controls our phy.
1014 if (ch->etc->mdcport != ch->etc->coreunit) {
1015 if (ch->etphy == NULL)
1016 ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
1017 if (ch->etphy)
1018 et_phywr(ch->etphy, phyaddr, reg, v);
1019 return;
1022 /* local phy: our emac controls our phy */
1024 regs = ch->regs;
1026 /* clear mii_int */
1027 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1028 ASSERT((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0);
1030 /* issue the write */
1031 W_REG(ch->osh, &regs->mdiodata, (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT)
1032 | (reg << MD_RA_SHIFT) | MD_TA_VALID | v));
1034 /* wait for it to complete */
1035 SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
1036 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1037 ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
1041 static void
1042 chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1044 uint16 tmp;
1046 tmp = chipphyrd(ch, phyaddr, reg);
1047 tmp |= v;
1048 chipphywr(ch, phyaddr, reg, tmp);
1051 static void
1052 chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1054 uint16 tmp;
1056 tmp = chipphyrd(ch, phyaddr, reg);
1057 tmp &= v;
1058 chipphywr(ch, phyaddr, reg, tmp);
1061 static void
1062 chipphyreset(struct bcm4xxx *ch, uint phyaddr)
1064 ASSERT(phyaddr < MAXEPHY);
1066 if (phyaddr == EPHY_NOREG)
1067 return;
1069 chipphywr(ch, phyaddr, 0, CTL_RESET);
1070 OSL_DELAY(100);
1071 if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) {
1072 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit));
1075 chipphyinit(ch, phyaddr);
1078 static void
1079 chipphyinit(struct bcm4xxx *ch, uint phyaddr)
1081 uint phyid = 0;
1083 /* enable activity led */
1084 chipphyand(ch, phyaddr, 26, 0x7fff);
1086 /* enable traffic meter led mode */
1087 chipphyor(ch, phyaddr, 27, (1 << 6));
1089 phyid = chipphyrd(ch, phyaddr, 0x2);
1090 phyid |= chipphyrd(ch, phyaddr, 0x3) << 16;
1092 if (phyid == 0x55210022) {
1093 chipphywr(ch, phyaddr, 28, (uint16) (chipphyrd(ch, phyaddr, 28) & 0x0fff));
1094 chipphywr(ch, phyaddr, 30, (uint16) (chipphyrd(ch, phyaddr, 30) | 0x3000));
1095 chipphywr(ch, phyaddr, 22, (uint16) (chipphyrd(ch, phyaddr, 22) & 0xffdf));
1097 chipphywr(ch, phyaddr, 28, (uint16) ((chipphyrd(ch, phyaddr, 28) & 0x0fff) | 0x1000));
1098 chipphywr(ch, phyaddr, 29, 1);
1099 chipphywr(ch, phyaddr, 30, 4);
1101 chipphywr(ch, phyaddr, 28, (uint16) (chipphyrd( ch, phyaddr, 28) & 0x0fff));
1105 static void
1106 chipphyforce(struct bcm4xxx *ch, uint phyaddr)
1108 etc_info_t *etc;
1109 uint16 ctl;
1111 ASSERT(phyaddr < MAXEPHY);
1113 if (phyaddr == EPHY_NOREG)
1114 return;
1116 etc = ch->etc;
1118 if (etc->forcespeed == ET_AUTO)
1119 return;
1121 ctl = chipphyrd(ch, phyaddr, 0);
1122 ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX);
1124 switch (etc->forcespeed) {
1125 case ET_10HALF:
1126 break;
1128 case ET_10FULL:
1129 ctl |= CTL_DUPLEX;
1130 break;
1132 case ET_100HALF:
1133 ctl |= CTL_SPEED;
1134 break;
1136 case ET_100FULL:
1137 ctl |= (CTL_SPEED | CTL_DUPLEX);
1138 break;
1141 chipphywr(ch, phyaddr, 0, ctl);
1143 /* force Auto MDI-X for the AC101L phy */
1144 if (chipphyrd(ch, phyaddr, 2) == 0x0022 &&
1145 chipphyrd(ch, phyaddr, 3) == 0x5521)
1147 chipphywr(ch, phyaddr, 23, 0x8000);
1151 /* set selected capability bits in autonegotiation advertisement */
1152 static void
1153 chipphyadvertise(struct bcm4xxx *ch, uint phyaddr)
1155 etc_info_t *etc;
1156 uint16 adv;
1158 ASSERT(phyaddr < MAXEPHY);
1160 if (phyaddr == EPHY_NOREG)
1161 return;
1163 etc = ch->etc;
1165 if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
1166 return;
1168 ASSERT(etc->advertise);
1170 /* reset our advertised capabilitity bits */
1171 adv = chipphyrd(ch, phyaddr, 4);
1172 adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
1173 adv |= etc->advertise;
1174 chipphywr(ch, phyaddr, 4, adv);
1176 /* restart autonegotiation */
1177 chipphyor(ch, phyaddr, 0, CTL_RESTART);
1179 etc->needautoneg = FALSE;