AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/09/10 08:21 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch adds support for the Motorcomm YT8824 quad-port 2.5Gbps Ethernet PHY chip and a generic C45 test mode helper called only by this driver. This requires specific physical PHY hardware and Device Tree descriptions not present or emulated in standard virtualized fuzzing environments (QEMU/GCE), making the code structurally unreachable.",
  "WorthFuzzing": false
}

1/1 2026/09/10 08:21 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 973593aab6b7bc7f1d9584a776f6166eff4b3e65\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Sep 10 08:21:23 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml\nnew file mode 100644\nindex 0000000000000..9907a4a7e63e8\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml\n@@ -0,0 +1,63 @@\n+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/net/motorcomm,yt8824.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: MotorComm YT8824 Ethernet PHY\n+\n+maintainers:\n+  - Kyle Switch \u003ckyle.switch@motor-comm.com\u003e\n+\n+description: |\n+  Motorcomm YT8824 Ethernet PHY is a PHY package of 4 PHYs.\n+\n+$ref: ethernet-phy-package.yaml#\n+\n+properties:\n+  compatible:\n+    enum:\n+      - ethernet-phy-id4f51.e8b8\n+\n+  motorcomm,interface-mode:\n+    description: |\n+      PHY package interface mode.\n+    $ref: /schemas/types.yaml#/definitions/string\n+    enum:\n+      - internal\n+      - usxgmii\n+    default: internal\n+\n+unevaluatedProperties: false\n+\n+examples:\n+  - |\n+    mdio {\n+        #address-cells = \u003c1\u003e;\n+        #size-cells = \u003c0\u003e;\n+\n+        ethernet-phy-package@0 {\n+            #address-cells = \u003c1\u003e;\n+            #size-cells = \u003c0\u003e;\n+            compatible = \"ethernet-phy-id4f51.e8b8\";\n+            reg = \u003c9\u003e;\n+\n+            motorcomm,interface-mode = \"usxgmii\";\n+\n+            ethernet-phy@4 {\n+                reg = \u003c4\u003e;\n+            };\n+\n+            ethernet-phy@5 {\n+                reg = \u003c5\u003e;\n+            };\n+\n+            ethernet-phy@6 {\n+                reg = \u003c6\u003e;\n+            };\n+\n+            ethernet-phy@7 {\n+                reg = \u003c7\u003e;\n+            };\n+        };\n+    };\ndiff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig\nindex b4ef927fd4a67..1dd80e06e2370 100644\n--- a/drivers/net/phy/Kconfig\n+++ b/drivers/net/phy/Kconfig\n@@ -361,9 +361,10 @@ config MICROSEMI_PHY\n \n config MOTORCOMM_PHY\n \ttristate \"Motorcomm PHYs\"\n+\tselect PHY_PACKAGE\n \thelp\n \t  Enables support for Motorcomm network PHYs.\n-\t  Currently supports YT85xx Gigabit Ethernet PHYs.\n+\t  Currently supports YT85xx Gigabit Ethernet PHYs and YT8824 4 * 2.5G PHY.\n \n config NATIONAL_PHY\n \ttristate \"National Semiconductor PHYs\"\ndiff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c\nindex 90a4f86f2758b..f41186b5b737f 100644\n--- a/drivers/net/phy/motorcomm.c\n+++ b/drivers/net/phy/motorcomm.c\n@@ -1,24 +1,29 @@\n // SPDX-License-Identifier: GPL-2.0+\n /*\n- * Motorcomm 8511/8521/8522/8531/8531S/8821 PHY driver.\n+ * Motorcomm 8511/8521/8522/8531/8531S/8821/8824 PHY driver.\n  *\n  * Author: Peter Geis \u003cpgwipeout@gmail.com\u003e\n  * Author: Frank \u003cFrank.Sae@motor-comm.com\u003e\n+ * Author: Kyle \u003ckyle.switch@motor-comm.com\u003e\n  */\n \n #include \u003clinux/clk.h\u003e\n #include \u003clinux/etherdevice.h\u003e\n #include \u003clinux/kernel.h\u003e\n #include \u003clinux/module.h\u003e\n+#include \u003clinux/of.h\u003e\n #include \u003clinux/phy.h\u003e\n #include \u003clinux/property.h\u003e\n \n+#include \"phylib.h\"\n+\n #define PHY_ID_YT8511\t\t0x0000010a\n #define PHY_ID_YT8521\t\t0x0000011a\n #define PHY_ID_YT8522\t\t0x4f51e928\n #define PHY_ID_YT8531\t\t0x4f51e91b\n #define PHY_ID_YT8531S\t\t0x4f51e91a\n #define PHY_ID_YT8821\t\t0x4f51ea19\n+#define PHY_ID_YT8824\t\t0x4f51e8b8\n /* YT8521/YT8531S/YT8821 Register Overview\n  *\tUTP Register space\t|\tFIBER Register space\n  *  ------------------------------------------------------------\n@@ -30,6 +35,18 @@\n  *  ------------------------------------------------------------\n  */\n \n+/* YT8824 Register Overview\n+ *\tUTP Register space\t|\tUSXGMII Register space\n+ *  ------------------------------------------------------------\n+ * |\tUTP MII\t\t\t|\tUSXGMII MII\t        |\n+ * |\tUTP MMD\t\t\t|\t\t\t\t|\n+ * |\tUTP Extended\t\t|\tUSXGMII Extended\t|\n+ * |\tUTP Top Extended\t|\tUSXGMII Top Extended\t|\n+ *  ------------------------------------------------------------\n+ * |\t\t\tCommon Top Extended\t\t\t|\n+ *  ------------------------------------------------------------\n+ */\n+\n /* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */\n \n /* Specific Function Control Register */\n@@ -381,6 +398,15 @@\n #define YT8821_CHIP_MODE_AUTO_BX2500_SGMII\t0\n #define YT8821_CHIP_MODE_FORCE_BX2500\t\t1\n \n+#define YT8824_RSSR_SPACE_MASK\t\t\tBIT(0)\n+#define YT8824_RSSR_USXGMII_SPACE\t\t(0x1)\n+#define YT8824_RSSR_UTP_SPACE\t\t\t(0x0)\n+#define YT8824_UTP_TEMPLATE_TEST_MODE1\t\t0x1\n+#define YT8824_UTP_TEMPLATE_TEST_NORMAL\t\t0x0\n+#define YT8824_SDS_CFG_MIN_PRE_MASK\t\tGENMASK(3, 0)\n+#define YT8824_SDS_EN_FILL_PRE\t\t\tBIT(13)\n+#define YT8824_SDS_TX_PRE_PADDING\t\t(0x7)\n+\n struct yt8521_priv {\n \t/* combo_advertising is used for case of YT8521 in combo mode,\n \t * this means that yt8521 may work in utp or fiber mode which depends\n@@ -399,6 +425,12 @@ struct yt8521_priv {\n \tu8 reg_page;\n };\n \n+struct yt8824_shared_priv {\n+\tunsigned int interface_mode;\n+\t/* shared_lock used to UTPs operation isolation during swap reg space */\n+\tstruct mutex shared_lock;\n+};\n+\n /**\n  * ytphy_read_ext() - read a PHY's extended register\n  * @phydev: a pointer to a \u0026struct phy_device\n@@ -437,6 +469,70 @@ static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum)\n \treturn ret;\n }\n \n+/**\n+ * ytphy_read_top_ext() - read a PHY's top extended register for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @regnum: register number to read\n+ *\n+ * Returns: the value of regnum reg or negative error code\n+ */\n+static int ytphy_read_top_ext(struct phy_device *phydev, u16 regnum)\n+{\n+\tint ret;\n+\n+\tlockdep_assert_held(\u0026phydev-\u003emdio.bus-\u003emdio_lock);\n+\tret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn __phy_package_read(phydev, 0, YTPHY_PAGE_DATA);\n+}\n+\n+/**\n+ * ytphy_write_top_ext() - write a PHY's top extended register for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @regnum: register number to write\n+ * @val: register val to write\n+ *\n+ * Returns: 0 or negative error code\n+ */\n+static int ytphy_write_top_ext(struct phy_device *phydev, u16 regnum,\n+\t\t\t       u16 val)\n+{\n+\tint ret;\n+\n+\tlockdep_assert_held(\u0026phydev-\u003emdio.bus-\u003emdio_lock);\n+\tret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn __phy_package_write(phydev, 0, YTPHY_PAGE_DATA, val);\n+}\n+\n+/**\n+ * phy8824_page_write_with_lock() - write page for YT8824\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @page: reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE).\n+ *\n+ * Returns: 0 or negative error code\n+ */\n+static int phy8824_page_write_with_lock(struct phy_device *phydev, int page)\n+{\n+\tint ret;\n+\n+\tphy_lock_mdio_bus(phydev);\n+\tret = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tret \u0026= ~YT8824_RSSR_SPACE_MASK;\n+\tret |= (page \u0026 YT8824_RSSR_SPACE_MASK);\n+\tret = ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, ret);\n+\n+err:\n+\tphy_unlock_mdio_bus(phydev);\n+\treturn ret;\n+}\n+\n /**\n  * ytphy_write_ext() - write a PHY's extended register\n  * @phydev: a pointer to a \u0026struct phy_device\n@@ -626,11 +722,1056 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)\n \t\tret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,\n \t\t\t\t   YTPHY_IER_WOL, 0);\n \t\tif (ret \u003c 0)\n-\t\t\tgoto err_restore_page;\n+\t\t\tgoto err_restore_page;\n+\t}\n+\n+err_restore_page:\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_read_page() - read PHY8824 reg page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: current reg space of yt8824 (YT8824_RSSR_USXGMII_SPACE/\n+ * YT8824_RSSR_UTP_SPACE) or negative errno code\n+ */\n+static int yt8824_read_page(struct phy_device *phydev)\n+{\n+\tint old_page;\n+\n+\told_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (old_page \u003c 0)\n+\t\treturn old_page;\n+\n+\treturn old_page \u0026 YT8824_RSSR_SPACE_MASK;\n+};\n+\n+/**\n+ * yt8824_write_page() - write reg page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @page: Reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE) to write.\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_write_page(struct phy_device *phydev, int page)\n+{\n+\tint old_page;\n+\tu16 data;\n+\n+\told_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);\n+\tif (old_page \u003c 0)\n+\t\treturn old_page;\n+\tdata = old_page \u0026 (~YT8824_RSSR_SPACE_MASK);\n+\tdata |= page;\n+\n+\treturn ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, data);\n+};\n+\n+/**\n+ * yt8824_utp_invalid_test_mode_paged() - config YT8824 to invalid test mode.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n+}\n+\n+/**\n+ * yt8824_sds_isolate_paged() - enable YT8824 serdes isolate.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_sds_isolate_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint ret = 0;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* enable sds isolate */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, BMCR_ISOLATE);\n+\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_utp_softreset_paged() - config YT8824 UTP softreset.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_softreset_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET, BMCR_RESET);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* wait until softreset done. */\n+\treturn phy_read_poll_timeout(phydev, MII_BMCR, val,\n+\t\t\t\t     !(val \u0026 BMCR_RESET),\n+\t\t\t\t     50000, 600000, true);\n+}\n+\n+/**\n+ * yt8824_utp_normal_test_mode_paged() - config YT8824 to normal test mode.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+}\n+\n+/**\n+ * yt8824_sds_isolate_and_softreset_paged() - disable YT8824 serdes isolate\n+ * and sds softreset.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_sds_isolate_and_softreset_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint val = 0;\n+\tint ret = -1;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* sds softreset and disable isolate */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ISOLATE,\n+\t\t\t   BMCR_RESET \u0026 ~BMCR_ISOLATE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* poll while still holding the lock */\n+\tret = read_poll_timeout(__phy_read, val, (val \u003c 0) ||\n+\t\t\t\t!(val \u0026 BMCR_RESET),\n+\t\t\t\t50000, 600000, true, phydev, MII_BMCR);\n+\tif (val \u003c 0)\n+\t\tret = val;\n+\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_restore_working_status() - called to do store working status\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ * @ret: operation's return code\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_restore_working_status(struct phy_device *phydev, int ret)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint r;\n+\n+\t/* configure normal test mode */\n+\tr = yt8824_utp_normal_test_mode_paged(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tif (priv-\u003einterface_mode != PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* sds soft reset and disable isolation */\n+\t\tr = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\t\tret = r;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_soft_reset() - called to do PHY software reset\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_soft_reset(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp soft reset */\n+\t\tret = yt8824_utp_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+retry:\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_extern_config_utp_init_paged() - config external phy8824 utp init\n+ * @phydev: target phy_device struct\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val = 0;\n+\tint r;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* power down */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* pll calibration */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimization utp */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* enable nibble */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* idle err detect enable */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 2.5G long cable performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0372, 0x5038);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized fast retrain */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 2.5G template tone */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 2.5G template */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 1000M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0336, 0xab0a);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 100M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 100M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x030b, 0xaa1d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* 10M template amplitude */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized 10M cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0466, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimize utp 1000M performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized EMC CS */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\t/* optimized EMC RE */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\n+\tret = genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\t/* reset */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\tret = phy_read_poll_timeout(phydev, MII_BMCR, val,\n+\t\t\t\t    !(val \u0026 BMCR_RESET),\n+\t\t\t\t    50000, 600000, true);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+\tret = genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\treturn 0;\n+\n+err_restore:\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+\n+err_restore_normal:\n+\tr = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_extern_config_sds_init_paged() - config external phy8824 sds init\n+ * @phydev: target phy_device struct\n+ *\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_extern_config_sds_init_paged(struct phy_device *phydev)\n+{\n+\tint old_page = YT8824_RSSR_UTP_SPACE;\n+\tint val_1, val_2, val_3, tmp;\n+\tint ret = -1;\n+\tint val;\n+\n+\told_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);\n+\tif (old_page \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* read efuse */\n+\tret = ytphy_read_top_ext(phydev, 0xa13e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_1 = ret;\n+\n+\tret = ytphy_read_top_ext(phydev, 0xa13f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_2 = ret;\n+\n+\tret = ytphy_read_top_ext(phydev, 0xa140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\telse\n+\t\tval_3 = ret;\n+\n+\t/* Serdes optimization */\n+\tret = ytphy_write_ext(phydev, 0x04be, 0x000d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x049f, 0x7ded);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04a9, 0x009f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* analog CDR */\n+\tret = ytphy_write_ext(phydev, 0x0406, 0x0800);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized VCO */\n+\tret = ytphy_write_ext(phydev, 0x0438, 0x9024);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0439, 0x00c0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized PLL lock */\n+\tret = ytphy_read_ext(phydev, 0x0429);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(13) | BIT(12));\n+\ttmp = (val_1 \u0026 (BIT(7) | BIT(6))) \u003e\u003e 6;\n+\tret |= (tmp \u003c\u003c 12);\n+\tret = ytphy_write_ext(phydev, 0x0429, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x0441);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(1) | BIT(0));\n+\ttmp = (val_1 \u0026 (BIT(5) | BIT(4))) \u003e\u003e 4;\n+\tret |= tmp;\n+\tret = ytphy_write_ext(phydev, 0x0441, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x042b);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(13) | BIT(12));\n+\ttmp = (val_3 \u0026 (BIT(1) | BIT(0)));\n+\tret |= (tmp \u003c\u003c 12);\n+\tret = ytphy_write_ext(phydev, 0x042b, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x043a, 0x1006);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x042a, 0xf070);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* cable length threshold */\n+\tret = ytphy_write_ext(phydev, 0x0491, 0x007f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes training threshold */\n+\tret = ytphy_write_ext(phydev, 0x0454, 0x0f14);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0497, 0x0a44);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* digital eye diagram of SerDes */\n+\tret = ytphy_write_ext(phydev, 0x04cd, 0x0000);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes LDO */\n+\tret = ytphy_read_ext(phydev, 0x04b5);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(6) | BIT(5) | BIT(4));\n+\ttmp = (val_2 \u0026 (BIT(4) | BIT(3) | BIT(2))) \u003e\u003e 2;\n+\tret |= (tmp \u003c\u003c 4);\n+\tret = ytphy_write_ext(phydev, 0x04b5, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_read_ext(phydev, 0x04b4);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret \u0026= ~(BIT(10) | BIT(9) | BIT(8));\n+\ttmp = (val_2 \u0026 (BIT(7) | BIT(6) | BIT(5))) \u003e\u003e 5;\n+\tret |= (tmp \u003c\u003c 8);\n+\tret = ytphy_write_ext(phydev, 0x04b4, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized Serdes RX */\n+\tret = ytphy_write_ext(phydev, 0x04af, 0x45e3);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x048a, 0x0fff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0408, 0x7c00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04d6, 0x007f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x044f, 0xff08);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* optimized Serdes TX */\n+\tret = ytphy_write_ext(phydev, 0x048e, 0x7d00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x000d, 0x0606);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* Serdes manual config */\n+\tret = ytphy_write_ext(phydev, 0x04b0, 0x0804);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04b1, 0x7074);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x04af, 0x45e7);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* restart calibration */\n+\tret = ytphy_write_ext(phydev, 0x0003, 0x5603);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7fff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x2000, 0x0040);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\tret = ytphy_write_ext(phydev, 0x2000, 0x0000);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\n+\t/* TX preamble padded to 8; RX IPG always \u003e 8 */\n+\tret = __phy_read(phydev, MII_RESV1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\tret \u0026= ~YT8824_SDS_CFG_MIN_PRE_MASK;\n+\tret |= YT8824_SDS_TX_PRE_PADDING;\n+\tret |= YT8824_SDS_EN_FILL_PRE;\n+\tret = __phy_write(phydev, MII_RESV1, ret);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\t/* reset serdes */\n+\tret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t   BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_page;\n+\t/* poll while still holding the lock; __phy_read takes no lock */\n+\tret = read_poll_timeout(__phy_read, val, (val \u003c 0) ||\n+\t\t\t\t!(val \u0026 BMCR_RESET),\n+\t\t\t\t50000, 600000, true, phydev, MII_BMCR);\n+\tif (val \u003c 0)\n+\t\tret = val;\n+err_restore_page:\n+\t/* restore page, release the lock */\n+\treturn phy_restore_page(phydev, old_page, ret);\n+}\n+\n+/**\n+ * yt8824_internal_config_init_paged() - config internal phy8824 init\n+ * @phydev: target phy_device struct\n+ *\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_internal_config_init_paged(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\tint val = 0;\n+\tint r = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\t/* power down */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x83);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 2.5G tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 1000 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 1000 performance */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 100 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 100 cable length threshold */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 10 tempate */\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* 10 tempate MAU*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* EMC CS, Inconsistent with external phy */\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\t/* EMC RE*/\n+\tret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore;\n+\tret = genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n+\tif (ret)\n+\t\tgoto err_restore_normal;\n+\t/* reset */\n+\tret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,\n+\t\t\t BMCR_RESET | BMCR_ANENABLE);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\tret = phy_read_poll_timeout(phydev, MII_BMCR, val,\n+\t\t\t\t    !(val \u0026 BMCR_RESET),\n+\t\t\t\t    50000, 600000, true);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+\tret = genphy_c45_template_testmode\n+\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+\tif (ret \u003c 0)\n+\t\tgoto err_restore_normal;\n+\n+err_restore:\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+\n+err_restore_normal:\n+\tr = genphy_c45_template_testmode(phydev,\n+\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_NORMAL);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tr = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_config_init() - phy initializatioin\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_config_init(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\tret = yt8824_internal_config_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err;\n+\t} else {\n+\t\tret = yt8824_extern_config_sds_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err;\n+\t\tret = yt8824_extern_config_utp_init_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto err;\n \t}\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_soft_reset(phydev);\n \n-err_restore_page:\n-\treturn phy_restore_page(phydev, old_page, ret);\n+\tphydev_dbg(phydev, \"%s done, phy addr: %d\\n\",\n+\t\t   __func__, phydev-\u003emdio.addr);\n+\treturn ret;\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n }\n \n static int yt8531_set_wol(struct phy_device *phydev,\n@@ -3104,6 +4245,429 @@ static int yt8821_resume(struct phy_device *phydev)\n \treturn yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);\n }\n \n+/**\n+ * yt8824_get_features - read mmd register to get 2.5G capability\n+ * @phydev: target phy_device struct\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_get_features(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tret = yt8821_get_features(phydev);\n+\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_aneg_done()  - check negotiation state.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: link status or negative errno code\n+ */\n+static int yt8824_aneg_done(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint link = 0;\n+\tint ret = 0;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\tlink = !!(ret \u0026 YTPHY_SSR_LINK);\n+\n+\tphydev_dbg(phydev, \"%s, phy addr: %d, link_utp: %d\\n\",\n+\t\t   __func__, phydev-\u003emdio.addr, link);\n+\treturn link;\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_read_status_paged() -  determines the speed and duplex of one page\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_read_status_paged(struct phy_device *phydev)\n+{\n+\tint link = 0;\n+\tint ret = 0;\n+\tint val = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tret = genphy_read_status(phydev);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tif (phydev-\u003eautoneg_complete) {\n+\t\tret = genphy_c45_read_lpa(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\tval = ret;\n+\n+\tlink = val \u0026 YTPHY_SSR_LINK;\n+\tif (link)\n+\t\tyt8821_adjust_status(phydev, val);\n+\n+\tif (link) {\n+\t\tif (phydev-\u003elink == 0)\n+\t\t\tphydev_dbg(phydev,\n+\t\t\t\t   \"%s, phy addr: %d, link up\\n\",\n+\t\t\t\t   __func__, phydev-\u003emdio.addr);\n+\t\tphydev-\u003elink = 1;\n+\t} else {\n+\t\tif (phydev-\u003elink == 1)\n+\t\t\tphydev_dbg(phydev,\n+\t\t\t\t   \"%s, phy addr: %d, link down\\n\",\n+\t\t\t\t   __func__, phydev-\u003emdio.addr);\n+\t\tphydev-\u003elink = 0;\n+\t}\n+\tphy_resolve_aneg_pause(phydev);\n+\treturn 0;\n+}\n+\n+/**\n+ * yt8824_read_status() -  determines the negotiated speed and duplex\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_read_status(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_read_status_paged(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_utp_power_on(): utp power on.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_power_on(struct phy_device *phydev)\n+{\n+\tint ret = 0;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0x0);\n+}\n+\n+/**\n+ * yt8824_utp_power_down(): utp power down.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_utp_power_down(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);\n+}\n+\n+/**\n+ * yt8824_power_on()  - set utp power on.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * NOTE: need WA like softreset\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_power_on(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\tint r;\n+\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp power on */\n+\t\tret = yt8824_utp_power_on(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\treturn 0;\n+\n+retry:\n+\t/*\n+\t * If the PHY up operation succeeds but the subsequent operation\n+\t * fails, revert to the default state.\n+\t */\n+\tr = yt8824_utp_power_down(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_resume() - resume the hardware\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_resume(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_power_on(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_power_down()  - set utp power down.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * NOTE: need WA like softreset\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_power_down(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\tint r;\n+\n+\tif (priv-\u003einterface_mode == PHY_INTERFACE_MODE_INTERNAL) {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t} else {\n+\t\t/* invalid test mode */\n+\t\tret = yt8824_utp_invalid_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds isolation */\n+\t\tret = yt8824_sds_isolate_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* utp power down */\n+\t\tret = yt8824_utp_power_down(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* normal mode */\n+\t\tret = yt8824_utp_normal_test_mode_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\n+\t\t/* sds soft reset and disable isolation */\n+\t\tret = yt8824_sds_isolate_and_softreset_paged(phydev);\n+\t\tif (ret \u003c 0)\n+\t\t\tgoto retry;\n+\t}\n+\treturn 0;\n+\n+retry:\n+\t/*\n+\t * If the PHY down operation succeeds but the subsequent operation\n+\t * fails, revert to the default state.\n+\t */\n+\tr = yt8824_utp_power_on(phydev);\n+\tif (ret \u003e= 0 \u0026\u0026 r \u003c 0)\n+\t\tret = r;\n+\tret = yt8824_restore_working_status(phydev, ret);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_suspend() - suspend the hardware\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_suspend(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = yt8824_power_down(phydev);\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_config_aneg() - config negotiation\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_config_aneg(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tint phy_ctrl = 0;\n+\tint ret;\n+\n+\tmutex_lock(\u0026priv-\u003eshared_lock);\n+\tret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tif (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,\n+\t\t\t      phydev-\u003eadvertising))\n+\t\tphy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;\n+\n+\tret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,\n+\t\t\t\t     MDIO_AN_10GBT_CTRL,\n+\t\t\t\t     MDIO_AN_10GBT_CTRL_ADV2_5G,\n+\t\t\t\t     phy_ctrl);\n+\tif (ret \u003c 0)\n+\t\tgoto err;\n+\n+\tret = __genphy_config_aneg(phydev, ret);\n+\n+err:\n+\tmutex_unlock(\u0026priv-\u003eshared_lock);\n+\treturn ret;\n+}\n+\n+/**\n+ * yt8824_phy_package_probe_once()  - init phy package for phy8824.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_phy_package_probe_once(struct phy_device *phydev)\n+{\n+\tstruct yt8824_shared_priv *priv = phy_package_get_priv(phydev);\n+\tstruct device_node *np = phy_package_get_node(phydev);\n+\tconst char *interface_mode_name;\n+\n+\t/* Initialise shared lock for YT8824 */\n+\tmutex_init(\u0026priv-\u003eshared_lock);\n+\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\tif (!of_property_read_string(np, \"motorcomm,interface-mode\",\n+\t\t\t\t     \u0026interface_mode_name)) {\n+\t\tif (!strcasecmp(interface_mode_name,\n+\t\t\t\tphy_modes(PHY_INTERFACE_MODE_USXGMII))) {\n+\t\t\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_USXGMII;\n+\t\t} else if (!strcasecmp\n+\t\t\t\t(interface_mode_name,\n+\t\t\t\t phy_modes(PHY_INTERFACE_MODE_INTERNAL))) {\n+\t\t\tpriv-\u003einterface_mode = PHY_INTERFACE_MODE_INTERNAL;\n+\t\t} else {\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tphydev_warn(phydev, \"%s, motorcomm,interface-mode missing in DTS.\\n\",\n+\t\t\t    __func__);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * yt8824_probe() - phy8824 probe.\n+ * @phydev: a pointer to a \u0026struct phy_device\n+ *\n+ * Returns: 0 or negative errno code\n+ */\n+static int yt8824_probe(struct phy_device *phydev)\n+{\n+\tstruct device *dev = \u0026phydev-\u003emdio.dev;\n+\tstruct yt8824_shared_priv *shared_priv;\n+\tint ret;\n+\n+\tret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (phy_package_probe_once(phydev)) {\n+\t\tret = yt8824_phy_package_probe_once(phydev);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static struct phy_driver motorcomm_phy_drvs[] = {\n \t{\n \t\tPHY_ID_MATCH_EXACT(PHY_ID_YT8511),\n@@ -3190,13 +4754,29 @@ static struct phy_driver motorcomm_phy_drvs[] = {\n \t\t.suspend\t\t= yt8821_suspend,\n \t\t.resume\t\t\t= yt8821_resume,\n \t},\n+\t{\n+\t\tPHY_ID_MATCH_EXACT(PHY_ID_YT8824),\n+\t\t.name\t\t\t= \"YT8824 Quad Ports 2.5Gbps Ethernet\",\n+\t\t.get_features\t\t= yt8824_get_features,\n+\t\t.read_page\t\t= yt8824_read_page,\n+\t\t.write_page\t\t= yt8824_write_page,\n+\t\t.probe\t\t        = yt8824_probe,\n+\t\t.config_aneg\t\t= yt8824_config_aneg,\n+\t\t.aneg_done\t\t= yt8824_aneg_done,\n+\t\t.config_init\t\t= yt8824_config_init,\n+\t\t.read_status\t\t= yt8824_read_status,\n+\t\t.soft_reset\t\t= yt8824_soft_reset,\n+\t\t.suspend\t\t= yt8824_suspend,\n+\t\t.resume\t\t\t= yt8824_resume,\n+\t},\n };\n \n module_phy_driver(motorcomm_phy_drvs);\n \n-MODULE_DESCRIPTION(\"Motorcomm 8511/8521/8531/8531S/8821 PHY driver\");\n+MODULE_DESCRIPTION(\"Motorcomm 8511/8521/8531/8531S/8821/8824 PHY driver\");\n MODULE_AUTHOR(\"Peter Geis\");\n MODULE_AUTHOR(\"Frank\");\n+MODULE_AUTHOR(\"Kyle\");\n MODULE_LICENSE(\"GPL\");\n \n static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {\n@@ -3206,6 +4786,7 @@ static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },\n \t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },\n+\t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8824) },\n \t{ /* sentinel */ }\n };\n \ndiff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c\nindex 870920311f9a0..528e3f4143110 100644\n--- a/drivers/net/phy/phy-c45.c\n+++ b/drivers/net/phy/phy-c45.c\n@@ -1408,6 +1408,61 @@ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)\n }\n EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);\n \n+/**\n+ * genphy_c45_template_testmode - configure template testmode registers\n+ * @phydev: target phy_device struct\n+ * @test_mode: testmode includes Normal to Test mode 7\n+ *\n+ * Description: Set template testmode include Normal to Test mode 7\n+ *\n+ * Return: 0 on success, or a negative error code on failure (e.g. register\n+ *\tread/write error).\n+ */\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\n+{\n+\tint ctrl = 0;\n+\n+\tswitch (test_mode) {\n+\tcase 0:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_NORMAL;\n+\t\tbreak;\n+\n+\tcase 1:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_1;\n+\t\tbreak;\n+\n+\tcase 2:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_2;\n+\t\tbreak;\n+\n+\tcase 3:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_3;\n+\t\tbreak;\n+\n+\tcase 4:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_4;\n+\t\tbreak;\n+\n+\tcase 5:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_5;\n+\t\tbreak;\n+\n+\tcase 6:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_6;\n+\t\tbreak;\n+\n+\tcase 7:\n+\t\tctrl = MDIO_PMA_10GBT_TESTMODE_7;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\treturn phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TESTMODE,\n+\t\t\t      MDIO_PMA_10GBT_TESTMODE_MASK, ctrl);\n+}\n+EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);\n+\n /**\n  * genphy_c45_plca_get_cfg - get PLCA configuration from standard registers\n  * @phydev: target phy_device struct\ndiff --git a/include/linux/phy.h b/include/linux/phy.h\nindex 3d8afe6b7f1c5..fb827cc3c98f4 100644\n--- a/include/linux/phy.h\n+++ b/include/linux/phy.h\n@@ -2357,6 +2357,7 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed);\n int genphy_c45_pma_resume(struct phy_device *phydev);\n int genphy_c45_pma_suspend(struct phy_device *phydev);\n int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);\n+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);\n int genphy_c45_plca_get_cfg(struct phy_device *phydev,\n \t\t\t    struct phy_plca_cfg *plca_cfg);\n int genphy_c45_plca_set_cfg(struct phy_device *phydev,\ndiff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h\nindex 06f4bc3c20c71..8576a48877c6d 100644\n--- a/include/uapi/linux/mdio.h\n+++ b/include/uapi/linux/mdio.h\n@@ -63,6 +63,7 @@\n /* Media-dependent registers. */\n #define MDIO_PMA_10GBT_SWAPPOL\t130\t/* 10GBASE-T pair swap \u0026 polarity */\n #define MDIO_PMA_10GBT_TXPWR\t131\t/* 10GBASE-T TX power control */\n+#define MDIO_PMA_10GBT_TESTMODE 132\t/* Test mode control */\n #define MDIO_PMA_10GBT_SNR\t133\t/* 10GBASE-T SNR margin, lane A.\n \t\t\t\t\t * Lanes B-D are numbered 134-136. */\n #define MDIO_PMA_10GBR_FSRT_CSR\t147\t/* 10GBASE-R fast retrain status and control */\n@@ -320,6 +321,17 @@\n /* PMA 10GBASE-R Fast Retrain status and control register. */\n #define MDIO_PMA_10GBR_FSRT_ENABLE\t0x0001\t/* Fast retrain enable */\n \n+/* PMA 10GBASE-T Template Test Mode Register*/\n+#define MDIO_PMA_10GBT_TESTMODE_MASK 0xE000\t/* Template test mode */\n+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0000\t/* Template Normal */\n+#define MDIO_PMA_10GBT_TESTMODE_1 0x2000 /* Template TestMode1 */\n+#define MDIO_PMA_10GBT_TESTMODE_2 0x4000 /* Template TestMode2 */\n+#define MDIO_PMA_10GBT_TESTMODE_3 0x6000 /* Template TestMode3 */\n+#define MDIO_PMA_10GBT_TESTMODE_4 0x8000 /* Template TestMode4 */\n+#define MDIO_PMA_10GBT_TESTMODE_5 0xa000 /* Template TestMode5 */\n+#define MDIO_PMA_10GBT_TESTMODE_6 0xc000 /* Template TestMode6 */\n+#define MDIO_PMA_10GBT_TESTMODE_7 0xe000 /* Template TestMode7 */\n+\n /* PCS 10GBASE-R/-T status register 1. */\n #define MDIO_PCS_10GBRT_STAT1_BLKLK\t0x0001\t/* Block lock attained */\n \n"
}

