LCOV - code coverage report
Current view: top level - dev/mii - brgphy.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 465 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: brgphy.c,v 1.105 2015/07/19 06:28:12 yuo 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             : #include <sys/param.h>
      38             : #include <sys/systm.h>
      39             : #include <sys/kernel.h>
      40             : #include <sys/device.h>
      41             : #include <sys/socket.h>
      42             : #include <sys/errno.h>
      43             : 
      44             : #include <machine/bus.h>
      45             : 
      46             : #include <net/if.h>
      47             : #include <net/if_media.h>
      48             : 
      49             : #include <netinet/in.h>
      50             : #include <netinet/if_ether.h>
      51             : 
      52             : #include <dev/pci/pcivar.h>
      53             : 
      54             : #include <dev/mii/mii.h>
      55             : #include <dev/mii/miivar.h>
      56             : #include <dev/mii/miidevs.h>
      57             : 
      58             : #include <dev/mii/brgphyreg.h>
      59             : 
      60             : #include <dev/pci/if_bgereg.h>
      61             : #include <dev/pci/if_bnxreg.h>
      62             : 
      63             : int brgphy_probe(struct device *, void *, void *);
      64             : void brgphy_attach(struct device *, struct device *, void *);
      65             : 
      66             : struct cfattach brgphy_ca = {
      67             :         sizeof(struct mii_softc), brgphy_probe, brgphy_attach, mii_phy_detach
      68             : };
      69             : 
      70             : struct cfdriver brgphy_cd = {
      71             :         NULL, "brgphy", DV_DULL
      72             : };
      73             : 
      74             : int     brgphy_service(struct mii_softc *, struct mii_data *, int);
      75             : void    brgphy_copper_status(struct mii_softc *);
      76             : void    brgphy_fiber_status(struct mii_softc *);
      77             : void    brgphy_5708s_status(struct mii_softc *);
      78             : void    brgphy_5709s_status(struct mii_softc *);
      79             : int     brgphy_mii_phy_auto(struct mii_softc *);
      80             : void    brgphy_loop(struct mii_softc *);
      81             : void    brgphy_reset(struct mii_softc *);
      82             : void    brgphy_reset_bge(struct mii_softc *);
      83             : void    brgphy_reset_bnx(struct mii_softc *);
      84             : void    brgphy_bcm5401_dspcode(struct mii_softc *);
      85             : void    brgphy_bcm5411_dspcode(struct mii_softc *);
      86             : void    brgphy_bcm5421_dspcode(struct mii_softc *);
      87             : void    brgphy_bcm54k2_dspcode(struct mii_softc *);
      88             : void    brgphy_adc_bug(struct mii_softc *);
      89             : void    brgphy_5704_a0_bug(struct mii_softc *);
      90             : void    brgphy_ber_bug(struct mii_softc *);
      91             : void    brgphy_crc_bug(struct mii_softc *);
      92             : void    brgphy_disable_early_dac(struct mii_softc *sc);
      93             : void    brgphy_jumbo_settings(struct mii_softc *);
      94             : void    brgphy_eth_wirespeed(struct mii_softc *);
      95             : 
      96             : const struct mii_phy_funcs brgphy_copper_funcs = {            
      97             :         brgphy_service, brgphy_copper_status, brgphy_reset,          
      98             : };
      99             : 
     100             : const struct mii_phy_funcs brgphy_fiber_funcs = {
     101             :         brgphy_service, brgphy_fiber_status, brgphy_reset,
     102             : };
     103             : 
     104             : const struct mii_phy_funcs brgphy_5708s_funcs = {
     105             :         brgphy_service, brgphy_5708s_status, brgphy_reset,
     106             : };
     107             : 
     108             : const struct mii_phy_funcs brgphy_5709s_funcs = {
     109             :         brgphy_service, brgphy_5709s_status, brgphy_reset,
     110             : };
     111             : 
     112             : static const struct mii_phydesc brgphys[] = {
     113             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5400,
     114             :           MII_STR_xxBROADCOM_BCM5400 },
     115             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5401,
     116             :           MII_STR_xxBROADCOM_BCM5401 },
     117             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5411,
     118             :           MII_STR_xxBROADCOM_BCM5411 },
     119             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5421,
     120             :           MII_STR_xxBROADCOM_BCM5421 },
     121             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM54K2,
     122             :           MII_STR_xxBROADCOM_BCM54K2 },
     123             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5461,
     124             :           MII_STR_xxBROADCOM_BCM5461 },
     125             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5462,
     126             :           MII_STR_xxBROADCOM_BCM5462 },
     127             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5464,
     128             :           MII_STR_xxBROADCOM_BCM5464 },
     129             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5701,
     130             :           MII_STR_xxBROADCOM_BCM5701 },
     131             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5703,
     132             :           MII_STR_xxBROADCOM_BCM5703 },
     133             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5704,
     134             :           MII_STR_xxBROADCOM_BCM5704 },
     135             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5705,
     136             :           MII_STR_xxBROADCOM_BCM5705 },
     137             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5714,
     138             :           MII_STR_xxBROADCOM_BCM5714 },
     139             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5750,
     140             :           MII_STR_xxBROADCOM_BCM5750 },
     141             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5752,
     142             :           MII_STR_xxBROADCOM_BCM5752 },
     143             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5780,
     144             :           MII_STR_xxBROADCOM_BCM5780 },
     145             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM54XX,
     146             :           MII_STR_xxBROADCOM2_BCM54XX },
     147             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5481,
     148             :           MII_STR_xxBROADCOM2_BCM5481 },
     149             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5482,
     150             :           MII_STR_xxBROADCOM2_BCM5482 },
     151             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5722,
     152             :           MII_STR_xxBROADCOM2_BCM5722 },
     153             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5755,
     154             :           MII_STR_xxBROADCOM2_BCM5755 },
     155             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5761,
     156             :           MII_STR_xxBROADCOM2_BCM5761 },
     157             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5784,
     158             :           MII_STR_xxBROADCOM2_BCM5784 },
     159             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5787,
     160             :           MII_STR_xxBROADCOM2_BCM5787 },
     161             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5706,
     162             :           MII_STR_xxBROADCOM_BCM5706 },
     163             :         { MII_OUI_xxBROADCOM,           MII_MODEL_xxBROADCOM_BCM5708C,
     164             :           MII_STR_xxBROADCOM_BCM5708C },
     165             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5708S,
     166             :           MII_STR_xxBROADCOM2_BCM5708S },
     167             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5709C,
     168             :           MII_STR_xxBROADCOM2_BCM5709C },
     169             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5709S,
     170             :           MII_STR_xxBROADCOM2_BCM5709S },
     171             :         { MII_OUI_xxBROADCOM2,          MII_MODEL_xxBROADCOM2_BCM5709CAX,
     172             :           MII_STR_xxBROADCOM2_BCM5709CAX },
     173             :         { MII_OUI_xxBROADCOM3,          MII_MODEL_xxBROADCOM3_BCM5717C,
     174             :           MII_STR_xxBROADCOM3_BCM5717C },
     175             :         { MII_OUI_xxBROADCOM3,          MII_MODEL_xxBROADCOM3_BCM5719C,
     176             :           MII_STR_xxBROADCOM3_BCM5719C },
     177             :         { MII_OUI_xxBROADCOM3,          MII_MODEL_xxBROADCOM3_BCM5720C,
     178             :           MII_STR_xxBROADCOM3_BCM5720C },
     179             :         { MII_OUI_xxBROADCOM3,          MII_MODEL_xxBROADCOM3_BCM57765,
     180             :           MII_STR_xxBROADCOM3_BCM57765 },
     181             :         { MII_OUI_xxBROADCOM3,          MII_MODEL_xxBROADCOM3_BCM57780,
     182             :           MII_STR_xxBROADCOM3_BCM57780 },
     183             :         { MII_OUI_BROADCOM2,            MII_MODEL_BROADCOM2_BCM5906,
     184             :           MII_STR_BROADCOM2_BCM5906 },
     185             : 
     186             :         { 0,                            0,
     187             :           NULL },
     188             : };
     189             : 
     190             : int
     191           0 : brgphy_probe(struct device *parent, void *match, void *aux)
     192             : {
     193           0 :         struct mii_attach_args *ma = aux;
     194             : 
     195           0 :         if (mii_phy_match(ma, brgphys) != NULL)
     196           0 :                 return (10);
     197             : 
     198           0 :         return (0);
     199           0 : }
     200             : 
     201             : void
     202           0 : brgphy_attach(struct device *parent, struct device *self, void *aux)
     203             : {
     204           0 :         struct mii_softc *sc = (struct mii_softc *)self;
     205             :         struct bge_softc *bge_sc = NULL;
     206             :         struct bnx_softc *bnx_sc = NULL;
     207           0 :         struct mii_attach_args *ma = aux;
     208           0 :         struct mii_data *mii = ma->mii_data;
     209             :         const struct mii_phydesc *mpd;
     210             :         char *devname;
     211             :         int fast_ether = 0;
     212             : 
     213           0 :         devname = sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name;
     214             : 
     215           0 :         if (strcmp(devname, "bge") == 0) {
     216           0 :                 bge_sc = mii->mii_ifp->if_softc;
     217             : 
     218           0 :                 if (bge_sc->bge_phy_flags & BGE_PHY_10_100_ONLY)
     219           0 :                         fast_ether = 1;
     220           0 :         } else if (strcmp(devname, "bnx") == 0)
     221           0 :                 bnx_sc = mii->mii_ifp->if_softc;
     222             : 
     223           0 :         mpd = mii_phy_match(ma, brgphys);
     224           0 :         printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
     225             : 
     226           0 :         sc->mii_inst = mii->mii_instance;
     227           0 :         sc->mii_phy = ma->mii_phyno;
     228           0 :         sc->mii_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
     229           0 :         sc->mii_model = MII_MODEL(ma->mii_id2);
     230           0 :         sc->mii_rev = MII_REV(ma->mii_id2);
     231           0 :         sc->mii_pdata = mii;
     232           0 :         sc->mii_flags = ma->mii_flags;
     233             : 
     234           0 :         if (sc->mii_flags & MIIF_HAVEFIBER) {
     235           0 :                 if (strcmp(devname, "bnx") == 0) {
     236           0 :                         if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5708)
     237           0 :                                 sc->mii_funcs = &brgphy_5708s_funcs;
     238           0 :                         else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709)
     239           0 :                                 sc->mii_funcs = &brgphy_5709s_funcs;
     240             :                         else
     241           0 :                                 sc->mii_funcs = &brgphy_fiber_funcs;
     242             :                 } else
     243           0 :                         sc->mii_funcs = &brgphy_fiber_funcs;
     244             :         } else
     245           0 :                 sc->mii_funcs = &brgphy_copper_funcs;
     246             : 
     247           0 :         if (fast_ether == 1)
     248           0 :                 sc->mii_anegticks = MII_ANEGTICKS;
     249             :         else
     250           0 :                 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
     251             : 
     252           0 :         sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
     253             : 
     254           0 :         PHY_RESET(sc);
     255             : 
     256           0 :         sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
     257           0 :         if (sc->mii_capabilities & BMSR_EXTSTAT)
     258           0 :                 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
     259             : 
     260             : #define ADD(m, c)       ifmedia_add(&mii->mii_media, (m), (c), NULL)
     261             : 
     262             :         /* Create an instance of Ethernet media. */
     263           0 :         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO);
     264             : 
     265             :         /* Add the supported media types */
     266           0 :         if (sc->mii_flags & MIIF_HAVEFIBER) {
     267           0 :                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
     268             :                     BMCR_S1000 | BMCR_FDX);
     269             : 
     270             :                 /*
     271             :                  * 2.5Gb support is a software enabled feature on the
     272             :                  * BCM5708S and BCM5709S controllers.
     273             :                  */
     274           0 :                 if (strcmp(devname, "bnx") == 0) {
     275           0 :                         if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG)
     276           0 :                                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX,
     277             :                                     IFM_FDX, sc->mii_inst), 0);
     278             :                 }
     279             :         } else {
     280           0 :                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
     281             :                     BMCR_S10);
     282           0 :                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
     283             :                     BMCR_S10 | BMCR_FDX);
     284           0 :                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
     285             :                     BMCR_S100);
     286           0 :                 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
     287             :                     BMCR_S100 | BMCR_FDX);
     288             : 
     289           0 :                 if (fast_ether == 0) {
     290           0 :                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
     291             :                             sc->mii_inst), BMCR_S1000);
     292           0 :                         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
     293             :                             sc->mii_inst), BMCR_S1000 | BMCR_FDX);
     294           0 :                 }
     295             :         }
     296             : 
     297           0 :         ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
     298             : 
     299             : #undef ADD
     300           0 : }
     301             : 
     302             : int
     303           0 : brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
     304             : {
     305           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     306             :         int reg, speed = 0, gig;
     307             : 
     308           0 :         if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
     309           0 :                 return (ENXIO);
     310             : 
     311           0 :         switch (cmd) {
     312             :         case MII_POLLSTAT:
     313             :                 /*
     314             :                  * If we're not polling our PHY instance, just return.
     315             :                  */
     316           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     317           0 :                         return (0);
     318             :                 break;
     319             : 
     320             :         case MII_MEDIACHG:
     321             :                 /*
     322             :                  * If the media indicates a different PHY instance,
     323             :                  * isolate ourselves.
     324             :                  */
     325           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
     326           0 :                         reg = PHY_READ(sc, MII_BMCR);
     327           0 :                         PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
     328           0 :                         return (0);
     329             :                 }
     330             : 
     331             :                 /*
     332             :                  * If the interface is not up, don't do anything.
     333             :                  */
     334           0 :                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
     335             :                         break;
     336             : 
     337           0 :                 PHY_RESET(sc); /* XXX hardware bug work-around */
     338             : 
     339           0 :                 switch (IFM_SUBTYPE(ife->ifm_media)) {
     340             :                 case IFM_AUTO:
     341           0 :                         (void) brgphy_mii_phy_auto(sc);
     342           0 :                         break;
     343             :                 case IFM_2500_SX:
     344             :                         speed = BRGPHY_5708S_BMCR_2500;
     345           0 :                         goto setit;
     346             :                 case IFM_1000_T:
     347             :                         speed = BMCR_S1000;
     348           0 :                         goto setit;
     349             :                 case IFM_100_TX:
     350             :                         speed = BMCR_S100;
     351           0 :                         goto setit;
     352             :                 case IFM_10_T:
     353           0 :                         speed = BMCR_S10;
     354             : setit:
     355           0 :                         brgphy_loop(sc);
     356           0 :                         if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
     357           0 :                                 speed |= BMCR_FDX;
     358             :                                 gig = GTCR_ADV_1000TFDX;
     359           0 :                         } else {
     360             :                                 gig = GTCR_ADV_1000THDX;
     361             :                         }
     362             : 
     363           0 :                         PHY_WRITE(sc, MII_100T2CR, 0);
     364           0 :                         PHY_WRITE(sc, MII_ANAR, ANAR_CSMA);
     365           0 :                         PHY_WRITE(sc, MII_BMCR, speed);
     366             : 
     367           0 :                         if ((IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) &&
     368           0 :                             (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_SX) &&
     369           0 :                             (IFM_SUBTYPE(ife->ifm_media) != IFM_2500_SX))
     370             :                                 break;
     371             : 
     372           0 :                         PHY_WRITE(sc, MII_100T2CR, gig);
     373           0 :                         PHY_WRITE(sc, MII_BMCR,
     374             :                             speed|BMCR_AUTOEN|BMCR_STARTNEG);
     375             : 
     376           0 :                         if (sc->mii_oui != MII_OUI_xxBROADCOM ||
     377           0 :                             sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701)
     378             :                                 break;
     379             : 
     380           0 :                         if (mii->mii_media.ifm_media & IFM_ETH_MASTER)
     381           0 :                                 gig |= GTCR_MAN_MS|GTCR_ADV_MS;
     382           0 :                         PHY_WRITE(sc, MII_100T2CR, gig);
     383           0 :                         break;
     384             :                 default:
     385           0 :                         return (EINVAL);
     386             :                 }
     387             :                 break;
     388             : 
     389             :         case MII_TICK:
     390             :                 /*
     391             :                  * If we're not currently selected, just return.
     392             :                  */
     393           0 :                 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
     394           0 :                         return (0);
     395             : 
     396             :                 /*
     397             :                  * Is the interface even up?
     398             :                  */
     399           0 :                 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
     400           0 :                         return (0);
     401             : 
     402             :                 /*
     403             :                  * Only used for autonegotiation.
     404             :                  */
     405           0 :                 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
     406             :                         break;
     407             : 
     408             :                 /*
     409             :                  * Check to see if we have link.  If we do, we don't
     410             :                  * need to restart the autonegotiation process.  Read
     411             :                  * the BMSR twice in case it's latched.
     412             :                  */
     413           0 :                 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     414           0 :                 if (reg & BMSR_LINK) {
     415           0 :                         sc->mii_ticks = 0;   /* Reset autoneg timer. */
     416           0 :                         break;
     417             :                 }
     418             : 
     419             :                 /*
     420             :                  * Only retry autonegotiation every mii_anegticks seconds.
     421             :                  */
     422           0 :                 if (++sc->mii_ticks <= sc->mii_anegticks)
     423             :                         break;
     424             : 
     425           0 :                 sc->mii_ticks = 0;
     426           0 :                 brgphy_mii_phy_auto(sc);
     427           0 :                 break;
     428             :         }
     429             : 
     430             :         /* Update the media status. */
     431           0 :         mii_phy_status(sc);
     432             : 
     433             :         /*
     434             :          * Callback if something changed. Note that we need to poke the DSP on
     435             :          * the Broadcom PHYs if the media changes.
     436             :          */
     437           0 :         if (sc->mii_media_active != mii->mii_media_active || 
     438           0 :             sc->mii_media_status != mii->mii_media_status ||
     439           0 :             cmd == MII_MEDIACHG) {
     440           0 :                 switch (sc->mii_oui) {
     441             :                 case MII_OUI_BROADCOM:
     442           0 :                         switch (sc->mii_model) {
     443             :                         case MII_MODEL_BROADCOM_BCM5400:
     444           0 :                                 brgphy_bcm5401_dspcode(sc);
     445           0 :                                 break;
     446             :                         }
     447             :                         break;
     448             :                 case MII_OUI_xxBROADCOM:
     449           0 :                         switch (sc->mii_model) {
     450             :                         case MII_MODEL_xxBROADCOM_BCM5401:
     451           0 :                                 if (sc->mii_rev == 1 || sc->mii_rev == 3)
     452           0 :                                         brgphy_bcm5401_dspcode(sc);
     453             :                                 break;
     454             :                         case MII_MODEL_xxBROADCOM_BCM5411:
     455           0 :                                 brgphy_bcm5411_dspcode(sc);
     456           0 :                                 break;
     457             :                         }
     458             :                         break;
     459             :                 }
     460             :         }
     461             : 
     462             :         /* Callback if something changed. */
     463           0 :         mii_phy_update(sc, cmd);
     464             : 
     465           0 :         return (0);
     466           0 : }
     467             : 
     468             : void
     469           0 : brgphy_copper_status(struct mii_softc *sc)
     470             : {
     471           0 :         struct mii_data *mii = sc->mii_pdata;
     472           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     473             :         int bmcr, bmsr;
     474             : 
     475           0 :         mii->mii_media_status = IFM_AVALID;
     476           0 :         mii->mii_media_active = IFM_ETHER;
     477             : 
     478           0 :         bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     479           0 :         if (bmsr & BMSR_LINK)
     480           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     481             : 
     482           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     483           0 :         if (bmcr & BMCR_LOOP)
     484           0 :                 mii->mii_media_active |= IFM_LOOP;
     485             : 
     486           0 :         if (bmcr & BMCR_AUTOEN) {
     487             :                 int auxsts;
     488             : 
     489           0 :                 if ((bmsr & BMSR_ACOMP) == 0) {
     490             :                         /* Erg, still trying, I guess... */
     491           0 :                         mii->mii_media_active |= IFM_NONE;
     492           0 :                         return;
     493             :                 }
     494             : 
     495           0 :                 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
     496             : 
     497           0 :                 switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
     498             :                 case BRGPHY_RES_1000FD:
     499           0 :                         mii->mii_media_active |= IFM_1000_T | IFM_FDX;
     500           0 :                         break;
     501             :                 case BRGPHY_RES_1000HD:
     502           0 :                         mii->mii_media_active |= IFM_1000_T | IFM_HDX;
     503           0 :                         break;
     504             :                 case BRGPHY_RES_100FD:
     505           0 :                         mii->mii_media_active |= IFM_100_TX | IFM_FDX;
     506           0 :                         break;
     507             :                 case BRGPHY_RES_100T4:
     508           0 :                         mii->mii_media_active |= IFM_100_T4 | IFM_HDX;
     509           0 :                         break;
     510             :                 case BRGPHY_RES_100HD:
     511           0 :                         mii->mii_media_active |= IFM_100_TX | IFM_HDX;
     512           0 :                         break;
     513             :                 case BRGPHY_RES_10FD:
     514           0 :                         mii->mii_media_active |= IFM_10_T | IFM_FDX;
     515           0 :                         break;
     516             :                 case BRGPHY_RES_10HD:
     517           0 :                         mii->mii_media_active |= IFM_10_T | IFM_HDX;
     518           0 :                         break;
     519             :                 default:
     520           0 :                         if (sc->mii_oui == MII_OUI_BROADCOM2 &&
     521           0 :                             sc->mii_model == MII_MODEL_BROADCOM2_BCM5906) {
     522           0 :                                 mii->mii_media_active |= (auxsts &
     523             :                                     BRGPHY_RES_100) ? IFM_100_TX : IFM_10_T;
     524           0 :                                 mii->mii_media_active |= (auxsts &
     525             :                                     BRGPHY_RES_FULL) ? IFM_FDX : IFM_HDX;
     526           0 :                                 break;
     527             :                         }
     528           0 :                         mii->mii_media_active |= IFM_NONE;
     529           0 :                         return;
     530             :                 }
     531             : 
     532           0 :                 if (mii->mii_media_active & IFM_FDX)
     533           0 :                         mii->mii_media_active |= mii_phy_flowstatus(sc);
     534             : 
     535           0 :                 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
     536           0 :                         if (PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES)
     537           0 :                                 mii->mii_media_active |= IFM_ETH_MASTER;
     538             :                 }
     539           0 :         } else
     540           0 :                 mii->mii_media_active = ife->ifm_media;
     541           0 : }
     542             : 
     543             : void
     544           0 : brgphy_fiber_status(struct mii_softc *sc)
     545             : {
     546           0 :         struct mii_data *mii = sc->mii_pdata;
     547           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     548             :         int bmcr, bmsr;
     549             : 
     550           0 :         mii->mii_media_status = IFM_AVALID;
     551           0 :         mii->mii_media_active = IFM_ETHER;
     552             : 
     553           0 :         bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     554           0 :         if (bmsr & BMSR_LINK)
     555           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     556             : 
     557           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     558           0 :         if (bmcr & BMCR_LOOP)
     559           0 :                 mii->mii_media_active |= IFM_LOOP;
     560             : 
     561           0 :         if (bmcr & BMCR_AUTOEN) {
     562             :                 int val;
     563             : 
     564           0 :                 if ((bmsr & BMSR_ACOMP) == 0) {
     565             :                         /* Erg, still trying, I guess... */
     566           0 :                         mii->mii_media_active |= IFM_NONE;
     567           0 :                         return;
     568             :                 }
     569             : 
     570           0 :                 mii->mii_media_active |= IFM_1000_SX;
     571             : 
     572           0 :                 val = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR);
     573             : 
     574           0 :                 if (val & ANAR_X_FD)
     575           0 :                         mii->mii_media_active |= IFM_FDX;
     576             :                 else
     577           0 :                         mii->mii_media_active |= IFM_HDX;
     578             : 
     579           0 :                 if (mii->mii_media_active & IFM_FDX)
     580           0 :                         mii->mii_media_active |= mii_phy_flowstatus(sc);
     581           0 :         } else
     582           0 :                 mii->mii_media_active = ife->ifm_media;
     583           0 : }
     584             : 
     585             : void
     586           0 : brgphy_5708s_status(struct mii_softc *sc)
     587             : {
     588           0 :         struct mii_data *mii = sc->mii_pdata;
     589           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     590             :         int bmcr, bmsr;
     591             : 
     592           0 :         mii->mii_media_status = IFM_AVALID;
     593           0 :         mii->mii_media_active = IFM_ETHER;
     594             : 
     595           0 :         bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     596           0 :         if (bmsr & BMSR_LINK)
     597           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     598             : 
     599           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     600           0 :         if (bmcr & BMCR_LOOP)
     601           0 :                 mii->mii_media_active |= IFM_LOOP;
     602             : 
     603           0 :         if (bmcr & BMCR_AUTOEN) {
     604             :                 int xstat;
     605             : 
     606           0 :                 if ((bmsr & BMSR_ACOMP) == 0) {
     607             :                         /* Erg, still trying, I guess... */
     608           0 :                         mii->mii_media_active |= IFM_NONE;
     609           0 :                         return;
     610             :                 }
     611             : 
     612           0 :                 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
     613             :                     BRGPHY_5708S_DIG_PG0);
     614             : 
     615           0 :                 xstat = PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1);
     616             : 
     617           0 :                 switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) {
     618             :                 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10:
     619           0 :                         mii->mii_media_active |= IFM_10_FL;
     620           0 :                         break;
     621             :                 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100:
     622           0 :                         mii->mii_media_active |= IFM_100_FX;
     623           0 :                         break;
     624             :                 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G:
     625           0 :                         mii->mii_media_active |= IFM_1000_SX;
     626           0 :                         break;
     627             :                 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G:
     628           0 :                         mii->mii_media_active |= IFM_2500_SX;
     629           0 :                         break;
     630             :                 }
     631             : 
     632           0 :                 if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_FDX)
     633           0 :                         mii->mii_media_active |= IFM_FDX;
     634             :                 else
     635           0 :                         mii->mii_media_active |= IFM_HDX;
     636             : 
     637           0 :                 if (mii->mii_media_active & IFM_FDX) {
     638           0 :                         if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_TX_PAUSE)
     639           0 :                                 mii->mii_media_active |= IFM_FLOW | IFM_ETH_TXPAUSE;
     640           0 :                         if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_RX_PAUSE)
     641           0 :                                 mii->mii_media_active |= IFM_FLOW | IFM_ETH_RXPAUSE;
     642             :                 }
     643           0 :         } else
     644           0 :                 mii->mii_media_active = ife->ifm_media;
     645           0 : }
     646             : 
     647             : void
     648           0 : brgphy_5709s_status(struct mii_softc *sc)
     649             : {
     650           0 :         struct mii_data *mii = sc->mii_pdata;
     651           0 :         struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
     652             :         int bmcr, bmsr;
     653             : 
     654           0 :         mii->mii_media_status = IFM_AVALID;
     655           0 :         mii->mii_media_active = IFM_ETHER;
     656             : 
     657           0 :         bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
     658           0 :         if (bmsr & BMSR_LINK)
     659           0 :                 mii->mii_media_status |= IFM_ACTIVE;
     660             : 
     661           0 :         bmcr = PHY_READ(sc, MII_BMCR);
     662           0 :         if (bmcr & BMCR_LOOP)
     663           0 :                 mii->mii_media_active |= IFM_LOOP;
     664             : 
     665           0 :         if (bmcr & BMCR_AUTOEN) {
     666             :                 int xstat;
     667             : 
     668           0 :                 if ((bmsr & BMSR_ACOMP) == 0) {
     669             :                         /* Erg, still trying, I guess... */
     670           0 :                         mii->mii_media_active |= IFM_NONE;
     671           0 :                         return;
     672             :                 }
     673             : 
     674           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
     675             :                     BRGPHY_BLOCK_ADDR_GP_STATUS);
     676             : 
     677           0 :                 xstat = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS);
     678             : 
     679           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
     680             :                     BRGPHY_BLOCK_ADDR_COMBO_IEEE0);
     681             : 
     682           0 :                 switch (xstat & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) {
     683             :                 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10:
     684           0 :                         mii->mii_media_active |= IFM_10_FL;
     685           0 :                         break;
     686             :                 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100:
     687           0 :                         mii->mii_media_active |= IFM_100_FX;
     688           0 :                         break;
     689             :                 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G:
     690           0 :                         mii->mii_media_active |= IFM_1000_SX;
     691           0 :                         break;
     692             :                 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G:
     693           0 :                         mii->mii_media_active |= IFM_2500_SX;
     694           0 :                         break;
     695             :                 }
     696             : 
     697           0 :                 if (xstat & BRGPHY_GP_STATUS_TOP_ANEG_FDX)
     698           0 :                         mii->mii_media_active |= IFM_FDX;
     699             :                 else
     700           0 :                         mii->mii_media_active |= IFM_HDX;
     701             : 
     702           0 :                 if (mii->mii_media_active & IFM_FDX)
     703           0 :                         mii->mii_media_active |= mii_phy_flowstatus(sc);
     704           0 :         } else
     705           0 :                 mii->mii_media_active = ife->ifm_media;
     706           0 : }
     707             : 
     708             : int
     709           0 : brgphy_mii_phy_auto(struct mii_softc *sc)
     710             : {
     711             :         int anar, ktcr = 0;
     712             : 
     713           0 :         PHY_RESET(sc);
     714             : 
     715           0 :         if (sc->mii_flags & MIIF_HAVEFIBER) {
     716             :                 anar = ANAR_X_FD | ANAR_X_HD;
     717           0 :                 if (sc->mii_flags & MIIF_DOPAUSE)
     718           0 :                         anar |= ANAR_X_PAUSE_TOWARDS;
     719           0 :                 PHY_WRITE(sc, MII_ANAR, anar);
     720           0 :         } else {
     721           0 :                 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
     722           0 :                 if (sc->mii_flags & MIIF_DOPAUSE)
     723           0 :                         anar |= ANAR_PAUSE_ASYM | ANAR_FC;
     724           0 :                 PHY_WRITE(sc, MII_ANAR, anar);
     725             :         }
     726             : 
     727             :         /* Enable speed in the 1000baseT control register */
     728             :         ktcr = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
     729           0 :         if (sc->mii_oui == MII_OUI_xxBROADCOM &&
     730           0 :             sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
     731           0 :                 ktcr |= GTCR_MAN_MS | GTCR_ADV_MS;
     732           0 :         PHY_WRITE(sc, MII_100T2CR, ktcr);
     733           0 :         ktcr = PHY_READ(sc, MII_100T2CR);
     734             : 
     735             :         /* Start autonegotiation */
     736           0 :         PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
     737           0 :         PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
     738             : 
     739           0 :         return (EJUSTRETURN);
     740             : }
     741             : 
     742             : /* Enable loopback to force the link down. */
     743             : void
     744           0 : brgphy_loop(struct mii_softc *sc)
     745             : {
     746             :         u_int32_t bmsr;
     747             :         int i;
     748             : 
     749           0 :         PHY_WRITE(sc, MII_BMCR, BMCR_LOOP);
     750           0 :         for (i = 0; i < 15000; i++) {
     751           0 :                 bmsr = PHY_READ(sc, MII_BMSR);
     752           0 :                 if (!(bmsr & BMSR_LINK))
     753             :                         break;
     754           0 :                 DELAY(10);
     755             :         }
     756           0 : }
     757             : 
     758             : void
     759           0 : brgphy_reset(struct mii_softc *sc)
     760             : {
     761             :         char *devname;
     762             : 
     763           0 :         devname = sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name;
     764             : 
     765           0 :         mii_phy_reset(sc);
     766             : 
     767           0 :         switch (sc->mii_oui) {
     768             :         case MII_OUI_BROADCOM:
     769           0 :                 switch (sc->mii_model) {
     770             :                 case MII_MODEL_BROADCOM_BCM5400:
     771           0 :                         brgphy_bcm5401_dspcode(sc);
     772           0 :                         break;
     773             :                 case MII_MODEL_BROADCOM_BCM5401:
     774           0 :                         if (sc->mii_rev == 1 || sc->mii_rev == 3)
     775           0 :                                 brgphy_bcm5401_dspcode(sc);
     776             :                         break;
     777             :                 case MII_MODEL_BROADCOM_BCM5411:
     778           0 :                         brgphy_bcm5411_dspcode(sc);
     779           0 :                         break;
     780             :                 }
     781             :                 break;
     782             :         case MII_OUI_xxBROADCOM:
     783           0 :                 switch (sc->mii_model) {
     784             :                 case MII_MODEL_xxBROADCOM_BCM5421:
     785           0 :                         brgphy_bcm5421_dspcode(sc);
     786           0 :                         break;
     787             :                 case MII_MODEL_xxBROADCOM_BCM54K2:
     788           0 :                         brgphy_bcm54k2_dspcode(sc);
     789           0 :                         break;
     790             :                 }
     791             :                 break;
     792             :         }
     793             : 
     794             :         /* Handle any bge (NetXtreme/NetLink) workarounds. */
     795           0 :         if (strcmp(devname, "bge") == 0)
     796           0 :                 brgphy_reset_bge(sc);
     797             :         /* Handle any bnx (NetXtreme II) workarounds. */
     798           0 :         else if (strcmp(devname, "bnx") == 0)
     799           0 :                 brgphy_reset_bnx(sc);
     800           0 : }
     801             : 
     802             : void
     803           0 : brgphy_reset_bge(struct mii_softc *sc)
     804             : {
     805           0 :         struct bge_softc *bge_sc = sc->mii_pdata->mii_ifp->if_softc;
     806             : 
     807           0 :         if (sc->mii_flags & MIIF_HAVEFIBER)
     808           0 :                 return;
     809             : 
     810           0 :         switch (sc->mii_oui) {
     811             :         case MII_OUI_xxBROADCOM3:
     812           0 :                 switch (sc->mii_model) {
     813             :                 case MII_MODEL_xxBROADCOM3_BCM5717C:
     814             :                 case MII_MODEL_xxBROADCOM3_BCM5719C:
     815             :                 case MII_MODEL_xxBROADCOM3_BCM5720C:
     816             :                 case MII_MODEL_xxBROADCOM3_BCM57765:
     817           0 :                         return;
     818             :                 }
     819             :         }
     820             : 
     821           0 :         if (bge_sc->bge_phy_flags & BGE_PHY_ADC_BUG)
     822           0 :                 brgphy_adc_bug(sc);
     823           0 :         if (bge_sc->bge_phy_flags & BGE_PHY_5704_A0_BUG)
     824           0 :                 brgphy_5704_a0_bug(sc);
     825           0 :         if (bge_sc->bge_phy_flags & BGE_PHY_BER_BUG)
     826           0 :                 brgphy_ber_bug(sc);
     827           0 :         else if (bge_sc->bge_phy_flags & BGE_PHY_JITTER_BUG) {
     828           0 :             PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00);
     829           0 :                 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
     830             : 
     831           0 :                 if (bge_sc->bge_phy_flags & BGE_PHY_ADJUST_TRIM) {
     832           0 :                         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b);
     833           0 :                         PHY_WRITE(sc, BRGPHY_TEST1, BRGPHY_TEST1_TRIM_EN |
     834             :                             0x4);
     835           0 :                 } else
     836           0 :                         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b);
     837             : 
     838           0 :                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400);
     839           0 :         }
     840             : 
     841           0 :         if (bge_sc->bge_phy_flags & BGE_PHY_CRC_BUG)
     842           0 :                 brgphy_crc_bug(sc);
     843             : 
     844             :         /* Set Jumbo frame settings in the PHY. */
     845           0 :         if (bge_sc->bge_flags & BGE_JUMBO_CAPABLE)
     846           0 :                 brgphy_jumbo_settings(sc);
     847             : 
     848             :         /* Adjust output voltage */
     849           0 :         if (sc->mii_oui == MII_OUI_BROADCOM2 &&
     850           0 :             sc->mii_model == MII_MODEL_BROADCOM2_BCM5906)
     851           0 :                 PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
     852             : 
     853             :         /* Enable Ethernet@Wirespeed */
     854           0 :         if (!(bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED))
     855           0 :                 brgphy_eth_wirespeed(sc);
     856             : 
     857             :         /* Enable Link LED on Dell boxes */
     858           0 :         if (bge_sc->bge_phy_flags & BGE_PHY_NO_3LED) {
     859           0 :                 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
     860             :                     PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL)
     861             :                     & ~BRGPHY_PHY_EXTCTL_3_LED);
     862           0 :         }
     863           0 : }
     864             : 
     865             : void
     866           0 : brgphy_reset_bnx(struct mii_softc *sc)
     867             : {
     868           0 :         struct bnx_softc *bnx_sc = sc->mii_pdata->mii_ifp->if_softc;
     869             : 
     870           0 :         if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5708 &&
     871           0 :             sc->mii_flags & MIIF_HAVEFIBER) {
     872             :                 /* Store autoneg capabilities/results in digital block (Page 0) */
     873           0 :                 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG3_PG2);
     874           0 :                 PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0,
     875             :                     BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE);
     876           0 :                 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0);
     877             : 
     878             :                 /* Enable fiber mode and autodetection */
     879           0 :                 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1,
     880             :                     PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1) |
     881             :                     BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN |
     882             :                     BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE);
     883             : 
     884             :                 /* Enable parallel detection */
     885           0 :                 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2,
     886             :                     PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2) |
     887             :                     BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN);
     888             : 
     889             :                 /* Advertise 2.5G support through next page during autoneg */
     890           0 :                 if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) {
     891           0 :                         PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1,
     892             :                             PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1) |
     893             :                             BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G);
     894           0 :                 }
     895             : 
     896             :                 /* Increase TX signal amplitude */
     897           0 :                 if ((BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_A0) ||
     898           0 :                     (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B0) ||
     899           0 :                     (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B1)) {
     900           0 :                         PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
     901             :                             BRGPHY_5708S_TX_MISC_PG5);
     902           0 :                         PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1,
     903             :                             PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1) &
     904             :                             ~BRGPHY_5708S_PG5_TXACTL1_VCM);
     905           0 :                         PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
     906             :                             BRGPHY_5708S_DIG_PG0);
     907           0 :                 }
     908             : 
     909             :                 /* Backplanes use special driver/pre-driver/pre-emphasis values. */
     910           0 :                 if ((bnx_sc->bnx_shared_hw_cfg & BNX_SHARED_HW_CFG_PHY_BACKPLANE) &&
     911           0 :                     (bnx_sc->bnx_port_hw_cfg & BNX_PORT_HW_CFG_CFG_TXCTL3_MASK)) {
     912           0 :                         PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
     913             :                             BRGPHY_5708S_TX_MISC_PG5);
     914           0 :                         PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3,
     915             :                             bnx_sc->bnx_port_hw_cfg &
     916             :                             BNX_PORT_HW_CFG_CFG_TXCTL3_MASK);
     917           0 :                             PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
     918             :                             BRGPHY_5708S_DIG_PG0);
     919           0 :                 }
     920           0 :         } else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709 &&
     921           0 :             sc->mii_flags & MIIF_HAVEFIBER) {
     922             :                 /* Select the SerDes Digital block of the AN MMD. */
     923           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_SERDES_DIG);
     924             : 
     925           0 :                 PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1,
     926             :                     (PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1) &
     927             :                     ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET) |
     928             :                     BRGPHY_SD_DIG_1000X_CTL1_FIBER);
     929             : 
     930           0 :                 if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) {
     931             :                         /* Select the Over 1G block of the AN MMD. */
     932           0 :                         PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
     933             :                             BRGPHY_BLOCK_ADDR_OVER_1G);
     934             : 
     935             :                         /*
     936             :                          * Enable autoneg "Next Page" to advertise
     937             :                          * 2.5G support.
     938             :                          */
     939           0 :                         PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1,
     940             :                             PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1) |
     941             :                             BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G);
     942           0 :                 }
     943             : 
     944             :                 /*
     945             :                  * Select the Multi-Rate Backplane Ethernet block of
     946             :                  * the AN MMD.
     947             :                  */
     948           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_MRBE);
     949             : 
     950             :                 /* Enable MRBE speed autoneg. */
     951           0 :                 PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP,
     952             :                     PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP) |
     953             :                     BRGPHY_MRBE_MSG_PG5_NP_MBRE |
     954             :                     BRGPHY_MRBE_MSG_PG5_NP_T2);
     955             : 
     956             :                 /* Select the Clause 73 User B0 block of the AN MMD. */
     957           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
     958             :                     BRGPHY_BLOCK_ADDR_CL73_USER_B0);
     959             : 
     960             :                 /* Enable MRBE speed autoneg. */
     961           0 :                 PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1,
     962             :                     BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP |
     963             :                     BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR |
     964             :                     BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG);
     965             : 
     966           0 :                 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
     967             :                     BRGPHY_BLOCK_ADDR_COMBO_IEEE0);
     968           0 :         } else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709) {
     969           0 :                 if (BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Ax ||
     970           0 :                     BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Bx)
     971           0 :                         brgphy_disable_early_dac(sc);
     972             : 
     973             :                 /* Set Jumbo frame settings in the PHY. */
     974           0 :                 brgphy_jumbo_settings(sc);  
     975             : 
     976             :                 /* Enable Ethernet@Wirespeed */
     977           0 :                 brgphy_eth_wirespeed(sc);   
     978           0 :         } else if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
     979           0 :                 brgphy_ber_bug(sc);
     980             : 
     981             :                 /* Set Jumbo frame settings in the PHY. */
     982           0 :                 brgphy_jumbo_settings(sc);
     983             : 
     984             :                 /* Enable Ethernet@Wirespeed */
     985           0 :                 brgphy_eth_wirespeed(sc);
     986           0 :         }
     987           0 : }
     988             : 
     989             : /* Disable tap power management */
     990             : void
     991           0 : brgphy_bcm5401_dspcode(struct mii_softc *sc)
     992             : {
     993             :         static const struct {
     994             :                 int             reg;
     995             :                 uint16_t        val;
     996             :         } dspcode[] = {
     997             :                 { BRGPHY_MII_AUXCTL,            0x0c20 },
     998             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x0012 },
     999             :                 { BRGPHY_MII_DSP_RW_PORT,       0x1804 },
    1000             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x0013 },
    1001             :                 { BRGPHY_MII_DSP_RW_PORT,       0x1204 },
    1002             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
    1003             :                 { BRGPHY_MII_DSP_RW_PORT,       0x0132 },
    1004             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x8006 },
    1005             :                 { BRGPHY_MII_DSP_RW_PORT,       0x0232 },
    1006             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
    1007             :                 { BRGPHY_MII_DSP_RW_PORT,       0x0a20 },
    1008             :                 { 0,                            0 },
    1009             :         };
    1010             :         int i;
    1011             : 
    1012           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1013           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1014           0 :         DELAY(40);
    1015           0 : }
    1016             : 
    1017             : /* Setting some undocumented voltage */
    1018             : void
    1019           0 : brgphy_bcm5411_dspcode(struct mii_softc *sc)
    1020             : {
    1021             :         static const struct {
    1022             :                 int             reg;
    1023             :                 uint16_t        val;
    1024             :         } dspcode[] = {
    1025             :                 { 0x1c,                         0x8c23 },
    1026             :                 { 0x1c,                         0x8ca3 },
    1027             :                 { 0x1c,                         0x8c23 },
    1028             :                 { 0,                            0 },
    1029             :         };
    1030             :         int i;
    1031             : 
    1032           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1033           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1034           0 : }
    1035             : 
    1036             : void
    1037           0 : brgphy_bcm5421_dspcode(struct mii_softc *sc)
    1038             : {
    1039             :         uint16_t data;
    1040             : 
    1041             :         /* Set Class A mode */
    1042           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007);
    1043           0 :         data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
    1044           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400);
    1045             : 
    1046             :         /* Set FFE gamma override to -0.125 */
    1047           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007);
    1048           0 :         data = PHY_READ(sc, BRGPHY_MII_AUXCTL);
    1049           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800);
    1050           0 :         PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a);
    1051           0 :         data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
    1052           0 :         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200);
    1053           0 : }
    1054             : 
    1055             : void
    1056           0 : brgphy_bcm54k2_dspcode(struct mii_softc *sc)
    1057             : {
    1058             :         static const struct {
    1059             :                 int             reg;
    1060             :                 uint16_t        val;
    1061             :         } dspcode[] = {
    1062             :                 { 4,                            0x01e1 },
    1063             :                 { 9,                            0x0300 },
    1064             :                 { 0,                            0 },
    1065             :         };
    1066             :         int i;
    1067             : 
    1068           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1069           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1070           0 : }
    1071             : 
    1072             : void
    1073           0 : brgphy_adc_bug(struct mii_softc *sc)
    1074             : {
    1075             :         static const struct {
    1076             :                 int             reg;
    1077             :                 uint16_t        val;
    1078             :         } dspcode[] = {
    1079             :                 { BRGPHY_MII_AUXCTL,            0x0c00 },
    1080             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
    1081             :                 { BRGPHY_MII_DSP_RW_PORT,       0x2aaa },
    1082             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
    1083             :                 { BRGPHY_MII_DSP_RW_PORT,       0x0323 },
    1084             :                 { BRGPHY_MII_AUXCTL,            0x0400 },
    1085             :                 { 0,                            0 },
    1086             :         };
    1087             :         int i;
    1088             : 
    1089           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1090           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1091           0 : }
    1092             : 
    1093             : void
    1094           0 : brgphy_5704_a0_bug(struct mii_softc *sc)
    1095             : {
    1096             :         static const struct {
    1097             :                 int             reg;
    1098             :                 uint16_t        val;
    1099             :         } dspcode[] = {
    1100             :                 { 0x1c,                         0x8d68 },
    1101             :                 { 0x1c,                         0x8d68 },
    1102             :                 { 0,                            0 },
    1103             :         };
    1104             :         int i;
    1105             : 
    1106           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1107           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1108           0 : }
    1109             : 
    1110             : void
    1111           0 : brgphy_ber_bug(struct mii_softc *sc)
    1112             : {
    1113             :         static const struct {
    1114             :                 int             reg;
    1115             :                 uint16_t        val;
    1116             :         } dspcode[] = {
    1117             :                 { BRGPHY_MII_AUXCTL,            0x0c00 },
    1118             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x000a },
    1119             :                 { BRGPHY_MII_DSP_RW_PORT,       0x310b },
    1120             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x201f },
    1121             :                 { BRGPHY_MII_DSP_RW_PORT,       0x9506 },
    1122             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x401f },
    1123             :                 { BRGPHY_MII_DSP_RW_PORT,       0x14e2 },
    1124             :                 { BRGPHY_MII_AUXCTL,            0x0400 },
    1125             :                 { 0,                            0 },
    1126             :         };
    1127             :         int i;
    1128             : 
    1129           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1130           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1131           0 : }
    1132             : 
    1133             : /* BCM5701 A0/B0 CRC bug workaround */
    1134             : void
    1135           0 : brgphy_crc_bug(struct mii_softc *sc)
    1136             : {
    1137             :         static const struct {
    1138             :                 int             reg;
    1139             :                 uint16_t        val;
    1140             :         } dspcode[] = {
    1141             :                 { BRGPHY_MII_DSP_ADDR_REG,      0x0a75 },
    1142             :                 { 0x1c,                         0x8c68 },
    1143             :                 { 0x1c,                         0x8d68 },
    1144             :                 { 0x1c,                         0x8c68 },
    1145             :                 { 0,                            0 },
    1146             :         };
    1147             :         int i;
    1148             : 
    1149           0 :         for (i = 0; dspcode[i].reg != 0; i++)
    1150           0 :                 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
    1151           0 : }
    1152             : 
    1153             : void
    1154           0 : brgphy_disable_early_dac(struct mii_softc *sc)
    1155             : {
    1156             :         uint32_t val;
    1157             : 
    1158           0 :         PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08);
    1159           0 :         val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT);
    1160           0 :         val &= ~(1 << 8);
    1161           0 :         PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val);
    1162             : 
    1163           0 : }
    1164             : 
    1165             : void
    1166           0 : brgphy_jumbo_settings(struct mii_softc *sc)
    1167             : {
    1168             :         u_int32_t val;
    1169             : 
    1170             :         /* Set Jumbo frame settings in the PHY. */
    1171           0 :         if (sc->mii_oui == MII_OUI_BROADCOM &&
    1172           0 :             sc->mii_model == MII_MODEL_BROADCOM_BCM5401) {
    1173             :                 /* Cannot do read-modify-write on the BCM5401 */
    1174           0 :                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20);
    1175           0 :         } else {
    1176           0 :                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
    1177           0 :                 val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
    1178           0 :                 PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
    1179             :                         val | BRGPHY_AUXCTL_LONG_PKT);
    1180             :         }
    1181             : 
    1182           0 :         val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
    1183           0 :         PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
    1184             :                 val | BRGPHY_PHY_EXTCTL_HIGH_LA);
    1185           0 : }
    1186             : 
    1187             : void
    1188           0 : brgphy_eth_wirespeed(struct mii_softc *sc)
    1189             : {
    1190             :         u_int32_t val;
    1191             : 
    1192             :         /* Enable Ethernet@Wirespeed */
    1193           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
    1194           0 :         val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
    1195           0 :         PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
    1196             :                 (val | (1 << 15) | (1 << 4)));
    1197           0 : }

Generated by: LCOV version 1.13