]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
generic: 6.12: backport MediaTek Ethernet PHY changes
authorDaniel Golle <daniel@makrotopia.org>
Thu, 8 May 2025 02:01:07 +0000 (03:01 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Mon, 26 May 2025 15:58:03 +0000 (16:58 +0100)
The MediaTek Ethernet PHY drivers are going to be used by multiple
targets (airoha, mediatek, ramips). Add generic backports of changes
required for recently added Ethernet PHYs.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
22 files changed:
target/linux/generic/backport-6.12/720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch [new file with mode: 0644]
target/linux/generic/backport-6.12/726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/781-10-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch
target/linux/generic/hack-6.12/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
target/linux/generic/hack-6.12/735-net-phy-realtek-rtl8261n.patch
target/linux/generic/hack-6.12/766-net-phy-mediatek-ge-add-LED-configuration-interface.patch
target/linux/generic/pending-6.12/510-block-add-uImage.FIT-subimage-block-driver.patch

diff --git a/target/linux/generic/backport-6.12/720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch b/target/linux/generic/backport-6.12/720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch
new file mode 100644 (file)
index 0000000..25bd96f
--- /dev/null
@@ -0,0 +1,88 @@
+From 277f96c1f3f71d6e1d3bcf650d7cd84c1442210f Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 17 Oct 2024 11:22:11 +0800
+Subject: [PATCH 01/20] net: phy: mediatek-ge-soc: Fix coding style
+
+This patch fixes spelling errors, re-arrange vars with
+reverse Xmas tree and remove unnecessary parens in
+mediatek-ge-soc.c.
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/net/phy/mediatek-ge-soc.c | 36 ++++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -408,16 +408,17 @@ static int tx_offset_cal_efuse(struct ph
+ static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
+ {
+-      int i;
+-      int bias[16] = {};
+-      const int vals_9461[16] = { 7, 1, 4, 7,
+-                                  7, 1, 4, 7,
+-                                  7, 1, 4, 7,
+-                                  7, 1, 4, 7 };
+       const int vals_9481[16] = { 10, 6, 6, 10,
+                                   10, 6, 6, 10,
+                                   10, 6, 6, 10,
+                                   10, 6, 6, 10 };
++      const int vals_9461[16] = { 7, 1, 4, 7,
++                                  7, 1, 4, 7,
++                                  7, 1, 4, 7,
++                                  7, 1, 4, 7 };
++      int bias[16] = {};
++      int i;
++
+       switch (phydev->drv->phy_id) {
+       case MTK_GPHY_ID_MT7981:
+               /* We add some calibration to efuse values
+@@ -1069,10 +1070,10 @@ static int start_cal(struct phy_device *
+ static int mt798x_phy_calibration(struct phy_device *phydev)
+ {
++      struct nvmem_cell *cell;
+       int ret = 0;
+-      u32 *buf;
+       size_t len;
+-      struct nvmem_cell *cell;
++      u32 *buf;
+       cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
+       if (IS_ERR(cell)) {
+@@ -1210,14 +1211,15 @@ static int mt798x_phy_led_brightness_set
+       return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
+ }
+-static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
+-                                               BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
+-                                               BIT(TRIGGER_NETDEV_LINK)        |
+-                                               BIT(TRIGGER_NETDEV_LINK_10)     |
+-                                               BIT(TRIGGER_NETDEV_LINK_100)    |
+-                                               BIT(TRIGGER_NETDEV_LINK_1000)   |
+-                                               BIT(TRIGGER_NETDEV_RX)          |
+-                                               BIT(TRIGGER_NETDEV_TX));
++static const unsigned long supported_triggers =
++      BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
++      BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
++      BIT(TRIGGER_NETDEV_LINK)        |
++      BIT(TRIGGER_NETDEV_LINK_10)     |
++      BIT(TRIGGER_NETDEV_LINK_100)    |
++      BIT(TRIGGER_NETDEV_LINK_1000)   |
++      BIT(TRIGGER_NETDEV_RX)          |
++      BIT(TRIGGER_NETDEV_TX);
+ static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+                                         unsigned long rules)
+@@ -1415,7 +1417,7 @@ static int mt7988_phy_probe_shared(struc
+        * LED_C and LED_D respectively. At the same time those pins are used to
+        * bootstrap configuration of the reference clock source (LED_A),
+        * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
+-       * In practise this is done using a LED and a resistor pulling the pin
++       * In practice this is done using a LED and a resistor pulling the pin
+        * either to GND or to VIO.
+        * The detected value at boot time is accessible at run-time using the
+        * TPBANK0 register located in the gpio base of the pinctrl, in order
diff --git a/target/linux/generic/backport-6.12/721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch b/target/linux/generic/backport-6.12/721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch
new file mode 100644 (file)
index 0000000..fbf3a99
--- /dev/null
@@ -0,0 +1,271 @@
+From c0dc1b412f9d840c51c5ee8927bf066e15a59550 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 17 Oct 2024 11:22:12 +0800
+Subject: [PATCH 02/20] net: phy: mediatek-ge-soc: Shrink line wrapping to 80
+ characters
+
+This patch shrinks line wrapping to 80 chars. Also, in
+tx_amp_fill_result(), use FIELD_PREP() to prettify code.
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/net/phy/mediatek-ge-soc.c | 125 +++++++++++++++++++++---------
+ 1 file changed, 88 insertions(+), 37 deletions(-)
+
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -342,7 +342,8 @@ static int cal_cycle(struct phy_device *
+       ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+                                       MTK_PHY_RG_AD_CAL_CLK, reg_val,
+                                       reg_val & MTK_PHY_DA_CAL_CLK, 500,
+-                                      ANALOG_INTERNAL_OPERATION_MAX_US, false);
++                                      ANALOG_INTERNAL_OPERATION_MAX_US,
++                                      false);
+       if (ret) {
+               phydev_err(phydev, "Calibration cycle timeout\n");
+               return ret;
+@@ -441,40 +442,72 @@ static int tx_amp_fill_result(struct phy
+       }
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+-                     MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
++                     MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
++                                buf[0] + bias[0]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+-                     MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
++                     MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
++                                buf[0] + bias[1]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+-                     MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
++                     MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
++                                buf[0] + bias[2]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+-                     MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
++                     MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
++                                buf[0] + bias[3]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+-                     MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
++                                buf[1] + bias[4]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+-                     MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
++                     MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
++                                buf[1] + bias[5]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+-                     MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
++                                buf[1] + bias[6]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+-                     MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
++                     MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
++                                buf[1] + bias[7]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+-                     MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
++                                buf[2] + bias[8]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+-                     MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
++                     MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
++                                buf[2] + bias[9]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+-                     MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
++                                buf[2] + bias[10]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+-                     MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
++                     MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
++                                buf[2] + bias[11]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+-                     MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
++                                buf[3] + bias[12]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+-                     MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
++                     MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
++                                buf[3] + bias[13]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+-                     MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
++                     MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
++                                buf[3] + bias[14]));
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+-                     MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
++                     MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
++                                buf[3] + bias[15]));
+       return 0;
+ }
+@@ -663,7 +696,8 @@ static int tx_vcm_cal_sw(struct phy_devi
+               goto restore;
+       /* We calibrate TX-VCM in different logic. Check upper index and then
+-       * lower index. If this calibration is valid, apply lower index's result.
++       * lower index. If this calibration is valid, apply lower index's
++       * result.
+        */
+       ret = upper_ret - lower_ret;
+       if (ret == 1) {
+@@ -692,7 +726,8 @@ static int tx_vcm_cal_sw(struct phy_devi
+       } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
+                  lower_ret == 0) {
+               ret = 0;
+-              phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
++              phydev_warn(phydev,
++                          "TX-VCM SW cal result at high margin 0x%x\n",
+                           upper_idx);
+       } else {
+               ret = -EINVAL;
+@@ -796,7 +831,8 @@ static void mt7981_phy_finetune(struct p
+       /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+-                     MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
++                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
++                     MTK_PHY_LPF_X_AVERAGE_MASK,
+                      BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
+       /* rg_tr_lpf_cnt_val = 512 */
+@@ -865,7 +901,8 @@ static void mt7988_phy_finetune(struct p
+       /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+-                     MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
++                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
++                     MTK_PHY_LPF_X_AVERAGE_MASK,
+                      BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
+       /* rg_tr_lpf_cnt_val = 1023 */
+@@ -977,7 +1014,8 @@ static void mt798x_phy_eee(struct phy_de
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+-      __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
++      __phy_modify(phydev, MTK_PHY_LPI_REG_14,
++                   MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+                    FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
+       __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
+@@ -987,7 +1025,8 @@ static void mt798x_phy_eee(struct phy_de
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+                      MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+                      MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+-                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
++                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
++                                0xff));
+ }
+ static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
+@@ -1147,7 +1186,8 @@ static int mt798x_phy_hw_led_on_set(stru
+                                       (index ? 16 : 0), &priv->led_state);
+       if (changed)
+               return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                    MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
++                                    MTK_PHY_LED1_ON_CTRL :
++                                    MTK_PHY_LED0_ON_CTRL,
+                                     MTK_PHY_LED_ON_MASK,
+                                     on ? MTK_PHY_LED_ON_FORCE_ON : 0);
+       else
+@@ -1157,7 +1197,8 @@ static int mt798x_phy_hw_led_on_set(stru
+ static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+                                      bool blinking)
+ {
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
+       struct mtk_socphy_priv *priv = phydev->priv;
+       bool changed;
+@@ -1170,8 +1211,10 @@ static int mt798x_phy_hw_led_blink_set(s
+                             (index ? 16 : 0), &priv->led_state);
+       if (changed)
+               return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                   MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL,
+-                                   blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
++                                   MTK_PHY_LED1_BLINK_CTRL :
++                                   MTK_PHY_LED0_BLINK_CTRL,
++                                   blinking ?
++                                   MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
+       else
+               return 0;
+ }
+@@ -1237,7 +1280,8 @@ static int mt798x_phy_led_hw_is_supporte
+ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+                                        unsigned long *rules)
+ {
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
+       unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+       unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+       struct mtk_socphy_priv *priv = phydev->priv;
+@@ -1258,8 +1302,8 @@ static int mt798x_phy_led_hw_control_get
+       if (blink < 0)
+               return -EIO;
+-      if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
+-                 MTK_PHY_LED_ON_LINKDOWN)) ||
++      if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX |
++                 MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
+           (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
+               set_bit(bit_netdev, &priv->led_state);
+       else
+@@ -1333,17 +1377,23 @@ static int mt798x_phy_led_hw_control_set
+       if (rules & BIT(TRIGGER_NETDEV_RX)) {
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000RX : 0)) :
+                         MTK_PHY_LED_BLINK_RX;
+       }
+       if (rules & BIT(TRIGGER_NETDEV_TX)) {
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000TX : 0)) :
+                         MTK_PHY_LED_BLINK_TX;
+       }
+@@ -1400,7 +1450,8 @@ static int mt7988_phy_fix_leds_polaritie
+       /* Only now setup pinctrl to avoid bogus blinking */
+       pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
+       if (IS_ERR(pinctrl))
+-              dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n");
++              dev_err(&phydev->mdio.bus->dev,
++                      "Failed to setup PHY LED pinctrl\n");
+       return 0;
+ }
diff --git a/target/linux/generic/backport-6.12/722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch b/target/linux/generic/backport-6.12/722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch
new file mode 100644 (file)
index 0000000..1f6f5f5
--- /dev/null
@@ -0,0 +1,40 @@
+From bcbbfb4f62c4ba35783cc617997a2e92d91e3940 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 17 Oct 2024 11:22:13 +0800
+Subject: [PATCH 03/20] net: phy: mediatek-ge-soc: Propagate error code
+ correctly in cal_cycle()
+
+This patch propagates error code correctly in cal_cycle()
+and improve with FIELD_GET().
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/net/phy/mediatek-ge-soc.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -110,7 +110,7 @@
+ #define   MTK_PHY_CR_TX_AMP_OFFSET_D_MASK     GENMASK(6, 0)
+ #define MTK_PHY_RG_AD_CAL_COMP                        0x17a
+-#define   MTK_PHY_AD_CAL_COMP_OUT_SHIFT               (8)
++#define   MTK_PHY_AD_CAL_COMP_OUT_MASK                GENMASK(8, 8)
+ #define MTK_PHY_RG_AD_CAL_CLK                 0x17b
+ #define   MTK_PHY_DA_CAL_CLK                  BIT(0)
+@@ -351,8 +351,10 @@ static int cal_cycle(struct phy_device *
+       phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+                          MTK_PHY_DA_CALIN_FLAG);
+-      ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
+-                         MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
++      ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP);
++      if (ret < 0)
++              return ret;
++      ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);
+       phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+       return ret;
diff --git a/target/linux/generic/backport-6.12/723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch b/target/linux/generic/backport-6.12/723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch
new file mode 100644 (file)
index 0000000..7161ffe
--- /dev/null
@@ -0,0 +1,3565 @@
+From e062f073dc0df4fcd338043cb0b69b6bcd31e4af Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Sat, 9 Nov 2024 00:34:51 +0800
+Subject: [PATCH 04/20] net: phy: mediatek: Re-organize MediaTek ethernet phy
+ drivers
+
+Re-organize MediaTek ethernet phy driver files and get ready to integrate
+some common functions and add new 2.5G phy driver.
+mtk-ge.c: MT7530 Gphy on MT7621 & MT7531 Gphy
+mtk-ge-soc.c: Built-in Gphy on MT7981 & Built-in switch Gphy on MT7988
+mtk-2p5ge.c: Planned for built-in 2.5G phy on MT7988
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ MAINTAINERS                                   |  4 ++--
+ drivers/net/phy/Kconfig                       | 17 +-------------
+ drivers/net/phy/Makefile                      |  3 +--
+ drivers/net/phy/mediatek/Kconfig              | 22 +++++++++++++++++++
+ drivers/net/phy/mediatek/Makefile             |  3 +++
+ .../mtk-ge-soc.c}                             |  0
+ .../phy/{mediatek-ge.c => mediatek/mtk-ge.c}  |  0
+ 7 files changed, 29 insertions(+), 20 deletions(-)
+ create mode 100644 drivers/net/phy/mediatek/Kconfig
+ create mode 100644 drivers/net/phy/mediatek/Makefile
+ rename drivers/net/phy/{mediatek-ge-soc.c => mediatek/mtk-ge-soc.c} (100%)
+ rename drivers/net/phy/{mediatek-ge.c => mediatek/mtk-ge.c} (100%)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -14427,8 +14427,8 @@ M:     Qingfang Deng <dqfext@gmail.com>
+ M:    SkyLake Huang <SkyLake.Huang@mediatek.com>
+ L:    netdev@vger.kernel.org
+ S:    Maintained
+-F:    drivers/net/phy/mediatek-ge-soc.c
+-F:    drivers/net/phy/mediatek-ge.c
++F:    drivers/net/phy/mediatek/mtk-ge-soc.c
++F:    drivers/net/phy/mediatek/mtk-ge.c
+ F:    drivers/phy/mediatek/phy-mtk-xfi-tphy.c
+ MEDIATEK I2C CONTROLLER DRIVER
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -266,22 +266,7 @@ config MAXLINEAR_GPHY
+         Support for the Maxlinear GPY115, GPY211, GPY212, GPY215,
+         GPY241, GPY245 PHYs.
+-config MEDIATEK_GE_PHY
+-      tristate "MediaTek Gigabit Ethernet PHYs"
+-      help
+-        Supports the MediaTek Gigabit Ethernet PHYs.
+-
+-config MEDIATEK_GE_SOC_PHY
+-      tristate "MediaTek SoC Ethernet PHYs"
+-      depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+-      depends on NVMEM_MTK_EFUSE
+-      help
+-        Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+-
+-        Include support for built-in Ethernet PHYs which are present in
+-        the MT7981 and MT7988 SoCs. These PHYs need calibration data
+-        present in the SoCs efuse and will dynamically calibrate VCM
+-        (common-mode voltage) during startup.
++source "drivers/net/phy/mediatek/Kconfig"
+ config MICREL_PHY
+       tristate "Micrel PHYs"
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -74,8 +74,7 @@ obj-$(CONFIG_MARVELL_PHY)    += marvell.o
+ obj-$(CONFIG_MARVELL_88Q2XXX_PHY)     += marvell-88q2xxx.o
+ obj-$(CONFIG_MARVELL_88X2222_PHY)     += marvell-88x2222.o
+ obj-$(CONFIG_MAXLINEAR_GPHY)  += mxl-gpy.o
+-obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+-obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)     += mediatek-ge-soc.o
++obj-y                         += mediatek/
+ obj-$(CONFIG_MESON_GXL_PHY)   += meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY)      += micrel.o
+--- /dev/null
++++ b/drivers/net/phy/mediatek/Kconfig
+@@ -0,0 +1,22 @@
++# SPDX-License-Identifier: GPL-2.0-only
++config MEDIATEK_GE_PHY
++      tristate "MediaTek Gigabit Ethernet PHYs"
++      help
++        Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
++
++        Non-built-in Gigabit Ethernet PHYs include mt7530/mt7531.
++        You may find mt7530 inside mt7621. This driver shares some
++        common operations with MediaTek SoC built-in Gigabit
++        Ethernet PHYs.
++
++config MEDIATEK_GE_SOC_PHY
++      tristate "MediaTek SoC Ethernet PHYs"
++      depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
++      depends on NVMEM_MTK_EFUSE
++      help
++        Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
++
++        Include support for built-in Ethernet PHYs which are present in
++        the MT7981 and MT7988 SoCs. These PHYs need calibration data
++        present in the SoCs efuse and will dynamically calibrate VCM
++        (common-mode voltage) during startup.
+--- /dev/null
++++ b/drivers/net/phy/mediatek/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_MEDIATEK_GE_PHY)         += mtk-ge.o
++obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)     += mtk-ge-soc.o
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ /dev/null
+@@ -1,1610 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0+
+-#include <linux/bitfield.h>
+-#include <linux/bitmap.h>
+-#include <linux/mfd/syscon.h>
+-#include <linux/module.h>
+-#include <linux/nvmem-consumer.h>
+-#include <linux/pinctrl/consumer.h>
+-#include <linux/phy.h>
+-#include <linux/regmap.h>
+-
+-#define MTK_GPHY_ID_MT7981                    0x03a29461
+-#define MTK_GPHY_ID_MT7988                    0x03a29481
+-
+-#define MTK_EXT_PAGE_ACCESS                   0x1f
+-#define MTK_PHY_PAGE_STANDARD                 0x0000
+-#define MTK_PHY_PAGE_EXTENDED_3                       0x0003
+-
+-#define MTK_PHY_LPI_REG_14                    0x14
+-#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK      GENMASK(8, 0)
+-
+-#define MTK_PHY_LPI_REG_1c                    0x1c
+-#define MTK_PHY_SMI_DET_ON_THRESH_MASK                GENMASK(13, 8)
+-
+-#define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
+-#define MTK_PHY_PAGE_EXTENDED_52B5            0x52b5
+-
+-#define ANALOG_INTERNAL_OPERATION_MAX_US      20
+-#define TXRESERVE_MIN                         0
+-#define TXRESERVE_MAX                         7
+-
+-#define MTK_PHY_ANARG_RG                      0x10
+-#define   MTK_PHY_TCLKOFFSET_MASK             GENMASK(12, 8)
+-
+-/* Registers on MDIO_MMD_VEND1 */
+-#define MTK_PHY_TXVLD_DA_RG                   0x12
+-#define   MTK_PHY_DA_TX_I2MPB_A_GBE_MASK      GENMASK(15, 10)
+-#define   MTK_PHY_DA_TX_I2MPB_A_TBT_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_A2         0x16
+-#define   MTK_PHY_DA_TX_I2MPB_A_HBT_MASK      GENMASK(15, 10)
+-#define   MTK_PHY_DA_TX_I2MPB_A_TST_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_B1         0x17
+-#define   MTK_PHY_DA_TX_I2MPB_B_GBE_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_B_TBT_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_B2         0x18
+-#define   MTK_PHY_DA_TX_I2MPB_B_HBT_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_B_TST_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_C1         0x19
+-#define   MTK_PHY_DA_TX_I2MPB_C_GBE_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_C_TBT_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_C2         0x20
+-#define   MTK_PHY_DA_TX_I2MPB_C_HBT_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_C_TST_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_D1         0x21
+-#define   MTK_PHY_DA_TX_I2MPB_D_GBE_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_D_TBT_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_TX_I2MPB_TEST_MODE_D2         0x22
+-#define   MTK_PHY_DA_TX_I2MPB_D_HBT_MASK      GENMASK(13, 8)
+-#define   MTK_PHY_DA_TX_I2MPB_D_TST_MASK      GENMASK(5, 0)
+-
+-#define MTK_PHY_RXADC_CTRL_RG7                        0xc6
+-#define   MTK_PHY_DA_AD_BUF_BIAS_LP_MASK      GENMASK(9, 8)
+-
+-#define MTK_PHY_RXADC_CTRL_RG9                        0xc8
+-#define   MTK_PHY_DA_RX_PSBN_TBT_MASK         GENMASK(14, 12)
+-#define   MTK_PHY_DA_RX_PSBN_HBT_MASK         GENMASK(10, 8)
+-#define   MTK_PHY_DA_RX_PSBN_GBE_MASK         GENMASK(6, 4)
+-#define   MTK_PHY_DA_RX_PSBN_LP_MASK          GENMASK(2, 0)
+-
+-#define MTK_PHY_LDO_OUTPUT_V                  0xd7
+-
+-#define MTK_PHY_RG_ANA_CAL_RG0                        0xdb
+-#define   MTK_PHY_RG_CAL_CKINV                        BIT(12)
+-#define   MTK_PHY_RG_ANA_CALEN                        BIT(8)
+-#define   MTK_PHY_RG_ZCALEN_A                 BIT(0)
+-
+-#define MTK_PHY_RG_ANA_CAL_RG1                        0xdc
+-#define   MTK_PHY_RG_ZCALEN_B                 BIT(12)
+-#define   MTK_PHY_RG_ZCALEN_C                 BIT(8)
+-#define   MTK_PHY_RG_ZCALEN_D                 BIT(4)
+-#define   MTK_PHY_RG_TXVOS_CALEN              BIT(0)
+-
+-#define MTK_PHY_RG_ANA_CAL_RG5                        0xe0
+-#define   MTK_PHY_RG_REXT_TRIM_MASK           GENMASK(13, 8)
+-
+-#define MTK_PHY_RG_TX_FILTER                  0xfe
+-
+-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120    0x120
+-#define   MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK       GENMASK(12, 8)
+-#define   MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK       GENMASK(4, 0)
+-
+-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122    0x122
+-#define   MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK     GENMASK(7, 0)
+-
+-#define MTK_PHY_RG_TESTMUX_ADC_CTRL           0x144
+-#define   MTK_PHY_RG_TXEN_DIG_MASK            GENMASK(5, 5)
+-
+-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B               0x172
+-#define   MTK_PHY_CR_TX_AMP_OFFSET_A_MASK     GENMASK(13, 8)
+-#define   MTK_PHY_CR_TX_AMP_OFFSET_B_MASK     GENMASK(6, 0)
+-
+-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D               0x173
+-#define   MTK_PHY_CR_TX_AMP_OFFSET_C_MASK     GENMASK(13, 8)
+-#define   MTK_PHY_CR_TX_AMP_OFFSET_D_MASK     GENMASK(6, 0)
+-
+-#define MTK_PHY_RG_AD_CAL_COMP                        0x17a
+-#define   MTK_PHY_AD_CAL_COMP_OUT_MASK                GENMASK(8, 8)
+-
+-#define MTK_PHY_RG_AD_CAL_CLK                 0x17b
+-#define   MTK_PHY_DA_CAL_CLK                  BIT(0)
+-
+-#define MTK_PHY_RG_AD_CALIN                   0x17c
+-#define   MTK_PHY_DA_CALIN_FLAG                       BIT(0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN0_A             0x17d
+-#define   MTK_PHY_DASN_DAC_IN0_A_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN0_B             0x17e
+-#define   MTK_PHY_DASN_DAC_IN0_B_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN0_C             0x17f
+-#define   MTK_PHY_DASN_DAC_IN0_C_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN0_D             0x180
+-#define   MTK_PHY_DASN_DAC_IN0_D_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN1_A             0x181
+-#define   MTK_PHY_DASN_DAC_IN1_A_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN1_B             0x182
+-#define   MTK_PHY_DASN_DAC_IN1_B_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN1_C             0x183
+-#define   MTK_PHY_DASN_DAC_IN1_C_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DASN_DAC_IN1_D             0x184
+-#define   MTK_PHY_DASN_DAC_IN1_D_MASK         GENMASK(9, 0)
+-
+-#define MTK_PHY_RG_DEV1E_REG19b                       0x19b
+-#define   MTK_PHY_BYPASS_DSP_LPI_READY                BIT(8)
+-
+-#define MTK_PHY_RG_LP_IIR2_K1_L                       0x22a
+-#define MTK_PHY_RG_LP_IIR2_K1_U                       0x22b
+-#define MTK_PHY_RG_LP_IIR2_K2_L                       0x22c
+-#define MTK_PHY_RG_LP_IIR2_K2_U                       0x22d
+-#define MTK_PHY_RG_LP_IIR2_K3_L                       0x22e
+-#define MTK_PHY_RG_LP_IIR2_K3_U                       0x22f
+-#define MTK_PHY_RG_LP_IIR2_K4_L                       0x230
+-#define MTK_PHY_RG_LP_IIR2_K4_U                       0x231
+-#define MTK_PHY_RG_LP_IIR2_K5_L                       0x232
+-#define MTK_PHY_RG_LP_IIR2_K5_U                       0x233
+-
+-#define MTK_PHY_RG_DEV1E_REG234                       0x234
+-#define   MTK_PHY_TR_OPEN_LOOP_EN_MASK                GENMASK(0, 0)
+-#define   MTK_PHY_LPF_X_AVERAGE_MASK          GENMASK(7, 4)
+-#define   MTK_PHY_TR_LP_IIR_EEE_EN            BIT(12)
+-
+-#define MTK_PHY_RG_LPF_CNT_VAL                        0x235
+-
+-#define MTK_PHY_RG_DEV1E_REG238                       0x238
+-#define   MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK  GENMASK(8, 0)
+-#define   MTK_PHY_LPI_SLV_SEND_TX_EN          BIT(12)
+-
+-#define MTK_PHY_RG_DEV1E_REG239                       0x239
+-#define   MTK_PHY_LPI_SEND_LOC_TIMER_MASK     GENMASK(8, 0)
+-#define   MTK_PHY_LPI_TXPCS_LOC_RCV           BIT(12)
+-
+-#define MTK_PHY_RG_DEV1E_REG27C                       0x27c
+-#define   MTK_PHY_VGASTATE_FFE_THR_ST1_MASK   GENMASK(12, 8)
+-#define MTK_PHY_RG_DEV1E_REG27D                       0x27d
+-#define   MTK_PHY_VGASTATE_FFE_THR_ST2_MASK   GENMASK(4, 0)
+-
+-#define MTK_PHY_RG_DEV1E_REG2C7                       0x2c7
+-#define   MTK_PHY_MAX_GAIN_MASK                       GENMASK(4, 0)
+-#define   MTK_PHY_MIN_GAIN_MASK                       GENMASK(12, 8)
+-
+-#define MTK_PHY_RG_DEV1E_REG2D1                       0x2d1
+-#define   MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK        GENMASK(7, 0)
+-#define   MTK_PHY_LPI_SKIP_SD_SLV_TR          BIT(8)
+-#define   MTK_PHY_LPI_TR_READY                        BIT(9)
+-#define   MTK_PHY_LPI_VCO_EEE_STG0_EN         BIT(10)
+-
+-#define MTK_PHY_RG_DEV1E_REG323                       0x323
+-#define   MTK_PHY_EEE_WAKE_MAS_INT_DC         BIT(0)
+-#define   MTK_PHY_EEE_WAKE_SLV_INT_DC         BIT(4)
+-
+-#define MTK_PHY_RG_DEV1E_REG324                       0x324
+-#define   MTK_PHY_SMI_DETCNT_MAX_MASK         GENMASK(5, 0)
+-#define   MTK_PHY_SMI_DET_MAX_EN              BIT(8)
+-
+-#define MTK_PHY_RG_DEV1E_REG326                       0x326
+-#define   MTK_PHY_LPI_MODE_SD_ON              BIT(0)
+-#define   MTK_PHY_RESET_RANDUPD_CNT           BIT(1)
+-#define   MTK_PHY_TREC_UPDATE_ENAB_CLR                BIT(2)
+-#define   MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF       BIT(4)
+-#define   MTK_PHY_TR_READY_SKIP_AFE_WAKEUP    BIT(5)
+-
+-#define MTK_PHY_LDO_PUMP_EN_PAIRAB            0x502
+-#define MTK_PHY_LDO_PUMP_EN_PAIRCD            0x503
+-
+-#define MTK_PHY_DA_TX_R50_PAIR_A              0x53d
+-#define MTK_PHY_DA_TX_R50_PAIR_B              0x53e
+-#define MTK_PHY_DA_TX_R50_PAIR_C              0x53f
+-#define MTK_PHY_DA_TX_R50_PAIR_D              0x540
+-
+-/* Registers on MDIO_MMD_VEND2 */
+-#define MTK_PHY_LED0_ON_CTRL                  0x24
+-#define MTK_PHY_LED1_ON_CTRL                  0x26
+-#define   MTK_PHY_LED_ON_MASK                 GENMASK(6, 0)
+-#define   MTK_PHY_LED_ON_LINK1000             BIT(0)
+-#define   MTK_PHY_LED_ON_LINK100              BIT(1)
+-#define   MTK_PHY_LED_ON_LINK10                       BIT(2)
+-#define   MTK_PHY_LED_ON_LINK                 (MTK_PHY_LED_ON_LINK10 |\
+-                                               MTK_PHY_LED_ON_LINK100 |\
+-                                               MTK_PHY_LED_ON_LINK1000)
+-#define   MTK_PHY_LED_ON_LINKDOWN             BIT(3)
+-#define   MTK_PHY_LED_ON_FDX                  BIT(4) /* Full duplex */
+-#define   MTK_PHY_LED_ON_HDX                  BIT(5) /* Half duplex */
+-#define   MTK_PHY_LED_ON_FORCE_ON             BIT(6)
+-#define   MTK_PHY_LED_ON_POLARITY             BIT(14)
+-#define   MTK_PHY_LED_ON_ENABLE                       BIT(15)
+-
+-#define MTK_PHY_LED0_BLINK_CTRL                       0x25
+-#define MTK_PHY_LED1_BLINK_CTRL                       0x27
+-#define   MTK_PHY_LED_BLINK_1000TX            BIT(0)
+-#define   MTK_PHY_LED_BLINK_1000RX            BIT(1)
+-#define   MTK_PHY_LED_BLINK_100TX             BIT(2)
+-#define   MTK_PHY_LED_BLINK_100RX             BIT(3)
+-#define   MTK_PHY_LED_BLINK_10TX              BIT(4)
+-#define   MTK_PHY_LED_BLINK_10RX              BIT(5)
+-#define   MTK_PHY_LED_BLINK_RX                        (MTK_PHY_LED_BLINK_10RX |\
+-                                               MTK_PHY_LED_BLINK_100RX |\
+-                                               MTK_PHY_LED_BLINK_1000RX)
+-#define   MTK_PHY_LED_BLINK_TX                        (MTK_PHY_LED_BLINK_10TX |\
+-                                               MTK_PHY_LED_BLINK_100TX |\
+-                                               MTK_PHY_LED_BLINK_1000TX)
+-#define   MTK_PHY_LED_BLINK_COLLISION         BIT(6)
+-#define   MTK_PHY_LED_BLINK_RX_CRC_ERR                BIT(7)
+-#define   MTK_PHY_LED_BLINK_RX_IDLE_ERR               BIT(8)
+-#define   MTK_PHY_LED_BLINK_FORCE_BLINK               BIT(9)
+-
+-#define MTK_PHY_LED1_DEFAULT_POLARITIES               BIT(1)
+-
+-#define MTK_PHY_RG_BG_RASEL                   0x115
+-#define   MTK_PHY_RG_BG_RASEL_MASK            GENMASK(2, 0)
+-
+-/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */
+-#define RG_GPIO_MISC_TPBANK0                  0x6f0
+-#define   RG_GPIO_MISC_TPBANK0_BOOTMODE               GENMASK(11, 8)
+-
+-/* These macro privides efuse parsing for internal phy. */
+-#define EFS_DA_TX_I2MPB_A(x)                  (((x) >> 0) & GENMASK(5, 0))
+-#define EFS_DA_TX_I2MPB_B(x)                  (((x) >> 6) & GENMASK(5, 0))
+-#define EFS_DA_TX_I2MPB_C(x)                  (((x) >> 12) & GENMASK(5, 0))
+-#define EFS_DA_TX_I2MPB_D(x)                  (((x) >> 18) & GENMASK(5, 0))
+-#define EFS_DA_TX_AMP_OFFSET_A(x)             (((x) >> 24) & GENMASK(5, 0))
+-
+-#define EFS_DA_TX_AMP_OFFSET_B(x)             (((x) >> 0) & GENMASK(5, 0))
+-#define EFS_DA_TX_AMP_OFFSET_C(x)             (((x) >> 6) & GENMASK(5, 0))
+-#define EFS_DA_TX_AMP_OFFSET_D(x)             (((x) >> 12) & GENMASK(5, 0))
+-#define EFS_DA_TX_R50_A(x)                    (((x) >> 18) & GENMASK(5, 0))
+-#define EFS_DA_TX_R50_B(x)                    (((x) >> 24) & GENMASK(5, 0))
+-
+-#define EFS_DA_TX_R50_C(x)                    (((x) >> 0) & GENMASK(5, 0))
+-#define EFS_DA_TX_R50_D(x)                    (((x) >> 6) & GENMASK(5, 0))
+-
+-#define EFS_RG_BG_RASEL(x)                    (((x) >> 4) & GENMASK(2, 0))
+-#define EFS_RG_REXT_TRIM(x)                   (((x) >> 7) & GENMASK(5, 0))
+-
+-enum {
+-      NO_PAIR,
+-      PAIR_A,
+-      PAIR_B,
+-      PAIR_C,
+-      PAIR_D,
+-};
+-
+-enum calibration_mode {
+-      EFUSE_K,
+-      SW_K
+-};
+-
+-enum CAL_ITEM {
+-      REXT,
+-      TX_OFFSET,
+-      TX_AMP,
+-      TX_R50,
+-      TX_VCM
+-};
+-
+-enum CAL_MODE {
+-      EFUSE_M,
+-      SW_M
+-};
+-
+-#define MTK_PHY_LED_STATE_FORCE_ON    0
+-#define MTK_PHY_LED_STATE_FORCE_BLINK 1
+-#define MTK_PHY_LED_STATE_NETDEV      2
+-
+-struct mtk_socphy_priv {
+-      unsigned long           led_state;
+-};
+-
+-struct mtk_socphy_shared {
+-      u32                     boottrap;
+-      struct mtk_socphy_priv  priv[4];
+-};
+-
+-static int mtk_socphy_read_page(struct phy_device *phydev)
+-{
+-      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+-}
+-
+-static int mtk_socphy_write_page(struct phy_device *phydev, int page)
+-{
+-      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+-}
+-
+-/* One calibration cycle consists of:
+- * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
+- *   until AD_CAL_COMP is ready to output calibration result.
+- * 2.Wait until DA_CAL_CLK is available.
+- * 3.Fetch AD_CAL_COMP_OUT.
+- */
+-static int cal_cycle(struct phy_device *phydev, int devad,
+-                   u32 regnum, u16 mask, u16 cal_val)
+-{
+-      int reg_val;
+-      int ret;
+-
+-      phy_modify_mmd(phydev, devad, regnum,
+-                     mask, cal_val);
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+-                       MTK_PHY_DA_CALIN_FLAG);
+-
+-      ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+-                                      MTK_PHY_RG_AD_CAL_CLK, reg_val,
+-                                      reg_val & MTK_PHY_DA_CAL_CLK, 500,
+-                                      ANALOG_INTERNAL_OPERATION_MAX_US,
+-                                      false);
+-      if (ret) {
+-              phydev_err(phydev, "Calibration cycle timeout\n");
+-              return ret;
+-      }
+-
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+-                         MTK_PHY_DA_CALIN_FLAG);
+-      ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP);
+-      if (ret < 0)
+-              return ret;
+-      ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);
+-      phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+-
+-      return ret;
+-}
+-
+-static int rext_fill_result(struct phy_device *phydev, u16 *buf)
+-{
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+-                     MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
+-                     MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
+-
+-      return 0;
+-}
+-
+-static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
+-{
+-      u16 rext_cal_val[2];
+-
+-      rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
+-      rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
+-      rext_fill_result(phydev, rext_cal_val);
+-
+-      return 0;
+-}
+-
+-static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
+-{
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+-                     MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+-                     MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+-                     MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+-                     MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
+-
+-      return 0;
+-}
+-
+-static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
+-{
+-      u16 tx_offset_cal_val[4];
+-
+-      tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
+-      tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
+-      tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
+-      tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
+-
+-      tx_offset_fill_result(phydev, tx_offset_cal_val);
+-
+-      return 0;
+-}
+-
+-static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
+-{
+-      const int vals_9481[16] = { 10, 6, 6, 10,
+-                                  10, 6, 6, 10,
+-                                  10, 6, 6, 10,
+-                                  10, 6, 6, 10 };
+-      const int vals_9461[16] = { 7, 1, 4, 7,
+-                                  7, 1, 4, 7,
+-                                  7, 1, 4, 7,
+-                                  7, 1, 4, 7 };
+-      int bias[16] = {};
+-      int i;
+-
+-      switch (phydev->drv->phy_id) {
+-      case MTK_GPHY_ID_MT7981:
+-              /* We add some calibration to efuse values
+-               * due to board level influence.
+-               * GBE: +7, TBT: +1, HBT: +4, TST: +7
+-               */
+-              memcpy(bias, (const void *)vals_9461, sizeof(bias));
+-              break;
+-      case MTK_GPHY_ID_MT7988:
+-              memcpy(bias, (const void *)vals_9481, sizeof(bias));
+-              break;
+-      }
+-
+-      /* Prevent overflow */
+-      for (i = 0; i < 12; i++) {
+-              if (buf[i >> 2] + bias[i] > 63) {
+-                      buf[i >> 2] = 63;
+-                      bias[i] = 0;
+-              }
+-      }
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+-                     MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
+-                                buf[0] + bias[0]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+-                     MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
+-                                buf[0] + bias[1]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+-                     MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
+-                                buf[0] + bias[2]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+-                     MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
+-                                buf[0] + bias[3]));
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+-                     MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
+-                                buf[1] + bias[4]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+-                     MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
+-                                buf[1] + bias[5]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+-                     MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
+-                                buf[1] + bias[6]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+-                     MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
+-                                buf[1] + bias[7]));
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+-                     MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
+-                                buf[2] + bias[8]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+-                     MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
+-                                buf[2] + bias[9]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+-                     MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
+-                                buf[2] + bias[10]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+-                     MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
+-                                buf[2] + bias[11]));
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+-                     MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
+-                                buf[3] + bias[12]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+-                     MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
+-                                buf[3] + bias[13]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+-                     MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
+-                                buf[3] + bias[14]));
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+-                     MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
+-                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
+-                                buf[3] + bias[15]));
+-
+-      return 0;
+-}
+-
+-static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
+-{
+-      u16 tx_amp_cal_val[4];
+-
+-      tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
+-      tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
+-      tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
+-      tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
+-      tx_amp_fill_result(phydev, tx_amp_cal_val);
+-
+-      return 0;
+-}
+-
+-static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
+-                            u8 txg_calen_x)
+-{
+-      int bias = 0;
+-      u16 reg, val;
+-
+-      if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
+-              bias = -1;
+-
+-      val = clamp_val(bias + tx_r50_cal_val, 0, 63);
+-
+-      switch (txg_calen_x) {
+-      case PAIR_A:
+-              reg = MTK_PHY_DA_TX_R50_PAIR_A;
+-              break;
+-      case PAIR_B:
+-              reg = MTK_PHY_DA_TX_R50_PAIR_B;
+-              break;
+-      case PAIR_C:
+-              reg = MTK_PHY_DA_TX_R50_PAIR_C;
+-              break;
+-      case PAIR_D:
+-              reg = MTK_PHY_DA_TX_R50_PAIR_D;
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
+-
+-      return 0;
+-}
+-
+-static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
+-                          u8 txg_calen_x)
+-{
+-      u16 tx_r50_cal_val;
+-
+-      switch (txg_calen_x) {
+-      case PAIR_A:
+-              tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
+-              break;
+-      case PAIR_B:
+-              tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
+-              break;
+-      case PAIR_C:
+-              tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
+-              break;
+-      case PAIR_D:
+-              tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-      tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
+-
+-      return 0;
+-}
+-
+-static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
+-{
+-      u8 lower_idx, upper_idx, txreserve_val;
+-      u8 lower_ret, upper_ret;
+-      int ret;
+-
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+-                       MTK_PHY_RG_ANA_CALEN);
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+-                         MTK_PHY_RG_CAL_CKINV);
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+-                       MTK_PHY_RG_TXVOS_CALEN);
+-
+-      switch (rg_txreserve_x) {
+-      case PAIR_A:
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN0_A,
+-                                 MTK_PHY_DASN_DAC_IN0_A_MASK);
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN1_A,
+-                                 MTK_PHY_DASN_DAC_IN1_A_MASK);
+-              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                               MTK_PHY_RG_ANA_CAL_RG0,
+-                               MTK_PHY_RG_ZCALEN_A);
+-              break;
+-      case PAIR_B:
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN0_B,
+-                                 MTK_PHY_DASN_DAC_IN0_B_MASK);
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN1_B,
+-                                 MTK_PHY_DASN_DAC_IN1_B_MASK);
+-              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                               MTK_PHY_RG_ANA_CAL_RG1,
+-                               MTK_PHY_RG_ZCALEN_B);
+-              break;
+-      case PAIR_C:
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN0_C,
+-                                 MTK_PHY_DASN_DAC_IN0_C_MASK);
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN1_C,
+-                                 MTK_PHY_DASN_DAC_IN1_C_MASK);
+-              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                               MTK_PHY_RG_ANA_CAL_RG1,
+-                               MTK_PHY_RG_ZCALEN_C);
+-              break;
+-      case PAIR_D:
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN0_D,
+-                                 MTK_PHY_DASN_DAC_IN0_D_MASK);
+-              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                                 MTK_PHY_RG_DASN_DAC_IN1_D,
+-                                 MTK_PHY_DASN_DAC_IN1_D_MASK);
+-              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                               MTK_PHY_RG_ANA_CAL_RG1,
+-                               MTK_PHY_RG_ZCALEN_D);
+-              break;
+-      default:
+-              ret = -EINVAL;
+-              goto restore;
+-      }
+-
+-      lower_idx = TXRESERVE_MIN;
+-      upper_idx = TXRESERVE_MAX;
+-
+-      phydev_dbg(phydev, "Start TX-VCM SW cal.\n");
+-      while ((upper_idx - lower_idx) > 1) {
+-              txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
+-              ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+-                              MTK_PHY_DA_RX_PSBN_TBT_MASK |
+-                              MTK_PHY_DA_RX_PSBN_HBT_MASK |
+-                              MTK_PHY_DA_RX_PSBN_GBE_MASK |
+-                              MTK_PHY_DA_RX_PSBN_LP_MASK,
+-                              txreserve_val << 12 | txreserve_val << 8 |
+-                              txreserve_val << 4 | txreserve_val);
+-              if (ret == 1) {
+-                      upper_idx = txreserve_val;
+-                      upper_ret = ret;
+-              } else if (ret == 0) {
+-                      lower_idx = txreserve_val;
+-                      lower_ret = ret;
+-              } else {
+-                      goto restore;
+-              }
+-      }
+-
+-      if (lower_idx == TXRESERVE_MIN) {
+-              lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+-                                    MTK_PHY_RXADC_CTRL_RG9,
+-                                    MTK_PHY_DA_RX_PSBN_TBT_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_HBT_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_GBE_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_LP_MASK,
+-                                    lower_idx << 12 | lower_idx << 8 |
+-                                    lower_idx << 4 | lower_idx);
+-              ret = lower_ret;
+-      } else if (upper_idx == TXRESERVE_MAX) {
+-              upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+-                                    MTK_PHY_RXADC_CTRL_RG9,
+-                                    MTK_PHY_DA_RX_PSBN_TBT_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_HBT_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_GBE_MASK |
+-                                    MTK_PHY_DA_RX_PSBN_LP_MASK,
+-                                    upper_idx << 12 | upper_idx << 8 |
+-                                    upper_idx << 4 | upper_idx);
+-              ret = upper_ret;
+-      }
+-      if (ret < 0)
+-              goto restore;
+-
+-      /* We calibrate TX-VCM in different logic. Check upper index and then
+-       * lower index. If this calibration is valid, apply lower index's
+-       * result.
+-       */
+-      ret = upper_ret - lower_ret;
+-      if (ret == 1) {
+-              ret = 0;
+-              /* Make sure we use upper_idx in our calibration system */
+-              cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+-                        MTK_PHY_DA_RX_PSBN_TBT_MASK |
+-                        MTK_PHY_DA_RX_PSBN_HBT_MASK |
+-                        MTK_PHY_DA_RX_PSBN_GBE_MASK |
+-                        MTK_PHY_DA_RX_PSBN_LP_MASK,
+-                        upper_idx << 12 | upper_idx << 8 |
+-                        upper_idx << 4 | upper_idx);
+-              phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+-      } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
+-                 lower_ret == 1) {
+-              ret = 0;
+-              cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+-                        MTK_PHY_DA_RX_PSBN_TBT_MASK |
+-                        MTK_PHY_DA_RX_PSBN_HBT_MASK |
+-                        MTK_PHY_DA_RX_PSBN_GBE_MASK |
+-                        MTK_PHY_DA_RX_PSBN_LP_MASK,
+-                        lower_idx << 12 | lower_idx << 8 |
+-                        lower_idx << 4 | lower_idx);
+-              phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n",
+-                          lower_idx);
+-      } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
+-                 lower_ret == 0) {
+-              ret = 0;
+-              phydev_warn(phydev,
+-                          "TX-VCM SW cal result at high margin 0x%x\n",
+-                          upper_idx);
+-      } else {
+-              ret = -EINVAL;
+-      }
+-
+-restore:
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+-                         MTK_PHY_RG_ANA_CALEN);
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+-                         MTK_PHY_RG_TXVOS_CALEN);
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+-                         MTK_PHY_RG_ZCALEN_A);
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+-                         MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
+-                         MTK_PHY_RG_ZCALEN_D);
+-
+-      return ret;
+-}
+-
+-static void mt798x_phy_common_finetune(struct phy_device *phydev)
+-{
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+-      __phy_write(phydev, 0x11, 0xc71);
+-      __phy_write(phydev, 0x12, 0xc);
+-      __phy_write(phydev, 0x10, 0x8fae);
+-
+-      /* EnabRandUpdTrig = 1 */
+-      __phy_write(phydev, 0x11, 0x2f00);
+-      __phy_write(phydev, 0x12, 0xe);
+-      __phy_write(phydev, 0x10, 0x8fb0);
+-
+-      /* NormMseLoThresh = 85 */
+-      __phy_write(phydev, 0x11, 0x55a0);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x83aa);
+-
+-      /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
+-      __phy_write(phydev, 0x11, 0x240);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9680);
+-
+-      /* TrFreeze = 0 (mt7988 default) */
+-      __phy_write(phydev, 0x11, 0x0);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9686);
+-
+-      /* SSTrKp100 = 5 */
+-      /* SSTrKf100 = 6 */
+-      /* SSTrKp1000Mas = 5 */
+-      /* SSTrKf1000Mas = 6 */
+-      /* SSTrKp1000Slv = 5 */
+-      /* SSTrKf1000Slv = 6 */
+-      __phy_write(phydev, 0x11, 0xbaef);
+-      __phy_write(phydev, 0x12, 0x2e);
+-      __phy_write(phydev, 0x10, 0x968c);
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-}
+-
+-static void mt7981_phy_finetune(struct phy_device *phydev)
+-{
+-      u16 val[8] = { 0x01ce, 0x01c1,
+-                     0x020f, 0x0202,
+-                     0x03d0, 0x03c0,
+-                     0x0013, 0x0005 };
+-      int i, k;
+-
+-      /* 100M eye finetune:
+-       * Keep middle level of TX MLT3 shapper as default.
+-       * Only change TX MLT3 overshoot level here.
+-       */
+-      for (k = 0, i = 1; i < 12; i++) {
+-              if (i % 3 == 0)
+-                      continue;
+-              phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
+-      }
+-
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* ResetSyncOffset = 6 */
+-      __phy_write(phydev, 0x11, 0x600);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8fc0);
+-
+-      /* VgaDecRate = 1 */
+-      __phy_write(phydev, 0x11, 0x4c2a);
+-      __phy_write(phydev, 0x12, 0x3e);
+-      __phy_write(phydev, 0x10, 0x8fa4);
+-
+-      /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
+-       * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
+-       */
+-      __phy_write(phydev, 0x11, 0xd10a);
+-      __phy_write(phydev, 0x12, 0x34);
+-      __phy_write(phydev, 0x10, 0x8f82);
+-
+-      /* VcoSlicerThreshBitsHigh */
+-      __phy_write(phydev, 0x11, 0x5555);
+-      __phy_write(phydev, 0x12, 0x55);
+-      __phy_write(phydev, 0x10, 0x8ec0);
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-
+-      /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+-                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+-                     MTK_PHY_LPF_X_AVERAGE_MASK,
+-                     BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
+-
+-      /* rg_tr_lpf_cnt_val = 512 */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
+-
+-      /* IIR2 related */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
+-
+-      /* FFE peaking */
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
+-                     MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
+-                     MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
+-
+-      /* Disable LDO pump */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
+-      /* Adjust LDO output voltage */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
+-}
+-
+-static void mt7988_phy_finetune(struct phy_device *phydev)
+-{
+-      u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
+-                      0x020d, 0x0206, 0x0384, 0x03d0,
+-                      0x03c6, 0x030a, 0x0011, 0x0005 };
+-      int i;
+-
+-      /* Set default MLT3 shaper first */
+-      for (i = 0; i < 12; i++)
+-              phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
+-
+-      /* TCT finetune */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
+-
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* ResetSyncOffset = 5 */
+-      __phy_write(phydev, 0x11, 0x500);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8fc0);
+-
+-      /* VgaDecRate is 1 at default on mt7988 */
+-
+-      /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
+-       * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
+-       */
+-      __phy_write(phydev, 0x11, 0xb90a);
+-      __phy_write(phydev, 0x12, 0x6f);
+-      __phy_write(phydev, 0x10, 0x8f82);
+-
+-      /* RemAckCntLimitCtrl = 1 */
+-      __phy_write(phydev, 0x11, 0xfbba);
+-      __phy_write(phydev, 0x12, 0xc3);
+-      __phy_write(phydev, 0x10, 0x87f8);
+-
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-
+-      /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+-                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+-                     MTK_PHY_LPF_X_AVERAGE_MASK,
+-                     BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
+-
+-      /* rg_tr_lpf_cnt_val = 1023 */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff);
+-}
+-
+-static void mt798x_phy_eee(struct phy_device *phydev)
+-{
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+-                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
+-                     MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
+-                     MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
+-                     FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
+-                     FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+-                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+-                     MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+-                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+-                                0xff));
+-
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                         MTK_PHY_RG_TESTMUX_ADC_CTRL,
+-                         MTK_PHY_RG_TXEN_DIG_MASK);
+-
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                       MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
+-
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+-                         MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
+-                     MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
+-                     MTK_PHY_LPI_SLV_SEND_TX_EN,
+-                     FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
+-
+-      /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
+-                         MTK_PHY_LPI_TXPCS_LOC_RCV);
+-
+-      /* This also fixes some IoT issues, such as CH340 */
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
+-                     MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
+-                     FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
+-                     FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
+-                     MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+-                     FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+-                                0x33) |
+-                     MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
+-                     MTK_PHY_LPI_VCO_EEE_STG0_EN);
+-
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
+-                       MTK_PHY_EEE_WAKE_MAS_INT_DC |
+-                       MTK_PHY_EEE_WAKE_SLV_INT_DC);
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
+-                     MTK_PHY_SMI_DETCNT_MAX_MASK,
+-                     FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
+-                     MTK_PHY_SMI_DET_MAX_EN);
+-
+-      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
+-                       MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
+-                       MTK_PHY_TREC_UPDATE_ENAB_CLR |
+-                       MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
+-                       MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
+-
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* Regsigdet_sel_1000 = 0 */
+-      __phy_write(phydev, 0x11, 0xb);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9690);
+-
+-      /* REG_EEE_st2TrKf1000 = 2 */
+-      __phy_write(phydev, 0x11, 0x114f);
+-      __phy_write(phydev, 0x12, 0x2);
+-      __phy_write(phydev, 0x10, 0x969a);
+-
+-      /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
+-      __phy_write(phydev, 0x11, 0x3028);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x969e);
+-
+-      /* RegEEE_slv_wake_int_timer_tar = 8 */
+-      __phy_write(phydev, 0x11, 0x5010);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96a0);
+-
+-      /* RegEEE_trfreeze_timer2 = 586 */
+-      __phy_write(phydev, 0x11, 0x24a);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96a8);
+-
+-      /* RegEEE100Stg1_tar = 16 */
+-      __phy_write(phydev, 0x11, 0x3210);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96b8);
+-
+-      /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
+-      __phy_write(phydev, 0x11, 0x1463);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96ca);
+-
+-      /* DfeTailEnableVgaThresh1000 = 27 */
+-      __phy_write(phydev, 0x11, 0x36);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8f80);
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+-      __phy_modify(phydev, MTK_PHY_LPI_REG_14,
+-                   MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+-                   FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
+-
+-      __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
+-                   FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+-                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+-                     MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+-                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+-                                0xff));
+-}
+-
+-static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
+-                u8 start_pair, u8 end_pair)
+-{
+-      u8 pair_n;
+-      int ret;
+-
+-      for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+-              /* TX_OFFSET & TX_AMP have no SW calibration. */
+-              switch (cal_item) {
+-              case TX_VCM:
+-                      ret = tx_vcm_cal_sw(phydev, pair_n);
+-                      break;
+-              default:
+-                      return -EINVAL;
+-              }
+-              if (ret)
+-                      return ret;
+-      }
+-      return 0;
+-}
+-
+-static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
+-                   u8 start_pair, u8 end_pair, u32 *buf)
+-{
+-      u8 pair_n;
+-      int ret;
+-
+-      for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+-              /* TX_VCM has no efuse calibration. */
+-              switch (cal_item) {
+-              case REXT:
+-                      ret = rext_cal_efuse(phydev, buf);
+-                      break;
+-              case TX_OFFSET:
+-                      ret = tx_offset_cal_efuse(phydev, buf);
+-                      break;
+-              case TX_AMP:
+-                      ret = tx_amp_cal_efuse(phydev, buf);
+-                      break;
+-              case TX_R50:
+-                      ret = tx_r50_cal_efuse(phydev, buf, pair_n);
+-                      break;
+-              default:
+-                      return -EINVAL;
+-              }
+-              if (ret)
+-                      return ret;
+-      }
+-
+-      return 0;
+-}
+-
+-static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
+-                   enum CAL_MODE cal_mode, u8 start_pair,
+-                   u8 end_pair, u32 *buf)
+-{
+-      int ret;
+-
+-      switch (cal_mode) {
+-      case EFUSE_M:
+-              ret = cal_efuse(phydev, cal_item, start_pair,
+-                              end_pair, buf);
+-              break;
+-      case SW_M:
+-              ret = cal_sw(phydev, cal_item, start_pair, end_pair);
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-
+-      if (ret) {
+-              phydev_err(phydev, "cal %d failed\n", cal_item);
+-              return -EIO;
+-      }
+-
+-      return 0;
+-}
+-
+-static int mt798x_phy_calibration(struct phy_device *phydev)
+-{
+-      struct nvmem_cell *cell;
+-      int ret = 0;
+-      size_t len;
+-      u32 *buf;
+-
+-      cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
+-      if (IS_ERR(cell)) {
+-              if (PTR_ERR(cell) == -EPROBE_DEFER)
+-                      return PTR_ERR(cell);
+-              return 0;
+-      }
+-
+-      buf = (u32 *)nvmem_cell_read(cell, &len);
+-      if (IS_ERR(buf))
+-              return PTR_ERR(buf);
+-      nvmem_cell_put(cell);
+-
+-      if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
+-              phydev_err(phydev, "invalid efuse data\n");
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+-      if (ret)
+-              goto out;
+-      ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+-      if (ret)
+-              goto out;
+-      ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+-      if (ret)
+-              goto out;
+-      ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
+-      if (ret)
+-              goto out;
+-      ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
+-      if (ret)
+-              goto out;
+-
+-out:
+-      kfree(buf);
+-      return ret;
+-}
+-
+-static int mt798x_phy_config_init(struct phy_device *phydev)
+-{
+-      switch (phydev->drv->phy_id) {
+-      case MTK_GPHY_ID_MT7981:
+-              mt7981_phy_finetune(phydev);
+-              break;
+-      case MTK_GPHY_ID_MT7988:
+-              mt7988_phy_finetune(phydev);
+-              break;
+-      }
+-
+-      mt798x_phy_common_finetune(phydev);
+-      mt798x_phy_eee(phydev);
+-
+-      return mt798x_phy_calibration(phydev);
+-}
+-
+-static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+-                                  bool on)
+-{
+-      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      bool changed;
+-
+-      if (on)
+-              changed = !test_and_set_bit(bit_on, &priv->led_state);
+-      else
+-              changed = !!test_and_clear_bit(bit_on, &priv->led_state);
+-
+-      changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
+-                                      (index ? 16 : 0), &priv->led_state);
+-      if (changed)
+-              return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                    MTK_PHY_LED1_ON_CTRL :
+-                                    MTK_PHY_LED0_ON_CTRL,
+-                                    MTK_PHY_LED_ON_MASK,
+-                                    on ? MTK_PHY_LED_ON_FORCE_ON : 0);
+-      else
+-              return 0;
+-}
+-
+-static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+-                                     bool blinking)
+-{
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+-                               (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      bool changed;
+-
+-      if (blinking)
+-              changed = !test_and_set_bit(bit_blink, &priv->led_state);
+-      else
+-              changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
+-
+-      changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
+-                            (index ? 16 : 0), &priv->led_state);
+-      if (changed)
+-              return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                   MTK_PHY_LED1_BLINK_CTRL :
+-                                   MTK_PHY_LED0_BLINK_CTRL,
+-                                   blinking ?
+-                                   MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
+-      else
+-              return 0;
+-}
+-
+-static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
+-                                  unsigned long *delay_on,
+-                                  unsigned long *delay_off)
+-{
+-      bool blinking = false;
+-      int err = 0;
+-
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
+-              blinking = true;
+-              *delay_on = 50;
+-              *delay_off = 50;
+-      }
+-
+-      err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
+-      if (err)
+-              return err;
+-
+-      return mt798x_phy_hw_led_on_set(phydev, index, false);
+-}
+-
+-static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
+-                                       u8 index, enum led_brightness value)
+-{
+-      int err;
+-
+-      err = mt798x_phy_hw_led_blink_set(phydev, index, false);
+-      if (err)
+-              return err;
+-
+-      return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
+-}
+-
+-static const unsigned long supported_triggers =
+-      BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
+-      BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
+-      BIT(TRIGGER_NETDEV_LINK)        |
+-      BIT(TRIGGER_NETDEV_LINK_10)     |
+-      BIT(TRIGGER_NETDEV_LINK_100)    |
+-      BIT(TRIGGER_NETDEV_LINK_1000)   |
+-      BIT(TRIGGER_NETDEV_RX)          |
+-      BIT(TRIGGER_NETDEV_TX);
+-
+-static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+-                                        unsigned long rules)
+-{
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      /* All combinations of the supported triggers are allowed */
+-      if (rules & ~supported_triggers)
+-              return -EOPNOTSUPP;
+-
+-      return 0;
+-};
+-
+-static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+-                                       unsigned long *rules)
+-{
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+-                               (index ? 16 : 0);
+-      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+-      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      int on, blink;
+-
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+-                        index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
+-
+-      if (on < 0)
+-              return -EIO;
+-
+-      blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+-                           index ? MTK_PHY_LED1_BLINK_CTRL :
+-                                   MTK_PHY_LED0_BLINK_CTRL);
+-      if (blink < 0)
+-              return -EIO;
+-
+-      if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX |
+-                 MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
+-          (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
+-              set_bit(bit_netdev, &priv->led_state);
+-      else
+-              clear_bit(bit_netdev, &priv->led_state);
+-
+-      if (on & MTK_PHY_LED_ON_FORCE_ON)
+-              set_bit(bit_on, &priv->led_state);
+-      else
+-              clear_bit(bit_on, &priv->led_state);
+-
+-      if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
+-              set_bit(bit_blink, &priv->led_state);
+-      else
+-              clear_bit(bit_blink, &priv->led_state);
+-
+-      if (!rules)
+-              return 0;
+-
+-      if (on & MTK_PHY_LED_ON_LINK)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK);
+-
+-      if (on & MTK_PHY_LED_ON_LINK10)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+-
+-      if (on & MTK_PHY_LED_ON_LINK100)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+-
+-      if (on & MTK_PHY_LED_ON_LINK1000)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+-
+-      if (on & MTK_PHY_LED_ON_FDX)
+-              *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
+-
+-      if (on & MTK_PHY_LED_ON_HDX)
+-              *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
+-
+-      if (blink & MTK_PHY_LED_BLINK_RX)
+-              *rules |= BIT(TRIGGER_NETDEV_RX);
+-
+-      if (blink & MTK_PHY_LED_BLINK_TX)
+-              *rules |= BIT(TRIGGER_NETDEV_TX);
+-
+-      return 0;
+-};
+-
+-static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+-                                       unsigned long rules)
+-{
+-      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      u16 on = 0, blink = 0;
+-      int ret;
+-
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
+-              on |= MTK_PHY_LED_ON_FDX;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
+-              on |= MTK_PHY_LED_ON_HDX;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK10;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK100;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK1000;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_RX)) {
+-              blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000RX : 0)) :
+-                        MTK_PHY_LED_BLINK_RX;
+-      }
+-
+-      if (rules & BIT(TRIGGER_NETDEV_TX)) {
+-              blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000TX : 0)) :
+-                        MTK_PHY_LED_BLINK_TX;
+-      }
+-
+-      if (blink || on)
+-              set_bit(bit_netdev, &priv->led_state);
+-      else
+-              clear_bit(bit_netdev, &priv->led_state);
+-
+-      ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                              MTK_PHY_LED1_ON_CTRL :
+-                              MTK_PHY_LED0_ON_CTRL,
+-                           MTK_PHY_LED_ON_FDX     |
+-                           MTK_PHY_LED_ON_HDX     |
+-                           MTK_PHY_LED_ON_LINK,
+-                           on);
+-
+-      if (ret)
+-              return ret;
+-
+-      return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                              MTK_PHY_LED1_BLINK_CTRL :
+-                              MTK_PHY_LED0_BLINK_CTRL, blink);
+-};
+-
+-static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
+-{
+-      struct mtk_socphy_shared *priv = phydev->shared->priv;
+-      u32 polarities;
+-
+-      if (led_num == 0)
+-              polarities = ~(priv->boottrap);
+-      else
+-              polarities = MTK_PHY_LED1_DEFAULT_POLARITIES;
+-
+-      if (polarities & BIT(phydev->mdio.addr))
+-              return true;
+-
+-      return false;
+-}
+-
+-static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev)
+-{
+-      struct pinctrl *pinctrl;
+-      int index;
+-
+-      /* Setup LED polarity according to bootstrap use of LED pins */
+-      for (index = 0; index < 2; ++index)
+-              phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                              MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
+-                             MTK_PHY_LED_ON_POLARITY,
+-                             mt7988_phy_led_get_polarity(phydev, index) ?
+-                              MTK_PHY_LED_ON_POLARITY : 0);
+-
+-      /* Only now setup pinctrl to avoid bogus blinking */
+-      pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
+-      if (IS_ERR(pinctrl))
+-              dev_err(&phydev->mdio.bus->dev,
+-                      "Failed to setup PHY LED pinctrl\n");
+-
+-      return 0;
+-}
+-
+-static int mt7988_phy_probe_shared(struct phy_device *phydev)
+-{
+-      struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
+-      struct mtk_socphy_shared *shared = phydev->shared->priv;
+-      struct regmap *regmap;
+-      u32 reg;
+-      int ret;
+-
+-      /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B,
+-       * LED_C and LED_D respectively. At the same time those pins are used to
+-       * bootstrap configuration of the reference clock source (LED_A),
+-       * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
+-       * In practice this is done using a LED and a resistor pulling the pin
+-       * either to GND or to VIO.
+-       * The detected value at boot time is accessible at run-time using the
+-       * TPBANK0 register located in the gpio base of the pinctrl, in order
+-       * to read it here it needs to be referenced by a phandle called
+-       * 'mediatek,pio' in the MDIO bus hosting the PHY.
+-       * The 4 bits in TPBANK0 are kept as package shared data and are used to
+-       * set LED polarity for each of the LED0.
+-       */
+-      regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio");
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
+-
+-      ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, &reg);
+-      if (ret)
+-              return ret;
+-
+-      shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg);
+-
+-      return 0;
+-}
+-
+-static void mt798x_phy_leds_state_init(struct phy_device *phydev)
+-{
+-      int i;
+-
+-      for (i = 0; i < 2; ++i)
+-              mt798x_phy_led_hw_control_get(phydev, i, NULL);
+-}
+-
+-static int mt7988_phy_probe(struct phy_device *phydev)
+-{
+-      struct mtk_socphy_shared *shared;
+-      struct mtk_socphy_priv *priv;
+-      int err;
+-
+-      if (phydev->mdio.addr > 3)
+-              return -EINVAL;
+-
+-      err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
+-                                  sizeof(struct mtk_socphy_shared));
+-      if (err)
+-              return err;
+-
+-      if (phy_package_probe_once(phydev)) {
+-              err = mt7988_phy_probe_shared(phydev);
+-              if (err)
+-                      return err;
+-      }
+-
+-      shared = phydev->shared->priv;
+-      priv = &shared->priv[phydev->mdio.addr];
+-
+-      phydev->priv = priv;
+-
+-      mt798x_phy_leds_state_init(phydev);
+-
+-      err = mt7988_phy_fix_leds_polarities(phydev);
+-      if (err)
+-              return err;
+-
+-      /* Disable TX power saving at probing to:
+-       * 1. Meet common mode compliance test criteria
+-       * 2. Make sure that TX-VCM calibration works fine
+-       */
+-      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+-                     MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
+-
+-      return mt798x_phy_calibration(phydev);
+-}
+-
+-static int mt7981_phy_probe(struct phy_device *phydev)
+-{
+-      struct mtk_socphy_priv *priv;
+-
+-      priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv),
+-                          GFP_KERNEL);
+-      if (!priv)
+-              return -ENOMEM;
+-
+-      phydev->priv = priv;
+-
+-      mt798x_phy_leds_state_init(phydev);
+-
+-      return mt798x_phy_calibration(phydev);
+-}
+-
+-static struct phy_driver mtk_socphy_driver[] = {
+-      {
+-              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+-              .name           = "MediaTek MT7981 PHY",
+-              .config_init    = mt798x_phy_config_init,
+-              .config_intr    = genphy_no_config_intr,
+-              .handle_interrupt = genphy_handle_interrupt_no_ack,
+-              .probe          = mt7981_phy_probe,
+-              .suspend        = genphy_suspend,
+-              .resume         = genphy_resume,
+-              .read_page      = mtk_socphy_read_page,
+-              .write_page     = mtk_socphy_write_page,
+-              .led_blink_set  = mt798x_phy_led_blink_set,
+-              .led_brightness_set = mt798x_phy_led_brightness_set,
+-              .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
+-              .led_hw_control_set = mt798x_phy_led_hw_control_set,
+-              .led_hw_control_get = mt798x_phy_led_hw_control_get,
+-      },
+-      {
+-              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
+-              .name           = "MediaTek MT7988 PHY",
+-              .config_init    = mt798x_phy_config_init,
+-              .config_intr    = genphy_no_config_intr,
+-              .handle_interrupt = genphy_handle_interrupt_no_ack,
+-              .probe          = mt7988_phy_probe,
+-              .suspend        = genphy_suspend,
+-              .resume         = genphy_resume,
+-              .read_page      = mtk_socphy_read_page,
+-              .write_page     = mtk_socphy_write_page,
+-              .led_blink_set  = mt798x_phy_led_blink_set,
+-              .led_brightness_set = mt798x_phy_led_brightness_set,
+-              .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
+-              .led_hw_control_set = mt798x_phy_led_hw_control_set,
+-              .led_hw_control_get = mt798x_phy_led_hw_control_get,
+-      },
+-};
+-
+-module_phy_driver(mtk_socphy_driver);
+-
+-static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+-      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+-      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
+-      { }
+-};
+-
+-MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver");
+-MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+-MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
+-MODULE_LICENSE("GPL");
+-
+-MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);
+--- a/drivers/net/phy/mediatek-ge.c
++++ /dev/null
+@@ -1,111 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0+
+-#include <linux/bitfield.h>
+-#include <linux/module.h>
+-#include <linux/phy.h>
+-
+-#define MTK_EXT_PAGE_ACCESS           0x1f
+-#define MTK_PHY_PAGE_STANDARD         0x0000
+-#define MTK_PHY_PAGE_EXTENDED         0x0001
+-#define MTK_PHY_PAGE_EXTENDED_2               0x0002
+-#define MTK_PHY_PAGE_EXTENDED_3               0x0003
+-#define MTK_PHY_PAGE_EXTENDED_2A30    0x2a30
+-#define MTK_PHY_PAGE_EXTENDED_52B5    0x52b5
+-
+-static int mtk_gephy_read_page(struct phy_device *phydev)
+-{
+-      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+-}
+-
+-static int mtk_gephy_write_page(struct phy_device *phydev, int page)
+-{
+-      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+-}
+-
+-static void mtk_gephy_config_init(struct phy_device *phydev)
+-{
+-      /* Enable HW auto downshift */
+-      phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
+-
+-      /* Increase SlvDPSready time */
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      __phy_write(phydev, 0x10, 0xafae);
+-      __phy_write(phydev, 0x12, 0x2f);
+-      __phy_write(phydev, 0x10, 0x8fae);
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+-
+-      /* Adjust 100_mse_threshold */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
+-
+-      /* Disable mcc */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
+-}
+-
+-static int mt7530_phy_config_init(struct phy_device *phydev)
+-{
+-      mtk_gephy_config_init(phydev);
+-
+-      /* Increase post_update_timer */
+-      phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
+-
+-      return 0;
+-}
+-
+-static int mt7531_phy_config_init(struct phy_device *phydev)
+-{
+-      mtk_gephy_config_init(phydev);
+-
+-      /* PHY link down power saving enable */
+-      phy_set_bits(phydev, 0x17, BIT(4));
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
+-
+-      /* Set TX Pair delay selection */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
+-
+-      return 0;
+-}
+-
+-static struct phy_driver mtk_gephy_driver[] = {
+-      {
+-              PHY_ID_MATCH_EXACT(0x03a29412),
+-              .name           = "MediaTek MT7530 PHY",
+-              .config_init    = mt7530_phy_config_init,
+-              /* Interrupts are handled by the switch, not the PHY
+-               * itself.
+-               */
+-              .config_intr    = genphy_no_config_intr,
+-              .handle_interrupt = genphy_handle_interrupt_no_ack,
+-              .suspend        = genphy_suspend,
+-              .resume         = genphy_resume,
+-              .read_page      = mtk_gephy_read_page,
+-              .write_page     = mtk_gephy_write_page,
+-      },
+-      {
+-              PHY_ID_MATCH_EXACT(0x03a29441),
+-              .name           = "MediaTek MT7531 PHY",
+-              .config_init    = mt7531_phy_config_init,
+-              /* Interrupts are handled by the switch, not the PHY
+-               * itself.
+-               */
+-              .config_intr    = genphy_no_config_intr,
+-              .handle_interrupt = genphy_handle_interrupt_no_ack,
+-              .suspend        = genphy_suspend,
+-              .resume         = genphy_resume,
+-              .read_page      = mtk_gephy_read_page,
+-              .write_page     = mtk_gephy_write_page,
+-      },
+-};
+-
+-module_phy_driver(mtk_gephy_driver);
+-
+-static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
+-      { PHY_ID_MATCH_EXACT(0x03a29441) },
+-      { PHY_ID_MATCH_EXACT(0x03a29412) },
+-      { }
+-};
+-
+-MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
+-MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
+-MODULE_LICENSE("GPL");
+-
+-MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);
+--- /dev/null
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -0,0 +1,1610 @@
++// SPDX-License-Identifier: GPL-2.0+
++#include <linux/bitfield.h>
++#include <linux/bitmap.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/phy.h>
++#include <linux/regmap.h>
++
++#define MTK_GPHY_ID_MT7981                    0x03a29461
++#define MTK_GPHY_ID_MT7988                    0x03a29481
++
++#define MTK_EXT_PAGE_ACCESS                   0x1f
++#define MTK_PHY_PAGE_STANDARD                 0x0000
++#define MTK_PHY_PAGE_EXTENDED_3                       0x0003
++
++#define MTK_PHY_LPI_REG_14                    0x14
++#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK      GENMASK(8, 0)
++
++#define MTK_PHY_LPI_REG_1c                    0x1c
++#define MTK_PHY_SMI_DET_ON_THRESH_MASK                GENMASK(13, 8)
++
++#define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
++#define MTK_PHY_PAGE_EXTENDED_52B5            0x52b5
++
++#define ANALOG_INTERNAL_OPERATION_MAX_US      20
++#define TXRESERVE_MIN                         0
++#define TXRESERVE_MAX                         7
++
++#define MTK_PHY_ANARG_RG                      0x10
++#define   MTK_PHY_TCLKOFFSET_MASK             GENMASK(12, 8)
++
++/* Registers on MDIO_MMD_VEND1 */
++#define MTK_PHY_TXVLD_DA_RG                   0x12
++#define   MTK_PHY_DA_TX_I2MPB_A_GBE_MASK      GENMASK(15, 10)
++#define   MTK_PHY_DA_TX_I2MPB_A_TBT_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_A2         0x16
++#define   MTK_PHY_DA_TX_I2MPB_A_HBT_MASK      GENMASK(15, 10)
++#define   MTK_PHY_DA_TX_I2MPB_A_TST_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_B1         0x17
++#define   MTK_PHY_DA_TX_I2MPB_B_GBE_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_B_TBT_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_B2         0x18
++#define   MTK_PHY_DA_TX_I2MPB_B_HBT_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_B_TST_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_C1         0x19
++#define   MTK_PHY_DA_TX_I2MPB_C_GBE_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_C_TBT_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_C2         0x20
++#define   MTK_PHY_DA_TX_I2MPB_C_HBT_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_C_TST_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_D1         0x21
++#define   MTK_PHY_DA_TX_I2MPB_D_GBE_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_D_TBT_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_TX_I2MPB_TEST_MODE_D2         0x22
++#define   MTK_PHY_DA_TX_I2MPB_D_HBT_MASK      GENMASK(13, 8)
++#define   MTK_PHY_DA_TX_I2MPB_D_TST_MASK      GENMASK(5, 0)
++
++#define MTK_PHY_RXADC_CTRL_RG7                        0xc6
++#define   MTK_PHY_DA_AD_BUF_BIAS_LP_MASK      GENMASK(9, 8)
++
++#define MTK_PHY_RXADC_CTRL_RG9                        0xc8
++#define   MTK_PHY_DA_RX_PSBN_TBT_MASK         GENMASK(14, 12)
++#define   MTK_PHY_DA_RX_PSBN_HBT_MASK         GENMASK(10, 8)
++#define   MTK_PHY_DA_RX_PSBN_GBE_MASK         GENMASK(6, 4)
++#define   MTK_PHY_DA_RX_PSBN_LP_MASK          GENMASK(2, 0)
++
++#define MTK_PHY_LDO_OUTPUT_V                  0xd7
++
++#define MTK_PHY_RG_ANA_CAL_RG0                        0xdb
++#define   MTK_PHY_RG_CAL_CKINV                        BIT(12)
++#define   MTK_PHY_RG_ANA_CALEN                        BIT(8)
++#define   MTK_PHY_RG_ZCALEN_A                 BIT(0)
++
++#define MTK_PHY_RG_ANA_CAL_RG1                        0xdc
++#define   MTK_PHY_RG_ZCALEN_B                 BIT(12)
++#define   MTK_PHY_RG_ZCALEN_C                 BIT(8)
++#define   MTK_PHY_RG_ZCALEN_D                 BIT(4)
++#define   MTK_PHY_RG_TXVOS_CALEN              BIT(0)
++
++#define MTK_PHY_RG_ANA_CAL_RG5                        0xe0
++#define   MTK_PHY_RG_REXT_TRIM_MASK           GENMASK(13, 8)
++
++#define MTK_PHY_RG_TX_FILTER                  0xfe
++
++#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120    0x120
++#define   MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK       GENMASK(12, 8)
++#define   MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK       GENMASK(4, 0)
++
++#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122    0x122
++#define   MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK     GENMASK(7, 0)
++
++#define MTK_PHY_RG_TESTMUX_ADC_CTRL           0x144
++#define   MTK_PHY_RG_TXEN_DIG_MASK            GENMASK(5, 5)
++
++#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B               0x172
++#define   MTK_PHY_CR_TX_AMP_OFFSET_A_MASK     GENMASK(13, 8)
++#define   MTK_PHY_CR_TX_AMP_OFFSET_B_MASK     GENMASK(6, 0)
++
++#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D               0x173
++#define   MTK_PHY_CR_TX_AMP_OFFSET_C_MASK     GENMASK(13, 8)
++#define   MTK_PHY_CR_TX_AMP_OFFSET_D_MASK     GENMASK(6, 0)
++
++#define MTK_PHY_RG_AD_CAL_COMP                        0x17a
++#define   MTK_PHY_AD_CAL_COMP_OUT_MASK                GENMASK(8, 8)
++
++#define MTK_PHY_RG_AD_CAL_CLK                 0x17b
++#define   MTK_PHY_DA_CAL_CLK                  BIT(0)
++
++#define MTK_PHY_RG_AD_CALIN                   0x17c
++#define   MTK_PHY_DA_CALIN_FLAG                       BIT(0)
++
++#define MTK_PHY_RG_DASN_DAC_IN0_A             0x17d
++#define   MTK_PHY_DASN_DAC_IN0_A_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN0_B             0x17e
++#define   MTK_PHY_DASN_DAC_IN0_B_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN0_C             0x17f
++#define   MTK_PHY_DASN_DAC_IN0_C_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN0_D             0x180
++#define   MTK_PHY_DASN_DAC_IN0_D_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN1_A             0x181
++#define   MTK_PHY_DASN_DAC_IN1_A_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN1_B             0x182
++#define   MTK_PHY_DASN_DAC_IN1_B_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN1_C             0x183
++#define   MTK_PHY_DASN_DAC_IN1_C_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DASN_DAC_IN1_D             0x184
++#define   MTK_PHY_DASN_DAC_IN1_D_MASK         GENMASK(9, 0)
++
++#define MTK_PHY_RG_DEV1E_REG19b                       0x19b
++#define   MTK_PHY_BYPASS_DSP_LPI_READY                BIT(8)
++
++#define MTK_PHY_RG_LP_IIR2_K1_L                       0x22a
++#define MTK_PHY_RG_LP_IIR2_K1_U                       0x22b
++#define MTK_PHY_RG_LP_IIR2_K2_L                       0x22c
++#define MTK_PHY_RG_LP_IIR2_K2_U                       0x22d
++#define MTK_PHY_RG_LP_IIR2_K3_L                       0x22e
++#define MTK_PHY_RG_LP_IIR2_K3_U                       0x22f
++#define MTK_PHY_RG_LP_IIR2_K4_L                       0x230
++#define MTK_PHY_RG_LP_IIR2_K4_U                       0x231
++#define MTK_PHY_RG_LP_IIR2_K5_L                       0x232
++#define MTK_PHY_RG_LP_IIR2_K5_U                       0x233
++
++#define MTK_PHY_RG_DEV1E_REG234                       0x234
++#define   MTK_PHY_TR_OPEN_LOOP_EN_MASK                GENMASK(0, 0)
++#define   MTK_PHY_LPF_X_AVERAGE_MASK          GENMASK(7, 4)
++#define   MTK_PHY_TR_LP_IIR_EEE_EN            BIT(12)
++
++#define MTK_PHY_RG_LPF_CNT_VAL                        0x235
++
++#define MTK_PHY_RG_DEV1E_REG238                       0x238
++#define   MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK  GENMASK(8, 0)
++#define   MTK_PHY_LPI_SLV_SEND_TX_EN          BIT(12)
++
++#define MTK_PHY_RG_DEV1E_REG239                       0x239
++#define   MTK_PHY_LPI_SEND_LOC_TIMER_MASK     GENMASK(8, 0)
++#define   MTK_PHY_LPI_TXPCS_LOC_RCV           BIT(12)
++
++#define MTK_PHY_RG_DEV1E_REG27C                       0x27c
++#define   MTK_PHY_VGASTATE_FFE_THR_ST1_MASK   GENMASK(12, 8)
++#define MTK_PHY_RG_DEV1E_REG27D                       0x27d
++#define   MTK_PHY_VGASTATE_FFE_THR_ST2_MASK   GENMASK(4, 0)
++
++#define MTK_PHY_RG_DEV1E_REG2C7                       0x2c7
++#define   MTK_PHY_MAX_GAIN_MASK                       GENMASK(4, 0)
++#define   MTK_PHY_MIN_GAIN_MASK                       GENMASK(12, 8)
++
++#define MTK_PHY_RG_DEV1E_REG2D1                       0x2d1
++#define   MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK        GENMASK(7, 0)
++#define   MTK_PHY_LPI_SKIP_SD_SLV_TR          BIT(8)
++#define   MTK_PHY_LPI_TR_READY                        BIT(9)
++#define   MTK_PHY_LPI_VCO_EEE_STG0_EN         BIT(10)
++
++#define MTK_PHY_RG_DEV1E_REG323                       0x323
++#define   MTK_PHY_EEE_WAKE_MAS_INT_DC         BIT(0)
++#define   MTK_PHY_EEE_WAKE_SLV_INT_DC         BIT(4)
++
++#define MTK_PHY_RG_DEV1E_REG324                       0x324
++#define   MTK_PHY_SMI_DETCNT_MAX_MASK         GENMASK(5, 0)
++#define   MTK_PHY_SMI_DET_MAX_EN              BIT(8)
++
++#define MTK_PHY_RG_DEV1E_REG326                       0x326
++#define   MTK_PHY_LPI_MODE_SD_ON              BIT(0)
++#define   MTK_PHY_RESET_RANDUPD_CNT           BIT(1)
++#define   MTK_PHY_TREC_UPDATE_ENAB_CLR                BIT(2)
++#define   MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF       BIT(4)
++#define   MTK_PHY_TR_READY_SKIP_AFE_WAKEUP    BIT(5)
++
++#define MTK_PHY_LDO_PUMP_EN_PAIRAB            0x502
++#define MTK_PHY_LDO_PUMP_EN_PAIRCD            0x503
++
++#define MTK_PHY_DA_TX_R50_PAIR_A              0x53d
++#define MTK_PHY_DA_TX_R50_PAIR_B              0x53e
++#define MTK_PHY_DA_TX_R50_PAIR_C              0x53f
++#define MTK_PHY_DA_TX_R50_PAIR_D              0x540
++
++/* Registers on MDIO_MMD_VEND2 */
++#define MTK_PHY_LED0_ON_CTRL                  0x24
++#define MTK_PHY_LED1_ON_CTRL                  0x26
++#define   MTK_PHY_LED_ON_MASK                 GENMASK(6, 0)
++#define   MTK_PHY_LED_ON_LINK1000             BIT(0)
++#define   MTK_PHY_LED_ON_LINK100              BIT(1)
++#define   MTK_PHY_LED_ON_LINK10                       BIT(2)
++#define   MTK_PHY_LED_ON_LINK                 (MTK_PHY_LED_ON_LINK10 |\
++                                               MTK_PHY_LED_ON_LINK100 |\
++                                               MTK_PHY_LED_ON_LINK1000)
++#define   MTK_PHY_LED_ON_LINKDOWN             BIT(3)
++#define   MTK_PHY_LED_ON_FDX                  BIT(4) /* Full duplex */
++#define   MTK_PHY_LED_ON_HDX                  BIT(5) /* Half duplex */
++#define   MTK_PHY_LED_ON_FORCE_ON             BIT(6)
++#define   MTK_PHY_LED_ON_POLARITY             BIT(14)
++#define   MTK_PHY_LED_ON_ENABLE                       BIT(15)
++
++#define MTK_PHY_LED0_BLINK_CTRL                       0x25
++#define MTK_PHY_LED1_BLINK_CTRL                       0x27
++#define   MTK_PHY_LED_BLINK_1000TX            BIT(0)
++#define   MTK_PHY_LED_BLINK_1000RX            BIT(1)
++#define   MTK_PHY_LED_BLINK_100TX             BIT(2)
++#define   MTK_PHY_LED_BLINK_100RX             BIT(3)
++#define   MTK_PHY_LED_BLINK_10TX              BIT(4)
++#define   MTK_PHY_LED_BLINK_10RX              BIT(5)
++#define   MTK_PHY_LED_BLINK_RX                        (MTK_PHY_LED_BLINK_10RX |\
++                                               MTK_PHY_LED_BLINK_100RX |\
++                                               MTK_PHY_LED_BLINK_1000RX)
++#define   MTK_PHY_LED_BLINK_TX                        (MTK_PHY_LED_BLINK_10TX |\
++                                               MTK_PHY_LED_BLINK_100TX |\
++                                               MTK_PHY_LED_BLINK_1000TX)
++#define   MTK_PHY_LED_BLINK_COLLISION         BIT(6)
++#define   MTK_PHY_LED_BLINK_RX_CRC_ERR                BIT(7)
++#define   MTK_PHY_LED_BLINK_RX_IDLE_ERR               BIT(8)
++#define   MTK_PHY_LED_BLINK_FORCE_BLINK               BIT(9)
++
++#define MTK_PHY_LED1_DEFAULT_POLARITIES               BIT(1)
++
++#define MTK_PHY_RG_BG_RASEL                   0x115
++#define   MTK_PHY_RG_BG_RASEL_MASK            GENMASK(2, 0)
++
++/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */
++#define RG_GPIO_MISC_TPBANK0                  0x6f0
++#define   RG_GPIO_MISC_TPBANK0_BOOTMODE               GENMASK(11, 8)
++
++/* These macro privides efuse parsing for internal phy. */
++#define EFS_DA_TX_I2MPB_A(x)                  (((x) >> 0) & GENMASK(5, 0))
++#define EFS_DA_TX_I2MPB_B(x)                  (((x) >> 6) & GENMASK(5, 0))
++#define EFS_DA_TX_I2MPB_C(x)                  (((x) >> 12) & GENMASK(5, 0))
++#define EFS_DA_TX_I2MPB_D(x)                  (((x) >> 18) & GENMASK(5, 0))
++#define EFS_DA_TX_AMP_OFFSET_A(x)             (((x) >> 24) & GENMASK(5, 0))
++
++#define EFS_DA_TX_AMP_OFFSET_B(x)             (((x) >> 0) & GENMASK(5, 0))
++#define EFS_DA_TX_AMP_OFFSET_C(x)             (((x) >> 6) & GENMASK(5, 0))
++#define EFS_DA_TX_AMP_OFFSET_D(x)             (((x) >> 12) & GENMASK(5, 0))
++#define EFS_DA_TX_R50_A(x)                    (((x) >> 18) & GENMASK(5, 0))
++#define EFS_DA_TX_R50_B(x)                    (((x) >> 24) & GENMASK(5, 0))
++
++#define EFS_DA_TX_R50_C(x)                    (((x) >> 0) & GENMASK(5, 0))
++#define EFS_DA_TX_R50_D(x)                    (((x) >> 6) & GENMASK(5, 0))
++
++#define EFS_RG_BG_RASEL(x)                    (((x) >> 4) & GENMASK(2, 0))
++#define EFS_RG_REXT_TRIM(x)                   (((x) >> 7) & GENMASK(5, 0))
++
++enum {
++      NO_PAIR,
++      PAIR_A,
++      PAIR_B,
++      PAIR_C,
++      PAIR_D,
++};
++
++enum calibration_mode {
++      EFUSE_K,
++      SW_K
++};
++
++enum CAL_ITEM {
++      REXT,
++      TX_OFFSET,
++      TX_AMP,
++      TX_R50,
++      TX_VCM
++};
++
++enum CAL_MODE {
++      EFUSE_M,
++      SW_M
++};
++
++#define MTK_PHY_LED_STATE_FORCE_ON    0
++#define MTK_PHY_LED_STATE_FORCE_BLINK 1
++#define MTK_PHY_LED_STATE_NETDEV      2
++
++struct mtk_socphy_priv {
++      unsigned long           led_state;
++};
++
++struct mtk_socphy_shared {
++      u32                     boottrap;
++      struct mtk_socphy_priv  priv[4];
++};
++
++static int mtk_socphy_read_page(struct phy_device *phydev)
++{
++      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
++}
++
++static int mtk_socphy_write_page(struct phy_device *phydev, int page)
++{
++      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
++}
++
++/* One calibration cycle consists of:
++ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
++ *   until AD_CAL_COMP is ready to output calibration result.
++ * 2.Wait until DA_CAL_CLK is available.
++ * 3.Fetch AD_CAL_COMP_OUT.
++ */
++static int cal_cycle(struct phy_device *phydev, int devad,
++                   u32 regnum, u16 mask, u16 cal_val)
++{
++      int reg_val;
++      int ret;
++
++      phy_modify_mmd(phydev, devad, regnum,
++                     mask, cal_val);
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
++                       MTK_PHY_DA_CALIN_FLAG);
++
++      ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
++                                      MTK_PHY_RG_AD_CAL_CLK, reg_val,
++                                      reg_val & MTK_PHY_DA_CAL_CLK, 500,
++                                      ANALOG_INTERNAL_OPERATION_MAX_US,
++                                      false);
++      if (ret) {
++              phydev_err(phydev, "Calibration cycle timeout\n");
++              return ret;
++      }
++
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
++                         MTK_PHY_DA_CALIN_FLAG);
++      ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP);
++      if (ret < 0)
++              return ret;
++      ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);
++      phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
++
++      return ret;
++}
++
++static int rext_fill_result(struct phy_device *phydev, u16 *buf)
++{
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
++                     MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
++                     MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
++
++      return 0;
++}
++
++static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
++{
++      u16 rext_cal_val[2];
++
++      rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
++      rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
++      rext_fill_result(phydev, rext_cal_val);
++
++      return 0;
++}
++
++static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
++{
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
++                     MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
++                     MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
++                     MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
++                     MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
++
++      return 0;
++}
++
++static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
++{
++      u16 tx_offset_cal_val[4];
++
++      tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
++      tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
++      tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
++      tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
++
++      tx_offset_fill_result(phydev, tx_offset_cal_val);
++
++      return 0;
++}
++
++static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
++{
++      const int vals_9481[16] = { 10, 6, 6, 10,
++                                  10, 6, 6, 10,
++                                  10, 6, 6, 10,
++                                  10, 6, 6, 10 };
++      const int vals_9461[16] = { 7, 1, 4, 7,
++                                  7, 1, 4, 7,
++                                  7, 1, 4, 7,
++                                  7, 1, 4, 7 };
++      int bias[16] = {};
++      int i;
++
++      switch (phydev->drv->phy_id) {
++      case MTK_GPHY_ID_MT7981:
++              /* We add some calibration to efuse values
++               * due to board level influence.
++               * GBE: +7, TBT: +1, HBT: +4, TST: +7
++               */
++              memcpy(bias, (const void *)vals_9461, sizeof(bias));
++              break;
++      case MTK_GPHY_ID_MT7988:
++              memcpy(bias, (const void *)vals_9481, sizeof(bias));
++              break;
++      }
++
++      /* Prevent overflow */
++      for (i = 0; i < 12; i++) {
++              if (buf[i >> 2] + bias[i] > 63) {
++                      buf[i >> 2] = 63;
++                      bias[i] = 0;
++              }
++      }
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
++                     MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
++                                buf[0] + bias[0]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
++                     MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
++                                buf[0] + bias[1]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
++                     MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
++                                buf[0] + bias[2]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
++                     MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
++                                buf[0] + bias[3]));
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
++                     MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
++                                buf[1] + bias[4]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
++                     MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
++                                buf[1] + bias[5]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
++                     MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
++                                buf[1] + bias[6]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
++                     MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
++                                buf[1] + bias[7]));
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
++                     MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
++                                buf[2] + bias[8]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
++                     MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
++                                buf[2] + bias[9]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
++                     MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
++                                buf[2] + bias[10]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
++                     MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
++                                buf[2] + bias[11]));
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
++                     MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
++                                buf[3] + bias[12]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
++                     MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
++                                buf[3] + bias[13]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
++                     MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
++                                buf[3] + bias[14]));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
++                     MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
++                     FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
++                                buf[3] + bias[15]));
++
++      return 0;
++}
++
++static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
++{
++      u16 tx_amp_cal_val[4];
++
++      tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
++      tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
++      tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
++      tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
++      tx_amp_fill_result(phydev, tx_amp_cal_val);
++
++      return 0;
++}
++
++static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
++                            u8 txg_calen_x)
++{
++      int bias = 0;
++      u16 reg, val;
++
++      if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
++              bias = -1;
++
++      val = clamp_val(bias + tx_r50_cal_val, 0, 63);
++
++      switch (txg_calen_x) {
++      case PAIR_A:
++              reg = MTK_PHY_DA_TX_R50_PAIR_A;
++              break;
++      case PAIR_B:
++              reg = MTK_PHY_DA_TX_R50_PAIR_B;
++              break;
++      case PAIR_C:
++              reg = MTK_PHY_DA_TX_R50_PAIR_C;
++              break;
++      case PAIR_D:
++              reg = MTK_PHY_DA_TX_R50_PAIR_D;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
++
++      return 0;
++}
++
++static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
++                          u8 txg_calen_x)
++{
++      u16 tx_r50_cal_val;
++
++      switch (txg_calen_x) {
++      case PAIR_A:
++              tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
++              break;
++      case PAIR_B:
++              tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
++              break;
++      case PAIR_C:
++              tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
++              break;
++      case PAIR_D:
++              tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
++              break;
++      default:
++              return -EINVAL;
++      }
++      tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
++
++      return 0;
++}
++
++static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
++{
++      u8 lower_idx, upper_idx, txreserve_val;
++      u8 lower_ret, upper_ret;
++      int ret;
++
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
++                       MTK_PHY_RG_ANA_CALEN);
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
++                         MTK_PHY_RG_CAL_CKINV);
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
++                       MTK_PHY_RG_TXVOS_CALEN);
++
++      switch (rg_txreserve_x) {
++      case PAIR_A:
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN0_A,
++                                 MTK_PHY_DASN_DAC_IN0_A_MASK);
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN1_A,
++                                 MTK_PHY_DASN_DAC_IN1_A_MASK);
++              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
++                               MTK_PHY_RG_ANA_CAL_RG0,
++                               MTK_PHY_RG_ZCALEN_A);
++              break;
++      case PAIR_B:
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN0_B,
++                                 MTK_PHY_DASN_DAC_IN0_B_MASK);
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN1_B,
++                                 MTK_PHY_DASN_DAC_IN1_B_MASK);
++              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
++                               MTK_PHY_RG_ANA_CAL_RG1,
++                               MTK_PHY_RG_ZCALEN_B);
++              break;
++      case PAIR_C:
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN0_C,
++                                 MTK_PHY_DASN_DAC_IN0_C_MASK);
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN1_C,
++                                 MTK_PHY_DASN_DAC_IN1_C_MASK);
++              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
++                               MTK_PHY_RG_ANA_CAL_RG1,
++                               MTK_PHY_RG_ZCALEN_C);
++              break;
++      case PAIR_D:
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN0_D,
++                                 MTK_PHY_DASN_DAC_IN0_D_MASK);
++              phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                                 MTK_PHY_RG_DASN_DAC_IN1_D,
++                                 MTK_PHY_DASN_DAC_IN1_D_MASK);
++              phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
++                               MTK_PHY_RG_ANA_CAL_RG1,
++                               MTK_PHY_RG_ZCALEN_D);
++              break;
++      default:
++              ret = -EINVAL;
++              goto restore;
++      }
++
++      lower_idx = TXRESERVE_MIN;
++      upper_idx = TXRESERVE_MAX;
++
++      phydev_dbg(phydev, "Start TX-VCM SW cal.\n");
++      while ((upper_idx - lower_idx) > 1) {
++              txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
++              ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
++                              MTK_PHY_DA_RX_PSBN_TBT_MASK |
++                              MTK_PHY_DA_RX_PSBN_HBT_MASK |
++                              MTK_PHY_DA_RX_PSBN_GBE_MASK |
++                              MTK_PHY_DA_RX_PSBN_LP_MASK,
++                              txreserve_val << 12 | txreserve_val << 8 |
++                              txreserve_val << 4 | txreserve_val);
++              if (ret == 1) {
++                      upper_idx = txreserve_val;
++                      upper_ret = ret;
++              } else if (ret == 0) {
++                      lower_idx = txreserve_val;
++                      lower_ret = ret;
++              } else {
++                      goto restore;
++              }
++      }
++
++      if (lower_idx == TXRESERVE_MIN) {
++              lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
++                                    MTK_PHY_RXADC_CTRL_RG9,
++                                    MTK_PHY_DA_RX_PSBN_TBT_MASK |
++                                    MTK_PHY_DA_RX_PSBN_HBT_MASK |
++                                    MTK_PHY_DA_RX_PSBN_GBE_MASK |
++                                    MTK_PHY_DA_RX_PSBN_LP_MASK,
++                                    lower_idx << 12 | lower_idx << 8 |
++                                    lower_idx << 4 | lower_idx);
++              ret = lower_ret;
++      } else if (upper_idx == TXRESERVE_MAX) {
++              upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
++                                    MTK_PHY_RXADC_CTRL_RG9,
++                                    MTK_PHY_DA_RX_PSBN_TBT_MASK |
++                                    MTK_PHY_DA_RX_PSBN_HBT_MASK |
++                                    MTK_PHY_DA_RX_PSBN_GBE_MASK |
++                                    MTK_PHY_DA_RX_PSBN_LP_MASK,
++                                    upper_idx << 12 | upper_idx << 8 |
++                                    upper_idx << 4 | upper_idx);
++              ret = upper_ret;
++      }
++      if (ret < 0)
++              goto restore;
++
++      /* We calibrate TX-VCM in different logic. Check upper index and then
++       * lower index. If this calibration is valid, apply lower index's
++       * result.
++       */
++      ret = upper_ret - lower_ret;
++      if (ret == 1) {
++              ret = 0;
++              /* Make sure we use upper_idx in our calibration system */
++              cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
++                        MTK_PHY_DA_RX_PSBN_TBT_MASK |
++                        MTK_PHY_DA_RX_PSBN_HBT_MASK |
++                        MTK_PHY_DA_RX_PSBN_GBE_MASK |
++                        MTK_PHY_DA_RX_PSBN_LP_MASK,
++                        upper_idx << 12 | upper_idx << 8 |
++                        upper_idx << 4 | upper_idx);
++              phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
++      } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
++                 lower_ret == 1) {
++              ret = 0;
++              cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
++                        MTK_PHY_DA_RX_PSBN_TBT_MASK |
++                        MTK_PHY_DA_RX_PSBN_HBT_MASK |
++                        MTK_PHY_DA_RX_PSBN_GBE_MASK |
++                        MTK_PHY_DA_RX_PSBN_LP_MASK,
++                        lower_idx << 12 | lower_idx << 8 |
++                        lower_idx << 4 | lower_idx);
++              phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n",
++                          lower_idx);
++      } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
++                 lower_ret == 0) {
++              ret = 0;
++              phydev_warn(phydev,
++                          "TX-VCM SW cal result at high margin 0x%x\n",
++                          upper_idx);
++      } else {
++              ret = -EINVAL;
++      }
++
++restore:
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
++                         MTK_PHY_RG_ANA_CALEN);
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
++                         MTK_PHY_RG_TXVOS_CALEN);
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
++                         MTK_PHY_RG_ZCALEN_A);
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
++                         MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
++                         MTK_PHY_RG_ZCALEN_D);
++
++      return ret;
++}
++
++static void mt798x_phy_common_finetune(struct phy_device *phydev)
++{
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
++      __phy_write(phydev, 0x11, 0xc71);
++      __phy_write(phydev, 0x12, 0xc);
++      __phy_write(phydev, 0x10, 0x8fae);
++
++      /* EnabRandUpdTrig = 1 */
++      __phy_write(phydev, 0x11, 0x2f00);
++      __phy_write(phydev, 0x12, 0xe);
++      __phy_write(phydev, 0x10, 0x8fb0);
++
++      /* NormMseLoThresh = 85 */
++      __phy_write(phydev, 0x11, 0x55a0);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x83aa);
++
++      /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
++      __phy_write(phydev, 0x11, 0x240);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x9680);
++
++      /* TrFreeze = 0 (mt7988 default) */
++      __phy_write(phydev, 0x11, 0x0);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x9686);
++
++      /* SSTrKp100 = 5 */
++      /* SSTrKf100 = 6 */
++      /* SSTrKp1000Mas = 5 */
++      /* SSTrKf1000Mas = 6 */
++      /* SSTrKp1000Slv = 5 */
++      /* SSTrKf1000Slv = 6 */
++      __phy_write(phydev, 0x11, 0xbaef);
++      __phy_write(phydev, 0x12, 0x2e);
++      __phy_write(phydev, 0x10, 0x968c);
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++}
++
++static void mt7981_phy_finetune(struct phy_device *phydev)
++{
++      u16 val[8] = { 0x01ce, 0x01c1,
++                     0x020f, 0x0202,
++                     0x03d0, 0x03c0,
++                     0x0013, 0x0005 };
++      int i, k;
++
++      /* 100M eye finetune:
++       * Keep middle level of TX MLT3 shapper as default.
++       * Only change TX MLT3 overshoot level here.
++       */
++      for (k = 0, i = 1; i < 12; i++) {
++              if (i % 3 == 0)
++                      continue;
++              phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
++      }
++
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      /* ResetSyncOffset = 6 */
++      __phy_write(phydev, 0x11, 0x600);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x8fc0);
++
++      /* VgaDecRate = 1 */
++      __phy_write(phydev, 0x11, 0x4c2a);
++      __phy_write(phydev, 0x12, 0x3e);
++      __phy_write(phydev, 0x10, 0x8fa4);
++
++      /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
++       * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
++       */
++      __phy_write(phydev, 0x11, 0xd10a);
++      __phy_write(phydev, 0x12, 0x34);
++      __phy_write(phydev, 0x10, 0x8f82);
++
++      /* VcoSlicerThreshBitsHigh */
++      __phy_write(phydev, 0x11, 0x5555);
++      __phy_write(phydev, 0x12, 0x55);
++      __phy_write(phydev, 0x10, 0x8ec0);
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++
++      /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
++                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
++                     MTK_PHY_LPF_X_AVERAGE_MASK,
++                     BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
++
++      /* rg_tr_lpf_cnt_val = 512 */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
++
++      /* IIR2 related */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
++
++      /* FFE peaking */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
++                     MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
++                     MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
++
++      /* Disable LDO pump */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
++      /* Adjust LDO output voltage */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
++}
++
++static void mt7988_phy_finetune(struct phy_device *phydev)
++{
++      u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
++                      0x020d, 0x0206, 0x0384, 0x03d0,
++                      0x03c6, 0x030a, 0x0011, 0x0005 };
++      int i;
++
++      /* Set default MLT3 shaper first */
++      for (i = 0; i < 12; i++)
++              phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
++
++      /* TCT finetune */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
++
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      /* ResetSyncOffset = 5 */
++      __phy_write(phydev, 0x11, 0x500);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x8fc0);
++
++      /* VgaDecRate is 1 at default on mt7988 */
++
++      /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
++       * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
++       */
++      __phy_write(phydev, 0x11, 0xb90a);
++      __phy_write(phydev, 0x12, 0x6f);
++      __phy_write(phydev, 0x10, 0x8f82);
++
++      /* RemAckCntLimitCtrl = 1 */
++      __phy_write(phydev, 0x11, 0xfbba);
++      __phy_write(phydev, 0x12, 0xc3);
++      __phy_write(phydev, 0x10, 0x87f8);
++
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++
++      /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
++                     MTK_PHY_TR_OPEN_LOOP_EN_MASK |
++                     MTK_PHY_LPF_X_AVERAGE_MASK,
++                     BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
++
++      /* rg_tr_lpf_cnt_val = 1023 */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff);
++}
++
++static void mt798x_phy_eee(struct phy_device *phydev)
++{
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
++                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
++                     MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
++                     MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
++                     FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
++                     FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
++                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
++                     MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
++                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
++                                0xff));
++
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                         MTK_PHY_RG_TESTMUX_ADC_CTRL,
++                         MTK_PHY_RG_TXEN_DIG_MASK);
++
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
++                       MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
++
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
++                         MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
++                     MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
++                     MTK_PHY_LPI_SLV_SEND_TX_EN,
++                     FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
++
++      /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
++                         MTK_PHY_LPI_TXPCS_LOC_RCV);
++
++      /* This also fixes some IoT issues, such as CH340 */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
++                     MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
++                     FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
++                     FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
++                     MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
++                     FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
++                                0x33) |
++                     MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
++                     MTK_PHY_LPI_VCO_EEE_STG0_EN);
++
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
++                       MTK_PHY_EEE_WAKE_MAS_INT_DC |
++                       MTK_PHY_EEE_WAKE_SLV_INT_DC);
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
++                     MTK_PHY_SMI_DETCNT_MAX_MASK,
++                     FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
++                     MTK_PHY_SMI_DET_MAX_EN);
++
++      phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
++                       MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
++                       MTK_PHY_TREC_UPDATE_ENAB_CLR |
++                       MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
++                       MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
++
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      /* Regsigdet_sel_1000 = 0 */
++      __phy_write(phydev, 0x11, 0xb);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x9690);
++
++      /* REG_EEE_st2TrKf1000 = 2 */
++      __phy_write(phydev, 0x11, 0x114f);
++      __phy_write(phydev, 0x12, 0x2);
++      __phy_write(phydev, 0x10, 0x969a);
++
++      /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
++      __phy_write(phydev, 0x11, 0x3028);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x969e);
++
++      /* RegEEE_slv_wake_int_timer_tar = 8 */
++      __phy_write(phydev, 0x11, 0x5010);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x96a0);
++
++      /* RegEEE_trfreeze_timer2 = 586 */
++      __phy_write(phydev, 0x11, 0x24a);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x96a8);
++
++      /* RegEEE100Stg1_tar = 16 */
++      __phy_write(phydev, 0x11, 0x3210);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x96b8);
++
++      /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
++      __phy_write(phydev, 0x11, 0x1463);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x96ca);
++
++      /* DfeTailEnableVgaThresh1000 = 27 */
++      __phy_write(phydev, 0x11, 0x36);
++      __phy_write(phydev, 0x12, 0x0);
++      __phy_write(phydev, 0x10, 0x8f80);
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
++      __phy_modify(phydev, MTK_PHY_LPI_REG_14,
++                   MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
++                   FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
++
++      __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
++                   FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
++                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
++                     MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
++                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
++                                0xff));
++}
++
++static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
++                u8 start_pair, u8 end_pair)
++{
++      u8 pair_n;
++      int ret;
++
++      for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
++              /* TX_OFFSET & TX_AMP have no SW calibration. */
++              switch (cal_item) {
++              case TX_VCM:
++                      ret = tx_vcm_cal_sw(phydev, pair_n);
++                      break;
++              default:
++                      return -EINVAL;
++              }
++              if (ret)
++                      return ret;
++      }
++      return 0;
++}
++
++static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
++                   u8 start_pair, u8 end_pair, u32 *buf)
++{
++      u8 pair_n;
++      int ret;
++
++      for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
++              /* TX_VCM has no efuse calibration. */
++              switch (cal_item) {
++              case REXT:
++                      ret = rext_cal_efuse(phydev, buf);
++                      break;
++              case TX_OFFSET:
++                      ret = tx_offset_cal_efuse(phydev, buf);
++                      break;
++              case TX_AMP:
++                      ret = tx_amp_cal_efuse(phydev, buf);
++                      break;
++              case TX_R50:
++                      ret = tx_r50_cal_efuse(phydev, buf, pair_n);
++                      break;
++              default:
++                      return -EINVAL;
++              }
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++}
++
++static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
++                   enum CAL_MODE cal_mode, u8 start_pair,
++                   u8 end_pair, u32 *buf)
++{
++      int ret;
++
++      switch (cal_mode) {
++      case EFUSE_M:
++              ret = cal_efuse(phydev, cal_item, start_pair,
++                              end_pair, buf);
++              break;
++      case SW_M:
++              ret = cal_sw(phydev, cal_item, start_pair, end_pair);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      if (ret) {
++              phydev_err(phydev, "cal %d failed\n", cal_item);
++              return -EIO;
++      }
++
++      return 0;
++}
++
++static int mt798x_phy_calibration(struct phy_device *phydev)
++{
++      struct nvmem_cell *cell;
++      int ret = 0;
++      size_t len;
++      u32 *buf;
++
++      cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
++      if (IS_ERR(cell)) {
++              if (PTR_ERR(cell) == -EPROBE_DEFER)
++                      return PTR_ERR(cell);
++              return 0;
++      }
++
++      buf = (u32 *)nvmem_cell_read(cell, &len);
++      if (IS_ERR(buf))
++              return PTR_ERR(buf);
++      nvmem_cell_put(cell);
++
++      if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
++              phydev_err(phydev, "invalid efuse data\n");
++              ret = -EINVAL;
++              goto out;
++      }
++
++      ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
++      if (ret)
++              goto out;
++      ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
++      if (ret)
++              goto out;
++      ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
++      if (ret)
++              goto out;
++      ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
++      if (ret)
++              goto out;
++      ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
++      if (ret)
++              goto out;
++
++out:
++      kfree(buf);
++      return ret;
++}
++
++static int mt798x_phy_config_init(struct phy_device *phydev)
++{
++      switch (phydev->drv->phy_id) {
++      case MTK_GPHY_ID_MT7981:
++              mt7981_phy_finetune(phydev);
++              break;
++      case MTK_GPHY_ID_MT7988:
++              mt7988_phy_finetune(phydev);
++              break;
++      }
++
++      mt798x_phy_common_finetune(phydev);
++      mt798x_phy_eee(phydev);
++
++      return mt798x_phy_calibration(phydev);
++}
++
++static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
++                                  bool on)
++{
++      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      bool changed;
++
++      if (on)
++              changed = !test_and_set_bit(bit_on, &priv->led_state);
++      else
++              changed = !!test_and_clear_bit(bit_on, &priv->led_state);
++
++      changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
++                                      (index ? 16 : 0), &priv->led_state);
++      if (changed)
++              return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                                    MTK_PHY_LED1_ON_CTRL :
++                                    MTK_PHY_LED0_ON_CTRL,
++                                    MTK_PHY_LED_ON_MASK,
++                                    on ? MTK_PHY_LED_ON_FORCE_ON : 0);
++      else
++              return 0;
++}
++
++static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
++                                     bool blinking)
++{
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      bool changed;
++
++      if (blinking)
++              changed = !test_and_set_bit(bit_blink, &priv->led_state);
++      else
++              changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
++
++      changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
++                            (index ? 16 : 0), &priv->led_state);
++      if (changed)
++              return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
++                                   MTK_PHY_LED1_BLINK_CTRL :
++                                   MTK_PHY_LED0_BLINK_CTRL,
++                                   blinking ?
++                                   MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
++      else
++              return 0;
++}
++
++static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
++                                  unsigned long *delay_on,
++                                  unsigned long *delay_off)
++{
++      bool blinking = false;
++      int err = 0;
++
++      if (index > 1)
++              return -EINVAL;
++
++      if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
++              blinking = true;
++              *delay_on = 50;
++              *delay_off = 50;
++      }
++
++      err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
++      if (err)
++              return err;
++
++      return mt798x_phy_hw_led_on_set(phydev, index, false);
++}
++
++static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
++                                       u8 index, enum led_brightness value)
++{
++      int err;
++
++      err = mt798x_phy_hw_led_blink_set(phydev, index, false);
++      if (err)
++              return err;
++
++      return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
++}
++
++static const unsigned long supported_triggers =
++      BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
++      BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
++      BIT(TRIGGER_NETDEV_LINK)        |
++      BIT(TRIGGER_NETDEV_LINK_10)     |
++      BIT(TRIGGER_NETDEV_LINK_100)    |
++      BIT(TRIGGER_NETDEV_LINK_1000)   |
++      BIT(TRIGGER_NETDEV_RX)          |
++      BIT(TRIGGER_NETDEV_TX);
++
++static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
++                                        unsigned long rules)
++{
++      if (index > 1)
++              return -EINVAL;
++
++      /* All combinations of the supported triggers are allowed */
++      if (rules & ~supported_triggers)
++              return -EOPNOTSUPP;
++
++      return 0;
++};
++
++static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
++                                       unsigned long *rules)
++{
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
++      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
++      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      int on, blink;
++
++      if (index > 1)
++              return -EINVAL;
++
++      on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
++                        index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
++
++      if (on < 0)
++              return -EIO;
++
++      blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
++                           index ? MTK_PHY_LED1_BLINK_CTRL :
++                                   MTK_PHY_LED0_BLINK_CTRL);
++      if (blink < 0)
++              return -EIO;
++
++      if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX |
++                 MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
++          (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
++              set_bit(bit_netdev, &priv->led_state);
++      else
++              clear_bit(bit_netdev, &priv->led_state);
++
++      if (on & MTK_PHY_LED_ON_FORCE_ON)
++              set_bit(bit_on, &priv->led_state);
++      else
++              clear_bit(bit_on, &priv->led_state);
++
++      if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
++              set_bit(bit_blink, &priv->led_state);
++      else
++              clear_bit(bit_blink, &priv->led_state);
++
++      if (!rules)
++              return 0;
++
++      if (on & MTK_PHY_LED_ON_LINK)
++              *rules |= BIT(TRIGGER_NETDEV_LINK);
++
++      if (on & MTK_PHY_LED_ON_LINK10)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_10);
++
++      if (on & MTK_PHY_LED_ON_LINK100)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_100);
++
++      if (on & MTK_PHY_LED_ON_LINK1000)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
++
++      if (on & MTK_PHY_LED_ON_FDX)
++              *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
++
++      if (on & MTK_PHY_LED_ON_HDX)
++              *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
++
++      if (blink & MTK_PHY_LED_BLINK_RX)
++              *rules |= BIT(TRIGGER_NETDEV_RX);
++
++      if (blink & MTK_PHY_LED_BLINK_TX)
++              *rules |= BIT(TRIGGER_NETDEV_TX);
++
++      return 0;
++};
++
++static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
++                                       unsigned long rules)
++{
++      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      u16 on = 0, blink = 0;
++      int ret;
++
++      if (index > 1)
++              return -EINVAL;
++
++      if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
++              on |= MTK_PHY_LED_ON_FDX;
++
++      if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
++              on |= MTK_PHY_LED_ON_HDX;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK10;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK100;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK1000;
++
++      if (rules & BIT(TRIGGER_NETDEV_RX)) {
++              blink |= (on & MTK_PHY_LED_ON_LINK) ?
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000RX : 0)) :
++                        MTK_PHY_LED_BLINK_RX;
++      }
++
++      if (rules & BIT(TRIGGER_NETDEV_TX)) {
++              blink |= (on & MTK_PHY_LED_ON_LINK) ?
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000TX : 0)) :
++                        MTK_PHY_LED_BLINK_TX;
++      }
++
++      if (blink || on)
++              set_bit(bit_netdev, &priv->led_state);
++      else
++              clear_bit(bit_netdev, &priv->led_state);
++
++      ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                              MTK_PHY_LED1_ON_CTRL :
++                              MTK_PHY_LED0_ON_CTRL,
++                           MTK_PHY_LED_ON_FDX     |
++                           MTK_PHY_LED_ON_HDX     |
++                           MTK_PHY_LED_ON_LINK,
++                           on);
++
++      if (ret)
++              return ret;
++
++      return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
++                              MTK_PHY_LED1_BLINK_CTRL :
++                              MTK_PHY_LED0_BLINK_CTRL, blink);
++};
++
++static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
++{
++      struct mtk_socphy_shared *priv = phydev->shared->priv;
++      u32 polarities;
++
++      if (led_num == 0)
++              polarities = ~(priv->boottrap);
++      else
++              polarities = MTK_PHY_LED1_DEFAULT_POLARITIES;
++
++      if (polarities & BIT(phydev->mdio.addr))
++              return true;
++
++      return false;
++}
++
++static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev)
++{
++      struct pinctrl *pinctrl;
++      int index;
++
++      /* Setup LED polarity according to bootstrap use of LED pins */
++      for (index = 0; index < 2; ++index)
++              phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                              MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
++                             MTK_PHY_LED_ON_POLARITY,
++                             mt7988_phy_led_get_polarity(phydev, index) ?
++                              MTK_PHY_LED_ON_POLARITY : 0);
++
++      /* Only now setup pinctrl to avoid bogus blinking */
++      pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
++      if (IS_ERR(pinctrl))
++              dev_err(&phydev->mdio.bus->dev,
++                      "Failed to setup PHY LED pinctrl\n");
++
++      return 0;
++}
++
++static int mt7988_phy_probe_shared(struct phy_device *phydev)
++{
++      struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
++      struct mtk_socphy_shared *shared = phydev->shared->priv;
++      struct regmap *regmap;
++      u32 reg;
++      int ret;
++
++      /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B,
++       * LED_C and LED_D respectively. At the same time those pins are used to
++       * bootstrap configuration of the reference clock source (LED_A),
++       * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
++       * In practice this is done using a LED and a resistor pulling the pin
++       * either to GND or to VIO.
++       * The detected value at boot time is accessible at run-time using the
++       * TPBANK0 register located in the gpio base of the pinctrl, in order
++       * to read it here it needs to be referenced by a phandle called
++       * 'mediatek,pio' in the MDIO bus hosting the PHY.
++       * The 4 bits in TPBANK0 are kept as package shared data and are used to
++       * set LED polarity for each of the LED0.
++       */
++      regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio");
++      if (IS_ERR(regmap))
++              return PTR_ERR(regmap);
++
++      ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, &reg);
++      if (ret)
++              return ret;
++
++      shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg);
++
++      return 0;
++}
++
++static void mt798x_phy_leds_state_init(struct phy_device *phydev)
++{
++      int i;
++
++      for (i = 0; i < 2; ++i)
++              mt798x_phy_led_hw_control_get(phydev, i, NULL);
++}
++
++static int mt7988_phy_probe(struct phy_device *phydev)
++{
++      struct mtk_socphy_shared *shared;
++      struct mtk_socphy_priv *priv;
++      int err;
++
++      if (phydev->mdio.addr > 3)
++              return -EINVAL;
++
++      err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
++                                  sizeof(struct mtk_socphy_shared));
++      if (err)
++              return err;
++
++      if (phy_package_probe_once(phydev)) {
++              err = mt7988_phy_probe_shared(phydev);
++              if (err)
++                      return err;
++      }
++
++      shared = phydev->shared->priv;
++      priv = &shared->priv[phydev->mdio.addr];
++
++      phydev->priv = priv;
++
++      mt798x_phy_leds_state_init(phydev);
++
++      err = mt7988_phy_fix_leds_polarities(phydev);
++      if (err)
++              return err;
++
++      /* Disable TX power saving at probing to:
++       * 1. Meet common mode compliance test criteria
++       * 2. Make sure that TX-VCM calibration works fine
++       */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
++                     MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
++
++      return mt798x_phy_calibration(phydev);
++}
++
++static int mt7981_phy_probe(struct phy_device *phydev)
++{
++      struct mtk_socphy_priv *priv;
++
++      priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv),
++                          GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      phydev->priv = priv;
++
++      mt798x_phy_leds_state_init(phydev);
++
++      return mt798x_phy_calibration(phydev);
++}
++
++static struct phy_driver mtk_socphy_driver[] = {
++      {
++              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
++              .name           = "MediaTek MT7981 PHY",
++              .config_init    = mt798x_phy_config_init,
++              .config_intr    = genphy_no_config_intr,
++              .handle_interrupt = genphy_handle_interrupt_no_ack,
++              .probe          = mt7981_phy_probe,
++              .suspend        = genphy_suspend,
++              .resume         = genphy_resume,
++              .read_page      = mtk_socphy_read_page,
++              .write_page     = mtk_socphy_write_page,
++              .led_blink_set  = mt798x_phy_led_blink_set,
++              .led_brightness_set = mt798x_phy_led_brightness_set,
++              .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
++              .led_hw_control_set = mt798x_phy_led_hw_control_set,
++              .led_hw_control_get = mt798x_phy_led_hw_control_get,
++      },
++      {
++              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
++              .name           = "MediaTek MT7988 PHY",
++              .config_init    = mt798x_phy_config_init,
++              .config_intr    = genphy_no_config_intr,
++              .handle_interrupt = genphy_handle_interrupt_no_ack,
++              .probe          = mt7988_phy_probe,
++              .suspend        = genphy_suspend,
++              .resume         = genphy_resume,
++              .read_page      = mtk_socphy_read_page,
++              .write_page     = mtk_socphy_write_page,
++              .led_blink_set  = mt798x_phy_led_blink_set,
++              .led_brightness_set = mt798x_phy_led_brightness_set,
++              .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
++              .led_hw_control_set = mt798x_phy_led_hw_control_set,
++              .led_hw_control_get = mt798x_phy_led_hw_control_get,
++      },
++};
++
++module_phy_driver(mtk_socphy_driver);
++
++static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
++      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
++      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
++      { }
++};
++
++MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver");
++MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
++MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
++MODULE_LICENSE("GPL");
++
++MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);
+--- /dev/null
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -0,0 +1,111 @@
++// SPDX-License-Identifier: GPL-2.0+
++#include <linux/bitfield.h>
++#include <linux/module.h>
++#include <linux/phy.h>
++
++#define MTK_EXT_PAGE_ACCESS           0x1f
++#define MTK_PHY_PAGE_STANDARD         0x0000
++#define MTK_PHY_PAGE_EXTENDED         0x0001
++#define MTK_PHY_PAGE_EXTENDED_2               0x0002
++#define MTK_PHY_PAGE_EXTENDED_3               0x0003
++#define MTK_PHY_PAGE_EXTENDED_2A30    0x2a30
++#define MTK_PHY_PAGE_EXTENDED_52B5    0x52b5
++
++static int mtk_gephy_read_page(struct phy_device *phydev)
++{
++      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
++}
++
++static int mtk_gephy_write_page(struct phy_device *phydev, int page)
++{
++      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
++}
++
++static void mtk_gephy_config_init(struct phy_device *phydev)
++{
++      /* Enable HW auto downshift */
++      phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
++
++      /* Increase SlvDPSready time */
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      __phy_write(phydev, 0x10, 0xafae);
++      __phy_write(phydev, 0x12, 0x2f);
++      __phy_write(phydev, 0x10, 0x8fae);
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++
++      /* Adjust 100_mse_threshold */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
++
++      /* Disable mcc */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
++}
++
++static int mt7530_phy_config_init(struct phy_device *phydev)
++{
++      mtk_gephy_config_init(phydev);
++
++      /* Increase post_update_timer */
++      phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
++
++      return 0;
++}
++
++static int mt7531_phy_config_init(struct phy_device *phydev)
++{
++      mtk_gephy_config_init(phydev);
++
++      /* PHY link down power saving enable */
++      phy_set_bits(phydev, 0x17, BIT(4));
++      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
++
++      /* Set TX Pair delay selection */
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
++      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
++
++      return 0;
++}
++
++static struct phy_driver mtk_gephy_driver[] = {
++      {
++              PHY_ID_MATCH_EXACT(0x03a29412),
++              .name           = "MediaTek MT7530 PHY",
++              .config_init    = mt7530_phy_config_init,
++              /* Interrupts are handled by the switch, not the PHY
++               * itself.
++               */
++              .config_intr    = genphy_no_config_intr,
++              .handle_interrupt = genphy_handle_interrupt_no_ack,
++              .suspend        = genphy_suspend,
++              .resume         = genphy_resume,
++              .read_page      = mtk_gephy_read_page,
++              .write_page     = mtk_gephy_write_page,
++      },
++      {
++              PHY_ID_MATCH_EXACT(0x03a29441),
++              .name           = "MediaTek MT7531 PHY",
++              .config_init    = mt7531_phy_config_init,
++              /* Interrupts are handled by the switch, not the PHY
++               * itself.
++               */
++              .config_intr    = genphy_no_config_intr,
++              .handle_interrupt = genphy_handle_interrupt_no_ack,
++              .suspend        = genphy_suspend,
++              .resume         = genphy_resume,
++              .read_page      = mtk_gephy_read_page,
++              .write_page     = mtk_gephy_write_page,
++      },
++};
++
++module_phy_driver(mtk_gephy_driver);
++
++static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
++      { PHY_ID_MATCH_EXACT(0x03a29441) },
++      { PHY_ID_MATCH_EXACT(0x03a29412) },
++      { }
++};
++
++MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
++MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
++MODULE_LICENSE("GPL");
++
++MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);
diff --git a/target/linux/generic/backport-6.12/724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch b/target/linux/generic/backport-6.12/724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch
new file mode 100644 (file)
index 0000000..63407ac
--- /dev/null
@@ -0,0 +1,774 @@
+From 71d88c7409b91c853d7f9c933f5e27933d656e5e Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Sat, 9 Nov 2024 00:34:52 +0800
+Subject: [PATCH 05/20] net: phy: mediatek: Move LED helper functions into mtk
+ phy lib
+
+This patch creates mtk-phy-lib.c & mtk-phy.h and integrates mtk-ge-soc.c's
+LED helper functions so that we can use those helper functions in other
+MTK's ethernet phy driver.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ MAINTAINERS                            |   2 +
+ drivers/net/phy/mediatek/Kconfig       |   4 +
+ drivers/net/phy/mediatek/Makefile      |   1 +
+ drivers/net/phy/mediatek/mtk-ge-soc.c  | 280 +++----------------------
+ drivers/net/phy/mediatek/mtk-phy-lib.c | 254 ++++++++++++++++++++++
+ drivers/net/phy/mediatek/mtk.h         |  86 ++++++++
+ 6 files changed, 372 insertions(+), 255 deletions(-)
+ create mode 100644 drivers/net/phy/mediatek/mtk-phy-lib.c
+ create mode 100644 drivers/net/phy/mediatek/mtk.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -14428,7 +14428,9 @@ M:     SkyLake Huang <SkyLake.Huang@mediatek
+ L:    netdev@vger.kernel.org
+ S:    Maintained
+ F:    drivers/net/phy/mediatek/mtk-ge-soc.c
++F:    drivers/net/phy/mediatek/mtk-phy-lib.c
+ F:    drivers/net/phy/mediatek/mtk-ge.c
++F:    drivers/net/phy/mediatek/mtk.h
+ F:    drivers/phy/mediatek/phy-mtk-xfi-tphy.c
+ MEDIATEK I2C CONTROLLER DRIVER
+--- a/drivers/net/phy/mediatek/Kconfig
++++ b/drivers/net/phy/mediatek/Kconfig
+@@ -1,4 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
++config MTK_NET_PHYLIB
++      tristate
++
+ config MEDIATEK_GE_PHY
+       tristate "MediaTek Gigabit Ethernet PHYs"
+       help
+@@ -13,6 +16,7 @@ config MEDIATEK_GE_SOC_PHY
+       tristate "MediaTek SoC Ethernet PHYs"
+       depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+       depends on NVMEM_MTK_EFUSE
++      select MTK_NET_PHYLIB
+       help
+         Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+--- a/drivers/net/phy/mediatek/Makefile
++++ b/drivers/net/phy/mediatek/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_MTK_NET_PHYLIB)          += mtk-phy-lib.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY)         += mtk-ge.o
+ obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)     += mtk-ge-soc.o
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -8,6 +8,8 @@
+ #include <linux/phy.h>
+ #include <linux/regmap.h>
++#include "mtk.h"
++
+ #define MTK_GPHY_ID_MT7981                    0x03a29461
+ #define MTK_GPHY_ID_MT7988                    0x03a29481
+@@ -210,41 +212,6 @@
+ #define MTK_PHY_DA_TX_R50_PAIR_D              0x540
+ /* Registers on MDIO_MMD_VEND2 */
+-#define MTK_PHY_LED0_ON_CTRL                  0x24
+-#define MTK_PHY_LED1_ON_CTRL                  0x26
+-#define   MTK_PHY_LED_ON_MASK                 GENMASK(6, 0)
+-#define   MTK_PHY_LED_ON_LINK1000             BIT(0)
+-#define   MTK_PHY_LED_ON_LINK100              BIT(1)
+-#define   MTK_PHY_LED_ON_LINK10                       BIT(2)
+-#define   MTK_PHY_LED_ON_LINK                 (MTK_PHY_LED_ON_LINK10 |\
+-                                               MTK_PHY_LED_ON_LINK100 |\
+-                                               MTK_PHY_LED_ON_LINK1000)
+-#define   MTK_PHY_LED_ON_LINKDOWN             BIT(3)
+-#define   MTK_PHY_LED_ON_FDX                  BIT(4) /* Full duplex */
+-#define   MTK_PHY_LED_ON_HDX                  BIT(5) /* Half duplex */
+-#define   MTK_PHY_LED_ON_FORCE_ON             BIT(6)
+-#define   MTK_PHY_LED_ON_POLARITY             BIT(14)
+-#define   MTK_PHY_LED_ON_ENABLE                       BIT(15)
+-
+-#define MTK_PHY_LED0_BLINK_CTRL                       0x25
+-#define MTK_PHY_LED1_BLINK_CTRL                       0x27
+-#define   MTK_PHY_LED_BLINK_1000TX            BIT(0)
+-#define   MTK_PHY_LED_BLINK_1000RX            BIT(1)
+-#define   MTK_PHY_LED_BLINK_100TX             BIT(2)
+-#define   MTK_PHY_LED_BLINK_100RX             BIT(3)
+-#define   MTK_PHY_LED_BLINK_10TX              BIT(4)
+-#define   MTK_PHY_LED_BLINK_10RX              BIT(5)
+-#define   MTK_PHY_LED_BLINK_RX                        (MTK_PHY_LED_BLINK_10RX |\
+-                                               MTK_PHY_LED_BLINK_100RX |\
+-                                               MTK_PHY_LED_BLINK_1000RX)
+-#define   MTK_PHY_LED_BLINK_TX                        (MTK_PHY_LED_BLINK_10TX |\
+-                                               MTK_PHY_LED_BLINK_100TX |\
+-                                               MTK_PHY_LED_BLINK_1000TX)
+-#define   MTK_PHY_LED_BLINK_COLLISION         BIT(6)
+-#define   MTK_PHY_LED_BLINK_RX_CRC_ERR                BIT(7)
+-#define   MTK_PHY_LED_BLINK_RX_IDLE_ERR               BIT(8)
+-#define   MTK_PHY_LED_BLINK_FORCE_BLINK               BIT(9)
+-
+ #define MTK_PHY_LED1_DEFAULT_POLARITIES               BIT(1)
+ #define MTK_PHY_RG_BG_RASEL                   0x115
+@@ -299,14 +266,6 @@ enum CAL_MODE {
+       SW_M
+ };
+-#define MTK_PHY_LED_STATE_FORCE_ON    0
+-#define MTK_PHY_LED_STATE_FORCE_BLINK 1
+-#define MTK_PHY_LED_STATE_NETDEV      2
+-
+-struct mtk_socphy_priv {
+-      unsigned long           led_state;
+-};
+-
+ struct mtk_socphy_shared {
+       u32                     boottrap;
+       struct mtk_socphy_priv  priv[4];
+@@ -1172,76 +1131,23 @@ static int mt798x_phy_config_init(struct
+       return mt798x_phy_calibration(phydev);
+ }
+-static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+-                                  bool on)
+-{
+-      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      bool changed;
+-
+-      if (on)
+-              changed = !test_and_set_bit(bit_on, &priv->led_state);
+-      else
+-              changed = !!test_and_clear_bit(bit_on, &priv->led_state);
+-
+-      changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
+-                                      (index ? 16 : 0), &priv->led_state);
+-      if (changed)
+-              return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                    MTK_PHY_LED1_ON_CTRL :
+-                                    MTK_PHY_LED0_ON_CTRL,
+-                                    MTK_PHY_LED_ON_MASK,
+-                                    on ? MTK_PHY_LED_ON_FORCE_ON : 0);
+-      else
+-              return 0;
+-}
+-
+-static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+-                                     bool blinking)
+-{
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+-                               (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      bool changed;
+-
+-      if (blinking)
+-              changed = !test_and_set_bit(bit_blink, &priv->led_state);
+-      else
+-              changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
+-
+-      changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
+-                            (index ? 16 : 0), &priv->led_state);
+-      if (changed)
+-              return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                                   MTK_PHY_LED1_BLINK_CTRL :
+-                                   MTK_PHY_LED0_BLINK_CTRL,
+-                                   blinking ?
+-                                   MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
+-      else
+-              return 0;
+-}
+-
+ static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
+                                   unsigned long *delay_on,
+                                   unsigned long *delay_off)
+ {
+       bool blinking = false;
+-      int err = 0;
+-
+-      if (index > 1)
+-              return -EINVAL;
++      int err;
+-      if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
+-              blinking = true;
+-              *delay_on = 50;
+-              *delay_off = 50;
+-      }
++      err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
++      if (err < 0)
++              return err;
+-      err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
++      err = mtk_phy_hw_led_blink_set(phydev, index, blinking);
+       if (err)
+               return err;
+-      return mt798x_phy_hw_led_on_set(phydev, index, false);
++      return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
++                                   false);
+ }
+ static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
+@@ -1249,11 +1155,12 @@ static int mt798x_phy_led_brightness_set
+ {
+       int err;
+-      err = mt798x_phy_hw_led_blink_set(phydev, index, false);
++      err = mtk_phy_hw_led_blink_set(phydev, index, false);
+       if (err)
+               return err;
+-      return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
++      return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
++                                   (value != LED_OFF));
+ }
+ static const unsigned long supported_triggers =
+@@ -1269,155 +1176,26 @@ static const unsigned long supported_tri
+ static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+                                         unsigned long rules)
+ {
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      /* All combinations of the supported triggers are allowed */
+-      if (rules & ~supported_triggers)
+-              return -EOPNOTSUPP;
+-
+-      return 0;
+-};
++      return mtk_phy_led_hw_is_supported(phydev, index, rules,
++                                         supported_triggers);
++}
+ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+                                        unsigned long *rules)
+ {
+-      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+-                               (index ? 16 : 0);
+-      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+-      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      int on, blink;
+-
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+-                        index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
+-
+-      if (on < 0)
+-              return -EIO;
+-
+-      blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+-                           index ? MTK_PHY_LED1_BLINK_CTRL :
+-                                   MTK_PHY_LED0_BLINK_CTRL);
+-      if (blink < 0)
+-              return -EIO;
+-
+-      if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX |
+-                 MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
+-          (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
+-              set_bit(bit_netdev, &priv->led_state);
+-      else
+-              clear_bit(bit_netdev, &priv->led_state);
+-
+-      if (on & MTK_PHY_LED_ON_FORCE_ON)
+-              set_bit(bit_on, &priv->led_state);
+-      else
+-              clear_bit(bit_on, &priv->led_state);
+-
+-      if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
+-              set_bit(bit_blink, &priv->led_state);
+-      else
+-              clear_bit(bit_blink, &priv->led_state);
+-
+-      if (!rules)
+-              return 0;
+-
+-      if (on & MTK_PHY_LED_ON_LINK)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK);
+-
+-      if (on & MTK_PHY_LED_ON_LINK10)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+-
+-      if (on & MTK_PHY_LED_ON_LINK100)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+-
+-      if (on & MTK_PHY_LED_ON_LINK1000)
+-              *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+-
+-      if (on & MTK_PHY_LED_ON_FDX)
+-              *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
+-
+-      if (on & MTK_PHY_LED_ON_HDX)
+-              *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
+-
+-      if (blink & MTK_PHY_LED_BLINK_RX)
+-              *rules |= BIT(TRIGGER_NETDEV_RX);
+-
+-      if (blink & MTK_PHY_LED_BLINK_TX)
+-              *rules |= BIT(TRIGGER_NETDEV_TX);
+-
+-      return 0;
++      return mtk_phy_led_hw_ctrl_get(phydev, index, rules,
++                                     MTK_GPHY_LED_ON_SET,
++                                     MTK_GPHY_LED_RX_BLINK_SET,
++                                     MTK_GPHY_LED_TX_BLINK_SET);
+ };
+ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+                                        unsigned long rules)
+ {
+-      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+-      struct mtk_socphy_priv *priv = phydev->priv;
+-      u16 on = 0, blink = 0;
+-      int ret;
+-
+-      if (index > 1)
+-              return -EINVAL;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
+-              on |= MTK_PHY_LED_ON_FDX;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
+-              on |= MTK_PHY_LED_ON_HDX;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK10;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK100;
+-
+-      if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
+-              on |= MTK_PHY_LED_ON_LINK1000;
+-
+-      if (rules & BIT(TRIGGER_NETDEV_RX)) {
+-              blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000RX : 0)) :
+-                        MTK_PHY_LED_BLINK_RX;
+-      }
+-
+-      if (rules & BIT(TRIGGER_NETDEV_TX)) {
+-              blink |= (on & MTK_PHY_LED_ON_LINK) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000TX : 0)) :
+-                        MTK_PHY_LED_BLINK_TX;
+-      }
+-
+-      if (blink || on)
+-              set_bit(bit_netdev, &priv->led_state);
+-      else
+-              clear_bit(bit_netdev, &priv->led_state);
+-
+-      ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                              MTK_PHY_LED1_ON_CTRL :
+-                              MTK_PHY_LED0_ON_CTRL,
+-                           MTK_PHY_LED_ON_FDX     |
+-                           MTK_PHY_LED_ON_HDX     |
+-                           MTK_PHY_LED_ON_LINK,
+-                           on);
+-
+-      if (ret)
+-              return ret;
+-
+-      return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+-                              MTK_PHY_LED1_BLINK_CTRL :
+-                              MTK_PHY_LED0_BLINK_CTRL, blink);
++      return mtk_phy_led_hw_ctrl_set(phydev, index, rules,
++                                     MTK_GPHY_LED_ON_SET,
++                                     MTK_GPHY_LED_RX_BLINK_SET,
++                                     MTK_GPHY_LED_TX_BLINK_SET);
+ };
+ static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
+@@ -1492,14 +1270,6 @@ static int mt7988_phy_probe_shared(struc
+       return 0;
+ }
+-static void mt798x_phy_leds_state_init(struct phy_device *phydev)
+-{
+-      int i;
+-
+-      for (i = 0; i < 2; ++i)
+-              mt798x_phy_led_hw_control_get(phydev, i, NULL);
+-}
+-
+ static int mt7988_phy_probe(struct phy_device *phydev)
+ {
+       struct mtk_socphy_shared *shared;
+@@ -1525,7 +1295,7 @@ static int mt7988_phy_probe(struct phy_d
+       phydev->priv = priv;
+-      mt798x_phy_leds_state_init(phydev);
++      mtk_phy_leds_state_init(phydev);
+       err = mt7988_phy_fix_leds_polarities(phydev);
+       if (err)
+@@ -1552,7 +1322,7 @@ static int mt7981_phy_probe(struct phy_d
+       phydev->priv = priv;
+-      mt798x_phy_leds_state_init(phydev);
++      mtk_phy_leds_state_init(phydev);
+       return mt798x_phy_calibration(phydev);
+ }
+--- /dev/null
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -0,0 +1,254 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <linux/phy.h>
++#include <linux/module.h>
++
++#include <linux/netdevice.h>
++
++#include "mtk.h"
++
++int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
++                              unsigned long rules,
++                              unsigned long supported_triggers)
++{
++      if (index > 1)
++              return -EINVAL;
++
++      /* All combinations of the supported triggers are allowed */
++      if (rules & ~supported_triggers)
++              return -EOPNOTSUPP;
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
++
++int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
++                          unsigned long *rules, u16 on_set,
++                          u16 rx_blink_set, u16 tx_blink_set)
++{
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
++      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
++      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      int on, blink;
++
++      if (index > 1)
++              return -EINVAL;
++
++      on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
++                        index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
++
++      if (on < 0)
++              return -EIO;
++
++      blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
++                           index ? MTK_PHY_LED1_BLINK_CTRL :
++                                   MTK_PHY_LED0_BLINK_CTRL);
++      if (blink < 0)
++              return -EIO;
++
++      if ((on & (on_set | MTK_PHY_LED_ON_FDX |
++                 MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
++          (blink & (rx_blink_set | tx_blink_set)))
++              set_bit(bit_netdev, &priv->led_state);
++      else
++              clear_bit(bit_netdev, &priv->led_state);
++
++      if (on & MTK_PHY_LED_ON_FORCE_ON)
++              set_bit(bit_on, &priv->led_state);
++      else
++              clear_bit(bit_on, &priv->led_state);
++
++      if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
++              set_bit(bit_blink, &priv->led_state);
++      else
++              clear_bit(bit_blink, &priv->led_state);
++
++      if (!rules)
++              return 0;
++
++      if (on & on_set)
++              *rules |= BIT(TRIGGER_NETDEV_LINK);
++
++      if (on & MTK_PHY_LED_ON_LINK10)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_10);
++
++      if (on & MTK_PHY_LED_ON_LINK100)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_100);
++
++      if (on & MTK_PHY_LED_ON_LINK1000)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
++
++      if (on & MTK_PHY_LED_ON_LINK2500)
++              *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
++
++      if (on & MTK_PHY_LED_ON_FDX)
++              *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
++
++      if (on & MTK_PHY_LED_ON_HDX)
++              *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
++
++      if (blink & rx_blink_set)
++              *rules |= BIT(TRIGGER_NETDEV_RX);
++
++      if (blink & tx_blink_set)
++              *rules |= BIT(TRIGGER_NETDEV_TX);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
++
++int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
++                          unsigned long rules, u16 on_set,
++                          u16 rx_blink_set, u16 tx_blink_set)
++{
++      unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      u16 on = 0, blink = 0;
++      int ret;
++
++      if (index > 1)
++              return -EINVAL;
++
++      if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
++              on |= MTK_PHY_LED_ON_FDX;
++
++      if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
++              on |= MTK_PHY_LED_ON_HDX;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK10;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK100;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK1000;
++
++      if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
++              on |= MTK_PHY_LED_ON_LINK2500;
++
++      if (rules & BIT(TRIGGER_NETDEV_RX)) {
++              blink |= (on & on_set) ?
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000RX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK2500) ?
++                          MTK_PHY_LED_BLINK_2500RX : 0)) :
++                        rx_blink_set;
++      }
++
++      if (rules & BIT(TRIGGER_NETDEV_TX)) {
++              blink |= (on & on_set) ?
++                        (((on & MTK_PHY_LED_ON_LINK10) ?
++                          MTK_PHY_LED_BLINK_10TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK100) ?
++                          MTK_PHY_LED_BLINK_100TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK1000) ?
++                          MTK_PHY_LED_BLINK_1000TX : 0) |
++                         ((on & MTK_PHY_LED_ON_LINK2500) ?
++                          MTK_PHY_LED_BLINK_2500TX : 0)) :
++                        tx_blink_set;
++      }
++
++      if (blink || on)
++              set_bit(bit_netdev, &priv->led_state);
++      else
++              clear_bit(bit_netdev, &priv->led_state);
++
++      ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                           MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
++                           MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
++                           on);
++
++      if (ret)
++              return ret;
++
++      return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
++                           MTK_PHY_LED1_BLINK_CTRL :
++                           MTK_PHY_LED0_BLINK_CTRL, blink);
++}
++EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
++
++int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
++                          unsigned long *delay_off, bool *blinking)
++{
++      if (index > 1)
++              return -EINVAL;
++
++      if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
++              *blinking = true;
++              *delay_on = 50;
++              *delay_off = 50;
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
++
++int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
++                        u16 led_on_mask, bool on)
++{
++      unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      bool changed;
++
++      if (on)
++              changed = !test_and_set_bit(bit_on, &priv->led_state);
++      else
++              changed = !!test_and_clear_bit(bit_on, &priv->led_state);
++
++      changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
++                                      (index ? 16 : 0), &priv->led_state);
++      if (changed)
++              return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                                    MTK_PHY_LED1_ON_CTRL :
++                                    MTK_PHY_LED0_ON_CTRL,
++                                    led_on_mask,
++                                    on ? MTK_PHY_LED_ON_FORCE_ON : 0);
++      else
++              return 0;
++}
++EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
++
++int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, bool blinking)
++{
++      unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
++                               (index ? 16 : 0);
++      struct mtk_socphy_priv *priv = phydev->priv;
++      bool changed;
++
++      if (blinking)
++              changed = !test_and_set_bit(bit_blink, &priv->led_state);
++      else
++              changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
++
++      changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
++                            (index ? 16 : 0), &priv->led_state);
++      if (changed)
++              return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
++                                   MTK_PHY_LED1_BLINK_CTRL :
++                                   MTK_PHY_LED0_BLINK_CTRL,
++                                   blinking ?
++                                   MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
++      else
++              return 0;
++}
++EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
++
++void mtk_phy_leds_state_init(struct phy_device *phydev)
++{
++      int i;
++
++      for (i = 0; i < 2; ++i)
++              phydev->drv->led_hw_control_get(phydev, i, NULL);
++}
++EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
++
++MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
++MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
++MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -0,0 +1,86 @@
++/* SPDX-License-Identifier: GPL-2.0
++ *
++ * Common definition for Mediatek Ethernet PHYs
++ * Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
++ * Copyright (c) 2024 MediaTek Inc.
++ */
++
++#ifndef _MTK_EPHY_H_
++#define _MTK_EPHY_H_
++
++#define MTK_EXT_PAGE_ACCESS                   0x1f
++
++/* Registers on MDIO_MMD_VEND2 */
++#define MTK_PHY_LED0_ON_CTRL                  0x24
++#define MTK_PHY_LED1_ON_CTRL                  0x26
++#define   MTK_GPHY_LED_ON_MASK                        GENMASK(6, 0)
++#define   MTK_2P5GPHY_LED_ON_MASK             GENMASK(7, 0)
++#define   MTK_PHY_LED_ON_LINK1000             BIT(0)
++#define   MTK_PHY_LED_ON_LINK100              BIT(1)
++#define   MTK_PHY_LED_ON_LINK10                       BIT(2)
++#define   MTK_PHY_LED_ON_LINKDOWN             BIT(3)
++#define   MTK_PHY_LED_ON_FDX                  BIT(4) /* Full duplex */
++#define   MTK_PHY_LED_ON_HDX                  BIT(5) /* Half duplex */
++#define   MTK_PHY_LED_ON_FORCE_ON             BIT(6)
++#define   MTK_PHY_LED_ON_LINK2500             BIT(7)
++#define   MTK_PHY_LED_ON_POLARITY             BIT(14)
++#define   MTK_PHY_LED_ON_ENABLE                       BIT(15)
++
++#define MTK_PHY_LED0_BLINK_CTRL                       0x25
++#define MTK_PHY_LED1_BLINK_CTRL                       0x27
++#define   MTK_PHY_LED_BLINK_1000TX            BIT(0)
++#define   MTK_PHY_LED_BLINK_1000RX            BIT(1)
++#define   MTK_PHY_LED_BLINK_100TX             BIT(2)
++#define   MTK_PHY_LED_BLINK_100RX             BIT(3)
++#define   MTK_PHY_LED_BLINK_10TX              BIT(4)
++#define   MTK_PHY_LED_BLINK_10RX              BIT(5)
++#define   MTK_PHY_LED_BLINK_COLLISION         BIT(6)
++#define   MTK_PHY_LED_BLINK_RX_CRC_ERR                BIT(7)
++#define   MTK_PHY_LED_BLINK_RX_IDLE_ERR               BIT(8)
++#define   MTK_PHY_LED_BLINK_FORCE_BLINK               BIT(9)
++#define   MTK_PHY_LED_BLINK_2500TX            BIT(10)
++#define   MTK_PHY_LED_BLINK_2500RX            BIT(11)
++
++#define MTK_GPHY_LED_ON_SET                   (MTK_PHY_LED_ON_LINK1000 | \
++                                               MTK_PHY_LED_ON_LINK100 | \
++                                               MTK_PHY_LED_ON_LINK10)
++#define MTK_GPHY_LED_RX_BLINK_SET             (MTK_PHY_LED_BLINK_1000RX | \
++                                               MTK_PHY_LED_BLINK_100RX | \
++                                               MTK_PHY_LED_BLINK_10RX)
++#define MTK_GPHY_LED_TX_BLINK_SET             (MTK_PHY_LED_BLINK_1000RX | \
++                                               MTK_PHY_LED_BLINK_100RX | \
++                                               MTK_PHY_LED_BLINK_10RX)
++
++#define MTK_2P5GPHY_LED_ON_SET                        (MTK_PHY_LED_ON_LINK2500 | \
++                                               MTK_GPHY_LED_ON_SET)
++#define MTK_2P5GPHY_LED_RX_BLINK_SET          (MTK_PHY_LED_BLINK_2500RX | \
++                                               MTK_GPHY_LED_RX_BLINK_SET)
++#define MTK_2P5GPHY_LED_TX_BLINK_SET          (MTK_PHY_LED_BLINK_2500RX | \
++                                               MTK_GPHY_LED_TX_BLINK_SET)
++
++#define MTK_PHY_LED_STATE_FORCE_ON    0
++#define MTK_PHY_LED_STATE_FORCE_BLINK 1
++#define MTK_PHY_LED_STATE_NETDEV      2
++
++struct mtk_socphy_priv {
++      unsigned long           led_state;
++};
++
++int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
++                              unsigned long rules,
++                              unsigned long supported_triggers);
++int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
++                          unsigned long rules, u16 on_set,
++                          u16 rx_blink_set, u16 tx_blink_set);
++int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
++                          unsigned long *rules, u16 on_set,
++                          u16 rx_blink_set, u16 tx_blink_set);
++int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
++                          unsigned long *delay_off, bool *blinking);
++int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
++                        u16 led_on_mask, bool on);
++int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
++                           bool blinking);
++void mtk_phy_leds_state_init(struct phy_device *phydev);
++
++#endif /* _MTK_EPHY_H_ */
diff --git a/target/linux/generic/backport-6.12/725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch b/target/linux/generic/backport-6.12/725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch
new file mode 100644 (file)
index 0000000..19f3a84
--- /dev/null
@@ -0,0 +1,72 @@
+From 3efd0595fc7aaae300f5d9f4f0ae86f432c8d2c7 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Sat, 9 Nov 2024 00:34:53 +0800
+Subject: [PATCH 06/20] net: phy: mediatek: Improve readability of
+ mtk-phy-lib.c's mtk_phy_led_hw_ctrl_set()
+
+This patch removes parens around TRIGGER_NETDEV_RX/TRIGGER_NETDEV_TX in
+mtk_phy_led_hw_ctrl_set(), which improves readability.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/mediatek/mtk-phy-lib.c | 44 ++++++++++++++------------
+ 1 file changed, 24 insertions(+), 20 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -129,29 +129,33 @@ int mtk_phy_led_hw_ctrl_set(struct phy_d
+               on |= MTK_PHY_LED_ON_LINK2500;
+       if (rules & BIT(TRIGGER_NETDEV_RX)) {
+-              blink |= (on & on_set) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000RX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK2500) ?
+-                          MTK_PHY_LED_BLINK_2500RX : 0)) :
+-                        rx_blink_set;
++              if (on & on_set) {
++                      if (on & MTK_PHY_LED_ON_LINK10)
++                              blink |= MTK_PHY_LED_BLINK_10RX;
++                      if (on & MTK_PHY_LED_ON_LINK100)
++                              blink |= MTK_PHY_LED_BLINK_100RX;
++                      if (on & MTK_PHY_LED_ON_LINK1000)
++                              blink |= MTK_PHY_LED_BLINK_1000RX;
++                      if (on & MTK_PHY_LED_ON_LINK2500)
++                              blink |= MTK_PHY_LED_BLINK_2500RX;
++              } else {
++                      blink |= rx_blink_set;
++              }
+       }
+       if (rules & BIT(TRIGGER_NETDEV_TX)) {
+-              blink |= (on & on_set) ?
+-                        (((on & MTK_PHY_LED_ON_LINK10) ?
+-                          MTK_PHY_LED_BLINK_10TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK100) ?
+-                          MTK_PHY_LED_BLINK_100TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK1000) ?
+-                          MTK_PHY_LED_BLINK_1000TX : 0) |
+-                         ((on & MTK_PHY_LED_ON_LINK2500) ?
+-                          MTK_PHY_LED_BLINK_2500TX : 0)) :
+-                        tx_blink_set;
++              if (on & on_set) {
++                      if (on & MTK_PHY_LED_ON_LINK10)
++                              blink |= MTK_PHY_LED_BLINK_10TX;
++                      if (on & MTK_PHY_LED_ON_LINK100)
++                              blink |= MTK_PHY_LED_BLINK_100TX;
++                      if (on & MTK_PHY_LED_ON_LINK1000)
++                              blink |= MTK_PHY_LED_BLINK_1000TX;
++                      if (on & MTK_PHY_LED_ON_LINK2500)
++                              blink |= MTK_PHY_LED_BLINK_2500TX;
++              } else {
++                      blink |= tx_blink_set;
++              }
+       }
+       if (blink || on)
diff --git a/target/linux/generic/backport-6.12/726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch b/target/linux/generic/backport-6.12/726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch
new file mode 100644 (file)
index 0000000..a5828bc
--- /dev/null
@@ -0,0 +1,153 @@
+From 50a97d716105a5f35aaecca0bdfe8e23cba0e87f Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Sat, 9 Nov 2024 00:34:54 +0800
+Subject: [PATCH 07/20] net: phy: mediatek: Integrate read/write page helper
+ functions
+
+This patch integrates read/write page helper functions as MTK phy lib.
+They are basically the same in mtk-ge.c & mtk-ge-soc.c.
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/mediatek/Kconfig       |  1 +
+ drivers/net/phy/mediatek/mtk-ge-soc.c  | 18 ++++--------------
+ drivers/net/phy/mediatek/mtk-ge.c      | 20 ++++++--------------
+ drivers/net/phy/mediatek/mtk-phy-lib.c | 12 ++++++++++++
+ drivers/net/phy/mediatek/mtk.h         |  3 +++
+ 5 files changed, 26 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/phy/mediatek/Kconfig
++++ b/drivers/net/phy/mediatek/Kconfig
+@@ -4,6 +4,7 @@ config MTK_NET_PHYLIB
+ config MEDIATEK_GE_PHY
+       tristate "MediaTek Gigabit Ethernet PHYs"
++      select MTK_NET_PHYLIB
+       help
+         Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -271,16 +271,6 @@ struct mtk_socphy_shared {
+       struct mtk_socphy_priv  priv[4];
+ };
+-static int mtk_socphy_read_page(struct phy_device *phydev)
+-{
+-      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+-}
+-
+-static int mtk_socphy_write_page(struct phy_device *phydev, int page)
+-{
+-      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+-}
+-
+ /* One calibration cycle consists of:
+  * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
+  *   until AD_CAL_COMP is ready to output calibration result.
+@@ -1337,8 +1327,8 @@ static struct phy_driver mtk_socphy_driv
+               .probe          = mt7981_phy_probe,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+-              .read_page      = mtk_socphy_read_page,
+-              .write_page     = mtk_socphy_write_page,
++              .read_page      = mtk_phy_read_page,
++              .write_page     = mtk_phy_write_page,
+               .led_blink_set  = mt798x_phy_led_blink_set,
+               .led_brightness_set = mt798x_phy_led_brightness_set,
+               .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
+@@ -1354,8 +1344,8 @@ static struct phy_driver mtk_socphy_driv
+               .probe          = mt7988_phy_probe,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+-              .read_page      = mtk_socphy_read_page,
+-              .write_page     = mtk_socphy_write_page,
++              .read_page      = mtk_phy_read_page,
++              .write_page     = mtk_phy_write_page,
+               .led_blink_set  = mt798x_phy_led_blink_set,
+               .led_brightness_set = mt798x_phy_led_brightness_set,
+               .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -3,6 +3,8 @@
+ #include <linux/module.h>
+ #include <linux/phy.h>
++#include "mtk.h"
++
+ #define MTK_EXT_PAGE_ACCESS           0x1f
+ #define MTK_PHY_PAGE_STANDARD         0x0000
+ #define MTK_PHY_PAGE_EXTENDED         0x0001
+@@ -11,16 +13,6 @@
+ #define MTK_PHY_PAGE_EXTENDED_2A30    0x2a30
+ #define MTK_PHY_PAGE_EXTENDED_52B5    0x52b5
+-static int mtk_gephy_read_page(struct phy_device *phydev)
+-{
+-      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+-}
+-
+-static int mtk_gephy_write_page(struct phy_device *phydev, int page)
+-{
+-      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+-}
+-
+ static void mtk_gephy_config_init(struct phy_device *phydev)
+ {
+       /* Enable HW auto downshift */
+@@ -77,8 +69,8 @@ static struct phy_driver mtk_gephy_drive
+               .handle_interrupt = genphy_handle_interrupt_no_ack,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+-              .read_page      = mtk_gephy_read_page,
+-              .write_page     = mtk_gephy_write_page,
++              .read_page      = mtk_phy_read_page,
++              .write_page     = mtk_phy_write_page,
+       },
+       {
+               PHY_ID_MATCH_EXACT(0x03a29441),
+@@ -91,8 +83,8 @@ static struct phy_driver mtk_gephy_drive
+               .handle_interrupt = genphy_handle_interrupt_no_ack,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+-              .read_page      = mtk_gephy_read_page,
+-              .write_page     = mtk_gephy_write_page,
++              .read_page      = mtk_phy_read_page,
++              .write_page     = mtk_phy_write_page,
+       },
+ };
+--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -6,6 +6,18 @@
+ #include "mtk.h"
++int mtk_phy_read_page(struct phy_device *phydev)
++{
++      return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
++}
++EXPORT_SYMBOL_GPL(mtk_phy_read_page);
++
++int mtk_phy_write_page(struct phy_device *phydev, int page)
++{
++      return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
++}
++EXPORT_SYMBOL_GPL(mtk_phy_write_page);
++
+ int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+                               unsigned long rules,
+                               unsigned long supported_triggers)
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -66,6 +66,9 @@ struct mtk_socphy_priv {
+       unsigned long           led_state;
+ };
++int mtk_phy_read_page(struct phy_device *phydev);
++int mtk_phy_write_page(struct phy_device *phydev, int page);
++
+ int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+                               unsigned long rules,
+                               unsigned long supported_triggers);
diff --git a/target/linux/generic/backport-6.12/727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch b/target/linux/generic/backport-6.12/727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch
new file mode 100644 (file)
index 0000000..1c87384
--- /dev/null
@@ -0,0 +1,56 @@
+From e6579df175d5b1baa605c82f8e759542262637cf Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Sat, 9 Nov 2024 00:34:55 +0800
+Subject: [PATCH 08/20] net: phy: mediatek: add MT7530 & MT7531's PHY ID macros
+
+This patch adds MT7530 & MT7531's PHY ID macros in mtk-ge.c so that
+it follows the same rule of mtk-ge-soc.c.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/mediatek/mtk-ge.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -5,6 +5,9 @@
+ #include "mtk.h"
++#define MTK_GPHY_ID_MT7530            0x03a29412
++#define MTK_GPHY_ID_MT7531            0x03a29441
++
+ #define MTK_EXT_PAGE_ACCESS           0x1f
+ #define MTK_PHY_PAGE_STANDARD         0x0000
+ #define MTK_PHY_PAGE_EXTENDED         0x0001
+@@ -59,7 +62,7 @@ static int mt7531_phy_config_init(struct
+ static struct phy_driver mtk_gephy_driver[] = {
+       {
+-              PHY_ID_MATCH_EXACT(0x03a29412),
++              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
+               .name           = "MediaTek MT7530 PHY",
+               .config_init    = mt7530_phy_config_init,
+               /* Interrupts are handled by the switch, not the PHY
+@@ -73,7 +76,7 @@ static struct phy_driver mtk_gephy_drive
+               .write_page     = mtk_phy_write_page,
+       },
+       {
+-              PHY_ID_MATCH_EXACT(0x03a29441),
++              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
+               .name           = "MediaTek MT7531 PHY",
+               .config_init    = mt7531_phy_config_init,
+               /* Interrupts are handled by the switch, not the PHY
+@@ -91,8 +94,8 @@ static struct phy_driver mtk_gephy_drive
+ module_phy_driver(mtk_gephy_driver);
+ static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
+-      { PHY_ID_MATCH_EXACT(0x03a29441) },
+-      { PHY_ID_MATCH_EXACT(0x03a29412) },
++      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
++      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
+       { }
+ };
diff --git a/target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch
new file mode 100644 (file)
index 0000000..a64bc51
--- /dev/null
@@ -0,0 +1,700 @@
+From e127f7380aaf2cd1614961d826a4af7ab297d37f Mon Sep 17 00:00:00 2001
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Date: Sun, 12 Jan 2025 15:14:50 +0100
+Subject: [PATCH 09/20] net: phy: Constify struct mdio_device_id
+
+'struct mdio_device_id' is not modified in these drivers.
+
+Constifying these structures moves some data to a read-only section, so
+increase overall security.
+
+On a x86_64, with allmodconfig, as an example:
+Before:
+======
+   text           data     bss     dec     hex filename
+  27014          12792       0   39806    9b7e drivers/net/phy/broadcom.o
+
+After:
+=====
+   text           data     bss     dec     hex filename
+  27206          12600       0   39806    9b7e drivers/net/phy/broadcom.o
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/403c381b7d9156b67ad68ffc44b8eee70c5e86a9.1736691226.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/adin.c                   | 2 +-
+ drivers/net/phy/adin1100.c               | 2 +-
+ drivers/net/phy/air_en8811h.c            | 2 +-
+ drivers/net/phy/amd.c                    | 2 +-
+ drivers/net/phy/aquantia/aquantia_main.c | 2 +-
+ drivers/net/phy/ax88796b.c               | 2 +-
+ drivers/net/phy/bcm-cygnus.c             | 2 +-
+ drivers/net/phy/bcm54140.c               | 2 +-
+ drivers/net/phy/bcm63xx.c                | 2 +-
+ drivers/net/phy/bcm7xxx.c                | 2 +-
+ drivers/net/phy/bcm84881.c               | 2 +-
+ drivers/net/phy/broadcom.c               | 2 +-
+ drivers/net/phy/cicada.c                 | 2 +-
+ drivers/net/phy/cortina.c                | 2 +-
+ drivers/net/phy/davicom.c                | 2 +-
+ drivers/net/phy/dp83640.c                | 2 +-
+ drivers/net/phy/dp83822.c                | 2 +-
+ drivers/net/phy/dp83848.c                | 2 +-
+ drivers/net/phy/dp83867.c                | 2 +-
+ drivers/net/phy/dp83869.c                | 2 +-
+ drivers/net/phy/dp83tc811.c              | 2 +-
+ drivers/net/phy/dp83td510.c              | 2 +-
+ drivers/net/phy/dp83tg720.c              | 2 +-
+ drivers/net/phy/et1011c.c                | 2 +-
+ drivers/net/phy/icplus.c                 | 2 +-
+ drivers/net/phy/intel-xway.c             | 2 +-
+ drivers/net/phy/lxt.c                    | 2 +-
+ drivers/net/phy/marvell-88q2xxx.c        | 2 +-
+ drivers/net/phy/marvell-88x2222.c        | 2 +-
+ drivers/net/phy/marvell.c                | 2 +-
+ drivers/net/phy/marvell10g.c             | 2 +-
+ drivers/net/phy/mediatek/mtk-ge-soc.c    | 2 +-
+ drivers/net/phy/mediatek/mtk-ge.c        | 2 +-
+ drivers/net/phy/meson-gxl.c              | 2 +-
+ drivers/net/phy/micrel.c                 | 2 +-
+ drivers/net/phy/microchip.c              | 2 +-
+ drivers/net/phy/microchip_t1.c           | 2 +-
+ drivers/net/phy/microchip_t1s.c          | 2 +-
+ drivers/net/phy/mscc/mscc_main.c         | 2 +-
+ drivers/net/phy/mxl-gpy.c                | 2 +-
+ drivers/net/phy/national.c               | 2 +-
+ drivers/net/phy/ncn26000.c               | 2 +-
+ drivers/net/phy/nxp-c45-tja11xx.c        | 2 +-
+ drivers/net/phy/nxp-cbtx.c               | 2 +-
+ drivers/net/phy/nxp-tja11xx.c            | 2 +-
+ drivers/net/phy/qcom/at803x.c            | 2 +-
+ drivers/net/phy/qcom/qca807x.c           | 2 +-
+ drivers/net/phy/qcom/qca808x.c           | 2 +-
+ drivers/net/phy/qcom/qca83xx.c           | 2 +-
+ drivers/net/phy/qsemi.c                  | 2 +-
+ drivers/net/phy/rockchip.c               | 2 +-
+ drivers/net/phy/smsc.c                   | 2 +-
+ drivers/net/phy/ste10Xp.c                | 2 +-
+ drivers/net/phy/teranetics.c             | 2 +-
+ drivers/net/phy/uPD60620.c               | 2 +-
+ drivers/net/phy/vitesse.c                | 2 +-
+ 56 files changed, 56 insertions(+), 56 deletions(-)
+
+--- a/drivers/net/phy/adin.c
++++ b/drivers/net/phy/adin.c
+@@ -1040,7 +1040,7 @@ static struct phy_driver adin_driver[] =
+ module_phy_driver(adin_driver);
+-static struct mdio_device_id __maybe_unused adin_tbl[] = {
++static const struct mdio_device_id __maybe_unused adin_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1200) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1300) },
+       { }
+--- a/drivers/net/phy/adin1100.c
++++ b/drivers/net/phy/adin1100.c
+@@ -340,7 +340,7 @@ static struct phy_driver adin_driver[] =
+ module_phy_driver(adin_driver);
+-static struct mdio_device_id __maybe_unused adin_tbl[] = {
++static const struct mdio_device_id __maybe_unused adin_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1110) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_ADIN2111) },
+--- a/drivers/net/phy/air_en8811h.c
++++ b/drivers/net/phy/air_en8811h.c
+@@ -1075,7 +1075,7 @@ static struct phy_driver en8811h_driver[
+ module_phy_driver(en8811h_driver);
+-static struct mdio_device_id __maybe_unused en8811h_tbl[] = {
++static const struct mdio_device_id __maybe_unused en8811h_tbl[] = {
+       { PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) },
+       { }
+ };
+--- a/drivers/net/phy/amd.c
++++ b/drivers/net/phy/amd.c
+@@ -111,7 +111,7 @@ static struct phy_driver am79c_drivers[]
+ module_phy_driver(am79c_drivers);
+-static struct mdio_device_id __maybe_unused amd_tbl[] = {
++static const struct mdio_device_id __maybe_unused amd_tbl[] = {
+       { PHY_ID_AC101L, 0xfffffff0 },
+       { PHY_ID_AM79C874, 0xfffffff0 },
+       { }
+--- a/drivers/net/phy/aquantia/aquantia_main.c
++++ b/drivers/net/phy/aquantia/aquantia_main.c
+@@ -1096,7 +1096,7 @@ static struct phy_driver aqr_driver[] =
+ module_phy_driver(aqr_driver);
+-static struct mdio_device_id __maybe_unused aqr_tbl[] = {
++static const struct mdio_device_id __maybe_unused aqr_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) },
+--- a/drivers/net/phy/ax88796b.c
++++ b/drivers/net/phy/ax88796b.c
+@@ -121,7 +121,7 @@ static struct phy_driver asix_driver[] =
+ module_phy_driver(asix_driver);
+-static struct mdio_device_id __maybe_unused asix_tbl[] = {
++static const struct mdio_device_id __maybe_unused asix_tbl[] = {
+       { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772A) },
+       { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772C) },
+       { PHY_ID_ASIX_AX88796B, 0xfffffff0 },
+--- a/drivers/net/phy/bcm-cygnus.c
++++ b/drivers/net/phy/bcm-cygnus.c
+@@ -278,7 +278,7 @@ static struct phy_driver bcm_cygnus_phy_
+ }
+ };
+-static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = {
++static const struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = {
+       { PHY_ID_BCM_CYGNUS, 0xfffffff0, },
+       { PHY_ID_BCM_OMEGA, 0xfffffff0, },
+       { }
+--- a/drivers/net/phy/bcm54140.c
++++ b/drivers/net/phy/bcm54140.c
+@@ -883,7 +883,7 @@ static struct phy_driver bcm54140_driver
+ };
+ module_phy_driver(bcm54140_drivers);
+-static struct mdio_device_id __maybe_unused bcm54140_tbl[] = {
++static const struct mdio_device_id __maybe_unused bcm54140_tbl[] = {
+       { PHY_ID_BCM54140, BCM54140_PHY_ID_MASK },
+       { }
+ };
+--- a/drivers/net/phy/bcm63xx.c
++++ b/drivers/net/phy/bcm63xx.c
+@@ -93,7 +93,7 @@ static struct phy_driver bcm63xx_driver[
+ module_phy_driver(bcm63xx_driver);
+-static struct mdio_device_id __maybe_unused bcm63xx_tbl[] = {
++static const struct mdio_device_id __maybe_unused bcm63xx_tbl[] = {
+       { 0x00406000, 0xfffffc00 },
+       { 0x002bdc00, 0xfffffc00 },
+       { }
+--- a/drivers/net/phy/bcm7xxx.c
++++ b/drivers/net/phy/bcm7xxx.c
+@@ -929,7 +929,7 @@ static struct phy_driver bcm7xxx_driver[
+       BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"),
+ };
+-static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
++static const struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
+       { PHY_ID_BCM72113, 0xfffffff0 },
+       { PHY_ID_BCM72116, 0xfffffff0, },
+       { PHY_ID_BCM72165, 0xfffffff0, },
+--- a/drivers/net/phy/bcm84881.c
++++ b/drivers/net/phy/bcm84881.c
+@@ -252,7 +252,7 @@ static struct phy_driver bcm84881_driver
+ module_phy_driver(bcm84881_drivers);
+ /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */
+-static struct mdio_device_id __maybe_unused bcm84881_tbl[] = {
++static const struct mdio_device_id __maybe_unused bcm84881_tbl[] = {
+       { 0xae025150, 0xfffffff0 },
+       { },
+ };
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -1717,7 +1717,7 @@ static struct phy_driver broadcom_driver
+ module_phy_driver(broadcom_drivers);
+-static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
++static const struct mdio_device_id __maybe_unused broadcom_tbl[] = {
+       { PHY_ID_BCM5411, 0xfffffff0 },
+       { PHY_ID_BCM5421, 0xfffffff0 },
+       { PHY_ID_BCM54210E, 0xfffffff0 },
+--- a/drivers/net/phy/cicada.c
++++ b/drivers/net/phy/cicada.c
+@@ -145,7 +145,7 @@ static struct phy_driver cis820x_driver[
+ module_phy_driver(cis820x_driver);
+-static struct mdio_device_id __maybe_unused cicada_tbl[] = {
++static const struct mdio_device_id __maybe_unused cicada_tbl[] = {
+       { 0x000fc410, 0x000ffff0 },
+       { 0x000fc440, 0x000fffc0 },
+       { }
+--- a/drivers/net/phy/cortina.c
++++ b/drivers/net/phy/cortina.c
+@@ -87,7 +87,7 @@ static struct phy_driver cortina_driver[
+ module_phy_driver(cortina_driver);
+-static struct mdio_device_id __maybe_unused cortina_tbl[] = {
++static const struct mdio_device_id __maybe_unused cortina_tbl[] = {
+       { PHY_ID_CS4340, 0xffffffff},
+       {},
+ };
+--- a/drivers/net/phy/davicom.c
++++ b/drivers/net/phy/davicom.c
+@@ -209,7 +209,7 @@ static struct phy_driver dm91xx_driver[]
+ module_phy_driver(dm91xx_driver);
+-static struct mdio_device_id __maybe_unused davicom_tbl[] = {
++static const struct mdio_device_id __maybe_unused davicom_tbl[] = {
+       { 0x0181b880, 0x0ffffff0 },
+       { 0x0181b8b0, 0x0ffffff0 },
+       { 0x0181b8a0, 0x0ffffff0 },
+--- a/drivers/net/phy/dp83640.c
++++ b/drivers/net/phy/dp83640.c
+@@ -1548,7 +1548,7 @@ MODULE_LICENSE("GPL");
+ module_init(dp83640_init);
+ module_exit(dp83640_exit);
+-static struct mdio_device_id __maybe_unused dp83640_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83640_tbl[] = {
+       { DP83640_PHY_ID, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/dp83822.c
++++ b/drivers/net/phy/dp83822.c
+@@ -825,7 +825,7 @@ static struct phy_driver dp83822_driver[
+ };
+ module_phy_driver(dp83822_driver);
+-static struct mdio_device_id __maybe_unused dp83822_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83822_tbl[] = {
+       { DP83822_PHY_ID, 0xfffffff0 },
+       { DP83825I_PHY_ID, 0xfffffff0 },
+       { DP83826C_PHY_ID, 0xfffffff0 },
+--- a/drivers/net/phy/dp83848.c
++++ b/drivers/net/phy/dp83848.c
+@@ -123,7 +123,7 @@ static int dp83848_config_init(struct ph
+       return 0;
+ }
+-static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83848_tbl[] = {
+       { TI_DP83848C_PHY_ID, 0xfffffff0 },
+       { NS_DP83848C_PHY_ID, 0xfffffff0 },
+       { TI_DP83620_PHY_ID, 0xfffffff0 },
+--- a/drivers/net/phy/dp83867.c
++++ b/drivers/net/phy/dp83867.c
+@@ -1210,7 +1210,7 @@ static struct phy_driver dp83867_driver[
+ };
+ module_phy_driver(dp83867_driver);
+-static struct mdio_device_id __maybe_unused dp83867_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83867_tbl[] = {
+       { DP83867_PHY_ID, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/dp83869.c
++++ b/drivers/net/phy/dp83869.c
+@@ -928,7 +928,7 @@ static struct phy_driver dp83869_driver[
+ };
+ module_phy_driver(dp83869_driver);
+-static struct mdio_device_id __maybe_unused dp83869_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83869_tbl[] = {
+       { PHY_ID_MATCH_MODEL(DP83869_PHY_ID) },
+       { PHY_ID_MATCH_MODEL(DP83561_PHY_ID) },
+       { }
+--- a/drivers/net/phy/dp83tc811.c
++++ b/drivers/net/phy/dp83tc811.c
+@@ -403,7 +403,7 @@ static struct phy_driver dp83811_driver[
+ };
+ module_phy_driver(dp83811_driver);
+-static struct mdio_device_id __maybe_unused dp83811_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83811_tbl[] = {
+       { DP83TC811_PHY_ID, 0xfffffff0 },
+       { },
+ };
+--- a/drivers/net/phy/dp83td510.c
++++ b/drivers/net/phy/dp83td510.c
+@@ -605,7 +605,7 @@ static struct phy_driver dp83td510_drive
+ } };
+ module_phy_driver(dp83td510_driver);
+-static struct mdio_device_id __maybe_unused dp83td510_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83td510_tbl[] = {
+       { PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID) },
+       { }
+ };
+--- a/drivers/net/phy/dp83tg720.c
++++ b/drivers/net/phy/dp83tg720.c
+@@ -361,7 +361,7 @@ static struct phy_driver dp83tg720_drive
+ } };
+ module_phy_driver(dp83tg720_driver);
+-static struct mdio_device_id __maybe_unused dp83tg720_tbl[] = {
++static const struct mdio_device_id __maybe_unused dp83tg720_tbl[] = {
+       { PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) },
+       { }
+ };
+--- a/drivers/net/phy/et1011c.c
++++ b/drivers/net/phy/et1011c.c
+@@ -94,7 +94,7 @@ static struct phy_driver et1011c_driver[
+ module_phy_driver(et1011c_driver);
+-static struct mdio_device_id __maybe_unused et1011c_tbl[] = {
++static const struct mdio_device_id __maybe_unused et1011c_tbl[] = {
+       { 0x0282f014, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/icplus.c
++++ b/drivers/net/phy/icplus.c
+@@ -624,7 +624,7 @@ static struct phy_driver icplus_driver[]
+ module_phy_driver(icplus_driver);
+-static struct mdio_device_id __maybe_unused icplus_tbl[] = {
++static const struct mdio_device_id __maybe_unused icplus_tbl[] = {
+       { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) },
+       { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) },
+       { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) },
+--- a/drivers/net/phy/intel-xway.c
++++ b/drivers/net/phy/intel-xway.c
+@@ -456,7 +456,7 @@ static struct phy_driver xway_gphy[] = {
+ };
+ module_phy_driver(xway_gphy);
+-static struct mdio_device_id __maybe_unused xway_gphy_tbl[] = {
++static const struct mdio_device_id __maybe_unused xway_gphy_tbl[] = {
+       { PHY_ID_PHY11G_1_3, 0xffffffff },
+       { PHY_ID_PHY22F_1_3, 0xffffffff },
+       { PHY_ID_PHY11G_1_4, 0xffffffff },
+--- a/drivers/net/phy/lxt.c
++++ b/drivers/net/phy/lxt.c
+@@ -348,7 +348,7 @@ static struct phy_driver lxt97x_driver[]
+ module_phy_driver(lxt97x_driver);
+-static struct mdio_device_id __maybe_unused lxt_tbl[] = {
++static const struct mdio_device_id __maybe_unused lxt_tbl[] = {
+       { 0x78100000, 0xfffffff0 },
+       { 0x001378e0, 0xfffffff0 },
+       { 0x00137a10, 0xfffffff0 },
+--- a/drivers/net/phy/marvell-88q2xxx.c
++++ b/drivers/net/phy/marvell-88q2xxx.c
+@@ -940,7 +940,7 @@ static struct phy_driver mv88q2xxx_drive
+ module_phy_driver(mv88q2xxx_driver);
+-static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
++static const struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
+       { MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK },
+       { /*sentinel*/ }
+--- a/drivers/net/phy/marvell-88x2222.c
++++ b/drivers/net/phy/marvell-88x2222.c
+@@ -613,7 +613,7 @@ static struct phy_driver mv2222_drivers[
+ };
+ module_phy_driver(mv2222_drivers);
+-static struct mdio_device_id __maybe_unused mv2222_tbl[] = {
++static const struct mdio_device_id __maybe_unused mv2222_tbl[] = {
+       { MARVELL_PHY_ID_88X2222, MARVELL_PHY_ID_MASK },
+       { }
+ };
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -4133,7 +4133,7 @@ static struct phy_driver marvell_drivers
+ module_phy_driver(marvell_drivers);
+-static struct mdio_device_id __maybe_unused marvell_tbl[] = {
++static const struct mdio_device_id __maybe_unused marvell_tbl[] = {
+       { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E3082, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK },
+--- a/drivers/net/phy/marvell10g.c
++++ b/drivers/net/phy/marvell10g.c
+@@ -1484,7 +1484,7 @@ static struct phy_driver mv3310_drivers[
+ module_phy_driver(mv3310_drivers);
+-static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
++static const struct mdio_device_id __maybe_unused mv3310_tbl[] = {
+       { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
+       { },
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -1356,7 +1356,7 @@ static struct phy_driver mtk_socphy_driv
+ module_phy_driver(mtk_socphy_driver);
+-static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
++static const struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
+       { }
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -93,7 +93,7 @@ static struct phy_driver mtk_gephy_drive
+ module_phy_driver(mtk_gephy_driver);
+-static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
++static const struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
+       { }
+--- a/drivers/net/phy/meson-gxl.c
++++ b/drivers/net/phy/meson-gxl.c
+@@ -221,7 +221,7 @@ static struct phy_driver meson_gxl_phy[]
+       },
+ };
+-static struct mdio_device_id __maybe_unused meson_gxl_tbl[] = {
++static const struct mdio_device_id __maybe_unused meson_gxl_tbl[] = {
+       { PHY_ID_MATCH_VENDOR(0x01814400) },
+       { PHY_ID_MATCH_VENDOR(0x01803301) },
+       { }
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -5691,7 +5691,7 @@ MODULE_DESCRIPTION("Micrel PHY driver");
+ MODULE_AUTHOR("David J. Choi");
+ MODULE_LICENSE("GPL");
+-static struct mdio_device_id __maybe_unused micrel_tbl[] = {
++static const struct mdio_device_id __maybe_unused micrel_tbl[] = {
+       { PHY_ID_KSZ9021, 0x000ffffe },
+       { PHY_ID_KSZ9031, MICREL_PHY_ID_MASK },
+       { PHY_ID_KSZ9131, MICREL_PHY_ID_MASK },
+--- a/drivers/net/phy/microchip.c
++++ b/drivers/net/phy/microchip.c
+@@ -508,7 +508,7 @@ static struct phy_driver microchip_phy_d
+ module_phy_driver(microchip_phy_driver);
+-static struct mdio_device_id __maybe_unused microchip_tbl[] = {
++static const struct mdio_device_id __maybe_unused microchip_tbl[] = {
+       { 0x0007c132, 0xfffffff2 },
+       { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X_TX) },
+       { }
+--- a/drivers/net/phy/microchip_t1.c
++++ b/drivers/net/phy/microchip_t1.c
+@@ -1886,7 +1886,7 @@ static struct phy_driver microchip_t1_ph
+ module_phy_driver(microchip_t1_phy_driver);
+-static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = {
++static const struct mdio_device_id __maybe_unused microchip_t1_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_LAN887X) },
+--- a/drivers/net/phy/microchip_t1s.c
++++ b/drivers/net/phy/microchip_t1s.c
+@@ -323,7 +323,7 @@ static struct phy_driver microchip_t1s_d
+ module_phy_driver(microchip_t1s_driver);
+-static struct mdio_device_id __maybe_unused tbl[] = {
++static const struct mdio_device_id __maybe_unused tbl[] = {
+       { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
+       { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) },
+       { }
+--- a/drivers/net/phy/mscc/mscc_main.c
++++ b/drivers/net/phy/mscc/mscc_main.c
+@@ -2700,7 +2700,7 @@ static struct phy_driver vsc85xx_driver[
+ module_phy_driver(vsc85xx_driver);
+-static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
++static const struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+       { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) },
+       { }
+ };
+--- a/drivers/net/phy/mxl-gpy.c
++++ b/drivers/net/phy/mxl-gpy.c
+@@ -1047,7 +1047,7 @@ static struct phy_driver gpy_drivers[] =
+ };
+ module_phy_driver(gpy_drivers);
+-static struct mdio_device_id __maybe_unused gpy_tbl[] = {
++static const struct mdio_device_id __maybe_unused gpy_tbl[] = {
+       {PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx)},
+       {PHY_ID_GPY115B, PHY_ID_GPYx15B_MASK},
+       {PHY_ID_MATCH_MODEL(PHY_ID_GPY115C)},
+--- a/drivers/net/phy/national.c
++++ b/drivers/net/phy/national.c
+@@ -173,7 +173,7 @@ MODULE_DESCRIPTION("NatSemi PHY driver")
+ MODULE_AUTHOR("Stuart Menefy");
+ MODULE_LICENSE("GPL");
+-static struct mdio_device_id __maybe_unused ns_tbl[] = {
++static const struct mdio_device_id __maybe_unused ns_tbl[] = {
+       { DP83865_PHY_ID, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/ncn26000.c
++++ b/drivers/net/phy/ncn26000.c
+@@ -159,7 +159,7 @@ static struct phy_driver ncn26000_driver
+ module_phy_driver(ncn26000_driver);
+-static struct mdio_device_id __maybe_unused ncn26000_tbl[] = {
++static const struct mdio_device_id __maybe_unused ncn26000_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_NCN26000) },
+       { }
+ };
+--- a/drivers/net/phy/nxp-c45-tja11xx.c
++++ b/drivers/net/phy/nxp-c45-tja11xx.c
+@@ -2052,7 +2052,7 @@ static struct phy_driver nxp_c45_driver[
+ module_phy_driver(nxp_c45_driver);
+-static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
++static const struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) },
+       { /*sentinel*/ },
+--- a/drivers/net/phy/nxp-cbtx.c
++++ b/drivers/net/phy/nxp-cbtx.c
+@@ -215,7 +215,7 @@ static struct phy_driver cbtx_driver[] =
+ module_phy_driver(cbtx_driver);
+-static struct mdio_device_id __maybe_unused cbtx_tbl[] = {
++static const struct mdio_device_id __maybe_unused cbtx_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_CBTX_SJA1110) },
+       { },
+ };
+--- a/drivers/net/phy/nxp-tja11xx.c
++++ b/drivers/net/phy/nxp-tja11xx.c
+@@ -888,7 +888,7 @@ static struct phy_driver tja11xx_driver[
+ module_phy_driver(tja11xx_driver);
+-static struct mdio_device_id __maybe_unused tja11xx_tbl[] = {
++static const struct mdio_device_id __maybe_unused tja11xx_tbl[] = {
+       { PHY_ID_MATCH_MODEL(PHY_ID_TJA1100) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_TJA1101) },
+       { PHY_ID_MATCH_MODEL(PHY_ID_TJA1102) },
+--- a/drivers/net/phy/qcom/at803x.c
++++ b/drivers/net/phy/qcom/at803x.c
+@@ -1098,7 +1098,7 @@ static struct phy_driver at803x_driver[]
+ module_phy_driver(at803x_driver);
+-static struct mdio_device_id __maybe_unused atheros_tbl[] = {
++static const struct mdio_device_id __maybe_unused atheros_tbl[] = {
+       { ATH8030_PHY_ID, AT8030_PHY_ID_MASK },
+       { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) },
+       { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
+--- a/drivers/net/phy/qcom/qca807x.c
++++ b/drivers/net/phy/qcom/qca807x.c
+@@ -828,7 +828,7 @@ static struct phy_driver qca807x_drivers
+ };
+ module_phy_driver(qca807x_drivers);
+-static struct mdio_device_id __maybe_unused qca807x_tbl[] = {
++static const struct mdio_device_id __maybe_unused qca807x_tbl[] = {
+       { PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) },
+       { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) },
+       { }
+--- a/drivers/net/phy/qcom/qca808x.c
++++ b/drivers/net/phy/qcom/qca808x.c
+@@ -655,7 +655,7 @@ static struct phy_driver qca808x_driver[
+ module_phy_driver(qca808x_driver);
+-static struct mdio_device_id __maybe_unused qca808x_tbl[] = {
++static const struct mdio_device_id __maybe_unused qca808x_tbl[] = {
+       { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) },
+       { }
+ };
+--- a/drivers/net/phy/qcom/qca83xx.c
++++ b/drivers/net/phy/qcom/qca83xx.c
+@@ -261,7 +261,7 @@ static struct phy_driver qca83xx_driver[
+ module_phy_driver(qca83xx_driver);
+-static struct mdio_device_id __maybe_unused qca83xx_tbl[] = {
++static const struct mdio_device_id __maybe_unused qca83xx_tbl[] = {
+       { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
+       { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
+       { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
+--- a/drivers/net/phy/qsemi.c
++++ b/drivers/net/phy/qsemi.c
+@@ -155,7 +155,7 @@ static struct phy_driver qs6612_driver[]
+ module_phy_driver(qs6612_driver);
+-static struct mdio_device_id __maybe_unused qs6612_tbl[] = {
++static const struct mdio_device_id __maybe_unused qs6612_tbl[] = {
+       { 0x00181440, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/rockchip.c
++++ b/drivers/net/phy/rockchip.c
+@@ -188,7 +188,7 @@ static struct phy_driver rockchip_phy_dr
+ module_phy_driver(rockchip_phy_driver);
+-static struct mdio_device_id __maybe_unused rockchip_phy_tbl[] = {
++static const struct mdio_device_id __maybe_unused rockchip_phy_tbl[] = {
+       { INTERNAL_EPHY_ID, 0xfffffff0 },
+       { }
+ };
+--- a/drivers/net/phy/smsc.c
++++ b/drivers/net/phy/smsc.c
+@@ -837,7 +837,7 @@ MODULE_DESCRIPTION("SMSC PHY driver");
+ MODULE_AUTHOR("Herbert Valerio Riedel");
+ MODULE_LICENSE("GPL");
+-static struct mdio_device_id __maybe_unused smsc_tbl[] = {
++static const struct mdio_device_id __maybe_unused smsc_tbl[] = {
+       { 0x0007c0a0, 0xfffffff0 },
+       { 0x0007c0b0, 0xfffffff0 },
+       { 0x0007c0c0, 0xfffffff0 },
+--- a/drivers/net/phy/ste10Xp.c
++++ b/drivers/net/phy/ste10Xp.c
+@@ -124,7 +124,7 @@ static struct phy_driver ste10xp_pdriver
+ module_phy_driver(ste10xp_pdriver);
+-static struct mdio_device_id __maybe_unused ste10Xp_tbl[] = {
++static const struct mdio_device_id __maybe_unused ste10Xp_tbl[] = {
+       { STE101P_PHY_ID, 0xfffffff0 },
+       { STE100P_PHY_ID, 0xffffffff },
+       { }
+--- a/drivers/net/phy/teranetics.c
++++ b/drivers/net/phy/teranetics.c
+@@ -87,7 +87,7 @@ static struct phy_driver teranetics_driv
+ module_phy_driver(teranetics_driver);
+-static struct mdio_device_id __maybe_unused teranetics_tbl[] = {
++static const struct mdio_device_id __maybe_unused teranetics_tbl[] = {
+       { PHY_ID_TN2020, 0xffffffff },
+       { }
+ };
+--- a/drivers/net/phy/uPD60620.c
++++ b/drivers/net/phy/uPD60620.c
+@@ -90,7 +90,7 @@ static struct phy_driver upd60620_driver
+ module_phy_driver(upd60620_driver);
+-static struct mdio_device_id __maybe_unused upd60620_tbl[] = {
++static const struct mdio_device_id __maybe_unused upd60620_tbl[] = {
+       { UPD60620_PHY_ID, 0xfffffffe },
+       { }
+ };
+--- a/drivers/net/phy/vitesse.c
++++ b/drivers/net/phy/vitesse.c
+@@ -674,7 +674,7 @@ static struct phy_driver vsc82xx_driver[
+ module_phy_driver(vsc82xx_driver);
+-static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
++static const struct mdio_device_id __maybe_unused vitesse_tbl[] = {
+       { PHY_ID_VSC8234, 0x000ffff0 },
+       { PHY_ID_VSC8244, 0x000fffc0 },
+       { PHY_ID_VSC8572, 0x000ffff0 },
diff --git a/target/linux/generic/backport-6.12/729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch b/target/linux/generic/backport-6.12/729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch
new file mode 100644 (file)
index 0000000..545e929
--- /dev/null
@@ -0,0 +1,146 @@
+From 7e06c3dbfa5f1e39eba92eb79d854fab2a7ad5fe Mon Sep 17 00:00:00 2001
+From: Sky Huang <skylake.huang@mediatek.com>
+Date: Thu, 13 Feb 2025 16:05:49 +0800
+Subject: [PATCH 10/20] net: phy: mediatek: Change to more meaningful macros
+
+Replace magic number with more meaningful macros in mtk-ge.c.
+Also, move some common macros into mtk-phy-lib.c.
+
+Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250213080553.921434-2-SkyLake.Huang@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge-soc.c |  1 -
+ drivers/net/phy/mediatek/mtk-ge.c     | 71 +++++++++++++++++++++------
+ drivers/net/phy/mediatek/mtk.h        |  2 +
+ 3 files changed, 57 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -24,7 +24,6 @@
+ #define MTK_PHY_SMI_DET_ON_THRESH_MASK                GENMASK(13, 8)
+ #define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
+-#define MTK_PHY_PAGE_EXTENDED_52B5            0x52b5
+ #define ANALOG_INTERNAL_OPERATION_MAX_US      20
+ #define TXRESERVE_MIN                         0
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -8,18 +8,38 @@
+ #define MTK_GPHY_ID_MT7530            0x03a29412
+ #define MTK_GPHY_ID_MT7531            0x03a29441
+-#define MTK_EXT_PAGE_ACCESS           0x1f
+-#define MTK_PHY_PAGE_STANDARD         0x0000
+-#define MTK_PHY_PAGE_EXTENDED         0x0001
+-#define MTK_PHY_PAGE_EXTENDED_2               0x0002
+-#define MTK_PHY_PAGE_EXTENDED_3               0x0003
+-#define MTK_PHY_PAGE_EXTENDED_2A30    0x2a30
+-#define MTK_PHY_PAGE_EXTENDED_52B5    0x52b5
++#define MTK_PHY_PAGE_EXTENDED_1                       0x0001
++#define MTK_PHY_AUX_CTRL_AND_STATUS           0x14
++#define   MTK_PHY_ENABLE_DOWNSHIFT            BIT(4)
++
++#define MTK_PHY_PAGE_EXTENDED_2                       0x0002
++#define MTK_PHY_PAGE_EXTENDED_3                       0x0003
++#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11     0x11
++
++#define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
++
++/* Registers on MDIO_MMD_VEND1 */
++#define MTK_PHY_GBE_MODE_TX_DELAY_SEL         0x13
++#define MTK_PHY_TEST_MODE_TX_DELAY_SEL                0x14
++#define   MTK_TX_DELAY_PAIR_B_MASK            GENMASK(10, 8)
++#define   MTK_TX_DELAY_PAIR_D_MASK            GENMASK(2, 0)
++
++#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL    0xa6
++#define   MTK_MCC_NEARECHO_OFFSET_MASK                GENMASK(15, 8)
++
++#define MTK_PHY_RXADC_CTRL_RG7                        0xc6
++#define   MTK_PHY_DA_AD_BUF_BIAS_LP_MASK      GENMASK(9, 8)
++
++#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123    0x123
++#define   MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK      GENMASK(15, 8)
++#define   MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK      GENMASK(7, 0)
+ static void mtk_gephy_config_init(struct phy_device *phydev)
+ {
+       /* Enable HW auto downshift */
+-      phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
++      phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
++                       MTK_PHY_AUX_CTRL_AND_STATUS,
++                       0, MTK_PHY_ENABLE_DOWNSHIFT);
+       /* Increase SlvDPSready time */
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+@@ -29,10 +49,20 @@ static void mtk_gephy_config_init(struct
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+       /* Adjust 100_mse_threshold */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
+-
+-      /* Disable mcc */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
++                     MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123,
++                     MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK |
++                     MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
++                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK,
++                                0xff) |
++                     FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
++                                0xff));
++
++      /* If echo time is narrower than 0x3, it will be regarded as noise */
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1,
++                     MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
++                     MTK_MCC_NEARECHO_OFFSET_MASK,
++                     FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
+ }
+ static int mt7530_phy_config_init(struct phy_device *phydev)
+@@ -40,7 +70,8 @@ static int mt7530_phy_config_init(struct
+       mtk_gephy_config_init(phydev);
+       /* Increase post_update_timer */
+-      phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
++      phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
++                      MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
+       return 0;
+ }
+@@ -51,11 +82,19 @@ static int mt7531_phy_config_init(struct
+       /* PHY link down power saving enable */
+       phy_set_bits(phydev, 0x17, BIT(4));
+-      phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
++                     MTK_PHY_DA_AD_BUF_BIAS_LP_MASK,
++                     FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3));
+       /* Set TX Pair delay selection */
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
+-      phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL,
++                     MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
++                     FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
++                     FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
++      phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL,
++                     MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
++                     FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
++                     FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
+       return 0;
+ }
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -9,6 +9,8 @@
+ #define _MTK_EPHY_H_
+ #define MTK_EXT_PAGE_ACCESS                   0x1f
++#define MTK_PHY_PAGE_STANDARD                 0x0000
++#define MTK_PHY_PAGE_EXTENDED_52B5            0x52b5
+ /* Registers on MDIO_MMD_VEND2 */
+ #define MTK_PHY_LED0_ON_CTRL                  0x24
diff --git a/target/linux/generic/backport-6.12/730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch b/target/linux/generic/backport-6.12/730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch
new file mode 100644 (file)
index 0000000..40ce29f
--- /dev/null
@@ -0,0 +1,448 @@
+From 6e7370079669b0d55c9464bb7c3fb8fb7368b912 Mon Sep 17 00:00:00 2001
+From: Sky Huang <skylake.huang@mediatek.com>
+Date: Thu, 13 Feb 2025 16:05:50 +0800
+Subject: [PATCH 11/20] net: phy: mediatek: Add token ring access helper
+ functions in mtk-phy-lib
+
+This patch adds TR(token ring) manipulations and adds correct
+macro names for those magic numbers. TR is a way to access
+proprietary registers on page 52b5. Use these helper functions
+so we can see which fields we're going to modify/set/clear.
+
+TR functions with __* prefix mean that the operations inside
+aren't wrapped by page select/restore functions.
+
+This patch doesn't really change registers' settings but just
+enhances readability and maintainability.
+
+Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250213080553.921434-3-SkyLake.Huang@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge-soc.c  | 231 +++++++++++++++++--------
+ drivers/net/phy/mediatek/mtk-ge.c      |  11 +-
+ drivers/net/phy/mediatek/mtk-phy-lib.c |  63 +++++++
+ drivers/net/phy/mediatek/mtk.h         |   5 +
+ 4 files changed, 230 insertions(+), 80 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -25,6 +25,90 @@
+ #define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
++/* Registers on Token Ring debug nodes */
++/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */
++/* NormMseLoThresh */
++#define NORMAL_MSE_LO_THRESH_MASK             GENMASK(15, 8)
++
++/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
++/* RemAckCntLimitCtrl */
++#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK      GENMASK(2, 1)
++
++/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */
++/* VcoSlicerThreshBitsHigh */
++#define VCO_SLICER_THRESH_HIGH_MASK           GENMASK(23, 0)
++
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */
++/* DfeTailEnableVgaThresh1000 */
++#define DFE_TAIL_EANBLE_VGA_TRHESH_1000               GENMASK(5, 1)
++
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */
++/* MrvlTrFix100Kp */
++#define MRVL_TR_FIX_100KP_MASK                        GENMASK(22, 20)
++/* MrvlTrFix100Kf */
++#define MRVL_TR_FIX_100KF_MASK                        GENMASK(19, 17)
++/* MrvlTrFix1000Kp */
++#define MRVL_TR_FIX_1000KP_MASK                       GENMASK(16, 14)
++/* MrvlTrFix1000Kf */
++#define MRVL_TR_FIX_1000KF_MASK                       GENMASK(13, 11)
++
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */
++/* VgaDecRate */
++#define VGA_DECIMATION_RATE_MASK              GENMASK(8, 5)
++
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
++/* SlvDSPreadyTime */
++#define SLAVE_DSP_READY_TIME_MASK             GENMASK(22, 15)
++/* MasDSPreadyTime */
++#define MASTER_DSP_READY_TIME_MASK            GENMASK(14, 7)
++
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */
++/* ResetSyncOffset */
++#define RESET_SYNC_OFFSET_MASK                        GENMASK(11, 8)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */
++/* FfeUpdGainForceVal */
++#define FFE_UPDATE_GAIN_FORCE_VAL_MASK                GENMASK(9, 7)
++/* FfeUpdGainForce */
++#define FFE_UPDATE_GAIN_FORCE                 BIT(6)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */
++/* SS: Steady-state, KP: Proportional Gain */
++/* SSTrKp100 */
++#define SS_TR_KP100_MASK                      GENMASK(21, 19)
++/* SSTrKf100 */
++#define SS_TR_KF100_MASK                      GENMASK(18, 16)
++/* SSTrKp1000Mas */
++#define SS_TR_KP1000_MASTER_MASK              GENMASK(15, 13)
++/* SSTrKf1000Mas */
++#define SS_TR_KF1000_MASTER_MASK              GENMASK(12, 10)
++/* SSTrKp1000Slv */
++#define SS_TR_KP1000_SLAVE_MASK                       GENMASK(9, 7)
++/* SSTrKf1000Slv */
++#define SS_TR_KF1000_SLAVE_MASK                       GENMASK(6, 4)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */
++/* RegEEE_st2TrKf1000 */
++#define EEE1000_STAGE2_TR_KF_MASK             GENMASK(13, 11)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */
++/* RegEEE_slv_waketr_timer_tar */
++#define SLAVE_WAKETR_TIMER_MASK                       GENMASK(20, 11)
++/* RegEEE_slv_remtx_timer_tar */
++#define SLAVE_REMTX_TIMER_MASK                        GENMASK(10, 1)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */
++/* RegEEE_slv_wake_int_timer_tar */
++#define SLAVE_WAKEINT_TIMER_MASK              GENMASK(10, 1)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */
++/* RegEEE_trfreeze_timer2 */
++#define TR_FREEZE_TIMER2_MASK                 GENMASK(9, 0)
++
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */
++/* RegEEE100Stg1_tar */
++#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK        GENMASK(8, 0)
++
+ #define ANALOG_INTERNAL_OPERATION_MAX_US      20
+ #define TXRESERVE_MIN                         0
+ #define TXRESERVE_MAX                         7
+@@ -700,40 +784,41 @@ restore:
+ static void mt798x_phy_common_finetune(struct phy_device *phydev)
+ {
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+-      __phy_write(phydev, 0x11, 0xc71);
+-      __phy_write(phydev, 0x12, 0xc);
+-      __phy_write(phydev, 0x10, 0x8fae);
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x17,
++                      SLAVE_DSP_READY_TIME_MASK | MASTER_DSP_READY_TIME_MASK,
++                      FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) |
++                      FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18));
+       /* EnabRandUpdTrig = 1 */
+       __phy_write(phydev, 0x11, 0x2f00);
+       __phy_write(phydev, 0x12, 0xe);
+       __phy_write(phydev, 0x10, 0x8fb0);
+-      /* NormMseLoThresh = 85 */
+-      __phy_write(phydev, 0x11, 0x55a0);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x83aa);
+-
+-      /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
+-      __phy_write(phydev, 0x11, 0x240);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9680);
++      __mtk_tr_modify(phydev, 0x0, 0x7, 0x15,
++                      NORMAL_MSE_LO_THRESH_MASK,
++                      FIELD_PREP(NORMAL_MSE_LO_THRESH_MASK, 0x55));
++
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0x0,
++                      FFE_UPDATE_GAIN_FORCE_VAL_MASK,
++                      FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) |
++                                 FFE_UPDATE_GAIN_FORCE);
+       /* TrFreeze = 0 (mt7988 default) */
+       __phy_write(phydev, 0x11, 0x0);
+       __phy_write(phydev, 0x12, 0x0);
+       __phy_write(phydev, 0x10, 0x9686);
+-      /* SSTrKp100 = 5 */
+-      /* SSTrKf100 = 6 */
+-      /* SSTrKp1000Mas = 5 */
+-      /* SSTrKf1000Mas = 6 */
+-      /* SSTrKp1000Slv = 5 */
+-      /* SSTrKf1000Slv = 6 */
+-      __phy_write(phydev, 0x11, 0xbaef);
+-      __phy_write(phydev, 0x12, 0x2e);
+-      __phy_write(phydev, 0x10, 0x968c);
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0x6,
++                      SS_TR_KP100_MASK | SS_TR_KF100_MASK |
++                      SS_TR_KP1000_MASTER_MASK | SS_TR_KF1000_MASTER_MASK |
++                      SS_TR_KP1000_SLAVE_MASK | SS_TR_KF1000_SLAVE_MASK,
++                      FIELD_PREP(SS_TR_KP100_MASK, 0x5) |
++                      FIELD_PREP(SS_TR_KF100_MASK, 0x6) |
++                      FIELD_PREP(SS_TR_KP1000_MASTER_MASK, 0x5) |
++                      FIELD_PREP(SS_TR_KF1000_MASTER_MASK, 0x6) |
++                      FIELD_PREP(SS_TR_KP1000_SLAVE_MASK, 0x5) |
++                      FIELD_PREP(SS_TR_KF1000_SLAVE_MASK, 0x6));
++
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+ }
+@@ -756,27 +841,29 @@ static void mt7981_phy_finetune(struct p
+       }
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* ResetSyncOffset = 6 */
+-      __phy_write(phydev, 0x11, 0x600);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8fc0);
+-
+-      /* VgaDecRate = 1 */
+-      __phy_write(phydev, 0x11, 0x4c2a);
+-      __phy_write(phydev, 0x12, 0x3e);
+-      __phy_write(phydev, 0x10, 0x8fa4);
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
++                      RESET_SYNC_OFFSET_MASK,
++                      FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x6));
++
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x12,
++                      VGA_DECIMATION_RATE_MASK,
++                      FIELD_PREP(VGA_DECIMATION_RATE_MASK, 0x1));
+       /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
+        * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
+        */
+-      __phy_write(phydev, 0x11, 0xd10a);
+-      __phy_write(phydev, 0x12, 0x34);
+-      __phy_write(phydev, 0x10, 0x8f82);
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
++                      MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
++                      MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
++                      FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x3) |
++                      FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x2) |
++                      FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x3) |
++                      FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x2));
+       /* VcoSlicerThreshBitsHigh */
+-      __phy_write(phydev, 0x11, 0x5555);
+-      __phy_write(phydev, 0x12, 0x55);
+-      __phy_write(phydev, 0x10, 0x8ec0);
++      __mtk_tr_modify(phydev, 0x1, 0xd, 0x20,
++                      VCO_SLICER_THRESH_HIGH_MASK,
++                      FIELD_PREP(VCO_SLICER_THRESH_HIGH_MASK, 0x555555));
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+       /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
+@@ -828,25 +915,23 @@ static void mt7988_phy_finetune(struct p
+       phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* ResetSyncOffset = 5 */
+-      __phy_write(phydev, 0x11, 0x500);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8fc0);
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
++                      RESET_SYNC_OFFSET_MASK,
++                      FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x5));
+       /* VgaDecRate is 1 at default on mt7988 */
+-      /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
+-       * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
+-       */
+-      __phy_write(phydev, 0x11, 0xb90a);
+-      __phy_write(phydev, 0x12, 0x6f);
+-      __phy_write(phydev, 0x10, 0x8f82);
+-
+-      /* RemAckCntLimitCtrl = 1 */
+-      __phy_write(phydev, 0x11, 0xfbba);
+-      __phy_write(phydev, 0x12, 0xc3);
+-      __phy_write(phydev, 0x10, 0x87f8);
+-
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
++                      MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
++                      MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
++                      FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x6) |
++                      FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x7) |
++                      FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x6) |
++                      FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x7));
++
++      __mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
++                      REMOTE_ACK_COUNT_LIMIT_CTRL_MASK,
++                      FIELD_PREP(REMOTE_ACK_COUNT_LIMIT_CTRL_MASK, 0x1));
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+       /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
+@@ -927,40 +1012,36 @@ static void mt798x_phy_eee(struct phy_de
+       __phy_write(phydev, 0x12, 0x0);
+       __phy_write(phydev, 0x10, 0x9690);
+-      /* REG_EEE_st2TrKf1000 = 2 */
+-      __phy_write(phydev, 0x11, 0x114f);
+-      __phy_write(phydev, 0x12, 0x2);
+-      __phy_write(phydev, 0x10, 0x969a);
+-
+-      /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
+-      __phy_write(phydev, 0x11, 0x3028);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x969e);
+-
+-      /* RegEEE_slv_wake_int_timer_tar = 8 */
+-      __phy_write(phydev, 0x11, 0x5010);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96a0);
+-
+-      /* RegEEE_trfreeze_timer2 = 586 */
+-      __phy_write(phydev, 0x11, 0x24a);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96a8);
+-
+-      /* RegEEE100Stg1_tar = 16 */
+-      __phy_write(phydev, 0x11, 0x3210);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96b8);
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0xd,
++                      EEE1000_STAGE2_TR_KF_MASK,
++                      FIELD_PREP(EEE1000_STAGE2_TR_KF_MASK, 0x2));
++
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0xf,
++                      SLAVE_WAKETR_TIMER_MASK | SLAVE_REMTX_TIMER_MASK,
++                      FIELD_PREP(SLAVE_WAKETR_TIMER_MASK, 0x6) |
++                      FIELD_PREP(SLAVE_REMTX_TIMER_MASK, 0x14));
++
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0x10,
++                      SLAVE_WAKEINT_TIMER_MASK,
++                      FIELD_PREP(SLAVE_WAKEINT_TIMER_MASK, 0x8));
++
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0x14,
++                      TR_FREEZE_TIMER2_MASK,
++                      FIELD_PREP(TR_FREEZE_TIMER2_MASK, 0x24a));
++
++      __mtk_tr_modify(phydev, 0x2, 0xd, 0x1c,
++                      EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
++                      FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
++                                 0x10));
+       /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
+       __phy_write(phydev, 0x11, 0x1463);
+       __phy_write(phydev, 0x12, 0x0);
+       __phy_write(phydev, 0x10, 0x96ca);
+-      /* DfeTailEnableVgaThresh1000 = 27 */
+-      __phy_write(phydev, 0x11, 0x36);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x8f80);
++      __mtk_tr_modify(phydev, 0x1, 0xf, 0x0,
++                      DFE_TAIL_EANBLE_VGA_TRHESH_1000,
++                      FIELD_PREP(DFE_TAIL_EANBLE_VGA_TRHESH_1000, 0x1b));
+       phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -18,6 +18,10 @@
+ #define MTK_PHY_PAGE_EXTENDED_2A30            0x2a30
++/* Registers on Token Ring debug nodes */
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
++#define SLAVE_DSP_READY_TIME_MASK             GENMASK(22, 15)
++
+ /* Registers on MDIO_MMD_VEND1 */
+ #define MTK_PHY_GBE_MODE_TX_DELAY_SEL         0x13
+ #define MTK_PHY_TEST_MODE_TX_DELAY_SEL                0x14
+@@ -42,11 +46,8 @@ static void mtk_gephy_config_init(struct
+                        0, MTK_PHY_ENABLE_DOWNSHIFT);
+       /* Increase SlvDPSready time */
+-      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      __phy_write(phydev, 0x10, 0xafae);
+-      __phy_write(phydev, 0x12, 0x2f);
+-      __phy_write(phydev, 0x10, 0x8fae);
+-      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++      mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK,
++                    FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e));
+       /* Adjust 100_mse_threshold */
+       phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -6,6 +6,69 @@
+ #include "mtk.h"
++/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is
++ * mtk_tr* functions: wrapped by page switching operations
++ * __mtk_tr* functions: no page switching operations
++ */
++
++static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr,
++                          u8 node_addr, u8 data_addr)
++{
++      u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
++
++      if (read)
++              tr_cmd |= BIT(13);
++
++      tr_cmd |= (((ch_addr & 0x3) << 11) |
++                 ((node_addr & 0xf) << 7) |
++                 ((data_addr & 0x3f) << 1));
++      dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd);
++      __phy_write(phydev, 0x10, tr_cmd);
++}
++
++static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                        u8 data_addr, u16 *tr_high, u16 *tr_low)
++{
++      __mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr);
++      *tr_low = __phy_read(phydev, 0x11);
++      *tr_high = __phy_read(phydev, 0x12);
++      dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
++              *tr_high, *tr_low);
++}
++
++static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                         u8 data_addr, u32 tr_data)
++{
++      __phy_write(phydev, 0x11, tr_data & 0xffff);
++      __phy_write(phydev, 0x12, tr_data >> 16);
++      dev_dbg(&phydev->mdio.dev, "tr_high write: 0x%x, tr_low write: 0x%x\n",
++              tr_data >> 16, tr_data & 0xffff);
++      __mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
++}
++
++void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                   u8 data_addr, u32 mask, u32 set)
++{
++      u32 tr_data;
++      u16 tr_high;
++      u16 tr_low;
++
++      __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
++      tr_data = (tr_high << 16) | tr_low;
++      tr_data = (tr_data & ~mask) | set;
++      __mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
++}
++EXPORT_SYMBOL_GPL(__mtk_tr_modify);
++
++void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                 u8 data_addr, u32 mask, u32 set)
++{
++      phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
++      __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set);
++      phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
++}
++EXPORT_SYMBOL_GPL(mtk_tr_modify);
++
+ int mtk_phy_read_page(struct phy_device *phydev)
+ {
+       return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -68,6 +68,11 @@ struct mtk_socphy_priv {
+       unsigned long           led_state;
+ };
++void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                   u8 data_addr, u32 mask, u32 set);
++void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                 u8 data_addr, u32 mask, u32 set);
++
+ int mtk_phy_read_page(struct phy_device *phydev);
+ int mtk_phy_write_page(struct phy_device *phydev, int page);
diff --git a/target/linux/generic/backport-6.12/731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch b/target/linux/generic/backport-6.12/731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch
new file mode 100644 (file)
index 0000000..972a9c0
--- /dev/null
@@ -0,0 +1,73 @@
+From c7e2fb3421ef5ebbb4c91f44bd735ab10edd755a Mon Sep 17 00:00:00 2001
+From: Sky Huang <skylake.huang@mediatek.com>
+Date: Thu, 13 Feb 2025 16:05:51 +0800
+Subject: [PATCH 12/20] net: phy: mediatek: Add token ring set bit operation
+ support
+
+Previously in mtk-ge-soc.c, we set some register bits via token
+ring, which were implemented in three __phy_write().
+Now we can do the same thing via __mtk_tr_set_bits() helper.
+
+Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250213080553.921434-4-SkyLake.Huang@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge-soc.c  | 10 ++++++----
+ drivers/net/phy/mediatek/mtk-phy-lib.c |  7 +++++++
+ drivers/net/phy/mediatek/mtk.h         |  2 ++
+ 3 files changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -62,6 +62,10 @@
+ /* MasDSPreadyTime */
+ #define MASTER_DSP_READY_TIME_MASK            GENMASK(14, 7)
++/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */
++/* EnabRandUpdTrig */
++#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER  BIT(8)
++
+ /* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */
+ /* ResetSyncOffset */
+ #define RESET_SYNC_OFFSET_MASK                        GENMASK(11, 8)
+@@ -789,10 +793,8 @@ static void mt798x_phy_common_finetune(s
+                       FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) |
+                       FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18));
+-      /* EnabRandUpdTrig = 1 */
+-      __phy_write(phydev, 0x11, 0x2f00);
+-      __phy_write(phydev, 0x12, 0xe);
+-      __phy_write(phydev, 0x10, 0x8fb0);
++      __mtk_tr_set_bits(phydev, 0x1, 0xf, 0x18,
++                        ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER);
+       __mtk_tr_modify(phydev, 0x0, 0x7, 0x15,
+                       NORMAL_MSE_LO_THRESH_MASK,
+--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -69,6 +69,13 @@ void mtk_tr_modify(struct phy_device *ph
+ }
+ EXPORT_SYMBOL_GPL(mtk_tr_modify);
++void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                     u8 data_addr, u32 set)
++{
++      __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set);
++}
++EXPORT_SYMBOL_GPL(__mtk_tr_set_bits);
++
+ int mtk_phy_read_page(struct phy_device *phydev)
+ {
+       return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -72,6 +72,8 @@ void __mtk_tr_modify(struct phy_device *
+                    u8 data_addr, u32 mask, u32 set);
+ void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+                  u8 data_addr, u32 mask, u32 set);
++void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                     u8 data_addr, u32 set);
+ int mtk_phy_read_page(struct phy_device *phydev);
+ int mtk_phy_write_page(struct phy_device *phydev, int page);
diff --git a/target/linux/generic/backport-6.12/732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch b/target/linux/generic/backport-6.12/732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch
new file mode 100644 (file)
index 0000000..47d891e
--- /dev/null
@@ -0,0 +1,122 @@
+From 7851c73a416b15aff6f9ada9c88affc5f48ff011 Mon Sep 17 00:00:00 2001
+From: Sky Huang <skylake.huang@mediatek.com>
+Date: Thu, 13 Feb 2025 16:05:52 +0800
+Subject: [PATCH 13/20] net: phy: mediatek: Add token ring clear bit operation
+ support
+
+Similar to __mtk_tr_set_bits() support. Previously in mtk-ge-soc.c,
+we clear some register bits via token ring, which were also implemented
+in three __phy_write(). Now we can do the same thing via
+__mtk_tr_clr_bits() helper.
+
+Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250213080553.921434-5-SkyLake.Huang@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge-soc.c  | 30 +++++++++++++++-----------
+ drivers/net/phy/mediatek/mtk-phy-lib.c |  7 ++++++
+ drivers/net/phy/mediatek/mtk.h         |  2 ++
+ 3 files changed, 27 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -76,6 +76,10 @@
+ /* FfeUpdGainForce */
+ #define FFE_UPDATE_GAIN_FORCE                 BIT(6)
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */
++/* TrFreeze */
++#define TR_FREEZE_MASK                                GENMASK(11, 0)
++
+ /* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */
+ /* SS: Steady-state, KP: Proportional Gain */
+ /* SSTrKp100 */
+@@ -91,6 +95,11 @@
+ /* SSTrKf1000Slv */
+ #define SS_TR_KF1000_SLAVE_MASK                       GENMASK(6, 4)
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */
++/* clear this bit if wanna select from AFE */
++/* Regsigdet_sel_1000 */
++#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE      BIT(4)
++
+ /* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */
+ /* RegEEE_st2TrKf1000 */
+ #define EEE1000_STAGE2_TR_KF_MASK             GENMASK(13, 11)
+@@ -113,6 +122,10 @@
+ /* RegEEE100Stg1_tar */
+ #define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK        GENMASK(8, 0)
++/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */
++/* REGEEE_wake_slv_tr_wait_dfesigdet_en */
++#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN   BIT(11)
++
+ #define ANALOG_INTERNAL_OPERATION_MAX_US      20
+ #define TXRESERVE_MIN                         0
+ #define TXRESERVE_MAX                         7
+@@ -805,10 +818,7 @@ static void mt798x_phy_common_finetune(s
+                       FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) |
+                                  FFE_UPDATE_GAIN_FORCE);
+-      /* TrFreeze = 0 (mt7988 default) */
+-      __phy_write(phydev, 0x11, 0x0);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9686);
++      __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x3, TR_FREEZE_MASK);
+       __mtk_tr_modify(phydev, 0x2, 0xd, 0x6,
+                       SS_TR_KP100_MASK | SS_TR_KF100_MASK |
+@@ -1009,10 +1019,8 @@ static void mt798x_phy_eee(struct phy_de
+                        MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
+       phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+-      /* Regsigdet_sel_1000 = 0 */
+-      __phy_write(phydev, 0x11, 0xb);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x9690);
++      __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x8,
++                        EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE);
+       __mtk_tr_modify(phydev, 0x2, 0xd, 0xd,
+                       EEE1000_STAGE2_TR_KF_MASK,
+@@ -1036,10 +1044,8 @@ static void mt798x_phy_eee(struct phy_de
+                       FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
+                                  0x10));
+-      /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
+-      __phy_write(phydev, 0x11, 0x1463);
+-      __phy_write(phydev, 0x12, 0x0);
+-      __phy_write(phydev, 0x10, 0x96ca);
++      __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x25,
++                        WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN);
+       __mtk_tr_modify(phydev, 0x1, 0xf, 0x0,
+                       DFE_TAIL_EANBLE_VGA_TRHESH_1000,
+--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
++++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
+@@ -76,6 +76,13 @@ void __mtk_tr_set_bits(struct phy_device
+ }
+ EXPORT_SYMBOL_GPL(__mtk_tr_set_bits);
++void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                     u8 data_addr, u32 clr)
++{
++      __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0);
++}
++EXPORT_SYMBOL_GPL(__mtk_tr_clr_bits);
++
+ int mtk_phy_read_page(struct phy_device *phydev)
+ {
+       return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -74,6 +74,8 @@ void mtk_tr_modify(struct phy_device *ph
+                  u8 data_addr, u32 mask, u32 set);
+ void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+                      u8 data_addr, u32 set);
++void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
++                     u8 data_addr, u32 clr);
+ int mtk_phy_read_page(struct phy_device *phydev);
+ int mtk_phy_write_page(struct phy_device *phydev, int page);
diff --git a/target/linux/generic/backport-6.12/733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch b/target/linux/generic/backport-6.12/733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch
new file mode 100644 (file)
index 0000000..858de09
--- /dev/null
@@ -0,0 +1,45 @@
+From bae8c61522c4d5a5250a24dcb57d120ea593fab1 Mon Sep 17 00:00:00 2001
+From: Sky Huang <skylake.huang@mediatek.com>
+Date: Thu, 13 Feb 2025 16:05:53 +0800
+Subject: [PATCH 14/20] net: phy: mediatek: Move some macros to phy-lib for
+ later use
+
+Move some macros to phy-lib because MediaTek's 2.5G built-in
+ethernet PHY will also use them.
+
+Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250213080553.921434-6-SkyLake.Huang@mediatek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge.c | 4 ----
+ drivers/net/phy/mediatek/mtk.h    | 4 ++++
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
+@@ -8,10 +8,6 @@
+ #define MTK_GPHY_ID_MT7530            0x03a29412
+ #define MTK_GPHY_ID_MT7531            0x03a29441
+-#define MTK_PHY_PAGE_EXTENDED_1                       0x0001
+-#define MTK_PHY_AUX_CTRL_AND_STATUS           0x14
+-#define   MTK_PHY_ENABLE_DOWNSHIFT            BIT(4)
+-
+ #define MTK_PHY_PAGE_EXTENDED_2                       0x0002
+ #define MTK_PHY_PAGE_EXTENDED_3                       0x0003
+ #define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11     0x11
+--- a/drivers/net/phy/mediatek/mtk.h
++++ b/drivers/net/phy/mediatek/mtk.h
+@@ -8,7 +8,11 @@
+ #ifndef _MTK_EPHY_H_
+ #define _MTK_EPHY_H_
++#define MTK_PHY_AUX_CTRL_AND_STATUS           0x14
++#define   MTK_PHY_ENABLE_DOWNSHIFT            BIT(4)
++
+ #define MTK_EXT_PAGE_ACCESS                   0x1f
++#define MTK_PHY_PAGE_EXTENDED_1                       0x0001
+ #define MTK_PHY_PAGE_STANDARD                 0x0000
+ #define MTK_PHY_PAGE_EXTENDED_52B5            0x52b5
diff --git a/target/linux/generic/backport-6.12/735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch b/target/linux/generic/backport-6.12/735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch
new file mode 100644 (file)
index 0000000..9778ea1
--- /dev/null
@@ -0,0 +1,37 @@
+From e5566162af8b9690e096d2e6089e4ed955a0d13d Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Thu, 10 Apr 2025 12:04:03 +0200
+Subject: [PATCH] net: phy: mediatek: permit to compile test GE SOC PHY driver
+
+When commit 462a3daad679 ("net: phy: mediatek: fix compile-test
+dependencies") fixed the dependency, it should have also introduced
+an or on COMPILE_TEST to permit this driver to be compile-tested even if
+NVMEM_MTK_EFUSE wasn't selected. The driver makes use of NVMEM API that
+are always compiled (return error) so the driver can actually be
+compiled even without that config.
+
+Fix and simplify the dependency condition of this kernel config.
+
+Fixes: 462a3daad679 ("net: phy: mediatek: fix compile-test dependencies")
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://patch.msgid.link/20250410100410.348-1-ansuelsmth@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/Kconfig | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/net/phy/mediatek/Kconfig
++++ b/drivers/net/phy/mediatek/Kconfig
+@@ -15,8 +15,7 @@ config MEDIATEK_GE_PHY
+ config MEDIATEK_GE_SOC_PHY
+       tristate "MediaTek SoC Ethernet PHYs"
+-      depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+-      depends on NVMEM_MTK_EFUSE
++      depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST
+       select MTK_NET_PHYLIB
+       help
+         Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
diff --git a/target/linux/generic/backport-6.12/736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch b/target/linux/generic/backport-6.12/736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch
new file mode 100644 (file)
index 0000000..5498ecb
--- /dev/null
@@ -0,0 +1,129 @@
+From 4590c8bc10951feee3e439bf7fff1b458c2e6fad Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Thu, 10 Apr 2025 12:04:04 +0200
+Subject: [PATCH 17/20] net: phy: mediatek: add Airoha PHY ID to SoC driver
+
+Airoha AN7581 SoC ship with a Switch based on the MT753x Switch embedded
+in other SoC like the MT7581 and the MT7988. Similar to these they
+require configuring some pin to enable LED PHYs.
+
+Add support for the PHY ID for the Airoha embedded Switch and define a
+simple probe function to toggle these pins. Also fill the LED functions
+and add dedicated function to define LED polarity.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://patch.msgid.link/20250410100410.348-2-ansuelsmth@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/Kconfig      |  4 +-
+ drivers/net/phy/mediatek/mtk-ge-soc.c | 62 +++++++++++++++++++++++++++
+ 2 files changed, 65 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/mediatek/Kconfig
++++ b/drivers/net/phy/mediatek/Kconfig
+@@ -15,7 +15,9 @@ config MEDIATEK_GE_PHY
+ config MEDIATEK_GE_SOC_PHY
+       tristate "MediaTek SoC Ethernet PHYs"
+-      depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST
++      depends on ARM64 || COMPILE_TEST
++      depends on ARCH_AIROHA || (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || \
++                 COMPILE_TEST
+       select MTK_NET_PHYLIB
+       help
+         Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -10,8 +10,11 @@
+ #include "mtk.h"
++#define MTK_PHY_MAX_LEDS                      2
++
+ #define MTK_GPHY_ID_MT7981                    0x03a29461
+ #define MTK_GPHY_ID_MT7988                    0x03a29481
++#define MTK_GPHY_ID_AN7581                    0x03a294c1
+ #define MTK_EXT_PAGE_ACCESS                   0x1f
+ #define MTK_PHY_PAGE_STANDARD                 0x0000
+@@ -1405,6 +1408,53 @@ static int mt7981_phy_probe(struct phy_d
+       return mt798x_phy_calibration(phydev);
+ }
++static int an7581_phy_probe(struct phy_device *phydev)
++{
++      struct mtk_socphy_priv *priv;
++      struct pinctrl *pinctrl;
++
++      /* Toggle pinctrl to enable PHY LED */
++      pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
++      if (IS_ERR(pinctrl))
++              dev_err(&phydev->mdio.bus->dev,
++                      "Failed to setup PHY LED pinctrl\n");
++
++      priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      phydev->priv = priv;
++
++      return 0;
++}
++
++static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,
++                                     unsigned long modes)
++{
++      u32 mode;
++      u16 val;
++
++      if (index >= MTK_PHY_MAX_LEDS)
++              return -EINVAL;
++
++      for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
++              switch (mode) {
++              case PHY_LED_ACTIVE_LOW:
++                      val = MTK_PHY_LED_ON_POLARITY;
++                      break;
++              case PHY_LED_ACTIVE_HIGH:
++                      val = 0;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++      }
++
++      return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
++                            MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
++                            MTK_PHY_LED_ON_POLARITY, val);
++}
++
+ static struct phy_driver mtk_socphy_driver[] = {
+       {
+               PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+@@ -1440,6 +1490,17 @@ static struct phy_driver mtk_socphy_driv
+               .led_hw_control_set = mt798x_phy_led_hw_control_set,
+               .led_hw_control_get = mt798x_phy_led_hw_control_get,
+       },
++      {
++              PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581),
++              .name           = "Airoha AN7581 PHY",
++              .probe          = an7581_phy_probe,
++              .led_blink_set  = mt798x_phy_led_blink_set,
++              .led_brightness_set = mt798x_phy_led_brightness_set,
++              .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
++              .led_hw_control_set = mt798x_phy_led_hw_control_set,
++              .led_hw_control_get = mt798x_phy_led_hw_control_get,
++              .led_polarity_set = an7581_phy_led_polarity_set,
++      },
+ };
+ module_phy_driver(mtk_socphy_driver);
+@@ -1447,6 +1508,7 @@ module_phy_driver(mtk_socphy_driver);
+ static const struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+       { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
++      { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581) },
+       { }
+ };
diff --git a/target/linux/generic/backport-6.12/737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch b/target/linux/generic/backport-6.12/737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch
new file mode 100644 (file)
index 0000000..1b1dda2
--- /dev/null
@@ -0,0 +1,40 @@
+From 34501d047ac0a6cbb13285ba9d15f75c1deb7da7 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 15 Apr 2025 12:53:05 +0200
+Subject: [PATCH 18/20] net: phy: mediatek: init val in .phy_led_polarity_set
+ for AN7581
+
+Fix smatch warning for uninitialised val in .phy_led_polarity_set for
+AN7581 driver.
+
+Correctly init to 0 to set polarity high by default.
+
+Reported-by: Simon Horman <horms@kernel.org>
+Fixes: 6a325aed130b ("net: phy: mediatek: add Airoha PHY ID to SoC driver")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://patch.msgid.link/20250415105313.3409-1-ansuelsmth@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/mediatek/mtk-ge-soc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
++++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
+@@ -1431,8 +1431,8 @@ static int an7581_phy_probe(struct phy_d
+ static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,
+                                      unsigned long modes)
+ {
++      u16 val = 0;
+       u32 mode;
+-      u16 val;
+       if (index >= MTK_PHY_MAX_LEDS)
+               return -EINVAL;
+@@ -1443,7 +1443,6 @@ static int an7581_phy_led_polarity_set(s
+                       val = MTK_PHY_LED_ON_POLARITY;
+                       break;
+               case PHY_LED_ACTIVE_HIGH:
+-                      val = 0;
+                       break;
+               default:
+                       return -EINVAL;
index 5f0b61e0ced2473f426efc14b3daf44dccf5d23e..633468f93a3e150d9385d13bb1b8dcff1dc08048 100644 (file)
@@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -358,10 +358,7 @@ config QSEMI_PHY
+@@ -343,10 +343,7 @@ config QSEMI_PHY
        help
          Currently supports the qs6612
  
@@ -38,7 +38,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
        tristate "Renesas PHYs"
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -95,7 +95,7 @@ obj-$(CONFIG_NXP_CBTX_PHY)   += nxp-cbtx.o
+@@ -94,7 +94,7 @@ obj-$(CONFIG_NXP_CBTX_PHY)   += nxp-cbtx.o
  obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
  obj-y                         += qcom/
  obj-$(CONFIG_QSEMI_PHY)               += qsemi.o
index 7443ad2f50bc832d93bafb5ef43b97a8a2573540..98c4186a3ed0e6a19fa7552c6ae0079fe9bfb172 100644 (file)
@@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
  };
  
  module_phy_driver(aqr_driver);
-@@ -1226,6 +1252,8 @@ static struct mdio_device_id __maybe_unu
+@@ -1226,6 +1252,8 @@ static const struct mdio_device_id __may
        { PHY_ID_MATCH_MODEL(PHY_ID_AQR114C) },
        { PHY_ID_MATCH_MODEL(PHY_ID_AQR115C) },
        { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
index e7372dc2cc88f88d5e642921523117235c7fc2d9..616db258906a5f401dd2317409ba4556c662f69e 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -434,6 +434,8 @@ config QSEMI_PHY
+@@ -419,6 +419,8 @@ config QSEMI_PHY
  
  source "drivers/net/phy/realtek/Kconfig"
  
@@ -11,7 +11,7 @@
        help
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -111,6 +111,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY)      += nxp-tja
+@@ -110,6 +110,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY)      += nxp-tja
  obj-y                         += qcom/
  obj-$(CONFIG_QSEMI_PHY)               += qsemi.o
  obj-$(CONFIG_REALTEK_PHY)     += realtek/
