diff options
Diffstat (limited to 'drivers/net/phy/at803x.c')
-rw-r--r-- | drivers/net/phy/at803x.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 93a8bb9df1..8d6b879a27 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -32,6 +32,9 @@ #define AT803X_DEBUG_REG_5 0x05 #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) +#define AT803X_DEBUG_REG_HIB_CTRL 0x0b +#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) + /* AT803x supports either the XTAL input pad, an internal PLL or the * DSP as clock reference for the clock output pad. The XTAL reference * is only used for 25 MHz output, all other frequencies need the PLL. @@ -59,6 +62,9 @@ */ #define AT8035_CLK_OUT_MASK GENMASK(4, 3) +#define AT803X_MMD3_SMARTEEE_CTL3 0x805d +#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8) + #define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7) #define AT803X_CLK_OUT_STRENGTH_FULL 0 #define AT803X_CLK_OUT_STRENGTH_HALF 1 @@ -128,6 +134,15 @@ static int at803x_disable_tx_delay(struct phy_device *phydev) AT803X_DEBUG_TX_CLK_DLY_EN, 0); } +static int at803x_hibernation_mode_config(struct phy_device *phydev) +{ + /* The default after hardware reset is hibernation mode enabled. After + * software reset, the value is retained. + */ + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, + AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0); +} + static bool at803x_match_phy_id(struct phy_device *phydev, u32 phy_id) { struct phy_driver *drv = to_phy_driver(phydev->dev.driver); @@ -138,8 +153,8 @@ static bool at803x_match_phy_id(struct phy_device *phydev, u32 phy_id) static int at803x_parse_dt(struct phy_device *phydev) { - const struct device_d *dev = &phydev->dev; - const struct device_node *node = dev->device_node; + const struct device *dev = &phydev->dev; + const struct device_node *node = dev->of_node; struct at803x_priv *priv = phydev->priv; unsigned int sel; u32 freq, strength; @@ -221,6 +236,12 @@ static int at803x_probe(struct phy_device *phydev) return at803x_parse_dt(phydev); } +static int at803x_smarteee_config(struct phy_device *phydev) +{ + return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3, + AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0); +} + static int at803x_clk_out_config(struct phy_device *phydev) { struct at803x_priv *priv = phydev->priv; @@ -229,14 +250,14 @@ static int at803x_clk_out_config(struct phy_device *phydev) if (!priv->clk_25m_mask) return 0; - val = phy_read_mmd_indirect(phydev, AT803X_MMD7_CLK25M, MDIO_MMD_AN); + val = phy_read_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M); if (val < 0) return val; val &= ~priv->clk_25m_mask; val |= priv->clk_25m_reg; - phy_write_mmd_indirect(phydev, AT803X_MMD7_CLK25M, MDIO_MMD_AN, val); + phy_write_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, val); return 0; } @@ -270,7 +291,25 @@ static int at803x_config_init(struct phy_device *phydev) if (ret < 0) return ret; - return at803x_clk_out_config(phydev); + ret = at803x_smarteee_config(phydev); + if (ret < 0) + return ret; + + ret = at803x_clk_out_config(phydev); + if (ret < 0) + return ret; + + ret = at803x_hibernation_mode_config(phydev); + if (ret < 0) + return ret; + + /* Ar803x extended next page bit is enabled by default. Cisco + * multigig switches read this bit and attempt to negotiate 10Gbps + * rates even if the next page bit is disabled. This is incorrect + * behaviour but we still need to accommodate it. XNP is only needed + * for 10Gbps support, so disable XNP. + */ + return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); } static struct phy_driver at803x_driver[] = { |