net: phy: realtek: Introduce quirk to mark RXC not stoppable
authorCarlo Caione <ccaione@baylibre.com>
Thu, 24 Jan 2019 08:54:37 +0000 (08:54 +0000)
committerJoe Hershberger <joe.hershberger@ni.com>
Tue, 7 May 2019 19:51:55 +0000 (14:51 -0500)
When EEE is supported by the PHY and the driver allows it, libphy in the
kernel is configuring the PHY to stop receiving the xMII clock while it
is signaling LPI. While this (usually) works fine in the kernel this is
causing issues in U-Boot when rebooting from the linux kernel with this
bit set (without having the possibility to reset the PHY) where the PHY
suddenly stops working.

A new quirk is introduced to unconditionally reset this bit. If the
quirk is not enabled using the proper configuration symbol, the PHY state
is not changed.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/phy/Kconfig
drivers/net/phy/realtek.c

index 3dc0822d9c21cfa83591be5791fcdd7a5066a7c6..631b52b1cfe2634a11e828395cd98ffd90fd650b 100644 (file)
@@ -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"
 
index dd45e11b3ad9852ef2cf9afada767dce6ab7a9bd..8f1d75963259848490b66af7a4453e628b8177ab 100644 (file)
@@ -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,