2/1 2026/09/10 08:21 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 quad-port 2.5Gbps Ethernet PHY chip and a generic C45 test mode helper called only by this driver. This requires specific physical PHY hardware and Device Tree descriptions not present or emulated in standard virtualized fuzzing environments (QEMU/GCE), making the code structurally unreachable.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 973593aab6b7bc7f1d9584a776f6166eff4b3e65
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Sep 10 08:21:23 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml
new file mode 100644
index 0000000000000..9907a4a7e63e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/motorcomm,yt8824.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/motorcomm,yt8824.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MotorComm YT8824 Ethernet PHY
+
+maintainers:
+  - Kyle Switch <kyle.switch@motor-comm.com>
+
+description: |
+  Motorcomm YT8824 Ethernet PHY is a PHY package of 4 PHYs.
+
+$ref: ethernet-phy-package.yaml#
+
+properties:
+  compatible:
+    enum:
+      - ethernet-phy-id4f51.e8b8
+
+  motorcomm,interface-mode:
+    description: |
+      PHY package interface mode.
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - internal
+      - usxgmii
+    default: internal
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet-phy-package@0 {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            compatible = "ethernet-phy-id4f51.e8b8";
+            reg = <9>;
+
+            motorcomm,interface-mode = "usxgmii";
+
+            ethernet-phy@4 {
+                reg = <4>;
+            };
+
+            ethernet-phy@5 {
+                reg = <5>;
+            };
+
+            ethernet-phy@6 {
+                reg = <6>;
+            };
+
+            ethernet-phy@7 {
+                reg = <7>;
+            };
+        };
+    };
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b4ef927fd4a67..1dd80e06e2370 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -361,9 +361,10 @@ config MICROSEMI_PHY
 
 config MOTORCOMM_PHY
 	tristate "Motorcomm PHYs"
