[][kernel][common][eth][Update Airoha EN8811H 2.5G PHY driver to v1.2.8 pre-release]

[Description]
Change Airoha EN8811H 2.5G PHY driver to v1.2.8 pre-release.

Change Log:
[2024/11/01] v1.2.8_pre-release
1.Add airoha,phy-handle parameter to ensure that the settings for
phy-handle and fixed-link can coexist.

=====================================================================
If your board that GMAC2 connects with Airoha EN8811H, please change
the eth node as following.

&eth {
	...

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy-handle = <&phy15>;
	};

	mdio: mdio-bus {
      		#address-cells = <1>;
      		#size-cells = <0>;

      		phy15: phy@15 {
       			compatible = "ethernet-phy-id03a2.a411";
			reg = <15>;
			phy-mode = "2500base-x";
			airoha,polarity = <1>;
			airoha,surge = <0>;
			airoha,phy-handle;
		};

       		...
	};
};

Note:
SerDes polarity setting could be configured in dts. Please refer to the
following description.
Tx Reverse, Rx Normal:
		airoha,polarity = <0>;
Tx Normal, Rx Normal:
		airoha,polarity = <1>;
Tx Reverse, Rx Reverse:
		airoha,polarity = <2>;
Tx Normal, Rx Reverse:
		airoha,polarity = <3>;

Surge protection setting could be configured in dts. Please refer to the
following description.
Surge protection - 0R
		airoha,surge = <0>;
Surge protection - 5R
		airoha,surge = <1>;

=====================================================================
In addition, if EN8811H connects with a RESET GPIO, please check the
GPIO number, and then add reset-gpio related definition to above phy
node.
=====================================================================
reset-gpios = <&gpio 6 1>;
reset-assert-us = <10000>;
reset-deassert-us = <10000>;
=====================================================================

If without this patch, kernel cannot load up-to-date PHY driver
for the Airoha EN8811H.

[Release-log]
N/A


Change-Id: I3feb4a16d6c794db792f108a0655b1f0dd1e12b3
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9885835
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
index 5f5ec38..bd06877 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
@@ -46,7 +46,7 @@
 #define MII_MMD_ADDR_DATA_REG       0x0e
 #define MMD_OP_MODE_DATA            BIT(14)
 
-#define EN8811H_DRIVER_VERSION      "v1.2.7"
+#define EN8811H_DRIVER_VERSION      "v1.2.8_pre_release"
 
 #define LED_ON_CTRL(i)              (0x024 + ((i)*2))
 #define LED_ON_EN                   (1 << 15)
@@ -138,6 +138,7 @@
 	bool                mcu_needs_restart;
 	bool                mcu_reload;
 	int                 debug;
+	int                 phy_handle;
 };
 
 struct air_base_t_led_cfg {
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
index 9ea0b70..3d5cbb8 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
@@ -26,12 +26,6 @@
 #include "air_en8811h.h"
 #include "air_en8811h_api.h"
 
-/*
-struct air_phy_debug {
-	struct dentry *root;
-};
-struct air_phy_debug air_debug;
-*/
 #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 static const char * const tx_rx_string[32] = {
 	"Tx Reverse, Rx Normal",
@@ -471,6 +465,11 @@
 	} else
 		priv->cko = AIR_CKO_DIS;
 
+	if (of_find_property(of_node, "airoha,phy-handle", NULL))
+		priv->phy_handle = true;
+	else
+		priv->phy_handle = false;
+
 	return 0;
 }
 #else
