PR 39241: Add support for Broadcom BCM5906(M) from Karl Uwe Lockhoff

This commit is contained in:
cegger 2008-08-25 08:15:05 +00:00
parent aa9ba46b38
commit bdc28ede37
5 changed files with 446 additions and 140 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: brgphy.c,v 1.39 2008/05/04 17:06:09 xtraeme Exp $ */ /* $NetBSD: brgphy.c,v 1.40 2008/08/25 08:15:05 cegger Exp $ */
/*- /*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.39 2008/05/04 17:06:09 xtraeme Exp $"); __KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.40 2008/08/25 08:15:05 cegger Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -183,6 +183,9 @@ static const struct mii_phydesc brgphys[] = {
{ MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754, { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754,
MII_STR_BROADCOM2_BCM5754 }, MII_STR_BROADCOM2_BCM5754 },
{ MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906,
MII_STR_xxBROADCOM_ALT1_BCM5906 },
{ 0, 0, { 0, 0,
NULL }, NULL },
}; };
@ -226,6 +229,10 @@ brgphyattach(struct device *parent, struct device *self, void *aux)
sc->mii_flags = ma->mii_flags; sc->mii_flags = ma->mii_flags;
sc->mii_anegticks = MII_ANEGTICKS; sc->mii_anegticks = MII_ANEGTICKS;
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM_ALT1) {
sc->mii_funcs = &brgphy_5750_funcs;
aprint_normal_dev(self, "using BCM5750 DSP patch\n");
} else {
switch (MII_MODEL(ma->mii_id2)) { switch (MII_MODEL(ma->mii_id2)) {
case MII_MODEL_BROADCOM_BCM5400: case MII_MODEL_BROADCOM_BCM5400:
sc->mii_funcs = &brgphy_5401_funcs; sc->mii_funcs = &brgphy_5401_funcs;
@ -278,6 +285,7 @@ brgphyattach(struct device *parent, struct device *self, void *aux)
sc->mii_funcs = &brgphy_funcs; sc->mii_funcs = &brgphy_funcs;
break; break;
} }
}
PHY_RESET(sc); PHY_RESET(sc);

View File

@ -1,4 +1,4 @@
/* $NetBSD: brgphyreg.h,v 1.2 2002/06/22 14:37:58 fvdl Exp $ */ /* $NetBSD: brgphyreg.h,v 1.3 2008/08/25 08:15:05 cegger Exp $ */
/* /*
* Copyright (c) 2000 * Copyright (c) 2000
@ -75,6 +75,14 @@
#define BRGPHY_PHY_EXTSTS_LOCK_ER 0x0002 /* Lock error */ #define BRGPHY_PHY_EXTSTS_LOCK_ER 0x0002 /* Lock error */
#define BRGPHY_PHY_EXTSTS_MLT3_ER 0x0001 /* MLT3 code error */ #define BRGPHY_PHY_EXTSTS_MLT3_ER 0x0001 /* MLT3 code error */
#define BRGPHY_MII_1000CTL 0x09 /* 1000baseT control */
#define BRGPHY_1000CTL_TST 0xE000 /* Test modes */
#define BRGPHY_1000CTL_MSE 0x1000 /* Master/Slave enable */
#define BRGPHY_1000CTL_MSC 0x0800 /* Master/Slave configuration */
#define BRGPHY_1000CTL_RD 0x0400 /* Repeater/DTE */
#define BRGPHY_1000CTL_AFD 0x0200 /* Advertise full duplex */
#define BRGPHY_1000CTL_AHD 0x0100 /* Advertise half duplex */
#define BRGPHY_MII_RXERRCNT 0x12 /* RX error counter */ #define BRGPHY_MII_RXERRCNT 0x12 /* RX error counter */
#define BRGPHY_MII_FCERRCNT 0x13 /* false carrier sense counter */ #define BRGPHY_MII_FCERRCNT 0x13 /* false carrier sense counter */

View File