+	select PHY_PACKAGE
 	help
 	  Enables support for Motorcomm network PHYs.
-	  Currently supports YT85xx Gigabit Ethernet PHYs.
+	  Currently supports YT85xx Gigabit Ethernet PHYs and YT8824 4 * 2.5G PHY.
 
 config NATIONAL_PHY
 	tristate "National Semiconductor PHYs"
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 90a4f86f2758b..f41186b5b737f 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,24 +1,29 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Motorcomm 8511/8521/8522/8531/8531S/8821 PHY driver.
+ * Motorcomm 8511/8521/8522/8531/8531S/8821/8824 PHY driver.
  *
  * Author: Peter Geis <pgwipeout@gmail.com>
  * Author: Frank <Frank.Sae@motor-comm.com>
+ * Author: Kyle <kyle.switch@motor-comm.com>
  */
 
 #include <linux/clk.h>
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/property.h>
 
+#include "phylib.h"
+
 #define PHY_ID_YT8511		0x0000010a
 #define PHY_ID_YT8521		0x0000011a
 #define PHY_ID_YT8522		0x4f51e928
 #define PHY_ID_YT8531		0x4f51e91b
 #define PHY_ID_YT8531S		0x4f51e91a
 #define PHY_ID_YT8821		0x4f51ea19
