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 (C) 2010, Broadcom Corporation
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.172.58.1 2010-07-01 23:25:46 Exp $
20 #include <bcmendian.h>
23 #include <proto/ethernet.h>
29 #include <bcmenet47xx.h>
30 #include <et_export.h> /* for et_phyxx() routines */
39 struct bcm4xxx
; /* forward declaration */
40 #define ch_t struct bcm4xxx
43 /* private chip state */
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 bcmenetmib_t mib
; /* mib counters */
60 si_t
*sih
; /* si utils handle */
62 char *vars
; /* sprom name=value */
65 void *adm
; /* optional admtek private data */
68 /* local prototypes */
69 static bool chipid(uint vendor
, uint device
);
70 static void *chipattach(etc_info_t
*etc
, void *osh
, void *regsva
);
71 static void chipdetach(ch_t
*ch
);
72 static void chipreset(ch_t
*ch
);
73 static void chipinit(ch_t
*ch
, uint options
);
74 static bool chiptx(ch_t
*ch
, void *p
);
75 static void *chiprx(ch_t
*ch
);
76 static void chiprxfill(ch_t
*ch
);
77 static int chipgetintrevents(ch_t
*ch
, bool in_isr
);
78 static bool chiperrors(ch_t
*ch
);
79 static void chipintrson(ch_t
*ch
);
80 static void chipintrsoff(ch_t
*ch
);
81 static void chiptxreclaim(ch_t
*ch
, bool all
);
82 static void chiprxreclaim(ch_t
*ch
);
83 static void chipstatsupd(ch_t
*ch
);
84 static void chipdumpmib(ch_t
*ch
, struct bcmstrbuf
*b
, bool clear
);
85 static void chipenablepme(ch_t
*ch
);
86 static void chipdisablepme(ch_t
*ch
);
87 static void chipphyreset(ch_t
*ch
, uint phyaddr
);
88 static void chipphyinit(ch_t
*ch
, uint phyaddr
);
89 static uint16
chipphyrd(ch_t
*ch
, uint phyaddr
, uint reg
);
90 static void chipdump(ch_t
*ch
, struct bcmstrbuf
*b
);
91 static void chiplongname(ch_t
*ch
, char *buf
, uint bufsize
);
92 static void chipduplexupd(ch_t
*ch
);
93 static void chipwrcam(struct bcm4xxx
*ch
, struct ether_addr
*ea
, uint camindex
);
94 static void chipphywr(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
95 static void chipphyor(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
96 static void chipphyand(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
97 static void chipphyforce(struct bcm4xxx
*ch
, uint phyaddr
);
98 static void chipphyadvertise(struct bcm4xxx
*ch
, uint phyaddr
);
100 static void chipdumpregs(struct bcm4xxx
*ch
, bcmenetregs_t
*regs
, struct bcmstrbuf
*b
);
103 /* chip interrupt bit error summary */
104 #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
105 #define DEF_INTMASK (I_XI | I_RI | I_ERRORS)
107 struct chops bcm47xx_et_chops
= {
134 static uint devices
[] = {
139 chipid(uint vendor
, uint device
)
143 if (vendor
!= VENDOR_BROADCOM
)
146 for (i
= 0; devices
[i
]; i
++) {
147 if (device
== devices
[i
])
154 chipattach(etc_info_t
*etc
, void *osh
, void *regsva
)
160 uint boardflags
, boardtype
;
162 ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc
->unit
, (ulong
)regsva
));
164 if ((ch
= (struct bcm4xxx
*)MALLOC(osh
, sizeof(struct bcm4xxx
))) == NULL
) {
165 ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc
->unit
,
169 bzero((char *)ch
, sizeof(struct bcm4xxx
));
175 /* store the pointer to the sw mib */
176 etc
->mib
= (void *)&ch
->mib
;
179 if ((ch
->sih
= si_attach(etc
->deviceid
, ch
->osh
, regsva
, PCI_BUS
, NULL
, &ch
->vars
,
180 &ch
->vars_size
)) == NULL
) {
181 ET_ERROR(("et%d: chipattach: si_attach error\n", etc
->unit
));
185 /* We used to have an assert here like:
186 * si_coreid(ch->sih) == ENET_CORE_ID
187 * but srom-less systems and simulators don't have a way to
188 * provide a default bar0window so we were relying on nvram
189 * variables. At some point we decided that we could do away
190 * with that since the wireless driver was simply doing a
191 * setcore in attach. So we need to do the same here for
194 if ((regs
= (bcmenetregs_t
*)si_setcore(ch
->sih
, ENET_CORE_ID
, etc
->unit
)) == NULL
) {
195 ET_ERROR(("et%d: chipattach: Could not setcore to the ENET core\n", etc
->unit
));
200 etc
->chip
= ch
->sih
->chip
;
201 etc
->chiprev
= ch
->sih
->chiprev
;
202 etc
->coreid
= si_coreid(ch
->sih
);
203 etc
->corerev
= si_corerev(ch
->sih
);
204 etc
->nicmode
= !(ch
->sih
->bustype
== SI_BUS
);
205 etc
->coreunit
= si_coreunit(ch
->sih
);
206 etc
->boardflags
= getintvar(ch
->vars
, "boardflags");
208 boardflags
= etc
->boardflags
;
209 boardtype
= ch
->sih
->boardtype
;
211 /* get our local ether addr */
212 sprintf(name
, "et%dmacaddr", etc
->coreunit
);
213 var
= getvar(ch
->vars
, name
);
215 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
218 bcm_ether_atoe(var
, &etc
->perm_etheraddr
);
220 if (ETHER_ISNULLADDR(&etc
->perm_etheraddr
)) {
221 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc
->unit
, name
, var
));
224 bcopy((char *)&etc
->perm_etheraddr
, (char *)&etc
->cur_etheraddr
, ETHER_ADDR_LEN
);
227 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
228 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
231 /* get our phyaddr value */
232 sprintf(name
, "et%dphyaddr", etc
->coreunit
);
233 var
= getvar(ch
->vars
, name
);
235 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
238 etc
->phyaddr
= bcm_atoi(var
) & EPHY_MASK
;
240 /* nvram says no phy is present */
241 if (etc
->phyaddr
== EPHY_NONE
) {
242 ET_ERROR(("et%d: chipattach: phy not present\n", etc
->unit
));
246 /* get our mdc/mdio port number */
247 sprintf(name
, "et%dmdcport", etc
->coreunit
);
248 var
= getvar(ch
->vars
, name
);
250 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
253 etc
->mdcport
= bcm_atoi(var
);
255 /* configure pci core */
256 si_pci_setup(ch
->sih
, (1 << si_coreidx(ch
->sih
)));
258 /* reset the enet core */
262 sprintf(name
, "et%d", etc
->coreunit
);
263 if ((ch
->di
= dma_attach(osh
, name
, ch
->sih
,
264 (void *)®s
->dmaregs
.xmt
, (void *)®s
->dmaregs
.rcv
,
265 NTXD
, NRXD
, RXBUFSZ
, -1, NRXBUFPOST
, HWRXOFF
,
266 &et_msg_level
)) == NULL
) {
267 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc
->unit
));
270 etc
->txavail
[TX_Q0
] = (uint
*)&ch
->di
->txavail
;
272 /* set default sofware intmask */
273 ch
->intmask
= DEF_INTMASK
;
276 * For the 5222 dual phy shared mdio contortion, our phy is
277 * on someone elses mdio pins. This other enet enet
278 * may not yet be attached so we must defer the et_phyfind().
280 /* if local phy: reset it once now */
281 if (etc
->mdcport
== etc
->coreunit
)
282 chipphyreset(ch
, etc
->phyaddr
);
286 * Broadcom Robo ethernet switch.
288 if ((boardflags
& BFL_ENETROBO
) &&
289 (etc
->phyaddr
== EPHY_NOREG
)) {
290 /* Attach to the switch */
291 if (!(etc
->robo
= bcm_robo_attach(ch
->sih
, ch
, ch
->vars
,
292 (miird_f
)bcm47xx_et_chops
.phyrd
,
293 (miiwr_f
)bcm47xx_et_chops
.phywr
))) {
294 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc
->unit
));
297 /* Enable the switch and set it to a known good state */
298 if (bcm_robo_enable_device(etc
->robo
)) {
299 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc
->unit
));
302 /* Configure the switch to do VLAN */
303 if ((boardflags
& BFL_ENETVLAN
) &&
304 bcm_robo_config_vlan(etc
->robo
, etc
->perm_etheraddr
.octet
)) {
305 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc
->unit
));
308 /* Enable switching/forwarding */
309 if (bcm_robo_enable_switch(etc
->robo
)) {
310 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc
->unit
));
318 * ADMtek ethernet switch.
320 if (boardflags
& BFL_ENETADM
) {
321 /* Attach to the device */
322 if (!(ch
->adm
= adm_attach(ch
->sih
, ch
->vars
))) {
323 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc
->unit
));
326 /* Enable the external switch and set it to a known good state */
327 if (adm_enable_device(ch
->adm
)) {
328 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc
->unit
));
331 /* Configure the switch */
332 if ((boardflags
& BFL_ENETVLAN
) && adm_config_vlan(ch
->adm
)) {
333 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc
->unit
));
347 chipdetach(struct bcm4xxx
*ch
)
349 ET_TRACE(("et%d: chipdetach\n", ch
->etc
->unit
));
355 /* free robo state */
357 bcm_robo_detach(ch
->etc
->robo
);
361 /* free ADMtek state */
371 /* put the core back into reset */
373 si_core_disable(ch
->sih
, 0);
381 MFREE(ch
->osh
, ch
->vars
, ch
->vars_size
);
383 /* free chip private state */
384 MFREE(ch
->osh
, ch
, sizeof(struct bcm4xxx
));
388 chiplongname(struct bcm4xxx
*ch
, char *buf
, uint bufsize
)
392 switch (ch
->etc
->deviceid
) {
393 case BCM47XX_ENET_ID
:
395 s
= "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
399 strncpy(buf
, s
, bufsize
);
400 buf
[bufsize
- 1] = '\0';
404 chipdump(struct bcm4xxx
*ch
, struct bcmstrbuf
*b
)
407 bcm_bprintf(b
, "regs 0x%x etphy 0x%x ch->intstatus 0x%x intmask 0x%x\n",
408 (ulong
)ch
->regs
, (ulong
)ch
->etphy
, ch
->intstatus
, ch
->intmask
);
409 bcm_bprintf(b
, "\n");
411 /* dma engine state */
412 dma_dump(ch
->di
, b
, FALSE
);
413 bcm_bprintf(b
, "\n");
416 chipdumpregs(ch
, ch
->regs
, b
);
417 bcm_bprintf(b
, "\n");
419 /* switch registers */
422 robo_dump_regs(ch
->etc
->robo
, b
);
426 adm_dump_regs(ch
->adm
, b
->buf
);
433 #define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->name))
434 #define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->mib.name))
437 chipdumpregs(struct bcm4xxx
*ch
, bcmenetregs_t
*regs
, struct bcmstrbuf
*b
)
441 phyaddr
= ch
->etc
->phyaddr
;
443 PRREG(devcontrol
); PRREG(biststatus
); PRREG(wakeuplength
);
444 bcm_bprintf(b
, "\n");
445 PRREG(intstatus
); PRREG(intmask
); PRREG(gptimer
);
446 bcm_bprintf(b
, "\n");
447 PRREG(emactxmaxburstlen
); PRREG(emacrxmaxburstlen
);
448 PRREG(emaccontrol
); PRREG(emacflowcontrol
);
449 bcm_bprintf(b
, "\n");
451 bcm_bprintf(b
, "\n");
454 PRREG(rxconfig
); PRREG(rxmaxlength
); PRREG(txmaxlength
);
455 bcm_bprintf(b
, "\n");
456 PRREG(mdiocontrol
); PRREG(camcontrol
); PRREG(enetcontrol
);
457 bcm_bprintf(b
, "\n");
458 PRREG(txcontrol
); PRREG(txwatermark
); PRREG(mibcontrol
);
459 bcm_bprintf(b
, "\n");
462 PRMIBREG(tx_good_octets
); PRMIBREG(tx_good_pkts
); PRMIBREG(tx_octets
); PRMIBREG(tx_pkts
);
463 bcm_bprintf(b
, "\n");
464 PRMIBREG(tx_broadcast_pkts
); PRMIBREG(tx_multicast_pkts
);
465 bcm_bprintf(b
, "\n");
466 PRMIBREG(tx_jabber_pkts
); PRMIBREG(tx_oversize_pkts
); PRMIBREG(tx_fragment_pkts
);
467 bcm_bprintf(b
, "\n");
468 PRMIBREG(tx_underruns
); PRMIBREG(tx_total_cols
); PRMIBREG(tx_single_cols
);
469 bcm_bprintf(b
, "\n");
470 PRMIBREG(tx_multiple_cols
); PRMIBREG(tx_excessive_cols
); PRMIBREG(tx_late_cols
);
471 bcm_bprintf(b
, "\n");
472 PRMIBREG(tx_defered
); PRMIBREG(tx_carrier_lost
); PRMIBREG(tx_pause_pkts
);
473 bcm_bprintf(b
, "\n");
475 PRMIBREG(rx_good_octets
); PRMIBREG(rx_good_pkts
); PRMIBREG(rx_octets
); PRMIBREG(rx_pkts
);
476 bcm_bprintf(b
, "\n");
477 PRMIBREG(rx_broadcast_pkts
); PRMIBREG(rx_multicast_pkts
);
478 bcm_bprintf(b
, "\n");
479 PRMIBREG(rx_jabber_pkts
); PRMIBREG(rx_oversize_pkts
); PRMIBREG(rx_fragment_pkts
);
480 bcm_bprintf(b
, "\n");
481 PRMIBREG(rx_missed_pkts
); PRMIBREG(rx_crc_align_errs
); PRMIBREG(rx_undersize
);
482 bcm_bprintf(b
, "\n");
483 PRMIBREG(rx_crc_errs
); PRMIBREG(rx_align_errs
); PRMIBREG(rx_symbol_errs
);
484 bcm_bprintf(b
, "\n");
485 PRMIBREG(rx_pause_pkts
); PRMIBREG(rx_nonpause_pkts
);
486 bcm_bprintf(b
, "\n");
488 if (phyaddr
!= EPHY_NOREG
) {
489 /* print a few interesting phy registers */
490 bcm_bprintf(b
, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n",
491 chipphyrd(ch
, phyaddr
, 0),
492 chipphyrd(ch
, phyaddr
, 1),
493 chipphyrd(ch
, phyaddr
, 2),
494 chipphyrd(ch
, phyaddr
, 3));
495 bcm_bprintf(b
, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n",
496 chipphyrd(ch
, phyaddr
, 4),
497 chipphyrd(ch
, phyaddr
, 5),
498 chipphyrd(ch
, phyaddr
, 24),
499 chipphyrd(ch
, phyaddr
, 25));
505 #define MDC_RATIO 5000000
508 chipreset(struct bcm4xxx
*ch
)
513 ET_TRACE(("et%d: chipreset\n", ch
->etc
->unit
));
517 if (!si_iscoreup(ch
->sih
)) {
518 if (!ch
->etc
->nicmode
)
519 si_pci_setup(ch
->sih
, (1 << si_coreidx(ch
->sih
)));
520 /* power on reset: reset the enet core */
521 si_core_reset(ch
->sih
, 0, 0);
525 /* read counters before resetting the chip */
529 /* reset the tx dma engine */
533 /* set emac into loopback mode to ensure no rx traffic */
534 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
537 /* reset the rx dma engine */
542 si_core_reset(ch
->sih
, 0, 0);
546 /* must clear mib registers by hand */
547 W_REG(ch
->osh
, ®s
->mibcontrol
, EMC_RZ
);
548 (void) R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
549 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
550 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
551 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
552 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
553 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
554 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
555 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
556 (void) R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
557 (void) R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
558 (void) R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
559 (void) R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
560 (void) R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
561 (void) R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
562 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
563 (void) R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
564 (void) R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
565 (void) R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
566 (void) R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
567 (void) R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
568 (void) R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
569 (void) R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
570 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
571 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
572 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
573 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
574 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
575 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
576 (void) R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
577 (void) R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
578 (void) R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
579 (void) R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
580 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
581 (void) R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
582 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
583 (void) R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
584 (void) R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
585 (void) R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
586 (void) R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
590 * We want the phy registers to be accessible even when
591 * the driver is "downed" so initialize MDC preamble, frequency,
592 * and whether internal or external phy here.
594 /* default: 100Mhz SI clock and external phy */
595 W_REG(ch
->osh
, ®s
->mdiocontrol
, 0x94);
596 if (ch
->etc
->deviceid
== BCM47XX_ENET_ID
) {
597 /* 47xx chips: find out the clock */
598 if ((clk
= si_clock(ch
->sih
)) != 0) {
599 mdc
= 0x80 | ((clk
+ (MDC_RATIO
/ 2)) / MDC_RATIO
);
600 W_REG(ch
->osh
, ®s
->mdiocontrol
, mdc
);
602 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
608 /* some chips have internal phy, some don't */
609 if (!(R_REG(ch
->osh
, ®s
->devcontrol
) & DC_IP
)) {
610 W_REG(ch
->osh
, ®s
->enetcontrol
, EC_EP
);
611 } else if (R_REG(ch
->osh
, ®s
->devcontrol
) & DC_ER
) {
612 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_ER
);
614 chipphyinit(ch
, ch
->etc
->phyaddr
);
617 /* clear persistent sw intstatus */
622 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
623 * but leave the devcontrol tx and rx (fifos) disabled.
626 chipinit(struct bcm4xxx
*ch
, uint options
)
637 ET_TRACE(("et%d: chipinit\n", etc
->unit
));
639 /* enable crc32 generation */
640 OR_REG(ch
->osh
, ®s
->emaccontrol
, EMC_CG
);
642 /* enable one rx interrupt per received frame */
643 W_REG(ch
->osh
, ®s
->intrecvlazy
, (1 << IRL_FC_SHIFT
));
645 /* enable 802.3x tx flow control (honor received PAUSE frames) */
646 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_FE
| ERC_UF
);
649 if (etc
->promisc
|| (R_REG(ch
->osh
, ®s
->rxconfig
) & ERC_CA
))
650 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_PE
);
652 /* our local address */
653 chipwrcam(ch
, &etc
->cur_etheraddr
, idx
++);
655 /* allmulti or a list of discrete multicast addresses */
657 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_AM
);
658 else if (etc
->nmulticast
) {
659 for (i
= 0; i
< etc
->nmulticast
; i
++)
660 chipwrcam(ch
, &etc
->multicast
[i
], idx
++);
664 OR_REG(ch
->osh
, ®s
->camcontrol
, CC_CE
);
667 /* optionally enable mac-level loopback */
669 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
671 /* set max frame lengths - account for possible vlan tag */
672 W_REG(ch
->osh
, ®s
->rxmaxlength
, ETHER_MAX_LEN
+ 32);
673 W_REG(ch
->osh
, ®s
->txmaxlength
, ETHER_MAX_LEN
+ 32);
675 /* set tx watermark */
676 W_REG(ch
->osh
, ®s
->txwatermark
, 56);
679 * Optionally, disable phy autonegotiation and force our speed/duplex
680 * or constrain our advertised capabilities.
682 if (etc
->forcespeed
!= ET_AUTO
)
683 chipphyforce(ch
, etc
->phyaddr
);
684 else if (etc
->advertise
&& etc
->needautoneg
)
685 chipphyadvertise(ch
, etc
->phyaddr
);
687 if (options
& ET_INIT_FULL
) {
688 /* initialize the tx and rx dma channels */
692 /* post dma receive buffers */
695 /* lastly, enable interrupts */
696 if (options
& ET_INIT_INTRON
)
700 dma_rxenable(ch
->di
);
702 /* turn on the emac */
703 OR_REG(ch
->osh
, ®s
->enetcontrol
, EC_EE
);
707 static bool BCMFASTPATH
708 chiptx(struct bcm4xxx
*ch
, void *p0
)
712 ET_TRACE(("et%d: chiptx\n", ch
->etc
->unit
));
713 ET_LOG("et%d: chiptx", ch
->etc
->unit
, 0);
715 error
= dma_txfast(ch
->di
, p0
, TRUE
);
718 ET_ERROR(("et%d: chiptx: out of txds\n", ch
->etc
->unit
));
725 /* reclaim completed transmit descriptors and packets */
726 static void BCMFASTPATH
727 chiptxreclaim(struct bcm4xxx
*ch
, bool forceall
)
729 ET_TRACE(("et%d: chiptxreclaim\n", ch
->etc
->unit
));
730 dma_txreclaim(ch
->di
, forceall
? HNDDMA_RANGE_ALL
: HNDDMA_RANGE_TRANSMITTED
);
731 ch
->intstatus
&= ~I_XI
;
734 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
735 static void * BCMFASTPATH
736 chiprx(struct bcm4xxx
*ch
)
740 ET_TRACE(("et%d: chiprx\n", ch
->etc
->unit
));
741 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
743 if ((p
= dma_rx(ch
->di
)) == NULL
)
744 ch
->intstatus
&= ~I_RI
;
749 /* reclaim completed dma receive descriptors and packets */
751 chiprxreclaim(struct bcm4xxx
*ch
)
753 ET_TRACE(("et%d: chiprxreclaim\n", ch
->etc
->unit
));
754 dma_rxreclaim(ch
->di
);
755 ch
->intstatus
&= ~I_RI
;
758 /* allocate and post dma receive buffers */
759 static void BCMFASTPATH
760 chiprxfill(struct bcm4xxx
*ch
)
762 ET_TRACE(("et%d: chiprxfill\n", ch
->etc
->unit
));
763 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
767 /* get current and pending interrupt events */
768 static int BCMFASTPATH
769 chipgetintrevents(struct bcm4xxx
*ch
, bool in_isr
)
778 /* read the interrupt status register */
779 intstatus
= R_REG(ch
->osh
, ®s
->intstatus
);
781 /* defer unsolicited interrupts */
782 intstatus
&= (in_isr
? ch
->intmask
: DEF_INTMASK
);
784 /* clear non-error interrupt conditions */
785 if (intstatus
!= 0) {
786 W_REG(ch
->osh
, ®s
->intstatus
, intstatus
);
790 /* or new bits into persistent intstatus */
791 intstatus
= (ch
->intstatus
|= intstatus
);
793 /* return if no events */
797 /* convert chip-specific intstatus bits into generic intr event bits */
798 if (intstatus
& I_RI
)
800 if (intstatus
& I_XI
)
802 if (intstatus
& I_ERRORS
)
803 events
|= INTR_ERROR
;
804 if (intstatus
& I_TO
)
810 /* enable chip interrupts */
811 static void BCMFASTPATH
812 chipintrson(struct bcm4xxx
*ch
)
814 ch
->intmask
= DEF_INTMASK
;
815 W_REG(ch
->osh
, &ch
->regs
->intmask
, ch
->intmask
);
818 /* disable chip interrupts */
819 static void BCMFASTPATH
820 chipintrsoff(struct bcm4xxx
*ch
)
822 W_REG(ch
->osh
, &ch
->regs
->intmask
, 0);
823 (void) R_REG(ch
->osh
, &ch
->regs
->intmask
); /* sync readback */
827 /* return true of caller should re-initialize, otherwise false */
828 static bool BCMFASTPATH
829 chiperrors(struct bcm4xxx
*ch
)
836 intstatus
= ch
->intstatus
;
837 ch
->intstatus
&= ~(I_ERRORS
);
839 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc
->unit
, intstatus
));
841 if (intstatus
& I_PC
) {
842 ET_ERROR(("et%d: descriptor error\n", etc
->unit
));
846 if (intstatus
& I_PD
) {
847 ET_ERROR(("et%d: data error\n", etc
->unit
));
851 if (intstatus
& I_DE
) {
852 ET_ERROR(("et%d: descriptor protocol error\n", etc
->unit
));
855 /* NOTE : this ie NOT an error. It becomes an error only
856 * when the rx fifo overflows
858 if (intstatus
& I_RU
) {
859 ET_ERROR(("et%d: receive descriptor underflow\n", etc
->unit
));
863 if (intstatus
& I_RO
) {
864 ET_ERROR(("et%d: receive fifo overflow\n", etc
->unit
));
868 if (intstatus
& I_XU
) {
869 ET_ERROR(("et%d: transmit fifo underflow\n", etc
->unit
));
872 /* if overflows or decriptors underflow, don't report it
873 * as an error and provoque a reset
875 if (intstatus
& ~(I_RU
) & I_ERRORS
)
881 chipwrcam(struct bcm4xxx
*ch
, struct ether_addr
*ea
, uint camindex
)
885 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & (CC_CB
| CC_CE
)) == 0);
887 w
= (ea
->octet
[2] << 24) | (ea
->octet
[3] << 16) | (ea
->octet
[4] << 8)
889 W_REG(ch
->osh
, &ch
->regs
->camdatalo
, w
);
890 w
= CD_V
| (ea
->octet
[0] << 8) | ea
->octet
[1];
891 W_REG(ch
->osh
, &ch
->regs
->camdatahi
, w
);
892 W_REG(ch
->osh
, &ch
->regs
->camcontrol
, ((camindex
<< CC_INDEX_SHIFT
) | CC_WR
));
894 /* spin until done */
895 SPINWAIT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
), 1000);
898 * This assertion is usually caused by the phy not providing a clock
899 * to the bottom portion of the mac..
901 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
) == 0);
905 chipstatsupd(struct bcm4xxx
*ch
)
916 * mib counters are clear-on-read.
917 * Don't bother using the pkt and octet counters since they are only
918 * 16bits and wrap too quickly to be useful.
920 m
->tx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
921 m
->tx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
922 m
->tx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
923 m
->tx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
924 m
->tx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
925 m
->tx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
926 m
->tx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
927 m
->tx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
928 m
->tx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
929 m
->tx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
930 m
->tx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
931 m
->tx_underruns
+= R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
932 m
->tx_total_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
933 m
->tx_single_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
934 m
->tx_multiple_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
935 m
->tx_excessive_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
936 m
->tx_late_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
937 m
->tx_defered
+= R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
938 m
->tx_carrier_lost
+= R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
939 m
->tx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
940 m
->rx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
941 m
->rx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
942 m
->rx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
943 m
->rx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
944 m
->rx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
945 m
->rx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
946 m
->rx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
947 m
->rx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
948 m
->rx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
949 m
->rx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
950 m
->rx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
951 m
->rx_missed_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
952 m
->rx_crc_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
953 m
->rx_undersize
+= R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
954 m
->rx_crc_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
955 m
->rx_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
956 m
->rx_symbol_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
957 m
->rx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
958 m
->rx_nonpause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
961 * Aggregate transmit and receive errors that probably resulted
962 * in the loss of a frame are computed on the fly.
964 * We seem to get lots of tx_carrier_lost errors when flipping
965 * speed modes so don't count these as tx errors.
967 * Arbitrarily lump the non-specific dma errors as tx errors.
969 etc
->txerror
= m
->tx_jabber_pkts
+ m
->tx_oversize_pkts
970 + m
->tx_underruns
+ m
->tx_excessive_cols
971 + m
->tx_late_cols
+ etc
->txnobuf
+ etc
->dmade
972 + etc
->dmada
+ etc
->dmape
+ etc
->txuflo
;
973 etc
->rxerror
= m
->rx_jabber_pkts
+ m
->rx_oversize_pkts
974 + m
->rx_missed_pkts
+ m
->rx_crc_align_errs
975 + m
->rx_undersize
+ m
->rx_crc_errs
976 + m
->rx_align_errs
+ m
->rx_symbol_errs
977 + etc
->rxnobuf
+ etc
->rxdmauflo
+ etc
->rxoflo
+ etc
->rxbadlen
;
981 chipdumpmib(ch_t
*ch
, struct bcmstrbuf
*b
, bool clear
)
988 bzero((char *)m
, sizeof(bcmenetmib_t
));
992 bcm_bprintf(b
, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d "
993 "tx_oversize_pkts %d\n",
994 m
->tx_broadcast_pkts
, m
->tx_multicast_pkts
,
996 m
->tx_oversize_pkts
);
997 bcm_bprintf(b
, "tx_fragment_pkts %d tx_underruns %d\n",
998 m
->tx_fragment_pkts
, m
->tx_underruns
);
999 bcm_bprintf(b
, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d "
1000 "tx_excessive_cols %d\n",
1001 m
->tx_total_cols
, m
->tx_single_cols
, m
->tx_multiple_cols
,
1002 m
->tx_excessive_cols
);
1003 bcm_bprintf(b
, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n",
1004 m
->tx_late_cols
, m
->tx_defered
, m
->tx_carrier_lost
,
1007 /* receive stat counters */
1008 /* hardware mib pkt and octet counters wrap too quickly to be useful */
1009 bcm_bprintf(b
, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d "
1010 "rx_oversize_pkts %d\n",
1011 m
->rx_broadcast_pkts
, m
->rx_multicast_pkts
,
1012 m
->rx_jabber_pkts
, m
->rx_oversize_pkts
);
1013 bcm_bprintf(b
, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d "
1014 "rx_undersize %d\n",
1015 m
->rx_fragment_pkts
, m
->rx_missed_pkts
,
1016 m
->rx_crc_align_errs
, m
->rx_undersize
);
1017 bcm_bprintf(b
, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n",
1018 m
->rx_crc_errs
, m
->rx_align_errs
, m
->rx_symbol_errs
);
1019 bcm_bprintf(b
, "rx_pause_pkts %d rx_nonpause_pkts %d\n",
1020 m
->rx_pause_pkts
, m
->rx_nonpause_pkts
);
1024 chipenablepme(struct bcm4xxx
*ch
)
1026 bcmenetregs_t
*regs
;
1030 /* enable chip wakeup pattern matching */
1031 OR_REG(ch
->osh
, ®s
->devcontrol
, DC_PM
);
1033 /* enable sonics bus PME */
1034 si_core_cflags(ch
->sih
, SICF_PME_EN
, SICF_PME_EN
);
1038 chipdisablepme(struct bcm4xxx
*ch
)
1040 bcmenetregs_t
*regs
;
1044 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_PM
);
1045 si_core_cflags(ch
->sih
, SICF_PME_EN
, 0);
1049 chipduplexupd(struct bcm4xxx
*ch
)
1053 txcontrol
= R_REG(ch
->osh
, &ch
->regs
->txcontrol
);
1054 if (ch
->etc
->duplex
&& !(txcontrol
& EXC_FD
))
1055 OR_REG(ch
->osh
, &ch
->regs
->txcontrol
, EXC_FD
);
1056 else if (!ch
->etc
->duplex
&& (txcontrol
& EXC_FD
))
1057 AND_REG(ch
->osh
, &ch
->regs
->txcontrol
, ~EXC_FD
);
1061 chipphyrd(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
)
1063 bcmenetregs_t
*regs
;
1065 ASSERT(phyaddr
< MAXEPHY
);
1068 * BCM5222 dualphy shared mdio contortion.
1069 * remote phy: another emac controls our phy.
1071 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
1072 if (ch
->etphy
== NULL
) {
1073 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
1075 /* first time reset */
1077 chipphyreset(ch
, ch
->etc
->phyaddr
);
1080 return (et_phyrd(ch
->etphy
, phyaddr
, reg
));
1085 /* local phy: our emac controls our phy */
1090 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
1092 /* issue the read */
1093 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_READ
| (phyaddr
<< MD_PMD_SHIFT
)
1094 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
));
1096 /* wait for it to complete */
1097 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
1098 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
1099 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch
->etc
->unit
));
1102 return (R_REG(ch
->osh
, ®s
->mdiodata
) & MD_DATA_MASK
);
1106 chipphywr(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1108 bcmenetregs_t
*regs
;
1110 ASSERT(phyaddr
< MAXEPHY
);
1113 * BCM5222 dualphy shared mdio contortion.
1114 * remote phy: another emac controls our phy.
1116 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
1117 if (ch
->etphy
== NULL
)
1118 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
1120 et_phywr(ch
->etphy
, phyaddr
, reg
, v
);
1124 /* local phy: our emac controls our phy */
1129 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
1130 ASSERT((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0);
1132 /* issue the write */
1133 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_WRITE
| (phyaddr
<< MD_PMD_SHIFT
)
1134 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
| v
));
1136 /* wait for it to complete */
1137 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
1138 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
1139 ET_ERROR(("et%d: chipphywr: did not complete\n", ch
->etc
->unit
));
1144 chipphyor(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1148 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1150 chipphywr(ch
, phyaddr
, reg
, tmp
);
1154 chipphyand(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1158 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1160 chipphywr(ch
, phyaddr
, reg
, tmp
);
1164 chipphyreset(struct bcm4xxx
*ch
, uint phyaddr
)
1166 ASSERT(phyaddr
< MAXEPHY
);
1168 if (phyaddr
== EPHY_NOREG
)
1171 chipphywr(ch
, phyaddr
, 0, CTL_RESET
);
1173 if (chipphyrd(ch
, phyaddr
, 0) & CTL_RESET
) {
1174 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch
->etc
->unit
));
1177 chipphyinit(ch
, phyaddr
);
1181 chipphyinit(struct bcm4xxx
*ch
, uint phyaddr
)
1185 /* enable activity led */
1186 chipphyand(ch
, phyaddr
, 26, 0x7fff);
1188 /* enable traffic meter led mode */
1189 chipphyor(ch
, phyaddr
, 27, (1 << 6));
1191 phyid
= chipphyrd(ch
, phyaddr
, 0x2);
1192 phyid
|= chipphyrd(ch
, phyaddr
, 0x3) << 16;
1193 if (phyid
== 0x55210022) {
1194 chipphywr(ch
, phyaddr
, 30, (uint16
) (chipphyrd(ch
, phyaddr
, 30) | 0x3000));
1195 chipphywr(ch
, phyaddr
, 22, (uint16
) (chipphyrd(ch
, phyaddr
, 22) & 0xffdf));
1200 chipphyforce(struct bcm4xxx
*ch
, uint phyaddr
)
1205 ASSERT(phyaddr
< MAXEPHY
);
1207 if (phyaddr
== EPHY_NOREG
)
1212 if (etc
->forcespeed
== ET_AUTO
)
1215 ctl
= chipphyrd(ch
, phyaddr
, 0);
1216 ctl
&= ~(CTL_SPEED
| CTL_ANENAB
| CTL_DUPLEX
);
1218 switch (etc
->forcespeed
) {
1231 ctl
|= (CTL_SPEED
| CTL_DUPLEX
);
1235 chipphywr(ch
, phyaddr
, 0, ctl
);
1238 /* set selected capability bits in autonegotiation advertisement */
1240 chipphyadvertise(struct bcm4xxx
*ch
, uint phyaddr
)
1245 ASSERT(phyaddr
< MAXEPHY
);
1247 if (phyaddr
== EPHY_NOREG
)
1252 if ((etc
->forcespeed
!= ET_AUTO
) || !etc
->needautoneg
)
1255 ASSERT(etc
->advertise
);
1257 /* reset our advertised capabilitity bits */
1258 adv
= chipphyrd(ch
, phyaddr
, 4);
1259 adv
&= ~(ADV_100FULL
| ADV_100HALF
| ADV_10FULL
| ADV_10HALF
);
1260 adv
|= etc
->advertise
;
1261 chipphywr(ch
, phyaddr
, 4, adv
);
1263 /* restart autonegotiation */
1264 chipphyor(ch
, phyaddr
, 0, CTL_RESTART
);
1266 etc
->needautoneg
= FALSE
;