@ -1,4 +1,4 @@
$NetBSD: miidevs,v 1.76 2008/04/28 20:23:53 martin Exp $ $NetBSD: miidevs,v 1.77 2008/08/25 08:15:05 cegger Exp $
/*- /*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@ -77,6 +77,7 @@ oui xxCICADA 0x00c08f Cicada Semiconductor
/* bad bitorder (bits "g" and "h" (= MSBs byte 1) lost) */ /* bad bitorder (bits "g" and "h" (= MSBs byte 1) lost) */
oui yyAMD 0x000058 Advanced Micro Devices oui yyAMD 0x000058 Advanced Micro Devices
oui xxBROADCOM 0x000818 Broadcom Corporation oui xxBROADCOM 0x000818 Broadcom Corporation
oui xxBROADCOM_ALT1 0x0050ef Broadcom Corporation
oui xxDAVICOM 0x000676 Davicom Semiconductor oui xxDAVICOM 0x000676 Davicom Semiconductor
oui yyINTEL 0x005500 Intel oui yyINTEL 0x005500 Intel
oui xxMARVELL 0x000ac2 Marvell Semiconductor oui xxMARVELL 0x000ac2 Marvell Semiconductor
@ -138,6 +139,7 @@ model BROADCOM BCM5780 0x0035 BCM5780 1000BASE-T media interface
model BROADCOM BCM5708C 0x0036 BCM5708C 1000BASE-T media interface model BROADCOM BCM5708C 0x0036 BCM5708C 1000BASE-T media interface
model BROADCOM2 BCM5755 0x000c BCM5755 1000BASE-T media interface model BROADCOM2 BCM5755 0x000c BCM5755 1000BASE-T media interface
model BROADCOM2 BCM5754 0x000e BCM5754/5787 1000BASE-T media interface model BROADCOM2 BCM5754 0x000e BCM5754/5787 1000BASE-T media interface
model xxBROADCOM_ALT1 BCM5906 0x0004 BCM5906 10/100baseTX media interface
/* Cicada Semiconductor PHYs (now owned by Vitesse?) */ /* Cicada Semiconductor PHYs (now owned by Vitesse?) */
model CICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY model CICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bge.c,v 1.150 2008/07/25 19:45:06 dsl Exp $ */ /* $NetBSD: if_bge.c,v 1.151 2008/08/25 08:15:05 cegger Exp $ */
/* /*
* Copyright (c) 2001 Wind River Systems * Copyright (c) 2001 Wind River Systems
@ -79,7 +79,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.150 2008/07/25 19:45:06 dsl Exp $"); __KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.151 2008/08/25 08:15:05 cegger Exp $");
#include "bpfilter.h" #include "bpfilter.h"
#include "vlan.h" #include "vlan.h"
@ -186,12 +186,19 @@ static int bge_rx_thresh_lvl;
static int bge_rxthresh_nodenum; static int bge_rxthresh_nodenum;
typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, u_int8_t[]);
static int bge_probe(device_t, cfdata_t, void *); static int bge_probe(device_t, cfdata_t, void *);
static void bge_attach(device_t, device_t, void *); static void bge_attach(device_t, device_t, void *);
static void bge_release_resources(struct bge_softc *); static void bge_release_resources(struct bge_softc *);
static void bge_txeof(struct bge_softc *); static void bge_txeof(struct bge_softc *);
static void bge_rxeof(struct bge_softc *); static void bge_rxeof(struct bge_softc *);
static int bge_get_eaddr_mem(struct bge_softc *, u_int8_t[]);
static int bge_get_eaddr_nvram(struct bge_softc *, u_int8_t[]);
static int bge_get_eaddr_eeprom(struct bge_softc *, u_int8_t[]);
static int bge_get_eaddr(struct bge_softc *, u_int8_t[]);
static void bge_tick(void *); static void bge_tick(void *);
static void bge_stats_update(struct bge_softc *); static void bge_stats_update(struct bge_softc *);
static int bge_encap(struct bge_softc *, struct mbuf *, u_int32_t *); static int bge_encap(struct bge_softc *, struct mbuf *, u_int32_t *);
@ -282,6 +289,7 @@ int bge_tso_debug = 0;
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || \ BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || \
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || \ BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || \
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 || \ BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 || \
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 || \
BGE_IS_5714_FAMILY(sc) ) BGE_IS_5714_FAMILY(sc) )
#define BGE_IS_5705_OR_BEYOND(sc) \ #define BGE_IS_5705_OR_BEYOND(sc) \
@ -329,6 +337,21 @@ bge_writereg_ind(struct bge_softc *sc, int off, int val)
pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_DATA, val); pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_DATA, val);
} }
static void
bge_writemem_direct(struct bge_softc *sc, int off, int val)
{
CSR_WRITE_4(sc, off, val);
}
static void
bge_writembx(struct bge_softc *sc, int off, int val)
{
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906)
off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
CSR_WRITE_4(sc, off, val);
}
#ifdef notdef #ifdef notdef
static u_int8_t static u_int8_t
bge_vpd_readbyte(struct bge_softc *sc, int addr) bge_vpd_readbyte(struct bge_softc *sc, int addr)
@ -413,6 +436,79 @@ bge_vpd_read(struct bge_softc *sc)
} }
#endif #endif
static u_int8_t
bge_nvram_getbyte(struct bge_softc *sc, int addr, u_int8_t *dest)
{
u_int32_t access, byte = 0;
int i;
/* Lock. */
CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
for (i = 0; i < 8000; i++) {
if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1)
break;
DELAY(20);
}
if (i == 8000)
return (1);
/* Enable access. */
access = CSR_READ_4(sc, BGE_NVRAM_ACCESS);
CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE);
CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc);
CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD);
for (i = 0; i < BGE_TIMEOUT * 10; i++) {
DELAY(10);
if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) {
DELAY(10);
break;
}
}
if (i == BGE_TIMEOUT * 10) {
aprint_error_dev(sc->bge_dev, "nvram read timed out\n");
return (1);
}
/* Get result. */
byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA);
*dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF;
/* Disable access. */
CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access);
/* Unlock. */
CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
CSR_READ_4(sc, BGE_NVRAM_SWARB);
return (0);
}
/*
* Read a sequence of bytes from NVRAM.
*/
static int
bge_read_nvram(struct bge_softc *sc, u_int8_t *dest, int off, int cnt)
{
int err = 0, i;
u_int8_t byte = 0;
if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5906)
return (1);
for (i = 0; i < cnt; i++) {
err = bge_nvram_getbyte(sc, off + i, &byte);
if (err)
break;
*(dest + i) = byte;
}
return (err ? 1 : 0);
}
/* /*
* Read a byte of data stored in the EEPROM at address 'addr.' The * Read a byte of data stored in the EEPROM at address 'addr.' The
* BCM570x supports both the traditional bitbang interface and an * BCM570x supports both the traditional bitbang interface and an
@ -539,6 +635,15 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
u_int32_t saved_autopoll; u_int32_t saved_autopoll;
int i; int i;
if (phy!=1) {
return;
}
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 &&
(reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL)) {
return;
}
/* Touching the PHY while autopolling is on may trigger PCI errors */ /* Touching the PHY while autopolling is on may trigger PCI errors */
saved_autopoll = CSR_READ_4(sc, BGE_MI_MODE); saved_autopoll = CSR_READ_4(sc, BGE_MI_MODE);
if (saved_autopoll & BGE_MIMODE_AUTOPOLL) { if (saved_autopoll & BGE_MIMODE_AUTOPOLL) {
@ -552,9 +657,12 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
BGE_MIPHY(phy)|BGE_MIREG(reg)|val); BGE_MIPHY(phy)|BGE_MIREG(reg)|val);
for (i = 0; i < BGE_TIMEOUT; i++) { for (i = 0; i < BGE_TIMEOUT; i++) {
if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY))
break;
delay(10); delay(10);
if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
delay(5);
CSR_READ_4(sc, BGE_MI_COMM);
break;
}
} }
if (saved_autopoll & BGE_MIMODE_AUTOPOLL) { if (saved_autopoll & BGE_MIMODE_AUTOPOLL) {
@ -968,7 +1076,7 @@ bge_init_rx_ring_std(struct bge_softc *sc)
} }
sc->bge_std = i - 1; sc->bge_std = i - 1;
CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
sc->bge_flags |= BGE_RXRING_VALID; sc->bge_flags |= BGE_RXRING_VALID;
@ -1018,7 +1126,7 @@ bge_init_rx_ring_jumbo(struct bge_softc *sc)
rcb->bge_maxlen_flags = 0; rcb->bge_maxlen_flags = 0;
CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
return(0); return(0);
} }
@ -1091,14 +1199,14 @@ bge_init_tx_ring(struct bge_softc *sc)
/* Initialize transmit producer index for host-memory send ring. */ /* Initialize transmit producer index for host-memory send ring. */
sc->bge_tx_prodidx = 0; sc->bge_tx_prodidx = 0;
CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */ if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */
CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
/* NIC-memory send ring not used; initialize to zero. */ /* NIC-memory send ring not used; initialize to zero. */
CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */ if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */
CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
SLIST_INIT(&sc->txdma_list); SLIST_INIT(&sc->txdma_list);
for (i = 0; i < BGE_RSLOTS; i++) { for (i = 0; i < BGE_RSLOTS; i++) {
@ -1466,6 +1574,10 @@ bge_blockinit(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50);
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20);
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
} else if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04);
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10);
} else { } else {
/* Values from Linux driver... */ /* Values from Linux driver... */
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 304); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 304);
@ -1484,6 +1596,7 @@ bge_blockinit(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10);
/* Enable buffer manager */ /* Enable buffer manager */
if ((sc->bge_quirks & BGE_QUIRK_5705_CORE) == 0) {
CSR_WRITE_4(sc, BGE_BMAN_MODE, CSR_WRITE_4(sc, BGE_BMAN_MODE,
BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN); BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN);
@ -1499,6 +1612,7 @@ bge_blockinit(struct bge_softc *sc)
"buffer manager failed to start\n"); "buffer manager failed to start\n");
return(ENXIO); return(ENXIO);
} }
}
/* Enable flow-through queues */ /* Enable flow-through queues */
CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF);
@ -1597,7 +1711,8 @@ bge_blockinit(struct bge_softc *sc)
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 || if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 ||
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 ||
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 ||
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787) BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 ||
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906)
i = 8; i = 8;
CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, i); CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, i);
@ -1637,15 +1752,15 @@ bge_blockinit(struct bge_softc *sc)
BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt,
BGE_RCB_FLAG_RING_DISABLED)); BGE_RCB_FLAG_RING_DISABLED));
RCB_WRITE_4(sc, rcb_addr, bge_nicaddr, 0); RCB_WRITE_4(sc, rcb_addr, bge_nicaddr, 0);
CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO + bge_writembx(sc, BGE_MBX_RX_CONS0_LO +
(i * (sizeof(u_int64_t))), 0); (i * (sizeof(u_int64_t))), 0);
rcb_addr += sizeof(struct bge_rcb); rcb_addr += sizeof(struct bge_rcb);
} }
/* Initialize RX ring indexes */ /* Initialize RX ring indexes */
CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, 0); bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0);
CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
CSR_WRITE_4(sc, BGE_MBX_RX_MINI_PROD_LO, 0); bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
/* /*
* Set up RX return ring 0 * Set up RX return ring 0
@ -2092,6 +2207,10 @@ static const struct bge_revision bge_majorrevs[] = {
BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
"unknown BCM5787" }, "unknown BCM5787" },
{ BGE_ASICREV_BCM5906,
BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
"unknown BCM5906" },
{ 0, { 0,
0, 0,
NULL } NULL }
@ -2345,6 +2464,16 @@ static const struct bge_product {
"3Com 3c996 Gigabit Ethernet", "3Com 3c996 Gigabit Ethernet",
}, },
{ PCI_VENDOR_BROADCOM,
PCI_PRODUCT_BROADCOM_BCM5906,
"Broadcom BCM5906 Fast Ethernet",
},
{ PCI_VENDOR_BROADCOM,
PCI_PRODUCT_BROADCOM_BCM5906M,
"Broadcom BCM5906M Fast Ethernet",
},
{ 0, { 0,
0, 0,
NULL }, NULL },
@ -2444,7 +2573,6 @@ bge_attach(device_t parent, device_t self, void *aux)
bus_dma_segment_t seg; bus_dma_segment_t seg;
int rseg; int rseg;
u_int32_t hwcfg = 0; u_int32_t hwcfg = 0;
u_int32_t mac_addr = 0;
u_int32_t command; u_int32_t command;
struct ifnet *ifp; struct ifnet *ifp;
void * kva; void * kva;
@ -2558,19 +2686,9 @@ bge_attach(device_t parent, device_t self, void *aux)
/* /*
* Get station address from the EEPROM. * Get station address from the EEPROM.
*/ */
mac_addr = bge_readmem_ind(sc, 0x0c14); if (bge_get_eaddr(sc, eaddr)) {
if ((mac_addr >> 16) == 0x484b) {
eaddr[0] = (u_char)(mac_addr >> 8);
eaddr[1] = (u_char)(mac_addr >> 0);
mac_addr = bge_readmem_ind(sc, 0x0c18);
eaddr[2] = (u_char)(mac_addr >> 24);
eaddr[3] = (u_char)(mac_addr >> 16);
eaddr[4] = (u_char)(mac_addr >> 8);
eaddr[5] = (u_char)(mac_addr >> 0);
} else if (bge_read_eeprom(sc, (void *)eaddr,
BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
aprint_error_dev(sc->bge_dev, aprint_error_dev(sc->bge_dev,
"failed to read station address\n"); "failed to reade station address\n");
bge_release_resources(sc); bge_release_resources(sc);
return; return;
} }
@ -2818,6 +2936,19 @@ bge_reset(struct bge_softc *sc)
{ {
u_int32_t cachesize, command, pcistate, new_pcistate; u_int32_t cachesize, command, pcistate, new_pcistate;
int i, val; int i, val;
void (*write_op)(struct bge_softc *, int, int);
if (BGE_IS_5750_OR_BEYOND(sc) && !BGE_IS_5714_FAMILY(sc) &&
(BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5906)) {
if (sc->bge_pcie) {
write_op = bge_writemem_direct;
} else {
write_op = bge_writemem_ind;
}
} else {
write_op = bge_writereg_ind;
}
/* Save some important PCI state. */ /* Save some important PCI state. */
cachesize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ); cachesize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ);
@ -2852,7 +2983,18 @@ bge_reset(struct bge_softc *sc)
} }
/* Issue global reset */ /* Issue global reset */
bge_writereg_ind(sc, BGE_MISC_CFG, val); write_op(sc, BGE_MISC_CFG, val);
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
i = CSR_READ_4(sc, BGE_VCPU_STATUS);
CSR_WRITE_4(sc, BGE_VCPU_STATUS,
i | BGE_VCPU_STATUS_DRV_RESET);
i = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL);
CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL,
i & ~BGE_VCPU_EXT_CTRL_HALT_CPU);
}
DELAY(1000); DELAY(1000);
@ -2886,7 +3028,7 @@ bge_reset(struct bge_softc *sc)
BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW); BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW);
pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, command); pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, command);
pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ, cachesize); pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ, cachesize);
bge_writereg_ind(sc, BGE_MISC_CFG, (65 << 1)); write_op(sc, BGE_MISC_CFG, (65 << 1));
/* Enable memory arbiter. */ /* Enable memory arbiter. */
{ {
@ -2897,6 +3039,19 @@ bge_reset(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode); CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode);
} }
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
for (i = 0; i < BGE_TIMEOUT; i++) {
val = CSR_READ_4(sc, BGE_VCPU_STATUS);
if (val & BGE_VCPU_STATUS_INIT_DONE)
break;
DELAY(100);
}
if (i == BGE_TIMEOUT) {
aprint_error_dev(sc->bge_dev, "reset timed out\n");
return;
}
} else {
/* /*
* Write the magic number to the firmware mailbox at 0xb50 * Write the magic number to the firmware mailbox at 0xb50
* so that the driver can synchronize with the firmware. * so that the driver can synchronize with the firmware.
@ -2927,6 +3082,7 @@ bge_reset(struct bge_softc *sc)
if (!sc->bge_pcie) if (!sc->bge_pcie)
return; return;
} }
}
/* /*
* XXX Wait for the value of the PCISTATE register to * XXX Wait for the value of the PCISTATE register to
@ -3131,11 +3287,11 @@ bge_rxeof(struct bge_softc *sc)
(*ifp->if_input)(ifp, m); (*ifp->if_input)(ifp, m);
} }
CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx); bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
if (stdcnt) if (stdcnt)
CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
if (jumbocnt) if (jumbocnt)
CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
} }
static void static void
@ -3246,7 +3402,7 @@ bge_intr(void *xsc)
*/ */
/* Ack interrupt and stop others from occuring. */ /* Ack interrupt and stop others from occuring. */
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
BGE_EVCNT_INCR(sc->bge_ev_intr); BGE_EVCNT_INCR(sc->bge_ev_intr);
@ -3318,7 +3474,7 @@ bge_intr(void *xsc)
bge_handle_events(sc); bge_handle_events(sc);
/* Re-enable interrupts. */ /* Re-enable interrupts. */
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
bge_start(ifp); bge_start(ifp);
@ -3949,9 +4105,9 @@ bge_start(struct ifnet *ifp)
return; return;
/* Transmit */ /* Transmit */
CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */ if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG) /* 5700 b2 errata */
CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
sc->bge_tx_prodidx = prodidx; sc->bge_tx_prodidx = prodidx;
@ -4037,7 +4193,7 @@ bge_init(struct ifnet *ifp)
/* Enable host interrupts. */ /* Enable host interrupts. */
BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA); BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
if ((error = bge_ifmedia_upd(ifp)) != 0) if ((error = bge_ifmedia_upd(ifp)) != 0)
goto out; goto out;
@ -4162,6 +4318,13 @@ bge_ioctl(struct ifnet *ifp, u_long command, void *data)
sc->bge_if_flags = ifp->if_flags; sc->bge_if_flags = ifp->if_flags;
error = 0; error = 0;
break; break;
case SIOCADDMULTI:
case SIOCDELMULTI:
if (ifp->if_flags & IFF_RUNNING) {
bge_setmulti(sc);
error = 0;
}
break;
case SIOCSIFMEDIA: case SIOCSIFMEDIA:
/* XXX Flow control is not supported for 1000BASE-SX */ /* XXX Flow control is not supported for 1000BASE-SX */
if (sc->bge_tbi) { if (sc->bge_tbi) {
@ -4194,15 +4357,10 @@ bge_ioctl(struct ifnet *ifp, u_long command, void *data)
} }
break; break;
default: default:
if ((error = ether_ioctl(ifp, command, data)) != ENETRESET) error = ether_ioctl(ifp, command, data);
break; if (error == ENETRESET) {
error = 0; error = 0;
}
if (command != SIOCADDMULTI && command != SIOCDELMULTI)
;
else if (ifp->if_flags & IFF_RUNNING)
bge_setmulti(sc);
break; break;
} }
@ -4302,7 +4460,7 @@ bge_stop(struct ifnet *ifp, int disable)
/* Disable host interrupts. */ /* Disable host interrupts. */
BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
/* /*
* Tell firmware we're shutting down. * Tell firmware we're shutting down.
@ -4405,3 +4563,66 @@ SYSCTL_SETUP(sysctl_bge, "sysctl bge subtree setup")
err: err:
aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
} }
static int
bge_get_eaddr_mem(struct bge_softc *sc, u_int8_t ether_addr[])
{
u_int32_t mac_addr;
mac_addr = bge_readmem_ind(sc, 0x0c14);
if ((mac_addr >> 16) == 0x484b) {
ether_addr[0] = (uint8_t)(mac_addr >> 8);
ether_addr[1] = (uint8_t)mac_addr;
mac_addr = bge_readmem_ind(sc, 0x0c18);
ether_addr[2] = (uint8_t)(mac_addr >> 24);
ether_addr[3] = (uint8_t)(mac_addr >> 16);
ether_addr[4] = (uint8_t)(mac_addr >> 8);
ether_addr[5] = (uint8_t)mac_addr;
return (0);
}
return (1);
}
static int
bge_get_eaddr_nvram(struct bge_softc *sc, u_int8_t ether_addr[])
{
int mac_offset = BGE_EE_MAC_OFFSET;
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
mac_offset = BGE_EE_MAC_OFFSET_5906;
}
return (bge_read_nvram(sc, ether_addr, mac_offset + 2,
ETHER_ADDR_LEN));
}
static int
bge_get_eaddr_eeprom(struct bge_softc *sc, u_int8_t ether_addr[])
{
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
return (1);
}
return (bge_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2,
ETHER_ADDR_LEN));
}
static int
bge_get_eaddr(struct bge_softc *sc, u_int8_t eaddr[])
{
static const bge_eaddr_fcn_t bge_eaddr_funcs[] = {
/* NOTE: Order is critical */
bge_get_eaddr_mem,
bge_get_eaddr_nvram,
bge_get_eaddr_eeprom,
NULL
};
const bge_eaddr_fcn_t *func;
for (func = bge_eaddr_funcs; *func != NULL; ++func) {
if ((*func)(sc, eaddr) == 0)
break;
}
return (*func == NULL ? ENXIO : 0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bgereg.h,v 1.47 2008/07/24 08:14:49 sborrill Exp $ */ /* $NetBSD: if_bgereg.h,v 1.48 2008/08/25 08:15:05 cegger Exp $ */
/* /*
* Copyright (c) 2001 Wind River Systems * Copyright (c) 2001 Wind River Systems
* Copyright (c) 1997, 1998, 1999, 2001 * Copyright (c) 1997, 1998, 1999, 2001
@ -300,8 +300,11 @@
#define BGE_ASICREV_BCM5714 0x09 #define BGE_ASICREV_BCM5714 0x09
#define BGE_ASICREV_BCM5755 0x0a #define BGE_ASICREV_BCM5755 0x0a
#define BGE_ASICREV_BCM5787 0x0b #define BGE_ASICREV_BCM5787 0x0b
/* is this one mistyped ??? */
#define BGE_ASICREV_BCM5706 0x0c #define BGE_ASICREV_BCM5706 0x0c
#define BGE_ASICREV_BCM5906 0x0c
/* chip revisions */ /* chip revisions */
#define BGE_CHIPREV(x) ((x) >> 24) #define BGE_CHIPREV(x) ((x) >> 24)
#define BGE_CHIPREV_5700_AX 0x70 #define BGE_CHIPREV_5700_AX 0x70
@ -1425,6 +1428,17 @@
#define BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW 0x40000000 #define BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW 0x40000000
#define BGE_RXCPUSTAT_BLOCKING_READ 0x80000000 #define BGE_RXCPUSTAT_BLOCKING_READ 0x80000000
/*
* V? CPU registers
*/
#define BGE_VCPU_STATUS 0x5100
#define BGE_VCPU_EXT_CTRL 0x6890
#define BGE_VCPU_STATUS_INIT_DONE 0x04000000
#define BGE_VCPU_STATUS_DRV_RESET 0x08000000
#define BGE_VCPU_EXT_CTRL_HALT_CPU 0x00400000
#define BGE_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000
/* /*
* TX CPU registers * TX CPU registers
@ -1676,6 +1690,57 @@
*/ */
#define BGE_PCIE_CTL0 0x7c00 #define BGE_PCIE_CTL0 0x7c00
#define BGE_PCIE_CTL1 0x7e2c #define BGE_PCIE_CTL1 0x7e2c
/*
* NVRAM Control registers
*/
#define BGE_NVRAM_CMD 0x7000
#define BGE_NVRAM_STAT 0x7004
#define BGE_NVRAM_WRDATA 0x7008
#define BGE_NVRAM_ADDR 0x700c
#define BGE_NVRAM_RDDATA 0x7010
#define BGE_NVRAM_CFG1 0x7014
#define BGE_NVRAM_CFG2 0x7018
#define BGE_NVRAM_CFG3 0x701c
#define BGE_NVRAM_SWARB 0x7020
#define BGE_NVRAM_ACCESS 0x7024
#define BGE_NVRAM_WRITE1 0x7028
#define BGE_NVRAMCMD_RESET 0x00000001
#define BGE_NVRAMCMD_DONE 0x00000008
#define BGE_NVRAMCMD_START 0x00000010
#define BGE_NVRAMCMD_WR 0x00000020 /* 1 = wr, 0 = rd */
#define BGE_NVRAMCMD_ERASE 0x00000040
#define BGE_NVRAMCMD_FIRST 0x00000080
#define BGE_NVRAMCMD_LAST 0x00000100
#define BGE_NVRAM_READCMD \
(BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE)
#define BGE_NVRAM_WRITECMD \
(BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR)
#define BGE_NVRAMSWARB_SET0 0x00000001
#define BGE_NVRAMSWARB_SET1 0x00000002
#define BGE_NVRAMSWARB_SET2 0x00000003
#define BGE_NVRAMSWARB_SET3 0x00000004
#define BGE_NVRAMSWARB_CLR0 0x00000010
#define BGE_NVRAMSWARB_CLR1 0x00000020
#define BGE_NVRAMSWARB_CLR2 0x00000040
#define BGE_NVRAMSWARB_CLR3 0x00000080
#define BGE_NVRAMSWARB_GNT0 0x00000100
#define BGE_NVRAMSWARB_GNT1 0x00000200
#define BGE_NVRAMSWARB_GNT2 0x00000400
#define BGE_NVRAMSWARB_GNT3 0x00000800
#define BGE_NVRAMSWARB_REQ0 0x00001000
#define BGE_NVRAMSWARB_REQ1 0x00002000
#define BGE_NVRAMSWARB_REQ2 0x00004000
#define BGE_NVRAMSWARB_REQ3 0x00008000
#define BGE_NVRAMACC_ENABLE 0x00000001
#define BGE_NVRAMACC_WRENABLE 0x00000002
/* /*
* TLP Control Register * TLP Control Register
* Applicable to BCM5721 and BCM5751 only * Applicable to BCM5721 and BCM5751 only
@ -1720,6 +1785,7 @@
/* Misc. config register */ /* Misc. config register */
#define BGE_MISCCFG_RESET_CORE_CLOCKS 0x00000001 #define BGE_MISCCFG_RESET_CORE_CLOCKS 0x00000001
#define BGE_MISCCFG_TIMER_PRESCALER 0x000000FE #define BGE_MISCCFG_TIMER_PRESCALER 0x000000FE
#define BGE_MISCCFG_EPHY_IDDQ 0x00200000
#define BGE_32BITTIME_66MHZ (0x41 << 1) #define BGE_32BITTIME_66MHZ (0x41 << 1)
@ -1997,6 +2063,7 @@ struct bge_status_block {
* Offset of MAC address inside EEPROM. * Offset of MAC address inside EEPROM.
*/ */
#define BGE_EE_MAC_OFFSET 0x7C #define BGE_EE_MAC_OFFSET 0x7C
#define BGE_EE_MAC_OFFSET_5906 0x10
#define BGE_EE_HWCFG_OFFSET 0xC8 #define BGE_EE_HWCFG_OFFSET 0xC8
#define BGE_HWCFG_VOLTAGE 0x00000003 #define BGE_HWCFG_VOLTAGE 0x00000003