+#define PHY_ID_YT8824		0x4f51e8b8
 /* YT8521/YT8531S/YT8821 Register Overview
  *	UTP Register space	|	FIBER Register space
  *  ------------------------------------------------------------
@@ -30,6 +35,18 @@
  *  ------------------------------------------------------------
  */
 
+/* YT8824 Register Overview
+ *	UTP Register space	|	USXGMII Register space
+ *  ------------------------------------------------------------
+ * |	UTP MII			|	USXGMII MII	        |
+ * |	UTP MMD			|				|
+ * |	UTP Extended		|	USXGMII Extended	|
+ * |	UTP Top Extended	|	USXGMII Top Extended	|
+ *  ------------------------------------------------------------
+ * |			Common Top Extended			|
+ *  ------------------------------------------------------------
+ */
+
 /* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */
 
 /* Specific Function Control Register */
@@ -381,6 +398,15 @@
 #define YT8821_CHIP_MODE_AUTO_BX2500_SGMII	0
 #define YT8821_CHIP_MODE_FORCE_BX2500		1
 
+#define YT8824_RSSR_SPACE_MASK			BIT(0)
+#define YT8824_RSSR_USXGMII_SPACE		(0x1)
+#define YT8824_RSSR_UTP_SPACE			(0x0)
+#define YT8824_UTP_TEMPLATE_TEST_MODE1		0x1
+#define YT8824_UTP_TEMPLATE_TEST_NORMAL		0x0
+#define YT8824_SDS_CFG_MIN_PRE_MASK		GENMASK(3, 0)
+#define YT8824_SDS_EN_FILL_PRE			BIT(13)
+#define YT8824_SDS_TX_PRE_PADDING		(0x7)
+
 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
@@ -399,6 +425,12 @@ struct yt8521_priv {
 	u8 reg_page;
 };
 
