4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * Base code from drivers/net/phy/davicom.c
20 * Copyright 2010-2011 Freescale Semiconductor, Inc.
23 * Some code get from linux kenrel
24 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
30 #define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
31 #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
32 #define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
34 static int smsc_parse_status(struct phy_device *phydev)
41 aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
45 if (aneg_exp & EXPANSION_MFAULTS) {
46 /* second read to clear latched status */
47 aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
48 if (aneg_exp & EXPANSION_MFAULTS)
52 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
55 if (bmcr & BMCR_ANENABLE) {
56 lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
59 mii_adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
64 if (!(aneg_exp & EXPANSION_NWAY)) {
65 /* parallel detection */
66 phydev->duplex = DUPLEX_HALF;
67 if (lpa & (LPA_100HALF | LPA_100FULL))
68 phydev->speed = SPEED_100;
70 phydev->speed = SPEED_10;
73 if (lpa & (LPA_100FULL | LPA_100HALF)) {
74 phydev->speed = SPEED_100;
75 if (lpa & LPA_100FULL)
76 phydev->duplex = DUPLEX_FULL;
78 phydev->duplex = DUPLEX_HALF;
79 } else if (lpa & (LPA_10FULL | LPA_10HALF)) {
80 phydev->speed = SPEED_10;
82 phydev->duplex = DUPLEX_FULL;
84 phydev->duplex = DUPLEX_HALF;
89 if (bmcr & BMCR_SPEED100)
90 phydev->speed = SPEED_100;
92 phydev->speed = SPEED_10;
94 if (bmcr & BMCR_FULLDPLX)
95 phydev->duplex = DUPLEX_FULL;
97 phydev->duplex = DUPLEX_HALF;
102 static int smsc_startup(struct phy_device *phydev)
107 /* Disable EDPD to wake up PHY */
108 ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS);
113 if (ret & MII_LAN83C185_EDPWRDOWN) {
114 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS,
115 ret & ~MII_LAN83C185_EDPWRDOWN);
119 /* Sleep 64 ms to allow ~5 link test pulses to be sent */
124 ret = genphy_update_link(phydev);
127 return smsc_parse_status(phydev);
130 static struct phy_driver lan8700_driver = {
131 .name = "SMSC LAN8700",
134 .features = PHY_BASIC_FEATURES,
135 .config = &genphy_config_aneg,
136 .startup = &smsc_startup,
137 .shutdown = &genphy_shutdown,
140 static struct phy_driver lan911x_driver = {
141 .name = "SMSC LAN911x Internal PHY",
144 .features = PHY_BASIC_FEATURES,
145 .config = &genphy_config_aneg,
146 .startup = &smsc_startup,
147 .shutdown = &genphy_shutdown,
150 static struct phy_driver lan8710_driver = {
151 .name = "SMSC LAN8710/LAN8720",
154 .features = PHY_GBIT_FEATURES,
155 .config = &genphy_config_aneg,
156 .startup = &smsc_startup,
157 .shutdown = &genphy_shutdown,
160 int phy_smsc_init(void)
162 phy_register(&lan8710_driver);
163 phy_register(&lan911x_driver);
164 phy_register(&lan8700_driver);