The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/netif/mii_layer/brgphy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: brgphy.c,v 1.48 2006/05/20 23:03:53 brad 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: src/sys/dev/mii/brgphy.c,v 1.1.2.7 2003/05/11 18:00:55 ps Exp $
   35  */
   36 
   37 /*
   38  * Driver for the Broadcom BCR5400 1000baseT 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/socket.h>
   46 #include <sys/bus.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <net/ethernet.h>
   50 #include <net/if.h>
   51 #include <net/if_media.h>
   52 #include <net/if_arp.h>
   53 
   54 #include "mii.h"
   55 #include "miivar.h"
   56 #include "miidevs.h"
   57 #include "brgphyreg.h"
   58 
   59 #include "miibus_if.h"
   60 
   61 static int brgphy_probe(device_t);
   62 static int brgphy_attach(device_t);
   63 
   64 static const struct mii_phydesc brgphys[] = {
   65         MII_PHYDESC(xxBROADCOM, BCM5400),
   66         MII_PHYDESC(xxBROADCOM, BCM5401),
   67         MII_PHYDESC(xxBROADCOM, BCM5411),
   68         MII_PHYDESC(xxBROADCOM, BCM5421),
   69         MII_PHYDESC(xxBROADCOM, BCM54K2),
   70         MII_PHYDESC(xxBROADCOM, BCM5461),
   71         MII_PHYDESC(xxBROADCOM, BCM5462),
   72         MII_PHYDESC(xxBROADCOM, BCM5464),
   73 
   74         MII_PHYDESC(xxBROADCOM, BCM5701),
   75         MII_PHYDESC(xxBROADCOM, BCM5703),
   76         MII_PHYDESC(xxBROADCOM, BCM5704),
   77         MII_PHYDESC(xxBROADCOM, BCM5705),
   78         MII_PHYDESC(xxBROADCOM, BCM5714),
   79         MII_PHYDESC(xxBROADCOM, BCM5750),
   80         MII_PHYDESC(xxBROADCOM, BCM5752),
   81         MII_PHYDESC(xxBROADCOM, BCM5780),
   82 
   83         MII_PHYDESC(xxBROADCOM2,BCM54XX),
   84         MII_PHYDESC(xxBROADCOM2,BCM5481),
   85         MII_PHYDESC(xxBROADCOM2,BCM5482),
   86         MII_PHYDESC(xxBROADCOM2,BCM5722),
   87         MII_PHYDESC(xxBROADCOM2,BCM5755),
   88         MII_PHYDESC(xxBROADCOM2,BCM5761),
   89         MII_PHYDESC(xxBROADCOM2,BCM5784),
   90         MII_PHYDESC(xxBROADCOM2,BCM5787),
   91 
   92         MII_PHYDESC(xxBROADCOM, BCM5706C),
   93         MII_PHYDESC(xxBROADCOM, BCM5708C),
   94         MII_PHYDESC(xxBROADCOM2, BCM5709CAX),
   95         MII_PHYDESC(xxBROADCOM2, BCM5709C),
   96 
   97         MII_PHYDESC(xxBROADCOM3, BCM54640),
   98         MII_PHYDESC(xxBROADCOM3, BCM54680),
   99         MII_PHYDESC(xxBROADCOM3, BCM54685),
  100         MII_PHYDESC(xxBROADCOM3, BCM54880),
  101         MII_PHYDESC(xxBROADCOM3, BCM54881),
  102         MII_PHYDESC(xxBROADCOM3, BCM5719C),
  103         MII_PHYDESC(xxBROADCOM3, BCM5718C),
  104         MII_PHYDESC(xxBROADCOM3, BCM5720C),
  105         MII_PHYDESC(xxBROADCOM3, BCM57765),
  106         MII_PHYDESC(xxBROADCOM3, BCM57780),
  107 
  108         MII_PHYDESC(xxBROADCOM4, BCM5762),
  109 
  110         MII_PHYDESC(BROADCOM2, BCM5906),
  111 
  112         MII_PHYDESC_NULL
  113 };
  114 
  115 static device_method_t brgphy_methods[] = {
  116         /* device interface */
  117         DEVMETHOD(device_probe,         brgphy_probe),
  118         DEVMETHOD(device_attach,        brgphy_attach),
  119         DEVMETHOD(device_detach,        ukphy_detach),
  120         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  121         DEVMETHOD_END
  122 };
  123 
  124 static devclass_t brgphy_devclass;
  125 
  126 static driver_t brgphy_driver = {
  127         "brgphy",
  128         brgphy_methods,
  129         sizeof(struct mii_softc)
  130 };
  131 
  132 DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, NULL, NULL);
  133 
  134 static int      brgphy_service(struct mii_softc *, struct mii_data *, int);
  135 static void     brgphy_status(struct mii_softc *);
  136 static void     brgphy_mii_phy_auto(struct mii_softc *);
  137 static void     brgphy_reset(struct mii_softc *);
  138 static void     brgphy_loop(struct mii_softc *);
  139 
  140 static void     brgphy_bcm5401_dspcode(struct mii_softc *);
  141 static void     brgphy_bcm5411_dspcode(struct mii_softc *);
  142 static void     brgphy_bcm5421_dspcode(struct mii_softc *);
  143 static void     brgphy_bcm54k2_dspcode(struct mii_softc *);
  144 
  145 static void     brgphy_adc_bug(struct mii_softc *);
  146 static void     brgphy_5704_a0_bug(struct mii_softc *);
  147 static void     brgphy_ber_bug(struct mii_softc *);
  148 static void     brgphy_crc_bug(struct mii_softc *);
  149 
  150 static void     brgphy_disable_early_dac(struct mii_softc *);
  151 static void     brgphy_jumbo_settings(struct mii_softc *, u_long);
  152 static void     brgphy_eth_wirespeed(struct mii_softc *);
  153 
  154 static int
  155 brgphy_probe(device_t dev)
  156 {
  157         struct mii_attach_args *ma = device_get_ivars(dev);
  158         const struct mii_phydesc *mpd;
  159 
  160         mpd = mii_phy_match(ma, brgphys);
  161         if (mpd != NULL) {
  162                 device_set_desc(dev, mpd->mpd_name);
  163                 return (0);
  164         }
  165         return(ENXIO);
  166 }
  167 
  168 static int
  169 brgphy_attach(device_t dev)
  170 {
  171         struct mii_softc *sc;
  172         struct mii_attach_args *ma;
  173         struct mii_data *mii;
  174 
  175         sc = device_get_softc(dev);
  176         ma = device_get_ivars(dev);
  177         mii_softc_init(sc, ma);
  178         sc->mii_dev = device_get_parent(dev);
  179         mii = device_get_softc(sc->mii_dev);
  180         LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
  181 
  182         sc->mii_inst = mii->mii_instance;
  183         sc->mii_service = brgphy_service;
  184         sc->mii_reset = brgphy_reset;
  185         sc->mii_pdata = mii;
  186 
  187         sc->mii_flags |= MIIF_NOISOLATE;
  188         mii->mii_instance++;
  189 
  190         brgphy_reset(sc);
  191 
  192 #define ADD(m, c)       ifmedia_add(&mii->mii_media, (m), (c), NULL)
  193 
  194         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
  195             MII_MEDIA_NONE);
  196 #if 0
  197         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
  198             MII_MEDIA_100_TX);
  199 #endif
  200 
  201 #undef ADD
  202 
  203         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  204         if (sc->mii_capabilities & BMSR_EXTSTAT)
  205                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
  206 
  207         device_printf(dev, " ");
  208         if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
  209             (sc->mii_extcapabilities & EXTSR_MEDIAMASK))
  210                 mii_phy_add_media(sc);
  211         else
  212                 kprintf("no media present");
  213         kprintf("\n");
  214 
  215         MIIBUS_MEDIAINIT(sc->mii_dev);
  216         return(0);
  217 }
  218 
  219 static int
  220 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
  221 {
  222         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
  223         int reg, speed, gig;
  224 
  225         switch (cmd) {
  226         case MII_POLLSTAT:
  227                 /*
  228                  * If we're not polling our PHY instance, just return.
  229                  */
  230                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  231                         return (0);
  232                 break;
  233 
  234         case MII_MEDIACHG:
  235                 /*
  236                  * If the media indicates a different PHY instance,
  237                  * isolate ourselves.
  238                  */
  239                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
  240                         reg = PHY_READ(sc, MII_BMCR);
  241                         PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
  242                         return (0);
  243                 }
  244 
  245                 /*
  246                  * If the interface is not up, don't do anything.
  247                  */
  248                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  249                         break;
  250 
  251                 brgphy_reset(sc);       /* XXX hardware bug work-around */
  252 
  253                 switch (IFM_SUBTYPE(ife->ifm_media)) {
  254                 case IFM_AUTO:
  255 #ifdef foo
  256                         /*
  257                          * If we're already in auto mode, just return.
  258                          */
  259                         if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN)
  260                                 return (0);
  261 #endif
  262                         brgphy_mii_phy_auto(sc);
  263                         break;
  264                 case IFM_1000_T:
  265                         speed = BRGPHY_S1000;
  266                         goto setit;
  267                 case IFM_100_TX:
  268                         speed = BRGPHY_S100;
  269                         goto setit;
  270                 case IFM_10_T:
  271                         speed = BRGPHY_S10;
  272 setit:
  273                         brgphy_loop(sc);
  274                         if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
  275                                 speed |= BRGPHY_BMCR_FDX;
  276                                 gig = BRGPHY_1000CTL_AFD;
  277                         } else {
  278                                 gig = BRGPHY_1000CTL_AHD;
  279                         }
  280 
  281                         PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
  282                         PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
  283                         PHY_WRITE(sc, BRGPHY_MII_BMCR, speed);
  284 
  285                         if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
  286                                 break;
  287 
  288                         PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
  289                         PHY_WRITE(sc, BRGPHY_MII_BMCR,
  290                             speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG);
  291 
  292                         if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701)
  293                                 break;
  294 
  295                         /*
  296                          * When settning the link manually, one side must
  297                          * be the master and the other the slave. However
  298                          * ifmedia doesn't give us a good way to specify
  299                          * this, so we fake it by using one of the LINK
  300                          * flags. If LINK0 is set, we program the PHY to
  301                          * be a master, otherwise it's a slave.
  302                          */
  303                         if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
  304                                 PHY_WRITE(sc, BRGPHY_MII_1000CTL,
  305                                     gig|BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC);
  306                         } else {
  307                                 PHY_WRITE(sc, BRGPHY_MII_1000CTL,
  308                                     gig|BRGPHY_1000CTL_MSE);
  309                         }
  310                         break;
  311 #ifdef foo
  312                 case IFM_NONE:
  313                         PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
  314                         break;
  315 #endif
  316                 case IFM_100_T4:
  317                 default:
  318                         return (EINVAL);
  319                 }
  320                 break;
  321 
  322         case MII_TICK:
  323                 /*
  324                  * If we're not currently selected, just return.
  325                  */
  326                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
  327                         return (0);
  328 
  329                 /*
  330                  * Is the interface even up?
  331                  */
  332                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
  333                         return (0);
  334 
  335                 /*
  336                  * Only used for autonegotiation.
  337                  */
  338                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
  339                         break;
  340 
  341                 /*
  342                  * Check to see if we have link.  If we do, we don't
  343                  * need to restart the autonegotiation process.  Read
  344                  * the BMSR twice in case it's latched.
  345                  */
  346                 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
  347                 if (reg & BMSR_LINK) {
  348                         sc->mii_ticks = 0;
  349                         break;
  350                 }
  351 
  352                 /*
  353                  * Only retry autonegotiation every 5 seconds.
  354                  */
  355                 if (++sc->mii_ticks <= sc->mii_anegticks)
  356                         break;
  357 
  358                 sc->mii_ticks = 0;
  359                 brgphy_mii_phy_auto(sc);
  360                 break;
  361         }
  362 
  363         /* Update the media status. */
  364         brgphy_status(sc);
  365 
  366         /*
  367          * Callback if something changed. Note that we need to poke
  368          * the DSP on the Broadcom PHYs if the media changes.
  369          */
  370         if (sc->mii_media_active != mii->mii_media_active ||
  371             sc->mii_media_status != mii->mii_media_status ||
  372             cmd == MII_MEDIACHG) {
  373                 switch (sc->mii_model) {
  374                 case MII_MODEL_xxBROADCOM_BCM5400:
  375                         brgphy_bcm5401_dspcode(sc);
  376                         break;
  377                 case MII_MODEL_xxBROADCOM_BCM5401:
  378                         if (sc->mii_rev == 1 || sc->mii_rev == 3)
  379                                 brgphy_bcm5401_dspcode(sc);
  380                         break;
  381                 case MII_MODEL_xxBROADCOM_BCM5411:
  382                         brgphy_bcm5411_dspcode(sc);
  383                         break;
  384                 }
  385         }
  386         mii_phy_update(sc, cmd);
  387         return (0);
  388 }
  389 
  390 static void
  391 brgphy_status(struct mii_softc *sc)
  392 {
  393         struct mii_data *mii = sc->mii_pdata;
  394         int bmcr, bmsr;
  395 
  396         mii->mii_media_status = IFM_AVALID;
  397         mii->mii_media_active = IFM_ETHER;
  398 
  399         bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR);
  400         if (bmsr & BRGPHY_BMSR_LINK)
  401                 mii->mii_media_status |= IFM_ACTIVE;
  402 
  403         bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
  404         if (bmcr & BRGPHY_BMCR_LOOP)
  405                 mii->mii_media_active |= IFM_LOOP;
  406 
  407         if (bmcr & BRGPHY_BMCR_AUTOEN) {
  408                 int auxsts;
  409 
  410                 if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
  411                         /* Erg, still trying, I guess... */
  412                         mii->mii_media_active |= IFM_NONE;
  413                         return;
  414                 }
  415 
  416                 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
  417 
  418                 switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
  419                 case BRGPHY_RES_1000FD:
  420                         mii->mii_media_active |= IFM_1000_T | IFM_FDX;
  421                         break;
  422                 case BRGPHY_RES_1000HD:
  423                         mii->mii_media_active |= IFM_1000_T | IFM_HDX;
  424                         break;
  425                 case BRGPHY_RES_100FD:
  426                         mii->mii_media_active |= IFM_100_TX | IFM_FDX;
  427                         break;
  428                 case BRGPHY_RES_100T4:
  429                         mii->mii_media_active |= IFM_100_T4;
  430                         break;
  431                 case BRGPHY_RES_100HD:
  432                         mii->mii_media_active |= IFM_100_TX | IFM_HDX;
  433                         break;
  434                 case BRGPHY_RES_10FD:
  435                         mii->mii_media_active |= IFM_10_T | IFM_FDX;
  436                         break;
  437                 case BRGPHY_RES_10HD:
  438                         mii->mii_media_active |= IFM_10_T | IFM_HDX;
  439                         break;
  440                 default:
  441                         if (sc->mii_model == MII_MODEL_BROADCOM2_BCM5906) {
  442                                 mii->mii_media_active |= (auxsts &
  443                                     BRGPHY_RES_100) ? IFM_100_TX : IFM_10_T;
  444                                 mii->mii_media_active |= (auxsts &
  445                                     BRGPHY_RES_FULL) ? IFM_FDX : IFM_HDX;
  446                                 break;
  447                         }
  448                         mii->mii_media_active |= IFM_NONE;
  449                         break;
  450                 }
  451         } else {
  452                 mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media;
  453         }
  454 }
  455 
  456 
  457 static void
  458 brgphy_mii_phy_auto(struct mii_softc *sc)
  459 {
  460         int ktcr;
  461 
  462         brgphy_reset(sc);
  463 
  464         PHY_WRITE(sc, BRGPHY_MII_ANAR,
  465             BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
  466         DELAY(1000);
  467 
  468         ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
  469         if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
  470                 ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
  471         PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
  472         ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
  473         DELAY(1000);
  474 
  475         PHY_WRITE(sc, BRGPHY_MII_BMCR,
  476             BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
  477         PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
  478 }
  479 
  480 static void
  481 brgphy_loop(struct mii_softc *sc)
  482 {
  483         uint32_t bmsr;
  484         int i;
  485 
  486         PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP);
  487         for (i = 0; i < 15000; i++) {
  488                 bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
  489                 if (!(bmsr & BRGPHY_BMSR_LINK))
  490                         break;
  491                 DELAY(10);
  492         }
  493 }
  494 
  495 static void
  496 brgphy_reset(struct mii_softc *sc)
  497 {
  498         mii_phy_reset(sc);
  499 
  500         switch (sc->mii_model) {
  501         case MII_MODEL_xxBROADCOM_BCM5400:
  502                 brgphy_bcm5401_dspcode(sc);
  503                         break;
  504         case MII_MODEL_xxBROADCOM_BCM5401:
  505                 if (sc->mii_rev == 1 || sc->mii_rev == 3)
  506                         brgphy_bcm5401_dspcode(sc);
  507                 break;
  508         case MII_MODEL_xxBROADCOM_BCM5411:
  509                 brgphy_bcm5411_dspcode(sc);
  510                 break;
  511         case MII_MODEL_xxBROADCOM_BCM5421:
  512                 brgphy_bcm5421_dspcode(sc);
  513                 break;
  514         case MII_MODEL_xxBROADCOM_BCM54K2:
  515                 brgphy_bcm54k2_dspcode(sc);
  516                 break;
  517         }
  518 
  519         if (sc->mii_privtag != MII_PRIVTAG_BRGPHY)
  520                 return;
  521 
  522         if (sc->mii_priv & BRGPHY_FLAG_ADC_BUG)
  523                 brgphy_adc_bug(sc);
  524         if (sc->mii_priv & BRGPHY_FLAG_5704_A0)
  525                 brgphy_5704_a0_bug(sc);
  526         if (sc->mii_priv & BRGPHY_FLAG_BER_BUG) {
  527                 brgphy_ber_bug(sc);
  528         } else if (sc->mii_priv & BRGPHY_FLAG_JITTER_BUG) {
  529                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00);
  530                 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
  531 
  532                 if (sc->mii_priv & BRGPHY_FLAG_ADJUST_TRIM) {
  533                         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b);
  534                         PHY_WRITE(sc, BRGPHY_TEST1,
  535                             BRGPHY_TEST1_TRIM_EN | 0x4);
  536                 } else {
  537                         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b);
  538                 }
  539 
  540                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400);
  541         }
  542         if (sc->mii_priv & BRGPHY_FLAG_CRC_BUG)
  543                 brgphy_crc_bug(sc);
  544         if (sc->mii_priv & BRGPHY_FLAG_NO_EARLYDAC)
  545                 brgphy_disable_early_dac(sc);
  546 
  547         /* Set Jumbo frame settings in the PHY. */
  548         brgphy_jumbo_settings(sc, sc->mii_pdata->mii_ifp->if_mtu);
  549 
  550         /* Adjust output voltage */
  551         if (sc->mii_priv & BRGPHY_FLAG_5906)
  552                 PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
  553 
  554         if (sc->mii_priv & BRGPHY_FLAG_5762_A0) {
  555                 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0xffb);
  556                 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x4000);
  557         }
  558 
  559         /* Enable Ethernet@Wirespeed */
  560         if (sc->mii_priv & BRGPHY_FLAG_WIRESPEED)
  561                 brgphy_eth_wirespeed(sc);
  562 
  563         /* Enable Link LED on Dell boxes */
  564         if (sc->mii_priv & BRGPHY_FLAG_NO_3LED) {
  565                 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
  566                     PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) &
  567                     ~BRGPHY_PHY_EXTCTL_3_LED);
  568         }
  569 }
  570 
  571 /* Turn off tap power management on 5401. */
  572 static void
  573 brgphy_bcm5401_dspcode(struct mii_softc *sc)
  574 {
  575         static const struct {
  576                 int             reg;
  577                 uint16_t        val;
  578         } dspcode[] = {
  579                 { BRGPHY_MII_AUXCTL,            0x0c20 },
  580                 { BRGPHY_MII_DSP_ADDR_REG,      0x0012 },
  581                 { BRGPHY_MII_DSP_RW_PORT,       0x1804 },
  582                 { BRGPHY_MII_DSP_ADDR_REG,      0x0013 },
  583                 { BRGPHY_MII_DSP_RW_PORT,       0x1204 },
  584                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
  585                 { BRGPHY_MII_DSP_RW_PORT,       0x0132 },
  586                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
  587                 { BRGPHY_MII_DSP_RW_PORT,       0x0232 },
  588                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
  589                 { BRGPHY_MII_DSP_RW_PORT,       0x0a20 },
  590                 { 0,                            0 },
  591         };
  592         int i;
  593 
  594         for (i = 0; dspcode[i].reg != 0; i++)
  595                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  596         DELAY(40);
  597 }
  598 
  599 /* Setting some undocumented voltage */
  600 static void
  601 brgphy_bcm5411_dspcode(struct mii_softc *sc)
  602 {
  603         static const struct {
  604                 int             reg;
  605                 uint16_t        val;
  606         } dspcode[] = {
  607                 { 0x1c,                         0x8c23 },
  608                 { 0x1c,                         0x8ca3 },
  609                 { 0x1c,                         0x8c23 },
  610                 { 0,                            0 },
  611         };
  612         int i;
  613 
  614         for (i = 0; dspcode[i].reg != 0; i++)
  615                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  616 }
  617 
  618 static void
  619 brgphy_bcm5421_dspcode(struct mii_softc *sc)
  620 {
  621         uint16_t data;
  622 
  623         /* Set Class A mode */
  624         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007);
  625         data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
  626         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400);
  627 
  628         /* Set FFE gamma override to -0.125 */
  629         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007);
  630         data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
  631         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800);
  632         PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
  633         data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
  634         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200);
  635 }
  636 
  637 static void
  638 brgphy_bcm54k2_dspcode(struct mii_softc *sc)
  639 {
  640         static const struct {
  641                 int             reg;
  642                 uint16_t        val;
  643         } dspcode[] = {
  644                 { 4,                            0x01e1 },
  645                 { 9,                            0x0300 },
  646                 { 0,                            0 },
  647         };
  648         int i;
  649 
  650         for (i = 0; dspcode[i].reg != 0; i++)
  651                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  652 }
  653 
  654 static void
  655 brgphy_adc_bug(struct mii_softc *sc)
  656 {
  657         static const struct {
  658                 int             reg;
  659                 uint16_t        val;
  660         } dspcode[] = {
  661                 { BRGPHY_MII_AUXCTL,            0x0c00 },
  662                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
  663                 { BRGPHY_MII_DSP_RW_PORT,       0x2aaa },
  664                 { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
  665                 { BRGPHY_MII_DSP_RW_PORT,       0x0323 },
  666                 { BRGPHY_MII_AUXCTL,            0x0400 },
  667                 { 0,                            0 },
  668         };
  669         int i;
  670 
  671         for (i = 0; dspcode[i].reg != 0; i++)
  672                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  673 }
  674 
  675 static void
  676 brgphy_5704_a0_bug(struct mii_softc *sc)
  677 {
  678         static const struct {
  679                 int             reg;
  680                 u_int16_t       val;
  681         } dspcode[] = {
  682                 { 0x1c,                         0x8d68 },
  683                 { 0x1c,                         0x8d68 },
  684                 { 0,                            0 },
  685         };
  686         int i;
  687 
  688         for (i = 0; dspcode[i].reg != 0; i++)
  689                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  690 }
  691 
  692 static void
  693 brgphy_ber_bug(struct mii_softc *sc)
  694 {
  695         static const struct {
  696                 int             reg;
  697                 uint16_t        val;
  698         } dspcode[] = {
  699                 { BRGPHY_MII_AUXCTL,            0x0c00 },
  700                 { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
  701                 { BRGPHY_MII_DSP_RW_PORT,       0x310b },
  702                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
  703                 { BRGPHY_MII_DSP_RW_PORT,       0x9506 },
  704                 { BRGPHY_MII_DSP_ADDR_REG,      0x401f },
  705                 { BRGPHY_MII_DSP_RW_PORT,       0x14e2 },
  706                 { BRGPHY_MII_AUXCTL,            0x0400 },
  707                 { 0,                            0 },
  708         };
  709         int i;
  710 
  711         for (i = 0; dspcode[i].reg != 0; i++)
  712                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  713 }
  714 
  715 static void
  716 brgphy_crc_bug(struct mii_softc *sc)
  717 {
  718         static const struct {
  719                 int             reg;
  720                 uint16_t        val;
  721         } dspcode[] = {
  722                 { BRGPHY_MII_DSP_ADDR_REG,      0x0a75 },
  723                 { 0x1c,                         0x8c68 },
  724                 { 0x1c,                         0x8d68 },
  725                 { 0x1c,                         0x8c68 },
  726                 { 0,                            0 },
  727         };
  728         int i;
  729 
  730         for (i = 0; dspcode[i].reg != 0; i++)
  731                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
  732 }
  733 
  734 static void
  735 brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu)
  736 {
  737         uint32_t val;
  738 
  739         /* Set or clear jumbo frame settings in the PHY. */
  740         if (mtu > ETHER_MAX_LEN) {
  741                 if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) {
  742                         /* BCM5401 PHY cannot read-modify-write. */
  743                         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20);
  744                 } else {
  745                         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
  746                         val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
  747                         PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
  748                             val | BRGPHY_AUXCTL_LONG_PKT);
  749                 }
  750 
  751                 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
  752                 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
  753                     val | BRGPHY_PHY_EXTCTL_HIGH_LA);
  754         } else {
  755                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
  756                 val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
  757                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
  758                     val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7));
  759 
  760                 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
  761                 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
  762                     val & ~BRGPHY_PHY_EXTCTL_HIGH_LA);
  763         }
  764 }
  765 
  766 static void
  767 brgphy_eth_wirespeed(struct mii_softc *sc)
  768 {
  769         u_int32_t val;
  770 
  771         /* Enable Ethernet@Wirespeed */
  772         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
  773         val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
  774         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, (val | (1 << 15) | (1 << 4)));
  775 }
  776 
  777 static void
  778 brgphy_disable_early_dac(struct mii_softc *sc)
  779 {
  780         uint32_t val;
  781 
  782         PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08);
  783         val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
  784         val &= ~(1 << 8);
  785         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val);
  786 }

Cache object: 629d68c3656751c81658c9deb4931258


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.