+struct yt8824_shared_priv {
+	unsigned int interface_mode;
+	/* shared_lock used to UTPs operation isolation during swap reg space */
+	struct mutex shared_lock;
+};
+
 /**
  * ytphy_read_ext() - read a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -437,6 +469,70 @@ static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum)
 	return ret;
 }
 
+/**
+ * ytphy_read_top_ext() - read a PHY's top extended register for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @regnum: register number to read
+ *
+ * Returns: the value of regnum reg or negative error code
+ */
+static int ytphy_read_top_ext(struct phy_device *phydev, u16 regnum)
+{
+	int ret;
+
+	lockdep_assert_held(&phydev->mdio.bus->mdio_lock);
+	ret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);
+	if (ret < 0)
+		return ret;
+
+	return __phy_package_read(phydev, 0, YTPHY_PAGE_DATA);
+}
+
+/**
+ * ytphy_write_top_ext() - write a PHY's top extended register for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @regnum: register number to write
+ * @val: register val to write
+ *
+ * Returns: 0 or negative error code
+ */
+static int ytphy_write_top_ext(struct phy_device *phydev, u16 regnum,
+			       u16 val)
+{
+	int ret;
+
+	lockdep_assert_held(&phydev->mdio.bus->mdio_lock);
+	ret = __phy_package_write(phydev, 0, YTPHY_PAGE_SELECT, regnum);
+	if (ret < 0)
+		return ret;
+
+	return __phy_package_write(phydev, 0, YTPHY_PAGE_DATA, val);
+}
+
+/**
+ * phy8824_page_write_with_lock() - write page for YT8824
+ * @phydev: a pointer to a &struct phy_device
+ * @page: reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE).
+ *
+ * Returns: 0 or negative error code
+ */
+static int phy8824_page_write_with_lock(struct phy_device *phydev, int page)
+{
+	int ret;
+
+	phy_lock_mdio_bus(phydev);
+	ret = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (ret < 0)
+		goto err;
+	ret &= ~YT8824_RSSR_SPACE_MASK;
+	ret |= (page & YT8824_RSSR_SPACE_MASK);
+	ret = ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, ret);
+
+err:
+	phy_unlock_mdio_bus(phydev);
+	return ret;
+}
+
 /**
  * ytphy_write_ext() - write a PHY's extended register
  * @phydev: a pointer to a &struct phy_device
@@ -626,11 +722,1056 @@ static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
 		ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG,
 				   YTPHY_IER_WOL, 0);
 		if (ret < 0)
-			goto err_restore_page;
+			goto err_restore_page;
+	}
+
+err_restore_page:
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_read_page() - read PHY8824 reg page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: current reg space of yt8824 (YT8824_RSSR_USXGMII_SPACE/
+ * YT8824_RSSR_UTP_SPACE) or negative errno code
+ */
+static int yt8824_read_page(struct phy_device *phydev)
+{
+	int old_page;
+
+	old_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (old_page < 0)
+		return old_page;
+
+	return old_page & YT8824_RSSR_SPACE_MASK;
+};
+
+/**
+ * yt8824_write_page() - write reg page
+ * @phydev: a pointer to a &struct phy_device
+ * @page: Reg page(YT8824_RSSR_USXGMII_SPACE/YT8824_RSSR_UTP_SPACE) to write.
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_write_page(struct phy_device *phydev, int page)
+{
+	int old_page;
+	u16 data;
+
+	old_page = ytphy_read_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG);
+	if (old_page < 0)
+		return old_page;
+	data = old_page & (~YT8824_RSSR_SPACE_MASK);
+	data |= page;
+
+	return ytphy_write_top_ext(phydev, YT8521_REG_SPACE_SELECT_REG, data);
+};
+
+/**
+ * yt8824_utp_invalid_test_mode_paged() - config YT8824 to invalid test mode.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);
+}
+
+/**
+ * yt8824_sds_isolate_paged() - enable YT8824 serdes isolate.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_sds_isolate_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int ret = 0;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* enable sds isolate */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, BMCR_ISOLATE);
+
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_utp_softreset_paged() - config YT8824 UTP softreset.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_softreset_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET, BMCR_RESET);
+	if (ret < 0)
+		return ret;
+	/* wait until softreset done. */
+	return phy_read_poll_timeout(phydev, MII_BMCR, val,
+				     !(val & BMCR_RESET),
+				     50000, 600000, true);
+}
+
+/**
+ * yt8824_utp_normal_test_mode_paged() - config YT8824 to normal test mode.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);
+}
+
+/**
+ * yt8824_sds_isolate_and_softreset_paged() - disable YT8824 serdes isolate
+ * and sds softreset.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_sds_isolate_and_softreset_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int val = 0;
+	int ret = -1;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* sds softreset and disable isolate */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ISOLATE,
+			   BMCR_RESET & ~BMCR_ISOLATE);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* poll while still holding the lock */
+	ret = read_poll_timeout(__phy_read, val, (val < 0) ||
+				!(val & BMCR_RESET),
+				50000, 600000, true, phydev, MII_BMCR);
+	if (val < 0)
+		ret = val;
+
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_restore_working_status() - called to do store working status
+ * @phydev: a pointer to a &struct phy_device
+ * @ret: operation's return code
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_restore_working_status(struct phy_device *phydev, int ret)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int r;
+
+	/* configure normal test mode */
+	r = yt8824_utp_normal_test_mode_paged(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	if (priv->interface_mode != PHY_INTERFACE_MODE_INTERNAL) {
+		/* sds soft reset and disable isolation */
+		r = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret >= 0 && r < 0)
+			ret = r;
+	}
+
+	return ret;
+}
+
+/**
+ * yt8824_soft_reset() - called to do PHY software reset
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_soft_reset(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp soft reset */
+		ret = yt8824_utp_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+retry:
+	ret = yt8824_restore_working_status(phydev, ret);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_extern_config_utp_init_paged() - config external phy8824 utp init
+ * @phydev: target phy_device struct
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val = 0;
+	int r;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+	/* power down */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+	if (ret < 0)
+		goto err_restore;
+
+	/* pll calibration */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0x0cba);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0a00);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0x0e00);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimization utp */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0001, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	/* enable nibble */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x0003);
+	if (ret < 0)
+		goto err_restore;
+
+	/* idle err detect enable */
+	ret = ytphy_write_ext_with_lock(phydev, 0x03d0, 0x5210);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 2.5G long cable performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0372, 0x5038);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037c, 0x6068);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0388, 0x00a0);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized fast retrain */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0359, 0x2140);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x000c, 0xc1a0);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 2.5G template tone */
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x0083);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04e2, 0x0149);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 2.5G template */
+	ret = ytphy_write_ext_with_lock(phydev, 0x047e, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x047f, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0480, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0481, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 1000M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0336, 0xab0a);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0340, 0x301d);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 100M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046e, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046f, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0470, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0471, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 100M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x030b, 0xaa1d);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x071f, 0x0036);
+	if (ret < 0)
+		goto err_restore;
+
+	/* 10M template amplitude */
+	ret = ytphy_write_ext_with_lock(phydev, 0x046b, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x046c, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized 10M cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0466, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0467, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0468, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0469, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimize utp 1000M performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x034a, 0xff03);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00f8, 0xb3ff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0059, 0x4040);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032c, 0x5094);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032d, 0xd094);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x032e, 0x5308);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x0322, 0x6440);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d3, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x04d2, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized EMC CS */
+	ret = ytphy_write_ext_with_lock(phydev, 0x00c8, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x00be, 0x6406);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x037a, 0x40ff);
+	if (ret < 0)
+		goto err_restore;
+
+	/* optimized EMC RE */
+	ret = ytphy_write_ext_with_lock(phydev, 0x0482, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x006e);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+
+	ret = genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);
+	if (ret < 0)
+		goto err_restore_normal;
+	/* reset */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			 BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_normal;
+	ret = phy_read_poll_timeout(phydev, MII_BMCR, val,
+				    !(val & BMCR_RESET),
+				    50000, 600000, true);
+	if (ret < 0)
+		goto err_restore_normal;
+
+	ret = genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);
+	if (ret < 0)
+		goto err_restore_normal;
+	return 0;
+
+err_restore:
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+
+err_restore_normal:
+	r = genphy_c45_template_testmode(phydev,
+					 YT8824_UTP_TEMPLATE_TEST_NORMAL);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+}
+
+/**
+ * yt8824_extern_config_sds_init_paged() - config external phy8824 sds init
+ * @phydev: target phy_device struct
+ *
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_extern_config_sds_init_paged(struct phy_device *phydev)
+{
+	int old_page = YT8824_RSSR_UTP_SPACE;
+	int val_1, val_2, val_3, tmp;
+	int ret = -1;
+	int val;
+
+	old_page = phy_select_page(phydev, YT8824_RSSR_USXGMII_SPACE);
+	if (old_page < 0)
+		goto err_restore_page;
+
+	/* read efuse */
+	ret = ytphy_read_top_ext(phydev, 0xa13e);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_1 = ret;
+
+	ret = ytphy_read_top_ext(phydev, 0xa13f);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_2 = ret;
+
+	ret = ytphy_read_top_ext(phydev, 0xa140);
+	if (ret < 0)
+		goto err_restore_page;
+	else
+		val_3 = ret;
+
+	/* Serdes optimization */
+	ret = ytphy_write_ext(phydev, 0x04be, 0x000d);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x049f, 0x7ded);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04a9, 0x009f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* analog CDR */
+	ret = ytphy_write_ext(phydev, 0x0406, 0x0800);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized VCO */
+	ret = ytphy_write_ext(phydev, 0x0438, 0x9024);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0439, 0x00c0);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized PLL lock */
+	ret = ytphy_read_ext(phydev, 0x0429);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(13) | BIT(12));
+	tmp = (val_1 & (BIT(7) | BIT(6))) >> 6;
+	ret |= (tmp << 12);
+	ret = ytphy_write_ext(phydev, 0x0429, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x0441);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(1) | BIT(0));
+	tmp = (val_1 & (BIT(5) | BIT(4))) >> 4;
+	ret |= tmp;
+	ret = ytphy_write_ext(phydev, 0x0441, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x042b);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(13) | BIT(12));
+	tmp = (val_3 & (BIT(1) | BIT(0)));
+	ret |= (tmp << 12);
+	ret = ytphy_write_ext(phydev, 0x042b, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x043a, 0x1006);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x042a, 0xf070);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* cable length threshold */
+	ret = ytphy_write_ext(phydev, 0x0491, 0x007f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes training threshold */
+	ret = ytphy_write_ext(phydev, 0x0454, 0x0f14);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0497, 0x0a44);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* digital eye diagram of SerDes */
+	ret = ytphy_write_ext(phydev, 0x04cd, 0x0000);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes LDO */
+	ret = ytphy_read_ext(phydev, 0x04b5);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(6) | BIT(5) | BIT(4));
+	tmp = (val_2 & (BIT(4) | BIT(3) | BIT(2))) >> 2;
+	ret |= (tmp << 4);
+	ret = ytphy_write_ext(phydev, 0x04b5, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_read_ext(phydev, 0x04b4);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret &= ~(BIT(10) | BIT(9) | BIT(8));
+	tmp = (val_2 & (BIT(7) | BIT(6) | BIT(5))) >> 5;
+	ret |= (tmp << 8);
+	ret = ytphy_write_ext(phydev, 0x04b4, ret);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized Serdes RX */
+	ret = ytphy_write_ext(phydev, 0x04af, 0x45e3);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x048a, 0x0fff);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0408, 0x7c00);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04d6, 0x007f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x044f, 0xff08);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* optimized Serdes TX */
+	ret = ytphy_write_ext(phydev, 0x048e, 0x7d00);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x000d, 0x0606);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* Serdes manual config */
+	ret = ytphy_write_ext(phydev, 0x04b0, 0x0804);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04b1, 0x7074);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x04af, 0x45e7);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* restart calibration */
+	ret = ytphy_write_ext(phydev, 0x0003, 0x5603);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7fff);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x0492, 0x7f7f);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x2000, 0x0040);
+	if (ret < 0)
+		goto err_restore_page;
+
+	ret = ytphy_write_ext(phydev, 0x2000, 0x0000);
+	if (ret < 0)
+		goto err_restore_page;
+
+	/* TX preamble padded to 8; RX IPG always > 8 */
+	ret = __phy_read(phydev, MII_RESV1);
+	if (ret < 0)
+		goto err_restore_page;
+	ret &= ~YT8824_SDS_CFG_MIN_PRE_MASK;
+	ret |= YT8824_SDS_TX_PRE_PADDING;
+	ret |= YT8824_SDS_EN_FILL_PRE;
+	ret = __phy_write(phydev, MII_RESV1, ret);
+	if (ret < 0)
+		goto err_restore_page;
+	/* reset serdes */
+	ret = __phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			   BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_page;
+	/* poll while still holding the lock; __phy_read takes no lock */
+	ret = read_poll_timeout(__phy_read, val, (val < 0) ||
+				!(val & BMCR_RESET),
+				50000, 600000, true, phydev, MII_BMCR);
+	if (val < 0)
+		ret = val;
+err_restore_page:
+	/* restore page, release the lock */
+	return phy_restore_page(phydev, old_page, ret);
+}
+
+/**
+ * yt8824_internal_config_init_paged() - config internal phy8824 init
+ * @phydev: target phy_device struct
+ *
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_internal_config_init_paged(struct phy_device *phydev)
+{
+	int ret = 0;
+	int val = 0;
+	int r = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = ytphy_write_ext_with_lock(phydev, 0x1, 0x3);
+	if (ret < 0)
+		return ret;
+	/* power down */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20e, 0xcba);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20a, 0xc3f1);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa20c, 0x1620);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xa00);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2b6, 0xe00);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa003, 0x3);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x3d0, 0x5210);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x372, 0x5038);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37c, 0x6068);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x388, 0xa0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x359, 0x2140);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2fa, 0x83);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4e2, 0x149);
+	if (ret < 0)
+		goto err_restore;
+	/* 2.5G tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x47e, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x47f, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x480, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x481, 0x3939);
+	if (ret < 0)
+		goto err_restore;
+	/* 1000 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x336, 0xab0a);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x340, 0x301d);
+	if (ret < 0)
+		goto err_restore;
+	/* 1000 performance */
+	ret = ytphy_write_ext_with_lock(phydev, 0x34a, 0xff03);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xf8, 0xb3ff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32c, 0x5094);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32d, 0xd094);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x32e, 0x5308);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x322, 0x6440);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d3, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x4d2, 0x5220);
+	if (ret < 0)
+		goto err_restore;
+	/* 100 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46e, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46f, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x470, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x471, 0x4545);
+	if (ret < 0)
+		goto err_restore;
+	/* 100 cable length threshold */
+	ret = ytphy_write_ext_with_lock(phydev, 0x30b, 0xaa1d);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x71f, 0x36);
+	if (ret < 0)
+		goto err_restore;
+	/* 10 tempate */
+	ret = ytphy_write_ext_with_lock(phydev, 0x46b, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x46c, 0x1818);
+	if (ret < 0)
+		goto err_restore;
+	/* 10 tempate MAU*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x466, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x467, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x468, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x469, 0x6c6c);
+	if (ret < 0)
+		goto err_restore;
+	/* EMC CS, Inconsistent with external phy */
+	ret = ytphy_write_ext_with_lock(phydev, 0xc8, 0xfff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xbe, 0x6406);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0x37a, 0x40ff);
+	if (ret < 0)
+		goto err_restore;
+	/* EMC RE*/
+	ret = ytphy_write_ext_with_lock(phydev, 0x482, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d5, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d6, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d7, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa2d8, 0x1f1f);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa218, 0x6e);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xfff0);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01d, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xa01e, 0xffff);
+	if (ret < 0)
+		goto err_restore;
+	ret = ytphy_write_ext_with_lock(phydev, 0xc, 0x41a1);
+	if (ret < 0)
+		goto err_restore;
+	ret = genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);
+	if (ret)
+		goto err_restore_normal;
+	/* reset */
+	ret = phy_modify(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE,
+			 BMCR_RESET | BMCR_ANENABLE);
+	if (ret < 0)
+		goto err_restore_normal;
+	ret = phy_read_poll_timeout(phydev, MII_BMCR, val,
+				    !(val & BMCR_RESET),
+				    50000, 600000, true);
+	if (ret < 0)
+		goto err_restore_normal;
+
+	ret = genphy_c45_template_testmode
+		(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);
+	if (ret < 0)
+		goto err_restore_normal;
+
+err_restore:
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+
+err_restore_normal:
+	r = genphy_c45_template_testmode(phydev,
+					 YT8824_UTP_TEMPLATE_TEST_NORMAL);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	r = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	return ret;
+}
+
+/**
+ * yt8824_config_init() - phy initializatioin
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_config_init(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		ret = yt8824_internal_config_init_paged(phydev);
+		if (ret < 0)
+			goto err;
+	} else {
+		ret = yt8824_extern_config_sds_init_paged(phydev);
+		if (ret < 0)
+			goto err;
+		ret = yt8824_extern_config_utp_init_paged(phydev);
+		if (ret < 0)
+			goto err;
 	}
+	mutex_unlock(&priv->shared_lock);
+	ret = yt8824_soft_reset(phydev);
 
-err_restore_page:
-	return phy_restore_page(phydev, old_page, ret);
+	phydev_dbg(phydev, "%s done, phy addr: %d\n",
+		   __func__, phydev->mdio.addr);
+	return ret;
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
 }
 
 static int yt8531_set_wol(struct phy_device *phydev,
@@ -3104,6 +4245,429 @@ static int yt8821_resume(struct phy_device *phydev)
 	return yt8821_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0);
 }
 
+/**
+ * yt8824_get_features - read mmd register to get 2.5G capability
+ * @phydev: target phy_device struct
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_get_features(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+	ret = yt8821_get_features(phydev);
+
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_aneg_done()  - check negotiation state.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: link status or negative errno code
+ */
+static int yt8824_aneg_done(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int link = 0;
+	int ret = 0;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+
+	ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+	if (ret < 0)
+		goto err;
+	mutex_unlock(&priv->shared_lock);
+	link = !!(ret & YTPHY_SSR_LINK);
+
+	phydev_dbg(phydev, "%s, phy addr: %d, link_utp: %d\n",
+		   __func__, phydev->mdio.addr, link);
+	return link;
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_read_status_paged() -  determines the speed and duplex of one page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_read_status_paged(struct phy_device *phydev)
+{
+	int link = 0;
+	int ret = 0;
+	int val = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	ret = genphy_read_status(phydev);
+	if (ret < 0)
+		return ret;
+
+	if (phydev->autoneg_complete) {
+		ret = genphy_c45_read_lpa(phydev);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG);
+	if (ret < 0)
+		return ret;
+
+	val = ret;
+
+	link = val & YTPHY_SSR_LINK;
+	if (link)
+		yt8821_adjust_status(phydev, val);
+
+	if (link) {
+		if (phydev->link == 0)
+			phydev_dbg(phydev,
+				   "%s, phy addr: %d, link up\n",
+				   __func__, phydev->mdio.addr);
+		phydev->link = 1;
+	} else {
+		if (phydev->link == 1)
+			phydev_dbg(phydev,
+				   "%s, phy addr: %d, link down\n",
+				   __func__, phydev->mdio.addr);
+		phydev->link = 0;
+	}
+	phy_resolve_aneg_pause(phydev);
+	return 0;
+}
+
+/**
+ * yt8824_read_status() -  determines the negotiated speed and duplex
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_read_status(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_read_status_paged(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_utp_power_on(): utp power on.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_power_on(struct phy_device *phydev)
+{
+	int ret = 0;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0x0);
+}
+
+/**
+ * yt8824_utp_power_down(): utp power down.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_utp_power_down(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		return ret;
+
+	return phy_modify(phydev, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN);
+}
+
+/**
+ * yt8824_power_on()  - set utp power on.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * NOTE: need WA like softreset
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_power_on(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+	int r;
+
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp power on */
+		ret = yt8824_utp_power_on(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	return 0;
+
+retry:
+	/*
+	 * If the PHY up operation succeeds but the subsequent operation
+	 * fails, revert to the default state.
+	 */
+	r = yt8824_utp_power_down(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	ret = yt8824_restore_working_status(phydev, ret);
+	return ret;
+}
+
+/**
+ * yt8824_resume() - resume the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_resume(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_power_on(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_power_down()  - set utp power down.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * NOTE: need WA like softreset
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_power_down(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+	int r;
+
+	if (priv->interface_mode == PHY_INTERFACE_MODE_INTERNAL) {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			goto retry;
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	} else {
+		/* invalid test mode */
+		ret = yt8824_utp_invalid_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds isolation */
+		ret = yt8824_sds_isolate_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* utp power down */
+		ret = yt8824_utp_power_down(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* normal mode */
+		ret = yt8824_utp_normal_test_mode_paged(phydev);
+		if (ret < 0)
+			goto retry;
+
+		/* sds soft reset and disable isolation */
+		ret = yt8824_sds_isolate_and_softreset_paged(phydev);
+		if (ret < 0)
+			goto retry;
+	}
+	return 0;
+
+retry:
+	/*
+	 * If the PHY down operation succeeds but the subsequent operation
+	 * fails, revert to the default state.
+	 */
+	r = yt8824_utp_power_on(phydev);
+	if (ret >= 0 && r < 0)
+		ret = r;
+	ret = yt8824_restore_working_status(phydev, ret);
+	return ret;
+}
+
+/**
+ * yt8824_suspend() - suspend the hardware
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_suspend(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = yt8824_power_down(phydev);
+	mutex_unlock(&priv->shared_lock);
+
+	return ret;
+}
+
+/**
+ * yt8824_config_aneg() - config negotiation
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_config_aneg(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	int phy_ctrl = 0;
+	int ret;
+
+	mutex_lock(&priv->shared_lock);
+	ret = phy8824_page_write_with_lock(phydev, YT8824_RSSR_UTP_SPACE);
+	if (ret < 0)
+		goto err;
+
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+			      phydev->advertising))
+		phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;
+
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
+				     MDIO_AN_10GBT_CTRL,
+				     MDIO_AN_10GBT_CTRL_ADV2_5G,
+				     phy_ctrl);
+	if (ret < 0)
+		goto err;
+
+	ret = __genphy_config_aneg(phydev, ret);
+
+err:
+	mutex_unlock(&priv->shared_lock);
+	return ret;
+}
+
+/**
+ * yt8824_phy_package_probe_once()  - init phy package for phy8824.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_phy_package_probe_once(struct phy_device *phydev)
+{
+	struct yt8824_shared_priv *priv = phy_package_get_priv(phydev);
+	struct device_node *np = phy_package_get_node(phydev);
+	const char *interface_mode_name;
+
+	/* Initialise shared lock for YT8824 */
+	mutex_init(&priv->shared_lock);
+	priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+	if (!of_property_read_string(np, "motorcomm,interface-mode",
+				     &interface_mode_name)) {
+		if (!strcasecmp(interface_mode_name,
+				phy_modes(PHY_INTERFACE_MODE_USXGMII))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_USXGMII;
+		} else if (!strcasecmp
+				(interface_mode_name,
+				 phy_modes(PHY_INTERFACE_MODE_INTERNAL))) {
+			priv->interface_mode = PHY_INTERFACE_MODE_INTERNAL;
+		} else {
+			return -EINVAL;
+		}
+	} else {
+		phydev_warn(phydev, "%s, motorcomm,interface-mode missing in DTS.\n",
+			    __func__);
+	}
+
+	return 0;
+}
+
+/**
+ * yt8824_probe() - phy8824 probe.
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns: 0 or negative errno code
+ */
+static int yt8824_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct yt8824_shared_priv *shared_priv;
+	int ret;
+
+	ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));
+	if (ret)
+		return ret;
+
+	if (phy_package_probe_once(phydev)) {
+		ret = yt8824_phy_package_probe_once(phydev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static struct phy_driver motorcomm_phy_drvs[] = {
 	{
 		PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
@@ -3190,13 +4754,29 @@ static struct phy_driver motorcomm_phy_drvs[] = {
 		.suspend		= yt8821_suspend,
 		.resume			= yt8821_resume,
 	},
+	{
+		PHY_ID_MATCH_EXACT(PHY_ID_YT8824),
+		.name			= "YT8824 Quad Ports 2.5Gbps Ethernet",
+		.get_features		= yt8824_get_features,
+		.read_page		= yt8824_read_page,
+		.write_page		= yt8824_write_page,
+		.probe		        = yt8824_probe,
+		.config_aneg		= yt8824_config_aneg,
+		.aneg_done		= yt8824_aneg_done,
+		.config_init		= yt8824_config_init,
+		.read_status		= yt8824_read_status,
+		.soft_reset		= yt8824_soft_reset,
+		.suspend		= yt8824_suspend,
+		.resume			= yt8824_resume,
+	},
 };
 
 module_phy_driver(motorcomm_phy_drvs);
 
-MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/8821 PHY driver");
+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S/8821/8824 PHY driver");
 MODULE_AUTHOR("Peter Geis");
 MODULE_AUTHOR("Frank");
+MODULE_AUTHOR("Kyle");
 MODULE_LICENSE("GPL");
 
 static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
@@ -3206,6 +4786,7 @@ static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },
 	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },
+	{ PHY_ID_MATCH_EXACT(PHY_ID_YT8824) },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 870920311f9a0..528e3f4143110 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1408,6 +1408,61 @@ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)
 }
 EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);
 
