Skip to content

Commit cb2f01b

Browse files
vwaxkuba-moo
authored andcommitted
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: Vincent Whitchurch <[email protected]> Acked-by: Nuno Sa <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 127532c commit cb2f01b

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

drivers/net/phy/adin.c

+53
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@
6868
#define ADIN1300_EEE_CAP_REG 0x8000
6969
#define ADIN1300_EEE_ADV_REG 0x8001
7070
#define ADIN1300_EEE_LPABLE_REG 0x8002
71+
72+
#define ADIN1300_FLD_EN_REG 0x8E27
73+
#define ADIN1300_FLD_PCS_ERR_100_EN BIT(7)
74+
#define ADIN1300_FLD_PCS_ERR_1000_EN BIT(6)
75+
#define ADIN1300_FLD_SLCR_OUT_STUCK_100_EN BIT(5)
76+
#define ADIN1300_FLD_SLCR_OUT_STUCK_1000_EN BIT(4)
77+
#define ADIN1300_FLD_SLCR_IN_ZDET_100_EN BIT(3)
78+
#define ADIN1300_FLD_SLCR_IN_ZDET_1000_EN BIT(2)
79+
#define ADIN1300_FLD_SLCR_IN_INVLD_100_EN BIT(1)
80+
#define ADIN1300_FLD_SLCR_IN_INVLD_1000_EN BIT(0)
81+
/* These bits are the ones which are enabled by default. */
82+
#define ADIN1300_FLD_EN_ON \
83+
(ADIN1300_FLD_SLCR_OUT_STUCK_100_EN | \
84+
ADIN1300_FLD_SLCR_OUT_STUCK_1000_EN | \
85+
ADIN1300_FLD_SLCR_IN_ZDET_100_EN | \
86+
ADIN1300_FLD_SLCR_IN_ZDET_1000_EN | \
87+
ADIN1300_FLD_SLCR_IN_INVLD_1000_EN)
88+
7189
#define ADIN1300_CLOCK_STOP_REG 0x9400
7290
#define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
7391

@@ -416,6 +434,37 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval)
416434
val);
417435
}
418436

437+
static int adin_get_fast_down(struct phy_device *phydev, u8 *msecs)
438+
{
439+
int reg;
440+
441+
reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_FLD_EN_REG);
442+
if (reg < 0)
443+
return reg;
444+
445+
if (reg & ADIN1300_FLD_EN_ON)
446+
*msecs = ETHTOOL_PHY_FAST_LINK_DOWN_ON;
447+
else
448+
*msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
449+
450+
return 0;
451+
}
452+
453+
static int adin_set_fast_down(struct phy_device *phydev, const u8 *msecs)
454+
{
455+
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_ON)
456+
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
457+
ADIN1300_FLD_EN_REG,
458+
ADIN1300_FLD_EN_ON);
459+
460+
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
461+
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
462+
ADIN1300_FLD_EN_REG,
463+
ADIN1300_FLD_EN_ON);
464+
465+
return -EINVAL;
466+
}
467+
419468
static int adin_get_tunable(struct phy_device *phydev,
420469
struct ethtool_tunable *tuna, void *data)
421470
{
@@ -424,6 +473,8 @@ static int adin_get_tunable(struct phy_device *phydev,
424473
return adin_get_downshift(phydev, data);
425474
case ETHTOOL_PHY_EDPD:
426475
return adin_get_edpd(phydev, data);
476+
case ETHTOOL_PHY_FAST_LINK_DOWN:
477+
return adin_get_fast_down(phydev, data);
427478
default:
428479
return -EOPNOTSUPP;
429480
}
@@ -437,6 +488,8 @@ static int adin_set_tunable(struct phy_device *phydev,
437488
return adin_set_downshift(phydev, *(const u8 *)data);
438489
case ETHTOOL_PHY_EDPD:
439490
return adin_set_edpd(phydev, *(const u16 *)data);
491+
case ETHTOOL_PHY_FAST_LINK_DOWN:
492+
return adin_set_fast_down(phydev, data);
440493
default:
441494
return -EOPNOTSUPP;
442495
}

0 commit comments

Comments
 (0)