mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 04:37:32 -04:00
net: phy: micrel: expose KSZ87xx low-loss cable tunables
Add support for the KSZ87xx low-loss cable PHY tunables in the Micrel PHY driver by implementing get_tunable and set_tunable callbacks. These callbacks expose vendor-specific PHY tunables used to control the KSZ87xx embedded PHY receiver behavior when operating with short or low-loss Ethernet cables. The tunables provide: - a boolean short-cable preset applying known good settings; - an integer LPF bandwidth control; - an integer DSP EQ initial value control. The Micrel PHY driver forwards these tunables via standard phy_read() / phy_write() operations, which are virtualized by the KSZ8 DSA driver and translated into the appropriate indirect switch register accesses. Reviewed-by: Marek Vasut <marex@nabladev.com> Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de> Signed-off-by: Fidelio Lawson <fidelio.lawson@exotec.com> Link: https://patch.msgid.link/20260609-ksz87xx_errata_low_loss_connections-v10-3-9ba4418cf3db@exotec.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
13655144dd
commit
a1ee1b9beb
@@ -287,6 +287,12 @@
|
||||
/* PHY Control 2 / PHY Control (if no PHY Control 1) */
|
||||
#define MII_KSZPHY_CTRL_2 0x1f
|
||||
#define MII_KSZPHY_CTRL MII_KSZPHY_CTRL_2
|
||||
|
||||
/* Vendor-specific Clause 22 register, virtualized by KSZ87xx embedded PHYs DSA driver */
|
||||
#define MII_KSZ87XX_SHORT_CABLE 0x1a
|
||||
#define MII_KSZ87XX_LPF_BW 0x1b
|
||||
#define MII_KSZ87XX_EQ_INIT 0x1c
|
||||
|
||||
/* bitmap of PHY register to set interrupt mode */
|
||||
#define KSZ8081_CTRL2_HP_MDIX BIT(15)
|
||||
#define KSZ8081_CTRL2_MDI_MDI_X_SELECT BIT(14)
|
||||
@@ -940,6 +946,59 @@ static int ksz8795_match_phy_device(struct phy_device *phydev,
|
||||
return ksz8051_ksz8795_match_phy_device(phydev, false);
|
||||
}
|
||||
|
||||
static int ksz8795_get_tunable(struct phy_device *phydev,
|
||||
struct ethtool_tunable *tuna, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (tuna->id) {
|
||||
case ETHTOOL_PHY_SHORT_CABLE_PRESET:
|
||||
ret = phy_read(phydev, MII_KSZ87XX_SHORT_CABLE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(u8 *)data = ret;
|
||||
return 0;
|
||||
case ETHTOOL_PHY_LPF_BW:
|
||||
ret = phy_read(phydev, MII_KSZ87XX_LPF_BW);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(u32 *)data = ret & 0xff;
|
||||
return 0;
|
||||
case ETHTOOL_PHY_DSP_EQ_INIT_VALUE:
|
||||
ret = phy_read(phydev, MII_KSZ87XX_EQ_INIT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(u32 *)data = ret & 0xff;
|
||||
return 0;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int ksz8795_set_tunable(struct phy_device *phydev,
|
||||
struct ethtool_tunable *tuna, const void *data)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (tuna->id) {
|
||||
case ETHTOOL_PHY_SHORT_CABLE_PRESET:
|
||||
return phy_write(phydev, MII_KSZ87XX_SHORT_CABLE,
|
||||
*(const u8 *)data);
|
||||
case ETHTOOL_PHY_LPF_BW:
|
||||
val = *(const u32 *)data;
|
||||
if (val > 0xff)
|
||||
return -EINVAL;
|
||||
return phy_write(phydev, MII_KSZ87XX_LPF_BW, (u8)val);
|
||||
case ETHTOOL_PHY_DSP_EQ_INIT_VALUE:
|
||||
val = *(const u32 *)data;
|
||||
if (val > 0xff)
|
||||
return -EINVAL;
|
||||
return phy_write(phydev, MII_KSZ87XX_EQ_INIT, (u8)val);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int ksz9021_load_values_from_of(struct phy_device *phydev,
|
||||
const struct device_node *of_node,
|
||||
u16 reg,
|
||||
@@ -6961,6 +7020,8 @@ static struct phy_driver ksphy_driver[] = {
|
||||
/* PHY_BASIC_FEATURES */
|
||||
.config_init = kszphy_config_init,
|
||||
.match_phy_device = ksz8795_match_phy_device,
|
||||
.get_tunable = ksz8795_get_tunable,
|
||||
.set_tunable = ksz8795_set_tunable,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
}, {
|
||||
|
||||
Reference in New Issue
Block a user