+/**
+ * genphy_c45_template_testmode - configure template testmode registers
+ * @phydev: target phy_device struct
+ * @test_mode: testmode includes Normal to Test mode 7
+ *
+ * Description: Set template testmode include Normal to Test mode 7
+ *
+ * Return: 0 on success, or a negative error code on failure (e.g. register
+ *	read/write error).
+ */
+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)
+{
+	int ctrl = 0;
+
+	switch (test_mode) {
+	case 0:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_NORMAL;
+		break;
+
+	case 1:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_1;
+		break;
+
+	case 2:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_2;
+		break;
+
+	case 3:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_3;
+		break;
+
+	case 4:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_4;
+		break;
+
+	case 5:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_5;
+		break;
+
+	case 6:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_6;
+		break;
+
+	case 7:
+		ctrl = MDIO_PMA_10GBT_TESTMODE_7;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TESTMODE,
+			      MDIO_PMA_10GBT_TESTMODE_MASK, ctrl);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);
+
 /**
  * genphy_c45_plca_get_cfg - get PLCA configuration from standard registers
  * @phydev: target phy_device struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 3d8afe6b7f1c5..fb827cc3c98f4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2357,6 +2357,7 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed);
 int genphy_c45_pma_resume(struct phy_device *phydev);
 int genphy_c45_pma_suspend(struct phy_device *phydev);
 int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);
+int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);
 int genphy_c45_plca_get_cfg(struct phy_device *phydev,
 			    struct phy_plca_cfg *plca_cfg);
 int genphy_c45_plca_set_cfg(struct phy_device *phydev,
diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index 06f4bc3c20c71..8576a48877c6d 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -63,6 +63,7 @@
 /* Media-dependent registers. */
 #define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
 #define MDIO_PMA_10GBT_TXPWR	131	/* 10GBASE-T TX power control */