@@ -1268,7 +1267,7 @@
 {
 	struct phy_device *phydev = seq->private;
 	struct mii_bus *mbus = phydev_mdio_bus(phydev);
-	int addr = phydev_addr(phydev);
+	int addr = phydev_addr(phydev), ret;
 
 	seq_puts(seq, "\t<<DEBUG REG DUMP>>\n");
 	seq_printf(seq, "| RG_MII_BMCR           : 0x%08x |\n",
@@ -1287,8 +1286,10 @@
 		   air_mii_cl22_read(mbus, addr, MII_STAT1000));
 	seq_printf(seq, "| RG_LINK_PARTNER_2G5   : 0x%08x |\n",
 		   air_buckpbus_reg_read(phydev, 0x3b30));
+	ret = air_mii_cl22_write(mbus, addr, 0x1f, 0x0);
+	ret = air_mii_cl22_read(mbus, addr, 0x1d);
 	seq_printf(seq, "| RG_MII_REF_CLK        : 0x%08x |\n",
-		   air_mii_cl22_read(mbus, addr, 0x1d));
+		   ret);
 	seq_printf(seq, "| RG_HW_STRAP1          : 0x%08x |\n",
 		   air_buckpbus_reg_read(phydev, 0xcf910));
 	seq_printf(seq, "| RG_HW_STRAP2          : 0x%08x |\n",
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
index b0b4290..7dbf66d 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
@@ -36,7 +36,6 @@
  **************************/
 /* User-defined.B */
 /* #define AIR_MD32_FW_CHECK */
-#define AIR_PHY_HANDLE_SUPPORT
 #define AIR_LED_SUPPORT
 #ifdef AIR_LED_SUPPORT
 static const struct air_base_t_led_cfg led_cfg[3] = {
@@ -422,8 +421,10 @@
 		return -ENOMEM;
 	phydev->priv = priv;
 	ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
-	if (ret < 0)
-		goto priv_free;
+	if (ret < 0) {
+		kfree(priv);
+		return ret;
+	}
 	pid1 = air_mii_cl22_read(mbus, addr, MII_PHYSID1);
 	pid2 = air_mii_cl22_read(mbus, addr, MII_PHYSID2);
 	dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
@@ -436,21 +437,30 @@
 	pbus_value = air_buckpbus_reg_read(phydev, 0xcf914);
 	dev_info(dev, "Bootmode: %s\n",
 			(GET_BIT(pbus_value, 24) ? "Flash" : "Download Code"));
+	ret = en8811h_of_init(phydev);
+	if (ret < 0) {
+		kfree(priv);
+		return ret;
+	}
 	ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
 	ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
-	if (ret < 0)
-		goto priv_free;
+	if (ret < 0) {
+		kfree(priv);
+		return ret;
+	}
 	ret = en8811h_load_firmware(phydev);
 	if (ret < 0) {
 		dev_err(dev, "EN8811H load firmware fail.\n");
-		goto priv_free;
+		kfree(priv);
+		return ret;
 	}
 #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	ret = airphy_debugfs_init(phydev);
 	if (ret < 0) {
 		dev_err(dev, "air_debug_procfs_init fail. (ret=%d)\n", ret);
 		airphy_debugfs_remove(phydev);
-		goto priv_free;
+		kfree(priv);
+		return ret;
 	}
 #endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
 	retry = MAX_RETRY;
@@ -461,7 +471,6 @@
 			dev_info(dev, "EN8811H PHY ready!\n");
 			break;
 		}
-		retry--;
 		if (retry == 0) {
 			dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
 			pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
@@ -469,66 +478,65 @@
 				"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
 			dev_err(dev,
 				"EN8811H initialize fail!\n");
-			goto priv_free;
+			kfree(priv);
+			return ret;
 		}
-	} while (retry);
-#ifdef AIR_PHY_HANDLE_SUPPORT
-	priv->mcu_needs_restart = false;
-	dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
-	return 0;
-priv_free:
-	kfree(priv);
-	return ret;
-#else
-	ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
-	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
-	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
-	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
-	if (ret < 0)
-		goto priv_free;
-	/* Serdes polarity */
-	ret = en8811h_of_init(phydev);
-	if (ret < 0)
-		goto priv_free;
-	pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
-	pbus_value &= ~0x3;
+	} while (retry--);
+
+	if (priv->phy_handle) {
+		priv->mcu_needs_restart = false;
+		dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
+	} else {
+		ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
+		ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
+		ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
+		ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
+		if (ret < 0) {
+			kfree(priv);
+			return ret;
+		}
+		pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
+		pbus_value &= ~0x3;
 #if defined(CONFIG_OF)
-	pbus_value |= priv->pol;
+		pbus_value |= priv->pol;
 #else
-	pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
+		pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
 #endif
-	ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
-	if (ret < 0)
-		goto priv_free;
-	pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
-	dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
-	priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
-	dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
-	ret = air_surge_protect_cfg(phydev);
-	if (ret < 0) {
-		dev_err(dev,
-			"air_surge_protect_cfg fail. (ret=%d)\n", ret);
-		goto priv_free;
-	}
-	ret = air_cko_cfg(phydev);
-	if (ret < 0) {
-		dev_err(dev,
-			"air_cko_cfg fail. (ret=%d)\n", ret);
-		goto priv_free;
-	}
+		ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
+		if (ret < 0) {
+			kfree(priv);
+			return ret;
+		}
+		pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
+		dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
+		priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
+		dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
+		ret = air_surge_protect_cfg(phydev);
+		if (ret < 0) {
+			dev_err(dev,
+				"air_surge_protect_cfg fail. (ret=%d)\n", ret);
+			kfree(priv);
+			return ret;
+		}
+		ret = air_cko_cfg(phydev);
+		if (ret < 0) {
+			dev_err(dev,
+				"air_cko_cfg fail. (ret=%d)\n", ret);
+			kfree(priv);
+			return ret;
+		}
 #if defined(AIR_LED_SUPPORT)
-	ret = en8811h_led_init(phydev);
-	if (ret < 0) {
-		dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
-		goto priv_free;
-	}
+		ret = en8811h_led_init(phydev);
+		if (ret < 0) {
+			dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
+			kfree(priv);
+			return ret;
+		}
 #endif
-	dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
+
+		dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
+	}
 	return 0;
