usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src-rt / et / sys / etcgmac.c
blob44116edfa0b311fdd360634931e1027ceb3c9805
1 /*
2 * Broadcom Gigabit Ethernet MAC (Unimac) core.
4 * This file implements the chip-specific routines for the GMAC core.
6 * Copyright (C) 2010, Broadcom Corporation
7 * All Rights Reserved.
8 *
9 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
10 * the contents of this file may not be disclosed to third parties, copied
11 * or duplicated in any form, in whole or in part, without the prior
12 * written permission of Broadcom Corporation.
13 * $Id: etcgmac.c,v 1.25.8.6 2010-11-16 21:25:19 Exp $
16 #include <typedefs.h>
17 #include <osl.h>
18 #include <bcmdefs.h>
19 #include <bcmendian.h>
20 #include <bcmutils.h>
21 #include <bcmdevs.h>
22 #include <bcmenetphy.h>
23 #include <proto/ethernet.h>
24 #include <proto/802.1d.h>
25 #include <siutils.h>
26 #include <sbhnddma.h>
27 #include <sbchipc.h>
28 #include <hnddma.h>
29 #include <et_dbg.h>
30 #include <hndsoc.h>
31 #include <hndpmu.h>
32 #include <bcmgmacmib.h>
33 #include <gmac_common.h>
34 #include <gmac_core.h>
35 #include <et_export.h> /* for et_phyxx() routines */
36 #include <etcgmac.h>
37 #include <bcmenetrxh.h>
38 #include <bcmgmacrxh.h>
40 #ifdef ETROBO
41 #include <bcmrobo.h>
42 #endif /* ETROBO */
43 #ifdef ETADM
44 #include <etc_adm.h>
45 #endif /* ETADM */
47 struct bcmgmac; /* forward declaration */
48 #define ch_t struct bcmgmac
49 #include <etc.h>
51 /* private chip state */
52 struct bcmgmac {
53 void *et; /* pointer to et private state */
54 etc_info_t *etc; /* pointer to etc public state */
56 gmac_commonregs_t *regscomm; /* pointer to GMAC COMMON registers */
57 gmacregs_t *regs; /* pointer to chip registers */
58 osl_t *osh; /* os handle */
60 void *etphy; /* pointer to et for shared mdc/mdio contortion */
62 uint32 intstatus; /* saved interrupt condition bits */
63 uint32 intmask; /* current software interrupt mask */
64 uint32 def_intmask; /* default interrupt mask */
66 hnddma_t *di[NUMTXQ]; /* dma engine software state */
68 bool mibgood; /* true once mib registers have been cleared */
69 gmacmib_t mib; /* mib statistic counters */
70 si_t *sih; /* si utils handle */
72 char *vars; /* sprom name=value */
73 uint vars_size;
75 void *adm; /* optional admtek private data */
76 mcfilter_t mf; /* multicast filter */
79 /* local prototypes */
80 static bool chipid(uint vendor, uint device);
81 static void *chipattach(etc_info_t *etc, void *osh, void *regsva);
82 static void chipdetach(ch_t *ch);
83 static void chipreset(ch_t *ch);
84 static void chipinit(ch_t *ch, uint options);
85 static bool chiptx(ch_t *ch, void *p);
86 static void *chiprx(ch_t *ch);
87 static void chiprxfill(ch_t *ch);
88 static int chipgetintrevents(ch_t *ch, bool in_isr);
89 static bool chiperrors(ch_t *ch);
90 static void chipintrson(ch_t *ch);
91 static void chipintrsoff(ch_t *ch);
92 static void chiptxreclaim(ch_t *ch, bool all);
93 static void chiprxreclaim(ch_t *ch);
94 static void chipstatsupd(ch_t *ch);
95 static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear);
96 static void chipenablepme(ch_t *ch);
97 static void chipdisablepme(ch_t *ch);
98 static void chipphyreset(ch_t *ch, uint phyaddr);
99 static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg);
100 static void chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v);
101 static void chipdump(ch_t *ch, struct bcmstrbuf *b);
102 static void chiplongname(ch_t *ch, char *buf, uint bufsize);
103 static void chipduplexupd(ch_t *ch);
105 static void chipphyinit(ch_t *ch, uint phyaddr);
106 static void chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v);
107 static void chipphyforce(ch_t *ch, uint phyaddr);
108 static void chipphyadvertise(ch_t *ch, uint phyaddr);
109 #ifdef BCMDBG
110 static void chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b);
111 #endif /* BCMDBG */
112 static void gmac_mf_cleanup(ch_t *ch);
113 static int gmac_speed(ch_t *ch, uint32 speed);
114 static void gmac_miiconfig(ch_t *ch);
116 struct chops bcmgmac_et_chops = {
117 chipid,
118 chipattach,
119 chipdetach,
120 chipreset,
121 chipinit,
122 chiptx,
123 chiprx,
124 chiprxfill,
125 chipgetintrevents,
126 chiperrors,
127 chipintrson,
128 chipintrsoff,
129 chiptxreclaim,
130 chiprxreclaim,
131 chipstatsupd,
132 chipdumpmib,
133 chipenablepme,
134 chipdisablepme,
135 chipphyreset,
136 chipphyrd,
137 chipphywr,
138 chipdump,
139 chiplongname,
140 chipduplexupd
143 static uint devices[] = {
144 BCM47XX_GMAC_ID,
145 BCM4716_CHIP_ID,
146 0x0000
149 static bool
150 chipid(uint vendor, uint device)
152 int i;
154 if (vendor != VENDOR_BROADCOM)
155 return (FALSE);
157 for (i = 0; devices[i]; i++) {
158 if (device == devices[i])
159 return (TRUE);
162 return (FALSE);
165 static void *
166 chipattach(etc_info_t *etc, void *osh, void *regsva)
168 ch_t *ch;
169 gmacregs_t *regs;
170 uint i;
171 char name[16];
172 char *var;
173 uint boardflags, boardtype, reset;
175 ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva));
177 if ((ch = (ch_t *)MALLOC(osh, sizeof(ch_t))) == NULL) {
178 ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit,
179 MALLOCED(osh)));
180 return (NULL);
182 bzero((char *)ch, sizeof(ch_t));
184 ch->etc = etc;
185 ch->et = etc->et;
186 ch->osh = osh;
188 /* store the pointer to the sw mib */
189 etc->mib = (void *)&ch->mib;
191 /* get si handle */
192 if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars,
193 &ch->vars_size)) == NULL) {
194 ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit));
195 goto fail;
198 if ((etc->corerev = si_corerev(ch->sih)) == GMAC_4706B0_CORE_REV &&
199 (ch->regscomm = (gmac_commonregs_t *)si_setcore(ch->sih,
200 GMAC_COMMON_4706_CORE_ID, 0)) == NULL) {
201 ET_ERROR(("et%d: chipattach: Could not setcore to the GMAC common core\n", etc->unit));
202 goto fail;
205 if ((regs = (gmacregs_t *)si_setcore(ch->sih, GMAC_CORE_ID, etc->unit)) == NULL) {
206 ET_ERROR(("et%d: chipattach: Could not setcore to the GMAC core\n", etc->unit));
207 goto fail;
210 ch->regs = regs;
211 etc->chip = ch->sih->chip;
212 etc->chiprev = ch->sih->chiprev;
213 etc->coreid = si_coreid(ch->sih);
214 etc->nicmode = !(ch->sih->bustype == SI_BUS);
215 etc->coreunit = si_coreunit(ch->sih);
216 etc->boardflags = getintvar(ch->vars, "boardflags");
218 boardflags = etc->boardflags;
219 boardtype = ch->sih->boardtype;
221 /* get our local ether addr */
222 sprintf(name, "et%dmacaddr", etc->coreunit);
223 var = getvar(ch->vars, name);
224 if (var == NULL) {
225 ET_ERROR(("et%d: chipattach: getvar(%s) not found\n", etc->unit, name));
226 goto fail;
228 ET_TRACE(("et get local ether addr: %s = %s\n", name, var));//Yau
229 bcm_ether_atoe(var, &etc->perm_etheraddr);
231 if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) {
232 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var));
233 goto fail;
235 bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN);
238 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
239 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
242 /* get our phyaddr value */
243 sprintf(name, "et%dphyaddr", etc->coreunit);
244 var = getvar(ch->vars, name);
245 if (var == NULL) {
246 ET_ERROR(("et%d: chipattach: getvar(%s) not found\n", etc->unit, name));
247 goto fail;
249 ET_TRACE(("et get phyaddr:: %s = %s\n", name, var));//Yau
250 etc->phyaddr = bcm_atoi(var) & EPHY_MASK;
252 /* nvram says no phy is present */
253 if (etc->phyaddr == EPHY_NONE) {
254 ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit));
255 goto fail;
258 /* configure pci core */
259 si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
261 /* reset the gmac core */
262 chipreset(ch);
264 /* dma attach */
265 sprintf(name, "et%d", etc->coreunit);
267 /* allocate dma resources for txqs */
268 /* TX: TC_BK, RX: RX_Q0 */
269 ch->di[0] = dma_attach(osh, name, ch->sih,
270 DMAREG(ch, DMA_TX, TX_Q0),
271 DMAREG(ch, DMA_RX, RX_Q0),
272 NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF,
273 &et_msg_level);
275 /* TX: TC_BE, RX: UNUSED */
276 ch->di[1] = dma_attach(osh, name, ch->sih,
277 DMAREG(ch, DMA_TX, TX_Q1),
278 NULL /* rxq unused */,
279 NTXD, 0, 0, -1, 0, 0, &et_msg_level);
281 /* TX: TC_CL, RX: UNUSED */
282 ch->di[2] = dma_attach(osh, name, ch->sih,
283 DMAREG(ch, DMA_TX, TX_Q2),
284 NULL /* rxq unused */,
285 NTXD, 0, 0, -1, 0, 0, &et_msg_level);
287 /* TX: TC_VO, RX: UNUSED */
288 ch->di[3] = dma_attach(osh, name, ch->sih,
289 DMAREG(ch, DMA_TX, TX_Q3),
290 NULL /* rxq unused */,
291 NTXD, 0, 0, -1, 0, 0, &et_msg_level);
293 for (i = 0; i < NUMTXQ; i++)
294 if (ch->di[i] == NULL) {
295 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit));
296 goto fail;
299 for (i = 0; i < NUMTXQ; i++)
300 if (ch->di[i] != NULL)
301 etc->txavail[i] = (uint *)&ch->di[i]->txavail;
303 /* set default sofware intmask */
304 sprintf(name, "et%d_no_txint", etc->coreunit);
305 if (getintvar(ch->vars, name)) {
306 /* if no_txint variable is non-zero we disable tx interrupts.
307 * we do the tx buffer reclaim once every few frames.
309 ch->def_intmask = (DEF_INTMASK & ~(I_XI0 | I_XI1 | I_XI2 | I_XI3));
310 etc->txrec_thresh = (((NTXD >> 2) > TXREC_THR) ? TXREC_THR - 1 : 1);
311 } else
312 ch->def_intmask = DEF_INTMASK;
314 ch->intmask = ch->def_intmask;
316 /* reset the external phy */
317 if ((reset = getgpiopin(ch->vars, "ephy_reset", GPIO_PIN_NOTDEFINED)) !=
318 GPIO_PIN_NOTDEFINED) {
319 reset = 1 << reset;
321 /* Keep RESET low for 2 us */
322 si_gpioout(ch->sih, reset, 0, GPIO_DRV_PRIORITY);
323 si_gpioouten(ch->sih, reset, reset, GPIO_DRV_PRIORITY);
324 OSL_DELAY(2);
326 /* Keep RESET high for at least 2 us */
327 si_gpioout(ch->sih, reset, reset, GPIO_DRV_PRIORITY);
328 OSL_DELAY(2);
330 /* if external phy is present enable auto-negotation and
331 * advertise full capabilities as default config.
333 ASSERT(etc->phyaddr != EPHY_NOREG);
334 etc->needautoneg = TRUE;
335 etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
336 etc->advertise2 = ADV_1000FULL;
339 /* reset phy: reset it once now */
340 chipphyreset(ch, etc->phyaddr);
342 #ifdef ETROBO
344 * Broadcom Robo ethernet switch.
346 if ((boardflags & BFL_ENETROBO) && (etc->phyaddr == EPHY_NOREG)) {
347 ET_TRACE(("et%d: chipattach: Calling robo attach\n", etc->unit));
349 /* Attach to the switch */
350 if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars,
351 (miird_f)bcmgmac_et_chops.phyrd,
352 (miiwr_f)bcmgmac_et_chops.phywr))) {
353 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit));
354 goto fail;
356 /* Enable the switch and set it to a known good state */
357 if (bcm_robo_enable_device(etc->robo)) {
358 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit));
359 goto fail;
361 /* Configure the switch to do VLAN */
362 if ((boardflags & BFL_ENETVLAN) &&
363 bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) {
364 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit));
365 goto fail;
367 /* Enable switching/forwarding */
368 if (bcm_robo_enable_switch(etc->robo)) {
369 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit));
370 goto fail;
372 #ifdef PLC
373 /* Configure the switch port connected to PLC chipset */
374 robo_plc_hw_init(etc->robo);
375 #endif /* PLC */
377 #endif /* ETROBO */
379 #ifdef ETADM
381 * ADMtek ethernet switch.
383 if (boardflags & BFL_ENETADM) {
384 /* Attach to the device */
385 if (!(ch->adm = adm_attach(ch->sih, ch->vars))) {
386 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc->unit));
387 goto fail;
389 /* Enable the external switch and set it to a known good state */
390 if (adm_enable_device(ch->adm)) {
391 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc->unit));
392 goto fail;
394 /* Configure the switch */
395 if ((boardflags & BFL_ENETVLAN) && adm_config_vlan(ch->adm)) {
396 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc->unit));
397 goto fail;
400 #endif /* ETADM */
402 return ((void *) ch);
404 fail:
405 chipdetach(ch);
406 return (NULL);
409 static void
410 chipdetach(ch_t *ch)
412 int32 i;
414 ET_TRACE(("et%d: chipdetach\n", ch->etc->unit));
416 if (ch == NULL)
417 return;
419 #ifdef ETROBO
420 /* free robo state */
421 if (ch->etc->robo)
422 bcm_robo_detach(ch->etc->robo);
423 #endif /* ETROBO */
425 #ifdef ETADM
426 /* free ADMtek state */
427 if (ch->adm)
428 adm_detach(ch->adm);
429 #endif /* ETADM */
431 /* free dma state */
432 for (i = 0; i < NUMTXQ; i++)
433 if (ch->di[i] != NULL) {
434 dma_detach(ch->di[i]);
435 ch->di[i] = NULL;
438 /* put the core back into reset */
439 if (ch->sih)
440 si_core_disable(ch->sih, 0);
442 ch->etc->mib = NULL;
444 /* free si handle */
445 si_detach(ch->sih);
446 ch->sih = NULL;
448 /* free vars */
449 if (ch->vars)
450 MFREE(ch->osh, ch->vars, ch->vars_size);
452 /* free chip private state */
453 MFREE(ch->osh, ch, sizeof(ch_t));
456 static void
457 chiplongname(ch_t *ch, char *buf, uint bufsize)
459 char *s;
461 switch (ch->etc->deviceid) {
462 case BCM47XX_GMAC_ID:
463 case BCM4716_CHIP_ID:
464 default:
465 s = "Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller";
466 break;
469 strncpy(buf, s, bufsize);
470 buf[bufsize - 1] = '\0';
473 static void
474 chipdump(ch_t *ch, struct bcmstrbuf *b)
476 #ifdef BCMDBG
477 int32 i;
479 bcm_bprintf(b, "regs 0x%lx etphy 0x%lx ch->intstatus 0x%x intmask 0x%x\n",
480 (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask);
481 bcm_bprintf(b, "\n");
483 /* dma engine state */
484 for (i = 0; i < NUMTXQ; i++) {
485 dma_dump(ch->di[i], b, TRUE);
486 bcm_bprintf(b, "\n");
489 /* registers */
490 chipdumpregs(ch, ch->regs, b);
491 bcm_bprintf(b, "\n");
493 /* switch registers */
494 #ifdef ETROBO
495 if (ch->etc->robo)
496 robo_dump_regs(ch->etc->robo, b);
497 #endif /* ETROBO */
498 #ifdef ETADM
499 if (ch->adm)
500 adm_dump_regs(ch->adm, b->buf);
501 #endif /* ETADM */
502 #endif /* BCMDBG */
505 #ifdef BCMDBG
507 #define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->name))
508 #define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, &regs->mib.name))
510 static void
511 chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b)
513 uint phyaddr;
515 phyaddr = ch->etc->phyaddr;
517 PRREG(devcontrol); PRREG(devstatus);
518 bcm_bprintf(b, "\n");
519 PRREG(biststatus);
520 bcm_bprintf(b, "\n");
521 PRREG(intstatus); PRREG(intmask); PRREG(gptimer);
522 bcm_bprintf(b, "\n");
523 PRREG(intrecvlazy);
524 bcm_bprintf(b, "\n");
525 PRREG(flowctlthresh); PRREG(wrrthresh); PRREG(gmac_idle_cnt_thresh);
526 bcm_bprintf(b, "\n");
527 if (ch->etc->corerev != GMAC_4706B0_CORE_REV) {
528 PRREG(phyaccess); PRREG(phycontrol);
529 bcm_bprintf(b, "\n");
531 PRREG(txqctl); PRREG(rxqctl);
532 bcm_bprintf(b, "\n");
533 PRREG(gpioselect); PRREG(gpio_output_en);
534 bcm_bprintf(b, "\n");
535 PRREG(clk_ctl_st); PRREG(pwrctl);
536 bcm_bprintf(b, "\n");
538 /* unimac registers */
539 PRREG(unimacversion); PRREG(hdbkpctl);
540 bcm_bprintf(b, "\n");
541 PRREG(cmdcfg);
542 bcm_bprintf(b, "\n");
543 PRREG(macaddrhigh); PRREG(macaddrlow);
544 bcm_bprintf(b, "\n");
545 PRREG(rxmaxlength); PRREG(pausequanta); PRREG(macmode);
546 bcm_bprintf(b, "\n");
547 PRREG(outertag); PRREG(innertag); PRREG(txipg); PRREG(pausectl);
548 bcm_bprintf(b, "\n");
549 PRREG(txflush); PRREG(rxstatus); PRREG(txstatus);
550 bcm_bprintf(b, "\n");
552 /* mib registers */
553 PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts);
554 bcm_bprintf(b, "\n");
555 PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts);
556 bcm_bprintf(b, "\n");
557 PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts);
558 bcm_bprintf(b, "\n");
559 PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols);
560 bcm_bprintf(b, "\n");
561 PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols);
562 bcm_bprintf(b, "\n");
563 if (ch->etc->corerev != GMAC_4706B0_CORE_REV) {
564 PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts);
565 bcm_bprintf(b, "\n");
568 PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts);
569 bcm_bprintf(b, "\n");
570 PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts);
571 bcm_bprintf(b, "\n");
572 PRMIBREG(rx_jabber_pkts);
573 if (ch->etc->corerev != GMAC_4706B0_CORE_REV) {
574 PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts);
575 bcm_bprintf(b, "\n");
576 PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize);
578 bcm_bprintf(b, "\n");
579 if (ch->etc->corerev != GMAC_4706B0_CORE_REV) {
580 PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs);
581 bcm_bprintf(b, "\n");
582 PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts);
583 bcm_bprintf(b, "\n");
585 if (phyaddr != EPHY_NOREG) {
586 /* print a few interesting phy registers */
587 bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n",
588 chipphyrd(ch, phyaddr, 0),
589 chipphyrd(ch, phyaddr, 1),
590 chipphyrd(ch, phyaddr, 2),
591 chipphyrd(ch, phyaddr, 3));
592 bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n",
593 chipphyrd(ch, phyaddr, 4),
594 chipphyrd(ch, phyaddr, 5),
595 chipphyrd(ch, phyaddr, 24),
596 chipphyrd(ch, phyaddr, 25));
600 #endif /* BCMDBG */
602 static void
603 gmac_clearmib(ch_t *ch)
605 volatile uint32 *ptr;
607 if (ch->etc->corerev == GMAC_4706B0_CORE_REV)
608 return;
610 /* enable clear on read */
611 OR_REG(ch->osh, &ch->regs->devcontrol, DC_MROR);
613 for (ptr = &ch->regs->mib.tx_good_octets; ptr <= &ch->regs->mib.rx_uni_pkts; ptr++) {
614 (void)R_REG(ch->osh, ptr);
615 if (ptr == &ch->regs->mib.tx_q3_octets_high)
616 ptr++;
619 return;
622 static void
623 gmac_init_reset(ch_t *ch)
625 OR_REG(ch->osh, &ch->regs->cmdcfg, CC_SR);
626 OSL_DELAY(GMAC_RESET_DELAY);
629 static void
630 gmac_clear_reset(ch_t *ch)
632 AND_REG(ch->osh, &ch->regs->cmdcfg, ~CC_SR);
633 OSL_DELAY(GMAC_RESET_DELAY);
636 static void
637 gmac_reset(ch_t *ch)
639 uint32 ocmdcfg, cmdcfg;
641 /* put the mac in reset */
642 gmac_init_reset(ch);
644 /* initialize default config */
645 ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
647 cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML |
648 CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF);
649 cmdcfg |= (CC_PROM | CC_NLC | CC_CFE);
651 if (cmdcfg != ocmdcfg)
652 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
654 /* bring mac out of reset */
655 gmac_clear_reset(ch);
658 static void
659 gmac_promisc(ch_t *ch, bool mode)
661 uint32 cmdcfg;
663 cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
665 /* put the mac in reset */
666 gmac_init_reset(ch);
668 /* enable or disable promiscuous mode */
669 if (mode)
670 cmdcfg |= CC_PROM;
671 else
672 cmdcfg &= ~CC_PROM;
674 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
676 /* bring mac out of reset */
677 gmac_clear_reset(ch);
680 static int
681 gmac_speed(ch_t *ch, uint32 speed)
683 uint32 cmdcfg;
684 uint32 hd_ena = 0;
686 switch (speed) {
687 case ET_10HALF:
688 hd_ena = CC_HD;
689 /* FALLTHRU */
691 case ET_10FULL:
692 speed = 0;
693 break;
695 case ET_100HALF:
696 hd_ena = CC_HD;
697 /* FALLTHRU */
699 case ET_100FULL:
700 speed = 1;
701 break;
703 case ET_1000FULL:
704 speed = 2;
705 break;
707 case ET_1000HALF:
708 ET_ERROR(("et%d: gmac_speed: supports 1000 mbps full duplex only\n",
709 ch->etc->unit));
710 return (FAILURE);
712 default:
713 ET_ERROR(("et%d: gmac_speed: speed %d not supported\n",
714 ch->etc->unit, speed));
715 return (FAILURE);
718 cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
720 /* put mac in reset */
721 gmac_init_reset(ch);
723 /* set the speed */
724 cmdcfg &= ~(CC_ES_MASK | CC_HD);
725 cmdcfg |= ((speed << CC_ES_SHIFT) | hd_ena);
726 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
728 /* bring mac out of reset */
729 gmac_clear_reset(ch);
731 return (SUCCESS);
734 static void
735 gmac_macloopback(ch_t *ch, bool on)
737 uint32 ocmdcfg, cmdcfg;
739 ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
741 /* put mac in reset */
742 gmac_init_reset(ch);
744 /* set/clear the mac loopback mode */
745 if (on)
746 cmdcfg |= CC_ML;
747 else
748 cmdcfg &= ~CC_ML;
750 if (cmdcfg != ocmdcfg)
751 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
753 /* bring mac out of reset */
754 gmac_clear_reset(ch);
757 static int
758 gmac_loopback(ch_t *ch, uint32 mode)
760 switch (mode) {
761 case LOOPBACK_MODE_DMA:
762 /* to enable loopback for any channel set the loopback
763 * enable bit in xmt0control register.
765 dma_fifoloopbackenable(ch->di[TX_Q0]);
766 break;
768 case LOOPBACK_MODE_MAC:
769 gmac_macloopback(ch, TRUE);
770 break;
772 case LOOPBACK_MODE_NONE:
773 gmac_macloopback(ch, FALSE);
774 break;
776 default:
777 ET_ERROR(("et%d: gmac_loopaback: Unknown loopback mode %d\n",
778 ch->etc->unit, mode));
779 return (FAILURE);
782 return (SUCCESS);
785 static void
786 gmac_enable(ch_t *ch)
788 uint32 cmdcfg, rxqctl, bp_clk, mdp, mode;
789 gmacregs_t *regs;
791 regs = ch->regs;
793 cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
795 /* put mac in reset */
796 gmac_init_reset(ch);
798 cmdcfg |= CC_SR;
800 /* first deassert rx_ena and tx_ena while in reset */
801 cmdcfg &= ~(CC_RE | CC_TE);
802 W_REG(ch->osh, &regs->cmdcfg, cmdcfg);
804 /* bring mac out of reset */
805 gmac_clear_reset(ch);
807 /* enable the mac transmit and receive paths now */
808 OSL_DELAY(2);
809 cmdcfg &= ~CC_SR;
810 cmdcfg |= (CC_RE | CC_TE);
812 /* assert rx_ena and tx_ena when out of reset to enable the mac */
813 W_REG(ch->osh, &regs->cmdcfg, cmdcfg);
815 /* WAR to not force ht for 47162 when gmac is in rev mii mode */
816 mode = ((R_REG(ch->osh, &regs->devstatus) & DS_MM_MASK) >> DS_MM_SHIFT);
817 if ((CHIPID(ch->sih->chip) != BCM47162_CHIP_ID) || (mode != 0))
818 /* request ht clock */
819 OR_REG(ch->osh, &regs->clk_ctl_st, CS_FH);
821 if ((CHIPID(ch->sih->chip) == BCM47162_CHIP_ID) && (mode == 2))
822 si_pmu_chipcontrol(ch->sih, PMU_CHIPCTL1, PMU_CC1_RXC_DLL_BYPASS,
823 PMU_CC1_RXC_DLL_BYPASS);
825 /* Set the GMAC flowcontrol on and off thresholds and pause retry timer
826 * the thresholds are tuned based on size of buffer internal to GMAC.
828 if ((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) ||
829 (CHIPID(ch->sih->chip) == BCM4749_CHIP_ID) ||
830 (CHIPID(ch->sih->chip) == BCM53572_CHIP_ID) ||
831 (CHIPID(ch->sih->chip) == BCM4716_CHIP_ID) ||
832 (CHIPID(ch->sih->chip) == BCM47162_CHIP_ID)) {
833 uint32 flctl = 0x03cb04cb;
835 if ((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) ||
836 (CHIPID(ch->sih->chip) == BCM4749_CHIP_ID) ||
837 (CHIPID(ch->sih->chip) == BCM53572_CHIP_ID))
838 flctl = 0x2300e1;
840 W_REG(ch->osh, &regs->flowctlthresh, flctl);
841 W_REG(ch->osh, &regs->pausectl, 0x27fff);
844 /* init the mac data period. the value is set according to expr
845 * ((128ns / bp_clk) - 3).
847 rxqctl = R_REG(ch->osh, &regs->rxqctl);
848 rxqctl &= ~RC_MDP_MASK;
849 bp_clk = si_clock(ch->sih) / 1000000;
850 mdp = ((bp_clk * 128) / 1000) - 3;
851 W_REG(ch->osh, &regs->rxqctl, rxqctl | (mdp << RC_MDP_SHIFT));
853 return;
856 static void
857 gmac_txflowcontrol(ch_t *ch, bool on)
859 uint32 cmdcfg;
861 cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
863 /* put the mac in reset */
864 gmac_init_reset(ch);
866 /* to enable tx flow control clear the rx pause ignore bit */
867 if (on)
868 cmdcfg &= ~CC_RPI;
869 else
870 cmdcfg |= CC_RPI;
872 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
874 /* bring mac out of reset */
875 gmac_clear_reset(ch);
878 static void
879 gmac_miiconfig(ch_t *ch)
881 uint32 devstatus, mode;
882 gmacregs_t *regs;
884 regs = ch->regs;
886 /* Read the devstatus to figure out the configuration
887 * mode of the interface.
889 devstatus = R_REG(ch->osh, &regs->devstatus);
890 mode = ((devstatus & DS_MM_MASK) >> DS_MM_SHIFT);
892 /* Set the speed to 100 if the switch interface is
893 * using mii/rev mii.
895 if ((mode == 0) || (mode == 1)) {
896 if (ch->etc->forcespeed == ET_AUTO)
897 gmac_speed(ch, ET_100FULL);
898 else
899 gmac_speed(ch, ch->etc->forcespeed);
903 static void
904 chipreset(ch_t *ch)
906 gmacregs_t *regs;
907 uint32 i, sflags, flagbits = 0;
909 ET_TRACE(("et%d: chipreset\n", ch->etc->unit));
911 regs = ch->regs;
913 if (!si_iscoreup(ch->sih)) {
914 if (!ch->etc->nicmode)
915 si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih)));
916 /* power on reset: reset the enet core */
917 goto chipinreset;
920 /* update software counters before resetting the chip */
921 if (ch->mibgood)
922 chipstatsupd(ch);
924 /* reset the tx dma engines */
925 for (i = 0; i < NUMTXQ; i++) {
926 if (ch->di[i]) {
927 ET_TRACE(("et%d: resetting tx dma%d\n", ch->etc->unit, i));
928 dma_txreset(ch->di[i]);
932 /* set gmac into loopback mode to ensure no rx traffic */
933 gmac_loopback(ch, LOOPBACK_MODE_MAC);
934 OSL_DELAY(1);
936 /* reset the rx dma engine */
937 if (ch->di[RX_Q0]) {
938 ET_TRACE(("et%d: resetting rx dma\n", ch->etc->unit));
939 dma_rxreset(ch->di[RX_Q0]);
942 /* clear the multicast filter table */
943 gmac_mf_cleanup(ch);
945 chipinreset:
946 sflags = si_core_sflags(ch->sih, 0, 0);
947 /* Do not enable internal switch for 47186/47188 */
948 if ((((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) ||
949 (CHIPID(ch->sih->chip) == BCM4749_CHIP_ID)) &&
950 (ch->sih->chippkg == BCM47186_PKG_ID)) ||
951 ((CHIPID(ch->sih->chip) == BCM53572_CHIP_ID) && (ch->sih->chippkg == BCM47188_PKG_ID)))
952 sflags &= ~SISF_SW_ATTACHED;
954 if (sflags & SISF_SW_ATTACHED) {
955 ET_TRACE(("et%d: internal switch attached\n", ch->etc->unit));
956 flagbits = SICF_SWCLKE;
957 if (!ch->etc->robo) {
958 ET_TRACE(("et%d: reseting switch\n", ch->etc->unit));
959 flagbits |= SICF_SWRST;
963 /* reset core */
964 si_core_reset(ch->sih, flagbits, 0);
966 /* Request Misc PLL for corerev > 2 */
967 if (ch->etc->corerev > 2) {
968 OR_REG(ch->osh, &regs->clk_ctl_st, CS_ER);
969 SPINWAIT((R_REG(ch->osh, &regs->clk_ctl_st) & CS_ES) != CS_ES, 1000);
972 if ((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) ||
973 (CHIPID(ch->sih->chip) == BCM4749_CHIP_ID) ||
974 (CHIPID(ch->sih->chip) == BCM53572_CHIP_ID)) {
975 char *var;
976 uint32 sw_type = PMU_CC1_SW_TYPE_EPHY | PMU_CC1_IF_TYPE_MII;
978 if ((var = getvar(ch->vars, "et_swtype")) != NULL)
979 sw_type = (bcm_atoi(var) & 0x0f) << 4;
980 else if ((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) &&
981 (ch->sih->chippkg == BCM5358_PKG_ID))
982 sw_type = PMU_CC1_SW_TYPE_EPHYRMII;
983 else if ((ch->sih->chippkg == BCM47186_PKG_ID) ||
984 ((CHIPID(ch->sih->chip) == BCM53572_CHIP_ID) &&
985 (ch->sih->chippkg == BCM47188_PKG_ID)) ||
986 (ch->sih->chippkg == HWSIM_PKG_ID))
987 sw_type = PMU_CC1_IF_TYPE_RGMII|PMU_CC1_SW_TYPE_RGMII;
989 ET_TRACE(("%s: sw_type %04x\n", __FUNCTION__, sw_type));
990 si_pmu_chipcontrol(ch->sih, PMU_CHIPCTL1,
991 (PMU_CC1_IF_TYPE_MASK|PMU_CC1_SW_TYPE_MASK),
992 sw_type);
995 if ((sflags & SISF_SW_ATTACHED) && (!ch->etc->robo)) {
996 ET_TRACE(("et%d: taking switch out of reset\n", ch->etc->unit));
997 si_core_cflags(ch->sih, SICF_SWRST, 0);
1000 /* reset gmac */
1001 gmac_reset(ch);
1003 /* clear mib */
1004 gmac_clearmib(ch);
1005 ch->mibgood = TRUE;
1007 if (ch->etc->corerev == GMAC_4706B0_CORE_REV)
1008 OR_REG(ch->osh, &ch->regscomm->phycontrol, PC_MTE);
1009 else
1010 OR_REG(ch->osh, &regs->phycontrol, PC_MTE);
1012 /* Read the devstatus to figure out the configuration mode of
1013 * the interface. Set the speed to 100 if the switch interface
1014 * is mii/rmii.
1016 gmac_miiconfig(ch);
1018 /* gmac doesn't have internal phy */
1019 chipphyinit(ch, ch->etc->phyaddr);
1021 /* clear persistent sw intstatus */
1022 ch->intstatus = 0;
1026 * Lookup a multicast address in the filter hash table.
1028 static int
1029 gmac_mf_lkup(ch_t *ch, struct ether_addr *mcaddr)
1031 mflist_t *ptr;
1033 /* find the multicast address */
1034 for (ptr = ch->mf.bucket[GMAC_MCADDR_HASH(mcaddr)]; ptr != NULL; ptr = ptr->next) {
1035 if (!ETHER_MCADDR_CMP(&ptr->mc_addr, mcaddr))
1036 return (SUCCESS);
1039 return (FAILURE);
1043 * Add a multicast address to the filter hash table.
1045 static int
1046 gmac_mf_add(ch_t *ch, struct ether_addr *mcaddr)
1048 uint32 hash;
1049 mflist_t *entry;
1050 #ifdef BCMDBG
1051 char mac[ETHER_ADDR_STR_LEN];
1052 #endif /* BCMDBG */
1054 /* add multicast addresses only */
1055 if (!ETHER_ISMULTI(mcaddr)) {
1056 ET_ERROR(("et%d: adding invalid multicast address %s\n",
1057 ch->etc->unit, bcm_ether_ntoa(mcaddr, mac)));
1058 return (FAILURE);
1061 /* discard duplicate add requests */
1062 if (gmac_mf_lkup(ch, mcaddr) == SUCCESS) {
1063 ET_ERROR(("et%d: adding duplicate mcast filter entry\n", ch->etc->unit));
1064 return (FAILURE);
1067 /* allocate memory for list entry */
1068 entry = MALLOC(ch->osh, sizeof(mflist_t));
1069 if (entry == NULL) {
1070 ET_ERROR(("et%d: out of memory allocating mcast filter entry\n", ch->etc->unit));
1071 return (FAILURE);
1074 /* add the entry to the hash bucket */
1075 ether_copy(mcaddr, &entry->mc_addr);
1076 hash = GMAC_MCADDR_HASH(mcaddr);
1077 entry->next = ch->mf.bucket[hash];
1078 ch->mf.bucket[hash] = entry;
1080 return (SUCCESS);
1084 * Cleanup the multicast filter hash table.
1086 static void
1087 gmac_mf_cleanup(ch_t *ch)
1089 mflist_t *ptr;
1090 int32 i;
1092 for (i = 0; i < GMAC_HASHT_SIZE; i++) {
1093 for (ptr = ch->mf.bucket[i]; ptr != NULL; ptr = ptr->next)
1094 MFREE(ch->osh, ptr, sizeof(mflist_t));
1095 ch->mf.bucket[i] = NULL;
1100 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
1101 * but leave the devcontrol tx and rx (fifos) disabled.
1103 static void
1104 chipinit(ch_t *ch, uint options)
1106 etc_info_t *etc;
1107 gmacregs_t *regs;
1108 uint idx;
1109 uint i;
1111 regs = ch->regs;
1112 etc = ch->etc;
1113 idx = 0;
1115 ET_TRACE(("et%d: chipinit\n", etc->unit));
1117 /* enable one rx interrupt per received frame */
1118 W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));
1120 /* enable 802.3x tx flow control (honor received PAUSE frames) */
1121 gmac_txflowcontrol(ch, TRUE);
1123 /* enable/disable promiscuous mode */
1124 gmac_promisc(ch, etc->promisc);
1126 if (!etc->promisc) {
1127 /* set our local address */
1128 W_REG(ch->osh, &regs->macaddrhigh,
1129 hton32(*(uint32 *)&etc->cur_etheraddr.octet[0]));
1130 W_REG(ch->osh, &regs->macaddrlow,
1131 hton16(*(uint16 *)&etc->cur_etheraddr.octet[4]));
1133 /* gmac doesn't have a cam, hence do the multicast address filtering
1134 * in the software
1136 /* allmulti or a list of discrete multicast addresses */
1137 if (!etc->allmulti && etc->nmulticast)
1138 for (i = 0; i < etc->nmulticast; i++)
1139 (void)gmac_mf_add(ch, &etc->multicast[i]);
1142 /* optionally enable mac-level loopback */
1143 if (etc->loopbk)
1144 gmac_loopback(ch, LOOPBACK_MODE_MAC);
1145 else
1146 gmac_loopback(ch, LOOPBACK_MODE_NONE);
1148 /* set max frame lengths - account for possible vlan tag */
1149 W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
1152 * Optionally, disable phy autonegotiation and force our speed/duplex
1153 * or constrain our advertised capabilities.
1155 if (etc->forcespeed != ET_AUTO) {
1156 gmac_speed(ch, etc->forcespeed);
1157 chipphyforce(ch, etc->phyaddr);
1158 } else if (etc->advertise && etc->needautoneg)
1159 chipphyadvertise(ch, etc->phyaddr);
1161 /* enable the overflow continue feature and disable parity */
1162 dma_ctrlflags(ch->di[0], DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */,
1163 DMA_CTRL_ROC /* value */);
1165 if (options & ET_INIT_FULL) {
1166 /* initialize the tx and rx dma channels */
1167 for (i = 0; i < NUMTXQ; i++)
1168 dma_txinit(ch->di[i]);
1169 dma_rxinit(ch->di[RX_Q0]);
1171 /* post dma receive buffers */
1172 dma_rxfill(ch->di[RX_Q0]);
1174 /* lastly, enable interrupts */
1175 if (options & ET_INIT_INTRON)
1176 et_intrson(etc->et);
1178 else
1179 dma_rxenable(ch->di[RX_Q0]);
1181 /* turn on the emac */
1182 gmac_enable(ch);
1185 /* dma transmit */
1186 static bool BCMFASTPATH
1187 chiptx(ch_t *ch, void *p0)
1189 int error, len;
1190 uint32 q = TX_Q0;
1192 ET_TRACE(("et%d: chiptx\n", ch->etc->unit));
1193 ET_LOG("et%d: chiptx", ch->etc->unit, 0);
1195 #ifdef ETROBO
1196 if ((ch->etc->robo != NULL) &&
1197 (((robo_info_t *)ch->etc->robo)->devid == DEVID53115)) {
1198 void *p = p0;
1200 if ((p0 = etc_bcm53115_war(ch->etc, p)) == NULL) {
1201 PKTFREE(ch->osh, p, TRUE);
1202 return FALSE;
1205 #endif /* ETROBO */
1207 len = PKTLEN(ch->osh, p0);
1209 /* check tx max length */
1210 if (len > (ETHER_MAX_LEN + 32)) {
1211 ET_ERROR(("et%d: chiptx: max frame length exceeded\n",
1212 ch->etc->unit));
1213 PKTFREE(ch->osh, p0, TRUE);
1214 return FALSE;
1217 if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0))
1218 PKTSETLEN(ch->osh, p0, GMAC_MIN_FRAMESIZE);
1220 /* queue the packet based on its priority */
1221 if (ch->etc->qos)
1222 q = etc_up2tc(PKTPRIO(p0));
1224 ASSERT(q < NUMTXQ);
1226 /* if tx completion intr is disabled then do the reclaim
1227 * once every few frames transmitted.
1229 if ((ch->etc->txframes[q] & ch->etc->txrec_thresh) == 1)
1230 dma_txreclaim(ch->di[q], HNDDMA_RANGE_TRANSMITTED);
1232 error = dma_txfast(ch->di[q], p0, TRUE);
1234 if (error) {
1235 ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit));
1236 ch->etc->txnobuf++;
1237 return FALSE;
1240 ch->etc->txframes[q]++;
1242 /* set back the orig length */
1243 PKTSETLEN(ch->osh, p0, len);
1245 return TRUE;
1248 /* reclaim completed transmit descriptors and packets */
1249 static void BCMFASTPATH
1250 chiptxreclaim(ch_t *ch, bool forceall)
1252 int32 i;
1254 ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit));
1256 for (i = 0; i < NUMTXQ; i++) {
1257 dma_txreclaim(ch->di[i], forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED);
1258 ch->intstatus &= ~(I_XI0 << i);
1262 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
1263 static void * BCMFASTPATH
1264 chiprx(ch_t *ch)
1266 void *p;
1267 struct ether_addr *da;
1269 ET_TRACE(("et%d: chiprx\n", ch->etc->unit));
1270 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
1272 /* gmac doesn't have a cam to do address filtering. so we implement
1273 * the multicast address filtering here.
1275 while ((p = dma_rx(ch->di[RX_Q0])) != NULL) {
1276 /* check for overflow error packet */
1277 if (RXH_FLAGS(ch->etc, PKTDATA(ch->osh, p)) & GRXF_OVF) {
1278 PKTFREE(ch->osh, p, FALSE);
1279 ch->etc->rxoflodiscards++;
1280 continue;
1283 /* skip the rx header */
1284 PKTPULL(ch->osh, p, HWRXOFF);
1286 /* do filtering only for multicast packets when allmulti is false */
1287 da = (struct ether_addr *)PKTDATA(ch->osh, p);
1288 if (!ETHER_ISMULTI(da) || ch->etc->allmulti ||
1289 (gmac_mf_lkup(ch, da) == SUCCESS) || ETHER_ISBCAST(da)) {
1290 PKTPUSH(ch->osh, p, HWRXOFF);
1291 return (p);
1294 PKTFREE(ch->osh, p, FALSE);
1297 ch->intstatus &= ~I_RI;
1299 /* post more rx buffers since we consumed a few */
1300 dma_rxfill(ch->di[RX_Q0]);
1302 return (NULL);
1305 /* reclaim completed dma receive descriptors and packets */
1306 static void
1307 chiprxreclaim(ch_t *ch)
1309 ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit));
1310 dma_rxreclaim(ch->di[RX_Q0]);
1311 ch->intstatus &= ~I_RI;
1314 /* allocate and post dma receive buffers */
1315 static void BCMFASTPATH
1316 chiprxfill(ch_t *ch)
1318 ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit));
1319 ET_LOG("et%d: chiprx", ch->etc->unit, 0);
1320 dma_rxfill(ch->di[RX_Q0]);
1323 /* get current and pending interrupt events */
1324 static int BCMFASTPATH
1325 chipgetintrevents(ch_t *ch, bool in_isr)
1327 uint32 intstatus;
1328 int events;
1330 events = 0;
1332 /* read the interrupt status register */
1333 intstatus = R_REG(ch->osh, &ch->regs->intstatus);
1335 /* defer unsolicited interrupts */
1336 intstatus &= (in_isr ? ch->intmask : ch->def_intmask);
1338 if (intstatus != 0)
1339 events = INTR_NEW;
1341 /* or new bits into persistent intstatus */
1342 intstatus = (ch->intstatus |= intstatus);
1344 /* return if no events */
1345 if (intstatus == 0)
1346 return (0);
1348 /* convert chip-specific intstatus bits into generic intr event bits */
1349 if (intstatus & I_RI)
1350 events |= INTR_RX;
1351 if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3))
1352 events |= INTR_TX;
1353 #if defined(_CFE_)
1354 if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS)
1355 #else
1356 if (intstatus & I_ERRORS)
1357 #endif
1358 events |= INTR_ERROR;
1360 return (events);
1363 /* enable chip interrupts */
1364 static void BCMFASTPATH
1365 chipintrson(ch_t *ch)
1367 ch->intmask = ch->def_intmask;
1368 W_REG(ch->osh, &ch->regs->intmask, ch->intmask);
1371 /* disable chip interrupts */
1372 static void BCMFASTPATH
1373 chipintrsoff(ch_t *ch)
1375 /* disable further interrupts from gmac */
1376 W_REG(ch->osh, &ch->regs->intmask, 0);
1377 (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */
1378 ch->intmask = 0;
1380 /* clear the interrupt conditions */
1381 W_REG(ch->osh, &ch->regs->intstatus, ch->intstatus);
1384 /* return true of caller should re-initialize, otherwise false */
1385 static bool BCMFASTPATH
1386 chiperrors(ch_t *ch)
1388 uint32 intstatus;
1389 etc_info_t *etc;
1391 etc = ch->etc;
1393 intstatus = ch->intstatus;
1394 ch->intstatus &= ~(I_ERRORS);
1396 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus));
1398 if (intstatus & I_PDEE) {
1399 ET_ERROR(("et%d: descriptor error\n", etc->unit));
1400 etc->dmade++;
1403 if (intstatus & I_PDE) {
1404 ET_ERROR(("et%d: data error\n", etc->unit));
1405 etc->dmada++;
1408 if (intstatus & I_DE) {
1409 ET_ERROR(("et%d: descriptor protocol error\n", etc->unit));
1410 etc->dmape++;
1413 if (intstatus & I_RDU) {
1414 ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit));
1415 etc->rxdmauflo++;
1418 if (intstatus & I_RFO) {
1419 ET_TRACE(("et%d: receive fifo overflow\n", etc->unit));
1420 etc->rxoflo++;
1423 if (intstatus & I_XFU) {
1424 ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit));
1425 etc->txuflo++;
1428 /* if overflows or decriptors underflow, don't report it
1429 * as an error and provoque a reset
1431 if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS)
1432 return (TRUE);
1434 return (FALSE);
1437 static void
1438 chipstatsupd(ch_t *ch)
1440 etc_info_t *etc;
1441 gmacregs_t *regs;
1442 volatile uint32 *s;
1443 uint32 *d;
1445 etc = ch->etc;
1446 regs = ch->regs;
1448 /* read the mib counters and update the driver maintained software
1449 * counters.
1451 if (etc->corerev != GMAC_4706B0_CORE_REV) {
1452 OR_REG(ch->osh, &regs->devcontrol, DC_MROR);
1453 for (s = &regs->mib.tx_good_octets, d = &ch->mib.tx_good_octets;
1454 s <= &regs->mib.rx_uni_pkts; s++, d++) {
1455 *d += R_REG(ch->osh, s);
1456 if (s == &ch->regs->mib.tx_q3_octets_high) {
1457 s++;
1458 d++;
1465 * Aggregate transmit and receive errors that probably resulted
1466 * in the loss of a frame are computed on the fly.
1468 * We seem to get lots of tx_carrier_lost errors when flipping
1469 * speed modes so don't count these as tx errors.
1471 * Arbitrarily lump the non-specific dma errors as tx errors.
1473 etc->txerror = ch->mib.tx_jabber_pkts + ch->mib.tx_oversize_pkts
1474 + ch->mib.tx_underruns + ch->mib.tx_excessive_cols
1475 + ch->mib.tx_late_cols + etc->txnobuf + etc->dmade
1476 + etc->dmada + etc->dmape + etc->txuflo;
1477 etc->rxerror = ch->mib.rx_jabber_pkts + ch->mib.rx_oversize_pkts
1478 + ch->mib.rx_missed_pkts + ch->mib.rx_crc_align_errs
1479 + ch->mib.rx_undersize + ch->mib.rx_crc_errs
1480 + ch->mib.rx_align_errs + ch->mib.rx_symbol_errs
1481 + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen;
1482 etc->rxgiants = (ch->di[RX_Q0])->rxgiants;
1485 static void
1486 chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear)
1488 gmacmib_t *m;
1490 m = &ch->mib;
1492 if (clear) {
1493 bzero((char *)m, sizeof(gmacmib_t));
1494 return;
1497 bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d "
1498 "tx_oversize_pkts %d\n",
1499 m->tx_broadcast_pkts, m->tx_multicast_pkts,
1500 m->tx_jabber_pkts,
1501 m->tx_oversize_pkts);
1502 bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n",
1503 m->tx_fragment_pkts, m->tx_underruns);
1504 bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d "
1505 "tx_excessive_cols %d\n",
1506 m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols,
1507 m->tx_excessive_cols);
1508 bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n",
1509 m->tx_late_cols, m->tx_defered, m->tx_carrier_lost,
1510 m->tx_pause_pkts);
1512 /* receive stat counters */
1513 /* hardware mib pkt and octet counters wrap too quickly to be useful */
1514 bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d "
1515 "rx_oversize_pkts %d\n",
1516 m->rx_broadcast_pkts, m->rx_multicast_pkts,
1517 m->rx_jabber_pkts, m->rx_oversize_pkts);
1518 bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d "
1519 "rx_undersize %d\n",
1520 m->rx_fragment_pkts, m->rx_missed_pkts,
1521 m->rx_crc_align_errs, m->rx_undersize);
1522 bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n",
1523 m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs);
1524 bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n",
1525 m->rx_pause_pkts, m->rx_nonpause_pkts);
1528 static void
1529 chipenablepme(ch_t *ch)
1531 return;
1534 static void
1535 chipdisablepme(ch_t *ch)
1537 return;
1540 static void
1541 chipduplexupd(ch_t *ch)
1543 uint32 cmdcfg;
1544 int32 duplex, speed;
1546 cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg);
1548 /* check if duplex mode changed */
1549 if (ch->etc->duplex && (cmdcfg & CC_HD))
1550 duplex = 0;
1551 else if (!ch->etc->duplex && ((cmdcfg & CC_HD) == 0))
1552 duplex = CC_HD;
1553 else
1554 duplex = -1;
1556 /* check if the speed changed */
1557 speed = ((cmdcfg & CC_ES_MASK) >> CC_ES_SHIFT);
1558 if ((ch->etc->speed == 1000) && (speed != 2))
1559 speed = 2;
1560 else if ((ch->etc->speed == 100) && (speed != 1))
1561 speed = 1;
1562 else if ((ch->etc->speed == 10) && (speed != 0))
1563 speed = 0;
1564 else
1565 speed = -1;
1567 /* no duplex or speed change required */
1568 if ((speed == -1) && (duplex == -1))
1569 return;
1571 /* update the speed */
1572 if (speed != -1) {
1573 cmdcfg &= ~CC_ES_MASK;
1574 cmdcfg |= (speed << CC_ES_SHIFT);
1577 /* update the duplex mode */
1578 if (duplex != -1) {
1579 cmdcfg &= ~CC_HD;
1580 cmdcfg |= duplex;
1583 ET_TRACE(("chipduplexupd: updating speed & duplex %x\n", cmdcfg));
1585 /* put mac in reset */
1586 gmac_init_reset(ch);
1588 W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg);
1590 /* bring mac out of reset */
1591 gmac_clear_reset(ch);
1594 static uint16
1595 chipphyrd(ch_t *ch, uint phyaddr, uint reg)
1597 uint32 tmp;
1598 gmacregs_t *regs;
1599 uint32 *phycontrol_addr, *phyaccess_addr;
1601 ASSERT(phyaddr < MAXEPHY);
1602 ASSERT(reg < MAXPHYREG);
1604 regs = ch->regs;
1606 if (ch->etc->corerev == GMAC_4706B0_CORE_REV) {
1607 phycontrol_addr = (uint32 *)&ch->regscomm->phycontrol;
1608 phyaccess_addr = (uint32 *)&ch->regscomm->phyaccess;
1609 } else {
1610 phycontrol_addr = (uint32 *)&regs->phycontrol;
1611 phyaccess_addr = (uint32 *)&regs->phyaccess;
1614 /* issue the read */
1615 tmp = R_REG(ch->osh, phycontrol_addr);
1616 tmp &= ~0x1f;
1617 tmp |= phyaddr;
1618 W_REG(ch->osh, phycontrol_addr, tmp);
1619 W_REG(ch->osh, phyaccess_addr,
1620 (PA_START | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT)));
1622 /* wait for it to complete */
1623 SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000);
1624 tmp = R_REG(ch->osh, phyaccess_addr);
1625 if (tmp & PA_START) {
1626 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
1627 tmp = 0xffff;
1630 return (tmp & PA_DATA_MASK);
1633 static void
1634 chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v)
1636 uint32 tmp;
1637 gmacregs_t *regs;
1638 uint32 *phycontrol_addr, *phyaccess_addr;
1640 ASSERT(phyaddr < MAXEPHY);
1641 ASSERT(reg < MAXPHYREG);
1643 regs = ch->regs;
1645 if (ch->etc->corerev == GMAC_4706B0_CORE_REV) {
1646 phycontrol_addr = (uint32 *)&ch->regscomm->phycontrol;
1647 phyaccess_addr = (uint32 *)&ch->regscomm->phyaccess;
1648 } else {
1649 phycontrol_addr = (uint32 *)&regs->phycontrol;
1650 phyaccess_addr = (uint32 *)&regs->phyaccess;
1653 /* clear mdioint bit of intstatus first */
1654 tmp = R_REG(ch->osh, phycontrol_addr);
1655 tmp &= ~0x1f;
1656 tmp |= phyaddr;
1657 W_REG(ch->osh, phycontrol_addr, tmp);
1658 W_REG(ch->osh, &regs->intstatus, I_MDIO);
1659 ASSERT((R_REG(ch->osh, &regs->intstatus) & I_MDIO) == 0);
1661 /* issue the write */
1662 W_REG(ch->osh, phyaccess_addr,
1663 (PA_START | PA_WRITE | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT) | v));
1665 /* wait for it to complete */
1666 SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000);
1667 if (R_REG(ch->osh, phyaccess_addr) & PA_START) {
1668 ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
1672 static void
1673 chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v)
1675 uint16 tmp;
1677 tmp = chipphyrd(ch, phyaddr, reg);
1678 tmp |= v;
1679 chipphywr(ch, phyaddr, reg, tmp);
1682 static void
1683 chipphyreset(ch_t *ch, uint phyaddr)
1685 ASSERT(phyaddr < MAXEPHY);
1687 if (phyaddr == EPHY_NOREG)
1688 return;
1690 ET_TRACE(("et%d: chipphyreset: phyaddr %d\n", ch->etc->unit, phyaddr));
1692 chipphywr(ch, phyaddr, 0, CTL_RESET);
1693 OSL_DELAY(100);
1694 if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) {
1695 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit));
1698 chipphyinit(ch, phyaddr);
1701 static void
1702 chipphyinit(ch_t *ch, uint phyaddr)
1704 if (CHIPID(ch->sih->chip) == BCM5356_CHIP_ID) {
1705 int i;
1707 for (i = 0; i < 5; i++) {
1708 chipphywr(ch, i, 0x1f, 0x008b);
1709 chipphywr(ch, i, 0x15, 0x0100);
1710 chipphywr(ch, i, 0x1f, 0x000f);
1711 chipphywr(ch, i, 0x12, 0x2aaa);
1712 chipphywr(ch, i, 0x1f, 0x000b);
1716 if ((((CHIPID(ch->sih->chip) == BCM5357_CHIP_ID) ||
1717 (CHIPID(ch->sih->chip) == BCM4749_CHIP_ID)) &&
1718 (ch->sih->chippkg != BCM47186_PKG_ID)) ||
1719 ((CHIPID(ch->sih->chip) == BCM53572_CHIP_ID) &&
1720 (ch->sih->chippkg != BCM47188_PKG_ID))) {
1721 int i;
1723 for (i = 0; i < 5; i++) {
1724 chipphywr(ch, i, 0x1f, 0x000f);
1725 chipphywr(ch, i, 0x16, 0x5284);
1726 chipphywr(ch, i, 0x1f, 0x000b);
1727 chipphywr(ch, i, 0x17, 0x0010);
1728 chipphywr(ch, i, 0x1f, 0x000f);
1729 chipphywr(ch, i, 0x16, 0x5296);
1730 chipphywr(ch, i, 0x17, 0x1073);
1731 chipphywr(ch, i, 0x17, 0x9073);
1732 chipphywr(ch, i, 0x16, 0x52b6);
1733 chipphywr(ch, i, 0x17, 0x9273);
1734 chipphywr(ch, i, 0x1f, 0x000b);
1738 if (phyaddr == EPHY_NOREG)
1739 return;
1741 ET_TRACE(("et%d: chipphyinit: phyaddr %d\n", ch->etc->unit, phyaddr));
1744 static void
1745 chipphyforce(ch_t *ch, uint phyaddr)
1747 etc_info_t *etc;
1748 uint16 ctl;
1750 ASSERT(phyaddr < MAXEPHY);
1752 if (phyaddr == EPHY_NOREG)
1753 return;
1755 etc = ch->etc;
1757 if (etc->forcespeed == ET_AUTO)
1758 return;
1760 ET_TRACE(("et%d: chipphyforce: phyaddr %d speed %d\n",
1761 ch->etc->unit, phyaddr, etc->forcespeed));
1763 ctl = chipphyrd(ch, phyaddr, 0);
1764 ctl &= ~(CTL_SPEED | CTL_SPEED_MSB | CTL_ANENAB | CTL_DUPLEX);
1766 switch (etc->forcespeed) {
1767 case ET_10HALF:
1768 break;
1770 case ET_10FULL:
1771 ctl |= CTL_DUPLEX;
1772 break;
1774 case ET_100HALF:
1775 ctl |= CTL_SPEED_100;
1776 break;
1778 case ET_100FULL:
1779 ctl |= (CTL_SPEED_100 | CTL_DUPLEX);
1780 break;
1782 case ET_1000FULL:
1783 ctl |= (CTL_SPEED_1000 | CTL_DUPLEX);
1784 break;
1787 chipphywr(ch, phyaddr, 0, ctl);
1790 /* set selected capability bits in autonegotiation advertisement */
1791 static void
1792 chipphyadvertise(ch_t *ch, uint phyaddr)
1794 etc_info_t *etc;
1795 uint16 adv, adv2;
1797 ASSERT(phyaddr < MAXEPHY);
1799 if (phyaddr == EPHY_NOREG)
1800 return;
1802 etc = ch->etc;
1804 if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
1805 return;
1807 ASSERT(etc->advertise);
1809 ET_TRACE(("et%d: chipphyadvertise: phyaddr %d advertise %x\n",
1810 ch->etc->unit, phyaddr, etc->advertise));
1812 /* reset our advertised capabilitity bits */
1813 adv = chipphyrd(ch, phyaddr, 4);
1814 adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF);
1815 adv |= etc->advertise;
1816 chipphywr(ch, phyaddr, 4, adv);
1818 adv2 = chipphyrd(ch, phyaddr, 9);
1819 adv2 &= ~(ADV_1000FULL | ADV_1000HALF);
1820 adv2 |= etc->advertise2;
1821 chipphywr(ch, phyaddr, 9, adv2);
1823 ET_TRACE(("et%d: chipphyadvertise: phyaddr %d adv %x adv2 %x phyad0 %x\n",
1824 ch->etc->unit, phyaddr, adv, adv2, chipphyrd(ch, phyaddr, 0)));
1826 /* restart autonegotiation */
1827 chipphyor(ch, phyaddr, 0, CTL_RESTART);
1829 etc->needautoneg = FALSE;