aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-12-26 13:22:17 -0800
committerDavid S. Miller <davem@davemloft.net>2019-12-26 13:22:17 -0800
commit8d347992989465fc7135ef1a84ca4c710a705c1a (patch)
treeabf617c9934dac2c8bb31ccb2e70f3422071e2fc
parentMerge branch 'mlxsw-spectrum_router-Cleanups' (diff)
parentnet: phy: realtek: add support for configuring the RX delay on RTL8211F (diff)
downloadlinux-dev-8d347992989465fc7135ef1a84ca4c710a705c1a.tar.xz
linux-dev-8d347992989465fc7135ef1a84ca4c710a705c1a.zip
Merge branch 'RTL8211F-RGMII-RX-TX-delay-configuration-improvements'
Martin Blumenstingl says: ==================== RTL8211F: RGMII RX/TX delay configuration improvements In discussion with Andrew [0] we figured out that it would be best to make the RX delay of the RTL8211F PHY configurable (just like the TX delay is already configurable). While here I took the opportunity to add some logging to the TX delay configuration as well. There is no public documentation for the RX and TX delay registers. I received this information a while ago (and created this RfC patch back then: [1]). Realtek gave me permission to take the information from the datasheet extracts and phase them in my own words and publish that (I am not allowed to publish the datasheet extracts). I have tested these patches on two boards: - Amlogic Meson8b Odroid-C1 - Amlogic GXM Khadas VIM2 Both still behave as before these changes (iperf3 speeds are the same in both directions: RX and TX), which is expected because they are currently using phy-mode = "rgmii" with the RX delay not being generated by the PHY. [0] https://patchwork.ozlabs.org/patch/1215313/ [1] https://patchwork.ozlabs.org/patch/843946/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/realtek.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 476db5345e1a..f5fa2fff3ddc 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -29,6 +29,8 @@
#define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY BIT(8)
+#define RTL8211F_RX_DELAY BIT(3)
+
#define RTL8211E_TX_DELAY BIT(1)
#define RTL8211E_RX_DELAY BIT(2)
#define RTL8211E_MODE_MII_GMII BIT(3)
@@ -171,25 +173,66 @@ static int rtl8211c_config_init(struct phy_device *phydev)
static int rtl8211f_config_init(struct phy_device *phydev)
{
- u16 val;
+ struct device *dev = &phydev->mdio.dev;
+ u16 val_txdly, val_rxdly;
+ int ret;
- /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
- * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
- */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
+ val_txdly = 0;
+ val_rxdly = 0;
+ break;
+
case PHY_INTERFACE_MODE_RGMII_RXID:
- val = 0;
+ val_txdly = 0;
+ val_rxdly = RTL8211F_RX_DELAY;
break;
- case PHY_INTERFACE_MODE_RGMII_ID:
+
case PHY_INTERFACE_MODE_RGMII_TXID:
- val = RTL8211F_TX_DELAY;
+ val_txdly = RTL8211F_TX_DELAY;
+ val_rxdly = 0;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ val_txdly = RTL8211F_TX_DELAY;
+ val_rxdly = RTL8211F_RX_DELAY;
break;
+
default: /* the rest of the modes imply leaving delay as is. */
return 0;
}
- return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
+ ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY,
+ val_txdly);
+ if (ret < 0) {
+ dev_err(dev, "Failed to update the TX delay register\n");
+ return ret;
+ } else if (ret) {
+ dev_dbg(dev,
+ "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n",
+ val_txdly ? "Enabling" : "Disabling");
+ } else {
+ dev_dbg(dev,
+ "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n",
+ val_txdly ? "enabled" : "disabled");
+ }
+
+ ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY,
+ val_rxdly);
+ if (ret < 0) {
+ dev_err(dev, "Failed to update the RX delay register\n");
+ return ret;
+ } else if (ret) {
+ dev_dbg(dev,
+ "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n",
+ val_rxdly ? "Enabling" : "Disabling");
+ } else {
+ dev_dbg(dev,
+ "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n",
+ val_rxdly ? "enabled" : "disabled");
+ }
+
+ return 0;
}
static int rtl8211e_config_init(struct phy_device *phydev)