1 1.91 msaitoh /* $NetBSD: brgphy.c,v 1.91 2023/02/22 08:09:09 msaitoh Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /*- 4 1.1 thorpej * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.1 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 thorpej * NASA Ames Research Center. 10 1.1 thorpej * 11 1.1 thorpej * Redistribution and use in source and binary forms, with or without 12 1.1 thorpej * modification, are permitted provided that the following conditions 13 1.1 thorpej * are met: 14 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.1 thorpej * notice, this list of conditions and the following disclaimer. 16 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.1 thorpej * documentation and/or other materials provided with the distribution. 19 1.1 thorpej * 20 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.1 thorpej */ 32 1.1 thorpej 33 1.1 thorpej /* 34 1.1 thorpej * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 35 1.1 thorpej * 36 1.1 thorpej * Redistribution and use in source and binary forms, with or without 37 1.1 thorpej * modification, are permitted provided that the following conditions 38 1.1 thorpej * are met: 39 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 40 1.1 thorpej * notice, this list of conditions and the following disclaimer. 41 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 43 1.1 thorpej * documentation and/or other materials provided with the distribution. 44 1.1 thorpej * 45 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 1.1 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 1.1 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 1.1 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 1.1 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 1.1 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 1.1 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 1.1 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 1.1 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 1.1 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 1.1 thorpej */ 56 1.1 thorpej 57 1.1 thorpej /* 58 1.57 jym * driver for the Broadcom BCM5400 and BCM5700 Gig-E PHYs. 59 1.1 thorpej * 60 1.1 thorpej * Programming information for this PHY was gleaned from FreeBSD 61 1.1 thorpej * (they were apparently able to get a datasheet from Broadcom). 62 1.1 thorpej */ 63 1.5 lukem 64 1.5 lukem #include <sys/cdefs.h> 65 1.91 msaitoh __KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.91 2023/02/22 08:09:09 msaitoh Exp $"); 66 1.1 thorpej 67 1.1 thorpej #include <sys/param.h> 68 1.1 thorpej #include <sys/systm.h> 69 1.1 thorpej #include <sys/kernel.h> 70 1.1 thorpej #include <sys/device.h> 71 1.1 thorpej #include <sys/socket.h> 72 1.1 thorpej #include <sys/errno.h> 73 1.44 msaitoh #include <prop/proplib.h> 74 1.1 thorpej 75 1.1 thorpej #include <net/if.h> 76 1.1 thorpej #include <net/if_media.h> 77 1.1 thorpej 78 1.1 thorpej #include <dev/mii/mii.h> 79 1.1 thorpej #include <dev/mii/miivar.h> 80 1.1 thorpej #include <dev/mii/miidevs.h> 81 1.1 thorpej #include <dev/mii/brgphyreg.h> 82 1.1 thorpej 83 1.43 msaitoh #include <dev/pci/if_bgereg.h> 84 1.43 msaitoh #include <dev/pci/if_bnxreg.h> 85 1.43 msaitoh 86 1.39 xtraeme static int brgphymatch(device_t, cfdata_t, void *); 87 1.39 xtraeme static void brgphyattach(device_t, device_t, void *); 88 1.1 thorpej 89 1.44 msaitoh struct brgphy_softc { 90 1.44 msaitoh struct mii_softc sc_mii; 91 1.54 dyoung bool sc_isbge; 92 1.54 dyoung bool sc_isbnx; 93 1.71 msaitoh uint32_t sc_chipid; /* parent's chipid */ 94 1.71 msaitoh uint32_t sc_phyflags; /* parent's phyflags */ 95 1.71 msaitoh uint32_t sc_shared_hwcfg; /* shared hw config */ 96 1.71 msaitoh uint32_t sc_port_hwcfg; /* port specific hw config */ 97 1.44 msaitoh }; 98 1.44 msaitoh 99 1.89 thorpej CFATTACH_DECL_NEW(brgphy, sizeof(struct brgphy_softc), 100 1.89 thorpej brgphymatch, brgphyattach, mii_phy_detach, mii_phy_activate); 101 1.1 thorpej 102 1.21 thorpej static int brgphy_service(struct mii_softc *, struct mii_data *, int); 103 1.71 msaitoh static void brgphy_copper_status(struct mii_softc *); 104 1.71 msaitoh static void brgphy_fiber_status(struct mii_softc *); 105 1.71 msaitoh static void brgphy_5708s_status(struct mii_softc *); 106 1.71 msaitoh static void brgphy_5709s_status(struct mii_softc *); 107 1.32 msaitoh static int brgphy_mii_phy_auto(struct mii_softc *); 108 1.32 msaitoh static void brgphy_loop(struct mii_softc *); 109 1.43 msaitoh static void brgphy_reset(struct mii_softc *); 110 1.43 msaitoh static void brgphy_bcm5401_dspcode(struct mii_softc *); 111 1.43 msaitoh static void brgphy_bcm5411_dspcode(struct mii_softc *); 112 1.43 msaitoh static void brgphy_bcm5421_dspcode(struct mii_softc *); 113 1.43 msaitoh static void brgphy_bcm54k2_dspcode(struct mii_softc *); 114 1.43 msaitoh static void brgphy_adc_bug(struct mii_softc *); 115 1.43 msaitoh static void brgphy_5704_a0_bug(struct mii_softc *); 116 1.43 msaitoh static void brgphy_ber_bug(struct mii_softc *); 117 1.43 msaitoh static void brgphy_crc_bug(struct mii_softc *); 118 1.58 jym static void brgphy_disable_early_dac(struct mii_softc *); 119 1.52 msaitoh static void brgphy_jumbo_settings(struct mii_softc *); 120 1.52 msaitoh static void brgphy_eth_wirespeed(struct mii_softc *); 121 1.90 jmcneill static void brgphy_bcm54xx_clock_delay(struct mii_softc *); 122 1.10 thorpej 123 1.71 msaitoh static const struct mii_phy_funcs brgphy_copper_funcs = { 124 1.71 msaitoh brgphy_service, brgphy_copper_status, brgphy_reset, 125 1.71 msaitoh }; 126 1.71 msaitoh 127 1.71 msaitoh static const struct mii_phy_funcs brgphy_fiber_funcs = { 128 1.71 msaitoh brgphy_service, brgphy_fiber_status, brgphy_reset, 129 1.71 msaitoh }; 130 1.71 msaitoh 131 1.71 msaitoh static const struct mii_phy_funcs brgphy_5708s_funcs = { 132 1.71 msaitoh brgphy_service, brgphy_5708s_status, brgphy_reset, 133 1.71 msaitoh }; 134 1.71 msaitoh 135 1.71 msaitoh static const struct mii_phy_funcs brgphy_5709s_funcs = { 136 1.71 msaitoh brgphy_service, brgphy_5709s_status, brgphy_reset, 137 1.34 markd }; 138 1.34 markd 139 1.21 thorpej static const struct mii_phydesc brgphys[] = { 140 1.81 christos MII_PHY_DESC(BROADCOM, BCM5400), 141 1.81 christos MII_PHY_DESC(BROADCOM, BCM5401), 142 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5402), 143 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5404), 144 1.81 christos MII_PHY_DESC(BROADCOM, BCM5411), 145 1.81 christos MII_PHY_DESC(BROADCOM, BCM5421), 146 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5424), 147 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5461), 148 1.81 christos MII_PHY_DESC(BROADCOM, BCM5462), 149 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5464), 150 1.82 msaitoh MII_PHY_DESC(BROADCOM, BCM5466), 151 1.81 christos MII_PHY_DESC(BROADCOM, BCM54K2), 152 1.81 christos MII_PHY_DESC(BROADCOM, BCM5701), 153 1.81 christos MII_PHY_DESC(BROADCOM, BCM5703), 154 1.81 christos MII_PHY_DESC(BROADCOM, BCM5704), 155 1.81 christos MII_PHY_DESC(BROADCOM, BCM5705), 156 1.81 christos MII_PHY_DESC(BROADCOM, BCM5706), 157 1.81 christos MII_PHY_DESC(BROADCOM, BCM5714), 158 1.81 christos MII_PHY_DESC(BROADCOM, BCM5750), 159 1.81 christos MII_PHY_DESC(BROADCOM, BCM5752), 160 1.81 christos MII_PHY_DESC(BROADCOM, BCM5780), 161 1.81 christos MII_PHY_DESC(BROADCOM, BCM5708C), 162 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5481), 163 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5482), 164 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5708S), 165 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5709C), 166 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5709S), 167 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5709CAX), 168 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5722), 169 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5754), 170 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5755), 171 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5756), 172 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5761), 173 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5784), 174 1.81 christos MII_PHY_DESC(BROADCOM2, BCM5785), 175 1.81 christos MII_PHY_DESC(BROADCOM3, BCM5717C), 176 1.81 christos MII_PHY_DESC(BROADCOM3, BCM5719C), 177 1.81 christos MII_PHY_DESC(BROADCOM3, BCM5720C), 178 1.81 christos MII_PHY_DESC(BROADCOM3, BCM57765), 179 1.81 christos MII_PHY_DESC(BROADCOM3, BCM57780), 180 1.87 jmcneill MII_PHY_DESC(BROADCOM4, BCM54213PE), 181 1.81 christos MII_PHY_DESC(BROADCOM4, BCM5725C), 182 1.81 christos MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906), 183 1.81 christos MII_PHY_END, 184 1.1 thorpej }; 185 1.1 thorpej 186 1.21 thorpej static int 187 1.48 tsutsui brgphymatch(device_t parent, cfdata_t match, void *aux) 188 1.1 thorpej { 189 1.1 thorpej struct mii_attach_args *ma = aux; 190 1.1 thorpej 191 1.2 thorpej if (mii_phy_match(ma, brgphys) != NULL) 192 1.83 msaitoh return 10; 193 1.1 thorpej 194 1.83 msaitoh return 0; 195 1.1 thorpej } 196 1.1 thorpej 197 1.21 thorpej static void 198 1.46 cegger brgphyattach(device_t parent, device_t self, void *aux) 199 1.1 thorpej { 200 1.44 msaitoh struct brgphy_softc *bsc = device_private(self); 201 1.44 msaitoh struct mii_softc *sc = &bsc->sc_mii; 202 1.1 thorpej struct mii_attach_args *ma = aux; 203 1.1 thorpej struct mii_data *mii = ma->mii_data; 204 1.2 thorpej const struct mii_phydesc *mpd; 205 1.44 msaitoh prop_dictionary_t dict; 206 1.1 thorpej 207 1.2 thorpej mpd = mii_phy_match(ma, brgphys); 208 1.17 thorpej aprint_naive(": Media interface\n"); 209 1.17 thorpej aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 210 1.1 thorpej 211 1.39 xtraeme sc->mii_dev = self; 212 1.1 thorpej sc->mii_inst = mii->mii_instance; 213 1.1 thorpej sc->mii_phy = ma->mii_phyno; 214 1.61 msaitoh sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 215 1.32 msaitoh sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 216 1.43 msaitoh sc->mii_mpd_rev = MII_REV(ma->mii_id2); 217 1.1 thorpej sc->mii_pdata = mii; 218 1.6 thorpej sc->mii_flags = ma->mii_flags; 219 1.10 thorpej 220 1.58 jym if (device_is_a(parent, "bge")) 221 1.54 dyoung bsc->sc_isbge = true; 222 1.58 jym else if (device_is_a(parent, "bnx")) 223 1.54 dyoung bsc->sc_isbnx = true; 224 1.58 jym 225 1.72 msaitoh dict = device_properties(parent); 226 1.58 jym if (bsc->sc_isbge || bsc->sc_isbnx) { 227 1.57 jym if (!prop_dictionary_get_uint32(dict, "phyflags", 228 1.58 jym &bsc->sc_phyflags)) 229 1.58 jym aprint_error_dev(self, "failed to get phyflags\n"); 230 1.58 jym if (!prop_dictionary_get_uint32(dict, "chipid", 231 1.58 jym &bsc->sc_chipid)) 232 1.58 jym aprint_error_dev(self, "failed to get chipid\n"); 233 1.44 msaitoh } 234 1.57 jym 235 1.71 msaitoh if (bsc->sc_isbnx) { 236 1.71 msaitoh /* Currently, only bnx use sc_shared_hwcfg and sc_port_hwcfg */ 237 1.71 msaitoh if (!prop_dictionary_get_uint32(dict, "shared_hwcfg", 238 1.71 msaitoh &bsc->sc_shared_hwcfg)) 239 1.71 msaitoh aprint_error_dev(self, "failed to get shared_hwcfg\n"); 240 1.71 msaitoh if (!prop_dictionary_get_uint32(dict, "port_hwcfg", 241 1.71 msaitoh &bsc->sc_port_hwcfg)) 242 1.71 msaitoh aprint_error_dev(self, "failed to get port_hwcfg\n"); 243 1.71 msaitoh } 244 1.71 msaitoh 245 1.71 msaitoh if (sc->mii_flags & MIIF_HAVEFIBER) { 246 1.74 msaitoh if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 247 1.74 msaitoh && sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5708S) 248 1.71 msaitoh sc->mii_funcs = &brgphy_5708s_funcs; 249 1.74 msaitoh else if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 250 1.75 msaitoh && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S)) { 251 1.75 msaitoh if (bsc->sc_isbnx) 252 1.75 msaitoh sc->mii_funcs = &brgphy_5709s_funcs; 253 1.75 msaitoh else { 254 1.75 msaitoh /* 255 1.75 msaitoh * XXX 256 1.75 msaitoh * 5720S and 5709S shares the same PHY id. 257 1.75 msaitoh * Assume 5720S PHY if parent device is bge(4). 258 1.75 msaitoh */ 259 1.75 msaitoh sc->mii_funcs = &brgphy_5708s_funcs; 260 1.75 msaitoh } 261 1.75 msaitoh } else 262 1.71 msaitoh sc->mii_funcs = &brgphy_fiber_funcs; 263 1.71 msaitoh } else 264 1.71 msaitoh sc->mii_funcs = &brgphy_copper_funcs; 265 1.71 msaitoh 266 1.88 thorpej mii_lock(mii); 267 1.88 thorpej 268 1.63 msaitoh PHY_RESET(sc); 269 1.63 msaitoh 270 1.79 msaitoh PHY_READ(sc, MII_BMSR, &sc->mii_capabilities); 271 1.79 msaitoh sc->mii_capabilities &= ma->mii_capmask; 272 1.63 msaitoh if (sc->mii_capabilities & BMSR_EXTSTAT) 273 1.79 msaitoh PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities); 274 1.63 msaitoh 275 1.88 thorpej mii_unlock(mii); 276 1.88 thorpej 277 1.75 msaitoh if (sc->mii_flags & MIIF_HAVEFIBER) { 278 1.88 thorpej mii_lock(mii); 279 1.75 msaitoh sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP; 280 1.57 jym 281 1.75 msaitoh /* 282 1.75 msaitoh * Set the proper bits for capabilities so that the 283 1.75 msaitoh * correct media get selected by mii_phy_add_media() 284 1.75 msaitoh */ 285 1.75 msaitoh sc->mii_capabilities |= BMSR_ANEG; 286 1.75 msaitoh sc->mii_capabilities &= ~BMSR_100T4; 287 1.75 msaitoh sc->mii_extcapabilities |= EXTSR_1000XFDX; 288 1.88 thorpej mii_unlock(mii); 289 1.75 msaitoh 290 1.75 msaitoh if (bsc->sc_isbnx) { 291 1.57 jym /* 292 1.75 msaitoh * 2.5Gb support is a software enabled feature 293 1.75 msaitoh * on the BCM5708S and BCM5709S controllers. 294 1.57 jym */ 295 1.57 jym #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 296 1.75 msaitoh if (bsc->sc_phyflags 297 1.75 msaitoh & BNX_PHY_2_5G_CAPABLE_FLAG) { 298 1.75 msaitoh ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, 299 1.75 msaitoh IFM_FDX, sc->mii_inst), 0); 300 1.86 msaitoh aprint_normal_dev(self, "2500baseSX-FDX\n"); 301 1.57 jym #undef ADD 302 1.57 jym } 303 1.57 jym } 304 1.57 jym } 305 1.75 msaitoh mii_phy_add_media(sc); 306 1.1 thorpej } 307 1.1 thorpej 308 1.21 thorpej static int 309 1.4 thorpej brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 310 1.1 thorpej { 311 1.1 thorpej struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 312 1.79 msaitoh uint16_t reg, speed, gig; 313 1.1 thorpej 314 1.88 thorpej KASSERT(mii_locked(mii)); 315 1.88 thorpej 316 1.1 thorpej switch (cmd) { 317 1.1 thorpej case MII_POLLSTAT: 318 1.73 msaitoh /* If we're not polling our PHY instance, just return. */ 319 1.1 thorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst) 320 1.83 msaitoh return 0; 321 1.1 thorpej break; 322 1.1 thorpej 323 1.1 thorpej case MII_MEDIACHG: 324 1.1 thorpej /* 325 1.1 thorpej * If the media indicates a different PHY instance, 326 1.1 thorpej * isolate ourselves. 327 1.1 thorpej */ 328 1.1 thorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 329 1.79 msaitoh PHY_READ(sc, MII_BMCR, ®); 330 1.1 thorpej PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 331 1.83 msaitoh return 0; 332 1.1 thorpej } 333 1.1 thorpej 334 1.73 msaitoh /* If the interface is not up, don't do anything. */ 335 1.1 thorpej if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 336 1.1 thorpej break; 337 1.1 thorpej 338 1.32 msaitoh PHY_RESET(sc); /* XXX hardware bug work-around */ 339 1.32 msaitoh 340 1.32 msaitoh switch (IFM_SUBTYPE(ife->ifm_media)) { 341 1.32 msaitoh case IFM_AUTO: 342 1.32 msaitoh (void) brgphy_mii_phy_auto(sc); 343 1.32 msaitoh break; 344 1.71 msaitoh case IFM_2500_SX: 345 1.71 msaitoh speed = BRGPHY_5708S_BMCR_2500; 346 1.71 msaitoh goto setit; 347 1.71 msaitoh case IFM_1000_SX: 348 1.32 msaitoh case IFM_1000_T: 349 1.32 msaitoh speed = BMCR_S1000; 350 1.32 msaitoh goto setit; 351 1.32 msaitoh case IFM_100_TX: 352 1.32 msaitoh speed = BMCR_S100; 353 1.32 msaitoh goto setit; 354 1.32 msaitoh case IFM_10_T: 355 1.32 msaitoh speed = BMCR_S10; 356 1.32 msaitoh setit: 357 1.32 msaitoh brgphy_loop(sc); 358 1.84 msaitoh if ((ife->ifm_media & IFM_FDX) != 0) { 359 1.32 msaitoh speed |= BMCR_FDX; 360 1.32 msaitoh gig = GTCR_ADV_1000TFDX; 361 1.69 msaitoh } else 362 1.32 msaitoh gig = GTCR_ADV_1000THDX; 363 1.32 msaitoh 364 1.32 msaitoh PHY_WRITE(sc, MII_100T2CR, 0); 365 1.51 bouyer PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 366 1.32 msaitoh PHY_WRITE(sc, MII_BMCR, speed); 367 1.32 msaitoh 368 1.71 msaitoh if ((IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) && 369 1.71 msaitoh (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_SX) && 370 1.71 msaitoh (IFM_SUBTYPE(ife->ifm_media) != IFM_2500_SX)) 371 1.32 msaitoh break; 372 1.32 msaitoh 373 1.32 msaitoh PHY_WRITE(sc, MII_100T2CR, gig); 374 1.32 msaitoh PHY_WRITE(sc, MII_BMCR, 375 1.65 msaitoh speed | BMCR_AUTOEN | BMCR_STARTNEG); 376 1.32 msaitoh 377 1.61 msaitoh if ((sc->mii_mpd_oui != MII_OUI_BROADCOM) 378 1.61 msaitoh || (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701)) 379 1.33 msaitoh break; 380 1.32 msaitoh 381 1.32 msaitoh if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 382 1.32 msaitoh gig |= GTCR_MAN_MS | GTCR_ADV_MS; 383 1.32 msaitoh PHY_WRITE(sc, MII_100T2CR, gig); 384 1.32 msaitoh break; 385 1.32 msaitoh default: 386 1.83 msaitoh return EINVAL; 387 1.32 msaitoh } 388 1.1 thorpej break; 389 1.1 thorpej 390 1.1 thorpej case MII_TICK: 391 1.73 msaitoh /* If we're not currently selected, just return. */ 392 1.1 thorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst) 393 1.83 msaitoh return 0; 394 1.1 thorpej 395 1.73 msaitoh /* Is the interface even up? */ 396 1.67 msaitoh if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 397 1.67 msaitoh return 0; 398 1.67 msaitoh 399 1.73 msaitoh /* Only used for autonegotiation. */ 400 1.67 msaitoh if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && 401 1.67 msaitoh (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { 402 1.67 msaitoh sc->mii_ticks = 0; 403 1.67 msaitoh break; 404 1.67 msaitoh } 405 1.67 msaitoh 406 1.67 msaitoh /* 407 1.67 msaitoh * Check for link. 408 1.67 msaitoh * Read the status register twice; BMSR_LINK is latch-low. 409 1.67 msaitoh */ 410 1.79 msaitoh PHY_READ(sc, MII_BMSR, ®); 411 1.79 msaitoh PHY_READ(sc, MII_BMSR, ®); 412 1.67 msaitoh if (reg & BMSR_LINK) { 413 1.67 msaitoh sc->mii_ticks = 0; 414 1.67 msaitoh break; 415 1.67 msaitoh } 416 1.67 msaitoh 417 1.67 msaitoh /* 418 1.67 msaitoh * mii_ticks == 0 means it's the first tick after changing the 419 1.67 msaitoh * media or the link became down since the last tick 420 1.67 msaitoh * (see above), so break to update the status. 421 1.67 msaitoh */ 422 1.67 msaitoh if (sc->mii_ticks++ == 0) 423 1.67 msaitoh break; 424 1.67 msaitoh 425 1.73 msaitoh /* Only retry autonegotiation every mii_anegticks seconds. */ 426 1.67 msaitoh KASSERT(sc->mii_anegticks != 0); 427 1.91 msaitoh if (sc->mii_ticks < sc->mii_anegticks) 428 1.67 msaitoh break; 429 1.67 msaitoh 430 1.67 msaitoh brgphy_mii_phy_auto(sc); 431 1.1 thorpej break; 432 1.1 thorpej 433 1.1 thorpej case MII_DOWN: 434 1.1 thorpej mii_phy_down(sc); 435 1.83 msaitoh return 0; 436 1.1 thorpej } 437 1.1 thorpej 438 1.1 thorpej /* Update the media status. */ 439 1.1 thorpej mii_phy_status(sc); 440 1.1 thorpej 441 1.10 thorpej /* 442 1.32 msaitoh * Callback if something changed. Note that we need to poke the DSP on 443 1.32 msaitoh * the Broadcom PHYs if the media changes. 444 1.10 thorpej */ 445 1.23 perry if (sc->mii_media_active != mii->mii_media_active || 446 1.10 thorpej sc->mii_media_status != mii->mii_media_status || 447 1.10 thorpej cmd == MII_MEDIACHG) { 448 1.61 msaitoh switch (sc->mii_mpd_oui) { 449 1.61 msaitoh case MII_OUI_BROADCOM: 450 1.61 msaitoh switch (sc->mii_mpd_model) { 451 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5400: 452 1.43 msaitoh brgphy_bcm5401_dspcode(sc); 453 1.61 msaitoh break; 454 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5401: 455 1.61 msaitoh if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) 456 1.61 msaitoh brgphy_bcm5401_dspcode(sc); 457 1.61 msaitoh break; 458 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5411: 459 1.61 msaitoh brgphy_bcm5411_dspcode(sc); 460 1.61 msaitoh break; 461 1.61 msaitoh } 462 1.43 msaitoh break; 463 1.90 jmcneill case MII_OUI_BROADCOM4: 464 1.90 jmcneill switch (sc->mii_mpd_model) { 465 1.90 jmcneill case MII_MODEL_BROADCOM4_BCM54213PE: 466 1.90 jmcneill brgphy_bcm54xx_clock_delay(sc); 467 1.90 jmcneill break; 468 1.90 jmcneill } 469 1.43 msaitoh } 470 1.10 thorpej } 471 1.43 msaitoh 472 1.43 msaitoh /* Callback if something changed. */ 473 1.43 msaitoh mii_phy_update(sc, cmd); 474 1.83 msaitoh return 0; 475 1.1 thorpej } 476 1.1 thorpej 477 1.21 thorpej static void 478 1.71 msaitoh brgphy_copper_status(struct mii_softc *sc) 479 1.1 thorpej { 480 1.1 thorpej struct mii_data *mii = sc->mii_pdata; 481 1.1 thorpej struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 482 1.79 msaitoh uint16_t bmcr, bmsr, auxsts, gtsr; 483 1.1 thorpej 484 1.88 thorpej KASSERT(mii_locked(mii)); 485 1.88 thorpej 486 1.1 thorpej mii->mii_media_status = IFM_AVALID; 487 1.1 thorpej mii->mii_media_active = IFM_ETHER; 488 1.1 thorpej 489 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 490 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 491 1.57 jym if (bmsr & BMSR_LINK) 492 1.1 thorpej mii->mii_media_status |= IFM_ACTIVE; 493 1.1 thorpej 494 1.79 msaitoh PHY_READ(sc, MII_BMCR, &bmcr); 495 1.1 thorpej if (bmcr & BMCR_ISO) { 496 1.1 thorpej mii->mii_media_active |= IFM_NONE; 497 1.1 thorpej mii->mii_media_status = 0; 498 1.1 thorpej return; 499 1.1 thorpej } 500 1.1 thorpej 501 1.1 thorpej if (bmcr & BMCR_LOOP) 502 1.1 thorpej mii->mii_media_active |= IFM_LOOP; 503 1.1 thorpej 504 1.1 thorpej if (bmcr & BMCR_AUTOEN) { 505 1.1 thorpej /* 506 1.85 msaitoh * The media status bits are only valid if autonegotiation 507 1.1 thorpej * has completed (or it's disabled). 508 1.1 thorpej */ 509 1.57 jym if ((bmsr & BMSR_ACOMP) == 0) { 510 1.1 thorpej /* Erg, still trying, I guess... */ 511 1.1 thorpej mii->mii_media_active |= IFM_NONE; 512 1.1 thorpej return; 513 1.1 thorpej } 514 1.1 thorpej 515 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_AUXSTS, &auxsts); 516 1.71 msaitoh 517 1.71 msaitoh switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 518 1.71 msaitoh case BRGPHY_RES_1000FD: 519 1.71 msaitoh mii->mii_media_active |= IFM_1000_T | IFM_FDX; 520 1.79 msaitoh PHY_READ(sc, MII_100T2SR, >sr); 521 1.71 msaitoh if (gtsr & GTSR_MS_RES) 522 1.71 msaitoh mii->mii_media_active |= IFM_ETH_MASTER; 523 1.71 msaitoh break; 524 1.71 msaitoh 525 1.71 msaitoh case BRGPHY_RES_1000HD: 526 1.71 msaitoh mii->mii_media_active |= IFM_1000_T | IFM_HDX; 527 1.79 msaitoh PHY_READ(sc, MII_100T2SR, >sr); 528 1.71 msaitoh if (gtsr & GTSR_MS_RES) 529 1.71 msaitoh mii->mii_media_active |= IFM_ETH_MASTER; 530 1.71 msaitoh break; 531 1.71 msaitoh 532 1.71 msaitoh case BRGPHY_RES_100FD: 533 1.71 msaitoh mii->mii_media_active |= IFM_100_TX | IFM_FDX; 534 1.71 msaitoh break; 535 1.71 msaitoh 536 1.71 msaitoh case BRGPHY_RES_100T4: 537 1.71 msaitoh mii->mii_media_active |= IFM_100_T4 | IFM_HDX; 538 1.71 msaitoh break; 539 1.71 msaitoh 540 1.71 msaitoh case BRGPHY_RES_100HD: 541 1.71 msaitoh mii->mii_media_active |= IFM_100_TX | IFM_HDX; 542 1.71 msaitoh break; 543 1.71 msaitoh 544 1.71 msaitoh case BRGPHY_RES_10FD: 545 1.71 msaitoh mii->mii_media_active |= IFM_10_T | IFM_FDX; 546 1.71 msaitoh break; 547 1.71 msaitoh 548 1.71 msaitoh case BRGPHY_RES_10HD: 549 1.71 msaitoh mii->mii_media_active |= IFM_10_T | IFM_HDX; 550 1.71 msaitoh break; 551 1.71 msaitoh 552 1.71 msaitoh default: 553 1.71 msaitoh mii->mii_media_active |= IFM_NONE; 554 1.71 msaitoh mii->mii_media_status = 0; 555 1.71 msaitoh } 556 1.71 msaitoh 557 1.71 msaitoh if (mii->mii_media_active & IFM_FDX) 558 1.71 msaitoh mii->mii_media_active |= mii_phy_flowstatus(sc); 559 1.71 msaitoh 560 1.71 msaitoh } else 561 1.71 msaitoh mii->mii_media_active = ife->ifm_media; 562 1.71 msaitoh } 563 1.71 msaitoh 564 1.71 msaitoh void 565 1.71 msaitoh brgphy_fiber_status(struct mii_softc *sc) 566 1.71 msaitoh { 567 1.71 msaitoh struct mii_data *mii = sc->mii_pdata; 568 1.71 msaitoh struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 569 1.79 msaitoh uint16_t bmcr, bmsr, anar, anlpar, result; 570 1.71 msaitoh 571 1.88 thorpej KASSERT(mii_locked(mii)); 572 1.88 thorpej 573 1.71 msaitoh mii->mii_media_status = IFM_AVALID; 574 1.71 msaitoh mii->mii_media_active = IFM_ETHER; 575 1.71 msaitoh 576 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 577 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 578 1.71 msaitoh if (bmsr & BMSR_LINK) 579 1.71 msaitoh mii->mii_media_status |= IFM_ACTIVE; 580 1.57 jym 581 1.79 msaitoh PHY_READ(sc, MII_BMCR, &bmcr); 582 1.71 msaitoh if (bmcr & BMCR_LOOP) 583 1.71 msaitoh mii->mii_media_active |= IFM_LOOP; 584 1.57 jym 585 1.71 msaitoh if (bmcr & BMCR_AUTOEN) { 586 1.71 msaitoh if ((bmsr & BMSR_ACOMP) == 0) { 587 1.71 msaitoh /* Erg, still trying, I guess... */ 588 1.71 msaitoh mii->mii_media_active |= IFM_NONE; 589 1.71 msaitoh return; 590 1.71 msaitoh } 591 1.57 jym 592 1.71 msaitoh mii->mii_media_active |= IFM_1000_SX; 593 1.57 jym 594 1.79 msaitoh PHY_READ(sc, MII_ANAR, &anar); 595 1.79 msaitoh PHY_READ(sc, MII_ANLPAR, &anlpar); 596 1.79 msaitoh result = anar & anlpar; 597 1.57 jym 598 1.79 msaitoh if (result & ANAR_X_FD) 599 1.71 msaitoh mii->mii_media_active |= IFM_FDX; 600 1.71 msaitoh else 601 1.71 msaitoh mii->mii_media_active |= IFM_HDX; 602 1.1 thorpej 603 1.71 msaitoh if (mii->mii_media_active & IFM_FDX) 604 1.71 msaitoh mii->mii_media_active |= mii_phy_flowstatus(sc); 605 1.71 msaitoh } else 606 1.71 msaitoh mii->mii_media_active = ife->ifm_media; 607 1.71 msaitoh } 608 1.1 thorpej 609 1.71 msaitoh void 610 1.71 msaitoh brgphy_5708s_status(struct mii_softc *sc) 611 1.71 msaitoh { 612 1.71 msaitoh struct mii_data *mii = sc->mii_pdata; 613 1.71 msaitoh struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 614 1.79 msaitoh uint16_t bmcr, bmsr; 615 1.1 thorpej 616 1.88 thorpej KASSERT(mii_locked(mii)); 617 1.88 thorpej 618 1.71 msaitoh mii->mii_media_status = IFM_AVALID; 619 1.71 msaitoh mii->mii_media_active = IFM_ETHER; 620 1.1 thorpej 621 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 622 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 623 1.71 msaitoh if (bmsr & BMSR_LINK) 624 1.71 msaitoh mii->mii_media_status |= IFM_ACTIVE; 625 1.1 thorpej 626 1.79 msaitoh PHY_READ(sc, MII_BMCR, &bmcr); 627 1.71 msaitoh if (bmcr & BMCR_LOOP) 628 1.71 msaitoh mii->mii_media_active |= IFM_LOOP; 629 1.1 thorpej 630 1.71 msaitoh if (bmcr & BMCR_AUTOEN) { 631 1.79 msaitoh uint16_t xstat; 632 1.1 thorpej 633 1.71 msaitoh if ((bmsr & BMSR_ACOMP) == 0) { 634 1.71 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 635 1.71 msaitoh BRGPHY_5708S_DIG_PG0); 636 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1, &xstat); 637 1.71 msaitoh if ((xstat & BRGPHY_5708S_PG0_1000X_STAT1_LINK) == 0) { 638 1.71 msaitoh /* Erg, still trying, I guess... */ 639 1.57 jym mii->mii_media_active |= IFM_NONE; 640 1.71 msaitoh return; 641 1.57 jym } 642 1.1 thorpej } 643 1.57 jym 644 1.71 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 645 1.71 msaitoh BRGPHY_5708S_DIG_PG0); 646 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1, &xstat); 647 1.71 msaitoh 648 1.71 msaitoh switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) { 649 1.71 msaitoh case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10: 650 1.71 msaitoh mii->mii_media_active |= IFM_10_FL; 651 1.71 msaitoh break; 652 1.71 msaitoh case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100: 653 1.71 msaitoh mii->mii_media_active |= IFM_100_FX; 654 1.71 msaitoh break; 655 1.71 msaitoh case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G: 656 1.71 msaitoh mii->mii_media_active |= IFM_1000_SX; 657 1.71 msaitoh break; 658 1.71 msaitoh case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G: 659 1.71 msaitoh mii->mii_media_active |= IFM_2500_SX; 660 1.71 msaitoh break; 661 1.71 msaitoh } 662 1.71 msaitoh 663 1.71 msaitoh if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_FDX) 664 1.71 msaitoh mii->mii_media_active |= IFM_FDX; 665 1.71 msaitoh else 666 1.71 msaitoh mii->mii_media_active |= IFM_HDX; 667 1.71 msaitoh 668 1.71 msaitoh if (mii->mii_media_active & IFM_FDX) { 669 1.71 msaitoh if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_TX_PAUSE) 670 1.83 msaitoh mii->mii_media_active 671 1.83 msaitoh |= IFM_FLOW | IFM_ETH_TXPAUSE; 672 1.71 msaitoh if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_RX_PAUSE) 673 1.83 msaitoh mii->mii_media_active 674 1.83 msaitoh |= IFM_FLOW | IFM_ETH_RXPAUSE; 675 1.71 msaitoh } 676 1.71 msaitoh } else 677 1.71 msaitoh mii->mii_media_active = ife->ifm_media; 678 1.71 msaitoh } 679 1.71 msaitoh 680 1.71 msaitoh static void 681 1.71 msaitoh brgphy_5709s_status(struct mii_softc *sc) 682 1.71 msaitoh { 683 1.71 msaitoh struct mii_data *mii = sc->mii_pdata; 684 1.71 msaitoh struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 685 1.79 msaitoh uint16_t bmcr, bmsr, auxsts; 686 1.71 msaitoh 687 1.88 thorpej KASSERT(mii_locked(mii)); 688 1.88 thorpej 689 1.71 msaitoh mii->mii_media_status = IFM_AVALID; 690 1.71 msaitoh mii->mii_media_active = IFM_ETHER; 691 1.71 msaitoh 692 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 693 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 694 1.71 msaitoh if (bmsr & BMSR_LINK) 695 1.71 msaitoh mii->mii_media_status |= IFM_ACTIVE; 696 1.71 msaitoh 697 1.79 msaitoh PHY_READ(sc, MII_BMCR, &bmcr); 698 1.71 msaitoh if (bmcr & BMCR_ISO) { 699 1.71 msaitoh mii->mii_media_active |= IFM_NONE; 700 1.71 msaitoh mii->mii_media_status = 0; 701 1.71 msaitoh return; 702 1.71 msaitoh } 703 1.71 msaitoh 704 1.71 msaitoh if (bmcr & BMCR_LOOP) 705 1.71 msaitoh mii->mii_media_active |= IFM_LOOP; 706 1.71 msaitoh 707 1.71 msaitoh if (bmcr & BMCR_AUTOEN) { 708 1.71 msaitoh /* 709 1.71 msaitoh * The media status bits are only valid of autonegotiation 710 1.71 msaitoh * has completed (or it's disabled). 711 1.71 msaitoh */ 712 1.71 msaitoh if ((bmsr & BMSR_ACOMP) == 0) { 713 1.71 msaitoh /* Erg, still trying, I guess... */ 714 1.71 msaitoh mii->mii_media_active |= IFM_NONE; 715 1.71 msaitoh return; 716 1.71 msaitoh } 717 1.71 msaitoh 718 1.71 msaitoh /* 5709S has its own general purpose status registers */ 719 1.79 msaitoh PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_GP_STATUS); 720 1.79 msaitoh PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS, &auxsts); 721 1.71 msaitoh 722 1.71 msaitoh PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 723 1.71 msaitoh BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 724 1.71 msaitoh 725 1.71 msaitoh switch (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { 726 1.71 msaitoh case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: 727 1.71 msaitoh mii->mii_media_active |= IFM_10_FL; 728 1.71 msaitoh break; 729 1.71 msaitoh case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: 730 1.71 msaitoh mii->mii_media_active |= IFM_100_FX; 731 1.71 msaitoh break; 732 1.71 msaitoh case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: 733 1.71 msaitoh mii->mii_media_active |= IFM_1000_SX; 734 1.71 msaitoh break; 735 1.71 msaitoh case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: 736 1.71 msaitoh mii->mii_media_active |= IFM_2500_SX; 737 1.71 msaitoh break; 738 1.71 msaitoh default: 739 1.71 msaitoh mii->mii_media_active |= IFM_NONE; 740 1.71 msaitoh mii->mii_media_status = 0; 741 1.71 msaitoh break; 742 1.71 msaitoh } 743 1.71 msaitoh 744 1.71 msaitoh if (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_FDX) 745 1.71 msaitoh mii->mii_media_active |= IFM_FDX; 746 1.71 msaitoh else 747 1.71 msaitoh mii->mii_media_active |= IFM_HDX; 748 1.71 msaitoh 749 1.19 thorpej if (mii->mii_media_active & IFM_FDX) 750 1.20 thorpej mii->mii_media_active |= mii_phy_flowstatus(sc); 751 1.1 thorpej } else 752 1.1 thorpej mii->mii_media_active = ife->ifm_media; 753 1.10 thorpej } 754 1.10 thorpej 755 1.88 thorpej static int 756 1.32 msaitoh brgphy_mii_phy_auto(struct mii_softc *sc) 757 1.32 msaitoh { 758 1.79 msaitoh uint16_t anar, ktcr = 0; 759 1.32 msaitoh 760 1.88 thorpej KASSERT(mii_locked(sc->mii_pdata)); 761 1.88 thorpej 762 1.64 msaitoh sc->mii_ticks = 0; 763 1.32 msaitoh brgphy_loop(sc); 764 1.32 msaitoh PHY_RESET(sc); 765 1.57 jym 766 1.57 jym if (sc->mii_flags & MIIF_HAVEFIBER) { 767 1.57 jym anar = ANAR_X_FD | ANAR_X_HD; 768 1.57 jym if (sc->mii_flags & MIIF_DOPAUSE) 769 1.69 msaitoh anar |= ANAR_X_PAUSE_TOWARDS; 770 1.57 jym } else { 771 1.57 jym anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 772 1.57 jym if (sc->mii_flags & MIIF_DOPAUSE) 773 1.66 msaitoh anar |= ANAR_FC | ANAR_PAUSE_ASYM; 774 1.71 msaitoh ktcr = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; 775 1.71 msaitoh if ((sc->mii_mpd_oui == MII_OUI_BROADCOM) 776 1.71 msaitoh && (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701)) 777 1.71 msaitoh ktcr |= GTCR_MAN_MS | GTCR_ADV_MS; 778 1.71 msaitoh PHY_WRITE(sc, MII_100T2CR, ktcr); 779 1.57 jym } 780 1.32 msaitoh PHY_WRITE(sc, MII_ANAR, anar); 781 1.57 jym 782 1.57 jym /* Start autonegotiation */ 783 1.69 msaitoh PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 784 1.32 msaitoh PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 785 1.32 msaitoh 786 1.83 msaitoh return EJUSTRETURN; 787 1.32 msaitoh } 788 1.32 msaitoh 789 1.88 thorpej static void 790 1.32 msaitoh brgphy_loop(struct mii_softc *sc) 791 1.32 msaitoh { 792 1.79 msaitoh uint16_t bmsr; 793 1.32 msaitoh int i; 794 1.32 msaitoh 795 1.88 thorpej KASSERT(mii_locked(sc->mii_pdata)); 796 1.88 thorpej 797 1.32 msaitoh PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 798 1.33 msaitoh for (i = 0; i < 15000; i++) { 799 1.79 msaitoh PHY_READ(sc, MII_BMSR, &bmsr); 800 1.32 msaitoh if (!(bmsr & BMSR_LINK)) 801 1.32 msaitoh break; 802 1.32 msaitoh DELAY(10); 803 1.32 msaitoh } 804 1.32 msaitoh } 805 1.32 msaitoh 806 1.21 thorpej static void 807 1.43 msaitoh brgphy_reset(struct mii_softc *sc) 808 1.10 thorpej { 809 1.56 jym struct brgphy_softc *bsc = device_private(sc->mii_dev); 810 1.79 msaitoh uint16_t reg; 811 1.10 thorpej 812 1.88 thorpej KASSERT(mii_locked(sc->mii_pdata)); 813 1.88 thorpej 814 1.10 thorpej mii_phy_reset(sc); 815 1.61 msaitoh switch (sc->mii_mpd_oui) { 816 1.61 msaitoh case MII_OUI_BROADCOM: 817 1.61 msaitoh switch (sc->mii_mpd_model) { 818 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5400: 819 1.43 msaitoh brgphy_bcm5401_dspcode(sc); 820 1.61 msaitoh break; 821 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5401: 822 1.61 msaitoh if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) 823 1.61 msaitoh brgphy_bcm5401_dspcode(sc); 824 1.61 msaitoh break; 825 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5411: 826 1.61 msaitoh brgphy_bcm5411_dspcode(sc); 827 1.61 msaitoh break; 828 1.61 msaitoh case MII_MODEL_BROADCOM_BCM5421: 829 1.61 msaitoh brgphy_bcm5421_dspcode(sc); 830 1.61 msaitoh break; 831 1.61 msaitoh case MII_MODEL_BROADCOM_BCM54K2: 832 1.61 msaitoh brgphy_bcm54k2_dspcode(sc); 833 1.61 msaitoh break; 834 1.61 msaitoh } 835 1.43 msaitoh break; 836 1.61 msaitoh case MII_OUI_BROADCOM3: 837 1.61 msaitoh switch (sc->mii_mpd_model) { 838 1.61 msaitoh case MII_MODEL_BROADCOM3_BCM5717C: 839 1.61 msaitoh case MII_MODEL_BROADCOM3_BCM5719C: 840 1.61 msaitoh case MII_MODEL_BROADCOM3_BCM5720C: 841 1.61 msaitoh case MII_MODEL_BROADCOM3_BCM57765: 842 1.61 msaitoh return; 843 1.61 msaitoh } 844 1.43 msaitoh break; 845 1.61 msaitoh default: 846 1.43 msaitoh break; 847 1.43 msaitoh } 848 1.15 jonathan 849 1.43 msaitoh /* Handle any bge (NetXtreme/NetLink) workarounds. */ 850 1.54 dyoung if (bsc->sc_isbge) { 851 1.43 msaitoh if (!(sc->mii_flags & MIIF_HAVEFIBER)) { 852 1.43 msaitoh 853 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_ADC_BUG) 854 1.43 msaitoh brgphy_adc_bug(sc); 855 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_5704_A0_BUG) 856 1.43 msaitoh brgphy_5704_a0_bug(sc); 857 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_BER_BUG) 858 1.43 msaitoh brgphy_ber_bug(sc); 859 1.68 msaitoh else if (bsc->sc_phyflags & BGEPHYF_JITTER_BUG) { 860 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00); 861 1.79 msaitoh PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); 862 1.43 msaitoh 863 1.77 msaitoh if (bsc->sc_phyflags 864 1.68 msaitoh & BGEPHYF_ADJUST_TRIM) { 865 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 866 1.43 msaitoh 0x110b); 867 1.43 msaitoh PHY_WRITE(sc, BRGPHY_TEST1, 868 1.43 msaitoh BRGPHY_TEST1_TRIM_EN | 0x4); 869 1.43 msaitoh } else { 870 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 871 1.43 msaitoh 0x010b); 872 1.43 msaitoh } 873 1.15 jonathan 874 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400); 875 1.43 msaitoh } 876 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_CRC_BUG) 877 1.43 msaitoh brgphy_crc_bug(sc); 878 1.15 jonathan 879 1.43 msaitoh /* Set Jumbo frame settings in the PHY. */ 880 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_JUMBO_CAPABLE) 881 1.43 msaitoh brgphy_jumbo_settings(sc); 882 1.43 msaitoh 883 1.43 msaitoh /* Adjust output voltage */ 884 1.61 msaitoh if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 885 1.61 msaitoh && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5906)) 886 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); 887 1.43 msaitoh 888 1.43 msaitoh /* Enable Ethernet@Wirespeed */ 889 1.68 msaitoh if (!(bsc->sc_phyflags & BGEPHYF_NO_WIRESPEED)) 890 1.43 msaitoh brgphy_eth_wirespeed(sc); 891 1.43 msaitoh 892 1.52 msaitoh #if 0 893 1.43 msaitoh /* Enable Link LED on Dell boxes */ 894 1.68 msaitoh if (bsc->sc_phyflags & BGEPHYF_NO_3LED) { 895 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL, ®); 896 1.77 msaitoh PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 897 1.79 msaitoh reg & ~BRGPHY_PHY_EXTCTL_3_LED); 898 1.43 msaitoh } 899 1.43 msaitoh #endif 900 1.43 msaitoh } 901 1.57 jym /* Handle any bnx (NetXtreme II) workarounds. */ 902 1.57 jym } else if (bsc->sc_isbnx) { 903 1.83 msaitoh uint32_t chip_num = _BNX_CHIP_NUM(bsc->sc_chipid); 904 1.83 msaitoh uint32_t chip_id = _BNX_CHIP_ID(bsc->sc_chipid); 905 1.83 msaitoh uint32_t chip_rev = _BNX_CHIP_REV(bsc->sc_chipid); 906 1.83 msaitoh 907 1.61 msaitoh if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 908 1.61 msaitoh && sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5708S) { 909 1.83 msaitoh /* 910 1.83 msaitoh * Store autoneg capabilities/results in digital block 911 1.83 msaitoh * (Page 0) 912 1.83 msaitoh */ 913 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 914 1.83 msaitoh BRGPHY_5708S_DIG3_PG2); 915 1.77 msaitoh PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0, 916 1.77 msaitoh BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE); 917 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 918 1.83 msaitoh BRGPHY_5708S_DIG_PG0); 919 1.43 msaitoh 920 1.43 msaitoh /* Enable fiber mode and autodetection */ 921 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1, ®); 922 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1, reg | 923 1.83 msaitoh BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN | 924 1.77 msaitoh BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE); 925 1.43 msaitoh 926 1.43 msaitoh /* Enable parallel detection */ 927 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2, ®); 928 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2, 929 1.79 msaitoh reg | BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN); 930 1.43 msaitoh 931 1.83 msaitoh /* 932 1.83 msaitoh * Advertise 2.5G support through next page during 933 1.83 msaitoh * autoneg 934 1.83 msaitoh */ 935 1.79 msaitoh if (bsc->sc_phyflags & BNX_PHY_2_5G_CAPABLE_FLAG) { 936 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, 937 1.79 msaitoh ®); 938 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, 939 1.79 msaitoh reg | BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); 940 1.79 msaitoh } 941 1.43 msaitoh 942 1.43 msaitoh /* Increase TX signal amplitude */ 943 1.83 msaitoh if ((chip_id == BNX_CHIP_ID_5708_A0) || 944 1.83 msaitoh (chip_id == BNX_CHIP_ID_5708_B0) || 945 1.83 msaitoh (chip_id == BNX_CHIP_ID_5708_B1)) { 946 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 947 1.79 msaitoh BRGPHY_5708S_TX_MISC_PG5); 948 1.79 msaitoh PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1, ®); 949 1.77 msaitoh PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1, 950 1.79 msaitoh reg & ~BRGPHY_5708S_PG5_TXACTL1_VCM); 951 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 952 1.79 msaitoh BRGPHY_5708S_DIG_PG0); 953 1.43 msaitoh } 954 1.15 jonathan 955 1.83 msaitoh /* 956 1.83 msaitoh * Backplanes use special 957 1.83 msaitoh * driver/pre-driver/pre-emphasis values. 958 1.83 msaitoh */ 959 1.71 msaitoh if ((bsc->sc_shared_hwcfg & BNX_SHARED_HW_CFG_PHY_BACKPLANE) && 960 1.71 msaitoh (bsc->sc_port_hwcfg & BNX_PORT_HW_CFG_CFG_TXCTL3_MASK)) { 961 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 962 1.83 msaitoh BRGPHY_5708S_TX_MISC_PG5); 963 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3, 964 1.83 msaitoh bsc->sc_port_hwcfg & 965 1.83 msaitoh BNX_PORT_HW_CFG_CFG_TXCTL3_MASK); 966 1.83 msaitoh PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 967 1.83 msaitoh BRGPHY_5708S_DIG_PG0); 968 1.43 msaitoh } 969 1.71 msaitoh } else if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 970 1.61 msaitoh && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S)) { 971 1.57 jym /* Select the SerDes Digital block of the AN MMD. */ 972 1.57 jym PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 973 1.57 jym BRGPHY_BLOCK_ADDR_SERDES_DIG); 974 1.57 jym 975 1.79 msaitoh PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1, ®); 976 1.57 jym PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, 977 1.79 msaitoh (reg & ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET) | 978 1.57 jym BRGPHY_SD_DIG_1000X_CTL1_FIBER); 979 1.57 jym 980 1.58 jym if (bsc->sc_phyflags & BNX_PHY_2_5G_CAPABLE_FLAG) { 981 1.57 jym /* Select the Over 1G block of the AN MMD. */ 982 1.57 jym PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 983 1.57 jym BRGPHY_BLOCK_ADDR_OVER_1G); 984 1.57 jym 985 1.57 jym /* 986 1.57 jym * Enable autoneg "Next Page" to advertise 987 1.57 jym * 2.5G support. 988 1.57 jym */ 989 1.79 msaitoh PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, 990 1.79 msaitoh ®); 991 1.57 jym PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, 992 1.79 msaitoh reg | BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); 993 1.57 jym } 994 1.57 jym 995 1.77 msaitoh /* 996 1.77 msaitoh * Select the Multi-Rate Backplane Ethernet block of 997 1.77 msaitoh * the AN MMD. 998 1.77 msaitoh */ 999 1.77 msaitoh PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 1000 1.77 msaitoh BRGPHY_BLOCK_ADDR_MRBE); 1001 1.77 msaitoh 1002 1.77 msaitoh /* Enable MRBE speed autoneg. */ 1003 1.79 msaitoh PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP, ®); 1004 1.77 msaitoh PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, 1005 1.79 msaitoh reg | BRGPHY_MRBE_MSG_PG5_NP_MBRE | 1006 1.77 msaitoh BRGPHY_MRBE_MSG_PG5_NP_T2); 1007 1.77 msaitoh 1008 1.77 msaitoh /* Select the Clause 73 User B0 block of the AN MMD. */ 1009 1.77 msaitoh PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 1010 1.77 msaitoh BRGPHY_BLOCK_ADDR_CL73_USER_B0); 1011 1.57 jym 1012 1.77 msaitoh /* Enable MRBE speed autoneg. */ 1013 1.77 msaitoh PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, 1014 1.77 msaitoh BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | 1015 1.77 msaitoh BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | 1016 1.77 msaitoh BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); 1017 1.77 msaitoh 1018 1.77 msaitoh PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 1019 1.77 msaitoh BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 1020 1.57 jym 1021 1.83 msaitoh } else if (chip_num == BNX_CHIP_NUM_5709) { 1022 1.83 msaitoh if ((chip_rev == BNX_CHIP_REV_Ax) || 1023 1.83 msaitoh (chip_rev == BNX_CHIP_REV_Bx)) 1024 1.58 jym brgphy_disable_early_dac(sc); 1025 1.58 jym 1026 1.58 jym /* Set Jumbo frame settings in the PHY. */ 1027 1.58 jym brgphy_jumbo_settings(sc); 1028 1.58 jym 1029 1.58 jym /* Enable Ethernet@Wirespeed */ 1030 1.58 jym brgphy_eth_wirespeed(sc); 1031 1.43 msaitoh } else { 1032 1.43 msaitoh if (!(sc->mii_flags & MIIF_HAVEFIBER)) { 1033 1.43 msaitoh brgphy_ber_bug(sc); 1034 1.18 hannken 1035 1.43 msaitoh /* Set Jumbo frame settings in the PHY. */ 1036 1.43 msaitoh brgphy_jumbo_settings(sc); 1037 1.18 hannken 1038 1.43 msaitoh /* Enable Ethernet@Wirespeed */ 1039 1.43 msaitoh brgphy_eth_wirespeed(sc); 1040 1.43 msaitoh } 1041 1.43 msaitoh } 1042 1.43 msaitoh } 1043 1.34 markd } 1044 1.34 markd 1045 1.16 jonathan /* Turn off tap power management on 5401. */ 1046 1.10 thorpej static void 1047 1.43 msaitoh brgphy_bcm5401_dspcode(struct mii_softc *sc) 1048 1.10 thorpej { 1049 1.10 thorpej static const struct { 1050 1.10 thorpej int reg; 1051 1.10 thorpej uint16_t val; 1052 1.10 thorpej } dspcode[] = { 1053 1.16 jonathan { BRGPHY_MII_AUXCTL, 0x0c20 }, 1054 1.10 thorpej { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 1055 1.10 thorpej { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 1056 1.10 thorpej { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 1057 1.10 thorpej { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 1058 1.10 thorpej { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 1059 1.10 thorpej { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 1060 1.10 thorpej { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 1061 1.10 thorpej { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 1062 1.10 thorpej { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 1063 1.10 thorpej { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 1064 1.10 thorpej { 0, 0 }, 1065 1.10 thorpej }; 1066 1.10 thorpej int i; 1067 1.10 thorpej 1068 1.10 thorpej for (i = 0; dspcode[i].reg != 0; i++) 1069 1.10 thorpej PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1070 1.61 msaitoh delay(40); 1071 1.10 thorpej } 1072 1.10 thorpej 1073 1.10 thorpej static void 1074 1.43 msaitoh brgphy_bcm5411_dspcode(struct mii_softc *sc) 1075 1.10 thorpej { 1076 1.10 thorpej static const struct { 1077 1.10 thorpej int reg; 1078 1.10 thorpej uint16_t val; 1079 1.10 thorpej } dspcode[] = { 1080 1.10 thorpej { 0x1c, 0x8c23 }, 1081 1.10 thorpej { 0x1c, 0x8ca3 }, 1082 1.10 thorpej { 0x1c, 0x8c23 }, 1083 1.15 jonathan { 0, 0 }, 1084 1.15 jonathan }; 1085 1.15 jonathan int i; 1086 1.15 jonathan 1087 1.15 jonathan for (i = 0; dspcode[i].reg != 0; i++) 1088 1.15 jonathan PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1089 1.15 jonathan } 1090 1.15 jonathan 1091 1.88 thorpej static void 1092 1.43 msaitoh brgphy_bcm5421_dspcode(struct mii_softc *sc) 1093 1.43 msaitoh { 1094 1.43 msaitoh uint16_t data; 1095 1.43 msaitoh 1096 1.43 msaitoh /* Set Class A mode */ 1097 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007); 1098 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_AUXCTL, &data); 1099 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400); 1100 1.43 msaitoh 1101 1.43 msaitoh /* Set FFE gamma override to -0.125 */ 1102 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007); 1103 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_AUXCTL, &data); 1104 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800); 1105 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); 1106 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT, &data); 1107 1.43 msaitoh PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200); 1108 1.43 msaitoh } 1109 1.43 msaitoh 1110 1.88 thorpej static void 1111 1.43 msaitoh brgphy_bcm54k2_dspcode(struct mii_softc *sc) 1112 1.43 msaitoh { 1113 1.43 msaitoh static const struct { 1114 1.43 msaitoh int reg; 1115 1.43 msaitoh uint16_t val; 1116 1.43 msaitoh } dspcode[] = { 1117 1.43 msaitoh { 4, 0x01e1 }, 1118 1.43 msaitoh { 9, 0x0300 }, 1119 1.43 msaitoh { 0, 0 }, 1120 1.43 msaitoh }; 1121 1.43 msaitoh int i; 1122 1.43 msaitoh 1123 1.43 msaitoh for (i = 0; dspcode[i].reg != 0; i++) 1124 1.43 msaitoh PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1125 1.43 msaitoh } 1126 1.43 msaitoh 1127 1.15 jonathan static void 1128 1.43 msaitoh brgphy_adc_bug(struct mii_softc *sc) 1129 1.15 jonathan { 1130 1.15 jonathan static const struct { 1131 1.15 jonathan int reg; 1132 1.15 jonathan uint16_t val; 1133 1.15 jonathan } dspcode[] = { 1134 1.15 jonathan { BRGPHY_MII_AUXCTL, 0x0c00 }, 1135 1.15 jonathan { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 1136 1.15 jonathan { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 1137 1.43 msaitoh { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 1138 1.43 msaitoh { BRGPHY_MII_DSP_RW_PORT, 0x0323 }, 1139 1.43 msaitoh { BRGPHY_MII_AUXCTL, 0x0400 }, 1140 1.15 jonathan { 0, 0 }, 1141 1.15 jonathan }; 1142 1.15 jonathan int i; 1143 1.15 jonathan 1144 1.15 jonathan for (i = 0; dspcode[i].reg != 0; i++) 1145 1.15 jonathan PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1146 1.15 jonathan } 1147 1.15 jonathan 1148 1.15 jonathan static void 1149 1.43 msaitoh brgphy_5704_a0_bug(struct mii_softc *sc) 1150 1.15 jonathan { 1151 1.15 jonathan static const struct { 1152 1.15 jonathan int reg; 1153 1.15 jonathan uint16_t val; 1154 1.15 jonathan } dspcode[] = { 1155 1.15 jonathan { 0x1c, 0x8d68 }, 1156 1.33 msaitoh { 0x1c, 0x8d68 }, 1157 1.10 thorpej { 0, 0 }, 1158 1.10 thorpej }; 1159 1.10 thorpej int i; 1160 1.10 thorpej 1161 1.10 thorpej for (i = 0; dspcode[i].reg != 0; i++) 1162 1.10 thorpej PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1163 1.1 thorpej } 1164 1.22 cube 1165 1.22 cube static void 1166 1.43 msaitoh brgphy_ber_bug(struct mii_softc *sc) 1167 1.22 cube { 1168 1.22 cube static const struct { 1169 1.22 cube int reg; 1170 1.22 cube uint16_t val; 1171 1.22 cube } dspcode[] = { 1172 1.22 cube { BRGPHY_MII_AUXCTL, 0x0c00 }, 1173 1.22 cube { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 1174 1.22 cube { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 1175 1.22 cube { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 1176 1.22 cube { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 1177 1.22 cube { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 1178 1.22 cube { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 1179 1.22 cube { BRGPHY_MII_AUXCTL, 0x0400 }, 1180 1.22 cube { 0, 0 }, 1181 1.22 cube }; 1182 1.22 cube int i; 1183 1.22 cube 1184 1.22 cube for (i = 0; dspcode[i].reg != 0; i++) 1185 1.22 cube PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1186 1.22 cube } 1187 1.34 markd 1188 1.43 msaitoh /* BCM5701 A0/B0 CRC bug workaround */ 1189 1.88 thorpej static void 1190 1.43 msaitoh brgphy_crc_bug(struct mii_softc *sc) 1191 1.34 markd { 1192 1.34 markd static const struct { 1193 1.34 markd int reg; 1194 1.34 markd uint16_t val; 1195 1.34 markd } dspcode[] = { 1196 1.43 msaitoh { BRGPHY_MII_DSP_ADDR_REG, 0x0a75 }, 1197 1.43 msaitoh { 0x1c, 0x8c68 }, 1198 1.43 msaitoh { 0x1c, 0x8d68 }, 1199 1.43 msaitoh { 0x1c, 0x8c68 }, 1200 1.34 markd { 0, 0 }, 1201 1.34 markd }; 1202 1.34 markd int i; 1203 1.34 markd 1204 1.34 markd for (i = 0; dspcode[i].reg != 0; i++) 1205 1.34 markd PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1206 1.34 markd } 1207 1.52 msaitoh 1208 1.52 msaitoh static void 1209 1.58 jym brgphy_disable_early_dac(struct mii_softc *sc) 1210 1.58 jym { 1211 1.79 msaitoh uint16_t val; 1212 1.58 jym 1213 1.58 jym PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08); 1214 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT, &val); 1215 1.58 jym val &= ~(1 << 8); 1216 1.58 jym PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val); 1217 1.58 jym 1218 1.58 jym } 1219 1.58 jym 1220 1.58 jym static void 1221 1.52 msaitoh brgphy_jumbo_settings(struct mii_softc *sc) 1222 1.52 msaitoh { 1223 1.79 msaitoh uint16_t val; 1224 1.52 msaitoh 1225 1.52 msaitoh /* Set Jumbo frame settings in the PHY. */ 1226 1.61 msaitoh if ((sc->mii_mpd_oui == MII_OUI_BROADCOM) 1227 1.61 msaitoh && (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5401)) { 1228 1.52 msaitoh /* Cannot do read-modify-write on the BCM5401 */ 1229 1.52 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); 1230 1.52 msaitoh } else { 1231 1.52 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 1232 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_AUXCTL, &val); 1233 1.52 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 1234 1.79 msaitoh val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); 1235 1.52 msaitoh } 1236 1.52 msaitoh 1237 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL, &val); 1238 1.79 msaitoh PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); 1239 1.52 msaitoh } 1240 1.52 msaitoh 1241 1.52 msaitoh static void 1242 1.52 msaitoh brgphy_eth_wirespeed(struct mii_softc *sc) 1243 1.52 msaitoh { 1244 1.79 msaitoh uint16_t val; 1245 1.52 msaitoh 1246 1.52 msaitoh /* Enable Ethernet@Wirespeed */ 1247 1.52 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); 1248 1.79 msaitoh PHY_READ(sc, BRGPHY_MII_AUXCTL, &val); 1249 1.79 msaitoh PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); 1250 1.52 msaitoh } 1251 1.90 jmcneill 1252 1.90 jmcneill static void 1253 1.90 jmcneill brgphy_bcm54xx_clock_delay(struct mii_softc *sc) 1254 1.90 jmcneill { 1255 1.90 jmcneill uint16_t val; 1256 1.90 jmcneill 1257 1.90 jmcneill PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_SHADOW_MISC | 1258 1.90 jmcneill BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT); 1259 1.90 jmcneill PHY_READ(sc, BRGPHY_MII_AUXCTL, &val); 1260 1.90 jmcneill val &= BRGPHY_AUXCTL_MISC_DATA_MASK; 1261 1.90 jmcneill if (sc->mii_flags & MIIF_RXID) 1262 1.90 jmcneill val |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN; 1263 1.90 jmcneill else 1264 1.90 jmcneill val &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN; 1265 1.90 jmcneill PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_MISC_WRITE_EN | 1266 1.90 jmcneill BRGPHY_AUXCTL_SHADOW_MISC | val); 1267 1.90 jmcneill 1268 1.90 jmcneill PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_CLK_CTRL); 1269 1.90 jmcneill PHY_READ(sc, BRGPHY_MII_SHADOW_1C, &val); 1270 1.90 jmcneill val &= BRGPHY_SHADOW_1C_DATA_MASK; 1271 1.90 jmcneill if (sc->mii_flags & MIIF_TXID) 1272 1.90 jmcneill val |= BRGPHY_SHADOW_1C_GTXCLK_EN; 1273 1.90 jmcneill else 1274 1.90 jmcneill val &= ~BRGPHY_SHADOW_1C_GTXCLK_EN; 1275 1.90 jmcneill PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_WRITE_EN | 1276 1.90 jmcneill BRGPHY_SHADOW_1C_CLK_CTRL | val); 1277 1.90 jmcneill } 1278