1 /* 2 * Core PHY library, taken from phy.c 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation; either version 2 of the License, or (at your 7 * option) any later version. 8 */ 9 #include <linux/export.h> 10 #include <linux/phy.h> 11 12 const char *phy_speed_to_str(int speed) 13 { 14 switch (speed) { 15 case SPEED_10: 16 return "10Mbps"; 17 case SPEED_100: 18 return "100Mbps"; 19 case SPEED_1000: 20 return "1Gbps"; 21 case SPEED_2500: 22 return "2.5Gbps"; 23 case SPEED_5000: 24 return "5Gbps"; 25 case SPEED_10000: 26 return "10Gbps"; 27 case SPEED_14000: 28 return "14Gbps"; 29 case SPEED_20000: 30 return "20Gbps"; 31 case SPEED_25000: 32 return "25Gbps"; 33 case SPEED_40000: 34 return "40Gbps"; 35 case SPEED_50000: 36 return "50Gbps"; 37 case SPEED_56000: 38 return "56Gbps"; 39 case SPEED_100000: 40 return "100Gbps"; 41 case SPEED_UNKNOWN: 42 return "Unknown"; 43 default: 44 return "Unsupported (update phy-core.c)"; 45 } 46 } 47 EXPORT_SYMBOL_GPL(phy_speed_to_str); 48 49 const char *phy_duplex_to_str(unsigned int duplex) 50 { 51 if (duplex == DUPLEX_HALF) 52 return "Half"; 53 if (duplex == DUPLEX_FULL) 54 return "Full"; 55 if (duplex == DUPLEX_UNKNOWN) 56 return "Unknown"; 57 return "Unsupported (update phy-core.c)"; 58 } 59 EXPORT_SYMBOL_GPL(phy_duplex_to_str); 60 61 /* A mapping of all SUPPORTED settings to speed/duplex. This table 62 * must be grouped by speed and sorted in descending match priority 63 * - iow, descending speed. */ 64 static const struct phy_setting settings[] = { 65 { 66 .speed = SPEED_10000, 67 .duplex = DUPLEX_FULL, 68 .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 69 }, 70 { 71 .speed = SPEED_10000, 72 .duplex = DUPLEX_FULL, 73 .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 74 }, 75 { 76 .speed = SPEED_10000, 77 .duplex = DUPLEX_FULL, 78 .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 79 }, 80 { 81 .speed = SPEED_2500, 82 .duplex = DUPLEX_FULL, 83 .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT, 84 }, 85 { 86 .speed = SPEED_1000, 87 .duplex = DUPLEX_FULL, 88 .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 89 }, 90 { 91 .speed = SPEED_1000, 92 .duplex = DUPLEX_FULL, 93 .bit = ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 94 }, 95 { 96 .speed = SPEED_1000, 97 .duplex = DUPLEX_FULL, 98 .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 99 }, 100 { 101 .speed = SPEED_1000, 102 .duplex = DUPLEX_HALF, 103 .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT, 104 }, 105 { 106 .speed = SPEED_100, 107 .duplex = DUPLEX_FULL, 108 .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT, 109 }, 110 { 111 .speed = SPEED_100, 112 .duplex = DUPLEX_HALF, 113 .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT, 114 }, 115 { 116 .speed = SPEED_10, 117 .duplex = DUPLEX_FULL, 118 .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT, 119 }, 120 { 121 .speed = SPEED_10, 122 .duplex = DUPLEX_HALF, 123 .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT, 124 }, 125 }; 126 127 /** 128 * phy_lookup_setting - lookup a PHY setting 129 * @speed: speed to match 130 * @duplex: duplex to match 131 * @mask: allowed link modes 132 * @maxbit: bit size of link modes 133 * @exact: an exact match is required 134 * 135 * Search the settings array for a setting that matches the speed and 136 * duplex, and which is supported. 137 * 138 * If @exact is unset, either an exact match or %NULL for no match will 139 * be returned. 140 * 141 * If @exact is set, an exact match, the fastest supported setting at 142 * or below the specified speed, the slowest supported setting, or if 143 * they all fail, %NULL will be returned. 144 */ 145 const struct phy_setting * 146 phy_lookup_setting(int speed, int duplex, const unsigned long *mask, 147 size_t maxbit, bool exact) 148 { 149 const struct phy_setting *p, *match = NULL, *last = NULL; 150 int i; 151 152 for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { 153 if (p->bit < maxbit && test_bit(p->bit, mask)) { 154 last = p; 155 if (p->speed == speed && p->duplex == duplex) { 156 /* Exact match for speed and duplex */ 157 match = p; 158 break; 159 } else if (!exact) { 160 if (!match && p->speed <= speed) 161 /* Candidate */ 162 match = p; 163 164 if (p->speed < speed) 165 break; 166 } 167 } 168 } 169 170 if (!match && !exact) 171 match = last; 172 173 return match; 174 } 175 EXPORT_SYMBOL_GPL(phy_lookup_setting); 176 177 size_t phy_speeds(unsigned int *speeds, size_t size, 178 unsigned long *mask, size_t maxbit) 179 { 180 size_t count; 181 int i; 182 183 for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++) 184 if (settings[i].bit < maxbit && 185 test_bit(settings[i].bit, mask) && 186 (count == 0 || speeds[count - 1] != settings[i].speed)) 187 speeds[count++] = settings[i].speed; 188 189 return count; 190 } 191 192 static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad, 193 u16 regnum) 194 { 195 /* Write the desired MMD Devad */ 196 bus->write(bus, phy_addr, MII_MMD_CTRL, devad); 197 198 /* Write the desired MMD register address */ 199 bus->write(bus, phy_addr, MII_MMD_DATA, regnum); 200 201 /* Select the Function : DATA with no post increment */ 202 bus->write(bus, phy_addr, MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); 203 } 204 205 /** 206 * phy_read_mmd - Convenience function for reading a register 207 * from an MMD on a given PHY. 208 * @phydev: The phy_device struct 209 * @devad: The MMD to read from (0..31) 210 * @regnum: The register on the MMD to read (0..65535) 211 * 212 * Same rules as for phy_read(); 213 */ 214 int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) 215 { 216 int val; 217 218 if (regnum > (u16)~0 || devad > 32) 219 return -EINVAL; 220 221 if (phydev->drv->read_mmd) { 222 val = phydev->drv->read_mmd(phydev, devad, regnum); 223 } else if (phydev->is_c45) { 224 u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff); 225 226 val = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr); 227 } else { 228 struct mii_bus *bus = phydev->mdio.bus; 229 int phy_addr = phydev->mdio.addr; 230 231 mutex_lock(&bus->mdio_lock); 232 mmd_phy_indirect(bus, phy_addr, devad, regnum); 233 234 /* Read the content of the MMD's selected register */ 235 val = bus->read(bus, phy_addr, MII_MMD_DATA); 236 mutex_unlock(&bus->mdio_lock); 237 } 238 return val; 239 } 240 EXPORT_SYMBOL(phy_read_mmd); 241 242 /** 243 * phy_write_mmd - Convenience function for writing a register 244 * on an MMD on a given PHY. 245 * @phydev: The phy_device struct 246 * @devad: The MMD to read from 247 * @regnum: The register on the MMD to read 248 * @val: value to write to @regnum 249 * 250 * Same rules as for phy_write(); 251 */ 252 int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) 253 { 254 int ret; 255 256 if (regnum > (u16)~0 || devad > 32) 257 return -EINVAL; 258 259 if (phydev->drv->write_mmd) { 260 ret = phydev->drv->write_mmd(phydev, devad, regnum, val); 261 } else if (phydev->is_c45) { 262 u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff); 263 264 ret = mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, 265 addr, val); 266 } else { 267 struct mii_bus *bus = phydev->mdio.bus; 268 int phy_addr = phydev->mdio.addr; 269 270 mutex_lock(&bus->mdio_lock); 271 mmd_phy_indirect(bus, phy_addr, devad, regnum); 272 273 /* Write the data into MMD's selected register */ 274 bus->write(bus, phy_addr, MII_MMD_DATA, val); 275 mutex_unlock(&bus->mdio_lock); 276 277 ret = 0; 278 } 279 return ret; 280 } 281 EXPORT_SYMBOL(phy_write_mmd); 282