#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/bus.h>
#include <sys/sysctl.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include "mii.h"
#include "miivar.h"
#include "miidevs.h"
#include "brgphyreg.h"
#include "miibus_if.h"
static int brgphy_probe(device_t);
static int brgphy_attach(device_t);
static const struct mii_phydesc brgphys[] = {
MII_PHYDESC(xxBROADCOM, BCM5400),
MII_PHYDESC(xxBROADCOM, BCM5401),
MII_PHYDESC(xxBROADCOM, BCM5411),
MII_PHYDESC(xxBROADCOM, BCM5421),
MII_PHYDESC(xxBROADCOM, BCM54K2),
MII_PHYDESC(xxBROADCOM, BCM5461),
MII_PHYDESC(xxBROADCOM, BCM5462),
MII_PHYDESC(xxBROADCOM, BCM5464),
MII_PHYDESC(xxBROADCOM, BCM5701),
MII_PHYDESC(xxBROADCOM, BCM5703),
MII_PHYDESC(xxBROADCOM, BCM5704),
MII_PHYDESC(xxBROADCOM, BCM5705),
MII_PHYDESC(xxBROADCOM, BCM5714),
MII_PHYDESC(xxBROADCOM, BCM5750),
MII_PHYDESC(xxBROADCOM, BCM5752),
MII_PHYDESC(xxBROADCOM, BCM5780),
MII_PHYDESC(xxBROADCOM2,BCM54XX),
MII_PHYDESC(xxBROADCOM2,BCM5481),
MII_PHYDESC(xxBROADCOM2,BCM5482),
MII_PHYDESC(xxBROADCOM2,BCM5722),
MII_PHYDESC(xxBROADCOM2,BCM5755),
MII_PHYDESC(xxBROADCOM2,BCM5761),
MII_PHYDESC(xxBROADCOM2,BCM5784),
MII_PHYDESC(xxBROADCOM2,BCM5787),
MII_PHYDESC(xxBROADCOM, BCM5706C),
MII_PHYDESC(xxBROADCOM, BCM5708C),
MII_PHYDESC(xxBROADCOM2, BCM5709CAX),
MII_PHYDESC(xxBROADCOM2, BCM5709C),
MII_PHYDESC(xxBROADCOM3, BCM54640),
MII_PHYDESC(xxBROADCOM3, BCM54680),
MII_PHYDESC(xxBROADCOM3, BCM54685),
MII_PHYDESC(xxBROADCOM3, BCM54880),
MII_PHYDESC(xxBROADCOM3, BCM54881),
MII_PHYDESC(xxBROADCOM3, BCM5719C),
MII_PHYDESC(xxBROADCOM3, BCM5718C),
MII_PHYDESC(xxBROADCOM3, BCM5720C),
MII_PHYDESC(xxBROADCOM3, BCM57765),
MII_PHYDESC(xxBROADCOM3, BCM57780),
MII_PHYDESC(xxBROADCOM4, BCM5762),
MII_PHYDESC(BROADCOM2, BCM5906),
MII_PHYDESC_NULL
};
static device_method_t brgphy_methods[] = {
DEVMETHOD(device_probe, brgphy_probe),
DEVMETHOD(device_attach, brgphy_attach),
DEVMETHOD(device_detach, ukphy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD_END
};
static devclass_t brgphy_devclass;
static driver_t brgphy_driver = {
"brgphy",
brgphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, NULL, NULL);
static int brgphy_service(struct mii_softc *, struct mii_data *, int);
static void brgphy_status(struct mii_softc *);
static void brgphy_mii_phy_auto(struct mii_softc *);
static void brgphy_reset(struct mii_softc *);
static void brgphy_loop(struct mii_softc *);
static void brgphy_bcm5401_dspcode(struct mii_softc *);
static void brgphy_bcm5411_dspcode(struct mii_softc *);
static void brgphy_bcm5421_dspcode(struct mii_softc *);
static void brgphy_bcm54k2_dspcode(struct mii_softc *);
static void brgphy_adc_bug(struct mii_softc *);
static void brgphy_5704_a0_bug(struct mii_softc *);
static void brgphy_ber_bug(struct mii_softc *);
static void brgphy_crc_bug(struct mii_softc *);
static void brgphy_disable_early_dac(struct mii_softc *);
static void brgphy_jumbo_settings(struct mii_softc *, u_long);
static void brgphy_eth_wirespeed(struct mii_softc *);
static int
brgphy_probe(device_t dev)
{
struct mii_attach_args *ma = device_get_ivars(dev);
const struct mii_phydesc *mpd;
mpd = mii_phy_match(ma, brgphys);
if (mpd != NULL) {
device_set_desc(dev, mpd->mpd_name);
return (0);
}
return(ENXIO);
}
static int
brgphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
mii_softc_init(sc, ma);
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance;
sc->mii_service = brgphy_service;
sc->mii_reset = brgphy_reset;
sc->mii_pdata = mii;
sc->mii_flags |= MIIF_NOISOLATE;
mii->mii_instance++;
brgphy_reset(sc);
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
MII_MEDIA_NONE);
#if 0
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
MII_MEDIA_100_TX);
#endif
#undef ADD
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_EXTSTAT)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " ");
if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
(sc->mii_extcapabilities & EXTSR_MEDIAMASK))
mii_phy_add_media(sc);
else
kprintf("no media present");
kprintf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev);
return(0);
}
static int
brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg, speed, gig;
switch (cmd) {
case MII_POLLSTAT:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
case MII_MEDIACHG:
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
brgphy_reset(sc);
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
#ifdef foo
if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN)
return (0);
#endif
brgphy_mii_phy_auto(sc);
break;
case IFM_1000_T:
speed = BRGPHY_S1000;
goto setit;
case IFM_100_TX:
speed = BRGPHY_S100;
goto setit;
case IFM_10_T:
speed = BRGPHY_S10;
setit:
brgphy_loop(sc);
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
speed |= BRGPHY_BMCR_FDX;
gig = BRGPHY_1000CTL_AFD;
} else {
gig = BRGPHY_1000CTL_AHD;
}
PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
PHY_WRITE(sc, BRGPHY_MII_BMCR, speed);
if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
break;
PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
PHY_WRITE(sc, BRGPHY_MII_BMCR,
speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG);
if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701)
break;
if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
PHY_WRITE(sc, BRGPHY_MII_1000CTL,
gig|BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC);
} else {
PHY_WRITE(sc, BRGPHY_MII_1000CTL,
gig|BRGPHY_1000CTL_MSE);
}
break;
#ifdef foo
case IFM_NONE:
PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
break;
#endif
case IFM_100_T4:
default:
return (EINVAL);
}
break;
case MII_TICK:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
break;
reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
if (reg & BMSR_LINK) {
sc->mii_ticks = 0;
break;
}
if (++sc->mii_ticks <= sc->mii_anegticks)
break;
sc->mii_ticks = 0;
brgphy_mii_phy_auto(sc);
break;
}
brgphy_status(sc);
if (sc->mii_media_active != mii->mii_media_active ||
sc->mii_media_status != mii->mii_media_status ||
cmd == MII_MEDIACHG) {
switch (sc->mii_model) {
case MII_MODEL_xxBROADCOM_BCM5400:
brgphy_bcm5401_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM5401:
if (sc->mii_rev == 1 || sc->mii_rev == 3)
brgphy_bcm5401_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM5411:
brgphy_bcm5411_dspcode(sc);
break;
}
}
mii_phy_update(sc, cmd);
return (0);
}
static void
brgphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
int bmcr, bmsr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR);
if (bmsr & BRGPHY_BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
if (bmcr & BRGPHY_BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BRGPHY_BMCR_AUTOEN) {
int auxsts;
if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
mii->mii_media_active |= IFM_NONE;
return;
}
auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
case BRGPHY_RES_1000FD:
mii->mii_media_active |= IFM_1000_T | IFM_FDX;
break;
case BRGPHY_RES_1000HD:
mii->mii_media_active |= IFM_1000_T | IFM_HDX;
break;
case BRGPHY_RES_100FD:
mii->mii_media_active |= IFM_100_TX | IFM_FDX;
break;
case BRGPHY_RES_100T4:
mii->mii_media_active |= IFM_100_T4;
break;
case BRGPHY_RES_100HD:
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
break;
case BRGPHY_RES_10FD:
mii->mii_media_active |= IFM_10_T | IFM_FDX;
break;
case BRGPHY_RES_10HD:
mii->mii_media_active |= IFM_10_T | IFM_HDX;
break;
default:
if (sc->mii_model == MII_MODEL_BROADCOM2_BCM5906) {
mii->mii_media_active |= (auxsts &
BRGPHY_RES_100) ? IFM_100_TX : IFM_10_T;
mii->mii_media_active |= (auxsts &
BRGPHY_RES_FULL) ? IFM_FDX : IFM_HDX;
break;
}
mii->mii_media_active |= IFM_NONE;
break;
}
} else {
mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media;
}
}
static void
brgphy_mii_phy_auto(struct mii_softc *sc)
{
int ktcr;
brgphy_reset(sc);
PHY_WRITE(sc, BRGPHY_MII_ANAR,
BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
DELAY(1000);
ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
DELAY(1000);
PHY_WRITE(sc, BRGPHY_MII_BMCR,
BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
}
static void
brgphy_loop(struct mii_softc *sc)
{
uint32_t bmsr;
int i;
PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP);
for (i = 0; i < 15000; i++) {
bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
if (!(bmsr & BRGPHY_BMSR_LINK))
break;
DELAY(10);
}
}
static void
brgphy_reset(struct mii_softc *sc)
{
mii_phy_reset(sc);
switch (sc->mii_model) {
case MII_MODEL_xxBROADCOM_BCM5400:
brgphy_bcm5401_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM5401:
if (sc->mii_rev == 1 || sc->mii_rev == 3)
brgphy_bcm5401_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM5411:
brgphy_bcm5411_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM5421:
brgphy_bcm5421_dspcode(sc);
break;
case MII_MODEL_xxBROADCOM_BCM54K2:
brgphy_bcm54k2_dspcode(sc);
break;
}
if (sc->mii_privtag != MII_PRIVTAG_BRGPHY)
return;
if (sc->mii_priv & BRGPHY_FLAG_ADC_BUG)
brgphy_adc_bug(sc);
if (sc->mii_priv & BRGPHY_FLAG_5704_A0)
brgphy_5704_a0_bug(sc);
if (sc->mii_priv & BRGPHY_FLAG_BER_BUG) {
brgphy_ber_bug(sc);
} else if (sc->mii_priv & BRGPHY_FLAG_JITTER_BUG) {
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00);
PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
if (sc->mii_priv & BRGPHY_FLAG_ADJUST_TRIM) {
PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b);
PHY_WRITE(sc, BRGPHY_TEST1,
BRGPHY_TEST1_TRIM_EN | 0x4);
} else {
PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b);
}
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400);
}
if (sc->mii_priv & BRGPHY_FLAG_CRC_BUG)
brgphy_crc_bug(sc);
if (sc->mii_priv & BRGPHY_FLAG_NO_EARLYDAC)
brgphy_disable_early_dac(sc);
brgphy_jumbo_settings(sc, sc->mii_pdata->mii_ifp->if_mtu);
if (sc->mii_priv & BRGPHY_FLAG_5906)
PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
if (sc->mii_priv & BRGPHY_FLAG_5762_A0) {
PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0xffb);
PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x4000);
}
if (sc->mii_priv & BRGPHY_FLAG_WIRESPEED)
brgphy_eth_wirespeed(sc);
if (sc->mii_priv & BRGPHY_FLAG_NO_3LED) {
PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) &
~BRGPHY_PHY_EXTCTL_3_LED);
}
}
static void
brgphy_bcm5401_dspcode(struct mii_softc *sc)
{
static const struct {
int reg;
uint16_t val;
} dspcode[] = {
{ BRGPHY_MII_AUXCTL, 0x0c20 },
{ 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);
DELAY(40);
}
static void
brgphy_bcm5411_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);
}
static void
brgphy_bcm5421_dspcode(struct mii_softc *sc)
{
uint16_t data;
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007);
data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007);
data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800);
PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200);
}
static void
brgphy_bcm54k2_dspcode(struct mii_softc *sc)
{
static const struct {
int reg;
uint16_t val;
} dspcode[] = {
{ 4, 0x01e1 },
{ 9, 0x0300 },
{ 0, 0 },
};
int i;
for (i = 0; dspcode[i].reg != 0; i++)
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
}
static void
brgphy_adc_bug(struct mii_softc *sc)
{
static const struct {
int reg;
uint16_t val;
} dspcode[] = {
{ BRGPHY_MII_AUXCTL, 0x0c00 },
{ BRGPHY_MII_DSP_ADDR_REG, 0x201f },
{ BRGPHY_MII_DSP_RW_PORT, 0x2aaa },
{ BRGPHY_MII_DSP_ADDR_REG, 0x000a },
{ BRGPHY_MII_DSP_RW_PORT, 0x0323 },
{ BRGPHY_MII_AUXCTL, 0x0400 },
{ 0, 0 },
};
int i;
for (i = 0; dspcode[i].reg != 0; i++)
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
}
static void
brgphy_5704_a0_bug(struct mii_softc *sc)
{
static const struct {
int reg;
u_int16_t val;
} dspcode[] = {
{ 0x1c, 0x8d68 },
{ 0x1c, 0x8d68 },
{ 0, 0 },
};
int i;
for (i = 0; dspcode[i].reg != 0; i++)
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
}
static void
brgphy_ber_bug(struct mii_softc *sc)
{
static const struct {
int reg;
uint16_t val;
} dspcode[] = {
{ BRGPHY_MII_AUXCTL, 0x0c00 },
{ BRGPHY_MII_DSP_ADDR_REG, 0x000a },
{ BRGPHY_MII_DSP_RW_PORT, 0x310b },
{ BRGPHY_MII_DSP_ADDR_REG, 0x201f },
{ BRGPHY_MII_DSP_RW_PORT, 0x9506 },
{ BRGPHY_MII_DSP_ADDR_REG, 0x401f },
{ BRGPHY_MII_DSP_RW_PORT, 0x14e2 },
{ BRGPHY_MII_AUXCTL, 0x0400 },
{ 0, 0 },
};
int i;
for (i = 0; dspcode[i].reg != 0; i++)
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
}
static void
brgphy_crc_bug(struct mii_softc *sc)
{
static const struct {
int reg;
uint16_t val;
} dspcode[] = {
{ BRGPHY_MII_DSP_ADDR_REG, 0x0a75 },
{ 0x1c, 0x8c68 },
{ 0x1c, 0x8d68 },
{ 0x1c, 0x8c68 },
{ 0, 0 },
};
int i;
for (i = 0; dspcode[i].reg != 0; i++)
PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
}
static void
brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu)
{
uint32_t val;
if (mtu > ETHER_MAX_LEN) {
if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) {
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20);
} else {
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
val | BRGPHY_AUXCTL_LONG_PKT);
}
val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
val | BRGPHY_PHY_EXTCTL_HIGH_LA);
} else {
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7));
val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
val & ~BRGPHY_PHY_EXTCTL_HIGH_LA);
}
}
static void
brgphy_eth_wirespeed(struct mii_softc *sc)
{
u_int32_t val;
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
PHY_WRITE(sc, BRGPHY_MII_AUXCTL, (val | (1 << 15) | (1 << 4)));
}
static void
brgphy_disable_early_dac(struct mii_softc *sc)
{
uint32_t val;
PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08);
val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
val &= ~(1 << 8);
PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val);
}