[BACK]Return to brgphy.c CVS log [TXT][DIR] Up to [local] / sys / dev / mii

Annotation of sys/dev/mii/brgphy.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: brgphy.c,v 1.71 2007/01/30 02:35:16 krw Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2000
        !             5:  *     Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Bill Paul.
        !            18:  * 4. Neither the name of the author nor the names of any co-contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
        !            26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            32:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  *
        !            34:  * $FreeBSD: brgphy.c,v 1.8 2002/03/22 06:38:52 wpaul Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * Driver for the Broadcom BCR5400 1000baseTX PHY. Speed is always
        !            39:  * 1000mbps; all we need to negotiate here is full or half duplex.
        !            40:  */
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/kernel.h>
        !            45: #include <sys/device.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/timeout.h>
        !            48: #include <sys/errno.h>
        !            49:
        !            50: #include <machine/bus.h>
        !            51:
        !            52: #include <net/if.h>
        !            53: #include <net/if_media.h>
        !            54:
        !            55: #ifdef INET
        !            56: #include <netinet/in.h>
        !            57: #include <netinet/if_ether.h>
        !            58: #endif
        !            59:
        !            60: #include <dev/pci/pcivar.h>
        !            61:
        !            62: #include <dev/mii/mii.h>
        !            63: #include <dev/mii/miivar.h>
        !            64: #include <dev/mii/miidevs.h>
        !            65:
        !            66: #include <dev/mii/brgphyreg.h>
        !            67:
        !            68: #include <dev/pci/if_bgereg.h>
        !            69:
        !            70: int brgphy_probe(struct device *, void *, void *);
        !            71: void brgphy_attach(struct device *, struct device *, void *);
        !            72:
        !            73: struct cfattach brgphy_ca = {
        !            74:        sizeof(struct mii_softc), brgphy_probe, brgphy_attach, mii_phy_detach,
        !            75:            mii_phy_activate
        !            76: };
        !            77:
        !            78: struct cfdriver brgphy_cd = {
        !            79:        NULL, "brgphy", DV_DULL
        !            80: };
        !            81:
        !            82: int    brgphy_service(struct mii_softc *, struct mii_data *, int);
        !            83: void   brgphy_status(struct mii_softc *);
        !            84: int    brgphy_mii_phy_auto(struct mii_softc *);
        !            85: void   brgphy_loop(struct mii_softc *);
        !            86: void   brgphy_reset(struct mii_softc *);
        !            87: void   brgphy_bcm5401_dspcode(struct mii_softc *);
        !            88: void   brgphy_bcm5411_dspcode(struct mii_softc *);
        !            89: void   brgphy_bcm5421_dspcode(struct mii_softc *);
        !            90: void   brgphy_bcm54k2_dspcode(struct mii_softc *);
        !            91: void   brgphy_adc_bug(struct mii_softc *);
        !            92: void   brgphy_5704_a0_bug(struct mii_softc *);
        !            93: void   brgphy_ber_bug(struct mii_softc *);
        !            94: void   brgphy_jumbo_settings(struct mii_softc *);
        !            95: void   brgphy_eth_wirespeed(struct mii_softc *);
        !            96:
        !            97: const struct mii_phy_funcs brgphy_funcs = {
        !            98:        brgphy_service, brgphy_status, brgphy_reset,
        !            99: };
        !           100:
        !           101: static const struct mii_phydesc brgphys[] = {
        !           102:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5400,
        !           103:          MII_STR_xxBROADCOM_BCM5400 },
        !           104:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5401,
        !           105:          MII_STR_xxBROADCOM_BCM5401 },
        !           106:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5411,
        !           107:          MII_STR_xxBROADCOM_BCM5411 },
        !           108:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5421,
        !           109:          MII_STR_xxBROADCOM_BCM5421 },
        !           110:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM54K2,
        !           111:          MII_STR_xxBROADCOM_BCM54K2 },
        !           112:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5462,
        !           113:          MII_STR_xxBROADCOM_BCM5462 },
        !           114:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5701,
        !           115:          MII_STR_xxBROADCOM_BCM5701 },
        !           116:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5703,
        !           117:          MII_STR_xxBROADCOM_BCM5703 },
        !           118:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5704,
        !           119:          MII_STR_xxBROADCOM_BCM5704 },
        !           120:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5705,
        !           121:          MII_STR_xxBROADCOM_BCM5705 },
        !           122:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5714,
        !           123:          MII_STR_xxBROADCOM_BCM5714 },
        !           124:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5750,
        !           125:          MII_STR_xxBROADCOM_BCM5750 },
        !           126:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5752,
        !           127:          MII_STR_xxBROADCOM_BCM5752 },
        !           128:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5780,
        !           129:          MII_STR_xxBROADCOM_BCM5780 },
        !           130:        { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5755,
        !           131:          MII_STR_xxBROADCOM2_BCM5755 },
        !           132:        { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5787,
        !           133:          MII_STR_xxBROADCOM2_BCM5787 },
        !           134:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5706C,
        !           135:          MII_STR_xxBROADCOM_BCM5706C },
        !           136:        { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5708C,
        !           137:          MII_STR_xxBROADCOM_BCM5708C },
        !           138:
        !           139:        { 0,                            0,
        !           140:          NULL },
        !           141: };
        !           142:
        !           143: int
        !           144: brgphy_probe(struct device *parent, void *match, void *aux)
        !           145: {
        !           146:        struct mii_attach_args *ma = aux;
        !           147:
        !           148:        if (mii_phy_match(ma, brgphys) != NULL)
        !           149:                return (10);
        !           150:
        !           151:        return (0);
        !           152: }
        !           153:
        !           154: void
        !           155: brgphy_attach(struct device *parent, struct device *self, void *aux)
        !           156: {
        !           157:        struct mii_softc *sc = (struct mii_softc *)self;
        !           158:        struct mii_attach_args *ma = aux;
        !           159:        struct mii_data *mii = ma->mii_data;
        !           160:        const struct mii_phydesc *mpd;
        !           161:
        !           162:        mpd = mii_phy_match(ma, brgphys);
        !           163:        printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
        !           164:
        !           165:        sc->mii_inst = mii->mii_instance;
        !           166:        sc->mii_phy = ma->mii_phyno;
        !           167:        sc->mii_funcs = &brgphy_funcs;
        !           168:        sc->mii_model = MII_MODEL(ma->mii_id2);
        !           169:        sc->mii_rev = MII_REV(ma->mii_id2);
        !           170:        sc->mii_pdata = mii;
        !           171:        sc->mii_flags = ma->mii_flags;
        !           172:        sc->mii_anegticks = MII_ANEGTICKS;
        !           173:
        !           174:        sc->mii_flags |= MIIF_NOISOLATE;
        !           175:
        !           176:        PHY_RESET(sc);
        !           177:
        !           178:        sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
        !           179:        if (sc->mii_capabilities & BMSR_EXTSTAT)
        !           180:                sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
        !           181:        if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
        !           182:            (sc->mii_extcapabilities & EXTSR_MEDIAMASK))
        !           183:                mii_phy_add_media(sc);
        !           184: }
        !           185:
        !           186: int
        !           187: brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
        !           188: {
        !           189:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
        !           190:        int reg, speed, gig;
        !           191:
        !           192:        if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
        !           193:                return (ENXIO);
        !           194:
        !           195:        switch (cmd) {
        !           196:        case MII_POLLSTAT:
        !           197:                /*
        !           198:                 * If we're not polling our PHY instance, just return.
        !           199:                 */
        !           200:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
        !           201:                        return (0);
        !           202:                break;
        !           203:
        !           204:        case MII_MEDIACHG:
        !           205:                /*
        !           206:                 * If the media indicates a different PHY instance,
        !           207:                 * isolate ourselves.
        !           208:                 */
        !           209:                if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
        !           210:                        reg = PHY_READ(sc, MII_BMCR);
        !           211:                        PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
        !           212:                        return (0);
        !           213:                }
        !           214:
        !           215:                /*
        !           216:                 * If the interface is not up, don't do anything.
        !           217:                 */
        !           218:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
        !           219:                        break;
        !           220:
        !           221:                PHY_RESET(sc); /* XXX hardware bug work-around */
        !           222:
        !           223:                switch (IFM_SUBTYPE(ife->ifm_media)) {
        !           224:                case IFM_AUTO:
        !           225:                        (void) brgphy_mii_phy_auto(sc);
        !           226:                        break;
        !           227:                case IFM_1000_T:
        !           228:                        speed = BRGPHY_S1000;
        !           229:                        goto setit;
        !           230:                case IFM_100_TX:
        !           231:                        speed = BRGPHY_S100;
        !           232:                        goto setit;
        !           233:                case IFM_10_T:
        !           234:                        speed = BRGPHY_S10;
        !           235: setit:
        !           236:                        brgphy_loop(sc);
        !           237:                        if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
        !           238:                                speed |= BRGPHY_BMCR_FDX;
        !           239:                                gig = BRGPHY_1000CTL_AFD;
        !           240:                        } else {
        !           241:                                gig = BRGPHY_1000CTL_AHD;
        !           242:                        }
        !           243:
        !           244:                        PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
        !           245:                        PHY_WRITE(sc, BRGPHY_MII_BMCR, speed);
        !           246:                        PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
        !           247:
        !           248:                        if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
        !           249:                                break;
        !           250:
        !           251:                        PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
        !           252:                        PHY_WRITE(sc, BRGPHY_MII_BMCR,
        !           253:                            speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG);
        !           254:
        !           255:                        if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701)
        !           256:                                break;
        !           257:
        !           258:                        if (mii->mii_media.ifm_media & IFM_ETH_MASTER)
        !           259:                                gig |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
        !           260:                        PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
        !           261:                        break;
        !           262:                default:
        !           263:                        return (EINVAL);
        !           264:                }
        !           265:                break;
        !           266:
        !           267:        case MII_TICK:
        !           268:                /*
        !           269:                 * If we're not currently selected, just return.
        !           270:                 */
        !           271:                if (IFM_INST(ife->ifm_media) != sc->mii_inst)
        !           272:                        return (0);
        !           273:
        !           274:                /*
        !           275:                 * Is the interface even up?
        !           276:                 */
        !           277:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
        !           278:                        return (0);
        !           279:
        !           280:                /*
        !           281:                 * Only used for autonegotiation.
        !           282:                 */
        !           283:                if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
        !           284:                        break;
        !           285:
        !           286:                /*
        !           287:                 * Check to see if we have link.  If we do, we don't
        !           288:                 * need to restart the autonegotiation process.  Read
        !           289:                 * the BMSR twice in case it's latched.
        !           290:                 */
        !           291:                reg = PHY_READ(sc, BRGPHY_MII_AUXSTS);
        !           292:                if (reg & BRGPHY_AUXSTS_LINK)
        !           293:                        break;
        !           294:
        !           295:                /*
        !           296:                 * Only retry autonegotiation every mii_anegticks seconds.
        !           297:                 */
        !           298:                if (++sc->mii_ticks <= sc->mii_anegticks)
        !           299:                        break;
        !           300:
        !           301:                sc->mii_ticks = 0;
        !           302:                brgphy_mii_phy_auto(sc);
        !           303:                break;
        !           304:        }
        !           305:
        !           306:        /* Update the media status. */
        !           307:        mii_phy_status(sc);
        !           308:
        !           309:        /*
        !           310:         * Callback if something changed. Note that we need to poke the DSP on
        !           311:         * the Broadcom PHYs if the media changes.
        !           312:         */
        !           313:        if (sc->mii_media_active != mii->mii_media_active ||
        !           314:            sc->mii_media_status != mii->mii_media_status ||
        !           315:            cmd == MII_MEDIACHG) {
        !           316:                switch (sc->mii_model) {
        !           317:                case MII_MODEL_BROADCOM_BCM5400:
        !           318:                        brgphy_bcm5401_dspcode(sc);
        !           319:                        break;
        !           320:                case MII_MODEL_xxBROADCOM_BCM5401:
        !           321:                        if (sc->mii_rev == 1 || sc->mii_rev == 3)
        !           322:                                brgphy_bcm5401_dspcode(sc);
        !           323:                        break;
        !           324:                case MII_MODEL_xxBROADCOM_BCM5411:
        !           325:                        brgphy_bcm5411_dspcode(sc);
        !           326:                        break;
        !           327:                }
        !           328:        }
        !           329:
        !           330:        /* Callback if something changed. */
        !           331:        mii_phy_update(sc, cmd);
        !           332:
        !           333:        return (0);
        !           334: }
        !           335:
        !           336: void
        !           337: brgphy_status(struct mii_softc *sc)
        !           338: {
        !           339:        struct mii_data *mii = sc->mii_pdata;
        !           340:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
        !           341:        int bmsr, bmcr, gsr;
        !           342:
        !           343:        mii->mii_media_status = IFM_AVALID;
        !           344:        mii->mii_media_active = IFM_ETHER;
        !           345:
        !           346:        bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
        !           347:        if (PHY_READ(sc, BRGPHY_MII_AUXSTS) & BRGPHY_AUXSTS_LINK)
        !           348:                mii->mii_media_status |= IFM_ACTIVE;
        !           349:
        !           350:        bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
        !           351:
        !           352:        if (bmcr & BRGPHY_BMCR_LOOP)
        !           353:                mii->mii_media_active |= IFM_LOOP;
        !           354:
        !           355:        if (bmcr & BRGPHY_BMCR_AUTOEN) {
        !           356:                if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
        !           357:                        /* Erg, still trying, I guess... */
        !           358:                        mii->mii_media_active |= IFM_NONE;
        !           359:                        return;
        !           360:                }
        !           361:
        !           362:                switch (PHY_READ(sc, BRGPHY_MII_AUXSTS) &
        !           363:                        BRGPHY_AUXSTS_AN_RES) {
        !           364:                case BRGPHY_RES_1000FD:
        !           365:                        mii->mii_media_active |= IFM_1000_T | IFM_FDX;
        !           366:                        break;
        !           367:                case BRGPHY_RES_1000HD:
        !           368:                        mii->mii_media_active |= IFM_1000_T | IFM_HDX;
        !           369:                        break;
        !           370:                case BRGPHY_RES_100FD:
        !           371:                        mii->mii_media_active |= IFM_100_TX | IFM_FDX;
        !           372:                        break;
        !           373:                case BRGPHY_RES_100T4:
        !           374:                        mii->mii_media_active |= IFM_100_T4;
        !           375:                        break;
        !           376:                case BRGPHY_RES_100HD:
        !           377:                        mii->mii_media_active |= IFM_100_TX | IFM_HDX;
        !           378:                        break;
        !           379:                case BRGPHY_RES_10FD:
        !           380:                        mii->mii_media_active |= IFM_10_T | IFM_FDX;
        !           381:                        break;
        !           382:                case BRGPHY_RES_10HD:
        !           383:                        mii->mii_media_active |= IFM_10_T | IFM_HDX;
        !           384:                        break;
        !           385:                default:
        !           386:                        mii->mii_media_active |= IFM_NONE;
        !           387:                        break;
        !           388:                }
        !           389:
        !           390:                if (mii->mii_media_active & IFM_FDX)
        !           391:                        mii->mii_media_active |= mii_phy_flowstatus(sc);
        !           392:
        !           393:                gsr = PHY_READ(sc, BRGPHY_MII_1000STS);
        !           394:                if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
        !           395:                    gsr & BRGPHY_1000STS_MSR)
        !           396:                        mii->mii_media_active |= IFM_ETH_MASTER;
        !           397:
        !           398:                return;
        !           399:        }
        !           400:
        !           401:        mii->mii_media_active = ife->ifm_media;
        !           402: }
        !           403:
        !           404:
        !           405: int
        !           406: brgphy_mii_phy_auto(struct mii_softc *sc)
        !           407: {
        !           408:        int anar, ktcr = 0;
        !           409:
        !           410:        brgphy_loop(sc);
        !           411:        PHY_RESET(sc);
        !           412:        ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
        !           413:        if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
        !           414:                ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
        !           415:        PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
        !           416:        ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
        !           417:        DELAY(1000);
        !           418:        anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
        !           419:        if (sc->mii_flags & MIIF_DOPAUSE)
        !           420:                anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP;
        !           421:
        !           422:        PHY_WRITE(sc, BRGPHY_MII_ANAR, anar);
        !           423:        DELAY(1000);
        !           424:        PHY_WRITE(sc, BRGPHY_MII_BMCR,
        !           425:            BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
        !           426:        PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
        !           427:
        !           428:        return (EJUSTRETURN);
        !           429: }
        !           430:
        !           431: void
        !           432: brgphy_loop(struct mii_softc *sc)
        !           433: {
        !           434:        u_int32_t bmsr;
        !           435:        int i;
        !           436:
        !           437:        PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP);
        !           438:        for (i = 0; i < 15000; i++) {
        !           439:                bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
        !           440:                if (!(bmsr & BRGPHY_BMSR_LINK))
        !           441:                        break;
        !           442:                DELAY(10);
        !           443:        }
        !           444: }
        !           445:
        !           446: void
        !           447: brgphy_reset(struct mii_softc *sc)
        !           448: {
        !           449:        struct bge_softc *bge_sc = NULL;
        !           450:        char *devname;
        !           451:
        !           452:        devname = sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name;
        !           453:
        !           454:        mii_phy_reset(sc);
        !           455:
        !           456:        switch (sc->mii_model) {
        !           457:        case MII_MODEL_BROADCOM_BCM5400:
        !           458:                brgphy_bcm5401_dspcode(sc);
        !           459:                        break;
        !           460:        case MII_MODEL_BROADCOM_BCM5401:
        !           461:                if (sc->mii_rev == 1 || sc->mii_rev == 3)
        !           462:                        brgphy_bcm5401_dspcode(sc);
        !           463:                break;
        !           464:        case MII_MODEL_BROADCOM_BCM5411:
        !           465:                brgphy_bcm5411_dspcode(sc);
        !           466:                break;
        !           467:        case MII_MODEL_xxBROADCOM_BCM5421:
        !           468:                brgphy_bcm5421_dspcode(sc);
        !           469:                break;
        !           470:        case MII_MODEL_xxBROADCOM_BCM54K2:
        !           471:                brgphy_bcm54k2_dspcode(sc);
        !           472:                break;
        !           473:        }
        !           474:
        !           475:        if (strcmp(devname, "bge") == 0) {
        !           476:                bge_sc = sc->mii_pdata->mii_ifp->if_softc;
        !           477:
        !           478:                if (bge_sc->bge_flags & BGE_PHY_ADC_BUG)
        !           479:                        brgphy_adc_bug(sc);
        !           480:                if (bge_sc->bge_flags & BGE_PHY_5704_A0_BUG)
        !           481:                        brgphy_5704_a0_bug(sc);
        !           482:                if (bge_sc->bge_flags & BGE_PHY_BER_BUG)
        !           483:                        brgphy_ber_bug(sc);
        !           484:                else if (bge_sc->bge_flags & BGE_PHY_JITTER_BUG) {
        !           485:                        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00);
        !           486:                        PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
        !           487:
        !           488:                        if (bge_sc->bge_flags & BGE_PHY_ADJUST_TRIM) {
        !           489:                                PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT,
        !           490:                                    0x110b);
        !           491:                                PHY_WRITE(sc, BRGPHY_TEST1,
        !           492:                                    BRGPHY_TEST1_TRIM_EN | 0x4);
        !           493:                        } else {
        !           494:                                PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT,
        !           495:                                    0x010b);
        !           496:                        }
        !           497:
        !           498:                        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400);
        !           499:                }
        !           500:
        !           501:                /* Set Jumbo frame settings in the PHY. */
        !           502:                if (bge_sc->bge_flags & BGE_JUMBO_CAP)
        !           503:                        brgphy_jumbo_settings(sc);
        !           504:
        !           505:                /* Enable Ethernet@Wirespeed */
        !           506:                if (!(bge_sc->bge_flags & BGE_NO_ETH_WIRE_SPEED))
        !           507:                        brgphy_eth_wirespeed(sc);
        !           508:
        !           509:                /* Enable Link LED on Dell boxes */
        !           510:                if (bge_sc->bge_flags & BGE_NO_3LED) {
        !           511:                        PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
        !           512:                        PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL)
        !           513:                                & ~BRGPHY_PHY_EXTCTL_3_LED);
        !           514:                }
        !           515:        } else if (strcmp(devname, "bnx") == 0) {
        !           516:                brgphy_ber_bug(sc);
        !           517:
        !           518:                /* Set Jumbo frame settings in the PHY. */
        !           519:                brgphy_jumbo_settings(sc);
        !           520:
        !           521:                /* Enable Ethernet@Wirespeed */
        !           522:                brgphy_eth_wirespeed(sc);
        !           523:        }
        !           524: }
        !           525:
        !           526: /* Disable tap power management */
        !           527: void
        !           528: brgphy_bcm5401_dspcode(struct mii_softc *sc)
        !           529: {
        !           530:        static const struct {
        !           531:                int             reg;
        !           532:                uint16_t        val;
        !           533:        } dspcode[] = {
        !           534:                { BRGPHY_MII_AUXCTL,            0x0c20 },
        !           535:                { BRGPHY_MII_DSP_ADDR_REG,      0x0012 },
        !           536:                { BRGPHY_MII_DSP_RW_PORT,       0x1804 },
        !           537:                { BRGPHY_MII_DSP_ADDR_REG,      0x0013 },
        !           538:                { BRGPHY_MII_DSP_RW_PORT,       0x1204 },
        !           539:                { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
        !           540:                { BRGPHY_MII_DSP_RW_PORT,       0x0132 },
        !           541:                { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
        !           542:                { BRGPHY_MII_DSP_RW_PORT,       0x0232 },
        !           543:                { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
        !           544:                { BRGPHY_MII_DSP_RW_PORT,       0x0a20 },
        !           545:                { 0,                            0 },
        !           546:        };
        !           547:        int i;
        !           548:
        !           549:        for (i = 0; dspcode[i].reg != 0; i++)
        !           550:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           551:        DELAY(40);
        !           552: }
        !           553:
        !           554: /* Setting some undocumented voltage */
        !           555: void
        !           556: brgphy_bcm5411_dspcode(struct mii_softc *sc)
        !           557: {
        !           558:        static const struct {
        !           559:                int             reg;
        !           560:                uint16_t        val;
        !           561:        } dspcode[] = {
        !           562:                { 0x1c,                         0x8c23 },
        !           563:                { 0x1c,                         0x8ca3 },
        !           564:                { 0x1c,                         0x8c23 },
        !           565:                { 0,                            0 },
        !           566:        };
        !           567:        int i;
        !           568:
        !           569:        for (i = 0; dspcode[i].reg != 0; i++)
        !           570:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           571: }
        !           572:
        !           573: void
        !           574: brgphy_bcm5421_dspcode(struct mii_softc *sc)
        !           575: {
        !           576:        uint16_t data;
        !           577:
        !           578:        /* Set Class A mode */
        !           579:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007);
        !           580:        data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
        !           581:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400);
        !           582:
        !           583:        /* Set FFE gamma override to -0.125 */
        !           584:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007);
        !           585:        data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
        !           586:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800);
        !           587:        PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
        !           588:        data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
        !           589:        PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200);
        !           590: }
        !           591:
        !           592: void
        !           593: brgphy_bcm54k2_dspcode(struct mii_softc *sc)
        !           594: {
        !           595:        static const struct {
        !           596:                int             reg;
        !           597:                uint16_t        val;
        !           598:        } dspcode[] = {
        !           599:                { 4,                            0x01e1 },
        !           600:                { 9,                            0x0300 },
        !           601:                { 0,                            0 },
        !           602:        };
        !           603:        int i;
        !           604:
        !           605:        for (i = 0; dspcode[i].reg != 0; i++)
        !           606:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           607: }
        !           608:
        !           609: void
        !           610: brgphy_adc_bug(struct mii_softc *sc)
        !           611: {
        !           612:        static const struct {
        !           613:                int             reg;
        !           614:                uint16_t        val;
        !           615:        } dspcode[] = {
        !           616:                { BRGPHY_MII_AUXCTL,            0x0c00 },
        !           617:                { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
        !           618:                { BRGPHY_MII_DSP_RW_PORT,       0x2aaa },
        !           619:                { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
        !           620:                { BRGPHY_MII_DSP_RW_PORT,       0x0323 },
        !           621:                { BRGPHY_MII_AUXCTL,            0x0400 },
        !           622:                { 0,                            0 },
        !           623:        };
        !           624:        int i;
        !           625:
        !           626:        for (i = 0; dspcode[i].reg != 0; i++)
        !           627:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           628: }
        !           629:
        !           630: void
        !           631: brgphy_5704_a0_bug(struct mii_softc *sc)
        !           632: {
        !           633:        static const struct {
        !           634:                int             reg;
        !           635:                uint16_t        val;
        !           636:        } dspcode[] = {
        !           637:                { 0x1c,                         0x8d68 },
        !           638:                { 0x1c,                         0x8d68 },
        !           639:                { 0,                            0 },
        !           640:        };
        !           641:        int i;
        !           642:
        !           643:        for (i = 0; dspcode[i].reg != 0; i++)
        !           644:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           645: }
        !           646:
        !           647: void
        !           648: brgphy_ber_bug(struct mii_softc *sc)
        !           649: {
        !           650:        static const struct {
        !           651:                int             reg;
        !           652:                uint16_t        val;
        !           653:        } dspcode[] = {
        !           654:                { BRGPHY_MII_AUXCTL,            0x0c00 },
        !           655:                { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
        !           656:                { BRGPHY_MII_DSP_RW_PORT,       0x310b },
        !           657:                { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
        !           658:                { BRGPHY_MII_DSP_RW_PORT,       0x9506 },
        !           659:                { BRGPHY_MII_DSP_ADDR_REG,      0x401f },
        !           660:                { BRGPHY_MII_DSP_RW_PORT,       0x14e2 },
        !           661:                { BRGPHY_MII_AUXCTL,            0x0400 },
        !           662:                { 0,                            0 },
        !           663:        };
        !           664:        int i;
        !           665:
        !           666:        for (i = 0; dspcode[i].reg != 0; i++)
        !           667:                PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
        !           668: }
        !           669:
        !           670: void
        !           671: brgphy_jumbo_settings(struct mii_softc *sc)
        !           672: {
        !           673:        u_int32_t val;
        !           674:
        !           675:        /* Set Jumbo frame settings in the PHY. */
        !           676:        if (sc->mii_model == MII_MODEL_BROADCOM_BCM5401) {
        !           677:                /* Cannot do read-modify-write on the BCM5401 */
        !           678:                PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20);
        !           679:        } else {
        !           680:                PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
        !           681:                val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
        !           682:                PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
        !           683:                        val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7));
        !           684:        }
        !           685:
        !           686:        val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
        !           687:        PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
        !           688:                val & ~BRGPHY_PHY_EXTCTL_HIGH_LA);
        !           689: }
        !           690:
        !           691: void
        !           692: brgphy_eth_wirespeed(struct mii_softc *sc)
        !           693: {
        !           694:        u_int32_t val;
        !           695:
        !           696:        /* Enable Ethernet@Wirespeed */
        !           697:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
        !           698:        val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
        !           699:        PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
        !           700:                (val | (1 << 15) | (1 << 4)));
        !           701: }

CVSweb