+#define MDIO_PMA_10GBT_TESTMODE 132	/* Test mode control */
 #define MDIO_PMA_10GBT_SNR	133	/* 10GBASE-T SNR margin, lane A.
 					 * Lanes B-D are numbered 134-136. */
 #define MDIO_PMA_10GBR_FSRT_CSR	147	/* 10GBASE-R fast retrain status and control */
@@ -320,6 +321,17 @@
 /* PMA 10GBASE-R Fast Retrain status and control register. */
 #define MDIO_PMA_10GBR_FSRT_ENABLE	0x0001	/* Fast retrain enable */
 
+/* PMA 10GBASE-T Template Test Mode Register*/
+#define MDIO_PMA_10GBT_TESTMODE_MASK 0xE000	/* Template test mode */
+#define MDIO_PMA_10GBT_TESTMODE_NORMAL 0x0000	/* Template Normal */
+#define MDIO_PMA_10GBT_TESTMODE_1 0x2000 /* Template TestMode1 */
+#define MDIO_PMA_10GBT_TESTMODE_2 0x4000 /* Template TestMode2 */
+#define MDIO_PMA_10GBT_TESTMODE_3 0x6000 /* Template TestMode3 */
+#define MDIO_PMA_10GBT_TESTMODE_4 0x8000 /* Template TestMode4 */
+#define MDIO_PMA_10GBT_TESTMODE_5 0xa000 /* Template TestMode5 */
+#define MDIO_PMA_10GBT_TESTMODE_6 0xc000 /* Template TestMode6 */
+#define MDIO_PMA_10GBT_TESTMODE_7 0xe000 /* Template TestMode7 */
+
 /* PCS 10GBASE-R/-T status register 1. */
 #define MDIO_PCS_10GBRT_STAT1_BLKLK	0x0001	/* Block lock attained */
 

3/2 2026/09/10 08:21 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 26263
							output: 25
							thoughts: 495
						

Thoughts:
**Fuzzing Feasibility Assessment**

