Broadcom et driver updates from SDK 5.10.140.0
[tomato.git] / release / src-rt / et / sys / etc47xx.c
blobc441715cbabb11f8c9931599d8d5df68d08211f6
1 /*
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
8 * All Rights Reserved.
9 *
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 $
17 #include <typedefs.h>
18 #include <osl.h>
19 #include <bcmdefs.h>
20 #include <bcmendian.h>
21 #include <bcmutils.h>
22 #include <bcmdevs.h>
23 #include <proto/ethernet.h>
24 #include <siutils.h>
25 #include <sbhnddma.h>
26 #include <hnddma.h>
27 #include <et_dbg.h>
28 #include <hndsoc.h>
29 #include <bcmenet47xx.h>
30 #include <et_export.h> /* for et_phyxx() routines */
32 #ifdef ETROBO
33 #include <bcmrobo.h>
34 #endif /* ETROBO */
35 #ifdef ETADM
36 #include <etc_adm.h>
37 #endif /* ETADM */
39 struct bcm4xxx; /* forward declaration */
40 #define ch_t struct bcm4xxx
41 #include <etc.h>
43 /* private chip state */
44 struct bcm4xxx {
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 */
63 uint vars_size;
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 = {
105 chipid,
106 chipattach,
107 chipdetach,
108 chipreset,
109 chipinit,
110 chiptx,
111 chiprx,
112 chiprxfill,
113 chipgetintrevents,
114 chiperrors,
115 chipintrson,
116 chipintrsoff,
117 chiptxreclaim,
118 chiprxreclaim,
119 chipstatsupd,
120 chipdumpmib,
121 chipenablepme,
122 chipdisablepme,
123 chipphyreset,
124 chipphyrd,
125 chipphywr,
126 chipdump,
127 chiplongname,
128 chipduplexupd
131 static uint devices[] = {
132 BCM47XX_ENET_ID,
133 BCM4402_ENET_ID,
134 BCM4401_ENET_ID,
135 0x0000 };
137 static bool
138 chipid(uint vendor, uint device)
140 int i;
142 if (vendor != VENDOR_BROADCOM)
143 return (FALSE);
145 for (i = 0; devices[i]; i++) {
146 if (device == devices[i])
147 return (TRUE);
149 return (FALSE);
152 static void *
153 chipattach(etc_info_t *etc, void *osh, void *regsva)
155 struct bcm4xxx *ch;
156 bcmenetregs_t *regs;
157 uint i;
158 char name[16];
159 char *var;
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,
166 MALLOCED(osh)));
167 return (NULL);
169 bzero((char *)ch, sizeof(struct bcm4xxx));
171 ch->etc = etc;
172 ch->et = etc->et;
173 ch->osh = osh;
175 /* store the pointer to the sw mib */
176 etc->mib = (void *)&ch->mib;
178 /* get si handle */
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));
182 goto fail;
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
192 * the ethernet.
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));
196 goto fail;
199 ch->regs = regs;
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 */
219 chipreset(ch);
221 /* dma attach */
222 sprintf(name, "et%d", etc->coreunit);
223 if ((ch->di = dma_attach(osh, name, ch->sih,
224 (void *)&regs->dmaregs.xmt, (void *)&regs->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));
228 goto fail;
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);
235 if (var == NULL) {
236 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
237 goto fail;
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));
243 goto fail;
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);
255 if (var == NULL) {
256 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
257 goto fail;
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));
264 goto fail;
267 /* get our mdc/mdio port number */
268 sprintf(name, "et%dmdcport", etc->coreunit);
269 var = getvar(ch->vars, name);
270 if (var == NULL) {
271 ET_ERROR(("et%d: chipattach: NVRAM_GET(%s) not found\n", etc->unit, name));
272 goto fail;
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++)
293 OSL_DELAY(1000);
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);
307 #ifdef ETROBO
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));
320 goto fail;
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));
325 goto fail;
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));
331 goto fail;
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));
336 goto fail;
339 #endif /* ETROBO */
341 #ifdef ETADM
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));
349 goto fail;
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));
354 goto fail;
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));
359 goto fail;
362 #endif /* ETADM */
364 return ((void *)ch);
366 fail:
367 chipdetach(ch);
368 return (NULL);
371 static void
372 chipdetach(struct bcm4xxx *ch)
374 ET_TRACE(("et%d: chipdetach\n", ch->etc->unit));
376 if (ch == NULL)
377 return;
379 #ifdef ETROBO
380 /* free robo state */
381 if (ch->etc->robo)
382 bcm_robo_detach(ch->etc->robo);
383 #endif /* ETROBO */
385 #ifdef ETADM
386 /* free ADMtek state */
387 if (ch->adm)
388 adm_detach(ch->adm);
389 #endif /* ETADM */
391 /* free dma state */
392 if (ch->di)
393 dma_detach(ch->di);
394 ch->di = NULL;
396 /* put the core back into reset */
397 if (ch->sih)
398 si_core_disable(ch->sih, 0);
400 /* free si handle */
401 si_detach(ch->sih);
402 ch->sih = NULL;
404 /* free vars */
405 if (ch->vars)
406 MFREE(ch->osh, ch->vars, ch->vars_size);
408 /* free chip private state */
409 MFREE(ch->osh, ch, sizeof(struct bcm4xxx));
412 static void
413 chiplongname(struct bcm4xxx *ch, char *buf, uint bufsize)
415 char *s;
417 switch (ch->etc->deviceid) {
418 case BCM4402_ENET_ID:
419 s = "BCM4402";
420 break;
421 case BCM47XX_ENET_ID:
422 default:
423 s = "BCM47xx";
424 break;
427 snprintf(buf, bufsize, "Broadcom %s 10/100 Mbps Ethernet Controller", s);
428 buf[bufsize - 1] = '\0';
431 static void
432 chipdump(struct bcm4xxx *ch, struct bcmstrbuf *b)
437 #define MDC_RATIO 5000000
439 static void
440 chipreset(struct bcm4xxx *ch)
442 bcmenetregs_t *regs;
443 uint32 clk, mdc;
445 ET_TRACE(("et%d: chipreset\n", ch->etc->unit));
447 regs = ch->regs;
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);
454 goto chipinreset;
457 /* read counters before resetting the chip */
458 if (ch->mibgood)
459 chipstatsupd(ch);
461 /* reset the tx dma engine */
462 if (ch->di)
463 dma_txreset(ch->di);
465 /* set emac into loopback mode to ensure no rx traffic */
466 W_REG(ch->osh, &regs->rxconfig, ERC_LE);
467 OSL_DELAY(1);
469 /* reset the rx dma engine */
470 if (ch->di)
471 dma_rxreset(ch->di);
473 /* reset core */
474 si_core_reset(ch->sih, 0, 0);
476 chipinreset:
478 /* must clear mib registers by hand */
479 W_REG(ch->osh, &regs->mibcontrol, EMC_RZ);
480 (void) R_REG(ch->osh, &regs->mib.tx_broadcast_pkts);
481 (void) R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
482 (void) R_REG(ch->osh, &regs->mib.tx_len_64);
483 (void) R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
484 (void) R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
485 (void) R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
486 (void) R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
487 (void) R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
488 (void) R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
489 (void) R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
490 (void) R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
491 (void) R_REG(ch->osh, &regs->mib.tx_underruns);
492 (void) R_REG(ch->osh, &regs->mib.tx_total_cols);
493 (void) R_REG(ch->osh, &regs->mib.tx_single_cols);
494 (void) R_REG(ch->osh, &regs->mib.tx_multiple_cols);
495 (void) R_REG(ch->osh, &regs->mib.tx_excessive_cols);
496 (void) R_REG(ch->osh, &regs->mib.tx_late_cols);
497 (void) R_REG(ch->osh, &regs->mib.tx_defered);
498 (void) R_REG(ch->osh, &regs->mib.tx_carrier_lost);
499 (void) R_REG(ch->osh, &regs->mib.tx_pause_pkts);
500 (void) R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
501 (void) R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
502 (void) R_REG(ch->osh, &regs->mib.rx_len_64);
503 (void) R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
504 (void) R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
505 (void) R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
506 (void) R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
507 (void) R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
508 (void) R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
509 (void) R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
510 (void) R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
511 (void) R_REG(ch->osh, &regs->mib.rx_missed_pkts);
512 (void) R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
513 (void) R_REG(ch->osh, &regs->mib.rx_undersize);
514 (void) R_REG(ch->osh, &regs->mib.rx_crc_errs);
515 (void) R_REG(ch->osh, &regs->mib.rx_align_errs);
516 (void) R_REG(ch->osh, &regs->mib.rx_symbol_errs);
517 (void) R_REG(ch->osh, &regs->mib.rx_pause_pkts);
518 (void) R_REG(ch->osh, &regs->mib.rx_nonpause_pkts);
519 ch->mibgood = TRUE;
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, &regs->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, &regs->mdiocontrol, mdc);
533 } else {
534 ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, "
535 "using 100Mhz\n",
536 ch->etc->unit));
538 } else if (ch->etc->deviceid == BCM4402_ENET_ID) {
539 /* 4402 has 62.5Mhz SB clock and internal phy */
540 W_REG(ch->osh, &regs->mdiocontrol, 0x8d);
543 /* some chips have internal phy, some don't */
544 if (!(R_REG(ch->osh, &regs->devcontrol) & DC_IP)) {
545 W_REG(ch->osh, &regs->enetcontrol, EC_EP);
546 } else if (R_REG(ch->osh, &regs->devcontrol) & DC_ER) {
547 AND_REG(ch->osh, &regs->devcontrol, ~DC_ER);
548 OSL_DELAY(100);
549 chipphyinit(ch, ch->etc->phyaddr);
552 /* clear persistent sw intstatus */
553 ch->intstatus = 0;
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.
560 static void
561 chipinit(struct bcm4xxx *ch, uint options)
563 etc_info_t *etc;
564 bcmenetregs_t *regs;
565 uint idx;
566 uint i;
568 regs = ch->regs;
569 etc = ch->etc;
570 idx = 0;
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, &regs->emaccontrol, EMC_CG);
580 /* enable one rx interrupt per received frame */
581 W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));
583 /* enable 802.3x tx flow control (honor received PAUSE frames) */
584 W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);
586 /* initialize CAM */
587 if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
588 OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
589 else {
590 /* our local address */
591 chipwrcam(ch, &etc->cur_etheraddr, idx++);
593 /* allmulti or a list of discrete multicast addresses */
594 if (etc->allmulti)
595 OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
596 else if (etc->nmulticast) {
597 for (i = 0; i < etc->nmulticast; i++)
598 chipwrcam(ch, &etc->multicast[i], idx++);
601 /* enable cam */
602 OR_REG(ch->osh, &regs->camcontrol, CC_CE);
605 /* optionally enable mac-level loopback */
606 if (etc->loopbk)
607 OR_REG(ch->osh, &regs->rxconfig, ERC_LE);
609 /* set max frame lengths - account for possible vlan tag */
610 W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
611 W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);
613 /* set tx watermark */
614 W_REG(ch->osh, &regs->txwatermark, 56);
616 /* set tx duplex */
617 W_REG(ch->osh, &regs->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 */
630 dma_txinit(ch->di);
631 dma_rxinit(ch->di);
633 /* post dma receive buffers */
634 dma_rxfill(ch->di);
636 /* setup timer interrupt */
637 W_REG(ch->osh, &regs->gptimer, 0);
639 /* lastly, enable interrupts */
640 if (options & ET_INIT_INTRON)
641 et_intrson(etc->et);
643 else
644 dma_rxenable(ch->di);
646 /* turn on the emac */
647 OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
650 /* dma transmit */
651 static bool BCMFASTPATH
652 chiptx(struct bcm4xxx *ch, void *p0)
654 int error;
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);
661 if (error) {
662 ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit));
663 ch->etc->txnobuf++;
664 return FALSE;
666 return TRUE;
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)
682 void *p;
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;
690 return (p);
693 /* reclaim completed dma receive descriptors and packets */
694 static void
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);
708 dma_rxfill(ch->di);
711 /* get current and pending interrupt events */
712 static int BCMFASTPATH
713 chipgetintrevents(struct bcm4xxx *ch, bool in_isr)
715 bcmenetregs_t *regs;
716 uint32 intstatus;
717 int events;
719 regs = ch->regs;
720 events = 0;
722 /* read the interrupt status register */
723 intstatus = R_REG(ch->osh, &regs->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, &regs->intstatus, intstatus);
731 events = INTR_NEW;
734 /* or new bits into persistent intstatus */
735 intstatus = (ch->intstatus |= intstatus);
737 /* return if no events */
738 if (intstatus == 0)
739 return (0);
741 /* convert chip-specific intstatus bits into generic intr event bits */
742 if (intstatus & I_RI)
743 events |= INTR_RX;
744 if (intstatus & I_XI)
745 events |= INTR_TX;
746 if (intstatus & I_ERRORS)
747 events |= INTR_ERROR;
748 if (intstatus & I_TO)
749 events |= INTR_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, &regs->gptimer, 0);
756 else if (!R_REG(ch->osh, &regs->gptimer))
757 W_REG(ch->osh, &regs->gptimer, 3 * 125000000);
760 return (events);
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 */
777 ch->intmask = 0;
780 /* return true of caller should re-initialize, otherwise false */
781 static bool BCMFASTPATH
782 chiperrors(struct bcm4xxx *ch)
784 uint32 intstatus;
785 etc_info_t *etc;
787 etc = ch->etc;
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));
796 etc->dmade++;
799 if (intstatus & I_PD) {
800 ET_ERROR(("et%d: data error\n", etc->unit));
801 etc->dmada++;
804 if (intstatus & I_DE) {
805 ET_ERROR(("et%d: descriptor protocol error\n", etc->unit));
806 etc->dmape++;
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));
813 etc->rxdmauflo++;
816 if (intstatus & I_RO) {
817 ET_ERROR(("et%d: receive fifo overflow\n", etc->unit));
818 etc->rxoflo++;
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));
827 etc->txuflo++;
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)
833 return (TRUE);
834 return FALSE;
837 static void
838 chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
840 uint32 w;
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)
845 | ea->octet[5];
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);
861 static void
862 chipstatsupd(struct bcm4xxx *ch)
864 etc_info_t *etc;
865 bcmenetregs_t *regs;
866 bcmenetmib_t *m;
868 etc = ch->etc;
869 regs = ch->regs;
870 m = &ch->mib;
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, &regs->mib.tx_broadcast_pkts);
878 m->tx_multicast_pkts += R_REG(ch->osh, &regs->mib.tx_multicast_pkts);
879 m->tx_len_64 += R_REG(ch->osh, &regs->mib.tx_len_64);
880 m->tx_len_65_to_127 += R_REG(ch->osh, &regs->mib.tx_len_65_to_127);
881 m->tx_len_128_to_255 += R_REG(ch->osh, &regs->mib.tx_len_128_to_255);
882 m->tx_len_256_to_511 += R_REG(ch->osh, &regs->mib.tx_len_256_to_511);
883 m->tx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.tx_len_512_to_1023);
884 m->tx_len_1024_to_max += R_REG(ch->osh, &regs->mib.tx_len_1024_to_max);
885 m->tx_jabber_pkts += R_REG(ch->osh, &regs->mib.tx_jabber_pkts);
886 m->tx_oversize_pkts += R_REG(ch->osh, &regs->mib.tx_oversize_pkts);
887 m->tx_fragment_pkts += R_REG(ch->osh, &regs->mib.tx_fragment_pkts);
888 m->tx_underruns += R_REG(ch->osh, &regs->mib.tx_underruns);
889 m->tx_total_cols += R_REG(ch->osh, &regs->mib.tx_total_cols);
890 m->tx_single_cols += R_REG(ch->osh, &regs->mib.tx_single_cols);
891 m->tx_multiple_cols += R_REG(ch->osh, &regs->mib.tx_multiple_cols);
892 m->tx_excessive_cols += R_REG(ch->osh, &regs->mib.tx_excessive_cols);
893 m->tx_late_cols += R_REG(ch->osh, &regs->mib.tx_late_cols);
894 m->tx_defered += R_REG(ch->osh, &regs->mib.tx_defered);
895 m->tx_carrier_lost += R_REG(ch->osh, &regs->mib.tx_carrier_lost);
896 m->tx_pause_pkts += R_REG(ch->osh, &regs->mib.tx_pause_pkts);
897 m->rx_broadcast_pkts += R_REG(ch->osh, &regs->mib.rx_broadcast_pkts);
898 m->rx_multicast_pkts += R_REG(ch->osh, &regs->mib.rx_multicast_pkts);
899 m->rx_len_64 += R_REG(ch->osh, &regs->mib.rx_len_64);
900 m->rx_len_65_to_127 += R_REG(ch->osh, &regs->mib.rx_len_65_to_127);
901 m->rx_len_128_to_255 += R_REG(ch->osh, &regs->mib.rx_len_128_to_255);
902 m->rx_len_256_to_511 += R_REG(ch->osh, &regs->mib.rx_len_256_to_511);
903 m->rx_len_512_to_1023 += R_REG(ch->osh, &regs->mib.rx_len_512_to_1023);
904 m->rx_len_1024_to_max += R_REG(ch->osh, &regs->mib.rx_len_1024_to_max);
905 m->rx_jabber_pkts += R_REG(ch->osh, &regs->mib.rx_jabber_pkts);
906 m->rx_oversize_pkts += R_REG(ch->osh, &regs->mib.rx_oversize_pkts);
907 m->rx_fragment_pkts += R_REG(ch->osh, &regs->mib.rx_fragment_pkts);
908 m->rx_missed_pkts += R_REG(ch->osh, &regs->mib.rx_missed_pkts);
909 m->rx_crc_align_errs += R_REG(ch->osh, &regs->mib.rx_crc_align_errs);
910 m->rx_undersize += R_REG(ch->osh, &regs->mib.rx_undersize);
911 m->rx_crc_errs += R_REG(ch->osh, &regs->mib.rx_crc_errs);
912 m->rx_align_errs += R_REG(ch->osh, &regs->mib.rx_align_errs);
913 m->rx_symbol_errs += R_REG(ch->osh, &regs->mib.rx_symbol_errs);
914 m->rx_pause_pkts += R_REG(ch->osh, &regs->mib.rx_pause_pkts);
915 m->rx_nonpause_pkts += R_REG(ch->osh, &regs->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;
937 static void
938 chipdumpmib(ch_t *ch, struct bcmstrbuf *b)
940 bcmenetmib_t *m;
942 m = &ch->mib;
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,
947 m->tx_jabber_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,
957 m->tx_pause_pkts);
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 "
966 "rx_undersize %d\n",
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);
975 static void
976 chipenablepme(struct bcm4xxx *ch)
978 bcmenetregs_t *regs;
980 regs = ch->regs;
982 /* enable chip wakeup pattern matching */
983 OR_REG(ch->osh, &regs->devcontrol, DC_PM);
985 /* enable sonics bus PME */
986 si_core_cflags(ch->sih, SICF_PME_EN, SICF_PME_EN);
989 static void
990 chipdisablepme(struct bcm4xxx *ch)
992 bcmenetregs_t *regs;
994 regs = ch->regs;
996 AND_REG(ch->osh, &regs->devcontrol, ~DC_PM);
997 si_core_cflags(ch->sih, SICF_PME_EN, 0);
1000 static void
1001 chipduplexupd(struct bcm4xxx *ch)
1003 uint32 txcontrol;
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);
1012 static uint16
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 */
1028 if (ch->etphy)
1029 chipphyreset(ch, ch->etc->phyaddr);
1031 if (ch->etphy)
1032 return (et_phyrd(ch->etphy, phyaddr, reg));
1033 else
1034 return (0xffff);
1037 /* local phy: our emac controls our phy */
1039 regs = ch->regs;
1041 /* clear mii_int */
1042 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1044 /* issue the read */
1045 W_REG(ch->osh, &regs->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, &regs->emacintstatus) & EI_MII) == 0), 100);
1050 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1051 ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
1054 return (R_REG(ch->osh, &regs->mdiodata) & MD_DATA_MASK);
1057 static void
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);
1071 if (ch->etphy)
1072 et_phywr(ch->etphy, phyaddr, reg, v);
1073 return;
1076 /* local phy: our emac controls our phy */
1078 regs = ch->regs;
1080 /* clear mii_int */
1081 W_REG(ch->osh, &regs->emacintstatus, EI_MII);
1082 ASSERT((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0);
1084 /* issue the write */
1085 W_REG(ch->osh, &regs->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, &regs->emacintstatus) & EI_MII) == 0), 100);
1090 if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
1091 ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
1095 static void
1096 chipphyor(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1098 uint16 tmp;
1100 tmp = chipphyrd(ch, phyaddr, reg);
1101 tmp |= v;
1102 chipphywr(ch, phyaddr, reg, tmp);
1105 static void
1106 chipphyand(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
1108 uint16 tmp;
1110 tmp = chipphyrd(ch, phyaddr, reg);
1111 tmp &= v;
1112 chipphywr(ch, phyaddr, reg, tmp);
1115 static void
1116 chipphyreset(struct bcm4xxx *ch, uint phyaddr)
1118 ASSERT(phyaddr < MAXEPHY);
1120 if (phyaddr == EPHY_NOREG)
1121 return;
1123 chipphywr(ch, phyaddr, 0, CTL_RESET);
1124 OSL_DELAY(100);
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);
1132 static void
1133 chipphyinit(struct bcm4xxx *ch, uint phyaddr)
1135 uint phyid = 0;
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));
1159 static void
1160 chipphyforce(struct bcm4xxx *ch, uint phyaddr)
1162 etc_info_t *etc;
1163 uint16 ctl;
1165 ASSERT(phyaddr < MAXEPHY);
1167 if (phyaddr == EPHY_NOREG)
1168 return;
1170 etc = ch->etc;
1172 if (etc->forcespeed == ET_AUTO)
1173 return;
1175 ctl = chipphyrd(ch, phyaddr, 0);
1176 ctl &= ~(CTL_SPEED | CTL_ANENAB | CTL_DUPLEX);
1178 switch (etc->forcespeed) {
1179 case ET_10HALF:
1180 break;
1182 case ET_10FULL:
1183 ctl |= CTL_DUPLEX;
1184 break;
1186 case ET_100HALF:
1187 ctl |= CTL_SPEED;
1188 break;
1190 case ET_100FULL:
1191 ctl |= (CTL_SPEED | CTL_DUPLEX);
1192 break;
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 */
1206 static void
1207 chipphyadvertise(struct bcm4xxx *ch, uint phyaddr)
1209 etc_info_t *etc;
1210 uint16 adv;
1212 ASSERT(phyaddr < MAXEPHY);
1214 if (phyaddr == EPHY_NOREG)
1215 return;
1217 etc = ch->etc;
1219 if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg)
1220 return;
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;