According to the AR8031 and AR8035 datasheets, smartEEE mode
(active by default) makes the PHY enter sleep after a configurable
idle time. It does this autonomously, without LPI (Low Power Idle)
signals coming from MAC. AR8021 does not appear to support this.

This patch allows disabling the SmartEEE feature of above PHYs.

Tested with ping (default of 1 second interval) over back-to-back
RGMII between 2 boards having AR8035 at both ends:
  - Without SmartEEE:
225 packets transmitted, 145 received, 35% packet loss, time 229334ms
  - With SmartEEE:
144 packets transmitted, 144 received, 0% packet loss, time 146378ms

Signed-off-by: Vladimir Oltean <vladimir.olt...@nxp.com>
Acked-by: Joe Hershberger <joe.hershber...@ni.com>
---
Changes in v3:
* Got rid of magic numbers.

 drivers/net/phy/Kconfig   | 21 +++++++++++++++++++++
 drivers/net/phy/atheros.c | 26 ++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3dc0822..6abe8c5 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -94,6 +94,27 @@ config PHY_AQUANTIA_FW_NAME
 config PHY_ATHEROS
        bool "Atheros Ethernet PHYs support"
 
+config PHY_ATHEROS_SMART_EEE
+       depends on PHY_ATHEROS
+       default y
+       tristate "SmartEEE feature for Atheros PHYs"
+       help
+         Enables the Atheros SmartEEE feature (not IEEE 802.3az). When 2 PHYs
+         which support this feature are connected back-to-back, they may
+         negotiate a low-power sleep mode autonomously, without the Ethernet
+         controller's knowledge. This setting may cause issues under 2 known
+         circumstances (both noticed at low traffic rates):
+           - If the voltage rails on the PHY are unstable, then the PHY can
+             actually reset as it enters the low power state. This means that
+             the frames it is supposed to buffer until it wakes up are going
+             to be dropped instead.
+           - If 1588/PTP synchronization is the only traffic source over this
+             PHY, the delays caused by the sleep/wakeup time are going to add
+             to the synchronization error between the master and the slave.
+         Default y, which means that the PHY's out-of-reset state is not
+         changed (SmartEEE active). To work around the issues described
+         above, change to n.
+
 config PHY_BROADCOM
        bool "Broadcom Ethernet PHYs support"
 
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 3783d15..7303267 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -5,6 +5,7 @@
  * Copyright 2011, 2013 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <linux/bitops.h>
 #include <common.h>
 #include <phy.h>
 
@@ -17,6 +18,21 @@
 #define AR803x_DEBUG_REG_0             0x0
 #define AR803x_RGMII_RX_CLK_DLY                0x8000
 
+#define AR803x_SMART_EEE_CTRL3_REG     0x805D
+#define AR803x_LPI_EN                  BIT(8)
+
+static void ar803x_enable_smart_eee(struct phy_device *phydev, bool on)
+{
+       int regval;
+
+       regval = phy_read_mmd(phydev, MDIO_MMD_PCS, AR803x_SMART_EEE_CTRL3_REG);
+       if (on)
+               regval |= AR803x_LPI_EN;
+       else
+               regval &= ~AR803x_LPI_EN;
+       phy_write_mmd(phydev, MDIO_MMD_PCS, AR803x_SMART_EEE_CTRL3_REG, regval);
+}
+
 static int ar8021_config(struct phy_device *phydev)
 {
        phy_write(phydev, MDIO_DEVAD_NONE, 0x00, 0x1200);
@@ -29,6 +45,11 @@ static int ar8021_config(struct phy_device *phydev)
 
 static int ar8031_config(struct phy_device *phydev)
 {
+#ifdef CONFIG_PHY_ATHEROS_SMART_EEE
+       ar803x_enable_smart_eee(phydev, true);
+#else
+       ar803x_enable_smart_eee(phydev, false);
+#endif
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
            phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
                phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
@@ -57,6 +78,11 @@ static int ar8035_config(struct phy_device *phydev)
 {
        int regval;
 
+#ifdef CONFIG_PHY_ATHEROS_SMART_EEE
+       ar803x_enable_smart_eee(phydev, true);
+#else
+       ar803x_enable_smart_eee(phydev, false);
+#endif
        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
        phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
        phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
-- 
2.7.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to