aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/dp83867.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/dp83867.c')
-rw-r--r--drivers/net/phy/dp83867.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index ddac79960ea7..1d6df3a1bfe6 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -26,6 +26,7 @@
#define MII_DP83867_MICR 0x12
#define MII_DP83867_ISR 0x13
#define DP83867_CFG2 0x14
+#define MII_DP83867_BISCR 0x16
#define DP83867_CFG3 0x1e
#define DP83867_CTRL 0x1f
@@ -104,6 +105,11 @@
#define DP83867_PHYCR_RX_FIFO_DEPTH_MASK GENMASK(13, 12)
#define DP83867_PHYCR_RESERVED_MASK BIT(11)
#define DP83867_PHYCR_FORCE_LINK_GOOD BIT(10)
+#define DP83867_MDI_CROSSOVER 5
+#define DP83867_MDI_CROSSOVER_AUTO 0b10
+#define DP83867_PHYCTRL_SGMIIEN 0x0800
+#define DP83867_PHYCTRL_RXFIFO_SHIFT 12
+#define DP83867_PHYCTRL_TXFIFO_SHIFT 14
/* RGMIIDCTL bits */
#define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
@@ -144,6 +150,14 @@
#define DP83867_CFG3_INT_OE BIT(7)
#define DP83867_CFG3_ROBUST_AUTO_MDIX BIT(9)
+/* CFG2 bits */
+#define MII_DP83867_CFG2_SPEEDOPT_10EN 0x0040
+#define MII_DP83867_CFG2_SGMII_AUTONEGEN 0x0080
+#define MII_DP83867_CFG2_SPEEDOPT_ENH 0x0100
+#define MII_DP83867_CFG2_SPEEDOPT_CNT 0x0800
+#define MII_DP83867_CFG2_SPEEDOPT_INTLOW 0x2000
+#define MII_DP83867_CFG2_MASK 0x003F
+
/* CFG4 bits */
#define DP83867_CFG4_PORT_MIRROR_EN BIT(0)
@@ -610,7 +624,7 @@ static int dp83867_config_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867 = phydev->priv;
int ret, val, bs;
- u16 delay;
+ u16 delay, cfg2;
/* Force speed optimization for the PHY even if it strapped */
ret = phy_modify(phydev, DP83867_CFG2, DP83867_DOWNSHIFT_EN,
@@ -759,6 +773,35 @@ static int dp83867_config_init(struct phy_device *phydev)
else
val &= ~DP83867_SGMII_TYPE;
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL, val);
+
+ phy_write(phydev, MII_BMCR,
+ (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
+
+ cfg2 = phy_read(phydev, DP83867_CFG2);
+ cfg2 &= MII_DP83867_CFG2_MASK;
+ cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN |
+ MII_DP83867_CFG2_SGMII_AUTONEGEN |
+ MII_DP83867_CFG2_SPEEDOPT_ENH |
+ MII_DP83867_CFG2_SPEEDOPT_CNT |
+ MII_DP83867_CFG2_SPEEDOPT_INTLOW);
+ phy_write(phydev, DP83867_CFG2, cfg2);
+
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, 0x0);
+
+ phy_write(phydev, MII_DP83867_PHYCTRL,
+ DP83867_PHYCTRL_SGMIIEN |
+ (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
+ (dp83867->rx_fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) |
+ (dp83867->tx_fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT));
+ phy_write(phydev, MII_DP83867_BISCR, 0x0);
+
+ /* This is a SW workaround for link instability if RX_CTRL is
+ * not strapped to mode 3 or 4 in HW. This is required along
+ * with clearing bit 7 and increasing autoneg timer above.
+ */
+ if (dp83867->rxctrl_strap_quirk)
+ phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
+ BIT(8));
}
val = phy_read(phydev, DP83867_CFG3);