Move the BCM5401 DSP patch out of the bge driver and into
the brgphy driver; all users of the BCM5400 and BCM5401 need the DSP patch and the sledgehammer-reset-at-media-set-time. Also add a DSP patch for the BCM5411 gleaned from Apple's GMAC driver for Darwin. Tested with a 3Com 3c996-T (BCM5700 + BCM5401).
This commit is contained in:
parent
f216ec52a0
commit
7d85789f0a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: brgphy.c,v 1.9 2002/07/12 04:00:10 thorpej Exp $ */
|
||||
/* $NetBSD: brgphy.c,v 1.10 2002/07/13 01:23:27 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
@ -74,7 +74,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.9 2002/07/12 04:00:10 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.10 2002/07/13 01:23:27 thorpej Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -103,10 +103,21 @@ struct cfattach brgphy_ca = {
|
||||
int brgphy_service(struct mii_softc *, struct mii_data *, int);
|
||||
void brgphy_status(struct mii_softc *);
|
||||
|
||||
void brgphy_5401_reset(struct mii_softc *);
|
||||
void brgphy_5411_reset(struct mii_softc *);
|
||||
|
||||
const struct mii_phy_funcs brgphy_funcs = {
|
||||
brgphy_service, brgphy_status, mii_phy_reset,
|
||||
};
|
||||
|
||||
const struct mii_phy_funcs brgphy_5401_funcs = {
|
||||
brgphy_service, brgphy_status, brgphy_5401_reset,
|
||||
};
|
||||
|
||||
const struct mii_phy_funcs brgphy_5411_funcs = {
|
||||
brgphy_service, brgphy_status, brgphy_5411_reset,
|
||||
};
|
||||
|
||||
const struct mii_phydesc brgphys[] = {
|
||||
{ MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5400,
|
||||
MII_STR_BROADCOM_BCM5400 },
|
||||
@ -127,6 +138,9 @@ const struct mii_phydesc brgphys[] = {
|
||||
NULL },
|
||||
};
|
||||
|
||||
static void bcm5401_load_dspcode(struct mii_softc *);
|
||||
static void bcm5411_load_dspcode(struct mii_softc *);
|
||||
|
||||
int
|
||||
brgphymatch(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
@ -151,11 +165,35 @@ brgphyattach(struct device *parent, struct device *self, void *aux)
|
||||
|
||||
sc->mii_inst = mii->mii_instance;
|
||||
sc->mii_phy = ma->mii_phyno;
|
||||
sc->mii_funcs = &brgphy_funcs;
|
||||
sc->mii_pdata = mii;
|
||||
sc->mii_flags = ma->mii_flags;
|
||||
sc->mii_anegticks = 5;
|
||||
|
||||
switch (MII_MODEL(ma->mii_id2)) {
|
||||
case MII_MODEL_BROADCOM_BCM5400:
|
||||
sc->mii_funcs = &brgphy_5401_funcs;
|
||||
printf("%s: using BCM5401 DSP patch\n", sc->mii_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case MII_MODEL_BROADCOM_BCM5401:
|
||||
if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) == 3) {
|
||||
sc->mii_funcs = &brgphy_5401_funcs;
|
||||
printf("%s: using BCM5401 DSP patch\n",
|
||||
sc->mii_dev.dv_xname);
|
||||
} else
|
||||
sc->mii_funcs = &brgphy_funcs;
|
||||
break;
|
||||
|
||||
case MII_MODEL_BROADCOM_BCM5411:
|
||||
sc->mii_funcs = &brgphy_5411_funcs;
|
||||
printf("%s: using BCM5411 DSP patch\n", sc->mii_dev.dv_xname);
|
||||
break;
|
||||
|
||||
default:
|
||||
sc->mii_funcs = &brgphy_funcs;
|
||||
break;
|
||||
}
|
||||
|
||||
PHY_RESET(sc);
|
||||
|
||||
sc->mii_capabilities =
|
||||
@ -204,6 +242,7 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
|
||||
break;
|
||||
|
||||
mii_phy_reset(sc); /* XXX hardware bug work-around */
|
||||
mii_phy_setmedia(sc);
|
||||
break;
|
||||
|
||||
@ -226,8 +265,19 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
/* Update the media status. */
|
||||
mii_phy_status(sc);
|
||||
|
||||
/* Callback if something changed. */
|
||||
mii_phy_update(sc, cmd);
|
||||
/*
|
||||
* Callback if something changed. Note that we need to poke
|
||||
* the DSP on the Broadcom PHYs if the media changes.
|
||||
*/
|
||||
if (sc->mii_media_active != mii->mii_media_active ||
|
||||
sc->mii_media_status != mii->mii_media_status ||
|
||||
cmd == MII_MEDIACHG) {
|
||||
mii_phy_update(sc, cmd);
|
||||
if (sc->mii_funcs == &brgphy_5401_funcs)
|
||||
bcm5401_load_dspcode(sc);
|
||||
else if (sc->mii_funcs == &brgphy_5411_funcs)
|
||||
bcm5411_load_dspcode(sc);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -309,3 +359,63 @@ brgphy_status(struct mii_softc *sc)
|
||||
} else
|
||||
mii->mii_media_active = ife->ifm_media;
|
||||
}
|
||||
|
||||
void
|
||||
brgphy_5401_reset(struct mii_softc *sc)
|
||||
{
|
||||
|
||||
mii_phy_reset(sc);
|
||||
bcm5401_load_dspcode(sc);
|
||||
}
|
||||
|
||||
void
|
||||
brgphy_5411_reset(struct mii_softc *sc)
|
||||
{
|
||||
|
||||
mii_phy_reset(sc);
|
||||
bcm5411_load_dspcode(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm5401_load_dspcode(struct mii_softc *sc)
|
||||
{
|
||||
static const struct {
|
||||
int reg;
|
||||
uint16_t val;
|
||||
} dspcode[] = {
|
||||
{ BRGPHY_MII_AUXCTL, 0x4c20 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x0012 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x1804 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x0013 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x1204 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x8006 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0132 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x8006 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0232 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x201f },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0a20 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; dspcode[i].reg != 0; i++)
|
||||
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm5411_load_dspcode(struct mii_softc *sc)
|
||||
{
|
||||
static const struct {
|
||||
int reg;
|
||||
uint16_t val;
|
||||
} dspcode[] = {
|
||||
{ 0x1c, 0x8c23 },
|
||||
{ 0x1c, 0x8ca3 },
|
||||
{ 0x1c, 0x8c23 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; dspcode[i].reg != 0; i++)
|
||||
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_bge.c,v 1.14 2002/07/12 22:29:14 enami Exp $ */
|
||||
/* $NetBSD: if_bge.c,v 1.15 2002/07/13 01:23:27 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wind River Systems
|
||||
@ -181,7 +181,6 @@ void bge_miibus_writereg(struct device *, int, int, int);
|
||||
void bge_miibus_statchg(struct device *);
|
||||
|
||||
void bge_reset(struct bge_softc *);
|
||||
void bge_phy_hack(struct bge_softc *);
|
||||
|
||||
void bge_dump_status(struct bge_softc *);
|
||||
void bge_dump_rxbd(struct bge_rx_bd *);
|
||||
@ -489,8 +488,6 @@ bge_miibus_statchg(dev)
|
||||
} else {
|
||||
BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
|
||||
}
|
||||
|
||||
bge_phy_hack(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2498,46 +2495,6 @@ bge_start(ifp)
|
||||
ifp->if_timer = 5;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a BCM5400 or BCM5401 PHY, we need to properly
|
||||
* program its internal DSP. Failing to do this can result in
|
||||
* massive packet loss at 1Gb speeds.
|
||||
*/
|
||||
void
|
||||
bge_phy_hack(sc)
|
||||
struct bge_softc *sc;
|
||||
{
|
||||
struct bge_bcom_hack bhack[] = {
|
||||
{ BRGPHY_MII_AUXCTL, 0x4C20 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x0012 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x1804 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x0013 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x1204 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x8006 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0132 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x8006 },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0232 },
|
||||
{ BRGPHY_MII_DSP_ADDR_REG, 0x201F },
|
||||
{ BRGPHY_MII_DSP_RW_PORT, 0x0A20 },
|
||||
{ 0, 0 } };
|
||||
u_int16_t vid, did;
|
||||
int i;
|
||||
|
||||
vid = bge_miibus_readreg(&sc->bge_dev, 1, MII_PHYIDR1);
|
||||
did = bge_miibus_readreg(&sc->bge_dev, 1, MII_PHYIDR2);
|
||||
|
||||
if (MII_OUI(vid, did) == MII_OUI_BROADCOM &&
|
||||
(MII_MODEL(did) == MII_MODEL_BROADCOM_BCM5400 ||
|
||||
MII_MODEL(did) == MII_MODEL_BROADCOM_BCM5401)) {
|
||||
i = 0;
|
||||
while (bhack[i].reg) {
|
||||
bge_miibus_writereg(&sc->bge_dev, 1, bhack[i].reg,
|
||||
bhack[i].val);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bge_init(ifp)
|
||||
struct ifnet *ifp;
|
||||
@ -2661,13 +2618,6 @@ bge_ifmedia_upd(ifp)
|
||||
}
|
||||
|
||||
sc->bge_link = 0;
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list))
|
||||
mii_phy_reset(miisc);
|
||||
}
|
||||
bge_phy_hack(sc);
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
|
Loading…
Reference in New Issue
Block a user