1a2443fd1SAndrew Lunn // SPDX-License-Identifier: GPL-2.0+ 2c9e055acSHerbert Valerio Riedel /* 3c9e055acSHerbert Valerio Riedel * drivers/net/phy/smsc.c 4c9e055acSHerbert Valerio Riedel * 5c9e055acSHerbert Valerio Riedel * Driver for SMSC PHYs 6c9e055acSHerbert Valerio Riedel * 7c9e055acSHerbert Valerio Riedel * Author: Herbert Valerio Riedel 8c9e055acSHerbert Valerio Riedel * 9c9e055acSHerbert Valerio Riedel * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org> 10c9e055acSHerbert Valerio Riedel * 1190b24cfbSSteve Glendinning * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net 124d9b1a02SSteve Glendinning * 13c9e055acSHerbert Valerio Riedel */ 14c9e055acSHerbert Valerio Riedel 15c9e055acSHerbert Valerio Riedel #include <linux/kernel.h> 16c9e055acSHerbert Valerio Riedel #include <linux/module.h> 17c9e055acSHerbert Valerio Riedel #include <linux/mii.h> 18c9e055acSHerbert Valerio Riedel #include <linux/ethtool.h> 19c6e970a0SAndrew Lunn #include <linux/of.h> 20c9e055acSHerbert Valerio Riedel #include <linux/phy.h> 21c9e055acSHerbert Valerio Riedel #include <linux/netdevice.h> 2243c6759eSJavier Martinez Canillas #include <linux/smscphy.h> 23c9e055acSHerbert Valerio Riedel 2405b35e7eSAndre Edich /* Vendor-specific PHY Definitions */ 2505b35e7eSAndre Edich /* EDPD NLP / crossover time configuration */ 2605b35e7eSAndre Edich #define PHY_EDPD_CONFIG 16 2705b35e7eSAndre Edich #define PHY_EDPD_CONFIG_EXT_CROSSOVER_ 0x0001 2805b35e7eSAndre Edich 2905b35e7eSAndre Edich /* Control/Status Indication Register */ 3005b35e7eSAndre Edich #define SPECIAL_CTRL_STS 27 3105b35e7eSAndre Edich #define SPECIAL_CTRL_STS_OVRRD_AMDIX_ 0x8000 3205b35e7eSAndre Edich #define SPECIAL_CTRL_STS_AMDIX_ENABLE_ 0x4000 3305b35e7eSAndre Edich #define SPECIAL_CTRL_STS_AMDIX_STATE_ 0x2000 3405b35e7eSAndre Edich 35030a8902SAndrew Lunn struct smsc_hw_stat { 36030a8902SAndrew Lunn const char *string; 37030a8902SAndrew Lunn u8 reg; 38030a8902SAndrew Lunn u8 bits; 39030a8902SAndrew Lunn }; 40030a8902SAndrew Lunn 41030a8902SAndrew Lunn static struct smsc_hw_stat smsc_hw_stats[] = { 42030a8902SAndrew Lunn { "phy_symbol_errors", 26, 16}, 43030a8902SAndrew Lunn }; 44030a8902SAndrew Lunn 450a9c453eSTeresa Remmet struct smsc_phy_priv { 460a9c453eSTeresa Remmet bool energy_enable; 470a9c453eSTeresa Remmet }; 480a9c453eSTeresa Remmet 4948c41b99SSteve Glendinning static int smsc_phy_config_intr(struct phy_device *phydev) 50c9e055acSHerbert Valerio Riedel { 51*73654945SMarco Felsch struct smsc_phy_priv *priv = phydev->priv; 52*73654945SMarco Felsch u16 intmask = 0; 53*73654945SMarco Felsch int rc; 54*73654945SMarco Felsch 55*73654945SMarco Felsch if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 56*73654945SMarco Felsch intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6; 57*73654945SMarco Felsch if (priv->energy_enable) 58*73654945SMarco Felsch intmask |= MII_LAN83C185_ISF_INT7; 59*73654945SMarco Felsch } 60*73654945SMarco Felsch 61*73654945SMarco Felsch rc = phy_write(phydev, MII_LAN83C185_IM, intmask); 62c9e055acSHerbert Valerio Riedel 63c9e055acSHerbert Valerio Riedel return rc < 0 ? rc : 0; 64c9e055acSHerbert Valerio Riedel } 65c9e055acSHerbert Valerio Riedel 6648c41b99SSteve Glendinning static int smsc_phy_ack_interrupt(struct phy_device *phydev) 67c9e055acSHerbert Valerio Riedel { 68c9e055acSHerbert Valerio Riedel int rc = phy_read (phydev, MII_LAN83C185_ISF); 69c9e055acSHerbert Valerio Riedel 70c9e055acSHerbert Valerio Riedel return rc < 0 ? rc : 0; 71c9e055acSHerbert Valerio Riedel } 72c9e055acSHerbert Valerio Riedel 7348c41b99SSteve Glendinning static int smsc_phy_config_init(struct phy_device *phydev) 74c9e055acSHerbert Valerio Riedel { 750a9c453eSTeresa Remmet struct smsc_phy_priv *priv = phydev->priv; 760a9c453eSTeresa Remmet 7721009686SGwenhael Goavec-Merou int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); 7821009686SGwenhael Goavec-Merou 7921009686SGwenhael Goavec-Merou if (rc < 0) 8021009686SGwenhael Goavec-Merou return rc; 8121009686SGwenhael Goavec-Merou 820a9c453eSTeresa Remmet if (priv->energy_enable) { 8321009686SGwenhael Goavec-Merou /* Enable energy detect mode for this SMSC Transceivers */ 8421009686SGwenhael Goavec-Merou rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, 8521009686SGwenhael Goavec-Merou rc | MII_LAN83C185_EDPWRDOWN); 8621009686SGwenhael Goavec-Merou if (rc < 0) 8721009686SGwenhael Goavec-Merou return rc; 88d88ecb37SHeiko Schocher } 8921009686SGwenhael Goavec-Merou 9021009686SGwenhael Goavec-Merou return smsc_phy_ack_interrupt(phydev); 9121009686SGwenhael Goavec-Merou } 9221009686SGwenhael Goavec-Merou 9321009686SGwenhael Goavec-Merou static int smsc_phy_reset(struct phy_device *phydev) 9421009686SGwenhael Goavec-Merou { 956ded7cd6Strem int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES); 966ded7cd6Strem if (rc < 0) 976ded7cd6Strem return rc; 986ded7cd6Strem 996ded7cd6Strem /* If the SMSC PHY is in power down mode, then set it 1006ded7cd6Strem * in all capable mode before using it. 1016ded7cd6Strem */ 1026ded7cd6Strem if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) { 103fc0f7e33SManfred Schlaegl /* set "all capable" mode */ 1046ded7cd6Strem rc |= MII_LAN83C185_MODE_ALL; 1056ded7cd6Strem phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc); 1066ded7cd6Strem } 107fc0f7e33SManfred Schlaegl 108fc0f7e33SManfred Schlaegl /* reset the phy */ 109fc0f7e33SManfred Schlaegl return genphy_soft_reset(phydev); 110c9e055acSHerbert Valerio Riedel } 111c9e055acSHerbert Valerio Riedel 1124223dbffSPatrick Trantham static int lan911x_config_init(struct phy_device *phydev) 113b629820dSMarek Vasut { 1144223dbffSPatrick Trantham return smsc_phy_ack_interrupt(phydev); 1154223dbffSPatrick Trantham } 1164223dbffSPatrick Trantham 11705b35e7eSAndre Edich static int lan87xx_config_aneg(struct phy_device *phydev) 11805b35e7eSAndre Edich { 11905b35e7eSAndre Edich int rc; 12005b35e7eSAndre Edich int val; 12105b35e7eSAndre Edich 12205b35e7eSAndre Edich switch (phydev->mdix_ctrl) { 12305b35e7eSAndre Edich case ETH_TP_MDI: 12405b35e7eSAndre Edich val = SPECIAL_CTRL_STS_OVRRD_AMDIX_; 12505b35e7eSAndre Edich break; 12605b35e7eSAndre Edich case ETH_TP_MDI_X: 12705b35e7eSAndre Edich val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ | 12805b35e7eSAndre Edich SPECIAL_CTRL_STS_AMDIX_STATE_; 12905b35e7eSAndre Edich break; 13005b35e7eSAndre Edich case ETH_TP_MDI_AUTO: 13105b35e7eSAndre Edich val = SPECIAL_CTRL_STS_AMDIX_ENABLE_; 13205b35e7eSAndre Edich break; 13305b35e7eSAndre Edich default: 13405b35e7eSAndre Edich return genphy_config_aneg(phydev); 13505b35e7eSAndre Edich } 13605b35e7eSAndre Edich 13705b35e7eSAndre Edich rc = phy_read(phydev, SPECIAL_CTRL_STS); 13805b35e7eSAndre Edich if (rc < 0) 13905b35e7eSAndre Edich return rc; 14005b35e7eSAndre Edich 14105b35e7eSAndre Edich rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ | 14205b35e7eSAndre Edich SPECIAL_CTRL_STS_AMDIX_ENABLE_ | 14305b35e7eSAndre Edich SPECIAL_CTRL_STS_AMDIX_STATE_); 14405b35e7eSAndre Edich rc |= val; 14505b35e7eSAndre Edich phy_write(phydev, SPECIAL_CTRL_STS, rc); 14605b35e7eSAndre Edich 14705b35e7eSAndre Edich phydev->mdix = phydev->mdix_ctrl; 14805b35e7eSAndre Edich return genphy_config_aneg(phydev); 14905b35e7eSAndre Edich } 15005b35e7eSAndre Edich 15105b35e7eSAndre Edich static int lan87xx_config_aneg_ext(struct phy_device *phydev) 15205b35e7eSAndre Edich { 15305b35e7eSAndre Edich int rc; 15405b35e7eSAndre Edich 15505b35e7eSAndre Edich /* Extend Manual AutoMDIX timer */ 15605b35e7eSAndre Edich rc = phy_read(phydev, PHY_EDPD_CONFIG); 15705b35e7eSAndre Edich if (rc < 0) 15805b35e7eSAndre Edich return rc; 15905b35e7eSAndre Edich 16005b35e7eSAndre Edich rc |= PHY_EDPD_CONFIG_EXT_CROSSOVER_; 16105b35e7eSAndre Edich phy_write(phydev, PHY_EDPD_CONFIG, rc); 16205b35e7eSAndre Edich return lan87xx_config_aneg(phydev); 16305b35e7eSAndre Edich } 16405b35e7eSAndre Edich 165b629820dSMarek Vasut /* 166776829deSIgor Plyatov * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable 167776829deSIgor Plyatov * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to 168776829deSIgor Plyatov * unstable detection of plugging in Ethernet cable. 169776829deSIgor Plyatov * This workaround disables Energy Detect Power-Down mode and waiting for 170776829deSIgor Plyatov * response on link pulses to detect presence of plugged Ethernet cable. 171776829deSIgor Plyatov * The Energy Detect Power-Down mode is enabled again in the end of procedure to 172776829deSIgor Plyatov * save approximately 220 mW of power if cable is unplugged. 173b629820dSMarek Vasut */ 1744223dbffSPatrick Trantham static int lan87xx_read_status(struct phy_device *phydev) 1754223dbffSPatrick Trantham { 1760a9c453eSTeresa Remmet struct smsc_phy_priv *priv = phydev->priv; 1770a9c453eSTeresa Remmet 1784223dbffSPatrick Trantham int err = genphy_read_status(phydev); 1790a9c453eSTeresa Remmet 1800a9c453eSTeresa Remmet if (!phydev->link && priv->energy_enable) { 1814223dbffSPatrick Trantham /* Disable EDPD to wake up PHY */ 182b629820dSMarek Vasut int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); 183b629820dSMarek Vasut if (rc < 0) 184b629820dSMarek Vasut return rc; 185b629820dSMarek Vasut 1864223dbffSPatrick Trantham rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, 1874223dbffSPatrick Trantham rc & ~MII_LAN83C185_EDPWRDOWN); 188b629820dSMarek Vasut if (rc < 0) 189b629820dSMarek Vasut return rc; 190b629820dSMarek Vasut 1916d61f483SDejin Zheng /* Wait max 640 ms to detect energy and the timeout is not 1926d61f483SDejin Zheng * an actual error. 1936d61f483SDejin Zheng */ 1946d61f483SDejin Zheng read_poll_timeout(phy_read, rc, 1956d61f483SDejin Zheng rc & MII_LAN83C185_ENERGYON || rc < 0, 1966d61f483SDejin Zheng 10000, 640000, true, phydev, 1976d61f483SDejin Zheng MII_LAN83C185_CTRL_STATUS); 198776829deSIgor Plyatov if (rc < 0) 199776829deSIgor Plyatov return rc; 2004223dbffSPatrick Trantham 2014223dbffSPatrick Trantham /* Re-enable EDPD */ 2024223dbffSPatrick Trantham rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); 2034223dbffSPatrick Trantham if (rc < 0) 2044223dbffSPatrick Trantham return rc; 2054223dbffSPatrick Trantham 2064223dbffSPatrick Trantham rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, 2074223dbffSPatrick Trantham rc | MII_LAN83C185_EDPWRDOWN); 2084223dbffSPatrick Trantham if (rc < 0) 2094223dbffSPatrick Trantham return rc; 210b629820dSMarek Vasut } 211b629820dSMarek Vasut 2124223dbffSPatrick Trantham return err; 213698244acSGiuseppe Cavallaro } 214c9e055acSHerbert Valerio Riedel 215030a8902SAndrew Lunn static int smsc_get_sset_count(struct phy_device *phydev) 216030a8902SAndrew Lunn { 217030a8902SAndrew Lunn return ARRAY_SIZE(smsc_hw_stats); 218030a8902SAndrew Lunn } 219030a8902SAndrew Lunn 220030a8902SAndrew Lunn static void smsc_get_strings(struct phy_device *phydev, u8 *data) 221030a8902SAndrew Lunn { 222030a8902SAndrew Lunn int i; 223030a8902SAndrew Lunn 224030a8902SAndrew Lunn for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) { 2252da55390SArnd Bergmann strncpy(data + i * ETH_GSTRING_LEN, 226030a8902SAndrew Lunn smsc_hw_stats[i].string, ETH_GSTRING_LEN); 227030a8902SAndrew Lunn } 228030a8902SAndrew Lunn } 229030a8902SAndrew Lunn 230030a8902SAndrew Lunn static u64 smsc_get_stat(struct phy_device *phydev, int i) 231030a8902SAndrew Lunn { 232030a8902SAndrew Lunn struct smsc_hw_stat stat = smsc_hw_stats[i]; 233030a8902SAndrew Lunn int val; 234030a8902SAndrew Lunn u64 ret; 235030a8902SAndrew Lunn 236030a8902SAndrew Lunn val = phy_read(phydev, stat.reg); 237030a8902SAndrew Lunn if (val < 0) 2386c3442f5SJisheng Zhang ret = U64_MAX; 239030a8902SAndrew Lunn else 240030a8902SAndrew Lunn ret = val; 241030a8902SAndrew Lunn 242030a8902SAndrew Lunn return ret; 243030a8902SAndrew Lunn } 244030a8902SAndrew Lunn 245030a8902SAndrew Lunn static void smsc_get_stats(struct phy_device *phydev, 246030a8902SAndrew Lunn struct ethtool_stats *stats, u64 *data) 247030a8902SAndrew Lunn { 248030a8902SAndrew Lunn int i; 249030a8902SAndrew Lunn 250030a8902SAndrew Lunn for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) 251030a8902SAndrew Lunn data[i] = smsc_get_stat(phydev, i); 252030a8902SAndrew Lunn } 253030a8902SAndrew Lunn 2540a9c453eSTeresa Remmet static int smsc_phy_probe(struct phy_device *phydev) 2550a9c453eSTeresa Remmet { 2560a9c453eSTeresa Remmet struct device *dev = &phydev->mdio.dev; 2570a9c453eSTeresa Remmet struct device_node *of_node = dev->of_node; 2580a9c453eSTeresa Remmet struct smsc_phy_priv *priv; 2590a9c453eSTeresa Remmet 2600a9c453eSTeresa Remmet priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2610a9c453eSTeresa Remmet if (!priv) 2620a9c453eSTeresa Remmet return -ENOMEM; 2630a9c453eSTeresa Remmet 2640a9c453eSTeresa Remmet priv->energy_enable = true; 2650a9c453eSTeresa Remmet 2660a9c453eSTeresa Remmet if (of_property_read_bool(of_node, "smsc,disable-energy-detect")) 2670a9c453eSTeresa Remmet priv->energy_enable = false; 2680a9c453eSTeresa Remmet 2690a9c453eSTeresa Remmet phydev->priv = priv; 2700a9c453eSTeresa Remmet 2710a9c453eSTeresa Remmet return 0; 2720a9c453eSTeresa Remmet } 2730a9c453eSTeresa Remmet 274d5bf9071SChristian Hohnstaedt static struct phy_driver smsc_phy_driver[] = { 275d5bf9071SChristian Hohnstaedt { 276c9e055acSHerbert Valerio Riedel .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ 277c9e055acSHerbert Valerio Riedel .phy_id_mask = 0xfffffff0, 278c9e055acSHerbert Valerio Riedel .name = "SMSC LAN83C185", 279c9e055acSHerbert Valerio Riedel 280dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 281c9e055acSHerbert Valerio Riedel 2820a9c453eSTeresa Remmet .probe = smsc_phy_probe, 2830a9c453eSTeresa Remmet 284c9e055acSHerbert Valerio Riedel /* basic functions */ 28548c41b99SSteve Glendinning .config_init = smsc_phy_config_init, 28621009686SGwenhael Goavec-Merou .soft_reset = smsc_phy_reset, 287c9e055acSHerbert Valerio Riedel 288c9e055acSHerbert Valerio Riedel /* IRQ related */ 28948c41b99SSteve Glendinning .ack_interrupt = smsc_phy_ack_interrupt, 29048c41b99SSteve Glendinning .config_intr = smsc_phy_config_intr, 291c9e055acSHerbert Valerio Riedel 292c64d2a9aSSteve Glendinning .suspend = genphy_suspend, 293c64d2a9aSSteve Glendinning .resume = genphy_resume, 294d5bf9071SChristian Hohnstaedt }, { 2954d9b1a02SSteve Glendinning .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */ 2964d9b1a02SSteve Glendinning .phy_id_mask = 0xfffffff0, 2974d9b1a02SSteve Glendinning .name = "SMSC LAN8187", 2984d9b1a02SSteve Glendinning 299dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 3004d9b1a02SSteve Glendinning 3010a9c453eSTeresa Remmet .probe = smsc_phy_probe, 3020a9c453eSTeresa Remmet 3034d9b1a02SSteve Glendinning /* basic functions */ 3044d9b1a02SSteve Glendinning .config_init = smsc_phy_config_init, 30521009686SGwenhael Goavec-Merou .soft_reset = smsc_phy_reset, 3064d9b1a02SSteve Glendinning 3074d9b1a02SSteve Glendinning /* IRQ related */ 3084d9b1a02SSteve Glendinning .ack_interrupt = smsc_phy_ack_interrupt, 3094d9b1a02SSteve Glendinning .config_intr = smsc_phy_config_intr, 3104d9b1a02SSteve Glendinning 311030a8902SAndrew Lunn /* Statistics */ 312030a8902SAndrew Lunn .get_sset_count = smsc_get_sset_count, 313030a8902SAndrew Lunn .get_strings = smsc_get_strings, 314030a8902SAndrew Lunn .get_stats = smsc_get_stats, 315030a8902SAndrew Lunn 316c64d2a9aSSteve Glendinning .suspend = genphy_suspend, 317c64d2a9aSSteve Glendinning .resume = genphy_resume, 318d5bf9071SChristian Hohnstaedt }, { 31905b35e7eSAndre Edich /* This covers internal PHY (phy_id: 0x0007C0C3) for 32005b35e7eSAndre Edich * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505) 32105b35e7eSAndre Edich */ 3224d9b1a02SSteve Glendinning .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */ 3234d9b1a02SSteve Glendinning .phy_id_mask = 0xfffffff0, 3244d9b1a02SSteve Glendinning .name = "SMSC LAN8700", 3254d9b1a02SSteve Glendinning 326dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 3274d9b1a02SSteve Glendinning 3280a9c453eSTeresa Remmet .probe = smsc_phy_probe, 3290a9c453eSTeresa Remmet 3304d9b1a02SSteve Glendinning /* basic functions */ 331776829deSIgor Plyatov .read_status = lan87xx_read_status, 3324d9b1a02SSteve Glendinning .config_init = smsc_phy_config_init, 33321009686SGwenhael Goavec-Merou .soft_reset = smsc_phy_reset, 33405b35e7eSAndre Edich .config_aneg = lan87xx_config_aneg, 3354d9b1a02SSteve Glendinning 3364d9b1a02SSteve Glendinning /* IRQ related */ 3374d9b1a02SSteve Glendinning .ack_interrupt = smsc_phy_ack_interrupt, 3384d9b1a02SSteve Glendinning .config_intr = smsc_phy_config_intr, 3394d9b1a02SSteve Glendinning 340030a8902SAndrew Lunn /* Statistics */ 341030a8902SAndrew Lunn .get_sset_count = smsc_get_sset_count, 342030a8902SAndrew Lunn .get_strings = smsc_get_strings, 343030a8902SAndrew Lunn .get_stats = smsc_get_stats, 344030a8902SAndrew Lunn 345c64d2a9aSSteve Glendinning .suspend = genphy_suspend, 346c64d2a9aSSteve Glendinning .resume = genphy_resume, 347d5bf9071SChristian Hohnstaedt }, { 348fd9abb3dSSteve Glendinning .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */ 349fd9abb3dSSteve Glendinning .phy_id_mask = 0xfffffff0, 350fd9abb3dSSteve Glendinning .name = "SMSC LAN911x Internal PHY", 351fd9abb3dSSteve Glendinning 352dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 353fd9abb3dSSteve Glendinning 3540a9c453eSTeresa Remmet .probe = smsc_phy_probe, 3550a9c453eSTeresa Remmet 356fd9abb3dSSteve Glendinning /* basic functions */ 357698244acSGiuseppe Cavallaro .config_init = lan911x_config_init, 358fd9abb3dSSteve Glendinning 359fd9abb3dSSteve Glendinning /* IRQ related */ 360fd9abb3dSSteve Glendinning .ack_interrupt = smsc_phy_ack_interrupt, 361fd9abb3dSSteve Glendinning .config_intr = smsc_phy_config_intr, 362fd9abb3dSSteve Glendinning 363c64d2a9aSSteve Glendinning .suspend = genphy_suspend, 364c64d2a9aSSteve Glendinning .resume = genphy_resume, 365d5bf9071SChristian Hohnstaedt }, { 36605b35e7eSAndre Edich /* This covers internal PHY (phy_id: 0x0007C0F0) for 36705b35e7eSAndre Edich * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01) 36805b35e7eSAndre Edich */ 369e072b639SSteve Glendinning .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */ 370e072b639SSteve Glendinning .phy_id_mask = 0xfffffff0, 371e072b639SSteve Glendinning .name = "SMSC LAN8710/LAN8720", 372e072b639SSteve Glendinning 373dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 374a4307c0eSHeiner Kallweit .flags = PHY_RST_AFTER_CLK_EN, 375e072b639SSteve Glendinning 3760a9c453eSTeresa Remmet .probe = smsc_phy_probe, 3770a9c453eSTeresa Remmet 378e072b639SSteve Glendinning /* basic functions */ 3794223dbffSPatrick Trantham .read_status = lan87xx_read_status, 3804257d583SPatrick Trantham .config_init = smsc_phy_config_init, 38121009686SGwenhael Goavec-Merou .soft_reset = smsc_phy_reset, 38205b35e7eSAndre Edich .config_aneg = lan87xx_config_aneg_ext, 383e072b639SSteve Glendinning 384e072b639SSteve Glendinning /* IRQ related */ 385e072b639SSteve Glendinning .ack_interrupt = smsc_phy_ack_interrupt, 386e072b639SSteve Glendinning .config_intr = smsc_phy_config_intr, 387e072b639SSteve Glendinning 388030a8902SAndrew Lunn /* Statistics */ 389030a8902SAndrew Lunn .get_sset_count = smsc_get_sset_count, 390030a8902SAndrew Lunn .get_strings = smsc_get_strings, 391030a8902SAndrew Lunn .get_stats = smsc_get_stats, 392030a8902SAndrew Lunn 393e072b639SSteve Glendinning .suspend = genphy_suspend, 394e072b639SSteve Glendinning .resume = genphy_resume, 39526706d43SJoshua Henderson }, { 39626706d43SJoshua Henderson .phy_id = 0x0007c110, 39726706d43SJoshua Henderson .phy_id_mask = 0xfffffff0, 39826706d43SJoshua Henderson .name = "SMSC LAN8740", 39926706d43SJoshua Henderson 400dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 40176db2d46SMartin Fuzzey .flags = PHY_RST_AFTER_CLK_EN, 40226706d43SJoshua Henderson 4030a9c453eSTeresa Remmet .probe = smsc_phy_probe, 4040a9c453eSTeresa Remmet 40526706d43SJoshua Henderson /* basic functions */ 40626706d43SJoshua Henderson .read_status = lan87xx_read_status, 40726706d43SJoshua Henderson .config_init = smsc_phy_config_init, 40826706d43SJoshua Henderson .soft_reset = smsc_phy_reset, 40926706d43SJoshua Henderson 41026706d43SJoshua Henderson /* IRQ related */ 41126706d43SJoshua Henderson .ack_interrupt = smsc_phy_ack_interrupt, 41226706d43SJoshua Henderson .config_intr = smsc_phy_config_intr, 41326706d43SJoshua Henderson 414030a8902SAndrew Lunn /* Statistics */ 415030a8902SAndrew Lunn .get_sset_count = smsc_get_sset_count, 416030a8902SAndrew Lunn .get_strings = smsc_get_strings, 417030a8902SAndrew Lunn .get_stats = smsc_get_stats, 418030a8902SAndrew Lunn 41926706d43SJoshua Henderson .suspend = genphy_suspend, 42026706d43SJoshua Henderson .resume = genphy_resume, 421d5bf9071SChristian Hohnstaedt } }; 422e072b639SSteve Glendinning 42350fd7150SJohan Hovold module_phy_driver(smsc_phy_driver); 424c9e055acSHerbert Valerio Riedel 425c9e055acSHerbert Valerio Riedel MODULE_DESCRIPTION("SMSC PHY driver"); 426c9e055acSHerbert Valerio Riedel MODULE_AUTHOR("Herbert Valerio Riedel"); 427c9e055acSHerbert Valerio Riedel MODULE_LICENSE("GPL"); 428c9e055acSHerbert Valerio Riedel 429cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused smsc_tbl[] = { 4304e4f10f6SDavid Woodhouse { 0x0007c0a0, 0xfffffff0 }, 4314e4f10f6SDavid Woodhouse { 0x0007c0b0, 0xfffffff0 }, 4324e4f10f6SDavid Woodhouse { 0x0007c0c0, 0xfffffff0 }, 4334e4f10f6SDavid Woodhouse { 0x0007c0d0, 0xfffffff0 }, 4344e4f10f6SDavid Woodhouse { 0x0007c0f0, 0xfffffff0 }, 43526706d43SJoshua Henderson { 0x0007c110, 0xfffffff0 }, 4364e4f10f6SDavid Woodhouse { } 4374e4f10f6SDavid Woodhouse }; 4384e4f10f6SDavid Woodhouse 4394e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, smsc_tbl); 440