-priv_free:
-	kfree(priv);
-	return ret;
-#endif
 }
 
 void en8811h_remove(struct phy_device *phydev)
@@ -547,7 +555,6 @@
 	}
 }
 
-#ifdef AIR_PHY_HANDLE_SUPPORT
 static int en8811h_restart_mcu(struct phy_device *phydev)
 {
 	int ret, retry, reg_value;
@@ -635,6 +642,8 @@
 	u32 pbus_value = 0;
 	struct device *dev = phydev_dev(phydev);
 	struct en8811h_priv *priv = phydev->priv;
+	int addr = phydev_addr(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
 
 	ret = en8811h_check_mcu(phydev);
 	if (ret < 0) {
@@ -699,6 +708,12 @@
 		goto priv_free;
 	}
 #endif
+	ret = air_mii_cl22_read(mbus, addr, MII_BMCR);
+	ret |= (BMCR_ANRESTART | BMCR_ANENABLE);
+	ret = air_mii_cl22_write(mbus, addr, MII_BMCR, ret);
+	if (ret < 0)
+		goto priv_free;
+
 	dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
 	return 0;
 priv_free:
@@ -777,10 +792,11 @@
 				 phydev->lp_advertising,
 				 phydev->speed == SPEED_2500);
 	}
+	if (phydev->speed <= SPEED_1000)
+		phydev->pause = 1;
 
 	return 0;
 }
-#endif /*AIR_PHY_HANDLE_SUPPORT*/
 
 static struct phy_driver en8811h_driver[] = {
 {
@@ -794,14 +810,12 @@
 	.read_mmd       = __air_mii_cl45_read,
 	.write_mmd      = __air_mii_cl45_write,
 #endif
-#ifdef AIR_PHY_HANDLE_SUPPORT
 	.config_init        = en8811h_config_init,
 	.read_status        = en8811h_read_status,
 	.get_rate_matching  = en8811h_get_rate_matching,
 	.config_aneg        = en8811h_config_aneg,
 	.resume             = genphy_resume,
 	.suspend            = genphy_suspend,
-#endif
 } };
 
 int __init en8811h_phy_driver_register(void)