Okay, let's break down this patch and see if it's worth our time to fuzz. It looks like we have a few files affected: documentation, Kconfig modifications selecting `PHY_PACKAGE` for `MOTORCOMM_PHY`, the actual driver code for the YT8824 PHY, a helper function addition in `phy-c45.c` called `genphy_c45_template_testmode`, the declaration of that helper, and some definitions in `mdio.h`.

The key question is reachability, right? Can we hit this stuff in a standard fuzzing setup, like syzkaller or a regular QEMU environment? Specifically, I'm thinking about those PHY drivers, particularly ethernet PHY drivers that attach via the MDIO bus. Can we probe them in a virtual environment? I have to remember how this all works... PHY drivers are probed when the MDIO bus is scanned. So, like, `mdio-bitbang`, `mdio-gpio`, `fixed-mdio`, or MAC-specific MDIO buses such as `fec` and `stmmac` will do the trick.

But this `drivers/net/phy/motorcomm.c` specifically... is it a hardware-dependent PHY driver? Does it *require* specific hardware to work, or can we simulate or mock the MDIO bus and probe it? Can we create a virtual device with the `PHY_ID_YT8824` ID and trigger the driver to probe?

And what about that `genphy_c45_template_testmode` function? That's in `phy-c45.c`, but who actually uses it? Ah, right, the code mentions that *only* `motorcomm.c` is calling `genphy_c45_template_testmode`. Good to know! Now, I need to check if anything else calls that function, or if it's somehow exposed to userspace. If it's only called internally, that makes fuzzing a bit trickier, but still doable.



4/2 2026/09/10 08:21 tool grepper
0m Args:
{
  "Expression": "genphy_c45_template_testmode"
}

Results:
{
  "Output": "drivers/net/phy/motorcomm.c=777=static int yt8824_utp_invalid_test_mode_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-784-\ndrivers/net/phy/motorcomm.c:785:\treturn genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-786-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c=841=static int yt8824_utp_normal_test_mode_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-848-\ndrivers/net/phy/motorcomm.c:849:\treturn genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-850-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=979=static int yt8824_extern_config_utp_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1232-\ndrivers/net/phy/motorcomm.c:1233:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1234-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c-1247-\ndrivers/net/phy/motorcomm.c:1248:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1249-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1260-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1261:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1262-\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c=1520=static int yt8824_internal_config_init_paged(struct phy_device *phydev)\n--\ndrivers/net/phy/motorcomm.c-1704-\t\tgoto err_restore;\ndrivers/net/phy/motorcomm.c:1705:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1706-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_MODE1);\n--\ndrivers/net/phy/motorcomm.c-1719-\ndrivers/net/phy/motorcomm.c:1720:\tret = genphy_c45_template_testmode\ndrivers/net/phy/motorcomm.c-1721-\t\t(phydev, YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/motorcomm.c-1731-err_restore_normal:\ndrivers/net/phy/motorcomm.c:1732:\tr = genphy_c45_template_testmode(phydev,\ndrivers/net/phy/motorcomm.c-1733-\t\t\t\t\t YT8824_UTP_TEMPLATE_TEST_NORMAL);\n--\ndrivers/net/phy/phy-c45.c=1409=EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);\n--\ndrivers/net/phy/phy-c45.c-1411-/**\ndrivers/net/phy/phy-c45.c:1412: * genphy_c45_template_testmode - configure template testmode registers\ndrivers/net/phy/phy-c45.c-1413- * @phydev: target phy_device struct\n--\ndrivers/net/phy/phy-c45.c-1420- */\ndrivers/net/phy/phy-c45.c:1421:int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode)\ndrivers/net/phy/phy-c45.c-1422-{\n--\ndrivers/net/phy/phy-c45.c-1463-}\ndrivers/net/phy/phy-c45.c:1464:EXPORT_SYMBOL_GPL(genphy_c45_template_testmode);\ndrivers/net/phy/phy-c45.c-1465-\n--\ninclude/linux/phy.h=2359=int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);\ninclude/linux/phy.h:2360:int genphy_c45_template_testmode(struct phy_device *phydev, int test_mode);\ninclude/linux/phy.h-2361-int genphy_c45_plca_get_cfg(struct phy_device *phydev,\n"
}

5/2 2026/09/10 08:21 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 28550
							output: 23
							thoughts: 336
						

Thoughts:
**Analyzing the Reachability of `genphy_c45_template_testmode`**

Okay, so `genphy_c45_template_testmode` resides within `phy-c45.c` and, according to this, is only invoked from `motorcomm.c`. The critical question is whether `motorcomm.c` is structurally accessible in a standard QEMU/GCE environment.

My understanding is that `motorcomm.c` is tied to the MotorComm YT8824, a physical Ethernet PHY. The question is can I even probe or run `motorcomm.c` without this particular, physical PHY and MDIO bus being present? Let me review the constraints in section 2 of these instructions. Ah, here we are: the mention of structurally unreachable hardware. It highlights specific examples like vendor-specific PCIe switches, SmartNICs, GPU drivers – things dependent on ASICs or PCIe cards not simulated in the typical QEMU context. And yes, it explicitly points out that PHY drivers – Motorcomm, Realtek, Broadcom, etc. – are reliant on actual MDIO hardware or at least an MDIO bus with the correct PHY device ID in registers 2 and 3.

Right, so can QEMU emulate a YT8824? The answer is no, it doesn’t. Okay, is there even a virtual PHY device or MDIO bus that might instantiate `motorcomm_phy_drvs`? I should check if MDIO or PHY devices can be created from userspace. I'll check via netlink, debugfs, or configfs.



6/2 2026/09/10 08:21 tool grepper
0m Args:
{
  "Expression": "PHY_ID_YT8824"
}

Results:
{
  "Output": "drivers/net/phy/motorcomm.c-25-#define PHY_ID_YT8821\t\t0x4f51ea19\ndrivers/net/phy/motorcomm.c:26:#define PHY_ID_YT8824\t\t0x4f51e8b8\ndrivers/net/phy/motorcomm.c-27-/* YT8521/YT8531S/YT8821 Register Overview\n--\ndrivers/net/phy/motorcomm.c=4671=static struct phy_driver motorcomm_phy_drvs[] = {\n--\ndrivers/net/phy/motorcomm.c-4757-\t{\ndrivers/net/phy/motorcomm.c:4758:\t\tPHY_ID_MATCH_EXACT(PHY_ID_YT8824),\ndrivers/net/phy/motorcomm.c-4759-\t\t.name\t\t\t= \"YT8824 Quad Ports 2.5Gbps Ethernet\",\n--\ndrivers/net/phy/motorcomm.c=4782=static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {\n--\ndrivers/net/phy/motorcomm.c-4788-\t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },\ndrivers/net/phy/motorcomm.c:4789:\t{ PHY_ID_MATCH_EXACT(PHY_ID_YT8824) },\ndrivers/net/phy/motorcomm.c-4790-\t{ /* sentinel */ }\n"
}

7/2 2026/09/10 08:21 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 29642
							output: 107
							thoughts: 577
						

Thoughts:
**My Assessment of the Code's Fuzzing Reachability**

Okay, let's break this down. I need to assess whether this patch introduces code paths that are realistically reachable during fuzzing. I'm starting with the `yt8824_probe` function. The key here is the use of `devm_of_phy_package_join`. This function, and by extension, the entire driver, relies on a Device Tree (DT) description of the PHY package, specifically the Motorcomm YT8824. The DT node ties the PHY to a physical MDIO bus and specifies the YT8824 PHY chip with its ID.

This immediately flags a problem: This kind of hardware configuration, that specific PHY chip, is structurally unreachable in standard virtualized environments. Think QEMU or Google Compute Engine – they aren't going to have this specific physical hardware or properly emulated DT. This is standard ethernet PHY hardware that requires that specific physical hardware to be meaningfully tested.

Now, let's confirm my initial suspicion. This aligns perfectly with section 2 of my criteria. I'm looking for code that deals with hardware that is vendor-specific, requiring physical ASICs or PCIe cards not simulated in common virtualization scenarios. The Motorcomm YT8824 PHY is a textbook example of this category.

To reinforce this, I investigated `genphy_c45_template_testmode`. This is another function that is important to the overall evaluation. A quick grep confirms that `genphy_c45_template_testmode` is *only* called within `motorcomm.c`. No other generic PHY code or ethtool/netlink code calls it. This further strengthens the argument that this particular modified code is functionally isolated and only ever runs in conjunction with that specific hardware.

Therefore, my conclusion is that the code introduced by this patch is *structurally unreachable* in standard fuzzing environments. There is no realistic way to trigger it with a standard virtualized fuzzing setup.

I'm setting:
*   `WorthFuzzing`: false
*   `EnableConfigs`: \[ ]
*   `FocusSymbols`: \[ ]
*   `Reasoning`: concise explanation that the patch introduces support for the MotorComm YT8824 Ethernet PHY transceiver chip (and a helper function in phylib used exclusively by this driver), which requires physical hardware / DT nodes not present or emulated in standard virtualized fuzzing environments.

I'm ready to call `set-results`.



8/2 2026/09/10 08:21 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 quad-port 2.5Gbps Ethernet PHY chip and a generic C45 test mode helper called only by this driver. This requires specific physical PHY hardware and Device Tree descriptions not present or emulated in standard virtualized fuzzing environments (QEMU/GCE), making the code structurally unreachable.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Motorcomm YT8824 quad-port 2.5Gbps Ethernet PHY chip and a generic C45 test mode helper called only by this driver. This requires specific physical PHY hardware and Device Tree descriptions not present or emulated in standard virtualized fuzzing environments (QEMU/GCE), making the code structurally unreachable.",
  "WorthFuzzing": false
}

9/1 2026/09/10 08:21 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)