1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021 Alstom Group. 5 * Copyright (c) 2021 Semihalf. 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Driver for TI DP83867 Ethernet PHY 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 #include <sys/resource.h> 41 #include <sys/rman.h> 42 #include <sys/socket.h> 43 44 #include <machine/resource.h> 45 46 #include <net/if.h> 47 #include <net/if_media.h> 48 49 #include <dev/mii/mii.h> 50 #include <dev/mii/miivar.h> 51 52 #include "miidevs.h" 53 #include "miibus_if.h" 54 55 #define BIT(x) (1 << (x)) 56 57 #define DP83867_PHYCR 0x10 58 #define DP83867_PHYSTS 0x11 59 #define DP83867_MICR 0x12 60 #define DP83867_ISR 0x13 61 #define DP83867_CFG3 0x1E 62 #define DP83867_CTRL 0x1F 63 #define DP83867_CFG4 0x31 64 #define DP83867_RGMIICTL 0x32 65 #define DP83867_STRP_STS1 0x6E 66 #define DP83867_STRP_STS2 0x6F 67 68 #define DP83867_PHYSTS_LINK_UP BIT(10) 69 #define DP83867_PHYSTS_ANEG_PENDING BIT(11) 70 #define DP83867_PHYSTS_FD BIT(13) 71 #define DP83867_PHYSTS_SPEED_MASK (BIT(15) | BIT(14)) 72 #define DP83867_PHYSTS_SPEED_1000 BIT(15) 73 #define DP83867_PHYSTS_SPEED_100 BIT(14) 74 #define DP83867_PHYSTS_SPEED_10 0 75 76 #define DP83867_MICR_AN_ERR BIT(15) 77 #define DP83867_MICR_SPEED_CHG BIT(14) 78 #define DP83867_MICR_DP_MODE_CHG BIT(13) 79 #define DP83867_MICR_AN_CMPL BIT(11) 80 #define DP83867_MICR_LINK_CHG BIT(10) 81 82 #define DP83867_CFG3_INT_OE BIT(7) 83 84 #define DP83867_CFG4_TST_MODE1 BIT(7) 85 #define DP83867_CFG4_ANEG_MASK (BIT(5) | BIT(6)) 86 #define DP83867_CFG4_ANEG_16MS (0 << 5) 87 88 #define BMSR_100_MASK (BMSR_100T4 | BMSR_100TXFDX | BMSR_100TXHDX | \ 89 BMSR_100T2FDX | BMSR_100T2HDX) 90 91 static int dp_probe(device_t); 92 static int dp_attach(device_t); 93 94 static int dp_service(struct mii_softc*, struct mii_data*, int); 95 static void dp_status(struct mii_softc*); 96 97 struct dp83867_softc { 98 struct mii_softc mii_sc; 99 struct resource *irq_res; 100 void *irq_cookie; 101 }; 102 103 static const struct mii_phydesc dpphys[] = { 104 MII_PHY_DESC(xxTI, DP83867), 105 MII_PHY_END 106 }; 107 108 static const struct mii_phy_funcs dpphy_funcs = { 109 dp_service, 110 dp_status, 111 mii_phy_reset 112 }; 113 114 static void 115 dp_intr(void *arg) 116 { 117 struct mii_softc *sc = (struct mii_softc *)arg; 118 uint32_t status; 119 120 status = PHY_READ(sc, DP83867_ISR); 121 status &= PHY_READ(sc, DP83867_MICR); 122 if (!status) 123 return; 124 125 PHY_STATUS(sc); 126 mii_phy_update(sc, MII_MEDIACHG); 127 } 128 129 static int 130 dp_probe(device_t dev) 131 { 132 133 return (mii_phy_dev_probe(dev, dpphys, BUS_PROBE_DEFAULT)); 134 } 135 136 static int 137 dp_attach(device_t dev) 138 { 139 struct dp83867_softc *sc; 140 struct mii_softc *mii_sc; 141 uint32_t value, maxspeed; 142 ssize_t size; 143 int rid, error; 144 145 sc = device_get_softc(dev); 146 mii_sc = &sc->mii_sc; 147 148 size = device_get_property(dev, "max-speed", &maxspeed, 149 sizeof(maxspeed), DEVICE_PROP_UINT32); 150 if (size <= 0) 151 maxspeed = 0; 152 153 mii_sc->mii_maxspeed = maxspeed; 154 mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &dpphy_funcs, 1); 155 156 rid = 0; 157 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 158 if (sc->irq_res == NULL) 159 goto no_irq; 160 161 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, 162 NULL, dp_intr, sc, &sc->irq_cookie); 163 if (error != 0) { 164 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 165 sc->irq_res = NULL; 166 goto no_irq; 167 } 168 169 /* Ack and unmask all relevant interrupts. */ 170 (void)PHY_READ(mii_sc, DP83867_ISR); 171 value = DP83867_MICR_AN_ERR | 172 DP83867_MICR_SPEED_CHG | 173 DP83867_MICR_DP_MODE_CHG | 174 DP83867_MICR_AN_CMPL | 175 DP83867_MICR_LINK_CHG; 176 PHY_WRITE(mii_sc, DP83867_MICR, value); 177 178 value = PHY_READ(mii_sc, DP83867_CFG3); 179 value |= DP83867_CFG3_INT_OE; 180 PHY_WRITE(mii_sc, DP83867_CFG3, value); 181 182 no_irq: 183 /* Set autonegotation timeout to max possible value. */ 184 value = PHY_READ(mii_sc, DP83867_CFG4); 185 value &= ~DP83867_CFG4_ANEG_MASK; 186 value &= ~DP83867_CFG4_TST_MODE1; 187 value |= DP83867_CFG4_ANEG_16MS; 188 PHY_WRITE(mii_sc, DP83867_CFG4, value); 189 190 return (0); 191 } 192 193 static int 194 dp_detach(device_t dev) 195 { 196 struct dp83867_softc *sc; 197 198 sc = device_get_softc(dev); 199 200 bus_teardown_intr(dev, sc->irq_res, sc->irq_cookie); 201 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 202 203 return (mii_phy_detach(dev)); 204 } 205 206 static int 207 dp_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 208 { 209 210 switch (cmd) { 211 case MII_POLLSTAT: 212 break; 213 case MII_MEDIACHG: 214 mii_phy_setmedia(sc); 215 break; 216 case MII_TICK: 217 if (mii_phy_tick(sc) == EJUSTRETURN) 218 return (0); 219 220 break; 221 } 222 223 PHY_STATUS(sc); 224 mii_phy_update(sc, cmd); 225 return (0); 226 } 227 228 static void 229 dp_status(struct mii_softc *sc) 230 { 231 struct mii_data *mii; 232 int bmsr, bmcr, physts; 233 234 mii = sc->mii_pdata; 235 mii->mii_media_status = IFM_AVALID; 236 mii->mii_media_active = IFM_ETHER; 237 238 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 239 physts = PHY_READ(sc, DP83867_PHYSTS); 240 241 if ((bmsr & BMSR_LINK) && (physts & DP83867_PHYSTS_LINK_UP)) 242 mii->mii_media_status |= IFM_ACTIVE; 243 244 bmcr = PHY_READ(sc, MII_BMCR); 245 if (bmcr & BMCR_ISO) { 246 mii->mii_media_active |= IFM_NONE; 247 mii->mii_media_status = 0; 248 return; 249 } 250 251 if (bmcr & BMCR_LOOP) 252 mii->mii_media_active |= IFM_LOOP; 253 254 /* Autoneg in progress. */ 255 if (!(physts & DP83867_PHYSTS_ANEG_PENDING)) { 256 mii->mii_media_active |= IFM_NONE; 257 return; 258 } 259 260 switch (physts & DP83867_PHYSTS_SPEED_MASK) { 261 case DP83867_PHYSTS_SPEED_1000: 262 mii->mii_media_active |= IFM_1000_T; 263 break; 264 case DP83867_PHYSTS_SPEED_100: 265 mii->mii_media_active |= IFM_100_TX; 266 break; 267 case DP83867_PHYSTS_SPEED_10: 268 mii->mii_media_active |= IFM_10_T; 269 break; 270 default: 271 mii->mii_media_active |= IFM_NONE; 272 break; 273 } 274 if (physts & DP83867_PHYSTS_FD) 275 mii->mii_media_active |= IFM_FDX; 276 else 277 mii->mii_media_active |= IFM_HDX; 278 279 } 280 281 static device_method_t dp_methods[] = { 282 DEVMETHOD(device_probe, dp_probe), 283 DEVMETHOD(device_attach, dp_attach), 284 DEVMETHOD(device_detach, dp_detach), 285 DEVMETHOD_END 286 }; 287 288 static driver_t dp_driver = { 289 "dp83867phy", 290 dp_methods, 291 sizeof(struct dp83867_softc) 292 }; 293 294 DRIVER_MODULE(dp83867phy, miibus, dp_driver, 0, 0); 295