From nobody Sat Jul 25 01:38:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C09233EF0D7; Tue, 21 Jul 2026 02:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; cv=none; b=itRGhSBAXLe+nJ9D2gp9rwwqR+C5GGBMQx9RYKbnyixFV+qE4NtryS91UtgC4tRnCXGYlD5J7rz3ZIKeBc4aODt9YRxyVceuZ3TaGZZN3DdJoi/iBOQrGGscIM56MH9J2/rRN6Noel75ptKUtw/nyNs29ZWeO1M8nY7akldPaRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; c=relaxed/simple; bh=c31mTF0K49t/Y0JhvbJFnbo3aD+WysmD+s/f/tNmCeY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GwIEDOR3dmevGV66tNIU8GOCdWMU+1GUuLLcM8Q8QugldULholus5axYSxp4+aVJ6LEZe+QagB+ao3/SlmZGXz+qE1CwrG3NjTR6T/ag7TTyn6D+KDcEzYzFLq+y0p10LUZB5g0Sl8xbGov6vtD24MFEzy6ikWRvNqItsva2kRE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=J54Son3R; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="J54Son3R" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66L2OE1W02860135, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1784600654; bh=6h9XZLScA2E9IJpQtIbrAmqsjKEXdNHLdX2ckQK90Uo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=J54Son3RVloln7t0Dv8gGo9g9dT9QTlPEn3I2URyYLLMrtkNGOWYuy/MQKFVmX0WM SETIKGIgC3g1LiA26qy5YtZYXeNVNCJOyHqZ40oJT6uUtVjcvN1LM834xkDv4TyjUh 9BEEjMU8R8FmfbRwxX2DeOu2IqgzR1kKLRaCJXzpcUMUgvEOVVrFPWM4SmQmq1fvj0 4dG6NbLiRYc7E6yBS6o9zBdbXhRYDAUbQw63ORRZ1F2HZI/rwUof8MCXDu6ba/Kvdv 034lHcYunb8Xbf1Cliot1elduRV08xfh/nCIioQGqjUW4vEBkJ/88UX3fcN/bIZZdN O7wPj9JOZJNog== Received: from RS-EX-MBS4.realsil.com.cn ([172.29.17.104]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66L2OE1W02860135 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 21 Jul 2026 10:24:14 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS4.realsil.com.cn (172.29.17.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.43; Tue, 21 Jul 2026 10:24:12 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Tue, 21 Jul 2026 10:24:12 +0800 From: javen To: , , , , , , , , , CC: , , , , Javen Xu Subject: [PATCH net-next v10 1/5] net: phy: c45: add genphy_c45_pma_soft_reset() Date: Tue, 21 Jul 2026 10:24:06 +0800 Message-ID: <20260721022410.1391-2-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260721022410.1391-1-javen_xu@realsil.com.cn> References: <20260721022410.1391-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu Add a generic Clause 45 software reset helper. The helper sets the reset bit in the PMA/PMD control register and waits until the bit is cleared by hardware. Reviewed-by: Nicolai Buchwitz Signed-off-by: Javen Xu Reviewed-by: Maxime Chevallier --- Changes in v2: - no changes, new file Changes in v3: - re-order function according to the order in phy-c45.c Changes in v4: - no changes Changes in v5: - no changes Changes in v6: - increase timeout to 600ms Changes in v7: - no changes Changes in v8: - no changes Changes in v9: - rename genphy_c45_soft_reset to genphy_c45_pma_soft_reset Changes in v10: - no change. Netdev queue overflown. Resend. --- drivers/net/phy/phy-c45.c | 22 ++++++++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 126951741428..c1f817a59739 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -384,6 +384,28 @@ int genphy_c45_check_and_restart_aneg(struct phy_devic= e *phydev, bool restart) } EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg); =20 +/** + * genphy_c45_pma_soft_reset - software reset the PHY via Clause 45 PMA/PM= D control register + * @phydev: target phy_device struct + * + * Return: 0 on success, negative errno on failure. + */ +int genphy_c45_pma_soft_reset(struct phy_device *phydev) +{ + int ret, val; + + ret =3D phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_CTRL1_RESET); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PMAPMD, + MDIO_CTRL1, val, + !(val & MDIO_CTRL1_RESET), + 5000, 600000, true); +} +EXPORT_SYMBOL_GPL(genphy_c45_pma_soft_reset); + /** * genphy_c45_aneg_done - return auto-negotiation complete status * @phydev: target phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index beff1d6fcc7c..57cf9ac3524d 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -2314,6 +2314,7 @@ int genphy_c37_read_status(struct phy_device *phydev,= bool *changed); /* Clause 45 PHY */ int genphy_c45_restart_aneg(struct phy_device *phydev); int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool rest= art); +int genphy_c45_pma_soft_reset(struct phy_device *phydev); int genphy_c45_aneg_done(struct phy_device *phydev); int genphy_c45_read_link(struct phy_device *phydev); int genphy_c45_read_lpa(struct phy_device *phydev); --=20 2.43.0 From nobody Sat Jul 25 01:38:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C08983D413C; Tue, 21 Jul 2026 02:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; cv=none; b=ox+Mfzu8S25clwT0JzJp2G/Xyyxz+h3T0h67Cy3Efg908NdNFMat8pbTSyhZBiU+7jfJhMofMzRdZP3cwraAXapgJ5Q/6yRaUBfsaxPpCCd+zGMTR5bjLCVtbFpFhcqIQUxJlB+pDlLw5qGKq/maz+QoPX4Maltc2HqBC5upSgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; c=relaxed/simple; bh=aW4pnnwEsjOegqYZ8xxJL6RmKf3t/pU770Nr3GPPCBY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PwWxZeIh8eHi3i73XB8X9WInJ5Z29ufQWPtaJHt4Xgcvvt6TV//zMvU6tT5Kl2HPzP3RaQXy3Hwmh8qQ4aPH4V8mh2stP8ZZLC8HPeZrh7TCsYkqv9J0KZP7/gUIbEfxFXrmW/52rEwzb08anO0YQewt4Gvcu2SsFLIPwMTw8a4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=L6Md4+oy; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="L6Md4+oy" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66L2OE1X02860135, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1784600654; bh=ZJlD99uY7K8SFORMYDQxUYt56yHqUHREllniP0yg94g=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=L6Md4+oys58A4C7cOoKeuF9Gbjk2/SJIRaKEXzN4hiONAgCU8D6QE/pT+mgrDT+X5 aYap3r2IICxbw1bO0lrR4Qm3/ec0xJgxvjhI2mQEHoUpu4Z2zLbmgFKHtIecKKaaxQ kFfyRR3fVTF6VaEPWgc0g3mZfpnNxut217W5pJVi4pVgbujs+RPXQltYsoA/oH04vo A+zic8LW6vQQufrRP5cRRenoxVMPqna6QZgc9PPH3kyU4MlAyR4guqrFGGgZPzuhH7 XCfRzHOQR8TJk1KSPniDTuy/7Xz8kAXcDEEv7yruNLQWn0WVjvf8wSMgTxtwYyXJuo +79B1JpFGeP4w== Received: from RS-EX-MBS4.realsil.com.cn ([172.29.17.104]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66L2OE1X02860135 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 21 Jul 2026 10:24:14 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS4.realsil.com.cn (172.29.17.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.43; Tue, 21 Jul 2026 10:24:12 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Tue, 21 Jul 2026 10:24:12 +0800 From: javen To: , , , , , , , , , CC: , , , , Javen Xu Subject: [PATCH net-next v10 2/5] net: phy: c45: add setup and read master/slave helpers Date: Tue, 21 Jul 2026 10:24:07 +0800 Message-ID: <20260721022410.1391-3-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260721022410.1391-1-javen_xu@realsil.com.cn> References: <20260721022410.1391-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch adds two static helpers in drivers/net/phy/phy-c45.c to configure and read back master-slave roles for non BASE-T1 Clause 45 PHYs via the 10GBASE-T AN control/status registers. These helpers are wired into genphy_c45_config_aneg() and genphy_c45_read_status(). This changes the observable ethtool output for drivers using the generic c45 read path. Reviewed-by: Andrew Lunn Signed-off-by: Javen Xu --- Changes in v2: - no changes, new file Changes in v3: - re-order function according to the order in phy-c45.c - add kernel-doc about return value - add MASTER_SLAVE_CFG_MASTER_PREFERRED, MASTER_SLAVE_CFG_SLAVE_PREFERRED, MASTER_SLAVE_CFG_UNKNOWN, MASTER_SLAVE_CFG_UNSUPPORTED, MASTER_SLAVE_CFG_SLAVE_PREFERRED cfg Changes in v4: - no changes Changes in v5: - move genphy_c45_an_setup_master_slave() to genphy_c45_config_aneg(), as that C22 does. Changes in v6: - add colon in the function description - add genphy_c45_read_master_slave in read function Changes in v7: - when phydev->link is down, just return UNKNOWN - modify commit message Changes in v8: - no changes Changes in v9: - no changes Changes in v10: - no changes. Netdev queue overflow. Resend. --- drivers/net/phy/phy-c45.c | 103 ++++++++++++++++++++++++++++++++++++++ include/uapi/linux/mdio.h | 5 ++ 2 files changed, 108 insertions(+) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c1f817a59739..870920311f9a 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -406,6 +406,97 @@ int genphy_c45_pma_soft_reset(struct phy_device *phyde= v) } EXPORT_SYMBOL_GPL(genphy_c45_pma_soft_reset); =20 +/** + * genphy_c45_an_setup_master_slave - Configure Master/Slave setting for C= 45 PHYs + * @phydev: target phy_device struct + * + * Description: Configure the forced or preferred Master/Slave role + * 10GBASE-T control register (MMD 7, Register 0x0020) according to + * IEEE 802.3 standards. + * + * Return: negative errno code on failure, 0 if Master/Slave didn't change, + * or 1 if Master/Slave modes changed. + */ +static int genphy_c45_an_setup_master_slave(struct phy_device *phydev) +{ + u16 ctl =3D 0; + + switch (phydev->master_slave_set) { + case MASTER_SLAVE_CFG_MASTER_PREFERRED: + ctl =3D MDIO_AN_10GBT_CTRL_MS_PORT_TYPE; + break; + case MASTER_SLAVE_CFG_SLAVE_PREFERRED: + break; + case MASTER_SLAVE_CFG_MASTER_FORCE: + ctl =3D MDIO_AN_10GBT_CTRL_MS_ENABLE | MDIO_AN_10GBT_CTRL_MS_VALUE; + break; + case MASTER_SLAVE_CFG_SLAVE_FORCE: + ctl =3D MDIO_AN_10GBT_CTRL_MS_ENABLE; + break; + case MASTER_SLAVE_CFG_UNKNOWN: + case MASTER_SLAVE_CFG_UNSUPPORTED: + return 0; + default: + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); + return -EOPNOTSUPP; + } + + return phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_MS_ENABLE | + MDIO_AN_10GBT_CTRL_MS_VALUE | + MDIO_AN_10GBT_CTRL_MS_PORT_TYPE, ctl); +} + +/** + * genphy_c45_read_master_slave - read master/slave status + * @phydev: target phy_device struct + * + * Description: Read the Master/Slave configuration and status + * from 10GBASE-T control/status registers (MMD 7, Reg 0x0020 and 0x0021). + * + * Return: 0 on success, or a negative error code on failure. + */ +static int genphy_c45_read_master_slave(struct phy_device *phydev) +{ + int val; + + phydev->master_slave_get =3D MASTER_SLAVE_CFG_UNKNOWN; + phydev->master_slave_state =3D MASTER_SLAVE_STATE_UNKNOWN; + + val =3D phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); + if (val < 0) + return val; + + if (val & MDIO_AN_10GBT_CTRL_MS_ENABLE) { + if (val & MDIO_AN_10GBT_CTRL_MS_VALUE) + phydev->master_slave_get =3D MASTER_SLAVE_CFG_MASTER_FORCE; + else + phydev->master_slave_get =3D MASTER_SLAVE_CFG_SLAVE_FORCE; + } else { + if (val & MDIO_AN_10GBT_CTRL_MS_PORT_TYPE) + phydev->master_slave_get =3D MASTER_SLAVE_CFG_MASTER_PREFERRED; + else + phydev->master_slave_get =3D MASTER_SLAVE_CFG_SLAVE_PREFERRED; + } + + val =3D phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); + if (val < 0) + return val; + + if (val & MDIO_AN_10GBT_STAT_MS_FAULT) { + phydev->master_slave_state =3D MASTER_SLAVE_STATE_ERR; + } else if (phydev->link) { + if (val & MDIO_AN_10GBT_STAT_MS_RES) + phydev->master_slave_state =3D MASTER_SLAVE_STATE_MASTER; + else + phydev->master_slave_state =3D MASTER_SLAVE_STATE_SLAVE; + } else { + phydev->master_slave_state =3D MASTER_SLAVE_STATE_UNKNOWN; + } + + return 0; +} + /** * genphy_c45_aneg_done - return auto-negotiation complete status * @phydev: target phy_device struct @@ -1214,6 +1305,10 @@ int genphy_c45_read_status(struct phy_device *phydev) ret =3D genphy_c45_baset1_read_status(phydev); if (ret < 0) return ret; + } else { + ret =3D genphy_c45_read_master_slave(phydev); + if (ret < 0) + return ret; } =20 phy_resolve_aneg_linkmode(phydev); @@ -1247,6 +1342,14 @@ int genphy_c45_config_aneg(struct phy_device *phydev) if (ret > 0) changed =3D true; =20 + if (!genphy_c45_baset1_able(phydev)) { + ret =3D genphy_c45_an_setup_master_slave(phydev); + if (ret < 0) + return ret; + if (ret > 0) + changed =3D true; + } + return genphy_c45_check_and_restart_aneg(phydev, changed); } EXPORT_SYMBOL_GPL(genphy_c45_config_aneg); diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index b2541c948fc1..06f4bc3c20c7 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -332,8 +332,13 @@ #define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */ #define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */ #define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */ +#define MDIO_AN_10GBT_CTRL_MS_ENABLE 0x8000 /* Master/slave manual config = enable */ +#define MDIO_AN_10GBT_CTRL_MS_VALUE 0x4000 /* Master/slave config value (1= =3DMaster) */ +#define MDIO_AN_10GBT_CTRL_MS_PORT_TYPE 0x2000 /* Master Preferred Type */ =20 /* AN 10GBASE-T status register. */ +#define MDIO_AN_10GBT_STAT_MS_FAULT 0x8000 /* Master/slave fault */ +#define MDIO_AN_10GBT_STAT_MS_RES 0x4000 /* Master/slave resolution (1=3DM= aster) */ #define MDIO_AN_10GBT_STAT_LP2_5G 0x0020 /* LP is 2.5GBT capable */ #define MDIO_AN_10GBT_STAT_LP5G 0x0040 /* LP is 5GBT capable */ #define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */ --=20 2.43.0 From nobody Sat Jul 25 01:38:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0AAA3FCB11; Tue, 21 Jul 2026 02:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; cv=none; b=NjOY+KeAluX6g0SWXp4ZfX6NdJLzXQJ4R/NiU2uRT6VmmQEagNM1ZzTXzDsFgva0tbiuzI9JrmeYqjlXZfDBKsRDYpq5yzsIzHjoXqVj80sFLq4TcnNSi67WVwD+ajLB/h6Yf2w8u62vix5DVzMV5hrskcfyizYEALJcqq5Y6jM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600759; c=relaxed/simple; bh=thNk5vBwiAyq5yqG4A1476HUeGb7nz5/2vTjoCl8lqY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LHbJS6/G7Rpd9D89RftjknxBiwyRq9I0dY/bvlS6+npa2tu3TzL+WbbaJ4Vnntun0Wffl8rvDTv8EfB5x5Yhux0AqAEs03NMxvM3+zcMcauiMShPo8Ob52Ryfn79hZRrVqTIFaXb/3Ra/7DTrTGvmZ9TGOmhsR5vPffz/cvNths= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=lfnqj2iS; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="lfnqj2iS" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66L2OE1Y02860135, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1784600654; bh=V1UFpRpSApkLv42ey0bJPoxSUj4ZI1JQhnLlvWH/KlY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=lfnqj2iSqmXFmX2o6kLlooYNbOz1TUuLQo0axjwpDrhoN7SJ2G4xs1sVd6KJzbgKf VcxkUPLr8YkltcNEHdGNJgxCxgStpW8Dyu1D5OdMrgAts0zujs29Nr+9ju5hMhtn/U 7HeACFTbqAoRLdv19ppI1/cZ43EYA8WDj1oAnT7IHETOAZr2jXRBYwz+GsMCHyvM9v It5zL6iZo3RuP+wWyfoh7U1esF0wrizowPYtYNBX79Su2MxdGnR6bEO+8uioqofsF2 TnJ0F4LsHYX7SIg6SbMZWuuzT6TfKEkOZ9/RqQBbxqniJ2tY4rGxFO4iQzLbpC8M7h wTAHEUy2FfJvg== Received: from RS-EX-MBS4.realsil.com.cn ([172.29.17.104]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66L2OE1Y02860135 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 21 Jul 2026 10:24:14 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS4.realsil.com.cn (172.29.17.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.43; Tue, 21 Jul 2026 10:24:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Tue, 21 Jul 2026 10:24:12 +0800 From: javen To: , , , , , , , , , CC: , , , , Javen Xu Subject: [PATCH net-next v10 3/5] net: phy: realtek: add support for RTL8261C_CG Date: Tue, 21 Jul 2026 10:24:08 +0800 Message-ID: <20260721022410.1391-4-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260721022410.1391-1-javen_xu@realsil.com.cn> References: <20260721022410.1391-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch adds support for Realtek phy chip RTL8261C_CG. Its PHY ID is 0x001cc898. This patch introduces a distinct family of handlers (probe, get_features, config_aneg, read_status, config_intr, handle_interrupt). Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Signed-off-by: Javen Xu --- Changes in v2: - no changes, new file Changes in v3: - re-order function according to the order in phy-c45.c - add kernel-doc about return value - add MASTER_SLAVE_CFG_MASTER_PREFERRED, MASTER_SLAVE_CFG_SLAVE_PREFERRED, MASTER_SLAVE_CFG_UNKNOWN, MASTER_SLAVE_CFG_UNSUPPORTED, MASTER_SLAVE_CFG_SLAVE_PREFERRED cfg Changes in v4: - no changes Changes in v5: - remove genphy_c45_pma_setup_forced() for this is already done when calling genphy_c45_config_aneg() Changes in v6: - when PHY_INTERRUPT_DISABLE, clear IMR and ISR - if AUTONEG_DISABLE, nothing need to do in rtl8261x_config_aneg - add rtl8261x_read_status, support 1G speed Changes in v7: - remove RTL8261X_IMR and RTL8261X_ISR, duplicated definition - modify commit message - continue with default behavior when meet unknown sub_phy_id - change the internal order of rtl8261x_read_status - expand RTL8261X_INT_MASK_DEFAULT - add the handle for ADVERTISE_1000HALF in rtl8261x_config_aneg Changes in v8: - no changes Changes in v9: - get an status from genphy_c45_aneg_done() Changes in v10: - no changes. Netdev queue overflow. Resend. --- drivers/net/phy/realtek/realtek_main.c | 192 +++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realt= ek/realtek_main.c index b65d0f5fa1a0..e09bff76e1dc 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -141,6 +141,10 @@ #define RTL8211F_PHYSICAL_ADDR_WORD1 17 #define RTL8211F_PHYSICAL_ADDR_WORD2 18 =20 +#define RTL8261X_EXT_ADDR_REG 0xa436 +#define RTL8261X_EXT_DATA_REG 0xa438 +#define RTL_8261X_SUB_PHY_ID_ADDR 0x801d + #define RTL822X_VND1_SERDES_OPTION 0x697a #define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) #define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0 @@ -251,6 +255,32 @@ #define RTL_8221B_VM_CG 0x001cc84a #define RTL_8251B 0x001cc862 #define RTL_8261C 0x001cc890 +#define RTL_8261C_CG 0x001cc898 + +#define RTL8261C_CE_MODEL 0x00 +#define RTL8261X_INT_AUTONEG_ERROR BIT(0) +#define RTL8261X_INT_PAGE_RECV BIT(2) +#define RTL8261X_INT_AUTONEG_DONE BIT(3) +#define RTL8261X_INT_LINK_CHG BIT(4) +#define RTL8261X_INT_PHY_REG_ACCESS BIT(5) +#define RTL8261X_INT_PME BIT(7) +#define RTL8261X_INT_ALDPS_CHG BIT(9) +#define RTL8261X_INT_JABBER BIT(10) + +#define RTL8261X_INT_MASK_DEFAULT (RTL8261X_INT_AUTONEG_DONE | \ + RTL8261X_INT_LINK_CHG | \ + RTL8261X_INT_AUTONEG_ERROR | \ + RTL8261X_INT_JABBER) + +#define RTL8261X_INT_MASK_ALL (RTL8261X_INT_AUTONEG_ERROR | \ + RTL8261X_INT_PAGE_RECV | \ + RTL8261X_INT_AUTONEG_DONE | \ + RTL8261X_INT_LINK_CHG | \ + RTL8261X_INT_PHY_REG_ACCESS | \ + RTL8261X_INT_PME | \ + RTL8261X_INT_ALDPS_CHG | \ + RTL8261X_INT_JABBER) + =20 /* RTL8211E and RTL8211F support up to three LEDs */ #define RTL8211x_LED_COUNT 3 @@ -310,6 +340,156 @@ static int rtl821x_modify_ext_page(struct phy_device = *phydev, u16 ext_page, return phy_restore_page(phydev, oldpage, ret); } =20 +static int rtl8261x_probe(struct phy_device *phydev) +{ + int sub_phy_id, ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8261X_EXT_ADDR_REG, + RTL_8261X_SUB_PHY_ID_ADDR); + if (ret < 0) + return ret; + + ret =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8261X_EXT_DATA_REG); + if (ret < 0) + return ret; + + sub_phy_id =3D (ret >> 8) & 0xff; + + switch (sub_phy_id) { + case RTL8261C_CE_MODEL: + phydev_info(phydev, "RTL8261C detected (sub_id 0x%02x)\n", sub_phy_id); + break; + + default: + phydev_warn(phydev, "Unknown sub_id 0x%02x, default behavior\n", sub_phy= _id); + return -ENODEV; + } + + return 0; +} + +static int rtl8261x_get_features(struct phy_device *phydev) +{ + int ret; + + ret =3D genphy_c45_pma_read_abilities(phydev); + if (ret) + return ret; + /* + * Supplement Multi-Gig speeds that may not be automatically detected + * RTL8261X supports 2.5G/5G in addition to standard 10G + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->supported); + + return 0; +} + +static int rtl8261x_read_status(struct phy_device *phydev) +{ + int ret, val =3D 0; + + if (phydev->autoneg =3D=3D AUTONEG_ENABLE) { + ret =3D genphy_c45_aneg_done(phydev); + if (ret < 0) + return ret; + + if (ret) { + val =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, + RTL822X_VND2_C22_REG(MII_STAT1000)); + if (val < 0) + return val; + } + } + + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); + + ret =3D genphy_c45_read_status(phydev); + if (ret < 0) + return ret; + + return 0; +} + +static int rtl8261x_config_intr(struct phy_device *phydev) +{ + int ret; + + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED) { + ret =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INSR); + if (ret < 0) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INER, + RTL8261X_INT_MASK_DEFAULT); + if (ret < 0) + return ret; + } else { + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INER, 0); + if (ret < 0) + return ret; + + ret =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INSR); + if (ret < 0) + return ret; + } + + return 0; +} + +static irqreturn_t rtl8261x_handle_interrupt(struct phy_device *phydev) +{ + int irq_status; + + irq_status =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INSR); + if (irq_status < 0) { + phy_error(phydev); + return IRQ_NONE; + } + + if (!(irq_status & RTL8261X_INT_MASK_ALL)) + return IRQ_NONE; + + if (irq_status & (RTL8261X_INT_LINK_CHG | RTL8261X_INT_AUTONEG_DONE | + RTL8261X_INT_AUTONEG_ERROR | RTL8261X_INT_JABBER)) + phy_trigger_machine(phydev); + + return IRQ_HANDLED; +} + +static int rtl8261x_config_aneg(struct phy_device *phydev) +{ + u16 adv_1g =3D 0; + int ret; + + ret =3D genphy_c45_config_aneg(phydev); + if (ret < 0) + return ret; + + if (phydev->autoneg =3D=3D AUTONEG_DISABLE) + return 0; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->advertising)) + adv_1g =3D ADVERTISE_1000FULL; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->advertising)) + adv_1g |=3D ADVERTISE_1000HALF; + + ret =3D phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, + RTL822X_VND2_C22_REG(MII_CTRL1000), + ADVERTISE_1000FULL | ADVERTISE_1000HALF, + adv_1g); + if (ret < 0) + return ret; + if (ret > 0) + return genphy_c45_restart_aneg(phydev); + + return 0; +} + static int rtl821x_probe(struct phy_device *phydev) { struct device *dev =3D &phydev->mdio.dev; @@ -3002,6 +3182,18 @@ static struct phy_driver realtek_drvs[] =3D { .resume =3D genphy_resume, .read_mmd =3D genphy_read_mmd_unsupported, .write_mmd =3D genphy_write_mmd_unsupported, + }, { + PHY_ID_MATCH_EXACT(RTL_8261C_CG), + .name =3D "Realtek RTL8261C 10Gbps PHY", + .probe =3D rtl8261x_probe, + .get_features =3D rtl8261x_get_features, + .config_aneg =3D rtl8261x_config_aneg, + .read_status =3D rtl8261x_read_status, + .config_intr =3D rtl8261x_config_intr, + .handle_interrupt =3D rtl8261x_handle_interrupt, + .soft_reset =3D genphy_c45_pma_soft_reset, + .suspend =3D genphy_c45_pma_suspend, + .resume =3D genphy_c45_pma_resume, }, }; =20 --=20 2.43.0 From nobody Sat Jul 25 01:38:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CA43364959; Tue, 21 Jul 2026 02:25:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600760; cv=none; b=htinKqIEiJexCA4LJN8INCI5ibzjntkW//rdPLAfzrkYWownGwCUw/uip0Mu3JBYXCawLXiuP43lJWgEEE6Osh04W4A9+YoOqcEzGkd7Xk+VpruDKMa7/smRiy611hnC4pfwPCDUaKbijODipXG/VoxocQ92BySsDUA6fbJcQq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600760; c=relaxed/simple; bh=XermuJBmE8XCNU56S8kdBUdkOKcHX6zHiDuNweMQnUs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FRx0I1Fp+bku5ZzSWArqsU1tsSjD6/qs7JMLW2FpAJv5FQCzX6uctEYwo4b2s/HasslteeJdQAYqmUUHi3kuIHKRKA5LzIqA4zOv4eJ/OrKRYmlyHvEjzKK4cso/h67wRQRISK0Yj0NRc/5dYArBntbrUPZz9eLSH0hge3wXb1A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=QoUI0sSn; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="QoUI0sSn" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66L2OE1Z02860135, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1784600655; bh=UIYncYARkVJrHjJB10+L71uvag/iFRC5OrzQiXEY6nk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=QoUI0sSnNu9nDOQm4bl/bnnBjaPJn+7JqG18cPELKDi/XXEbcFre9h0vR53mMt12b o7auPHgSy2K4jv7o6nsqZzAhMSTtCuBrQXYVqC0icqxwCgYxJDxYHUn5nXs4visj8Y N0QJ+XUXFScBFsA9YwnX0fZl1iSLjMsZBoL1a0nuKpnWwYs2KxZPnZMZl+GKtPVeSR WDaT1Vfl11BggItNawzr7WiWjguau5uefum3BvsvNVfCddt3WYU0p5uV29hNXZeR16 Z50eE9Ozx/QJPYk2bnki52jw7Ed3apm72DJQyik/7E2XFmOXzFzZy0lkfWiUxu8ERw VAvqpaX6qv1dg== Received: from RS-EX-MBS4.realsil.com.cn ([172.29.17.104]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66L2OE1Z02860135 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 21 Jul 2026 10:24:15 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS4.realsil.com.cn (172.29.17.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.43; Tue, 21 Jul 2026 10:24:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Tue, 21 Jul 2026 10:24:13 +0800 From: javen To: , , , , , , , , , CC: , , , , Javen Xu Subject: [PATCH net-next v10 4/5] net: phy: realtek: load firmware for RTL8261C_CG Date: Tue, 21 Jul 2026 10:24:09 +0800 Message-ID: <20260721022410.1391-5-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260721022410.1391-1-javen_xu@realsil.com.cn> References: <20260721022410.1391-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch adds support for loading firmware. Download some parameters for RTL8261C_CG. Reviewed-by: Andrew Lunn Signed-off-by: Javen Xu --- Changes in v2: - remove __pack, struct rtl8261x_fw_header and rtl8261x_fw_entry will not = pad - reverse xmas tree for some definition - add explanation on rtl_phy_write_mmd_bits() Changes in v3: - add struct rtl8261x_priv Changes in v4: - add struct device *dev Changes in v5: - no changes Changes in v6: - replace rtl_phy_write_mmd_bits with phy_modify_mmd, keep mdio lock - check msb and lsb at the beginning of rtl8261x_fw_execute_entry() - add comments on rtl8261x_config_init() Changes in v7: - no changes Changes in v8: - remove some phydev_err message in rtl8261x_fw_execute_entry() and rtl8261x_config_init() Changes in v9: - no changes Changes in v10: - no changes. Netdev queue overflow. Resend. --- drivers/net/phy/realtek/realtek_main.c | 214 +++++++++++++++++++++++++ 1 file changed, 214 insertions(+) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realt= ek/realtek_main.c index e09bff76e1dc..ba218559f39c 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -8,7 +8,9 @@ * Copyright (c) 2004 Freescale Semiconductor, Inc. */ #include +#include #include +#include #include #include #include @@ -281,6 +283,43 @@ RTL8261X_INT_ALDPS_CHG | \ RTL8261X_INT_JABBER) =20 +#define FW_MAIN_MAGIC 0x52544C38 +#define FW_SUB_MAGIC_8261C 0x32363143 +#define RTL8261X_POLL_TIMEOUT_MS 100 +#define RTL8261X_MAX_MMD_DEV 31 + +#define RTL8261C_CE_FW_NAME "rtl_nic/rtl8261c.bin" +MODULE_FIRMWARE(RTL8261C_CE_FW_NAME); + +enum rtl8261x_fw_op { + OP_WRITE =3D 0x00, /* Write */ + OP_POLL =3D 0x02, /* Polling */ +}; + +struct rtl8261x_fw_header { + __le32 main_magic; /* Main magic number */ + __le32 sub_magic; /* Sub magic number */ + __le16 version_major; /* Major version */ + __le16 version_minor; /* Minor version */ + __le16 num_entries; /* Number of entries */ + __le16 reserved; /* Reserved */ + __le32 crc32; /* CRC32 checksum */ +}; + +struct rtl8261x_fw_entry { + __u8 type; /* Operation type (OP_*) */ + __u8 dev; /* MMD device */ + __le16 addr; /* Register address */ + __u8 msb; /* MSB bit position */ + __u8 lsb; /* LSB bit position */ + __le16 value; /* Value to write/compare */ + __le16 timeout_ms; /* Poll timeout in milliseconds */ + __u8 poll_set; /* Poll until equal (1) or not equal (0) */ + __u8 reserved; /* Reserved */ +}; + +#define FW_HEADER_SIZE sizeof(struct rtl8261x_fw_header) +#define FW_ENTRY_SIZE sizeof(struct rtl8261x_fw_entry) =20 /* RTL8211E and RTL8211F support up to three LEDs */ #define RTL8211x_LED_COUNT 3 @@ -300,6 +339,11 @@ struct rtl821x_priv { u16 iner; }; =20 +struct rtl8261x_priv { + const char *fw_name; + bool fw_loaded; +}; + static int rtl821x_read_page(struct phy_device *phydev) { return __phy_read(phydev, RTL821x_PAGE_SELECT); @@ -342,8 +386,16 @@ static int rtl821x_modify_ext_page(struct phy_device *= phydev, u16 ext_page, =20 static int rtl8261x_probe(struct phy_device *phydev) { + struct device *dev =3D &phydev->mdio.dev; + struct rtl8261x_priv *priv; int sub_phy_id, ret; =20 + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv =3D priv; + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8261X_EXT_ADDR_REG, RTL_8261X_SUB_PHY_ID_ADDR); if (ret < 0) @@ -357,6 +409,7 @@ static int rtl8261x_probe(struct phy_device *phydev) =20 switch (sub_phy_id) { case RTL8261C_CE_MODEL: + priv->fw_name =3D RTL8261C_CE_FW_NAME; phydev_info(phydev, "RTL8261C detected (sub_id 0x%02x)\n", sub_phy_id); break; =20 @@ -413,6 +466,152 @@ static int rtl8261x_read_status(struct phy_device *ph= ydev) return 0; } =20 +static int rtl8261x_verify_firmware(struct phy_device *phydev, const struc= t firmware *fw) +{ + const struct rtl8261x_fw_header *hdr; + u32 main_magic, sub_magic; + u32 calc_crc, file_crc; + size_t data_len; + u16 num_entries; + + if (fw->size < FW_HEADER_SIZE) { + phydev_err(phydev, "Firmware too small: %zu bytes\n", fw->size); + return -EINVAL; + } + + hdr =3D (const struct rtl8261x_fw_header *)fw->data; + + main_magic =3D le32_to_cpu(hdr->main_magic); + if (main_magic !=3D FW_MAIN_MAGIC) { + phydev_err(phydev, "Invalid firmware magic: 0x%08x\n", main_magic); + return -EINVAL; + } + + sub_magic =3D le32_to_cpu(hdr->sub_magic); + if (sub_magic !=3D FW_SUB_MAGIC_8261C) { + phydev_err(phydev, "Invalid sub magic: 0x%08x\n", sub_magic); + return -EINVAL; + } + + num_entries =3D le16_to_cpu(hdr->num_entries); + data_len =3D num_entries * FW_ENTRY_SIZE; + + if (fw->size !=3D sizeof(*hdr) + data_len) { + phydev_err(phydev, "Firmware size mismatch\n"); + return -EINVAL; + } + + calc_crc =3D crc32(~0, fw->data + FW_HEADER_SIZE, data_len) ^ ~0; + file_crc =3D le32_to_cpu(hdr->crc32); + + if (calc_crc !=3D file_crc) { + phydev_err(phydev, "CRC32 mismatch: calculated=3D0x%08x file=3D0x%08x\n", + calc_crc, file_crc); + return -EINVAL; + } + + return 0; +} + +static int rtl8261x_fw_execute_entry(struct phy_device *phydev, + const struct rtl8261x_fw_entry *entry) +{ + u16 addr, value, timeout_ms; + u8 dev, msb, lsb, poll_set; + u32 bits, expect_val; + int ret, val; + + dev =3D entry->dev; + addr =3D le16_to_cpu(entry->addr); + msb =3D entry->msb; + lsb =3D entry->lsb; + value =3D le16_to_cpu(entry->value); + timeout_ms =3D le16_to_cpu(entry->timeout_ms); + poll_set =3D entry->poll_set; + + if (timeout_ms =3D=3D 0) + timeout_ms =3D RTL8261X_POLL_TIMEOUT_MS; + + if (dev > RTL8261X_MAX_MMD_DEV) { + phydev_err(phydev, "invalid firmware MMD device: dev=3D%u\n", dev); + return -EINVAL; + } + + if (msb > 15 || lsb > msb) { + phydev_err(phydev, "invalid firmware bits: msb=3D%u, lsb=3D%u\n", msb, l= sb); + return -EINVAL; + } + + switch (entry->type) { + case OP_WRITE: + ret =3D phy_modify_mmd(phydev, dev, addr, + GENMASK(msb, lsb), (value << lsb) & GENMASK(msb, lsb)); + if (ret) + return ret; + break; + + case OP_POLL: + bits =3D GENMASK(msb, lsb); + expect_val =3D (value << lsb) & bits; + + if (poll_set) + ret =3D phy_read_mmd_poll_timeout(phydev, dev, addr, val, + (val & bits) =3D=3D expect_val, + 1000, timeout_ms * 1000, false); + else + ret =3D phy_read_mmd_poll_timeout(phydev, dev, addr, val, + (val & bits) !=3D expect_val, + 1000, timeout_ms * 1000, false); + if (ret) + return ret; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int rtl8261x_fw_load(struct phy_device *phydev) +{ + struct rtl8261x_priv *priv =3D phydev->priv; + const struct rtl8261x_fw_entry *entry; + const struct rtl8261x_fw_header *hdr; + const struct firmware *fw; + int ret, i; + + if (!priv->fw_name) + return 0; + + ret =3D request_firmware(&fw, priv->fw_name, &phydev->mdio.dev); + if (ret) { + phydev_err(phydev, "Failed to load firmware %s: %d\n", priv->fw_name, re= t); + return ret; + } + + ret =3D rtl8261x_verify_firmware(phydev, fw); + if (ret) + goto release_fw; + + hdr =3D (const struct rtl8261x_fw_header *)fw->data; + + entry =3D (const struct rtl8261x_fw_entry *)(fw->data + FW_HEADER_SIZE); + for (i =3D 0; i < le16_to_cpu(hdr->num_entries); i++, entry++) { + ret =3D rtl8261x_fw_execute_entry(phydev, entry); + if (ret) { + phydev_err(phydev, "Entry %d failed: %d\n", i, ret); + goto release_fw; + } + } + + priv->fw_loaded =3D true; + +release_fw: + release_firmware(fw); + return ret; +} + static int rtl8261x_config_intr(struct phy_device *phydev) { int ret; @@ -490,6 +689,20 @@ static int rtl8261x_config_aneg(struct phy_device *phy= dev) return 0; } =20 +static int rtl8261x_config_init(struct phy_device *phydev) +{ + struct rtl8261x_priv *priv =3D phydev->priv; + + /* The firmware parameters are preserved across IEEE soft resets and + * suspend/resume cycles. Reloading is only necessary after a power + * cycle or hard reset. + */ + if (priv->fw_name && !priv->fw_loaded) + return rtl8261x_fw_load(phydev); + + return 0; +} + static int rtl821x_probe(struct phy_device *phydev) { struct device *dev =3D &phydev->mdio.dev; @@ -3186,6 +3399,7 @@ static struct phy_driver realtek_drvs[] =3D { PHY_ID_MATCH_EXACT(RTL_8261C_CG), .name =3D "Realtek RTL8261C 10Gbps PHY", .probe =3D rtl8261x_probe, + .config_init =3D rtl8261x_config_init, .get_features =3D rtl8261x_get_features, .config_aneg =3D rtl8261x_config_aneg, .read_status =3D rtl8261x_read_status, --=20 2.43.0 From nobody Sat Jul 25 01:38:04 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EAEEC3FD960; Tue, 21 Jul 2026 02:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600760; cv=none; b=qV2v0NIl5gTtGNxejfTTH83cguZkeFKhQI2ooP+ZCdxBj1dHLs0yQ2WRTb8H/bOJZF634YENoIFnQTzf/1DIZSostXwUprTFp/x+2tTdzYs1cRebziNJbikMz2L2rRjKy8FOKHbqgblziBzYKcPIhTo/lKiIIKMacTzKnq+qlBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784600760; c=relaxed/simple; bh=y5WrvcsuUblRyUtZbHEmnxHmOraXMzZOGPaaVHDfYRw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PbM6MJNZj/cQq9NLHU8y6RyrSmPztgtIs8EXHFPRM4dyK6gttWTt81RDrckRjjmYqsG4fBKTQnw1/5G8V6XwH9eW5cRvfbyJFmovva+n2pqvQxyEgfK5Fxu64yAra3XG4s/p7OhlZVvJIRKf4pFmC0Ym7yhcGjB7vokwyryP1F8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=Ecid64a0; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="Ecid64a0" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 66L2OF1W02860135, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1784600655; bh=v3FB5AxMqgd8L9yl3rgnxZmaXywV19D/v9zzcnCXYLU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=Ecid64a0tgRQf+KT2jQljSmV5nLjrfpUSoEpI/dp5Gn9JGkS1ev72TILtnZS1QffD F3m7yl/p8DWOK5CjpzJab41vfnXiNyu/P1mMqJO+0DhetX7ySTaLgrNr3cCAU9fviz hYRe48Hz+k+SyKCD0JyQugL1jDANDYEpfAVT2OG+v5LM7Td9LRn8WhervIutYTG9Lt N1Gtbj/Oy/dRdGkjebivjukc/UqP8RTkfXcPmaRb+RKNG9kS7vxr7TOGgGjIgu3NTf c1yI1Q51LTHQRhfi8PkXzS3dm4MJUSTxxhhREFNZ0UBfQqTOWRNloGBDPyNamJUGQ1 INFnvqRvviotA== Received: from RS-EX-MBS4.realsil.com.cn ([172.29.17.104]) by rtits2.realtek.com.tw (8.15.2/3.29/5.94) with ESMTPS id 66L2OF1W02860135 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 21 Jul 2026 10:24:15 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS4.realsil.com.cn (172.29.17.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.43; Tue, 21 Jul 2026 10:24:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Tue, 21 Jul 2026 10:24:13 +0800 From: javen To: , , , , , , , , , CC: , , , , Javen Xu Subject: [PATCH net-next v10 5/5] net: phy: realtek: add support for RTL8261D Date: Tue, 21 Jul 2026 10:24:10 +0800 Message-ID: <20260721022410.1391-6-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260721022410.1391-1-javen_xu@realsil.com.cn> References: <20260721022410.1391-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu RTL8261D is also 10g phy. It's sub_phy_id is 0x81. And it does not need any firmware. Signed-off-by: Javen Xu --- Changes in v10: - no changes. New file. --- drivers/net/phy/realtek/realtek_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realt= ek/realtek_main.c index ba218559f39c..1c0b9c40a81e 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -260,6 +260,7 @@ #define RTL_8261C_CG 0x001cc898 =20 #define RTL8261C_CE_MODEL 0x00 +#define RTL8261D_MODEL 0x81 #define RTL8261X_INT_AUTONEG_ERROR BIT(0) #define RTL8261X_INT_PAGE_RECV BIT(2) #define RTL8261X_INT_AUTONEG_DONE BIT(3) @@ -413,6 +414,10 @@ static int rtl8261x_probe(struct phy_device *phydev) phydev_info(phydev, "RTL8261C detected (sub_id 0x%02x)\n", sub_phy_id); break; =20 + case RTL8261D_MODEL: + phydev_info(phydev, "RTL8261D detected (sub_id 0x%02x)\n", sub_phy_id); + break; + default: phydev_warn(phydev, "Unknown sub_id 0x%02x, default behavior\n", sub_phy= _id); return -ENODEV; @@ -3397,7 +3402,7 @@ static struct phy_driver realtek_drvs[] =3D { .write_mmd =3D genphy_write_mmd_unsupported, }, { PHY_ID_MATCH_EXACT(RTL_8261C_CG), - .name =3D "Realtek RTL8261C 10Gbps PHY", + .name =3D "Realtek RTL8261 10Gbps PHY", .probe =3D rtl8261x_probe, .config_init =3D rtl8261x_config_init, .get_features =3D rtl8261x_get_features, --=20 2.43.0