root/dev/mii/brgphy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. brgphy_probe
  2. brgphy_attach
  3. brgphy_service
  4. brgphy_status
  5. brgphy_mii_phy_auto
  6. brgphy_loop
  7. brgphy_reset
  8. brgphy_bcm5401_dspcode
  9. brgphy_bcm5411_dspcode
  10. brgphy_bcm5421_dspcode
  11. brgphy_bcm54k2_dspcode
  12. brgphy_adc_bug
  13. brgphy_5704_a0_bug
  14. brgphy_ber_bug
  15. brgphy_jumbo_settings
  16. brgphy_eth_wirespeed

    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 }

/* [<][>][^][v][top][bottom][index][help] */