diff options
Diffstat (limited to 'drivers/net/pcs/pcs-xpcs.c')
-rw-r--r-- | drivers/net/pcs/pcs-xpcs.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 944ba105cac1..aa985a5aae8d 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -63,6 +63,9 @@ #define DW_VR_MII_DIG_CTRL1 0x8000 #define DW_VR_MII_AN_CTRL 0x8001 #define DW_VR_MII_AN_INTR_STS 0x8002 +/* EEE Mode Control Register */ +#define DW_VR_MII_EEE_MCTRL0 0x8006 +#define DW_VR_MII_EEE_MCTRL1 0x800b /* VR_MII_DIG_CTRL1 */ #define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9) @@ -86,6 +89,20 @@ #define DW_VR_MII_C37_ANSGM_SP_1000 0x2 #define DW_VR_MII_C37_ANSGM_SP_LNKSTS BIT(4) +/* VR MII EEE Control 0 defines */ +#define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */ +#define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */ +#define DW_VR_MII_EEE_TX_QUIET_EN BIT(2) /* Tx Quiet Enable */ +#define DW_VR_MII_EEE_RX_QUIET_EN BIT(3) /* Rx Quiet Enable */ +#define DW_VR_MII_EEE_TX_EN_CTRL BIT(4) /* Tx Control Enable */ +#define DW_VR_MII_EEE_RX_EN_CTRL BIT(7) /* Rx Control Enable */ + +#define DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT 8 +#define DW_VR_MII_EEE_MULT_FACT_100NS GENMASK(11, 8) + +/* VR MII EEE Control 1 defines */ +#define DW_VR_MII_EEE_TRN_LPI BIT(0) /* Transparent Mode Enable */ + static const int xpcs_usxgmii_features[] = { ETHTOOL_LINK_MODE_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT, @@ -650,6 +667,39 @@ static int xpcs_validate(struct mdio_xpcs_args *xpcs, return 0; } +static int xpcs_config_eee(struct mdio_xpcs_args *xpcs, int mult_fact_100ns, + int enable) +{ + int ret; + + if (enable) { + /* Enable EEE */ + ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN | + DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN | + DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL | + mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT; + } else { + ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0); + if (ret < 0) + return ret; + ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN | + DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN | + DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL | + DW_VR_MII_EEE_MULT_FACT_100NS); + } + + ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret); + if (ret < 0) + return ret; + + ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1); + if (ret < 0) + return ret; + + ret |= DW_VR_MII_EEE_TRN_LPI; + return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret); +} + static int xpcs_config_aneg_c37_sgmii(struct mdio_xpcs_args *xpcs) { int ret; @@ -908,6 +958,7 @@ static struct mdio_xpcs_ops xpcs_ops = { .get_state = xpcs_get_state, .link_up = xpcs_link_up, .probe = xpcs_probe, + .config_eee = xpcs_config_eee, }; struct mdio_xpcs_ops *mdio_xpcs_get_ops(void) |