index 95134083fa2a4f351948b326ba6f8aa92c8ee47a..2eeca8fd774d5dbc85698a9557c7da0fb5118465 100644 (file)
@@ -12,18 +12,18 @@ plans on integrating their own framework for handling these LEDs.
 
 Signed-off-by: David Bauer <mail@david-bauer.net>
 ---
- drivers/net/phy/mediatek-ge.c | 33 +++++++++++++++++++++++++++++++++
+ drivers/net/phy/mediatek/mtk-ge.c | 33 +++++++++++++++++++++++++++++++++
  1 file changed, 33 insertions(+)
 
---- a/drivers/net/phy/mediatek-ge.c
-+++ b/drivers/net/phy/mediatek-ge.c
+--- a/drivers/net/phy/mediatek/mtk-ge.c
++++ b/drivers/net/phy/mediatek/mtk-ge.c
 @@ -1,4 +1,5 @@
  // SPDX-License-Identifier: GPL-2.0+
 +#include <linux/of.h>
  #include <linux/bitfield.h>
  #include <linux/module.h>
  #include <linux/phy.h>
-@@ -50,6 +51,36 @@ static int mt7530_phy_config_init(struct
+@@ -73,6 +74,36 @@ static int mt7530_phy_config_init(struct
        return 0;
  }
  
@@ -60,9 +60,9 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
  static int mt7531_phy_config_init(struct phy_device *phydev)
  {
        mtk_gephy_config_init(phydev);
-@@ -62,6 +93,9 @@ static int mt7531_phy_config_init(struct
-       phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
-       phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
+@@ -93,6 +124,9 @@ static int mt7531_phy_config_init(struct
+                      FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
+                      FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
  
 +      /* LED Config*/
 +      mt7530_led_config_of(phydev);
index b786c2073ccba1e2b3440a584d907ef6446a159a..c3d246c5eea5f76471863c62a8d9f09745b713e2 100644 (file)
@@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -23666,6 +23666,12 @@ F:    Documentation/filesystems/ubifs-authe
+@@ -23668,6 +23668,12 @@ F:    Documentation/filesystems/ubifs-authe
  F:    Documentation/filesystems/ubifs.rst
  F:    fs/ubifs/