summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/Kconfig20
-rw-r--r--drivers/net/phy/realtek.c19
2 files changed, 39 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3dc0822d9c..631b52b1cf 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -202,6 +202,26 @@ config RTL8211X_PHY_FORCE_MASTER
If unsure, say N.
+config RTL8211F_PHY_FORCE_EEE_RXC_ON
+ bool "Ethernet PHY RTL8211F: do not stop receiving the xMII clock during LPI"
+ depends on PHY_REALTEK
+ default n
+ help
+ The IEEE 802.3az-2010 (EEE) standard provides a protocol to coordinate
+ transitions to/from a lower power consumption level (Low Power Idle
+ mode) based on link utilization. When no packets are being
+ transmitted, the system goes to Low Power Idle mode to save power.
+
+ Under particular circumstances this setting can cause issues where
+ the PHY is unable to transmit or receive any packet when in LPI mode.
+ The problem is caused when the PHY is configured to stop receiving
+ the xMII clock while it is signaling LPI. For some PHYs the bit
+ configuring this behavior is set by the Linux kernel, causing the
+ issue in U-Boot on reboot if the PHY retains the register value.
+
+ Default n, which means that the PHY state is not changed. To work
+ around the issues, change this setting to y.
+
config PHY_SMSC
bool "Microchip(SMSC) Ethernet PHYs support"
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index dd45e11b3a..8f1d759632 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,7 @@
#define PHY_RTL8211x_FORCE_MASTER BIT(1)
#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
+#define PHY_RTL8211F_FORCE_EEE_RXC_ON BIT(3)
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
@@ -102,6 +103,15 @@ static int rtl8211e_probe(struct phy_device *phydev)
return 0;
}
+static int rtl8211f_probe(struct phy_device *phydev)
+{
+#ifdef CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON
+ phydev->flags |= PHY_RTL8211F_FORCE_EEE_RXC_ON;
+#endif
+
+ return 0;
+}
+
/* RealTek RTL8211x */
static int rtl8211x_config(struct phy_device *phydev)
{
@@ -151,6 +161,14 @@ static int rtl8211f_config(struct phy_device *phydev)
{
u16 reg;
+ if (phydev->flags & PHY_RTL8211F_FORCE_EEE_RXC_ON) {
+ unsigned int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_PCS_CTRL1_CLKSTOP_EN;
+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ }
+
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
phy_write(phydev, MDIO_DEVAD_NONE,
@@ -360,6 +378,7 @@ static struct phy_driver RTL8211F_driver = {
.uid = 0x1cc916,
.mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
+ .probe = &rtl8211f_probe,
.config = &rtl8211f_config,
.startup = &rtl8211f_startup,
.shutdown = &genphy_shutdown,