* [PATCH net-next v?] [PATCH net-next] net: phy: motorcomm: add YT8831 2.5G PHY support
@ 2026-10-22 5:46 Frank.sae
2026-10-27 0:17 ` Jakub Kicinski
0 siblings, 1 reply; 2+ messages in thread
From: Frank.sae @ 2026-10-22 5:46 UTC (permalink / raw)
To: andrew, hkallweit1, linux, kuba, pabeni, edumazet, davem, netdev
Cc: linux-kernel, lingyu.zou, xiaoyong.li, jie.han
Add a driver for motorcomm yt8831/yt8821-vd ethernet phy.
Verified the driver in BPI-R3(with MTK Filogic-830 Soc)development board
YT8831 works in AUTO_BX2500_SGMII or FORCE_BX2500 interface,
supports 2.5G/1000M/100M/10M speeds, and wol(magic package)
Signed-off-by: Frank.sae <frank.sae@motor-comm.com>
---
drivers/net/phy/motorcomm.c | 548 +++++++++++++++++++++++++++++++++++-
1 file changed, 546 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 463e1ea3efc9..04852b4a5ba5 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Motorcomm 8511/8521/8522/8531/8531S/861x/8821 PHY driver.
+ * Motorcomm 8511/8521/8522/8531/8531S/861x/8821/8831 PHY driver.
*
* Author: Peter Geis <pgwipeout@gmail.com>
* Author: Frank <Frank.Sae@motor-comm.com>
@@ -22,6 +22,7 @@
/* Live captured from YT921x switch internal MDIO bus */
#define PHY_ID_INT861X 0x01e04281
#define PHY_ID_YT8821 0x4f51ea19
+#define PHY_ID_YT8831 0x4f51e938
/* YT8521/YT8531S/YT8821 Register Overview
* UTP Register space | FIBER Register space
* ------------------------------------------------------------
@@ -171,6 +172,11 @@
#define YT8521_RSSR_UTP_SPACE (0x0 << 1)
#define YT8521_RSSR_TO_BE_ARBITRATED (0xFF)
+#define YT8831_REG_SPACE_SELECT_REG 0x8020
+#define YT8831_RSSR_SPACE_MASK (BIT(1) | BIT(0))
+#define YT8831_RSSR_FIBER_SAPCE BIT(1)
+#define YT8831_RSSR_UTP_SAPCE BIT(0)
+
#define YT8521_CHIP_CONFIG_REG 0xA001
#define YT8521_CCR_SW_RST BIT(15)
#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4)
@@ -258,6 +264,53 @@
#define YTPHY_WCR_INTR_SEL BIT(6)
#define YTPHY_WCR_ENABLE BIT(3)
+#define YT8831_WOL_CONFIG_REG 0x160a
+#define YT8831_WOL_ENABLE_MASK BIT(0)
+#define YT8831_WOL_ENABLE BIT(0)
+#define YT8831_WOL_DISABLE 0x0
+#define YT8831_WOL_PULSE_WIDTH_MASK (BIT(3) | BIT(2))
+#define YT8831_WOL_PULSE_WIDTH_168MS BIT(2)
+#define YT8831_WOL_OUTPUT_TYPE_SEL_MASK BIT(1)
+#define YT8831_WOL_OUTPUT_TYPE_SEL_PULSE BIT(1)
+
+#define YT8831_WOL_MACADDR2_REG 0x1604
+#define YT8831_WOL_MACADDR1_REG 0xA006
+#define YT8831_WOL_MACADDR0_REG 0xA008
+
+#define YT8831_WCR_INTR_REG 0x8301
+#define YT8831_WCR_INTR_SEL_MASK (BIT(1) | BIT(0))
+#define YT8831_WCR_INTR_SEL_WOL_ONLY 0x2
+#define YT8831_WCR_INTR_SEL_ALL 0x1
+
+
+#define YT8831_SDS_WRITE_PROTECT_REG 0x873
+#define YT8831_SDS_SGMII_OUTPUT_REG 0x1002
+
+#define YT8831_UTP_WRITE_PROTECT_REG 0x1
+#define YT8831_UTP_DAC_DATA_DLY_REG 0x0
+#define YT8831_UTP_REF_DLAY_SEL_REG 0x3
+#define YT8831_UTP_REF_DLAY_SEL_FEXT_REG 0x4
+#define YT8831_UTP_COE_MANUAL_SHIFT_SEL_2500_REG 0x723
+#define YT8831_UTP_EEE_OPTIM_1_REG 0x727
+#define YT8831_UTP_EEE_OPTIM_2_REG 0x339
+#define YT8831_UTP_EEE_MSE1_REG 0xc3
+#define YT8831_UTP_EEE_MSE2_REG 0x32
+#define YT8831_UTP_EEE_OPTIM_3_REG 0xff
+#define YT8831_UTP_EEE_OPTIM_4_REG 0x372
+#define YT8831_UTP_EEE_OPTIM_5_REG 0x336
+#define YT8831_UTP_EEE_OPTIM_6_REG 0x340
+#define YT8831_UTP_PSAN_OPTIM_REG 0x1e58
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_1_REG 0x209e
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_2_REG 0x20a4
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_3_REG 0x20a9
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_4_REG 0x20af
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_5_REG 0x20b4
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_6_REG 0x20ba
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_7_REG 0x20bf
+#define YT8831_UTP_1000M_TEMPLATE_OPTIM_8_REG 0x20c5
+#define YT8831_UTP_2500M_TEMPLATE_OPTIM_1_REG 0x20ff
+#define YT8831_UTP_2500M_TEMPLATE_OPTIM_2_REG 0x2100
+
/* 2b00 84ms
* 2b01 168ms *default*
* 2b10 336ms
@@ -397,6 +450,16 @@
#define YT8821_CHIP_MODE_AUTO_BX2500_SGMII 0
#define YT8821_CHIP_MODE_FORCE_BX2500 1
+#define YT8831_CHIP_MODE_SEL 0x8802
+#define YT8831_CHIP_MODE_SEL_MASK GENMASK(2, 0)
+#define YT8831_CHIP_MODE_AUTO_BX2500_SGMII 0x0
+#define YT8831_CHIP_MODE_FORCE_2500BASEX BIT(0)
+#define YT8831_CHIP_MODE_UTP_TO_FIBER_FORCE (BIT(2) | BIT(0))
+
+#define YT8831_MDIO_ADDRESS_CTL 0x8004
+#define YT8831_MDIO_ADDRESS_CTL_EN_BROADCAST_MASK BIT(8)
+#define YT8831_MDIO_ADDRESS_CTL_EN_BROADCAST BIT(8)
+
struct yt8521_priv {
/* combo_advertising is used for case of YT8521 in combo mode,
* this means that yt8521 may work in utp or fiber mode which depends
@@ -543,6 +606,29 @@ static int ytphy_modify_ext_with_lock(struct phy_device *phydev, u16 regnum,
return ret;
}
+/**
+ * yt8831_get_wol() - report whether wake-on-lan is enabled
+ * @phydev: a pointer to a &struct phy_device
+ * @wol: a pointer to a &struct ethtool_wolinfo
+ *
+ * NOTE: YT8831_WOL_CONFIG_REG is common ext reg.
+ */
+static void yt8831_get_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ int wol_config;
+
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = 0;
+
+ wol_config = ytphy_read_ext_with_lock(phydev, YT8831_WOL_CONFIG_REG);
+ if (wol_config < 0)
+ return;
+
+ if (wol_config & YT8831_WOL_ENABLE_MASK)
+ wol->wolopts |= WAKE_MAGIC;
+}
+
/**
* ytphy_get_wol() - report whether wake-on-lan is enabled
* @phydev: a pointer to a &struct phy_device
@@ -704,6 +790,74 @@ static int yt8531_set_wol(struct phy_device *phydev,
return 0;
}
+/**
+ * yt8831_set_wol() - turn wake-on-lan on or off
+ * @phydev: a pointer to a &struct phy_device
+ * @wol: a pointer to a &struct ethtool_wolinfo
+ *
+ * NOTE: YT8831_WOL_CONFIG_REG is common ext reg.
+ */
+static int yt8831_set_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ const u16 mac_addr_reg[] = {
+ YT8831_WOL_MACADDR2_REG,
+ YT8831_WOL_MACADDR1_REG,
+ YT8831_WOL_MACADDR0_REG,
+ };
+ const u8 *mac_addr;
+ u16 mask, val;
+ int ret;
+ u8 i;
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ mac_addr = phydev->attached_dev->dev_addr;
+
+ /* Store the device address for the magic packet */
+ for (i = 0; i < 3; i++) {
+ ret = ytphy_write_ext_with_lock(phydev, mac_addr_reg[i],
+ ((mac_addr[i * 2] << 8)) |
+ (mac_addr[i * 2 + 1]));
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Enable WOL feature */
+ mask = YT8831_WOL_ENABLE_MASK
+ | YT8831_WOL_PULSE_WIDTH_MASK
+ | YT8831_WOL_OUTPUT_TYPE_SEL_MASK;
+
+ val = YT8831_WOL_ENABLE
+ | YT8831_WOL_PULSE_WIDTH_168MS
+ | YT8831_WOL_OUTPUT_TYPE_SEL_PULSE;
+
+ ret = ytphy_modify_ext_with_lock(phydev, YT8831_WOL_CONFIG_REG,
+ mask, val);
+ if (ret < 0)
+ return ret;
+
+ /* Enable WOL interrupt */
+ ret = ytphy_modify_ext_with_lock(phydev, YT8831_WCR_INTR_REG,
+ YT8831_WCR_INTR_SEL_MASK,
+ YT8831_WCR_INTR_SEL_WOL_ONLY);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* Disable WOL feature */
+ mask = YT8831_WOL_ENABLE_MASK;
+ ret = ytphy_modify_ext_with_lock(phydev, YT8831_WOL_CONFIG_REG,
+ mask, YT8831_WOL_DISABLE);
+
+ /* Disable WOL interrupt */
+ ret = ytphy_modify_ext_with_lock(phydev, YT8831_WCR_INTR_REG,
+ YT8831_WCR_INTR_SEL_MASK, YT8831_WCR_INTR_SEL_ALL);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int yt8511_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, YT8511_PAGE_SELECT);
@@ -798,6 +952,27 @@ static int yt8521_read_page(struct phy_device *phydev)
return YT8521_RSSR_UTP_SPACE;
};
+/**
+ * yt8831_read_page() - read reg page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * returns current reg space of yt8831 (YT8831_RSSR_FIBER_SAPCE/
+ * YT8831_RSSR_UTP_SAPCE) or negative errno code
+ */
+static int yt8831_read_page(struct phy_device *phydev)
+{
+ int old_page;
+
+ old_page = ytphy_read_ext(phydev, YT8831_REG_SPACE_SELECT_REG);
+ if (old_page < 0)
+ return old_page;
+
+ if ((old_page & YT8831_RSSR_SPACE_MASK) == YT8831_RSSR_FIBER_SAPCE)
+ return YT8831_RSSR_FIBER_SAPCE;
+
+ return YT8831_RSSR_UTP_SAPCE;
+};
+
/**
* yt8521_write_page() - write reg page
* @phydev: a pointer to a &struct phy_device
@@ -818,6 +993,26 @@ static int yt8521_write_page(struct phy_device *phydev, int page)
return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set);
};
+/**
+ * yt8831_write_page() - write reg page
+ * @phydev: a pointer to a &struct phy_device
+ * @page: The reg page(YT8831_RSSR_FIBER_SAPCE/YT8831_RSSR_UTP_SAPCE) to write.
+ *
+ * returns 0 or negative errno code
+ */
+static int yt8831_write_page(struct phy_device *phydev, int page)
+{
+ int mask = YT8831_RSSR_SPACE_MASK;
+ int set;
+
+ if ((page & YT8831_RSSR_SPACE_MASK) == YT8831_RSSR_FIBER_SAPCE)
+ set = YT8831_RSSR_FIBER_SAPCE;
+ else
+ set = YT8831_RSSR_UTP_SAPCE;
+
+ return ytphy_modify_ext(phydev, YT8831_REG_SPACE_SELECT_REG, mask, set);
+};
+
/**
* struct ytphy_cfg_reg_map - map a config value to a register value
* @cfg: value in device configuration
@@ -2554,6 +2749,187 @@ static int yt8521_get_features(struct phy_device *phydev)
return ret;
}
+static int yt8831_config_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_config_aneg(phydev);
+ if (ret < 0)
+ return ret;
+
+ return genphy_c45_config_aneg(phydev);
+}
+
+/**
+ * yt8831_serdes_init() - serdes init
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8831_serdes_init(struct phy_device *phydev)
+{
+ int old_page = YT8831_RSSR_UTP_SAPCE;
+ int ret = -EINVAL;
+
+
+ old_page = phy_select_page(phydev, YT8831_RSSR_FIBER_SAPCE);
+ if (old_page < 0) {
+ phydev_err(phydev, "Failed to select page: %d\n",
+ old_page);
+ goto err_restore_page;
+ }
+
+ ret = ytphy_write_ext(phydev, YT8831_SDS_WRITE_PROTECT_REG, 0x1);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = ytphy_write_ext(phydev, YT8831_SDS_SGMII_OUTPUT_REG, 0xc4);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* softreset sds space */
+ ret = ytphy_modify_ext(phydev, MII_BMCR, BMCR_RESET, BMCR_RESET);
+ if (ret < 0)
+ goto err_restore_page;
+
+
+err_restore_page:
+ return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8831_utp_init() - utp init
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8831_utp_init(struct phy_device *phydev)
+{
+ int ret = -EINVAL;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_WRITE_PROTECT_REG, 0x3);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_DAC_DATA_DLY_REG, 0xc8d);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_REF_DLAY_SEL_REG, 0xa426);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_REF_DLAY_SEL_FEXT_REG, 0x8009);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_COE_MANUAL_SHIFT_SEL_2500_REG, 6);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_1_REG, 0x1001);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_2_REG, 0x7c52);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_MSE1_REG, 0x3848);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_MSE2_REG, 0xa8e8);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_3_REG, 0x5200);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_4_REG, 0x5849);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_5_REG, 0xb00a);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_EEE_OPTIM_6_REG, 0x3022);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_PSAN_OPTIM_REG, 0x1f10);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_1_REG, 0x22c8);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_2_REG, 0x2437);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_3_REG, 0x22c8);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_4_REG, 0x2437);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_5_REG, 0x22c8);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_6_REG, 0x2437);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_7_REG, 0x22c8);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_1000M_TEMPLATE_OPTIM_8_REG, 0x2437);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_2500M_TEMPLATE_OPTIM_1_REG, 0x1111);
+ if (ret < 0)
+ goto err;
+
+ ret = ytphy_write_ext_with_lock(phydev, YT8831_UTP_2500M_TEMPLATE_OPTIM_2_REG, 0x1111);
+ if (ret < 0)
+ goto err;
+
+err:
+ return ret;
+}
+
+/**
+ * yt8831_get_rate_matching - read register to get phy chip mode
+ * @phydev: target phy_device struct
+ * @iface: PHY data interface type
+ *
+ * Returns: rate matching type or negative errno code
+ */
+static int yt8831_get_rate_matching(struct phy_device *phydev,
+ phy_interface_t iface)
+{
+ int val;
+
+ val = ytphy_read_ext_with_lock(phydev, YT8831_CHIP_MODE_SEL);
+ if (val < 0)
+ return val;
+
+ if (FIELD_GET(YT8831_CHIP_MODE_SEL_MASK, val) ==
+ YT8831_CHIP_MODE_FORCE_2500BASEX)
+ return RATE_MATCH_PAUSE;
+
+ return RATE_MATCH_NONE;
+}
+
/**
* yt861x_config_init() - apply the auto sleep setting to the PHY
* @phydev: a pointer to a &struct phy_device
@@ -2992,6 +3368,67 @@ static int yt8821_soft_reset(struct phy_device *phydev)
YT8521_CCR_SW_RST, 0);
}
+/**
+ * yt8831_config_init() - phy initializatioin
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8831_config_init(struct phy_device *phydev)
+{
+
+ u8 mode = YT8831_CHIP_MODE_AUTO_BX2500_SGMII;
+ int ret;
+
+
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX,
+ phydev->possible_interfaces);
+
+
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ phydev->possible_interfaces);
+
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_2500BASEX:
+ mode = YT8831_CHIP_MODE_FORCE_2500BASEX;
+ phydev->rate_matching = RATE_MATCH_PAUSE;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ mode = YT8831_CHIP_MODE_AUTO_BX2500_SGMII;
+ phydev->rate_matching = RATE_MATCH_NONE;
+ break;
+ default:
+ mode = YT8831_CHIP_MODE_AUTO_BX2500_SGMII;
+ phydev->rate_matching = RATE_MATCH_NONE;
+ break;
+ }
+
+ ret = ytphy_modify_ext_with_lock(phydev,
+ YT8831_CHIP_MODE_SEL,
+ YT8831_CHIP_MODE_SEL_MASK,
+ mode);
+ if (ret < 0)
+ return ret;
+
+ /* Disable broadcast*/
+ ret = ytphy_modify_ext_with_lock(phydev,
+ YT8831_MDIO_ADDRESS_CTL,
+ YT8831_MDIO_ADDRESS_CTL_EN_BROADCAST_MASK,
+ 0);
+ if (ret < 0)
+ return ret;
+
+ ret = yt8831_serdes_init(phydev);
+ if (ret < 0)
+ return ret;
+
+ ret = yt8831_utp_init(phydev);
+ if (ret < 0)
+ return ret;
+
+ return genphy_soft_reset(phydev);
+}
+
/**
* yt8821_config_init() - phy initializatioin
* @phydev: a pointer to a &struct phy_device
@@ -3102,6 +3539,50 @@ static void yt8821_update_interface(struct phy_device *phydev)
}
}
+/**
+ * yt8831_read_status() - determines the negotiated speed and duplex
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8831_read_status(struct phy_device *phydev)
+{
+ int ret;
+ int val;
+
+ phydev->speed = SPEED_UNKNOWN;
+ phydev->duplex = DUPLEX_UNKNOWN;
+
+ ret = genphy_read_status(phydev);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+ phydev->link = val & YTPHY_SSR_LINK;
+ if (phydev->link)
+ yt8821_adjust_status(phydev, val);
+
+ phydev_dbg(phydev,
+ "%s, phy addr: %d, link %s\n",
+ __func__, phydev->mdio.addr, phydev->link ? "up" : "down");
+
+
+ val = ytphy_read_ext_with_lock(phydev, YT8831_CHIP_MODE_SEL);
+ if (val < 0)
+ return val;
+
+ if (FIELD_GET(YT8831_CHIP_MODE_SEL_MASK, val) ==
+ YT8831_CHIP_MODE_AUTO_BX2500_SGMII)
+ yt8821_update_interface(phydev);
+
+
+ return 0;
+}
+
/**
* yt8821_read_status() - determines the negotiated speed and duplex
* @phydev: a pointer to a &struct phy_device
@@ -3190,6 +3671,29 @@ static int yt8821_modify_utp_fiber_bmcr(struct phy_device *phydev,
mask, set);
}
+/**
+ * yt8831_suspend() - suspend the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+
+static int yt8831_suspend(struct phy_device *phydev)
+{
+ struct ethtool_wolinfo wol = {0};
+ int ret;
+
+ yt8831_get_wol(phydev, &wol);
+
+ /* if wol enable, do nothing */
+ if (wol.wolopts & WAKE_MAGIC)
+ ret = 0;
+ else
+ ret = genphy_suspend(phydev);
+
+ return ret;
+}
+
/**
* yt8821_suspend() - suspend the hardware
* @phydev: a pointer to a &struct phy_device
@@ -3212,6 +3716,29 @@ static int yt8821_suspend(struct phy_device *phydev)
return yt8821_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN);
}
+/**
+ * yt8831_resume() - resume the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8831_resume(struct phy_device *phydev)
+{
+ struct ethtool_wolinfo wol = {0};
+ int ret;
+
+ yt8831_get_wol(phydev, &wol);
+
+ /* if wol enable, do nothing */
+ if (wol.wolopts & WAKE_MAGIC)
+ ret = 0;
+ else
+ ret = genphy_resume(phydev);
+
+ return ret;
+}
+
+
/**
* yt8821_resume() - resume the hardware
* @phydev: a pointer to a &struct phy_device
@@ -3337,11 +3864,28 @@ static struct phy_driver motorcomm_phy_drvs[] = {
.suspend = yt8821_suspend,
.resume = yt8821_resume,
},
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8831),
+ .name = "YT8831/YT8821-VD 2.5Gbps PHY",
+ .get_features = yt8821_get_features,
+ .read_page = yt8831_read_page,
+ .write_page = yt8831_write_page,
+ .get_wol = yt8831_get_wol,
+ .set_wol = yt8831_set_wol,
+ .config_aneg = yt8831_config_aneg,
+ .aneg_done = genphy_aneg_done,
+ .config_init = yt8831_config_init,
+ .get_rate_matching = yt8831_get_rate_matching,
+ .read_status = yt8831_read_status,
+ .soft_reset = genphy_soft_reset,
+ .suspend = yt8831_suspend,
+ .resume = yt8831_resume,
+ },
};
module_phy_driver(motorcomm_phy_drvs);
-MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/861x/8821 PHY driver");
+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/861x/8821/8831 PHY driver");
MODULE_AUTHOR("Peter Geis");
MODULE_AUTHOR("Frank");
MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH net-next v?] [PATCH net-next] net: phy: motorcomm: add YT8831 2.5G PHY support
2026-10-22 5:46 [PATCH net-next v?] [PATCH net-next] net: phy: motorcomm: add YT8831 2.5G PHY support Frank.sae
@ 2026-10-27 0:17 ` Jakub Kicinski
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2026-10-27 0:17 UTC (permalink / raw)
To: Frank.sae
Cc: andrew, hkallweit1, linux, pabeni, edumazet, davem, netdev,
linux-kernel, lingyu.zou, xiaoyong.li, jie.han
On Thu, 22 Oct 2026 05:46:42 +0000 Frank.sae wrote:
> Add a driver for motorcomm yt8831/yt8821-vd ethernet phy.
> Verified the driver in BPI-R3(with MTK Filogic-830 Soc)development board
> YT8831 works in AUTO_BX2500_SGMII or FORCE_BX2500 interface,
> supports 2.5G/1000M/100M/10M speeds, and wol(magic package)
## Form letter - net-next-closed
The merge window for Linux v7.4 has begun, and the net-next
tree is now closed for new drivers, features, code refactoring
and optimizations. We are currently accepting bug fixes only.
Please repost when net-next reopens. There is some uncertainty
about how long this merge window will last, so please check
https://netdev.bots.linux.dev/net-next.html
before reposting. net-next _may_ reopen on Nov 2nd.
See:
https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#development-cycle
> +/**
> + * yt8831_set_wol() - turn wake-on-lan on or off
> + * @phydev: a pointer to a &struct phy_device
> + * @wol: a pointer to a &struct ethtool_wolinfo
> + *
> + * NOTE: YT8831_WOL_CONFIG_REG is common ext reg.
> + */
> +static int yt8831_set_wol(struct phy_device *phydev,
> + struct ethtool_wolinfo *wol)
Please run scripts/kernel-doc -Wall on this, the return
value must be documented in newly added kdoc.
--
pw-bot: defer
pv-bot: closed
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-27 0:17 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 5:46 [PATCH net-next v?] [PATCH net-next] net: phy: motorcomm: add YT8831 2.5G PHY support Frank.sae
2026-10-27 0:17 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®