diff options
Diffstat (limited to 'drivers/net/phy/dp83867.c')
-rw-r--r-- | drivers/net/phy/dp83867.c | 45 |
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); |