4 * SPDX-License-Identifier: GPL-2.0+
6 * Base code from drivers/net/phy/davicom.c
7 * Copyright 2010-2011 Freescale Semiconductor, Inc.
10 * Some code get from linux kenrel
11 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
16 #define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
17 #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
18 #define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
20 static int smsc_parse_status(struct phy_device *phydev)
27 aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
31 if (aneg_exp & EXPANSION_MFAULTS) {
32 /* second read to clear latched status */
33 aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
34 if (aneg_exp & EXPANSION_MFAULTS)
38 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
41 if (bmcr & BMCR_ANENABLE) {
42 lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
45 mii_adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
50 if (!(aneg_exp & EXPANSION_NWAY)) {
51 /* parallel detection */
52 phydev->duplex = DUPLEX_HALF;
53 if (lpa & (LPA_100HALF | LPA_100FULL))
54 phydev->speed = SPEED_100;
56 phydev->speed = SPEED_10;
59 if (lpa & (LPA_100FULL | LPA_100HALF)) {
60 phydev->speed = SPEED_100;
61 if (lpa & LPA_100FULL)
62 phydev->duplex = DUPLEX_FULL;
64 phydev->duplex = DUPLEX_HALF;
65 } else if (lpa & (LPA_10FULL | LPA_10HALF)) {
66 phydev->speed = SPEED_10;
68 phydev->duplex = DUPLEX_FULL;
70 phydev->duplex = DUPLEX_HALF;
75 if (bmcr & BMCR_SPEED100)
76 phydev->speed = SPEED_100;
78 phydev->speed = SPEED_10;
80 if (bmcr & BMCR_FULLDPLX)
81 phydev->duplex = DUPLEX_FULL;
83 phydev->duplex = DUPLEX_HALF;
88 static int smsc_startup(struct phy_device *phydev)
93 /* Disable EDPD to wake up PHY */
94 ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS);
99 if (ret & MII_LAN83C185_EDPWRDOWN) {
100 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS,
101 ret & ~MII_LAN83C185_EDPWRDOWN);
105 /* Sleep 64 ms to allow ~5 link test pulses to be sent */
110 ret = genphy_update_link(phydev);
113 return smsc_parse_status(phydev);
116 static struct phy_driver lan8700_driver = {
117 .name = "SMSC LAN8700",
120 .features = PHY_BASIC_FEATURES,
121 .config = &genphy_config_aneg,
122 .startup = &smsc_startup,
123 .shutdown = &genphy_shutdown,
126 static struct phy_driver lan911x_driver = {
127 .name = "SMSC LAN911x Internal PHY",
130 .features = PHY_BASIC_FEATURES,
131 .config = &genphy_config_aneg,
132 .startup = &smsc_startup,
133 .shutdown = &genphy_shutdown,
136 static struct phy_driver lan8710_driver = {
137 .name = "SMSC LAN8710/LAN8720",
140 .features = PHY_GBIT_FEATURES,
141 .config = &genphy_config_aneg,
142 .startup = &smsc_startup,
143 .shutdown = &genphy_shutdown,
146 int phy_smsc_init(void)
148 phy_register(&lan8710_driver);
149 phy_register(&lan911x_driver);
150 phy_register(&lan8700_driver);