1 /* $NetBSD: ikphy.c,v 1.12 2016/11/02 07:01:54 msaitoh Exp $ */ 2 3 /******************************************************************************* 4 Copyright (c) 2001-2005, Intel Corporation 5 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 are met: 9 10 1. Redistributions of source code must retain the above copyright notice, 11 this list of conditions and the following disclaimer. 12 13 2. Redistributions in binary form must reproduce the above copyright 14 notice, this list of conditions and the following disclaimer in the 15 documentation and/or other materials provided with the distribution. 16 17 3. Neither the name of the Intel Corporation nor the names of its 18 contributors may be used to endorse or promote products derived from 19 this software without specific prior written permission. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 POSSIBILITY OF SUCH DAMAGE. 32 *******************************************************************************/ 33 /* 34 * Copyright (c) 2006 Manuel Bouyer. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 /* 58 * driver for Intel's i82563 ethernet 10/100/1000 PHY 59 */ 60 61 #include <sys/cdefs.h> 62 __KERNEL_RCSID(0, "$NetBSD: ikphy.c,v 1.12 2016/11/02 07:01:54 msaitoh Exp $"); 63 64 #include <sys/param.h> 65 #include <sys/systm.h> 66 #include <sys/kernel.h> 67 #include <sys/device.h> 68 #include <sys/socket.h> 69 #include <sys/errno.h> 70 71 #include <net/if.h> 72 #include <net/if_media.h> 73 74 #include <dev/mii/mii.h> 75 #include <dev/mii/miivar.h> 76 #include <dev/mii/miidevs.h> 77 78 #include <dev/mii/ikphyreg.h> 79 80 static int ikphymatch(device_t, cfdata_t, void *); 81 static void ikphyattach(device_t, device_t, void *); 82 83 CFATTACH_DECL_NEW(ikphy, sizeof(struct mii_softc), 84 ikphymatch, ikphyattach, mii_phy_detach, mii_phy_activate); 85 86 static int ikphy_service(struct mii_softc *, struct mii_data *, int); 87 static void ikphy_status(struct mii_softc *); 88 static void ikphy_setmedia(struct mii_softc *); 89 90 static const struct mii_phy_funcs ikphy_funcs = { 91 ikphy_service, ikphy_status, mii_phy_reset, 92 }; 93 94 static const struct mii_phydesc ikphys[] = { 95 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_I82563, 96 MII_STR_xxMARVELL_I82563 }, 97 98 { 0, 0, 99 NULL }, 100 }; 101 102 static int 103 ikphymatch(device_t parent, cfdata_t match, void *aux) 104 { 105 struct mii_attach_args *ma = aux; 106 107 if (mii_phy_match(ma, ikphys) != NULL) 108 return (10); 109 110 return (0); 111 } 112 113 static void 114 ikphyattach(device_t parent, device_t self, void *aux) 115 { 116 struct mii_softc *sc = device_private(self); 117 struct mii_attach_args *ma = aux; 118 struct mii_data *mii = ma->mii_data; 119 const struct mii_phydesc *mpd; 120 121 mpd = mii_phy_match(ma, ikphys); 122 aprint_naive(": Media interface\n"); 123 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 124 125 sc->mii_dev = self; 126 sc->mii_inst = mii->mii_instance; 127 sc->mii_phy = ma->mii_phyno; 128 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 129 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 130 sc->mii_mpd_rev = MII_REV(ma->mii_id2); 131 sc->mii_funcs = &ikphy_funcs; 132 sc->mii_pdata = mii; 133 sc->mii_flags = ma->mii_flags; 134 sc->mii_anegticks = MII_ANEGTICKS; 135 136 PHY_RESET(sc); 137 138 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 139 if (sc->mii_capabilities & BMSR_EXTSTAT) 140 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 141 aprint_normal_dev(self, ""); 142 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 143 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 144 aprint_error("no media present"); 145 else 146 mii_phy_add_media(sc); 147 aprint_normal("\n"); 148 } 149 150 static int 151 ikphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 152 { 153 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 154 int reg; 155 156 switch (cmd) { 157 case MII_POLLSTAT: 158 /* 159 * If we're not polling our PHY instance, just return. 160 */ 161 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 162 return (0); 163 break; 164 165 case MII_MEDIACHG: 166 /* 167 * If the media indicates a different PHY instance, 168 * isolate ourselves. 169 */ 170 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 171 reg = PHY_READ(sc, MII_BMCR); 172 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 173 return (0); 174 } 175 176 /* 177 * If the interface is not up, don't do anything. 178 */ 179 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 180 break; 181 182 ikphy_setmedia(sc); 183 break; 184 185 case MII_TICK: 186 /* 187 * If we're not currently selected, just return. 188 */ 189 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 190 return (0); 191 192 if (mii_phy_tick(sc) == EJUSTRETURN) 193 return (0); 194 break; 195 196 case MII_DOWN: 197 mii_phy_down(sc); 198 return (0); 199 } 200 201 /* Update the media status. */ 202 mii_phy_status(sc); 203 204 /* Callback if something changed. */ 205 mii_phy_update(sc, cmd); 206 return (0); 207 } 208 209 static void 210 ikphy_setmedia(struct mii_softc *sc) 211 { 212 uint16_t phy_data; 213 struct mii_data *mii = sc->mii_pdata; 214 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 215 216 /* Enable CRS on TX for half-duplex operation. */ 217 phy_data = PHY_READ(sc, GG82563_PHY_MAC_SPEC_CTRL); 218 phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; 219 /* Use 25MHz for both link down and 1000BASE-T for Tx clock */ 220 phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ; 221 PHY_WRITE(sc, GG82563_PHY_MAC_SPEC_CTRL, phy_data); 222 223 /* set mdi/mid-x options */ 224 phy_data = PHY_READ(sc, GG82563_PHY_SPEC_CTRL); 225 phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; 226 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) 227 phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; 228 else 229 phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI; 230 /* set polarity correction */ 231 phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; 232 PHY_WRITE(sc, GG82563_PHY_SPEC_CTRL, phy_data); 233 234 /* SW Reset the PHY so all changes take effect */ 235 PHY_RESET(sc); 236 237 /* for the i80003 */ 238 phy_data = PHY_READ(sc, GG82563_PHY_SPEC_CTRL_2); 239 phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; 240 PHY_WRITE(sc, GG82563_PHY_SPEC_CTRL_2, phy_data); 241 242 /* Enable Electrical Idle on the PHY */ 243 phy_data = PHY_READ(sc, GG82563_PHY_PWR_MGMT_CTRL); 244 phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; 245 PHY_WRITE(sc, GG82563_PHY_PWR_MGMT_CTRL, phy_data); 246 247 phy_data = PHY_READ(sc, GG82563_PHY_KMRN_MODE_CTRL); 248 phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; 249 PHY_WRITE(sc, GG82563_PHY_KMRN_MODE_CTRL, phy_data); 250 251 /* 252 * Workaround: Disable padding in Kumeran interface in the MAC 253 * and in the PHY to avoid CRC errors. 254 */ 255 phy_data = PHY_READ(sc, GG82563_PHY_INBAND_CTRL); 256 phy_data |= GG82563_ICR_DIS_PADDING; 257 PHY_WRITE(sc, GG82563_PHY_INBAND_CTRL, phy_data); 258 259 mii_phy_setmedia(sc); 260 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { 261 /* 262 * when not in auto mode, we need to restart nego 263 * anyway, or a switch from a fixed mode to another 264 * fixed mode may not be seen by the switch. 265 */ 266 PHY_WRITE(sc, MII_BMCR, 267 PHY_READ(sc, MII_BMCR) | BMCR_STARTNEG); 268 } 269 phy_data = PHY_READ(sc, GG82563_PHY_MAC_SPEC_CTRL); 270 phy_data &= ~GG82563_MSCR_TX_CLK_MASK; 271 switch(IFM_SUBTYPE(ife->ifm_media)) { 272 case IFM_10_T: 273 phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ; 274 break; 275 case IFM_100_TX: 276 phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ; 277 break; 278 case IFM_1000_T: 279 phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ; 280 break; 281 } 282 phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; 283 PHY_WRITE(sc, GG82563_PHY_MAC_SPEC_CTRL, phy_data); 284 } 285 286 static void 287 ikphy_status(struct mii_softc *sc) 288 { 289 struct mii_data *mii = sc->mii_pdata; 290 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 291 int pssr, bmcr, gtsr, kmrn; 292 293 mii->mii_media_status = IFM_AVALID; 294 mii->mii_media_active = IFM_ETHER; 295 296 pssr = PHY_READ(sc, GG82563_PHY_SPEC_STATUS); 297 298 if (pssr & GG82563_PSSR_LINK) 299 mii->mii_media_status |= IFM_ACTIVE; 300 301 bmcr = PHY_READ(sc, MII_BMCR); 302 if (bmcr & BMCR_ISO) { 303 mii->mii_media_active |= IFM_NONE; 304 mii->mii_media_status = 0; 305 return; 306 } 307 308 if (bmcr & BMCR_LOOP) 309 mii->mii_media_active |= IFM_LOOP; 310 311 if (bmcr & BMCR_AUTOEN) { 312 /* 313 * The media status bits are only valid of autonegotiation 314 * has completed (or it's disabled). 315 */ 316 if ((pssr & GG82563_PSSR_SPEED_DUPLEX_RESOLVED) == 0) { 317 /* Erg, still trying, I guess... */ 318 mii->mii_media_active |= IFM_NONE; 319 return; 320 } 321 322 switch (pssr & GG82563_PSSR_SPEED_MASK) { 323 case GG82563_PSSR_SPEED_1000MBPS: 324 mii->mii_media_active |= IFM_1000_T; 325 gtsr = PHY_READ(sc, MII_100T2SR); 326 if (gtsr & GTSR_MS_RES) 327 mii->mii_media_active |= IFM_ETH_MASTER; 328 break; 329 330 case GG82563_PSSR_SPEED_100MBPS: 331 mii->mii_media_active |= IFM_100_TX; 332 break; 333 334 case GG82563_PSSR_SPEED_10MBPS: 335 mii->mii_media_active |= IFM_10_T; 336 break; 337 338 default: 339 mii->mii_media_active |= IFM_NONE; 340 mii->mii_media_status = 0; 341 return; 342 } 343 344 if (pssr & GG82563_PSSR_DUPLEX) 345 mii->mii_media_active |= 346 IFM_FDX | mii_phy_flowstatus(sc); 347 else 348 mii->mii_media_active |= IFM_HDX; 349 } else 350 mii->mii_media_active = ife->ifm_media; 351 kmrn = PHY_READ(sc, GG82563_PHY_KMRN_MODE_CTRL); 352 if (mii->mii_media_active & IFM_FDX) 353 kmrn &= ~GG82563_KMCR_PASS_FALSE_CARRIER; 354 else 355 kmrn |= GG82563_KMCR_PASS_FALSE_CARRIER; 356 PHY_WRITE(sc, GG82563_PHY_KMRN_MODE_CTRL, kmrn); 357 } 358