aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/phy/realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/realtek.c')
-rw-r--r--drivers/net/phy/realtek.c69
1 files changed, 43 insertions, 26 deletions
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index b1b1fa5..24c3ea5 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,7 +12,6 @@
#include <linux/delay.h>
#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_RTL8201F_S700_RMII_TIMINGS BIT(4)
@@ -49,10 +48,10 @@
#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_CONFREG 0x1c
+#define MIIM_RTL8211E_CTRL_DELAY BIT(13)
+#define MIIM_RTL8211E_TX_DELAY BIT(12)
+#define MIIM_RTL8211E_RX_DELAY BIT(11)
#define MIIM_RTL8211E_EXT_PAGE_SELECT 0x1e
@@ -108,10 +107,6 @@ static int rtl8211b_probe(struct phy_device *phydev)
static int rtl8211e_probe(struct phy_device *phydev)
{
-#ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX
- phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX;
-#endif
-
return 0;
}
@@ -154,22 +149,6 @@ 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);
@@ -201,6 +180,44 @@ static int rtl8201f_config(struct phy_device *phydev)
return 0;
}
+static int rtl8211e_config(struct phy_device *phydev)
+{
+ int reg, val;
+
+ /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ val = MIIM_RTL8211E_CTRL_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ val = MIIM_RTL8211E_CTRL_DELAY | MIIM_RTL8211E_TX_DELAY |
+ MIIM_RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ val = MIIM_RTL8211E_CTRL_DELAY | MIIM_RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ val = MIIM_RTL8211E_CTRL_DELAY | MIIM_RTL8211E_TX_DELAY;
+ break;
+ default: /* the rest of the modes imply leaving delays as is. */
+ goto default_delay;
+ }
+
+ 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);
+ reg &= ~(MIIM_RTL8211E_TX_DELAY | MIIM_RTL8211E_RX_DELAY);
+ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg | val);
+
+ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0);
+
+default_delay:
+ genphy_config_aneg(phydev);
+
+ return 0;
+}
+
static int rtl8211f_config(struct phy_device *phydev)
{
u16 reg;
@@ -410,7 +427,7 @@ static struct phy_driver RTL8211E_driver = {
.mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
.probe = &rtl8211e_probe,
- .config = &rtl8211x_config,
+ .config = &rtl8211e_config,
.startup = &rtl8211e_startup,
.shutdown = &genphy_shutdown,
};