Commit cb2f01b8 authored by Vincent Whitchurch's avatar Vincent Whitchurch Committed by Jakub Kicinski

net: phy: adin: allow control of Fast Link Down

Add support to allow Fast Link Down (aka "Enhanced link detection") to
be controlled via the ETHTOOL_PHY_FAST_LINK_DOWN tunable.  These PHYs
have this feature enabled by default.
Signed-off-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Acked-by: default avatarNuno Sa <nuno.sa@analog.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20231127-adin-fld-v1-1-797f6423fd48@axis.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 127532cd
...@@ -68,6 +68,24 @@ ...@@ -68,6 +68,24 @@
#define ADIN1300_EEE_CAP_REG 0x8000 #define ADIN1300_EEE_CAP_REG 0x8000
#define ADIN1300_EEE_ADV_REG 0x8001 #define ADIN1300_EEE_ADV_REG 0x8001
#define ADIN1300_EEE_LPABLE_REG 0x8002 #define ADIN1300_EEE_LPABLE_REG 0x8002
#define ADIN1300_FLD_EN_REG 0x8E27
#define ADIN1300_FLD_PCS_ERR_100_EN BIT(7)
#define ADIN1300_FLD_PCS_ERR_1000_EN BIT(6)
#define ADIN1300_FLD_SLCR_OUT_STUCK_100_EN BIT(5)
#define ADIN1300_FLD_SLCR_OUT_STUCK_1000_EN BIT(4)
#define ADIN1300_FLD_SLCR_IN_ZDET_100_EN BIT(3)
#define ADIN1300_FLD_SLCR_IN_ZDET_1000_EN BIT(2)
#define ADIN1300_FLD_SLCR_IN_INVLD_100_EN BIT(1)
#define ADIN1300_FLD_SLCR_IN_INVLD_1000_EN BIT(0)
/* These bits are the ones which are enabled by default. */
#define ADIN1300_FLD_EN_ON \
(ADIN1300_FLD_SLCR_OUT_STUCK_100_EN | \
ADIN1300_FLD_SLCR_OUT_STUCK_1000_EN | \
ADIN1300_FLD_SLCR_IN_ZDET_100_EN | \
ADIN1300_FLD_SLCR_IN_ZDET_1000_EN | \
ADIN1300_FLD_SLCR_IN_INVLD_1000_EN)
#define ADIN1300_CLOCK_STOP_REG 0x9400 #define ADIN1300_CLOCK_STOP_REG 0x9400
#define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000 #define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
...@@ -416,6 +434,37 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval) ...@@ -416,6 +434,37 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval)
val); val);
} }
static int adin_get_fast_down(struct phy_device *phydev, u8 *msecs)
{
int reg;
reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_FLD_EN_REG);
if (reg < 0)
return reg;
if (reg & ADIN1300_FLD_EN_ON)
*msecs = ETHTOOL_PHY_FAST_LINK_DOWN_ON;
else
*msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
return 0;
}
static int adin_set_fast_down(struct phy_device *phydev, const u8 *msecs)
{
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_ON)
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_FLD_EN_REG,
ADIN1300_FLD_EN_ON);
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_FLD_EN_REG,
ADIN1300_FLD_EN_ON);
return -EINVAL;
}
static int adin_get_tunable(struct phy_device *phydev, static int adin_get_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, void *data) struct ethtool_tunable *tuna, void *data)
{ {
...@@ -424,6 +473,8 @@ static int adin_get_tunable(struct phy_device *phydev, ...@@ -424,6 +473,8 @@ static int adin_get_tunable(struct phy_device *phydev,
return adin_get_downshift(phydev, data); return adin_get_downshift(phydev, data);
case ETHTOOL_PHY_EDPD: case ETHTOOL_PHY_EDPD:
return adin_get_edpd(phydev, data); return adin_get_edpd(phydev, data);
case ETHTOOL_PHY_FAST_LINK_DOWN:
return adin_get_fast_down(phydev, data);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -437,6 +488,8 @@ static int adin_set_tunable(struct phy_device *phydev, ...@@ -437,6 +488,8 @@ static int adin_set_tunable(struct phy_device *phydev,
return adin_set_downshift(phydev, *(const u8 *)data); return adin_set_downshift(phydev, *(const u8 *)data);
case ETHTOOL_PHY_EDPD: case ETHTOOL_PHY_EDPD:
return adin_set_edpd(phydev, *(const u16 *)data); return adin_set_edpd(phydev, *(const u16 *)data);
case ETHTOOL_PHY_FAST_LINK_DOWN:
return adin_set_fast_down(phydev, data);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment