mdio_10g.c (8927B)
1// SPDX-License-Identifier: GPL-2.0-only 2/**************************************************************************** 3 * Driver for Solarflare network controllers and boards 4 * Copyright 2006-2011 Solarflare Communications Inc. 5 */ 6/* 7 * Useful functions for working with MDIO clause 45 PHYs 8 */ 9#include <linux/types.h> 10#include <linux/ethtool.h> 11#include <linux/delay.h> 12#include "net_driver.h" 13#include "mdio_10g.h" 14#include "workarounds.h" 15 16unsigned ef4_mdio_id_oui(u32 id) 17{ 18 unsigned oui = 0; 19 int i; 20 21 /* The bits of the OUI are designated a..x, with a=0 and b variable. 22 * In the id register c is the MSB but the OUI is conventionally 23 * written as bytes h..a, p..i, x..q. Reorder the bits accordingly. */ 24 for (i = 0; i < 22; ++i) 25 if (id & (1 << (i + 10))) 26 oui |= 1 << (i ^ 7); 27 28 return oui; 29} 30 31int ef4_mdio_reset_mmd(struct ef4_nic *port, int mmd, 32 int spins, int spintime) 33{ 34 u32 ctrl; 35 36 /* Catch callers passing values in the wrong units (or just silly) */ 37 EF4_BUG_ON_PARANOID(spins * spintime >= 5000); 38 39 ef4_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET); 40 /* Wait for the reset bit to clear. */ 41 do { 42 msleep(spintime); 43 ctrl = ef4_mdio_read(port, mmd, MDIO_CTRL1); 44 spins--; 45 46 } while (spins && (ctrl & MDIO_CTRL1_RESET)); 47 48 return spins ? spins : -ETIMEDOUT; 49} 50 51static int ef4_mdio_check_mmd(struct ef4_nic *efx, int mmd) 52{ 53 int status; 54 55 if (mmd != MDIO_MMD_AN) { 56 /* Read MMD STATUS2 to check it is responding. */ 57 status = ef4_mdio_read(efx, mmd, MDIO_STAT2); 58 if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) { 59 netif_err(efx, hw, efx->net_dev, 60 "PHY MMD %d not responding.\n", mmd); 61 return -EIO; 62 } 63 } 64 65 return 0; 66} 67 68/* This ought to be ridiculous overkill. We expect it to fail rarely */ 69#define MDIO45_RESET_TIME 1000 /* ms */ 70#define MDIO45_RESET_ITERS 100 71 72int ef4_mdio_wait_reset_mmds(struct ef4_nic *efx, unsigned int mmd_mask) 73{ 74 const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; 75 int tries = MDIO45_RESET_ITERS; 76 int rc = 0; 77 int in_reset; 78 79 while (tries) { 80 int mask = mmd_mask; 81 int mmd = 0; 82 int stat; 83 in_reset = 0; 84 while (mask) { 85 if (mask & 1) { 86 stat = ef4_mdio_read(efx, mmd, MDIO_CTRL1); 87 if (stat < 0) { 88 netif_err(efx, hw, efx->net_dev, 89 "failed to read status of" 90 " MMD %d\n", mmd); 91 return -EIO; 92 } 93 if (stat & MDIO_CTRL1_RESET) 94 in_reset |= (1 << mmd); 95 } 96 mask = mask >> 1; 97 mmd++; 98 } 99 if (!in_reset) 100 break; 101 tries--; 102 msleep(spintime); 103 } 104 if (in_reset != 0) { 105 netif_err(efx, hw, efx->net_dev, 106 "not all MMDs came out of reset in time." 107 " MMDs still in reset: %x\n", in_reset); 108 rc = -ETIMEDOUT; 109 } 110 return rc; 111} 112 113int ef4_mdio_check_mmds(struct ef4_nic *efx, unsigned int mmd_mask) 114{ 115 int mmd = 0, probe_mmd, devs1, devs2; 116 u32 devices; 117 118 /* Historically we have probed the PHYXS to find out what devices are 119 * present,but that doesn't work so well if the PHYXS isn't expected 120 * to exist, if so just find the first item in the list supplied. */ 121 probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS : 122 __ffs(mmd_mask); 123 124 /* Check all the expected MMDs are present */ 125 devs1 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS1); 126 devs2 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS2); 127 if (devs1 < 0 || devs2 < 0) { 128 netif_err(efx, hw, efx->net_dev, 129 "failed to read devices present\n"); 130 return -EIO; 131 } 132 devices = devs1 | (devs2 << 16); 133 if ((devices & mmd_mask) != mmd_mask) { 134 netif_err(efx, hw, efx->net_dev, 135 "required MMDs not present: got %x, wanted %x\n", 136 devices, mmd_mask); 137 return -ENODEV; 138 } 139 netif_vdbg(efx, hw, efx->net_dev, "Devices present: %x\n", devices); 140 141 /* Check all required MMDs are responding and happy. */ 142 while (mmd_mask) { 143 if ((mmd_mask & 1) && ef4_mdio_check_mmd(efx, mmd)) 144 return -EIO; 145 mmd_mask = mmd_mask >> 1; 146 mmd++; 147 } 148 149 return 0; 150} 151 152bool ef4_mdio_links_ok(struct ef4_nic *efx, unsigned int mmd_mask) 153{ 154 /* If the port is in loopback, then we should only consider a subset 155 * of mmd's */ 156 if (LOOPBACK_INTERNAL(efx)) 157 return true; 158 else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS) 159 return false; 160 else if (ef4_phy_mode_disabled(efx->phy_mode)) 161 return false; 162 else if (efx->loopback_mode == LOOPBACK_PHYXS) 163 mmd_mask &= ~(MDIO_DEVS_PHYXS | 164 MDIO_DEVS_PCS | 165 MDIO_DEVS_PMAPMD | 166 MDIO_DEVS_AN); 167 else if (efx->loopback_mode == LOOPBACK_PCS) 168 mmd_mask &= ~(MDIO_DEVS_PCS | 169 MDIO_DEVS_PMAPMD | 170 MDIO_DEVS_AN); 171 else if (efx->loopback_mode == LOOPBACK_PMAPMD) 172 mmd_mask &= ~(MDIO_DEVS_PMAPMD | 173 MDIO_DEVS_AN); 174 175 return mdio45_links_ok(&efx->mdio, mmd_mask); 176} 177 178void ef4_mdio_transmit_disable(struct ef4_nic *efx) 179{ 180 ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, 181 MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL, 182 efx->phy_mode & PHY_MODE_TX_DISABLED); 183} 184 185void ef4_mdio_phy_reconfigure(struct ef4_nic *efx) 186{ 187 ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, 188 MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK, 189 efx->loopback_mode == LOOPBACK_PMAPMD); 190 ef4_mdio_set_flag(efx, MDIO_MMD_PCS, 191 MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK, 192 efx->loopback_mode == LOOPBACK_PCS); 193 ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, 194 MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK, 195 efx->loopback_mode == LOOPBACK_PHYXS_WS); 196} 197 198static void ef4_mdio_set_mmd_lpower(struct ef4_nic *efx, 199 int lpower, int mmd) 200{ 201 int stat = ef4_mdio_read(efx, mmd, MDIO_STAT1); 202 203 netif_vdbg(efx, drv, efx->net_dev, "Setting low power mode for MMD %d to %d\n", 204 mmd, lpower); 205 206 if (stat & MDIO_STAT1_LPOWERABLE) { 207 ef4_mdio_set_flag(efx, mmd, MDIO_CTRL1, 208 MDIO_CTRL1_LPOWER, lpower); 209 } 210} 211 212void ef4_mdio_set_mmds_lpower(struct ef4_nic *efx, 213 int low_power, unsigned int mmd_mask) 214{ 215 int mmd = 0; 216 mmd_mask &= ~MDIO_DEVS_AN; 217 while (mmd_mask) { 218 if (mmd_mask & 1) 219 ef4_mdio_set_mmd_lpower(efx, low_power, mmd); 220 mmd_mask = (mmd_mask >> 1); 221 mmd++; 222 } 223} 224 225/** 226 * ef4_mdio_set_link_ksettings - Set (some of) the PHY settings over MDIO. 227 * @efx: Efx NIC 228 * @cmd: New settings 229 */ 230int ef4_mdio_set_link_ksettings(struct ef4_nic *efx, 231 const struct ethtool_link_ksettings *cmd) 232{ 233 struct ethtool_link_ksettings prev = { 234 .base.cmd = ETHTOOL_GLINKSETTINGS 235 }; 236 u32 prev_advertising, advertising; 237 u32 prev_supported; 238 239 efx->phy_op->get_link_ksettings(efx, &prev); 240 241 ethtool_convert_link_mode_to_legacy_u32(&advertising, 242 cmd->link_modes.advertising); 243 ethtool_convert_link_mode_to_legacy_u32(&prev_advertising, 244 prev.link_modes.advertising); 245 ethtool_convert_link_mode_to_legacy_u32(&prev_supported, 246 prev.link_modes.supported); 247 248 if (advertising == prev_advertising && 249 cmd->base.speed == prev.base.speed && 250 cmd->base.duplex == prev.base.duplex && 251 cmd->base.port == prev.base.port && 252 cmd->base.autoneg == prev.base.autoneg) 253 return 0; 254 255 /* We can only change these settings for -T PHYs */ 256 if (prev.base.port != PORT_TP || cmd->base.port != PORT_TP) 257 return -EINVAL; 258 259 /* Check that PHY supports these settings */ 260 if (!cmd->base.autoneg || 261 (advertising | SUPPORTED_Autoneg) & ~prev_supported) 262 return -EINVAL; 263 264 ef4_link_set_advertising(efx, advertising | ADVERTISED_Autoneg); 265 ef4_mdio_an_reconfigure(efx); 266 return 0; 267} 268 269/** 270 * ef4_mdio_an_reconfigure - Push advertising flags and restart autonegotiation 271 * @efx: Efx NIC 272 */ 273void ef4_mdio_an_reconfigure(struct ef4_nic *efx) 274{ 275 int reg; 276 277 WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); 278 279 /* Set up the base page */ 280 reg = ADVERTISE_CSMA | ADVERTISE_RESV; 281 if (efx->link_advertising & ADVERTISED_Pause) 282 reg |= ADVERTISE_PAUSE_CAP; 283 if (efx->link_advertising & ADVERTISED_Asym_Pause) 284 reg |= ADVERTISE_PAUSE_ASYM; 285 ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); 286 287 /* Set up the (extended) next page */ 288 efx->phy_op->set_npage_adv(efx, efx->link_advertising); 289 290 /* Enable and restart AN */ 291 reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); 292 reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP; 293 ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); 294} 295 296u8 ef4_mdio_get_pause(struct ef4_nic *efx) 297{ 298 BUILD_BUG_ON(EF4_FC_AUTO & (EF4_FC_RX | EF4_FC_TX)); 299 300 if (!(efx->wanted_fc & EF4_FC_AUTO)) 301 return efx->wanted_fc; 302 303 WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); 304 305 return mii_resolve_flowctrl_fdx( 306 mii_advertise_flowctrl(efx->wanted_fc), 307 ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); 308} 309 310int ef4_mdio_test_alive(struct ef4_nic *efx) 311{ 312 int rc; 313 int devad = __ffs(efx->mdio.mmds); 314 u16 physid1, physid2; 315 316 mutex_lock(&efx->mac_lock); 317 318 physid1 = ef4_mdio_read(efx, devad, MDIO_DEVID1); 319 physid2 = ef4_mdio_read(efx, devad, MDIO_DEVID2); 320 321 if ((physid1 == 0x0000) || (physid1 == 0xffff) || 322 (physid2 == 0x0000) || (physid2 == 0xffff)) { 323 netif_err(efx, hw, efx->net_dev, 324 "no MDIO PHY present with ID %d\n", efx->mdio.prtad); 325 rc = -EINVAL; 326 } else { 327 rc = ef4_mdio_check_mmds(efx, efx->mdio.mmds); 328 } 329 330 mutex_unlock(&efx->mac_lock); 331 return rc; 332}