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) 2009, 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.164.2.5 2009/01/23 01:55:15 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
);
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 /* chip interrupt bit error summary */
101 #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU | I_TO)
102 #define DEF_INTMASK (I_XI | I_RI | I_ERRORS)
104 struct chops bcm47xx_et_chops
= {
131 static uint devices
[] = {
138 chipid(uint vendor
, uint device
)
142 if (vendor
!= VENDOR_BROADCOM
)
145 for (i
= 0; devices
[i
]; i
++) {
146 if (device
== devices
[i
])
153 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 /* set boardflags for 5365 and 5350 */
209 if (etc
->chip
== BCM5365_CHIP_ID
|| etc
->chip
== BCM5350_CHIP_ID
)
210 etc
->boardflags
|= BFL_ENETROBO
| BFL_ENETVLAN
;
212 boardflags
= etc
->boardflags
;
213 boardtype
= ch
->sih
->boardtype
;
215 /* configure pci core */
216 si_pci_setup(ch
->sih
, (1 << si_coreidx(ch
->sih
)));
218 /* reset the enet core */
222 sprintf(name
, "et%d", etc
->coreunit
);
223 if ((ch
->di
= dma_attach(osh
, name
, ch
->sih
,
224 (void *)®s
->dmaregs
.xmt
, (void *)®s
->dmaregs
.rcv
,
225 NTXD
, NRXD
, RXBUFSZ
, NRXBUFPOST
, HWRXOFF
,
226 &et_msg_level
)) == NULL
) {
227 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc
->unit
));
230 etc
->txavail
[TX_Q0
] = (uint
*)&ch
->di
->txavail
;
232 /* get our local ether addr */
233 sprintf(name
, "et%dmacaddr", etc
->coreunit
);
234 var
= getvar(ch
->vars
, name
);
236 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
239 bcm_ether_atoe(var
, &etc
->perm_etheraddr
);
241 if (ETHER_ISNULLADDR(&etc
->perm_etheraddr
)) {
242 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc
->unit
, name
, var
));
245 bcopy((char *)&etc
->perm_etheraddr
, (char *)&etc
->cur_etheraddr
, ETHER_ADDR_LEN
);
248 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
249 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
252 /* get our phyaddr value */
253 sprintf(name
, "et%dphyaddr", etc
->coreunit
);
254 var
= getvar(ch
->vars
, name
);
256 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
259 etc
->phyaddr
= bcm_atoi(var
) & EPHY_MASK
;
261 /* nvram says no phy is present */
262 if (etc
->phyaddr
== EPHY_NONE
) {
263 ET_ERROR(("et%d: chipattach: phy not present\n", etc
->unit
));
267 /* get our mdc/mdio port number */
268 sprintf(name
, "et%dmdcport", etc
->coreunit
);
269 var
= getvar(ch
->vars
, name
);
271 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
274 etc
->mdcport
= bcm_atoi(var
);
276 /* set default sofware intmask */
277 ch
->intmask
= DEF_INTMASK
;
280 * GPIO bits 2 and 6 on bcm94710r1 and bcm94710dev reset the
281 * external phys to a known good state. bcm94710r4 uses only
282 * GPIO 6 but GPIO 2 is not connected. Just reset both of them
283 * whenever this function is called.
285 if ((boardtype
== BCM94710D_BOARD
) ||
286 (boardtype
== BCM94710AP_BOARD
) ||
287 (boardtype
== BCM94710R1_BOARD
) ||
288 (boardtype
== BCM94710R4_BOARD
)) {
289 si_gpioout(ch
->sih
, 0x44, 0, GPIO_DRV_PRIORITY
);
290 si_gpioouten(ch
->sih
, 0x44, 0x44, GPIO_DRV_PRIORITY
);
291 /* Hold phys in reset for a nice long 2 ms */
292 for (i
= 0; i
< 2; i
++)
294 si_gpioout(ch
->sih
, 0x44, 0x44, GPIO_DRV_PRIORITY
);
295 si_gpioouten(ch
->sih
, 0x44, 0, GPIO_DRV_PRIORITY
);
299 * For the 5222 dual phy shared mdio contortion, our phy is
300 * on someone elses mdio pins. This other enet enet
301 * may not yet be attached so we must defer the et_phyfind().
303 /* if local phy: reset it once now */
304 if (etc
->mdcport
== etc
->coreunit
)
305 chipphyreset(ch
, etc
->phyaddr
);
309 * Broadcom Robo ethernet switch.
311 if (((boardflags
& BFL_ENETROBO
) ||
312 (boardtype
== BCM94710AP_BOARD
) ||
313 (boardtype
== BCM94702MN_BOARD
)) &&
314 (etc
->phyaddr
== EPHY_NOREG
)) {
315 /* Attach to the switch */
316 if (!(etc
->robo
= bcm_robo_attach(ch
->sih
, ch
, ch
->vars
,
317 (miird_f
)bcm47xx_et_chops
.phyrd
,
318 (miiwr_f
)bcm47xx_et_chops
.phywr
))) {
319 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc
->unit
));
322 /* Enable the switch and set it to a known good state */
323 if (bcm_robo_enable_device(etc
->robo
)) {
324 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc
->unit
));
327 /* Configure the switch to do VLAN */
328 if ((boardflags
& BFL_ENETVLAN
) &&
329 bcm_robo_config_vlan(etc
->robo
, etc
->perm_etheraddr
.octet
)) {
330 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc
->unit
));
333 /* Enable switching/forwarding */
334 if (bcm_robo_enable_switch(etc
->robo
)) {
335 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc
->unit
));
343 * ADMtek ethernet switch.
345 if (boardflags
& BFL_ENETADM
) {
346 /* Attach to the device */
347 if (!(ch
->adm
= adm_attach(ch
->sih
, ch
->vars
))) {
348 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc
->unit
));
351 /* Enable the external switch and set it to a known good state */
352 if (adm_enable_device(ch
->adm
)) {
353 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc
->unit
));
356 /* Configure the switch */
357 if ((boardflags
& BFL_ENETVLAN
) && adm_config_vlan(ch
->adm
)) {
358 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc
->unit
));
372 chipdetach(struct bcm4xxx
*ch
)
374 ET_TRACE(("et%d: chipdetach\n", ch
->etc
->unit
));
380 /* free robo state */
382 bcm_robo_detach(ch
->etc
->robo
);
386 /* free ADMtek state */
396 /* put the core back into reset */
398 si_core_disable(ch
->sih
, 0);
406 MFREE(ch
->osh
, ch
->vars
, ch
->vars_size
);
408 /* free chip private state */
409 MFREE(ch
->osh
, ch
, sizeof(struct bcm4xxx
));
413 chiplongname(struct bcm4xxx
*ch
, char *buf
, uint bufsize
)
417 switch (ch
->etc
->deviceid
) {
418 case BCM4402_ENET_ID
:
421 case BCM47XX_ENET_ID
:
427 snprintf(buf
, bufsize
, "Broadcom %s 10/100 Mbps Ethernet Controller", s
);
428 buf
[bufsize
- 1] = '\0';
432 chipdump(struct bcm4xxx
*ch
, struct bcmstrbuf
*b
)
437 #define MDC_RATIO 5000000
440 chipreset(struct bcm4xxx
*ch
)
445 ET_TRACE(("et%d: chipreset\n", ch
->etc
->unit
));
449 if (!si_iscoreup(ch
->sih
)) {
450 if (!ch
->etc
->nicmode
)
451 si_pci_setup(ch
->sih
, (1 << si_coreidx(ch
->sih
)));
452 /* power on reset: reset the enet core */
453 si_core_reset(ch
->sih
, 0, 0);
457 /* read counters before resetting the chip */
461 /* reset the tx dma engine */
465 /* set emac into loopback mode to ensure no rx traffic */
466 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
469 /* reset the rx dma engine */
474 si_core_reset(ch
->sih
, 0, 0);
478 /* must clear mib registers by hand */
479 W_REG(ch
->osh
, ®s
->mibcontrol
, EMC_RZ
);
480 (void) R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
481 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
482 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
483 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
484 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
485 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
486 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
487 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
488 (void) R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
489 (void) R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
490 (void) R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
491 (void) R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
492 (void) R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
493 (void) R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
494 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
495 (void) R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
496 (void) R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
497 (void) R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
498 (void) R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
499 (void) R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
500 (void) R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
501 (void) R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
502 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
503 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
504 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
505 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
506 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
507 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
508 (void) R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
509 (void) R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
510 (void) R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
511 (void) R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
512 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
513 (void) R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
514 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
515 (void) R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
516 (void) R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
517 (void) R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
518 (void) R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
522 * We want the phy registers to be accessible even when
523 * the driver is "downed" so initialize MDC preamble, frequency,
524 * and whether internal or external phy here.
526 /* default: 100Mhz SI clock and external phy */
527 W_REG(ch
->osh
, ®s
->mdiocontrol
, 0x94);
528 if (ch
->etc
->deviceid
== BCM47XX_ENET_ID
) {
529 /* 47xx chips: find out the clock */
530 if ((clk
= si_clock(ch
->sih
)) != 0) {
531 mdc
= 0x80 | ((clk
+ (MDC_RATIO
/ 2)) / MDC_RATIO
);
532 W_REG(ch
->osh
, ®s
->mdiocontrol
, mdc
);
534 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
538 } else if (ch
->etc
->deviceid
== BCM4402_ENET_ID
) {
539 /* 4402 has 62.5Mhz SB clock and internal phy */
540 W_REG(ch
->osh
, ®s
->mdiocontrol
, 0x8d);
543 /* some chips have internal phy, some don't */
544 if (!(R_REG(ch
->osh
, ®s
->devcontrol
) & DC_IP
)) {
545 W_REG(ch
->osh
, ®s
->enetcontrol
, EC_EP
);
546 } else if (R_REG(ch
->osh
, ®s
->devcontrol
) & DC_ER
) {
547 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_ER
);
549 chipphyinit(ch
, ch
->etc
->phyaddr
);
552 /* clear persistent sw intstatus */
557 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
558 * but leave the devcontrol tx and rx (fifos) disabled.
561 chipinit(struct bcm4xxx
*ch
, uint options
)
572 ET_TRACE(("et%d: chipinit\n", etc
->unit
));
574 /* Do timeout fixup */
575 si_core_tofixup(ch
->sih
);
577 /* enable crc32 generation */
578 OR_REG(ch
->osh
, ®s
->emaccontrol
, EMC_CG
);
580 /* enable one rx interrupt per received frame */
581 W_REG(ch
->osh
, ®s
->intrecvlazy
, (1 << IRL_FC_SHIFT
));
583 /* enable 802.3x tx flow control (honor received PAUSE frames) */
584 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_FE
| ERC_UF
);
587 if (etc
->promisc
|| (R_REG(ch
->osh
, ®s
->rxconfig
) & ERC_CA
))
588 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_PE
);
590 /* our local address */
591 chipwrcam(ch
, &etc
->cur_etheraddr
, idx
++);
593 /* allmulti or a list of discrete multicast addresses */
595 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_AM
);
596 else if (etc
->nmulticast
) {
597 for (i
= 0; i
< etc
->nmulticast
; i
++)
598 chipwrcam(ch
, &etc
->multicast
[i
], idx
++);
602 OR_REG(ch
->osh
, ®s
->camcontrol
, CC_CE
);
605 /* optionally enable mac-level loopback */
607 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
609 /* set max frame lengths - account for possible vlan tag */
610 W_REG(ch
->osh
, ®s
->rxmaxlength
, ETHER_MAX_LEN
+ 32);
611 W_REG(ch
->osh
, ®s
->txmaxlength
, ETHER_MAX_LEN
+ 32);
613 /* set tx watermark */
614 W_REG(ch
->osh
, ®s
->txwatermark
, 56);
617 W_REG(ch
->osh
, ®s
->txcontrol
, etc
->duplex
? EXC_FD
: 0);
620 * Optionally, disable phy autonegotiation and force our speed/duplex
621 * or constrain our advertised capabilities.
623 if (etc
->forcespeed
!= ET_AUTO
)
624 chipphyforce(ch
, etc
->phyaddr
);
625 else if (etc
->advertise
&& etc
->needautoneg
)
626 chipphyadvertise(ch
, etc
->phyaddr
);
628 if (options
& ET_INIT_FULL
) {
629 /* initialize the tx and rx dma channels */
633 /* post dma receive buffers */
636 /* setup timer interrupt */
637 W_REG(ch
->osh
, ®s
->gptimer
, 0);
639 /* lastly, enable interrupts */
640 if (options
& ET_INIT_INTRON
)
644 dma_rxenable(ch
->di
);
646 /* turn on the emac */
647 OR_REG(ch
->osh
, ®s
->enetcontrol
, EC_EE
);
651 static bool BCMFASTPATH
652 chiptx(struct bcm4xxx
*ch
, void *p0
)
656 ET_TRACE(("et%d: chiptx\n", ch
->etc
->unit
));
657 ET_LOG("et%d: chiptx", ch
->etc
->unit
, 0);
659 error
= dma_txfast(ch
->di
, p0
, TRUE
);
662 ET_ERROR(("et%d: chiptx: out of txds\n", ch
->etc
->unit
));
669 /* reclaim completed transmit descriptors and packets */
670 static void BCMFASTPATH
671 chiptxreclaim(struct bcm4xxx
*ch
, bool forceall
)
673 ET_TRACE(("et%d: chiptxreclaim\n", ch
->etc
->unit
));
674 dma_txreclaim(ch
->di
, forceall
);
675 ch
->intstatus
&= ~I_XI
;
678 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
679 static void * BCMFASTPATH
680 chiprx(struct bcm4xxx
*ch
)
684 ET_TRACE(("et%d: chiprx\n", ch
->etc
->unit
));
685 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
687 if ((p
= dma_rx(ch
->di
)) == NULL
)
688 ch
->intstatus
&= ~I_RI
;
693 /* reclaim completed dma receive descriptors and packets */
695 chiprxreclaim(struct bcm4xxx
*ch
)
697 ET_TRACE(("et%d: chiprxreclaim\n", ch
->etc
->unit
));
698 dma_rxreclaim(ch
->di
);
699 ch
->intstatus
&= ~I_RI
;
702 /* allocate and post dma receive buffers */
703 static void BCMFASTPATH
704 chiprxfill(struct bcm4xxx
*ch
)
706 ET_TRACE(("et%d: chiprxfill\n", ch
->etc
->unit
));
707 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
711 /* get current and pending interrupt events */
712 static int BCMFASTPATH
713 chipgetintrevents(struct bcm4xxx
*ch
, bool in_isr
)
722 /* read the interrupt status register */
723 intstatus
= R_REG(ch
->osh
, ®s
->intstatus
);
725 /* defer unsolicited interrupts */
726 intstatus
&= (in_isr
? ch
->intmask
: DEF_INTMASK
);
728 /* clear non-error interrupt conditions */
729 if (intstatus
!= 0) {
730 W_REG(ch
->osh
, ®s
->intstatus
, intstatus
);
734 /* or new bits into persistent intstatus */
735 intstatus
= (ch
->intstatus
|= intstatus
);
737 /* return if no events */
741 /* convert chip-specific intstatus bits into generic intr event bits */
742 if (intstatus
& I_RI
)
744 if (intstatus
& I_XI
)
746 if (intstatus
& I_ERRORS
)
747 events
|= INTR_ERROR
;
748 if (intstatus
& I_TO
)
751 /* check for rx after tx for 3 seconds on the unit 1, */
752 /* schedule reset if it's missing - possible rx stuck */
753 if (ch
->etc
->chip
== BCM4710_CHIP_ID
&& ch
->etc
->unit
== 1) {
754 if (intstatus
& I_RI
)
755 W_REG(ch
->osh
, ®s
->gptimer
, 0);
756 else if (!R_REG(ch
->osh
, ®s
->gptimer
))
757 W_REG(ch
->osh
, ®s
->gptimer
, 3 * 125000000);
763 /* enable chip interrupts */
764 static void BCMFASTPATH
765 chipintrson(struct bcm4xxx
*ch
)
767 ch
->intmask
= DEF_INTMASK
;
768 W_REG(ch
->osh
, &ch
->regs
->intmask
, ch
->intmask
);
771 /* disable chip interrupts */
772 static void BCMFASTPATH
773 chipintrsoff(struct bcm4xxx
*ch
)
775 W_REG(ch
->osh
, &ch
->regs
->intmask
, 0);
776 (void) R_REG(ch
->osh
, &ch
->regs
->intmask
); /* sync readback */
780 /* return true of caller should re-initialize, otherwise false */
781 static bool BCMFASTPATH
782 chiperrors(struct bcm4xxx
*ch
)
789 intstatus
= ch
->intstatus
;
790 ch
->intstatus
&= ~(I_ERRORS
);
792 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc
->unit
, intstatus
));
794 if (intstatus
& I_PC
) {
795 ET_ERROR(("et%d: descriptor error\n", etc
->unit
));
799 if (intstatus
& I_PD
) {
800 ET_ERROR(("et%d: data error\n", etc
->unit
));
804 if (intstatus
& I_DE
) {
805 ET_ERROR(("et%d: descriptor protocol error\n", etc
->unit
));
808 /* NOTE : this ie NOT an error. It becomes an error only
809 * when the rx fifo overflows
811 if (intstatus
& I_RU
) {
812 ET_ERROR(("et%d: receive descriptor underflow\n", etc
->unit
));
816 if (intstatus
& I_RO
) {
817 ET_ERROR(("et%d: receive fifo overflow\n", etc
->unit
));
821 if (intstatus
& I_TO
) {
822 ET_ERROR(("et%d: rx stuck suspected\n", etc
->unit
));
825 if (intstatus
& I_XU
) {
826 ET_ERROR(("et%d: transmit fifo underflow\n", etc
->unit
));
829 /* if overflows or decriptors underflow, don't report it
830 * as an error and provoque a reset
832 if (intstatus
& ~(I_RU
) & I_ERRORS
)
838 chipwrcam(struct bcm4xxx
*ch
, struct ether_addr
*ea
, uint camindex
)
842 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & (CC_CB
| CC_CE
)) == 0);
844 w
= (ea
->octet
[2] << 24) | (ea
->octet
[3] << 16) | (ea
->octet
[4] << 8)
846 W_REG(ch
->osh
, &ch
->regs
->camdatalo
, w
);
847 w
= CD_V
| (ea
->octet
[0] << 8) | ea
->octet
[1];
848 W_REG(ch
->osh
, &ch
->regs
->camdatahi
, w
);
849 W_REG(ch
->osh
, &ch
->regs
->camcontrol
, ((camindex
<< CC_INDEX_SHIFT
) | CC_WR
));
851 /* spin until done */
852 SPINWAIT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
), 100);
855 * This assertion is usually caused by the phy not providing a clock
856 * to the bottom portion of the mac..
858 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
) == 0);
862 chipstatsupd(struct bcm4xxx
*ch
)
873 * mib counters are clear-on-read.
874 * Don't bother using the pkt and octet counters since they are only
875 * 16bits and wrap too quickly to be useful.
877 m
->tx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
878 m
->tx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
879 m
->tx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
880 m
->tx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
881 m
->tx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
882 m
->tx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
883 m
->tx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
884 m
->tx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
885 m
->tx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
886 m
->tx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
887 m
->tx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
888 m
->tx_underruns
+= R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
889 m
->tx_total_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
890 m
->tx_single_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
891 m
->tx_multiple_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
892 m
->tx_excessive_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
893 m
->tx_late_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
894 m
->tx_defered
+= R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
895 m
->tx_carrier_lost
+= R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
896 m
->tx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
897 m
->rx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
898 m
->rx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
899 m
->rx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
900 m
->rx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
901 m
->rx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
902 m
->rx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
903 m
->rx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
904 m
->rx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
905 m
->rx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
906 m
->rx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
907 m
->rx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
908 m
->rx_missed_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
909 m
->rx_crc_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
910 m
->rx_undersize
+= R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
911 m
->rx_crc_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
912 m
->rx_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
913 m
->rx_symbol_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
914 m
->rx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
915 m
->rx_nonpause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
918 * Aggregate transmit and receive errors that probably resulted
919 * in the loss of a frame are computed on the fly.
921 * We seem to get lots of tx_carrier_lost errors when flipping
922 * speed modes so don't count these as tx errors.
924 * Arbitrarily lump the non-specific dma errors as tx errors.
926 etc
->txerror
= m
->tx_jabber_pkts
+ m
->tx_oversize_pkts
927 + m
->tx_underruns
+ m
->tx_excessive_cols
928 + m
->tx_late_cols
+ etc
->txnobuf
+ etc
->dmade
929 + etc
->dmada
+ etc
->dmape
+ etc
->txuflo
;
930 etc
->rxerror
= m
->rx_jabber_pkts
+ m
->rx_oversize_pkts
931 + m
->rx_missed_pkts
+ m
->rx_crc_align_errs
932 + m
->rx_undersize
+ m
->rx_crc_errs
933 + m
->rx_align_errs
+ m
->rx_symbol_errs
934 + etc
->rxnobuf
+ etc
->rxdmauflo
+ etc
->rxoflo
+ etc
->rxbadlen
;
938 chipdumpmib(ch_t
*ch
, struct bcmstrbuf
*b
)
944 bcm_bprintf(b
, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d "
945 "tx_oversize_pkts %d\n",
946 m
->tx_broadcast_pkts
, m
->tx_multicast_pkts
,
948 m
->tx_oversize_pkts
);
949 bcm_bprintf(b
, "tx_fragment_pkts %d tx_underruns %d\n",
950 m
->tx_fragment_pkts
, m
->tx_underruns
);
951 bcm_bprintf(b
, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d "
952 "tx_excessive_cols %d\n",
953 m
->tx_total_cols
, m
->tx_single_cols
, m
->tx_multiple_cols
,
954 m
->tx_excessive_cols
);
955 bcm_bprintf(b
, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n",
956 m
->tx_late_cols
, m
->tx_defered
, m
->tx_carrier_lost
,
959 /* receive stat counters */
960 /* hardware mib pkt and octet counters wrap too quickly to be useful */
961 bcm_bprintf(b
, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d "
962 "rx_oversize_pkts %d\n",
963 m
->rx_broadcast_pkts
, m
->rx_multicast_pkts
,
964 m
->rx_jabber_pkts
, m
->rx_oversize_pkts
);
965 bcm_bprintf(b
, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d "
967 m
->rx_fragment_pkts
, m
->rx_missed_pkts
,
968 m
->rx_crc_align_errs
, m
->rx_undersize
);
969 bcm_bprintf(b
, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n",
970 m
->rx_crc_errs
, m
->rx_align_errs
, m
->rx_symbol_errs
);
971 bcm_bprintf(b
, "rx_pause_pkts %d rx_nonpause_pkts %d\n",
972 m
->rx_pause_pkts
, m
->rx_nonpause_pkts
);
976 chipenablepme(struct bcm4xxx
*ch
)
982 /* enable chip wakeup pattern matching */
983 OR_REG(ch
->osh
, ®s
->devcontrol
, DC_PM
);
985 /* enable sonics bus PME */
986 si_core_cflags(ch
->sih
, SICF_PME_EN
, SICF_PME_EN
);
990 chipdisablepme(struct bcm4xxx
*ch
)
996 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_PM
);
997 si_core_cflags(ch
->sih
, SICF_PME_EN
, 0);
1001 chipduplexupd(struct bcm4xxx
*ch
)
1005 txcontrol
= R_REG(ch
->osh
, &ch
->regs
->txcontrol
);
1006 if (ch
->etc
->duplex
&& !(txcontrol
& EXC_FD
))
1007 OR_REG(ch
->osh
, &ch
->regs
->txcontrol
, EXC_FD
);
1008 else if (!ch
->etc
->duplex
&& (txcontrol
& EXC_FD
))
1009 AND_REG(ch
->osh
, &ch
->regs
->txcontrol
, ~EXC_FD
);
1013 chipphyrd(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
)
1015 bcmenetregs_t
*regs
;
1017 ASSERT(phyaddr
< MAXEPHY
);
1020 * BCM5222 dualphy shared mdio contortion.
1021 * remote phy: another emac controls our phy.
1023 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
1024 if (ch
->etphy
== NULL
) {
1025 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
1027 /* first time reset */
1029 chipphyreset(ch
, ch
->etc
->phyaddr
);
1032 return (et_phyrd(ch
->etphy
, phyaddr
, reg
));
1037 /* local phy: our emac controls our phy */
1042 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
1044 /* issue the read */
1045 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_READ
| (phyaddr
<< MD_PMD_SHIFT
)
1046 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
));
1048 /* wait for it to complete */
1049 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
1050 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
1051 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch
->etc
->unit
));
1054 return (R_REG(ch
->osh
, ®s
->mdiodata
) & MD_DATA_MASK
);
1058 chipphywr(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1060 bcmenetregs_t
*regs
;
1062 ASSERT(phyaddr
< MAXEPHY
);
1065 * BCM5222 dualphy shared mdio contortion.
1066 * remote phy: another emac controls our phy.
1068 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
1069 if (ch
->etphy
== NULL
)
1070 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
1072 et_phywr(ch
->etphy
, phyaddr
, reg
, v
);
1076 /* local phy: our emac controls our phy */
1081 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
1082 ASSERT((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0);
1084 /* issue the write */
1085 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_WRITE
| (phyaddr
<< MD_PMD_SHIFT
)
1086 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
| v
));
1088 /* wait for it to complete */
1089 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
1090 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
1091 ET_ERROR(("et%d: chipphywr: did not complete\n", ch
->etc
->unit
));
1096 chipphyor(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1100 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1102 chipphywr(ch
, phyaddr
, reg
, tmp
);
1106 chipphyand(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1110 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1112 chipphywr(ch
, phyaddr
, reg
, tmp
);
1116 chipphyreset(struct bcm4xxx
*ch
, uint phyaddr
)
1118 ASSERT(phyaddr
< MAXEPHY
);
1120 if (phyaddr
== EPHY_NOREG
)
1123 chipphywr(ch
, phyaddr
, 0, CTL_RESET
);
1125 if (chipphyrd(ch
, phyaddr
, 0) & CTL_RESET
) {
1126 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch
->etc
->unit
));
1129 chipphyinit(ch
, phyaddr
);
1133 chipphyinit(struct bcm4xxx
*ch
, uint phyaddr
)
1137 /* enable activity led */
1138 chipphyand(ch
, phyaddr
, 26, 0x7fff);
1140 /* enable traffic meter led mode */
1141 chipphyor(ch
, phyaddr
, 27, (1 << 6));
1143 phyid
= chipphyrd(ch
, phyaddr
, 0x2);
1144 phyid
|= chipphyrd(ch
, phyaddr
, 0x3) << 16;
1146 if (phyid
== 0x55210022) {
1147 chipphywr(ch
, phyaddr
, 28, (uint16
) (chipphyrd(ch
, phyaddr
, 28) & 0x0fff));
1148 chipphywr(ch
, phyaddr
, 30, (uint16
) (chipphyrd(ch
, phyaddr
, 30) | 0x3000));
1149 chipphywr(ch
, phyaddr
, 22, (uint16
) (chipphyrd(ch
, phyaddr
, 22) & 0xffdf));
1151 chipphywr(ch
, phyaddr
, 28, (uint16
) ((chipphyrd(ch
, phyaddr
, 28) & 0x0fff) | 0x1000));
1152 chipphywr(ch
, phyaddr
, 29, 1);
1153 chipphywr(ch
, phyaddr
, 30, 4);
1155 chipphywr(ch
, phyaddr
, 28, (uint16
) (chipphyrd( ch
, phyaddr
, 28) & 0x0fff));
1160 chipphyforce(struct bcm4xxx
*ch
, uint phyaddr
)
1165 ASSERT(phyaddr
< MAXEPHY
);
1167 if (phyaddr
== EPHY_NOREG
)
1172 if (etc
->forcespeed
== ET_AUTO
)
1175 ctl
= chipphyrd(ch
, phyaddr
, 0);
1176 ctl
&= ~(CTL_SPEED
| CTL_ANENAB
| CTL_DUPLEX
);
1178 switch (etc
->forcespeed
) {
1191 ctl
|= (CTL_SPEED
| CTL_DUPLEX
);
1195 chipphywr(ch
, phyaddr
, 0, ctl
);
1197 /* force Auto MDI-X for the AC101L phy */
1198 if (chipphyrd(ch
, phyaddr
, 2) == 0x0022 &&
1199 chipphyrd(ch
, phyaddr
, 3) == 0x5521)
1201 chipphywr(ch
, phyaddr
, 23, 0x8000);
1205 /* set selected capability bits in autonegotiation advertisement */
1207 chipphyadvertise(struct bcm4xxx
*ch
, uint phyaddr
)
1212 ASSERT(phyaddr
< MAXEPHY
);
1214 if (phyaddr
== EPHY_NOREG
)
1219 if ((etc
->forcespeed
!= ET_AUTO
) || !etc
->needautoneg
)
1222 ASSERT(etc
->advertise
);
1224 /* reset our advertised capabilitity bits */
1225 adv
= chipphyrd(ch
, phyaddr
, 4);
1226 adv
&= ~(ADV_100FULL
| ADV_100HALF
| ADV_10FULL
| ADV_10HALF
);
1227 adv
|= etc
->advertise
;
1228 chipphywr(ch
, phyaddr
, 4, adv
);
1230 /* restart autonegotiation */
1231 chipphyor(ch
, phyaddr
, 0, CTL_RESTART
);
1233 etc
->needautoneg
= FALSE
;