2 * Broadcom Home Networking Division 10/100 Mbit/s Ethernet core.
4 * This file implements the chip-specific routines
5 * for Broadcom HNBU Sonics SiliconBackplane enet cores.
7 * Copyright 2006, Broadcom Corporation
10 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
11 * the contents of this file may not be disclosed to third parties, copied
12 * or duplicated in any form, in whole or in part, without the prior
13 * written permission of Broadcom Corporation.
14 * $Id: etc47xx.c,v 1.1.1.1 2007/03/20 12:22:00 roly Exp $
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 sb_t
*sbh
; /* sb utils handle */
61 char *vars
; /* sprom name=value */
64 void *adm
; /* optional admtek private data */
67 /* local prototypes */
68 static bool chipid(uint vendor
, uint device
);
69 static void *chipattach(etc_info_t
*etc
, void *osh
, void *regsva
);
70 static void chipdetach(ch_t
*ch
);
71 static void chipreset(ch_t
*ch
);
72 static void chipinit(ch_t
*ch
, bool full
);
73 static bool chiptx(ch_t
*ch
, void *p
);
74 static void *chiprx(ch_t
*ch
);
75 static void chiprxfill(ch_t
*ch
);
76 static int chipgetintrevents(ch_t
*ch
, bool in_isr
);
77 static bool chiperrors(ch_t
*ch
);
78 static void chipintrson(ch_t
*ch
);
79 static void chipintrsoff(ch_t
*ch
);
80 static void chiptxreclaim(ch_t
*ch
, bool all
);
81 static void chiprxreclaim(ch_t
*ch
);
82 static void chipstatsupd(ch_t
*ch
);
83 static void chipenablepme(ch_t
*ch
);
84 static void chipdisablepme(ch_t
*ch
);
85 static void chipphyreset(ch_t
*ch
, uint phyaddr
);
86 static void chipphyinit(ch_t
*ch
, uint phyaddr
);
87 static uint16
chipphyrd(ch_t
*ch
, uint phyaddr
, uint reg
);
88 static void chipdump(ch_t
*ch
, struct bcmstrbuf
*b
);
89 static void chiplongname(ch_t
*ch
, char *buf
, uint bufsize
);
90 static void chipduplexupd(ch_t
*ch
);
91 static void chipwrcam(struct bcm4xxx
*ch
, struct ether_addr
*ea
, uint camindex
);
92 static void chipphywr(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
93 static void chipphyor(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
94 static void chipphyand(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
);
95 static void chipphyforce(struct bcm4xxx
*ch
, uint phyaddr
);
96 static void chipphyadvertise(struct bcm4xxx
*ch
, uint phyaddr
);
98 /* chip interrupt bit error summary */
99 #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU | I_TO)
100 #define DEF_INTMASK (I_XI | I_RI | I_ERRORS)
102 struct chops bcm47xx_et_chops
= {
128 static uint devices
[] = {
135 chipid(uint vendor
, uint device
)
139 if (vendor
!= VENDOR_BROADCOM
)
142 for (i
= 0; devices
[i
]; i
++) {
143 if (device
== devices
[i
])
150 chipattach(etc_info_t
*etc
, void *osh
, void *regsva
)
157 uint boardflags
, boardtype
;
159 ET_TRACE(("et%d: chipattach: regsva 0x%x\n", etc
->unit
, (uint
)regsva
));
161 if ((ch
= (struct bcm4xxx
*) MALLOC(osh
, sizeof(struct bcm4xxx
))) == NULL
) {
162 ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc
->unit
,
166 bzero((char*)ch
, sizeof(struct bcm4xxx
));
173 if ((ch
->sbh
= sb_attach(etc
->deviceid
, ch
->osh
, regsva
, PCI_BUS
, NULL
, &ch
->vars
,
174 &ch
->vars_size
)) == NULL
) {
175 ET_ERROR(("et%d: chipattach: sb_attach error\n", etc
->unit
));
179 /* We used to have an assert here like:
180 * sb_coreid(ch->sbh) == SB_ENET
181 * but srom-less systems and simulators don't have a way to
182 * provide a default bar0window so we were relying on nvram
183 * variables. At some point we decided that we could do away
184 * with that since the wireless driver was simply doing a
185 * setcore in attach. So we need to do the same here for
188 if ((regs
= (bcmenetregs_t
*)sb_setcore(ch
->sbh
, SB_ENET
, etc
->unit
)) == NULL
) {
189 ET_ERROR(("et%d: chipattach: Could not setcore to the ENET core\n", etc
->unit
));
194 etc
->chip
= sb_chip(ch
->sbh
);
195 etc
->chiprev
= sb_chiprev(ch
->sbh
);
196 etc
->nicmode
= !(sb_bus(ch
->sbh
) == SB_BUS
);
197 etc
->coreunit
= sb_coreunit(ch
->sbh
);
198 etc
->boardflags
= getintvar(ch
->vars
, "boardflags");
200 /* set boardflags for 5365 and 5350 */
201 if (etc
->chip
== BCM5365_CHIP_ID
|| etc
->chip
== BCM5350_CHIP_ID
)
202 etc
->boardflags
|= BFL_ENETROBO
| BFL_ENETVLAN
;
204 boardflags
= etc
->boardflags
;
205 boardtype
= sb_boardtype(ch
->sbh
);
207 /* configure pci core */
208 sb_pci_setup(ch
->sbh
, (1 << sb_coreidx(ch
->sbh
)));
210 /* reset the enet core */
214 sprintf(name
, "et%d", etc
->coreunit
);
215 if ((ch
->di
= dma_attach(osh
, name
, ch
->sbh
,
216 (void *)®s
->dmaregs
.xmt
, (void *)®s
->dmaregs
.rcv
,
217 NTXD
, NRXD
, RXBUFSZ
, NRXBUFPOST
, HWRXOFF
,
218 &et_msg_level
)) == NULL
) {
219 ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc
->unit
));
222 etc
->txavail
= (uint
*) dma_getvar(ch
->di
, "&txavail");
224 /* get our local ether addr */
225 sprintf(name
, "et%dmacaddr", etc
->coreunit
);
226 var
= getvar(ch
->vars
, name
);
228 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
231 bcm_ether_atoe(var
, &etc
->perm_etheraddr
);
233 if (ETHER_ISNULLADDR(&etc
->perm_etheraddr
)) {
234 ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc
->unit
, name
, var
));
237 bcopy((char*)&etc
->perm_etheraddr
, (char*)&etc
->cur_etheraddr
, ETHER_ADDR_LEN
);
240 * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" .
241 * Instead, explicitly require the environment var "et<coreunit>phyaddr=<val>".
244 /* get our phyaddr value */
245 sprintf(name
, "et%dphyaddr", etc
->coreunit
);
246 var
= getvar(ch
->vars
, name
);
248 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
251 etc
->phyaddr
= bcm_atoi(var
) & EPHY_MASK
;
253 /* nvram says no phy is present */
254 if (etc
->phyaddr
== EPHY_NONE
) {
255 ET_ERROR(("et%d: chipattach: phy not present\n", etc
->unit
));
259 /* get our mdc/mdio port number */
260 sprintf(name
, "et%dmdcport", etc
->coreunit
);
261 var
= getvar(ch
->vars
, name
);
263 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc
->unit
, name
));
266 etc
->mdcport
= bcm_atoi(var
);
268 /* set default sofware intmask */
269 ch
->intmask
= DEF_INTMASK
;
272 * GPIO bits 2 and 6 on bcm94710r1 and bcm94710dev reset the
273 * external phys to a known good state. bcm94710r4 uses only
274 * GPIO 6 but GPIO 2 is not connected. Just reset both of them
275 * whenever this function is called.
277 if ((boardtype
== BCM94710D_BOARD
) ||
278 (boardtype
== BCM94710AP_BOARD
) ||
279 (boardtype
== BCM94710R1_BOARD
) ||
280 (boardtype
== BCM94710R4_BOARD
)) {
281 sb_gpioout(ch
->sbh
, 0x44, 0, GPIO_DRV_PRIORITY
);
282 sb_gpioouten(ch
->sbh
, 0x44, 0x44, GPIO_DRV_PRIORITY
);
283 /* Hold phys in reset for a nice long 2 ms */
284 for (i
= 0; i
< 2; i
++)
286 sb_gpioout(ch
->sbh
, 0x44, 0x44, GPIO_DRV_PRIORITY
);
287 sb_gpioouten(ch
->sbh
, 0x44, 0, GPIO_DRV_PRIORITY
);
291 * For the 5222 dual phy shared mdio contortion, our phy is
292 * on someone elses mdio pins. This other enet enet
293 * may not yet be attached so we must defer the et_phyfind().
295 /* if local phy: reset it once now */
296 if (etc
->mdcport
== etc
->coreunit
)
297 chipphyreset(ch
, etc
->phyaddr
);
301 * Broadcom Robo ethernet switch.
303 if (((boardflags
& BFL_ENETROBO
) ||
304 (boardtype
== BCM94710AP_BOARD
) ||
305 (boardtype
== BCM94702MN_BOARD
)) &&
306 (etc
->phyaddr
== EPHY_NOREG
)) {
307 /* Attach to the switch */
308 if (!(etc
->robo
= bcm_robo_attach(ch
->sbh
, ch
, ch
->vars
,
309 (miird_f
)bcm47xx_et_chops
.phyrd
,
310 (miiwr_f
)bcm47xx_et_chops
.phywr
))) {
311 ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc
->unit
));
314 /* Enable the switch and set it to a known good state */
315 if (bcm_robo_enable_device(etc
->robo
)) {
316 ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc
->unit
));
319 /* Configure the switch to do VLAN */
320 if ((boardflags
& BFL_ENETVLAN
) &&
321 bcm_robo_config_vlan(etc
->robo
, etc
->perm_etheraddr
.octet
)) {
322 ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc
->unit
));
325 /* Enable switching/forwarding */
326 if (bcm_robo_enable_switch(etc
->robo
)) {
327 ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc
->unit
));
335 * ADMtek ethernet switch.
337 if (boardflags
& BFL_ENETADM
) {
338 /* Attach to the device */
339 if (!(ch
->adm
= adm_attach(ch
->sbh
, ch
->vars
))) {
340 ET_ERROR(("et%d: chipattach: adm_attach failed\n", etc
->unit
));
343 /* Enable the external switch and set it to a known good state */
344 if (adm_enable_device(ch
->adm
)) {
345 ET_ERROR(("et%d: chipattach: adm_enable_device failed\n", etc
->unit
));
348 /* Configure the switch */
349 if ((boardflags
& BFL_ENETVLAN
) && adm_config_vlan(ch
->adm
)) {
350 ET_ERROR(("et%d: chipattach: adm_config_vlan failed\n", etc
->unit
));
364 chipdetach(struct bcm4xxx
*ch
)
366 ET_TRACE(("et%d: chipdetach\n", ch
->etc
->unit
));
372 /* free robo state */
374 bcm_robo_detach(ch
->etc
->robo
);
378 /* free ADMtek state */
387 /* put the core back into reset */
389 sb_core_disable(ch
->sbh
, 0);
397 MFREE(ch
->osh
, ch
->vars
, ch
->vars_size
);
399 /* free chip private state */
400 MFREE(ch
->osh
, ch
, sizeof(struct bcm4xxx
));
404 chiplongname(struct bcm4xxx
*ch
, char *buf
, uint bufsize
)
408 switch (ch
->etc
->deviceid
) {
409 case BCM4402_ENET_ID
:
410 s
= "Broadcom BCM4402 10/100 Mbps Ethernet Controller";
412 case BCM47XX_ENET_ID
:
414 s
= "Broadcom BCM47xx 10/100 Mbps Ethernet Controller";
418 strncpy(buf
, s
, bufsize
);
419 buf
[bufsize
- 1] = '\0';
423 chipdump(struct bcm4xxx
*ch
, struct bcmstrbuf
*b
)
428 #define MDC_RATIO 5000000
431 chipreset(struct bcm4xxx
*ch
)
436 ET_TRACE(("et%d: chipreset\n", ch
->etc
->unit
));
440 if (!sb_iscoreup(ch
->sbh
)) {
441 if (!ch
->etc
->nicmode
)
442 sb_pci_setup(ch
->sbh
, (1 << sb_coreidx(ch
->sbh
)));
443 /* power on reset: reset the enet core */
444 sb_core_reset(ch
->sbh
, 0, 0);
448 /* read counters before resetting the chip */
452 /* reset the tx dma engine */
456 /* set emac into loopback mode to ensure no rx traffic */
457 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
460 /* reset the rx dma engine */
464 ASSERT(!((ch
->etc
->deviceid
== BCM4402_ENET_ID
) && (ch
->etc
->chiprev
== 0)));
467 sb_core_reset(ch
->sbh
, 0, 0);
471 /* must clear mib registers by hand */
472 W_REG(ch
->osh
, ®s
->mibcontrol
, EMC_RZ
);
473 (void) R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
474 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
475 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
476 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
477 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
478 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
479 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
480 (void) R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
481 (void) R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
482 (void) R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
483 (void) R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
484 (void) R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
485 (void) R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
486 (void) R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
487 (void) R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
488 (void) R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
489 (void) R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
490 (void) R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
491 (void) R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
492 (void) R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
493 (void) R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
494 (void) R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
495 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
496 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
497 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
498 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
499 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
500 (void) R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
501 (void) R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
502 (void) R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
503 (void) R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
504 (void) R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
505 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
506 (void) R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
507 (void) R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
508 (void) R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
509 (void) R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
510 (void) R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
511 (void) R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
515 * We want the phy registers to be accessible even when
516 * the driver is "downed" so initialize MDC preamble, frequency,
517 * and whether internal or external phy here.
519 /* default: 100Mhz SB clock and external phy */
520 W_REG(ch
->osh
, ®s
->mdiocontrol
, 0x94);
521 if (ch
->etc
->deviceid
== BCM47XX_ENET_ID
) {
522 /* 47xx chips: find out the clock */
523 if ((clk
= sb_clock(ch
->sbh
)) != 0) {
524 mdc
= 0x80 | ((clk
+ (MDC_RATIO
/ 2)) / MDC_RATIO
);
525 W_REG(ch
->osh
, ®s
->mdiocontrol
, mdc
);
527 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
531 } else if (ch
->etc
->deviceid
== BCM4402_ENET_ID
) {
532 /* 4402 has 62.5Mhz SB clock and internal phy */
533 W_REG(ch
->osh
, ®s
->mdiocontrol
, 0x8d);
536 /* some chips have internal phy, some don't */
537 if (!(R_REG(ch
->osh
, ®s
->devcontrol
) & DC_IP
)) {
538 W_REG(ch
->osh
, ®s
->enetcontrol
, EC_EP
);
539 } else if (R_REG(ch
->osh
, ®s
->devcontrol
) & DC_ER
) {
540 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_ER
);
542 chipphyinit(ch
, ch
->etc
->phyaddr
);
545 /* clear persistent sw intstatus */
550 * Initialize all the chip registers. If dma mode, init tx and rx dma engines
551 * but leave the devcontrol tx and rx (fifos) disabled.
554 chipinit(struct bcm4xxx
*ch
, bool full
)
565 ET_TRACE(("et%d: chipinit\n", etc
->unit
));
567 /* Do timeout fixup */
568 sb_core_tofixup(ch
->sbh
);
570 /* enable crc32 generation */
571 OR_REG(ch
->osh
, ®s
->emaccontrol
, EMC_CG
);
573 /* enable one rx interrupt per received frame */
574 W_REG(ch
->osh
, ®s
->intrecvlazy
, (1 << IRL_FC_SHIFT
));
576 /* enable 802.3x tx flow control (honor received PAUSE frames) */
577 W_REG(ch
->osh
, ®s
->rxconfig
, ERC_FE
| ERC_UF
);
580 if (etc
->promisc
|| (R_REG(ch
->osh
, ®s
->rxconfig
) & ERC_CA
))
581 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_PE
);
583 /* our local address */
584 chipwrcam(ch
, &etc
->cur_etheraddr
, idx
++);
586 /* allmulti or a list of discrete multicast addresses */
588 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_AM
);
589 else if (etc
->nmulticast
) {
590 for (i
= 0; i
< etc
->nmulticast
; i
++)
591 chipwrcam(ch
, &etc
->multicast
[i
], idx
++);
595 OR_REG(ch
->osh
, ®s
->camcontrol
, CC_CE
);
598 /* optionally enable mac-level loopback */
600 OR_REG(ch
->osh
, ®s
->rxconfig
, ERC_LE
);
602 /* set max frame lengths - account for possible vlan tag */
603 W_REG(ch
->osh
, ®s
->rxmaxlength
, ETHER_MAX_LEN
+ 32);
604 W_REG(ch
->osh
, ®s
->txmaxlength
, ETHER_MAX_LEN
+ 32);
606 /* set tx watermark */
607 W_REG(ch
->osh
, ®s
->txwatermark
, 56);
610 W_REG(ch
->osh
, ®s
->txcontrol
, etc
->duplex
? EXC_FD
: 0);
613 * Optionally, disable phy autonegotiation and force our speed/duplex
614 * or constrain our advertised capabilities.
616 if (etc
->forcespeed
!= ET_AUTO
)
617 chipphyforce(ch
, etc
->phyaddr
);
618 else if (etc
->advertise
&& etc
->needautoneg
)
619 chipphyadvertise(ch
, etc
->phyaddr
);
622 /* initialize the tx and rx dma channels */
626 /* post dma receive buffers */
629 /* setup timer interrupt */
630 W_REG(ch
->osh
, ®s
->gptimer
, 0);
632 /* lastly, enable interrupts */
636 dma_rxenable(ch
->di
);
638 /* turn on the emac */
639 OR_REG(ch
->osh
, ®s
->enetcontrol
, EC_EE
);
644 chiptx(struct bcm4xxx
*ch
, void *p0
)
648 ET_TRACE(("et%d: chiptx\n", ch
->etc
->unit
));
649 ET_LOG("et%d: chiptx", ch
->etc
->unit
, 0);
651 error
= dma_txfast(ch
->di
, p0
, TRUE
);
654 ET_ERROR(("et%d: chiptx: out of txds\n", ch
->etc
->unit
));
661 /* reclaim completed transmit descriptors and packets */
663 chiptxreclaim(struct bcm4xxx
*ch
, bool forceall
)
665 ET_TRACE(("et%d: chiptxreclaim\n", ch
->etc
->unit
));
666 dma_txreclaim(ch
->di
, forceall
);
667 ch
->intstatus
&= ~I_XI
;
670 /* dma receive: returns a pointer to the next frame received, or NULL if there are no more */
672 chiprx(struct bcm4xxx
*ch
)
676 ET_TRACE(("et%d: chiprx\n", ch
->etc
->unit
));
677 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
679 if ((p
= dma_rx(ch
->di
)) == NULL
)
680 ch
->intstatus
&= ~I_RI
;
685 /* reclaim completed dma receive descriptors and packets */
687 chiprxreclaim(struct bcm4xxx
*ch
)
689 ET_TRACE(("et%d: chiprxreclaim\n", ch
->etc
->unit
));
690 dma_rxreclaim(ch
->di
);
691 ch
->intstatus
&= ~I_RI
;
694 /* allocate and post dma receive buffers */
696 chiprxfill(struct bcm4xxx
*ch
)
698 ET_TRACE(("et%d: chiprxfill\n", ch
->etc
->unit
));
699 ET_LOG("et%d: chiprx", ch
->etc
->unit
, 0);
703 /* get current and pending interrupt events */
705 chipgetintrevents(struct bcm4xxx
*ch
, bool in_isr
)
714 /* read the interrupt status register */
715 intstatus
= R_REG(ch
->osh
, ®s
->intstatus
);
717 /* defer unsolicited interrupts */
718 intstatus
&= (in_isr
? ch
->intmask
: DEF_INTMASK
);
720 /* clear non-error interrupt conditions */
721 if (intstatus
!= 0) {
722 W_REG(ch
->osh
, ®s
->intstatus
, intstatus
);
726 /* or new bits into persistent intstatus */
727 intstatus
= (ch
->intstatus
|= intstatus
);
729 /* return if no events */
733 /* convert chip-specific intstatus bits into generic intr event bits */
734 if (intstatus
& I_RI
)
736 if (intstatus
& I_XI
)
738 if (intstatus
& I_ERRORS
)
739 events
|= INTR_ERROR
;
740 if (intstatus
& I_TO
)
743 /* check for rx after tx for 3 seconds on the unit 1, */
744 /* schedule reset if it's missing - possible rx stuck */
745 if (ch
->etc
->chip
== BCM4710_CHIP_ID
&& ch
->etc
->unit
== 1) {
746 if (intstatus
& I_RI
)
747 W_REG(ch
->osh
, ®s
->gptimer
, 0);
748 else if (!R_REG(ch
->osh
, ®s
->gptimer
))
749 W_REG(ch
->osh
, ®s
->gptimer
, 3 * 125000000);
755 /* enable chip interrupts */
757 chipintrson(struct bcm4xxx
*ch
)
759 ch
->intmask
= DEF_INTMASK
;
760 W_REG(ch
->osh
, &ch
->regs
->intmask
, ch
->intmask
);
763 /* disable chip interrupts */
765 chipintrsoff(struct bcm4xxx
*ch
)
767 W_REG(ch
->osh
, &ch
->regs
->intmask
, 0);
768 (void) R_REG(ch
->osh
, &ch
->regs
->intmask
); /* sync readback */
772 /* return true of caller should re-initialize, otherwise false */
774 chiperrors(struct bcm4xxx
*ch
)
781 intstatus
= ch
->intstatus
;
782 ch
->intstatus
&= ~(I_ERRORS
);
784 ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc
->unit
, intstatus
));
786 if (intstatus
& I_PC
) {
787 ET_ERROR(("et%d: descriptor error\n", etc
->unit
));
791 if (intstatus
& I_PD
) {
792 ET_ERROR(("et%d: data error\n", etc
->unit
));
796 if (intstatus
& I_DE
) {
797 ET_ERROR(("et%d: descriptor protocol error\n", etc
->unit
));
801 if (intstatus
& I_RU
) {
802 ET_ERROR(("et%d: receive descriptor underflow\n", etc
->unit
));
806 if (intstatus
& I_RO
) {
807 ET_ERROR(("et%d: receive fifo overflow\n", etc
->unit
));
811 if (intstatus
& I_XU
) {
812 ET_ERROR(("et%d: transmit fifo underflow\n", etc
->unit
));
816 if (intstatus
& I_TO
) {
817 ET_ERROR(("et%d: rx stuck suspected\n", etc
->unit
));
824 chipwrcam(struct bcm4xxx
*ch
, struct ether_addr
*ea
, uint camindex
)
828 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & (CC_CB
| CC_CE
)) == 0);
830 w
= (ea
->octet
[2] << 24) | (ea
->octet
[3] << 16) | (ea
->octet
[4] << 8)
832 W_REG(ch
->osh
, &ch
->regs
->camdatalo
, w
);
833 w
= CD_V
| (ea
->octet
[0] << 8) | ea
->octet
[1];
834 W_REG(ch
->osh
, &ch
->regs
->camdatahi
, w
);
835 W_REG(ch
->osh
, &ch
->regs
->camcontrol
, ((camindex
<< CC_INDEX_SHIFT
) | CC_WR
));
837 /* spin until done */
838 SPINWAIT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
), 100);
841 * This assertion is usually caused by the phy not providing a clock
842 * to the bottom portion of the mac..
844 ASSERT((R_REG(ch
->osh
, &ch
->regs
->camcontrol
) & CC_CB
) == 0);
848 chipstatsupd(struct bcm4xxx
*ch
)
857 * mib counters are clear-on-read.
858 * Don't bother using the pkt and octet counters since they are only
859 * 16bits and wrap too quickly to be useful.
861 etc
->mib
.tx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_broadcast_pkts
);
862 etc
->mib
.tx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_multicast_pkts
);
863 etc
->mib
.tx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_64
);
864 etc
->mib
.tx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_65_to_127
);
865 etc
->mib
.tx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_128_to_255
);
866 etc
->mib
.tx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_256_to_511
);
867 etc
->mib
.tx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_512_to_1023
);
868 etc
->mib
.tx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.tx_len_1024_to_max
);
869 etc
->mib
.tx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_jabber_pkts
);
870 etc
->mib
.tx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_oversize_pkts
);
871 etc
->mib
.tx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_fragment_pkts
);
872 etc
->mib
.tx_underruns
+= R_REG(ch
->osh
, ®s
->mib
.tx_underruns
);
873 etc
->mib
.tx_total_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_total_cols
);
874 etc
->mib
.tx_single_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_single_cols
);
875 etc
->mib
.tx_multiple_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_multiple_cols
);
876 etc
->mib
.tx_excessive_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_excessive_cols
);
877 etc
->mib
.tx_late_cols
+= R_REG(ch
->osh
, ®s
->mib
.tx_late_cols
);
878 etc
->mib
.tx_defered
+= R_REG(ch
->osh
, ®s
->mib
.tx_defered
);
879 etc
->mib
.tx_carrier_lost
+= R_REG(ch
->osh
, ®s
->mib
.tx_carrier_lost
);
880 etc
->mib
.tx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.tx_pause_pkts
);
881 etc
->mib
.rx_broadcast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_broadcast_pkts
);
882 etc
->mib
.rx_multicast_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_multicast_pkts
);
883 etc
->mib
.rx_len_64
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_64
);
884 etc
->mib
.rx_len_65_to_127
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_65_to_127
);
885 etc
->mib
.rx_len_128_to_255
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_128_to_255
);
886 etc
->mib
.rx_len_256_to_511
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_256_to_511
);
887 etc
->mib
.rx_len_512_to_1023
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_512_to_1023
);
888 etc
->mib
.rx_len_1024_to_max
+= R_REG(ch
->osh
, ®s
->mib
.rx_len_1024_to_max
);
889 etc
->mib
.rx_jabber_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_jabber_pkts
);
890 etc
->mib
.rx_oversize_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_oversize_pkts
);
891 etc
->mib
.rx_fragment_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_fragment_pkts
);
892 etc
->mib
.rx_missed_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_missed_pkts
);
893 etc
->mib
.rx_crc_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_align_errs
);
894 etc
->mib
.rx_undersize
+= R_REG(ch
->osh
, ®s
->mib
.rx_undersize
);
895 etc
->mib
.rx_crc_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_crc_errs
);
896 etc
->mib
.rx_align_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_align_errs
);
897 etc
->mib
.rx_symbol_errs
+= R_REG(ch
->osh
, ®s
->mib
.rx_symbol_errs
);
898 etc
->mib
.rx_pause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_pause_pkts
);
899 etc
->mib
.rx_nonpause_pkts
+= R_REG(ch
->osh
, ®s
->mib
.rx_nonpause_pkts
);
902 * Aggregate transmit and receive errors that probably resulted
903 * in the loss of a frame are computed on the fly.
905 * We seem to get lots of tx_carrier_lost errors when flipping
906 * speed modes so don't count these as tx errors.
908 * Arbitrarily lump the non-specific dma errors as tx errors.
910 etc
->txerror
= etc
->mib
.tx_jabber_pkts
+ etc
->mib
.tx_oversize_pkts
911 + etc
->mib
.tx_underruns
+ etc
->mib
.tx_excessive_cols
912 + etc
->mib
.tx_late_cols
+ etc
->txnobuf
+ etc
->dmade
913 + etc
->dmada
+ etc
->dmape
+ etc
->txuflo
+ etc
->txnobuf
;
914 etc
->rxerror
= etc
->mib
.rx_jabber_pkts
+ etc
->mib
.rx_oversize_pkts
915 + etc
->mib
.rx_missed_pkts
+ etc
->mib
.rx_crc_align_errs
916 + etc
->mib
.rx_undersize
+ etc
->mib
.rx_crc_errs
917 + etc
->mib
.rx_align_errs
+ etc
->mib
.rx_symbol_errs
918 + etc
->rxnobuf
+ etc
->rxdmauflo
+ etc
->rxoflo
+ etc
->rxbadlen
;
922 chipenablepme(struct bcm4xxx
*ch
)
928 /* enable chip wakeup pattern matching */
929 OR_REG(ch
->osh
, ®s
->devcontrol
, DC_PM
);
931 /* enable sonics bus PME */
932 sb_coreflags(ch
->sbh
, SBTML_PE
, SBTML_PE
);
936 chipdisablepme(struct bcm4xxx
*ch
)
942 AND_REG(ch
->osh
, ®s
->devcontrol
, ~DC_PM
);
943 sb_coreflags(ch
->sbh
, SBTML_PE
, 0);
947 chipduplexupd(struct bcm4xxx
*ch
)
951 txcontrol
= R_REG(ch
->osh
, &ch
->regs
->txcontrol
);
952 if (ch
->etc
->duplex
&& !(txcontrol
& EXC_FD
))
953 OR_REG(ch
->osh
, &ch
->regs
->txcontrol
, EXC_FD
);
954 else if (!ch
->etc
->duplex
&& (txcontrol
& EXC_FD
))
955 AND_REG(ch
->osh
, &ch
->regs
->txcontrol
, ~EXC_FD
);
959 chipphyrd(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
)
963 ASSERT(phyaddr
< MAXEPHY
);
966 * BCM5222 dualphy shared mdio contortion.
967 * remote phy: another emac controls our phy.
969 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
970 if (ch
->etphy
== NULL
) {
971 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
973 /* first time reset */
975 chipphyreset(ch
, ch
->etc
->phyaddr
);
978 return (et_phyrd(ch
->etphy
, phyaddr
, reg
));
983 /* local phy: our emac controls our phy */
988 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
991 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_READ
| (phyaddr
<< MD_PMD_SHIFT
)
992 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
));
994 /* wait for it to complete */
995 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
996 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
997 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch
->etc
->unit
));
1000 return (R_REG(ch
->osh
, ®s
->mdiodata
) & MD_DATA_MASK
);
1004 chipphywr(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1006 bcmenetregs_t
*regs
;
1008 ASSERT(phyaddr
< MAXEPHY
);
1011 * BCM5222 dualphy shared mdio contortion.
1012 * remote phy: another emac controls our phy.
1014 if (ch
->etc
->mdcport
!= ch
->etc
->coreunit
) {
1015 if (ch
->etphy
== NULL
)
1016 ch
->etphy
= et_phyfind(ch
->et
, ch
->etc
->mdcport
);
1018 et_phywr(ch
->etphy
, phyaddr
, reg
, v
);
1022 /* local phy: our emac controls our phy */
1027 W_REG(ch
->osh
, ®s
->emacintstatus
, EI_MII
);
1028 ASSERT((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0);
1030 /* issue the write */
1031 W_REG(ch
->osh
, ®s
->mdiodata
, (MD_SB_START
| MD_OP_WRITE
| (phyaddr
<< MD_PMD_SHIFT
)
1032 | (reg
<< MD_RA_SHIFT
) | MD_TA_VALID
| v
));
1034 /* wait for it to complete */
1035 SPINWAIT(((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0), 100);
1036 if ((R_REG(ch
->osh
, ®s
->emacintstatus
) & EI_MII
) == 0) {
1037 ET_ERROR(("et%d: chipphywr: did not complete\n", ch
->etc
->unit
));
1042 chipphyor(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1046 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1048 chipphywr(ch
, phyaddr
, reg
, tmp
);
1052 chipphyand(struct bcm4xxx
*ch
, uint phyaddr
, uint reg
, uint16 v
)
1056 tmp
= chipphyrd(ch
, phyaddr
, reg
);
1058 chipphywr(ch
, phyaddr
, reg
, tmp
);
1062 chipphyreset(struct bcm4xxx
*ch
, uint phyaddr
)
1064 ASSERT(phyaddr
< MAXEPHY
);
1066 if (phyaddr
== EPHY_NOREG
)
1069 chipphywr(ch
, phyaddr
, 0, CTL_RESET
);
1071 if (chipphyrd(ch
, phyaddr
, 0) & CTL_RESET
) {
1072 ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch
->etc
->unit
));
1075 chipphyinit(ch
, phyaddr
);
1079 chipphyinit(struct bcm4xxx
*ch
, uint phyaddr
)
1083 /* enable activity led */
1084 chipphyand(ch
, phyaddr
, 26, 0x7fff);
1086 /* enable traffic meter led mode */
1087 chipphyor(ch
, phyaddr
, 27, (1 << 6));
1089 phyid
= chipphyrd(ch
, phyaddr
, 0x2);
1090 phyid
|= chipphyrd(ch
, phyaddr
, 0x3) << 16;
1092 if (phyid
== 0x55210022) {
1093 chipphywr(ch
, phyaddr
, 28, (uint16
) (chipphyrd(ch
, phyaddr
, 28) & 0x0fff));
1094 chipphywr(ch
, phyaddr
, 30, (uint16
) (chipphyrd(ch
, phyaddr
, 30) | 0x3000));
1095 chipphywr(ch
, phyaddr
, 22, (uint16
) (chipphyrd(ch
, phyaddr
, 22) & 0xffdf));
1097 chipphywr(ch
, phyaddr
, 28, (uint16
) ((chipphyrd(ch
, phyaddr
, 28) & 0x0fff) | 0x1000));
1098 chipphywr(ch
, phyaddr
, 29, 1);
1099 chipphywr(ch
, phyaddr
, 30, 4);
1101 chipphywr(ch
, phyaddr
, 28, (uint16
) (chipphyrd( ch
, phyaddr
, 28) & 0x0fff));
1106 chipphyforce(struct bcm4xxx
*ch
, uint phyaddr
)
1111 ASSERT(phyaddr
< MAXEPHY
);
1113 if (phyaddr
== EPHY_NOREG
)
1118 if (etc
->forcespeed
== ET_AUTO
)
1121 ctl
= chipphyrd(ch
, phyaddr
, 0);
1122 ctl
&= ~(CTL_SPEED
| CTL_ANENAB
| CTL_DUPLEX
);
1124 switch (etc
->forcespeed
) {
1137 ctl
|= (CTL_SPEED
| CTL_DUPLEX
);
1141 chipphywr(ch
, phyaddr
, 0, ctl
);
1143 /* force Auto MDI-X for the AC101L phy */
1144 if (chipphyrd(ch
, phyaddr
, 2) == 0x0022 &&
1145 chipphyrd(ch
, phyaddr
, 3) == 0x5521)
1147 chipphywr(ch
, phyaddr
, 23, 0x8000);
1151 /* set selected capability bits in autonegotiation advertisement */
1153 chipphyadvertise(struct bcm4xxx
*ch
, uint phyaddr
)
1158 ASSERT(phyaddr
< MAXEPHY
);
1160 if (phyaddr
== EPHY_NOREG
)
1165 if ((etc
->forcespeed
!= ET_AUTO
) || !etc
->needautoneg
)
1168 ASSERT(etc
->advertise
);
1170 /* reset our advertised capabilitity bits */
1171 adv
= chipphyrd(ch
, phyaddr
, 4);
1172 adv
&= ~(ADV_100FULL
| ADV_100HALF
| ADV_10FULL
| ADV_10HALF
);
1173 adv
|= etc
->advertise
;
1174 chipphywr(ch
, phyaddr
, 4, adv
);
1176 /* restart autonegotiation */
1177 chipphyor(ch
, phyaddr
, 0, CTL_RESTART
);
1179 etc
->needautoneg
= FALSE
;