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