1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * drivers/net/phy/smsc.c 4 * 5 * Driver for SMSC PHYs 6 * 7 * Author: Herbert Valerio Riedel 8 * 9 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org> 10 * 11 * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net 12 * 13 */ 14 15 #include <linux/clk.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/mii.h> 19 #include <linux/ethtool.h> 20 #include <linux/of.h> 21 #include <linux/phy.h> 22 #include <linux/netdevice.h> 23 #include <linux/smscphy.h> 24 25 /* Vendor-specific PHY Definitions */ 26 /* EDPD NLP / crossover time configuration */ 27 #define PHY_EDPD_CONFIG 16 28 #define PHY_EDPD_CONFIG_EXT_CROSSOVER_ 0x0001 29 30 /* Control/Status Indication Register */ 31 #define SPECIAL_CTRL_STS 27 32 #define SPECIAL_CTRL_STS_OVRRD_AMDIX_ 0x8000 33 #define SPECIAL_CTRL_STS_AMDIX_ENABLE_ 0x4000 34 #define SPECIAL_CTRL_STS_AMDIX_STATE_ 0x2000 35 36 struct smsc_hw_stat { 37 const char *string; 38 u8 reg; 39 u8 bits; 40 }; 41 42 static struct smsc_hw_stat smsc_hw_stats[] = { 43 { "phy_symbol_errors", 26, 16}, 44 }; 45 46 struct smsc_phy_priv { 47 bool energy_enable; 48 }; 49 50 static int smsc_phy_ack_interrupt(struct phy_device *phydev) 51 { 52 int rc = phy_read(phydev, MII_LAN83C185_ISF); 53 54 return rc < 0 ? rc : 0; 55 } 56 57 int smsc_phy_config_intr(struct phy_device *phydev) 58 { 59 int rc; 60 61 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 62 rc = smsc_phy_ack_interrupt(phydev); 63 if (rc) 64 return rc; 65 66 rc = phy_write(phydev, MII_LAN83C185_IM, 67 MII_LAN83C185_ISF_INT_PHYLIB_EVENTS); 68 } else { 69 rc = phy_write(phydev, MII_LAN83C185_IM, 0); 70 if (rc) 71 return rc; 72 73 rc = smsc_phy_ack_interrupt(phydev); 74 } 75 76 return rc < 0 ? rc : 0; 77 } 78 EXPORT_SYMBOL_GPL(smsc_phy_config_intr); 79 80 irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev) 81 { 82 int irq_status; 83 84 irq_status = phy_read(phydev, MII_LAN83C185_ISF); 85 if (irq_status < 0) { 86 if (irq_status != -ENODEV) 87 phy_error(phydev); 88 89 return IRQ_NONE; 90 } 91 92 if (!(irq_status & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS)) 93 return IRQ_NONE; 94 95 phy_trigger_machine(phydev); 96 97 return IRQ_HANDLED; 98 } 99 EXPORT_SYMBOL_GPL(smsc_phy_handle_interrupt); 100 101 int smsc_phy_config_init(struct phy_device *phydev) 102 { 103 struct smsc_phy_priv *priv = phydev->priv; 104 105 if (!priv || !priv->energy_enable || phydev->irq != PHY_POLL) 106 return 0; 107 108 /* Enable energy detect power down mode */ 109 return phy_set_bits(phydev, MII_LAN83C185_CTRL_STATUS, 110 MII_LAN83C185_EDPWRDOWN); 111 } 112 EXPORT_SYMBOL_GPL(smsc_phy_config_init); 113 114 static int smsc_phy_reset(struct phy_device *phydev) 115 { 116 int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES); 117 if (rc < 0) 118 return rc; 119 120 /* If the SMSC PHY is in power down mode, then set it 121 * in all capable mode before using it. 122 */ 123 if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) { 124 /* set "all capable" mode */ 125 rc |= MII_LAN83C185_MODE_ALL; 126 phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc); 127 } 128 129 /* reset the phy */ 130 return genphy_soft_reset(phydev); 131 } 132 133 static int lan87xx_config_aneg(struct phy_device *phydev) 134 { 135 int rc; 136 int val; 137 138 switch (phydev->mdix_ctrl) { 139 case ETH_TP_MDI: 140 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_; 141 break; 142 case ETH_TP_MDI_X: 143 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ | 144 SPECIAL_CTRL_STS_AMDIX_STATE_; 145 break; 146 case ETH_TP_MDI_AUTO: 147 val = SPECIAL_CTRL_STS_AMDIX_ENABLE_; 148 break; 149 default: 150 return genphy_config_aneg(phydev); 151 } 152 153 rc = phy_read(phydev, SPECIAL_CTRL_STS); 154 if (rc < 0) 155 return rc; 156 157 rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ | 158 SPECIAL_CTRL_STS_AMDIX_ENABLE_ | 159 SPECIAL_CTRL_STS_AMDIX_STATE_); 160 rc |= val; 161 phy_write(phydev, SPECIAL_CTRL_STS, rc); 162 163 phydev->mdix = phydev->mdix_ctrl; 164 return genphy_config_aneg(phydev); 165 } 166 167 static int lan95xx_config_aneg_ext(struct phy_device *phydev) 168 { 169 if (phydev->phy_id == 0x0007c0f0) { /* LAN9500A or LAN9505A */ 170 /* Extend Manual AutoMDIX timer */ 171 int rc = phy_set_bits(phydev, PHY_EDPD_CONFIG, 172 PHY_EDPD_CONFIG_EXT_CROSSOVER_); 173 174 if (rc < 0) 175 return rc; 176 } 177 178 return lan87xx_config_aneg(phydev); 179 } 180 181 /* 182 * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable 183 * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to 184 * unstable detection of plugging in Ethernet cable. 185 * This workaround disables Energy Detect Power-Down mode and waiting for 186 * response on link pulses to detect presence of plugged Ethernet cable. 187 * The Energy Detect Power-Down mode is enabled again in the end of procedure to 188 * save approximately 220 mW of power if cable is unplugged. 189 * The workaround is only applicable to poll mode. Energy Detect Power-Down may 190 * not be used in interrupt mode lest link change detection becomes unreliable. 191 */ 192 int lan87xx_read_status(struct phy_device *phydev) 193 { 194 struct smsc_phy_priv *priv = phydev->priv; 195 int err; 196 197 err = genphy_read_status(phydev); 198 if (err) 199 return err; 200 201 if (!phydev->link && priv && priv->energy_enable && 202 phydev->irq == PHY_POLL) { 203 /* Disable EDPD to wake up PHY */ 204 int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); 205 if (rc < 0) 206 return rc; 207 208 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, 209 rc & ~MII_LAN83C185_EDPWRDOWN); 210 if (rc < 0) 211 return rc; 212 213 /* Wait max 640 ms to detect energy and the timeout is not 214 * an actual error. 215 */ 216 read_poll_timeout(phy_read, rc, 217 rc & MII_LAN83C185_ENERGYON || rc < 0, 218 10000, 640000, true, phydev, 219 MII_LAN83C185_CTRL_STATUS); 220 if (rc < 0) 221 return rc; 222 223 /* Re-enable EDPD */ 224 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); 225 if (rc < 0) 226 return rc; 227 228 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, 229 rc | MII_LAN83C185_EDPWRDOWN); 230 if (rc < 0) 231 return rc; 232 } 233 234 return err; 235 } 236 EXPORT_SYMBOL_GPL(lan87xx_read_status); 237 238 static int smsc_get_sset_count(struct phy_device *phydev) 239 { 240 return ARRAY_SIZE(smsc_hw_stats); 241 } 242 243 static void smsc_get_strings(struct phy_device *phydev, u8 *data) 244 { 245 int i; 246 247 for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) { 248 strncpy(data + i * ETH_GSTRING_LEN, 249 smsc_hw_stats[i].string, ETH_GSTRING_LEN); 250 } 251 } 252 253 static u64 smsc_get_stat(struct phy_device *phydev, int i) 254 { 255 struct smsc_hw_stat stat = smsc_hw_stats[i]; 256 int val; 257 u64 ret; 258 259 val = phy_read(phydev, stat.reg); 260 if (val < 0) 261 ret = U64_MAX; 262 else 263 ret = val; 264 265 return ret; 266 } 267 268 static void smsc_get_stats(struct phy_device *phydev, 269 struct ethtool_stats *stats, u64 *data) 270 { 271 int i; 272 273 for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) 274 data[i] = smsc_get_stat(phydev, i); 275 } 276 277 int smsc_phy_probe(struct phy_device *phydev) 278 { 279 struct device *dev = &phydev->mdio.dev; 280 struct smsc_phy_priv *priv; 281 struct clk *refclk; 282 283 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 284 if (!priv) 285 return -ENOMEM; 286 287 priv->energy_enable = true; 288 289 if (device_property_present(dev, "smsc,disable-energy-detect")) 290 priv->energy_enable = false; 291 292 phydev->priv = priv; 293 294 /* Make clk optional to keep DTB backward compatibility. */ 295 refclk = devm_clk_get_optional_enabled(dev, NULL); 296 if (IS_ERR(refclk)) 297 return dev_err_probe(dev, PTR_ERR(refclk), 298 "Failed to request clock\n"); 299 300 return clk_set_rate(refclk, 50 * 1000 * 1000); 301 } 302 EXPORT_SYMBOL_GPL(smsc_phy_probe); 303 304 static struct phy_driver smsc_phy_driver[] = { 305 { 306 .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ 307 .phy_id_mask = 0xfffffff0, 308 .name = "SMSC LAN83C185", 309 310 /* PHY_BASIC_FEATURES */ 311 312 .probe = smsc_phy_probe, 313 314 /* basic functions */ 315 .config_init = smsc_phy_config_init, 316 .soft_reset = smsc_phy_reset, 317 318 /* IRQ related */ 319 .config_intr = smsc_phy_config_intr, 320 .handle_interrupt = smsc_phy_handle_interrupt, 321 322 .suspend = genphy_suspend, 323 .resume = genphy_resume, 324 }, { 325 .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */ 326 .phy_id_mask = 0xfffffff0, 327 .name = "SMSC LAN8187", 328 329 /* PHY_BASIC_FEATURES */ 330 331 .probe = smsc_phy_probe, 332 333 /* basic functions */ 334 .config_init = smsc_phy_config_init, 335 .soft_reset = smsc_phy_reset, 336 337 /* IRQ related */ 338 .config_intr = smsc_phy_config_intr, 339 .handle_interrupt = smsc_phy_handle_interrupt, 340 341 /* Statistics */ 342 .get_sset_count = smsc_get_sset_count, 343 .get_strings = smsc_get_strings, 344 .get_stats = smsc_get_stats, 345 346 .suspend = genphy_suspend, 347 .resume = genphy_resume, 348 }, { 349 /* This covers internal PHY (phy_id: 0x0007C0C3) for 350 * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505) 351 */ 352 .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */ 353 .phy_id_mask = 0xfffffff0, 354 .name = "SMSC LAN8700", 355 356 /* PHY_BASIC_FEATURES */ 357 358 .probe = smsc_phy_probe, 359 360 /* basic functions */ 361 .read_status = lan87xx_read_status, 362 .config_init = smsc_phy_config_init, 363 .soft_reset = smsc_phy_reset, 364 .config_aneg = lan87xx_config_aneg, 365 366 /* IRQ related */ 367 .config_intr = smsc_phy_config_intr, 368 .handle_interrupt = smsc_phy_handle_interrupt, 369 370 /* Statistics */ 371 .get_sset_count = smsc_get_sset_count, 372 .get_strings = smsc_get_strings, 373 .get_stats = smsc_get_stats, 374 375 .suspend = genphy_suspend, 376 .resume = genphy_resume, 377 }, { 378 .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */ 379 .phy_id_mask = 0xfffffff0, 380 .name = "SMSC LAN911x Internal PHY", 381 382 /* PHY_BASIC_FEATURES */ 383 384 .probe = smsc_phy_probe, 385 386 /* IRQ related */ 387 .config_intr = smsc_phy_config_intr, 388 .handle_interrupt = smsc_phy_handle_interrupt, 389 390 .suspend = genphy_suspend, 391 .resume = genphy_resume, 392 }, { 393 /* This covers internal PHY (phy_id: 0x0007C0F0) for 394 * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01) 395 */ 396 .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */ 397 .phy_id_mask = 0xfffffff0, 398 .name = "SMSC LAN8710/LAN8720", 399 400 /* PHY_BASIC_FEATURES */ 401 402 .probe = smsc_phy_probe, 403 404 /* basic functions */ 405 .read_status = lan87xx_read_status, 406 .config_init = smsc_phy_config_init, 407 .soft_reset = smsc_phy_reset, 408 .config_aneg = lan95xx_config_aneg_ext, 409 410 /* IRQ related */ 411 .config_intr = smsc_phy_config_intr, 412 .handle_interrupt = smsc_phy_handle_interrupt, 413 414 /* Statistics */ 415 .get_sset_count = smsc_get_sset_count, 416 .get_strings = smsc_get_strings, 417 .get_stats = smsc_get_stats, 418 419 .suspend = genphy_suspend, 420 .resume = genphy_resume, 421 }, { 422 .phy_id = 0x0007c110, 423 .phy_id_mask = 0xfffffff0, 424 .name = "SMSC LAN8740", 425 426 /* PHY_BASIC_FEATURES */ 427 .flags = PHY_RST_AFTER_CLK_EN, 428 429 .probe = smsc_phy_probe, 430 431 /* basic functions */ 432 .read_status = lan87xx_read_status, 433 .config_init = smsc_phy_config_init, 434 .soft_reset = smsc_phy_reset, 435 436 /* IRQ related */ 437 .config_intr = smsc_phy_config_intr, 438 .handle_interrupt = smsc_phy_handle_interrupt, 439 440 /* Statistics */ 441 .get_sset_count = smsc_get_sset_count, 442 .get_strings = smsc_get_strings, 443 .get_stats = smsc_get_stats, 444 445 .suspend = genphy_suspend, 446 .resume = genphy_resume, 447 }, { 448 .phy_id = 0x0007c130, /* 0x0007c130 and 0x0007c131 */ 449 /* This mask (0xfffffff2) is to differentiate from 450 * LAN88xx (phy_id 0x0007c132) 451 * and allows future phy_id revisions. 452 */ 453 .phy_id_mask = 0xfffffff2, 454 .name = "Microchip LAN8742", 455 456 /* PHY_BASIC_FEATURES */ 457 .flags = PHY_RST_AFTER_CLK_EN, 458 459 .probe = smsc_phy_probe, 460 461 /* basic functions */ 462 .read_status = lan87xx_read_status, 463 .config_init = smsc_phy_config_init, 464 .soft_reset = smsc_phy_reset, 465 466 /* IRQ related */ 467 .config_intr = smsc_phy_config_intr, 468 .handle_interrupt = smsc_phy_handle_interrupt, 469 470 /* Statistics */ 471 .get_sset_count = smsc_get_sset_count, 472 .get_strings = smsc_get_strings, 473 .get_stats = smsc_get_stats, 474 475 .suspend = genphy_suspend, 476 .resume = genphy_resume, 477 } }; 478 479 module_phy_driver(smsc_phy_driver); 480 481 MODULE_DESCRIPTION("SMSC PHY driver"); 482 MODULE_AUTHOR("Herbert Valerio Riedel"); 483 MODULE_LICENSE("GPL"); 484 485 static struct mdio_device_id __maybe_unused smsc_tbl[] = { 486 { 0x0007c0a0, 0xfffffff0 }, 487 { 0x0007c0b0, 0xfffffff0 }, 488 { 0x0007c0c0, 0xfffffff0 }, 489 { 0x0007c0d0, 0xfffffff0 }, 490 { 0x0007c0f0, 0xfffffff0 }, 491 { 0x0007c110, 0xfffffff0 }, 492 { 0x0007c130, 0xfffffff2 }, 493 { } 494 }; 495 496 MODULE_DEVICE_TABLE(mdio, smsc_tbl); 497