diff mbox series

[U-Boot,1/2] net: phy: Add PHY_RTL8211E_PINE64_GIGABIT_FIX for realtek phys

Message ID 20180214230216.2001-2-kevans@FreeBSD.org
State Accepted
Commit 66526e70381dbaad58533cfbd7bce07c668205c6
Delegated to: Joe Hershberger
Headers show
Series Add fix for Pine64 gigabit throughput issues | expand

Commit Message

Kyle Evans Feb. 14, 2018, 11:02 p.m. UTC
Setting PHY_RTL8211E_PINE64_GIGABIT_FIX forces internal rx/tx delays off
on the PHY, as well as flipping some magical undocumented bits. The
magic number comes from the Pine64 engineering team, presumably as a
proxy from Realtek. This configuration fixes the throughput on some
Pine64 models. Packet loss of up to 60-70% has been observed without
this.

Signed-off-by: Kyle Evans <kevans@FreeBSD.org>
---
 drivers/net/phy/Kconfig   | 10 ++++++++++
 drivers/net/phy/realtek.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

Comments

Joe Hershberger Feb. 27, 2018, 3:59 p.m. UTC | #1
On Wed, Feb 14, 2018 at 5:02 PM,  <kevans@freebsd.org> wrote:
> Setting PHY_RTL8211E_PINE64_GIGABIT_FIX forces internal rx/tx delays off
> on the PHY, as well as flipping some magical undocumented bits. The
> magic number comes from the Pine64 engineering team, presumably as a
> proxy from Realtek. This configuration fixes the throughput on some
> Pine64 models. Packet loss of up to 60-70% has been observed without
> this.
>
> Signed-off-by: Kyle Evans <kevans@FreeBSD.org>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Joe Hershberger March 26, 2018, 7:24 p.m. UTC | #2
Hi Kyle,

https://patchwork.ozlabs.org/patch/873752/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git

Thanks!
-Joe
diff mbox series

Patch

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index e32f1eb1c0..ad648a889d 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -114,6 +114,16 @@  config PHY_NATSEMI
 config PHY_REALTEK
 	bool "Realtek Ethernet PHYs support"
 
+config RTL8211E_PINE64_GIGABIT_FIX
+	bool "Fix gigabit throughput on some Pine64+ models"
+	depends on PHY_REALTEK
+	help
+	  Configure the Realtek RTL8211E found on some Pine64+ models differently to
+	  fix throughput on Gigabit links, turning off all internal delays in the
+	  process. The settings that this touches are not documented in the CONFREG
+	  section of the RTL8211E datasheet, but come from Realtek by way of the
+	  Pine64 engineering team.
+
 config RTL8211X_PHY_FORCE_MASTER
 	bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode"
 	depends on PHY_REALTEK
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 6d917f86f4..d5c2a46c67 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -13,6 +13,7 @@ 
 #include <phy.h>
 
 #define PHY_RTL8211x_FORCE_MASTER BIT(1)
+#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
 
 #define PHY_AUTONEGOTIATE_TIMEOUT 5000
 
@@ -47,6 +48,13 @@ 
 #define MIIM_RTL8211F_PHYSTAT_SPDDONE  0x0800
 #define MIIM_RTL8211F_PHYSTAT_LINK     0x0004
 
+#define MIIM_RTL8211E_CONFREG           0x1c
+#define MIIM_RTL8211E_CONFREG_TXD		0x0002
+#define MIIM_RTL8211E_CONFREG_RXD		0x0004
+#define MIIM_RTL8211E_CONFREG_MAGIC		0xb400	/* Undocumented */
+
+#define MIIM_RTL8211E_EXT_PAGE_SELECT  0x1e
+
 #define MIIM_RTL8211F_PAGE_SELECT      0x1f
 #define MIIM_RTL8211F_TX_DELAY		0x100
 #define MIIM_RTL8211F_LCR		0x10
@@ -60,6 +68,15 @@  static int rtl8211b_probe(struct phy_device *phydev)
 	return 0;
 }
 
+static int rtl8211e_probe(struct phy_device *phydev)
+{
+#ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX
+	phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX;
+#endif
+
+	return 0;
+}
+
 /* RealTek RTL8211x */
 static int rtl8211x_config(struct phy_device *phydev)
 {
@@ -81,6 +98,22 @@  static int rtl8211x_config(struct phy_device *phydev)
 		reg |= MIIM_RTL8211x_CTRL1000T_MASTER;
 		phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg);
 	}
+	if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) {
+		unsigned int reg;
+
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
+			  7);
+		phy_write(phydev, MDIO_DEVAD_NONE,
+			  MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4);
+		reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG);
+		/* Ensure both internal delays are turned off */
+		reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD);
+		/* Flip the magic undocumented bits */
+		reg |= MIIM_RTL8211E_CONFREG_MAGIC;
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg);
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
+			  0);
+	}
 	/* read interrupt status just to clear it */
 	phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);
 
@@ -279,6 +312,7 @@  static struct phy_driver RTL8211E_driver = {
 	.uid = 0x1cc915,
 	.mask = 0xffffff,
 	.features = PHY_GBIT_FEATURES,
+	.probe = &rtl8211e_probe,
 	.config = &rtl8211x_config,
 	.startup = &rtl8211e_startup,
 	.shutdown = &genphy_shutdown,