| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/26 07:44 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific Ethernet PHY driver for Airoha SoCs and refactors shared MediaTek PHY library code. This code requires physical Airoha/MediaTek hardware (or specific MDIO bus emulation) to be probed and executed, which is not available in standard QEMU or virtualized environments. Therefore, it is unreachable during fuzzing.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/26 07:44 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 4bc164341d3cd4731036d67a6c6b951bf996ed51\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Jul 26 07:44:10 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex 60cff00953dcbe..cf06a1512101cb 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -760,6 +760,14 @@ S:\tMaintained\n F:\tDocumentation/devicetree/bindings/net/airoha,en7581-eth.yaml\n F:\tdrivers/net/ethernet/airoha/\n \n+AIROHA ETHERNET PHY DRIVER\n+M:\tChristian Marangi \u003cansuelsmth@gmail.com\u003e\n+L:\tlinux-arm-kernel@lists.infradead.org (moderated for non-subscribers)\n+L:\tlinux-mediatek@lists.infradead.org (moderated for non-subscribers)\n+L:\tnetdev@vger.kernel.org\n+S:\tMaintained\n+F:\tdrivers/net/phy/mediatek/airoha-ge-soc.c\n+\n AIROHA PCIE PHY DRIVER\n M:\tLorenzo Bianconi \u003clorenzo@kernel.org\u003e\n L:\tlinux-arm-kernel@lists.infradead.org (moderated for non-subscribers)\n@@ -16500,6 +16508,7 @@ L:\tnetdev@vger.kernel.org\n S:\tMaintained\n F:\tdrivers/net/phy/mediatek/mtk-2p5ge.c\n F:\tdrivers/net/phy/mediatek/mtk-ge-soc.c\n+F:\tdrivers/net/phy/mediatek/mtk-ge-soc.h\n F:\tdrivers/net/phy/mediatek/mtk-phy-lib.c\n F:\tdrivers/net/phy/mediatek/mtk-ge.c\n F:\tdrivers/net/phy/mediatek/mtk.h\ndiff --git a/drivers/net/phy/mediatek/Kconfig b/drivers/net/phy/mediatek/Kconfig\nindex bb7dc876271e83..fe51f4616c544f 100644\n--- a/drivers/net/phy/mediatek/Kconfig\n+++ b/drivers/net/phy/mediatek/Kconfig\n@@ -1,4 +1,17 @@\n # SPDX-License-Identifier: GPL-2.0-only\n+config AIROHA_GE_SOC_PHY\n+\ttristate \"Airoha SoC Ethernet PHYs\"\n+\tdepends on ARM64 || COMPILE_TEST\n+\tdepends on ARCH_AIROHA || COMPILE_TEST\n+\tselect MTK_NET_PHYLIB\n+\tselect PHY_PACKAGE\n+\thelp\n+\t Supports Airoha SoC built-in Gigabit Ethernet PHYs.\n+\n+\t Include support for built-in Ethernet PHYs which are present in\n+\t the AN7581 and AN7583 SoCs. These PHYs d will dynamically\n+\t calibrate during startup.\n+\n config MEDIATEK_2P5GE_PHY\n \ttristate \"MediaTek 2.5Gb Ethernet PHYs\"\n \tdepends on (ARM64 \u0026\u0026 ARCH_MEDIATEK) || COMPILE_TEST\n@@ -24,8 +37,7 @@ config MEDIATEK_GE_PHY\n config MEDIATEK_GE_SOC_PHY\n \ttristate \"MediaTek SoC Ethernet PHYs\"\n \tdepends on ARM64 || COMPILE_TEST\n-\tdepends on ARCH_AIROHA || (ARCH_MEDIATEK \u0026\u0026 NVMEM_MTK_EFUSE) || \\\n-\t\t COMPILE_TEST\n+\tdepends on (ARCH_MEDIATEK \u0026\u0026 NVMEM_MTK_EFUSE) || COMPILE_TEST\n \tselect MTK_NET_PHYLIB\n \tselect PHY_PACKAGE\n \thelp\ndiff --git a/drivers/net/phy/mediatek/Makefile b/drivers/net/phy/mediatek/Makefile\nindex ac57ecc799fc81..eb430f008169e2 100644\n--- a/drivers/net/phy/mediatek/Makefile\n+++ b/drivers/net/phy/mediatek/Makefile\n@@ -1,4 +1,5 @@\n # SPDX-License-Identifier: GPL-2.0\n+obj-$(CONFIG_AIROHA_GE_SOC_PHY)\t\t+= airoha-ge-soc.o\n obj-$(CONFIG_MEDIATEK_2P5GE_PHY)\t+= mtk-2p5ge.o\n obj-$(CONFIG_MEDIATEK_GE_PHY)\t\t+= mtk-ge.o\n obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)\t+= mtk-ge-soc.o\ndiff --git a/drivers/net/phy/mediatek/airoha-ge-soc.c b/drivers/net/phy/mediatek/airoha-ge-soc.c\nnew file mode 100644\nindex 00000000000000..601a64d8336542\n--- /dev/null\n+++ b/drivers/net/phy/mediatek/airoha-ge-soc.c\n@@ -0,0 +1,1812 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+#include \u003clinux/bitfield.h\u003e\n+#include \u003clinux/pinctrl/consumer.h\u003e\n+#include \u003clinux/phy.h\u003e\n+\n+#include \"../phylib.h\"\n+#include \"mtk.h\"\n+#include \"mtk-ge-soc.h\"\n+\n+#define AIROHA_DEFAULT_PORT0_ADDR\t\t0x9\n+#define AIROHA_PHY_MAX_LEDS\t\t\t2\n+\n+enum airoha_mdi_resister_type {\n+\tMDI_0R,\n+\tMDI_5R,\n+\n+\tMDI_TYPE_MAX,\n+};\n+\n+enum airoha_transformer_type {\n+\tTXMR,\n+\tDISCRETE,\n+\n+\tTRANSFORMER_TYPE_MAX,\n+};\n+\n+enum airoha_calib_const_type {\n+\tTX_AMP_TEST_A,\n+\tTX_AMP_TEST_B,\n+\tTX_AMP_TEST_C,\n+\tTX_AMP_TEST_D,\n+\tTX_AMP_1G_A,\n+\tTX_AMP_1G_B,\n+\tTX_AMP_1G_C,\n+\tTX_AMP_1G_D,\n+\tTX_AMP_100M_A,\n+\tTX_AMP_100M_B,\n+\tTX_AMP_10M_A,\n+\tTX_AMP_10M_B,\n+\tR50_A,\n+\tR50_B,\n+\tR50_C,\n+\tR50_D,\n+\n+\tCALIB_CONST_TYPE_MAX,\n+};\n+\n+struct airoha_socphy_shared {\n+\tstruct phy_device *phydev_p0;\n+\tenum airoha_transformer_type transformer_type[4];\n+\tenum airoha_mdi_resister_type mdi_resister_type;\n+\tbool rext_sw_calib_done;\n+\tint (*tx_amp_compensation_tbl)[TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4];\n+\tu8 *r50_cal_tbl;\n+};\n+\n+/*\n+ * 2 chip revision\n+ * TXMR or discrete\n+ * 2 MDI type\n+ * TX AMP test/TX AMP 1G/TX AMP 100M/TX AMP 10M/R50\n+ * 4 PHY\n+ */\n+static int an7581_tx_amp_compensation_tbl[2][TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4] = {\n+\t{ /* IC version 1 */\n+\t\t[TXMR] = {\n+\t\t\t{ },\n+\t\t\t{\n+\t\t\t\t[TX_AMP_TEST_A] = { -12, -11, -9, -6 },\n+\t\t\t\t[TX_AMP_TEST_B] = { -9, -13, -9, -5 },\n+\t\t\t\t[TX_AMP_TEST_C] = { -5, -4, -3, 1 },\n+\t\t\t\t[TX_AMP_TEST_D] = { -9, -8, -7, -5 },\n+\t\t\t\t[TX_AMP_1G_A] = { -12, -11, -9, -6 },\n+\t\t\t\t[TX_AMP_1G_B] = { -9, -13, -9, -5 },\n+\t\t\t\t[TX_AMP_1G_C] = { -5, -4, -3, 1 },\n+\t\t\t\t[TX_AMP_1G_D] = { -9, -8, -7, -5 },\n+\t\t\t\t[TX_AMP_100M_A] = { -2, -2, 0, 2 },\n+\t\t\t\t[TX_AMP_100M_B] = { -2, -2, 1, 1 },\n+\t\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_A] = { 15, 15, 15, 15 },\n+\t\t\t\t[R50_B] = { 15, 15, 18, 15 },\n+\t\t\t\t[R50_C] = { -8, -8, -8, -8 },\n+\t\t\t\t[R50_D] = { -8, -8, -8, -8 },\n+\t\t\t},\n+\t\t},\n+\t\t[DISCRETE] = {\n+\t\t\t{ },\n+\t\t\t{\n+\t\t\t\t[TX_AMP_TEST_A] = { -9, -7, -7, -5 },\n+\t\t\t\t[TX_AMP_TEST_B] = { -9, -9, -7, -4 },\n+\t\t\t\t[TX_AMP_TEST_C] = { -9, -7, -9, -6 },\n+\t\t\t\t[TX_AMP_TEST_D] = { -11, -9, -10, -8 },\n+\t\t\t\t[TX_AMP_1G_A] = { -9, -7, -7, -5 },\n+\t\t\t\t[TX_AMP_1G_B] = { -9, -8, -7, -4 },\n+\t\t\t\t[TX_AMP_1G_C] = { -9, -7, -9, -6 },\n+\t\t\t\t[TX_AMP_1G_D] = { -11, -8, -10, -8 },\n+\t\t\t\t[TX_AMP_100M_A] = { 4, 3, 4, 4 },\n+\t\t\t\t[TX_AMP_100M_B] = { 4, 4, 5, 4 },\n+\t\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_A] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_B] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_C] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_D] = { 0, 0, 0, 0 },\n+\t\t\t},\n+\t\t},\n+\t},\n+\t{ /* IC version 2 */\n+\t\t[TXMR] = {\n+\t\t\t{ },\n+\t\t\t{\n+\t\t\t\t[TX_AMP_TEST_A] = { -10, -12, -12, -11 },\n+\t\t\t\t[TX_AMP_TEST_B] = { -10, -11, -11, -10 },\n+\t\t\t\t[TX_AMP_TEST_C] = { -5, -7, -9, -3 },\n+\t\t\t\t[TX_AMP_TEST_D] = { -8, -10, -7, -8 },\n+\t\t\t\t[TX_AMP_1G_A] = { -12, -6, -6, 4 },\n+\t\t\t\t[TX_AMP_1G_B] = { -10, -5, -5, 1 },\n+\t\t\t\t[TX_AMP_1G_C] = { -5, -3, -4, 11 },\n+\t\t\t\t[TX_AMP_1G_D] = { -8, -3, -3, 4 },\n+\t\t\t\t[TX_AMP_100M_A] = { 2, 1, 0, 3 },\n+\t\t\t\t[TX_AMP_100M_B] = { 0, 0, 0, 3 },\n+\t\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_A] = { 15, 15, 15, 15 },\n+\t\t\t\t[R50_B] = { 15, 15, 18, 15 },\n+\t\t\t\t[R50_C] = { 4, 4, 4, 4 },\n+\t\t\t\t[R50_D] = { 4, 4, 4, 4 },\n+\t\t\t},\n+\t\t},\n+\t\t[DISCRETE] = {\n+\t\t\t{ },\n+\t\t\t{\n+\t\t\t\t[TX_AMP_TEST_A] = { -11, 11, -12, -7 },\n+\t\t\t\t[TX_AMP_TEST_B] = { -9, -10, -9, -8 },\n+\t\t\t\t[TX_AMP_TEST_C] = { -6, -3, -7, -4 },\n+\t\t\t\t[TX_AMP_TEST_D] = { -7, -8, -10, -7 },\n+\t\t\t\t[TX_AMP_1G_A] = { -11, -11, -12, -7 },\n+\t\t\t\t[TX_AMP_1G_B] = { -9, -10, -9, -8 },\n+\t\t\t\t[TX_AMP_1G_C] = { -6, -3, -7, -4 },\n+\t\t\t\t[TX_AMP_1G_D] = { -7, -8, -10, -7 },\n+\t\t\t\t[TX_AMP_100M_A] = { 2, 2, 1, 2 },\n+\t\t\t\t[TX_AMP_100M_B] = { 3, 3, 3, 3 },\n+\t\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t\t[R50_A] = { 12, 12, 12, 12 },\n+\t\t\t\t[R50_B] = { 7, 7, 7, 7 },\n+\t\t\t\t[R50_C] = { 2, 2, 0, 0 },\n+\t\t\t\t[R50_D] = { 0, 0, 2, 2 },\n+\t\t\t},\n+\t\t},\n+\t},\n+};\n+\n+static u8 an7581_zcal_to_r45ohm[64] = {\n+\t127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,\n+\t127, 127, 127, 127, 127, 127, 127, 127, 123, 119, 115, 112, 108, 104, 100, 96,\n+\t 94, 92, 88, 85, 82, 80, 76, 74, 72, 68, 66, 64, 62, 60, 56, 55,\n+\t 52, 50, 48, 46, 44, 42, 40, 39, 36, 35, 32, 32, 30, 28, 27, 25\n+};\n+\n+/*\n+ * 2 chip revision\n+ * TXMR or discrete\n+ * 2 MDI type\n+ * TX AMP test/TX AMP 1G/TX AMP 100M/TX AMP 10M/R50\n+ * 4 PHY\n+ */\n+static int an7583_tx_amp_compensation_tbl[TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4] = {\n+\t[TXMR] = {\n+\t\t[MDI_0R] = {\n+\t\t\t[TX_AMP_TEST_A] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_B] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_C] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_D] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_1G_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_B] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_C] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_D] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_100M_A] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_100M_B] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t[R50_A] = { 4, 4, 0, 0 },\n+\t\t\t[R50_B] = { 4, 4, 0, 0 },\n+\t\t\t[R50_C] = { 5, 5, 3, 4 },\n+\t\t\t[R50_D] = { 4, 4, 4, 0 },\n+\t\t},\n+\t\t[MDI_5R] = {\n+\t\t\t[TX_AMP_TEST_A] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_B] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_C] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_D] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_1G_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_B] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_C] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_D] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_100M_A] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_100M_B] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t[R50_A] = { -4, -4, -4, -4 },\n+\t\t\t[R50_B] = { -4, -4, -4, -4 },\n+\t\t\t[R50_C] = { -2, -2, -2, -2 },\n+\t\t\t[R50_D] = { -3, -3, -2, -2 },\n+\t\t},\n+\t},\n+\t[DISCRETE] = {\n+\t\t[MDI_0R] = {\n+\t\t\t[TX_AMP_TEST_A] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_B] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_C] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_D] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_1G_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_B] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_C] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_D] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_100M_A] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_100M_B] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t[R50_A] = { 4, 4, 4, 4 },\n+\t\t\t[R50_B] = { 4, 4, 4, 4 },\n+\t\t\t[R50_C] = { 6, 6, 6, 6 },\n+\t\t\t[R50_D] = { 4, 4, 4, 4 },\n+\t\t},\n+\t\t[MDI_5R] = {\n+\t\t\t[TX_AMP_TEST_A] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_B] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_C] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_TEST_D] = { -3, -3, -3, -3 },\n+\t\t\t[TX_AMP_1G_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_B] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_C] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_1G_D] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_100M_A] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_100M_B] = { 4, 4, 4, 4 },\n+\t\t\t[TX_AMP_10M_A] = { 0, 0, 0, 0 },\n+\t\t\t[TX_AMP_10M_B] = { 0, 0, 0, 0 },\n+\t\t\t[R50_A] = { 0, 0, 0, 0 },\n+\t\t\t[R50_B] = { 0, 0, 0, 0 },\n+\t\t\t[R50_C] = { 0, 0, 0, 0 },\n+\t\t\t[R50_D] = { 0, 0, 0, 0 },\n+\t\t},\n+\t},\n+};\n+\n+static u8 an7583_zcal_to_r50ohm_0R[64] = {\n+\t127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,\n+\t127, 127, 127, 122, 118, 114, 110, 106, 102, 98, 96, 92, 88, 85, 82, 80,\n+\t 76, 72, 70, 68, 64, 62, 60, 57, 55, 52, 50, 48, 46, 44, 41, 40,\n+\t 38, 36, 33, 32, 30, 28, 26, 24, 24, 22, 20, 18, 16, 16, 14, 12,\n+};\n+\n+static u8 an7583_zcal_to_r50ohm_5R[64] = {\n+\t127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,\n+\t127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 120, 116, 112, 110, 106, 102,\n+\t 99, 96, 93, 90, 88, 84, 81, 79, 76, 73, 71, 68, 66, 64, 61, 59,\n+\t 56, 54, 52, 50, 48, 46, 44, 42, 40, 39, 37, 36, 33, 32, 31, 29,\n+};\n+\n+static int airoha_cal_cycle(struct phy_device *phydev, int devad,\n+\t\t\t u32 regnum, u16 mask, u16 cal_val)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\n+\tphy_modify_mmd(phydev, devad, regnum, mask, cal_val);\n+\n+\tret = mtk_cal_cycle_wait(phydev_p0);\n+\tphydev_dbg(phydev, \"cal_val: 0x%x, ret: %d\\n\", cal_val, ret);\n+\n+\treturn ret;\n+}\n+\n+static int airoha_rext_cal_sw(struct phy_device *phydev)\n+{\n+\tint calibration_polarity;\n+\tu8 zcal_ctrl = 32;\n+\tint first_calib;\n+\tint ret;\n+\n+\t/* BG voltage output */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x100, 0xc000);\n+\t/* tst_mode2 */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0xff, 0x2);\n+\n+\tphy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 0xff,\n+\t\t\t GENMASK(15, 4) | GENMASK(1, 0));\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN |\n+\t\t MTK_PHY_RG_REXT_CALEN);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0);\n+\n+\tphydev_dbg(phydev, \"Start REXT SW cal.\\n\");\n+\tfirst_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,\n+\t\t\t\t MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);\n+\n+\tif (first_calib \u003c 0) {\n+\t\tphydev_err(phydev, \"REXT SW calibration failed.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* If REXT calibration failed:\n+\t * - increase dB until calibration succeed.\n+\t * If REXT calibration succeeded:\n+\t * - decrease dB until calibration fail to fine tune it.\n+\t */\n+\tif (first_calib == 1)\n+\t\tcalibration_polarity = -1;\n+\telse\n+\t\tcalibration_polarity = 1;\n+\n+\twhile (zcal_ctrl \u003e 0 \u0026\u0026\n+\t zcal_ctrl \u003c FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {\n+\t\tzcal_ctrl += calibration_polarity;\n+\n+\t\tret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,\n+\t\t\t\t MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);\n+\t\t/* Exit if we either failed or succeeded compared to the\n+\t\t * first calibration result. (aka we finished fine tuning or\n+\t\t * we succeeded with calibration)\n+\t\t */\n+\t\tif (ret != first_calib)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (ret \u003c 0) {\n+\t\tphydev_err(phydev, \"REXT SW calibration failed.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (zcal_ctrl == 0 ||\n+\t zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {\n+\t\tzcal_ctrl = 32;\n+\t\tphydev_err(phydev, \"REXT SW calibration saturation. Defaulting to %x.\\n\",\n+\t\t\t zcal_ctrl);\n+\t}\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,\n+\t\t MTK_PHY_RG_REXT_TRIM_MASK,\n+\t\t FIELD_PREP(MTK_PHY_RG_REXT_TRIM_MASK, zcal_ctrl));\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,\n+\t\t MTK_PHY_RG_BG_RASEL_MASK,\n+\t\t FIELD_PREP(MTK_PHY_RG_BG_RASEL_MASK, zcal_ctrl \u003e\u003e 3));\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_tx_offset_cal_sw(struct phy_device *phydev, u8 txg_calen_x)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tu16 dev1e_145_tmp, bmcr_tmp;\n+\tint calibration_polarity;\n+\tu16 reg_dac1, reg_dac2;\n+\tint zcal_ctrl = 0;\n+\tint first_calib;\n+\tu16 reg, mask;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\n+\t/* BG voltage output */\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_ANA_CALEN);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t MTK_PHY_RG_TXVOS_CALEN);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_ANA_CALEN);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t MTK_PHY_RG_TXVOS_CALEN);\n+\n+\t/* Force 1G full duplex for calibration */\n+\tbmcr_tmp = phy_read(phydev, MII_BMCR);\n+\tphy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);\n+\n+\t/* Force MDI */\n+\tdev1e_145_tmp = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x0145);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, 0x1010);\n+\n+\t/* 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96,\n+\t\t 0x8000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e,\n+\t\t 0xf808);\n+\n+\tswitch (txg_calen_x) {\n+\tcase PAIR_A:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_A;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_A;\n+\t\treg = MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B;\n+\t\tmask = MTK_PHY_CR_TX_AMP_OFFSET_A_MASK;\n+\t\tbreak;\n+\tcase PAIR_B:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(8));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_B;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_B;\n+\t\treg = MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B;\n+\t\tmask = MTK_PHY_CR_TX_AMP_OFFSET_B_MASK;\n+\t\tbreak;\n+\tcase PAIR_C:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(4));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_C;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_C;\n+\t\treg = MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D;\n+\t\tmask = MTK_PHY_CR_TX_AMP_OFFSET_C_MASK;\n+\t\tbreak;\n+\tcase PAIR_D:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(0));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_D;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_D;\n+\t\treg = MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D;\n+\t\tmask = MTK_PHY_CR_TX_AMP_OFFSET_D_MASK;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac1,\n+\t\t 0x8000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac2,\n+\t\t 0x8000);\n+\n+\tphydev_dbg(phydev, \"Start TX Offset SW cal.\\n\");\n+\n+\tfirst_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg, mask,\n+\t\t\t\t zcal_ctrl \u003c\u003c __ffs(mask));\n+\n+\t/* If TX Offset calibration failed:\n+\t * - increase dB until calibration succeed.\n+\t * If TX Offset calibration succeeded:\n+\t * - decrease dB until calibration fail to fine tune it.\n+\t */\n+\tif (first_calib == 1)\n+\t\tcalibration_polarity = -1;\n+\telse\n+\t\tcalibration_polarity = 1;\n+\n+\twhile (zcal_ctrl \u003e -32 \u0026\u0026 zcal_ctrl \u003c 32) {\n+\t\tu32 val;\n+\n+\t\tzcal_ctrl += calibration_polarity;\n+\t\tif (zcal_ctrl \u003e= 0)\n+\t\t\tval = zcal_ctrl;\n+\t\telse\n+\t\t\t/* BIT(5) signal negative number for TX Offset */\n+\t\t\tval = BIT(5) | abs(zcal_ctrl);\n+\n+\t\tret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg, mask,\n+\t\t\t\t val \u003c\u003c __ffs(mask));\n+\t\t/* Exit if we either failed or succeeded compared to the\n+\t\t * first calibration result. (aka we finished fine tuning or\n+\t\t * we succeeded with calibration)\n+\t\t */\n+\t\tif (ret != first_calib)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (ret \u003c 0) {\n+\t\tphydev_err(phydev, \"TX Offset calibration failed.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (zcal_ctrl == -32 ||\n+\t zcal_ctrl == 32) {\n+\t\tzcal_ctrl = 0;\n+\t\tphydev_err(phydev, \"TX Offset SW calibration saturation. Defaulting to %x.\\n\",\n+\t\t\t zcal_ctrl);\n+\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1, reg, mask,\n+\t\t\t zcal_ctrl \u003c\u003c __ffs(mask));\n+\t}\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x100, 0x0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D, 0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96, 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0);\n+\n+\t/* Restore BMCR */\n+\tphy_write(phydev, MII_BMCR, bmcr_tmp);\n+\n+\t/* Restore MDI */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, dev1e_145_tmp);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_tx_amp_cal_sw(struct phy_device *phydev, u8 txg_calen_x)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tu16 mask_gbe, mask_tbt, mask_tst, mask_hbt;\n+\tu16 reg, reg_100, reg_dac1, reg_dac2;\n+\tstruct phy_device *phydev_p0;\n+\tint calibration_polarity;\n+\tu8 zcal_ctrl = 32;\n+\tint first_calib;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\n+\t/* BG voltage output */\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x145, 0x1010);\n+\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t MTK_PHY_RG_TXVOS_CALEN);\n+\n+\t/* select 1V */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);\n+\n+\t/* enable Tx VLD*/\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xf808);\n+\n+\t/* Force 1G full duplex for calibration */\n+\tphy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);\n+\n+\tswitch (txg_calen_x) {\n+\tcase PAIR_A:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_A;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_A;\n+\t\treg = MTK_PHY_TXVLD_DA_RG;\n+\t\tmask_gbe = MTK_PHY_DA_TX_I2MPB_A_GBE_MASK;\n+\t\tmask_tbt = MTK_PHY_DA_TX_I2MPB_A_TBT_MASK;\n+\t\treg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_A2;\n+\t\tmask_hbt = MTK_PHY_DA_TX_I2MPB_A_HBT_MASK;\n+\t\tmask_tst = MTK_PHY_DA_TX_I2MPB_A_TST_MASK;\n+\t\tbreak;\n+\tcase PAIR_B:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(8));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_B;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_B;\n+\t\treg = MTK_PHY_TX_I2MPB_TEST_MODE_B1;\n+\t\tmask_gbe = MTK_PHY_DA_TX_I2MPB_B_GBE_MASK;\n+\t\tmask_tbt = MTK_PHY_DA_TX_I2MPB_B_TBT_MASK;\n+\t\treg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_B2;\n+\t\tmask_hbt = MTK_PHY_DA_TX_I2MPB_B_HBT_MASK;\n+\t\tmask_tst = MTK_PHY_DA_TX_I2MPB_B_TST_MASK;\n+\t\tbreak;\n+\tcase PAIR_C:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(4));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_C;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_C;\n+\t\treg = MTK_PHY_TX_I2MPB_TEST_MODE_C1;\n+\t\tmask_gbe = MTK_PHY_DA_TX_I2MPB_C_GBE_MASK;\n+\t\tmask_tbt = MTK_PHY_DA_TX_I2MPB_C_TBT_MASK;\n+\t\treg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_C2;\n+\t\tmask_hbt = MTK_PHY_DA_TX_I2MPB_C_HBT_MASK;\n+\t\tmask_tst = MTK_PHY_DA_TX_I2MPB_C_TST_MASK;\n+\t\tbreak;\n+\tcase PAIR_D:\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(0));\n+\t\treg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_D;\n+\t\treg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_D;\n+\t\treg = MTK_PHY_TX_I2MPB_TEST_MODE_D1;\n+\t\tmask_gbe = MTK_PHY_DA_TX_I2MPB_D_GBE_MASK;\n+\t\tmask_tbt = MTK_PHY_DA_TX_I2MPB_D_TBT_MASK;\n+\t\treg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_D2;\n+\t\tmask_hbt = MTK_PHY_DA_TX_I2MPB_D_HBT_MASK;\n+\t\tmask_tst = MTK_PHY_DA_TX_I2MPB_D_TST_MASK;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac1,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac2,\n+\t\t 0x8000 | 0xf0);\n+\n+\tphydev_dbg(phydev, \"Start TX Amp SW cal.\\n\");\n+\tfirst_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg,\n+\t\t\t\t mask_gbe, zcal_ctrl \u003c\u003c __ffs(mask_gbe));\n+\n+\t/* If TX Amp calibration failed:\n+\t * - increase dB until calibration succeed.\n+\t * If TX Amp calibration succeeded:\n+\t * - decrease dB until calibration fail to fine tune it.\n+\t */\n+\tif (first_calib == 1)\n+\t\tcalibration_polarity = -1;\n+\telse\n+\t\tcalibration_polarity = 1;\n+\n+\twhile (zcal_ctrl \u003e 0 \u0026\u0026\n+\t zcal_ctrl \u003c FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {\n+\t\tzcal_ctrl += calibration_polarity;\n+\n+\t\tret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg,\n+\t\t\t\t mask_gbe, zcal_ctrl \u003c\u003c __ffs(mask_gbe));\n+\t\t/* Exit if we either failed or succeeded compared to the\n+\t\t * first calibration result. (aka we finished fine tuning or\n+\t\t * we succeeded with calibration)\n+\t\t */\n+\t\tif (ret != first_calib)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (ret \u003c 0) {\n+\t\tphydev_err(phydev, \"TX AMP calibration failed.\\n\");\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1, reg,\n+\t\t\t mask_gbe | mask_tbt,\n+\t\t\t (zcal_ctrl \u003c\u003c __ffs(mask_gbe)) |\n+\t\t\t (zcal_ctrl \u003c\u003c __ffs(mask_tbt)));\n+\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (zcal_ctrl == 0 ||\n+\t zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK))\n+\t\tphydev_warn(phydev, \"TX AMP SW calibration saturation.\\n\");\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND1, reg,\n+\t\t mask_gbe | mask_tbt,\n+\t\t (zcal_ctrl \u003c\u003c __ffs(mask_gbe)) |\n+\t\t (zcal_ctrl \u003c\u003c __ffs(mask_tbt)));\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND1, reg_100,\n+\t\t mask_hbt | mask_tst,\n+\t\t (zcal_ctrl \u003c\u003c __ffs(mask_hbt)) |\n+\t\t (zcal_ctrl \u003c\u003c __ffs(mask_tst)));\n+\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, 0x145, 0x1000);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0);\n+\n+\t/* Restore AN enable */\n+\tphy_write(phydev, MII_BMCR, BMCR_ANENABLE);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_tx_r50_cal_sw(struct phy_device *phydev, u8 txg_calen_x)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tu16 dev1e_145_tmp, bmcr_tmp;\n+\tint calibration_polarity;\n+\tu8 zcal_ctrl = 32;\n+\tint first_calib;\n+\tu16 reg;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\n+\t/* BG voltage output */\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);\n+\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\t/* select 1V */\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\t/* select 1V */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);\n+\n+\t/* Force 1G full duplex for calibration */\n+\tbmcr_tmp = phy_read(phydev, MII_BMCR);\n+\tphy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);\n+\n+\t/* Force MDI */\n+\tdev1e_145_tmp = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x0145);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, 0x1010);\n+\n+\t/* disable tx slew control */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0185, 0x0000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00fb, 0x0100);\n+\n+\tswitch (txg_calen_x) {\n+\tcase PAIR_A:\n+\t\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t\t MTK_PHY_RG_ANA_CAL_RG0,\n+\t\t\t\t MTK_PHY_RG_ZCALEN_A);\n+\t\tbreak;\n+\tcase PAIR_B:\n+\t\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t\t MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t\t\t MTK_PHY_RG_ZCALEN_B);\n+\t\tbreak;\n+\tcase PAIR_C:\n+\t\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t\t MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t\t\t MTK_PHY_RG_ZCALEN_C);\n+\t\tbreak;\n+\tcase PAIR_D:\n+\t\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t\t MTK_PHY_RG_ANA_CAL_RG1,\n+\t\t\t\t MTK_PHY_RG_ZCALEN_D);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tphydev_dbg(phydev, \"Start TX r50 SW cal.\\n\");\n+\tfirst_calib = airoha_cal_cycle(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,\n+\t\t\t\t MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);\n+\n+\tif (first_calib \u003c 0) {\n+\t\tphydev_err(phydev, \"TX r50 SW calibration failed.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* If TX r50 calibration failed:\n+\t * - increase dB until calibration succeed.\n+\t * If TX r50 calibration succeeded:\n+\t * - decrease dB until calibration fail to fine tune it.\n+\t */\n+\tif (first_calib == 1)\n+\t\tcalibration_polarity = -1;\n+\telse\n+\t\tcalibration_polarity = 1;\n+\n+\twhile (zcal_ctrl \u003e 0 \u0026\u0026\n+\t zcal_ctrl \u003c FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {\n+\t\tzcal_ctrl += calibration_polarity;\n+\n+\t\tret = airoha_cal_cycle(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,\n+\t\t\t\t MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);\n+\t\t/* Exit if we either failed or succeeded compared to the\n+\t\t * first calibration result. (aka we finished fine tuning or\n+\t\t * we succeeded with calibration)\n+\t\t */\n+\t\tif (ret != first_calib)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (ret \u003c 0) {\n+\t\tphydev_err(phydev, \"TX r50 SW calibration failed.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (zcal_ctrl == 0 ||\n+\t zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK))\n+\t\tphydev_warn(phydev, \"TX r50 SW calibration saturation.\\n\");\n+\n+\tzcal_ctrl = shared-\u003er50_cal_tbl[zcal_ctrl];\n+\n+\tswitch (txg_calen_x) {\n+\tcase PAIR_A:\n+\t\treg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_A_MASK, zcal_ctrl);\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t MTK_PHY_RG_CR_TX_R50_OFFSET_A_B,\n+\t\t\t BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_A_MASK, reg);\n+\t\tbreak;\n+\tcase PAIR_B:\n+\t\treg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_B_MASK, zcal_ctrl);\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t MTK_PHY_RG_CR_TX_R50_OFFSET_A_B,\n+\t\t\t BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_B_MASK, reg);\n+\t\tbreak;\n+\tcase PAIR_C:\n+\t\treg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_C_MASK, zcal_ctrl);\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t MTK_PHY_RG_CR_TX_R50_OFFSET_C_D,\n+\t\t\t BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_C_MASK, reg);\n+\t\tbreak;\n+\tcase PAIR_D:\n+\t\treg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_D_MASK, zcal_ctrl);\n+\t\tphy_modify_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t MTK_PHY_RG_CR_TX_R50_OFFSET_C_D,\n+\t\t\t BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_D_MASK, reg);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);\n+\n+\t/* Enable tx slew control */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0185, 0x0001);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00fb, 0x0000);\n+\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x0);\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x0);\n+\n+\t/* Restore BMCR */\n+\tphy_write(phydev, MII_BMCR, bmcr_tmp);\n+\n+\t/* Restore MDI */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, dev1e_145_tmp);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_rx_offset_cal_sw(struct phy_device *phydev)\n+{\n+\t/* Hw bypass, Fw cal */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96, 0x8000);\n+\t/* tx/rx_cal_criteria_value */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x37, 0x0033);\n+\n+\t/* rx offset cal by Hw setup */\n+\tphy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,\n+\t\t\t BIT(14) | BIT(11));\n+\n+\t/* disable rtune calibration */\n+\tphy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 0x107,\n+\t\t\t BIT(12));\n+\n+\t/* bypass tx/rx dc offset cancellation process */\n+\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 0x171,\n+\t\t\t BIT(8) | BIT(7));\n+\n+\t/* rx offset calibration start */\n+\tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,\n+\t\t\t BIT(13));\n+\n+\t/* rx offset calibration stop */\n+\tphy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,\n+\t\t\t BIT(13));\n+\n+\tmdelay(10);\n+\n+\tphy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x171,\n+\t\t\t BIT(8) | BIT(7));\n+\n+\tif (phydev-\u003edrv-\u003ephy_id == AIROHA_GPHY_ID_AN7581)\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1,\n+\t\t\t MTK_PHY_RG_ANA_CAL_RG6, 0x1);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,\n+\t\t\t u8 start_pair, u8 end_pair)\n+{\n+\tu8 pair_n;\n+\tint ret;\n+\n+\tfor (pair_n = start_pair; pair_n \u003c= end_pair; pair_n++) {\n+\t\tswitch (cal_item) {\n+\t\tcase REXT:\n+\t\t\tret = airoha_rext_cal_sw(phydev);\n+\t\t\tbreak;\n+\t\tcase TX_OFFSET:\n+\t\t\tret = airoha_tx_offset_cal_sw(phydev, pair_n);\n+\t\t\tbreak;\n+\t\tcase TX_AMP:\n+\t\t\tret = airoha_tx_amp_cal_sw(phydev, pair_n);\n+\t\t\tbreak;\n+\t\tcase TX_R50:\n+\t\t\tret = airoha_tx_r50_cal_sw(phydev, pair_n);\n+\t\t\tbreak;\n+\t\tcase RX_OFFSET:\n+\t\t\tret = airoha_rx_offset_cal_sw(phydev);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+static int airoha_start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,\n+\t\t\t enum CAL_MODE cal_mode, u8 start_pair,\n+\t\t\t u8 end_pair, u32 *buf)\n+{\n+\tint ret;\n+\n+\tswitch (cal_mode) {\n+\tcase SW_M:\n+\t\tret = airoha_cal_sw(phydev, cal_item, start_pair, end_pair);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (ret) {\n+\t\tphydev_err(phydev, \"cal %d failed\\n\", cal_item);\n+\t\treturn -EIO;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int airoha_phy_calib(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\n+\t/* PreCalibrate Set */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x5c, 0x6666);\n+\n+\tif (!shared-\u003erext_sw_calib_done) {\n+\t\tret = airoha_start_cal(phydev, REXT, SW_M, NO_PAIR, NO_PAIR, NULL);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tshared-\u003erext_sw_calib_done = true;\n+\t}\n+\n+\tret = airoha_start_cal(phydev, TX_R50, SW_M, PAIR_A, PAIR_D, NULL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_start_cal(phydev, TX_OFFSET, SW_M, PAIR_A, PAIR_D, NULL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_start_cal(phydev, TX_AMP, SW_M, PAIR_A, PAIR_D, NULL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_start_cal(phydev, RX_OFFSET, SW_M, NO_PAIR, NO_PAIR, NULL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Gating, short with other pair */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x15, 0x0);\n+\n+\tphy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_phy_auto_select_transformer(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tu8 phy_offset;\n+\tu16 bmcr_tmp;\n+\tu16 val;\n+\tint i;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\tphy_offset = phydev-\u003emdio.addr - phydev_p0-\u003emdio.addr;\n+\n+\t/* Force 1G full duplex for calibration */\n+\tbmcr_tmp = phy_read(phydev, MII_BMCR);\n+\tphy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x271, GENMASK(4, 0),\n+\t\t FIELD_PREP(GENMASK(4, 0), 0x3));\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x269, GENMASK(15, 12),\n+\t\t FIELD_PREP(GENMASK(15, 12), 0x2));\n+\n+\tphy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x26f, GENMASK(14, 12),\n+\t\t FIELD_PREP(GENMASK(14, 12), 0x0));\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D,\n+\t\t 0x8000 | 0xf0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D,\n+\t\t 0x8000 | 0xf0);\n+\n+\t/* Force pGA gain */\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);\n+\t__mtk_tr_modify(phydev, 0x1, 0xf, 0x10,\n+\t\t\tGENMASK(20, 15),\n+\t\t\tFIELD_PREP(GENMASK(20, 15), 0x1f));\n+\n+\t__mtk_tr_modify(phydev, 0x1, 0xf, 0x11,\n+\t\t\tGENMASK(23, 18) | GENMASK(15, 10) | GENMASK(7, 2),\n+\t\t\tFIELD_PREP(GENMASK(23, 18), 0x1f) |\n+\t\t\tFIELD_PREP(GENMASK(15, 10), 0x1f) |\n+\t\t\tFIELD_PREP(GENMASK(7, 2), 0x1f));\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xc9, 0xffff);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x151, 0x12);\n+\n+\tswitch (phy_offset) {\n+\tcase 0:\n+\t\tval = 0x1;\n+\t\tbreak;\n+\tcase 1:\n+\t\tval = 0x3;\n+\t\tbreak;\n+\tcase 2:\n+\t\tval = 0x5;\n+\t\tbreak;\n+\tcase 3:\n+\t\tval = 0x7;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x15,\n+\t\t FIELD_PREP(GENMASK(14, 12), val) | 0x161);\n+\tmdelay(500);\n+\n+\tfor (i = 0; i \u003c 3; i++)\n+\t\tval = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0x1a);\n+\n+\t/* Check the value and report transformer type for later */\n+\tshared-\u003etransformer_type[phy_offset] = val \u003c 0xe0;\n+\n+\t/* Switch to Default */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x15, 0x1000);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0x0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D,\n+\t\t 0x0);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D,\n+\t\t 0x0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xc9, 0xfff);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x151, 0x0);\n+\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);\n+\t__mtk_tr_modify(phydev, 0x1, 0xf, 0x10,\n+\t\t\tGENMASK(20, 15),\n+\t\t\tFIELD_PREP(GENMASK(20, 15), 0x4));\n+\n+\t__mtk_tr_modify(phydev, 0x1, 0xf, 0x11,\n+\t\t\tGENMASK(23, 18) | GENMASK(15, 10) | GENMASK(7, 2),\n+\t\t\tFIELD_PREP(GENMASK(23, 18), 0x0) |\n+\t\t\tFIELD_PREP(GENMASK(15, 10), 0x0) |\n+\t\t\tFIELD_PREP(GENMASK(7, 2), 0x0));\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\t/* Restore BMCR */\n+\tphy_write(phydev, MII_BMCR, bmcr_tmp);\n+\n+\treturn 0;\n+}\n+\n+static int airoha_phy_tx_amp_compensation(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\n+\tu16 reg_1e_12_read;\n+\tu16 reg_1e_16_read;\n+\tu16 reg_1e_17_read;\n+\tu16 reg_1e_18_read;\n+\tu16 reg_1e_19_read;\n+\tu16 reg_1e_20_read;\n+\tu16 reg_1e_21_read;\n+\tu16 reg_1e_22_read;\n+\tu16 reg_1e_174_read;\n+\tu16 reg_1e_175_read;\n+\n+\tint reg_1e_12_header;\n+\tint reg_1e_16_header;\n+\tint reg_1e_17_header;\n+\tint reg_1e_18_header;\n+\tint reg_1e_19_header;\n+\tint reg_1e_21_header;\n+\tint reg_1e_174_header;\n+\tint reg_1e_175_header;\n+\n+\tint reg_1e_12_end;\n+\tint reg_1e_16_end;\n+\tint reg_1e_17_end;\n+\tint reg_1e_18_end;\n+\tint reg_1e_20_end;\n+\tint reg_1e_22_end;\n+\tint reg_1e_174_end;\n+\tint reg_1e_175_end;\n+\n+\tstruct phy_device *phydev_p0;\n+\tu8 phy_offset;\n+\n+\tint txamp_low_limit = -3;\n+\tint txamp_high_limit = 0x42;\n+\n+\tint r50_low_limit = -8;\n+\tint r50_high_limit = 0x88;\n+\n+\tbool overflow;\n+\tint (*tx_amp_table)[CALIB_CONST_TYPE_MAX][4];\n+\tint transformer_type, mdi_resister_type;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\tphy_offset = phydev-\u003emdio.addr - phydev_p0-\u003emdio.addr;\n+\n+\ttransformer_type = shared-\u003etransformer_type[phy_offset];\n+\tmdi_resister_type = shared-\u003emdi_resister_type;\n+\ttx_amp_table = shared-\u003etx_amp_compensation_tbl[transformer_type][mdi_resister_type];\n+\n+\treg_1e_12_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x12);\n+\treg_1e_16_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x16);\n+\treg_1e_17_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x17);\n+\treg_1e_18_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x18);\n+\treg_1e_19_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x19);\n+\treg_1e_20_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x20);\n+\treg_1e_21_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x21);\n+\treg_1e_22_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x22);\n+\treg_1e_174_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x174);\n+\treg_1e_175_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x175);\n+\n+\treg_1e_12_header = ((reg_1e_12_read \u0026 0xfc00) / 1024) + *tx_amp_table[TX_AMP_1G_A][phy_offset];\n+\treg_1e_17_header = ((reg_1e_17_read \u0026 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_B][phy_offset];\n+\treg_1e_19_header = ((reg_1e_19_read \u0026 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_C][phy_offset];\n+\treg_1e_21_header = ((reg_1e_21_read \u0026 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_D][phy_offset];\n+\n+\toverflow = false;\n+\tif (reg_1e_12_header \u003c txamp_low_limit ||\n+\t reg_1e_12_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_17_header \u003c txamp_low_limit ||\n+\t reg_1e_17_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_19_header \u003c txamp_low_limit ||\n+\t reg_1e_19_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_21_header \u003c txamp_low_limit ||\n+\t reg_1e_21_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\n+\tif (overflow) {\n+\t\treg_1e_12_header = 0x20;\n+\t\treg_1e_17_header = 0x20;\n+\t\treg_1e_19_header = 0x20;\n+\t\treg_1e_21_header = 0x20;\n+\t} else {\n+\t\tif (reg_1e_12_header \u003c 0)\n+\t\t\treg_1e_12_header = 0;\n+\t\telse if (reg_1e_12_header \u003e 0x3f)\n+\t\t\treg_1e_12_header = 0x3f;\n+\t\tif (reg_1e_17_header \u003c 0)\n+\t\t\treg_1e_17_header = 0;\n+\t\telse if (reg_1e_17_header \u003e 0x3f)\n+\t\t\treg_1e_17_header = 0x3f;\n+\t\tif (reg_1e_19_header \u003c 0)\n+\t\t\treg_1e_19_header = 0;\n+\t\telse if (reg_1e_19_header \u003e 0x3f)\n+\t\t\treg_1e_19_header = 0x3f;\n+\t\tif (reg_1e_21_header \u003c 0)\n+\t\t\treg_1e_21_header = 0;\n+\t\telse if (reg_1e_21_header \u003e 0x3f)\n+\t\t\treg_1e_21_header = 0x3f;\n+\t}\n+\n+\treg_1e_16_end = (reg_1e_16_read \u0026 0x003f) + *tx_amp_table[TX_AMP_TEST_A][phy_offset];\n+\treg_1e_18_end = (reg_1e_18_read \u0026 0x003f) + *tx_amp_table[TX_AMP_TEST_B][phy_offset];\n+\treg_1e_20_end = (reg_1e_20_read \u0026 0x003f) + *tx_amp_table[TX_AMP_TEST_C][phy_offset];\n+\treg_1e_22_end = (reg_1e_22_read \u0026 0x003f) + *tx_amp_table[TX_AMP_TEST_D][phy_offset];\n+\n+\toverflow = false;\n+\tif (reg_1e_16_end \u003c txamp_low_limit ||\n+\t reg_1e_16_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_18_end \u003c txamp_low_limit ||\n+\t reg_1e_18_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_20_end \u003c txamp_low_limit ||\n+\t reg_1e_20_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_22_end \u003c txamp_low_limit ||\n+\t reg_1e_22_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\n+\tif (overflow) {\n+\t\treg_1e_16_end = 0x20;\n+\t\treg_1e_18_end = 0x20;\n+\t\treg_1e_20_end = 0x20;\n+\t\treg_1e_22_end = 0x20;\n+\t} else {\n+\t\tif (reg_1e_16_end \u003c 0)\n+\t\t\treg_1e_16_end = 0;\n+\t\telse if (reg_1e_16_end \u003e 0x3f)\n+\t\t\treg_1e_16_end = 0x3f;\n+\t\tif (reg_1e_18_end \u003c 0)\n+\t\t\treg_1e_18_end = 0;\n+\t\telse if (reg_1e_18_end \u003e 0x3f)\n+\t\t\treg_1e_18_end = 0x3f;\n+\t\tif (reg_1e_20_end \u003c 0)\n+\t\t\treg_1e_20_end = 0;\n+\t\telse if (reg_1e_20_end \u003e 0x3f)\n+\t\t\treg_1e_20_end = 0x3f;\n+\t\tif (reg_1e_22_end \u003c 0)\n+\t\t\treg_1e_22_end = 0;\n+\t\telse if (reg_1e_22_end \u003e 0x3f)\n+\t\t\treg_1e_22_end = 0x3f;\n+\t}\n+\n+\treg_1e_16_header = ((reg_1e_16_read \u0026 0xfc00) / 1024) + *tx_amp_table[TX_AMP_100M_A][phy_offset];\n+\treg_1e_18_header = ((reg_1e_18_read \u0026 0x3f00) / 256) + *tx_amp_table[TX_AMP_100M_B][phy_offset];\n+\n+\toverflow = false;\n+\tif (reg_1e_16_header \u003c txamp_low_limit ||\n+\t reg_1e_16_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_18_header \u003c txamp_low_limit ||\n+\t reg_1e_18_header \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\n+\tif (overflow) {\n+\t\treg_1e_16_header = 0x20;\n+\t\treg_1e_18_header = 0x20;\n+\t} else {\n+\t\tif (reg_1e_16_header \u003c 0)\n+\t\t\treg_1e_16_header = 0;\n+\t\telse if (reg_1e_16_header \u003e 0x3f)\n+\t\t\treg_1e_16_header = 0x3f;\n+\t\tif (reg_1e_18_header \u003c 0)\n+\t\t\treg_1e_18_header = 0;\n+\t\telse if (reg_1e_18_header \u003e 0x3f)\n+\t\t\treg_1e_18_header = 0x3f;\n+\t}\n+\n+\treg_1e_12_end = (reg_1e_12_read \u0026 0x003f) + *tx_amp_table[TX_AMP_10M_A][phy_offset];\n+\treg_1e_17_end = (reg_1e_17_read \u0026 0x003f) + *tx_amp_table[TX_AMP_10M_B][phy_offset];\n+\n+\toverflow = false;\n+\tif (reg_1e_12_end \u003c txamp_low_limit ||\n+\t reg_1e_12_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_17_end \u003c txamp_low_limit ||\n+\t reg_1e_17_end \u003e txamp_high_limit)\n+\t\toverflow = true;\n+\n+\tif (overflow) {\n+\t\treg_1e_12_end = 0x20;\n+\t\treg_1e_17_end = 0x20;\n+\t} else {\n+\t\tif (reg_1e_12_end \u003c 0)\n+\t\t\treg_1e_12_end = 0;\n+\t\telse if (reg_1e_12_end \u003e 0x3f)\n+\t\t\treg_1e_12_end = 0x3f;\n+\t\tif (reg_1e_17_end \u003c 0)\n+\t\t\treg_1e_17_end = 0;\n+\t\telse if (reg_1e_17_end \u003e 0x3f)\n+\t\t\treg_1e_17_end = 0x3f;\n+\t}\n+\n+\treg_1e_174_header = ((reg_1e_174_read \u0026 0x7f00) / 256) + *tx_amp_table[R50_A][phy_offset];\n+\treg_1e_174_end = (reg_1e_174_read \u0026 0x007f) + *tx_amp_table[R50_B][phy_offset];\n+\treg_1e_175_header = ((reg_1e_175_read \u0026 0x7f00) / 256) + *tx_amp_table[R50_C][phy_offset];\n+\treg_1e_175_end = (reg_1e_175_read \u0026 0x007f) + *tx_amp_table[R50_D][phy_offset];\n+\n+\toverflow = false;\n+\tif (reg_1e_174_header \u003c r50_low_limit ||\n+\t reg_1e_174_header \u003e r50_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_174_end \u003c r50_low_limit ||\n+\t reg_1e_174_end \u003e r50_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_175_header \u003c r50_low_limit ||\n+\t reg_1e_175_header \u003e r50_high_limit)\n+\t\toverflow = true;\n+\tif (reg_1e_175_end \u003c r50_low_limit ||\n+\t reg_1e_175_end \u003e r50_high_limit)\n+\t\toverflow = true;\n+\n+\tif (overflow) {\n+\t\treg_1e_174_header = 0x34;\n+\t\treg_1e_174_end = 0x34;\n+\t\treg_1e_175_header = 0x34;\n+\t\treg_1e_175_end = 0x34;\n+\t} else {\n+\t\tif (reg_1e_174_header \u003c 0)\n+\t\t\treg_1e_174_header = 0;\n+\t\telse if (reg_1e_174_header \u003e 0x7f)\n+\t\t\treg_1e_174_header = 0x7f;\n+\t\tif (reg_1e_174_end \u003c 0)\n+\t\t\treg_1e_174_end = 0;\n+\t\telse if (reg_1e_174_end \u003e 0x7f)\n+\t\t\treg_1e_174_end = 0x7f;\n+\t\tif (reg_1e_175_header \u003c 0)\n+\t\t\treg_1e_175_header = 0;\n+\t\telse if (reg_1e_175_header \u003e 0x7f)\n+\t\t\treg_1e_175_header = 0x7f;\n+\t\tif (reg_1e_175_end \u003c 0)\n+\t\t\treg_1e_175_end = 0;\n+\t\telse if (reg_1e_175_end \u003e 0x7f)\n+\t\t\treg_1e_175_end = 0x7f;\n+\t}\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x12,\n+\t\t (reg_1e_12_header * 1024) + reg_1e_12_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x16,\n+\t\t (reg_1e_16_header * 1024) + reg_1e_16_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x17,\n+\t\t (reg_1e_17_header * 256) + reg_1e_17_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x18,\n+\t\t (reg_1e_18_header * 256) + reg_1e_18_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x19,\n+\t\t (reg_1e_19_read \u0026 0x00ff) + (reg_1e_19_header * 256));\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x20,\n+\t\t (reg_1e_20_read \u0026 0xff00) + reg_1e_20_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x21,\n+\t\t (reg_1e_21_read \u0026 0x00ff) + (reg_1e_21_header * 256));\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x22,\n+\t\t (reg_1e_22_read \u0026 0xff00) + reg_1e_22_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x174,\n+\t\t 0x8080 + (reg_1e_174_header * 256) + reg_1e_174_end);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x175,\n+\t\t 0x8080 + (reg_1e_175_header * 256) + reg_1e_175_end);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x176, 0x4400);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x177, 0x0044);\n+\n+\treturn 0;\n+}\n+\n+static int an7581_phy_config_init(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tu32 soc_pdidr;\n+\tu8 phy_offset;\n+\tint ret;\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\tphy_offset = phydev-\u003emdio.addr - phydev_p0-\u003emdio.addr;\n+\n+\t/* FIXME: Read SoC PDIDR if available or default to 1 */\n+\tsoc_pdidr = 1;\n+\n+\tshared-\u003emdi_resister_type = MDI_5R;\n+\tif (soc_pdidr == 1)\n+\t\tshared-\u003etx_amp_compensation_tbl = \u0026an7581_tx_amp_compensation_tbl[0];\n+\telse\n+\t\tshared-\u003etx_amp_compensation_tbl = \u0026an7581_tx_amp_compensation_tbl[1];\n+\tshared-\u003er50_cal_tbl = an7581_zcal_to_r45ohm;\n+\n+\tret = airoha_phy_calib(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_phy_auto_select_transformer(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_phy_tx_amp_compensation(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* RX setting for 5R_TXMR before AN setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe6, 0x1111);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe7, 0x5555);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe9, 0x0001);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xfe, 0x0000);\n+\n+\t/* Long Loop Reach setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x11, 0xff00);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x202, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x203, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x204, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x205, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x206, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x207, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x208, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x209, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20a, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20b, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20e, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20f, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x210, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x211, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x212, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x213, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x214, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x215, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x216, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x217, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21a, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21b, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21c, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21d, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21e, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21f, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x220, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x221, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x222, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x223, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x226, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x227, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x228, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x229, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22a, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22b, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22c, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22d, 0x0025);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22e, 0x2310);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22f, 0x0025);\n+\n+\t/* RX Setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3c, 0xc000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3d, 0x0000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);\n+\n+\t/* EEE setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_AN, 0x3c, 0x0000);\n+\n+\t/* RX */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x41, 0x3333);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x44, 0x00c0);\n+\n+\t/* 10M settings */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a3, 0x00d2);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a4, 0x010e);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27b, 0x1177);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27c, 0x0808);\n+\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);\n+\t__phy_write(phydev, 0x14, 0x3a18);\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\tphy_write(phydev, 0x9, 0x1e00);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x269, 0x2114);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26a, 0x1113);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26f, 0x0000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x2c63);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x272, 0x0c2b);\n+\n+\t/* EEE set because power down can't set tokenring */\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);\n+\t__mtk_tr_write(phydev, 0x0, 0x7, 0x15, 0x0055a0);\n+\t__mtk_tr_write(phydev, 0x0, 0x7, 0x17, 0x07ff3f);\n+\t__mtk_tr_write(phydev, 0x1, 0xf, 0x0, 0x00001e);\n+\t__mtk_tr_write(phydev, 0x1, 0xf, 0x1, 0x6fb90a);\n+\t__mtk_tr_write(phydev, 0x1, 0xf, 0x18, 0x0e2f00);\n+\t__mtk_tr_write(phydev, 0x1, 0xd, 0x26, 0x444444);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x3, 0x000004);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x6, 0x2ebaef);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x8, 0x00000b);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0xc, 0x00504d);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0xd, 0x02314f);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0xf, 0x003028);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x10, 0x00000a);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x11, 0x040001);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x14, 0x00024a);\n+\t__mtk_tr_write(phydev, 0x2, 0xd, 0x1c, 0x003210);\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x120, 0x8014);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x122, 0xffff);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x144, 0x0200);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14a, 0xee20);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x19b, 0x0111);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x234, 0x1181);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x238, 0x0120);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x239, 0x0117);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x2d1, 0x0733);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x323, 0x0011);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x324, 0x013f);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x326, 0x0037);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x268, 0x07f4);\n+\n+\tif (shared-\u003etransformer_type[phy_offset] == TXMR) {\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0187);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cc);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0109);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x020b);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0202);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03c5);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c2);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0309);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x000e);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0002);\n+\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0880);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0880);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0880);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0880);\n+\t} else {\n+\t\tif (soc_pdidr == 2) {\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x269, 0x1114);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26a, 0x1113);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26f, 0x2000);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x4c88);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x272, 0x0c2b);\n+\n+\t\t\t/* 100M sharp */\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0190);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01c8);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c0);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0030);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0208);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0000);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0318);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03c8);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c0);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0230);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x0008);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0200);\n+\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0885);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0885);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0885);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0885);\n+\t\t} else {\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0190);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cf);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c0);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0030);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x020f);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0000);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0318);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03cf);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c0);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0230);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x000f);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0200);\n+\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0003);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0003);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0003);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0003);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int an7581_phy_probe(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared;\n+\tstruct mtk_socphy_priv *priv;\n+\tstruct pinctrl *pinctrl;\n+\tint ret;\n+\n+\t/* Toggle pinctrl to enable PHY LED */\n+\tpinctrl = devm_pinctrl_get_select(\u0026phydev-\u003emdio.dev, \"gbe-led\");\n+\tif (IS_ERR(pinctrl))\n+\t\tdev_err(\u0026phydev-\u003emdio.bus-\u003edev,\n+\t\t\t\"Failed to setup PHY LED pinctrl\\n\");\n+\n+\tret = devm_phy_package_join(\u0026phydev-\u003emdio.dev, phydev, 0,\n+\t\t\t\t sizeof(struct airoha_socphy_shared));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tpriv = devm_kzalloc(\u0026phydev-\u003emdio.dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\tif (phydev-\u003emdio.addr == AIROHA_DEFAULT_PORT0_ADDR)\n+\t\tshared-\u003ephydev_p0 = phydev;\n+\n+\tphydev-\u003epriv = priv;\n+\n+\treturn 0;\n+}\n+\n+static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,\n+\t\t\t\t unsigned long modes)\n+{\n+\tu16 val = 0;\n+\tu32 mode;\n+\n+\tif (index \u003e= AIROHA_PHY_MAX_LEDS)\n+\t\treturn -EINVAL;\n+\n+\tfor_each_set_bit(mode, \u0026modes, __PHY_LED_MODES_NUM) {\n+\t\tswitch (mode) {\n+\t\tcase PHY_LED_ACTIVE_LOW:\n+\t\t\tval = MTK_PHY_LED_ON_POLARITY;\n+\t\t\tbreak;\n+\t\tcase PHY_LED_ACTIVE_HIGH:\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?\n+\t\t\t MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,\n+\t\t\t MTK_PHY_LED_ON_POLARITY, val);\n+}\n+\n+static int an7583_phy_config_init(struct phy_device *phydev)\n+{\n+\tstruct airoha_socphy_shared *shared = phy_package_get_priv(phydev);\n+\tstruct phy_device *phydev_p0;\n+\tu8 phy_offset;\n+\tint ret;\n+\n+\t/* BMCR_PDOWN is enabled by default */\n+\tphy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);\n+\n+\tphydev_p0 = shared-\u003ephydev_p0;\n+\tphy_offset = phydev-\u003emdio.addr - phydev_p0-\u003emdio.addr;\n+\n+\t/* FIXME: Read SoC MDI Resister Type if available or default to 5R */\n+\tshared-\u003emdi_resister_type = MDI_5R;\n+\n+\tshared-\u003emdi_resister_type = MDI_5R;\n+\tif (shared-\u003emdi_resister_type == MDI_0R)\n+\t\tshared-\u003er50_cal_tbl = an7583_zcal_to_r50ohm_0R;\n+\tif (shared-\u003emdi_resister_type == MDI_5R)\n+\t\tshared-\u003er50_cal_tbl = an7583_zcal_to_r50ohm_5R;\n+\tshared-\u003etx_amp_compensation_tbl = \u0026an7583_tx_amp_compensation_tbl;\n+\n+\tret = airoha_phy_calib(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_phy_auto_select_transformer(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = airoha_phy_tx_amp_compensation(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Enable Idle Mode Power Setting */\n+\tif (phy_offset == 0) {\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x268, 0x07F1);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x703, 0x3111);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x3C24);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x701, 0x1023);\n+\t}\n+\n+\tif (shared-\u003etransformer_type[phy_offset] == TXMR) {\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0881);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0881);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0881);\n+\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0881);\n+\n+\t\tif (shared-\u003emdi_resister_type == MDI_0R)\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);\n+\t\telse\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0200);\n+\t} else {\n+\t\tif (shared-\u003emdi_resister_type == MDI_0R) {\n+\t\t\t/* RX setting for 5R_TXMR before AN setting */\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe7, 0x6666);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe9, 0x0003);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xfe, 0x0006);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe6, 0x1111);\n+\t\t\t/* 100M sharp */\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0c86);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0c86);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0c86);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0c86);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cb);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0108);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0211);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03ce);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c8);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0005);\n+\t\t} else {\n+\t\t\t/* 100M sharp */\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0886);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0886);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0886);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0886);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0195);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cb);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0108);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0211);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03ce);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c3);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x0010);\n+\t\t\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0005);\n+\t\t}\n+\t}\n+\n+\t/* RX Setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3c, 0xc000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3d, 0x0000);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);\n+\n+\t/* EEE setting */\n+\tphy_write_mmd(phydev, MDIO_MMD_AN, 0x3c, 0x0000);\n+\n+\t/* 10M settings */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a3, 0x00d2);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a4, 0x010e);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27b, 0x1177);\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27c, 0x0808);\n+\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);\n+\t__phy_write(phydev, 0x14, 0x190);\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\tphy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);\n+\t__phy_write(phydev, 0x14, 0x3a18);\n+\tphy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);\n+\n+\tphy_write(phydev, 0x9, 0x0600);\n+\n+\t/* EEE keep only Pair A ON */\n+\tphy_write_mmd(phydev, MDIO_MMD_VEND1, 0x630, 0x006E);\n+\n+\treturn 0;\n+}\n+\n+static struct phy_driver mtk_socphy_driver[] = {\n+\t{\n+\t\tPHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7581),\n+\t\t.name\t\t= \"Airoha AN7581 PHY\",\n+\t\t.config_init\t= an7581_phy_config_init,\n+\t\t.config_intr\t= genphy_no_config_intr,\n+\t\t.handle_interrupt = genphy_handle_interrupt_no_ack,\n+\t\t.probe\t\t= an7581_phy_probe,\n+\t\t.led_blink_set\t= mt798x_phy_led_blink_set,\n+\t\t.led_brightness_set = mt798x_phy_led_brightness_set,\n+\t\t.led_hw_is_supported = mt798x_phy_led_hw_is_supported,\n+\t\t.led_hw_control_set = mt798x_phy_led_hw_control_set,\n+\t\t.led_hw_control_get = mt798x_phy_led_hw_control_get,\n+\t\t.led_polarity_set = an7581_phy_led_polarity_set,\n+\t\t.read_page\t= mtk_phy_read_page,\n+\t\t.write_page\t= mtk_phy_write_page,\n+\t},\n+\t{\n+\t\tPHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7583),\n+\t\t.name\t\t= \"Airoha AN7583 PHY\",\n+\t\t.config_init\t= an7583_phy_config_init,\n+\t\t.probe\t\t= an7581_phy_probe,\n+\t\t.led_blink_set\t= mt798x_phy_led_blink_set,\n+\t\t.led_brightness_set = mt798x_phy_led_brightness_set,\n+\t\t.led_hw_is_supported = mt798x_phy_led_hw_is_supported,\n+\t\t.led_hw_control_set = mt798x_phy_led_hw_control_set,\n+\t\t.led_hw_control_get = mt798x_phy_led_hw_control_get,\n+\t\t.led_polarity_set = an7581_phy_led_polarity_set,\n+\t\t.read_page\t= mtk_phy_read_page,\n+\t\t.write_page\t= mtk_phy_write_page,\n+\t},\n+};\n+\n+module_phy_driver(mtk_socphy_driver);\n+\n+static const struct mdio_device_id __maybe_unused airoha_socphy_tbl[] = {\n+\t{ PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7581) },\n+\t{ PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7583) },\n+\t{ }\n+};\n+\n+MODULE_DESCRIPTION(\"Airoha SoC Gigabit Ethernet PHY driver\");\n+MODULE_AUTHOR(\"Christian Marangi \u003cansuelsmth@gmail.com\u003e\");\n+MODULE_LICENSE(\"GPL\");\n+MODULE_VERSION(\"01.01.20260306\");\n+\n+MODULE_DEVICE_TABLE(mdio, airoha_socphy_tbl);\ndiff --git a/drivers/net/phy/mediatek/mtk-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c\nindex 9a54949644d5a5..4132ac40358355 100644\n--- a/drivers/net/phy/mediatek/mtk-ge-soc.c\n+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c\n@@ -11,322 +11,10 @@\n \n #include \"../phylib.h\"\n #include \"mtk.h\"\n+#include \"mtk-ge-soc.h\"\n \n #define MTK_PHY_MAX_LEDS\t\t\t2\n \n-#define MTK_GPHY_ID_MT7981\t\t\t0x03a29461\n-#define MTK_GPHY_ID_MT7988\t\t\t0x03a29481\n-#define MTK_GPHY_ID_AN7581\t\t\t0x03a294c1\n-#define MTK_GPHY_ID_AN7583\t\t\t0xc0ff0420\n-\n-#define MTK_EXT_PAGE_ACCESS\t\t\t0x1f\n-#define MTK_PHY_PAGE_STANDARD\t\t\t0x0000\n-#define MTK_PHY_PAGE_EXTENDED_3\t\t\t0x0003\n-\n-#define MTK_PHY_LPI_REG_14\t\t\t0x14\n-#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK\tGENMASK(8, 0)\n-\n-#define MTK_PHY_LPI_REG_1c\t\t\t0x1c\n-#define MTK_PHY_SMI_DET_ON_THRESH_MASK\t\tGENMASK(13, 8)\n-\n-#define MTK_PHY_PAGE_EXTENDED_2A30\t\t0x2a30\n-\n-/* Registers on Token Ring debug nodes */\n-/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */\n-/* NormMseLoThresh */\n-#define NORMAL_MSE_LO_THRESH_MASK\t\tGENMASK(15, 8)\n-\n-/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */\n-/* RemAckCntLimitCtrl */\n-#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK\tGENMASK(2, 1)\n-\n-/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */\n-/* VcoSlicerThreshBitsHigh */\n-#define VCO_SLICER_THRESH_HIGH_MASK\t\tGENMASK(23, 0)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */\n-/* DfeTailEnableVgaThresh1000 */\n-#define DFE_TAIL_EANBLE_VGA_TRHESH_1000\t\tGENMASK(5, 1)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */\n-/* MrvlTrFix100Kp */\n-#define MRVL_TR_FIX_100KP_MASK\t\t\tGENMASK(22, 20)\n-/* MrvlTrFix100Kf */\n-#define MRVL_TR_FIX_100KF_MASK\t\t\tGENMASK(19, 17)\n-/* MrvlTrFix1000Kp */\n-#define MRVL_TR_FIX_1000KP_MASK\t\t\tGENMASK(16, 14)\n-/* MrvlTrFix1000Kf */\n-#define MRVL_TR_FIX_1000KF_MASK\t\t\tGENMASK(13, 11)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */\n-/* VgaDecRate */\n-#define VGA_DECIMATION_RATE_MASK\t\tGENMASK(8, 5)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */\n-/* SlvDSPreadyTime */\n-#define SLAVE_DSP_READY_TIME_MASK\t\tGENMASK(22, 15)\n-/* MasDSPreadyTime */\n-#define MASTER_DSP_READY_TIME_MASK\t\tGENMASK(14, 7)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */\n-/* EnabRandUpdTrig */\n-#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER\tBIT(8)\n-\n-/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */\n-/* ResetSyncOffset */\n-#define RESET_SYNC_OFFSET_MASK\t\t\tGENMASK(11, 8)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */\n-/* FfeUpdGainForceVal */\n-#define FFE_UPDATE_GAIN_FORCE_VAL_MASK\t\tGENMASK(9, 7)\n-/* FfeUpdGainForce */\n-#define FFE_UPDATE_GAIN_FORCE\t\t\tBIT(6)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */\n-/* TrFreeze */\n-#define TR_FREEZE_MASK\t\t\t\tGENMASK(11, 0)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */\n-/* SS: Steady-state, KP: Proportional Gain */\n-/* SSTrKp100 */\n-#define SS_TR_KP100_MASK\t\t\tGENMASK(21, 19)\n-/* SSTrKf100 */\n-#define SS_TR_KF100_MASK\t\t\tGENMASK(18, 16)\n-/* SSTrKp1000Mas */\n-#define SS_TR_KP1000_MASTER_MASK\t\tGENMASK(15, 13)\n-/* SSTrKf1000Mas */\n-#define SS_TR_KF1000_MASTER_MASK\t\tGENMASK(12, 10)\n-/* SSTrKp1000Slv */\n-#define SS_TR_KP1000_SLAVE_MASK\t\t\tGENMASK(9, 7)\n-/* SSTrKf1000Slv */\n-#define SS_TR_KF1000_SLAVE_MASK\t\t\tGENMASK(6, 4)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */\n-/* clear this bit if wanna select from AFE */\n-/* Regsigdet_sel_1000 */\n-#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE\tBIT(4)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */\n-/* RegEEE_st2TrKf1000 */\n-#define EEE1000_STAGE2_TR_KF_MASK\t\tGENMASK(13, 11)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */\n-/* RegEEE_slv_waketr_timer_tar */\n-#define SLAVE_WAKETR_TIMER_MASK\t\t\tGENMASK(20, 11)\n-/* RegEEE_slv_remtx_timer_tar */\n-#define SLAVE_REMTX_TIMER_MASK\t\t\tGENMASK(10, 1)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */\n-/* RegEEE_slv_wake_int_timer_tar */\n-#define SLAVE_WAKEINT_TIMER_MASK\t\tGENMASK(10, 1)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */\n-/* RegEEE_trfreeze_timer2 */\n-#define TR_FREEZE_TIMER2_MASK\t\t\tGENMASK(9, 0)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */\n-/* RegEEE100Stg1_tar */\n-#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK\tGENMASK(8, 0)\n-\n-/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */\n-/* REGEEE_wake_slv_tr_wait_dfesigdet_en */\n-#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN\tBIT(11)\n-\n-#define ANALOG_INTERNAL_OPERATION_MAX_US\t20\n-#define TXRESERVE_MIN\t\t\t\t0\n-#define TXRESERVE_MAX\t\t\t\t7\n-\n-#define MTK_PHY_ANARG_RG\t\t\t0x10\n-#define MTK_PHY_TCLKOFFSET_MASK\t\tGENMASK(12, 8)\n-\n-/* Registers on MDIO_MMD_VEND1 */\n-#define MTK_PHY_TXVLD_DA_RG\t\t\t0x12\n-#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK\tGENMASK(15, 10)\n-#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_A2\t\t0x16\n-#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK\tGENMASK(15, 10)\n-#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_B1\t\t0x17\n-#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_B2\t\t0x18\n-#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_C1\t\t0x19\n-#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_C2\t\t0x20\n-#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_D1\t\t0x21\n-#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_TX_I2MPB_TEST_MODE_D2\t\t0x22\n-#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK\tGENMASK(5, 0)\n-\n-#define MTK_PHY_RXADC_CTRL_RG7\t\t\t0xc6\n-#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK\tGENMASK(9, 8)\n-\n-#define MTK_PHY_RXADC_CTRL_RG9\t\t\t0xc8\n-#define MTK_PHY_DA_RX_PSBN_TBT_MASK\t\tGENMASK(14, 12)\n-#define MTK_PHY_DA_RX_PSBN_HBT_MASK\t\tGENMASK(10, 8)\n-#define MTK_PHY_DA_RX_PSBN_GBE_MASK\t\tGENMASK(6, 4)\n-#define MTK_PHY_DA_RX_PSBN_LP_MASK\t\tGENMASK(2, 0)\n-\n-#define MTK_PHY_LDO_OUTPUT_V\t\t\t0xd7\n-\n-#define MTK_PHY_RG_ANA_CAL_RG0\t\t\t0xdb\n-#define MTK_PHY_RG_CAL_CKINV\t\t\tBIT(12)\n-#define MTK_PHY_RG_ANA_CALEN\t\t\tBIT(8)\n-#define MTK_PHY_RG_ZCALEN_A\t\t\tBIT(0)\n-\n-#define MTK_PHY_RG_ANA_CAL_RG1\t\t\t0xdc\n-#define MTK_PHY_RG_ZCALEN_B\t\t\tBIT(12)\n-#define MTK_PHY_RG_ZCALEN_C\t\t\tBIT(8)\n-#define MTK_PHY_RG_ZCALEN_D\t\t\tBIT(4)\n-#define MTK_PHY_RG_TXVOS_CALEN\t\tBIT(0)\n-\n-#define MTK_PHY_RG_ANA_CAL_RG5\t\t\t0xe0\n-#define MTK_PHY_RG_REXT_TRIM_MASK\t\tGENMASK(13, 8)\n-\n-#define MTK_PHY_RG_TX_FILTER\t\t\t0xfe\n-\n-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120\t0x120\n-#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK\tGENMASK(12, 8)\n-#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK\tGENMASK(4, 0)\n-\n-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122\t0x122\n-#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK\tGENMASK(7, 0)\n-\n-#define MTK_PHY_RG_TESTMUX_ADC_CTRL\t\t0x144\n-#define MTK_PHY_RG_TXEN_DIG_MASK\t\tGENMASK(5, 5)\n-\n-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B\t\t0x172\n-#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK\tGENMASK(6, 0)\n-\n-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D\t\t0x173\n-#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK\tGENMASK(13, 8)\n-#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK\tGENMASK(6, 0)\n-\n-#define MTK_PHY_RG_AD_CAL_COMP\t\t\t0x17a\n-#define MTK_PHY_AD_CAL_COMP_OUT_MASK\t\tGENMASK(8, 8)\n-\n-#define MTK_PHY_RG_AD_CAL_CLK\t\t\t0x17b\n-#define MTK_PHY_DA_CAL_CLK\t\t\tBIT(0)\n-\n-#define MTK_PHY_RG_AD_CALIN\t\t\t0x17c\n-#define MTK_PHY_DA_CALIN_FLAG\t\t\tBIT(0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN0_A\t\t0x17d\n-#define MTK_PHY_DASN_DAC_IN0_A_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN0_B\t\t0x17e\n-#define MTK_PHY_DASN_DAC_IN0_B_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN0_C\t\t0x17f\n-#define MTK_PHY_DASN_DAC_IN0_C_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN0_D\t\t0x180\n-#define MTK_PHY_DASN_DAC_IN0_D_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN1_A\t\t0x181\n-#define MTK_PHY_DASN_DAC_IN1_A_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN1_B\t\t0x182\n-#define MTK_PHY_DASN_DAC_IN1_B_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN1_C\t\t0x183\n-#define MTK_PHY_DASN_DAC_IN1_C_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DASN_DAC_IN1_D\t\t0x184\n-#define MTK_PHY_DASN_DAC_IN1_D_MASK\t\tGENMASK(9, 0)\n-\n-#define MTK_PHY_RG_DEV1E_REG19b\t\t\t0x19b\n-#define MTK_PHY_BYPASS_DSP_LPI_READY\t\tBIT(8)\n-\n-#define MTK_PHY_RG_LP_IIR2_K1_L\t\t\t0x22a\n-#define MTK_PHY_RG_LP_IIR2_K1_U\t\t\t0x22b\n-#define MTK_PHY_RG_LP_IIR2_K2_L\t\t\t0x22c\n-#define MTK_PHY_RG_LP_IIR2_K2_U\t\t\t0x22d\n-#define MTK_PHY_RG_LP_IIR2_K3_L\t\t\t0x22e\n-#define MTK_PHY_RG_LP_IIR2_K3_U\t\t\t0x22f\n-#define MTK_PHY_RG_LP_IIR2_K4_L\t\t\t0x230\n-#define MTK_PHY_RG_LP_IIR2_K4_U\t\t\t0x231\n-#define MTK_PHY_RG_LP_IIR2_K5_L\t\t\t0x232\n-#define MTK_PHY_RG_LP_IIR2_K5_U\t\t\t0x233\n-\n-#define MTK_PHY_RG_DEV1E_REG234\t\t\t0x234\n-#define MTK_PHY_TR_OPEN_LOOP_EN_MASK\t\tGENMASK(0, 0)\n-#define MTK_PHY_LPF_X_AVERAGE_MASK\t\tGENMASK(7, 4)\n-#define MTK_PHY_TR_LP_IIR_EEE_EN\t\tBIT(12)\n-\n-#define MTK_PHY_RG_LPF_CNT_VAL\t\t\t0x235\n-\n-#define MTK_PHY_RG_DEV1E_REG238\t\t\t0x238\n-#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK\tGENMASK(8, 0)\n-#define MTK_PHY_LPI_SLV_SEND_TX_EN\t\tBIT(12)\n-\n-#define MTK_PHY_RG_DEV1E_REG239\t\t\t0x239\n-#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK\tGENMASK(8, 0)\n-#define MTK_PHY_LPI_TXPCS_LOC_RCV\t\tBIT(12)\n-\n-#define MTK_PHY_RG_DEV1E_REG27C\t\t\t0x27c\n-#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK\tGENMASK(12, 8)\n-#define MTK_PHY_RG_DEV1E_REG27D\t\t\t0x27d\n-#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK\tGENMASK(4, 0)\n-\n-#define MTK_PHY_RG_DEV1E_REG2C7\t\t\t0x2c7\n-#define MTK_PHY_MAX_GAIN_MASK\t\t\tGENMASK(4, 0)\n-#define MTK_PHY_MIN_GAIN_MASK\t\t\tGENMASK(12, 8)\n-\n-#define MTK_PHY_RG_DEV1E_REG2D1\t\t\t0x2d1\n-#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK\tGENMASK(7, 0)\n-#define MTK_PHY_LPI_SKIP_SD_SLV_TR\t\tBIT(8)\n-#define MTK_PHY_LPI_TR_READY\t\t\tBIT(9)\n-#define MTK_PHY_LPI_VCO_EEE_STG0_EN\t\tBIT(10)\n-\n-#define MTK_PHY_RG_DEV1E_REG323\t\t\t0x323\n-#define MTK_PHY_EEE_WAKE_MAS_INT_DC\t\tBIT(0)\n-#define MTK_PHY_EEE_WAKE_SLV_INT_DC\t\tBIT(4)\n-\n-#define MTK_PHY_RG_DEV1E_REG324\t\t\t0x324\n-#define MTK_PHY_SMI_DETCNT_MAX_MASK\t\tGENMASK(5, 0)\n-#define MTK_PHY_SMI_DET_MAX_EN\t\tBIT(8)\n-\n-#define MTK_PHY_RG_DEV1E_REG326\t\t\t0x326\n-#define MTK_PHY_LPI_MODE_SD_ON\t\tBIT(0)\n-#define MTK_PHY_RESET_RANDUPD_CNT\t\tBIT(1)\n-#define MTK_PHY_TREC_UPDATE_ENAB_CLR\t\tBIT(2)\n-#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF\tBIT(4)\n-#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP\tBIT(5)\n-\n-#define MTK_PHY_LDO_PUMP_EN_PAIRAB\t\t0x502\n-#define MTK_PHY_LDO_PUMP_EN_PAIRCD\t\t0x503\n-\n-#define MTK_PHY_DA_TX_R50_PAIR_A\t\t0x53d\n-#define MTK_PHY_DA_TX_R50_PAIR_B\t\t0x53e\n-#define MTK_PHY_DA_TX_R50_PAIR_C\t\t0x53f\n-#define MTK_PHY_DA_TX_R50_PAIR_D\t\t0x540\n-\n-/* Registers on MDIO_MMD_VEND2 */\n-#define MTK_PHY_LED1_DEFAULT_POLARITIES\t\tBIT(1)\n-\n-#define MTK_PHY_RG_BG_RASEL\t\t\t0x115\n-#define MTK_PHY_RG_BG_RASEL_MASK\t\tGENMASK(2, 0)\n-\n-/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */\n-#define RG_GPIO_MISC_TPBANK0\t\t\t0x6f0\n-#define RG_GPIO_MISC_TPBANK0_BOOTMODE\t\tGENMASK(11, 8)\n-\n /* These macro privides efuse parsing for internal phy. */\n #define EFS_DA_TX_I2MPB_A(x)\t\t\t(((x) \u003e\u003e 0) \u0026 GENMASK(5, 0))\n #define EFS_DA_TX_I2MPB_B(x)\t\t\t(((x) \u003e\u003e 6) \u0026 GENMASK(5, 0))\n@@ -346,51 +34,16 @@\n #define EFS_RG_BG_RASEL(x)\t\t\t(((x) \u003e\u003e 4) \u0026 GENMASK(2, 0))\n #define EFS_RG_REXT_TRIM(x)\t\t\t(((x) \u003e\u003e 7) \u0026 GENMASK(5, 0))\n \n-enum {\n-\tNO_PAIR,\n-\tPAIR_A,\n-\tPAIR_B,\n-\tPAIR_C,\n-\tPAIR_D,\n-};\n-\n-enum calibration_mode {\n-\tEFUSE_K,\n-\tSW_K\n-};\n-\n-enum CAL_ITEM {\n-\tREXT,\n-\tTX_OFFSET,\n-\tTX_AMP,\n-\tTX_R50,\n-\tTX_VCM\n-};\n-\n-enum CAL_MODE {\n-\tEFUSE_M,\n-\tSW_M\n-};\n-\n struct mtk_socphy_shared {\n \tu32\t\t\tboottrap;\n \tstruct mtk_socphy_priv\tpriv[4];\n };\n \n-/* One calibration cycle consists of:\n- * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high\n- * until AD_CAL_COMP is ready to output calibration result.\n- * 2.Wait until DA_CAL_CLK is available.\n- * 3.Fetch AD_CAL_COMP_OUT.\n- */\n-static int cal_cycle(struct phy_device *phydev, int devad,\n-\t\t u32 regnum, u16 mask, u16 cal_val)\n+int mtk_cal_cycle_wait(struct phy_device *phydev)\n {\n \tint reg_val;\n \tint ret;\n \n-\tphy_modify_mmd(phydev, devad, regnum,\n-\t\t mask, cal_val);\n \tphy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,\n \t\t\t MTK_PHY_DA_CALIN_FLAG);\n \n@@ -409,7 +62,26 @@ static int cal_cycle(struct phy_device *phydev, int devad,\n \tret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP);\n \tif (ret \u003c 0)\n \t\treturn ret;\n-\tret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);\n+\n+\treturn FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);\n+}\n+EXPORT_SYMBOL_GPL(mtk_cal_cycle_wait);\n+\n+/* One calibration cycle consists of:\n+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high\n+ * until AD_CAL_COMP is ready to output calibration result.\n+ * 2.Wait until DA_CAL_CLK is available.\n+ * 3.Fetch AD_CAL_COMP_OUT.\n+ */\n+static int cal_cycle(struct phy_device *phydev, int devad,\n+\t\t u32 regnum, u16 mask, u16 cal_val)\n+{\n+\tint ret;\n+\n+\tphy_modify_mmd(phydev, devad, regnum,\n+\t\t mask, cal_val);\n+\n+\tret = mtk_cal_cycle_wait(phydev);\n \tphydev_dbg(phydev, \"cal_val: 0x%x, ret: %d\\n\", cal_val, ret);\n \n \treturn ret;\n@@ -1215,73 +887,6 @@ static int mt798x_phy_config_init(struct phy_device *phydev)\n \treturn mt798x_phy_calibration(phydev);\n }\n \n-static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,\n-\t\t\t\t unsigned long *delay_on,\n-\t\t\t\t unsigned long *delay_off)\n-{\n-\tbool blinking = false;\n-\tint err;\n-\n-\terr = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, \u0026blinking);\n-\tif (err \u003c 0)\n-\t\treturn err;\n-\n-\terr = mtk_phy_hw_led_blink_set(phydev, index, blinking);\n-\tif (err)\n-\t\treturn err;\n-\n-\treturn mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,\n-\t\t\t\t false);\n-}\n-\n-static int mt798x_phy_led_brightness_set(struct phy_device *phydev,\n-\t\t\t\t\t u8 index, enum led_brightness value)\n-{\n-\tint err;\n-\n-\terr = mtk_phy_hw_led_blink_set(phydev, index, false);\n-\tif (err)\n-\t\treturn err;\n-\n-\treturn mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,\n-\t\t\t\t (value != LED_OFF));\n-}\n-\n-static const unsigned long supported_triggers =\n-\tBIT(TRIGGER_NETDEV_FULL_DUPLEX) |\n-\tBIT(TRIGGER_NETDEV_HALF_DUPLEX) |\n-\tBIT(TRIGGER_NETDEV_LINK) |\n-\tBIT(TRIGGER_NETDEV_LINK_10) |\n-\tBIT(TRIGGER_NETDEV_LINK_100) |\n-\tBIT(TRIGGER_NETDEV_LINK_1000) |\n-\tBIT(TRIGGER_NETDEV_RX) |\n-\tBIT(TRIGGER_NETDEV_TX);\n-\n-static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,\n-\t\t\t\t\t unsigned long rules)\n-{\n-\treturn mtk_phy_led_hw_is_supported(phydev, index, rules,\n-\t\t\t\t\t supported_triggers);\n-}\n-\n-static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,\n-\t\t\t\t\t unsigned long *rules)\n-{\n-\treturn mtk_phy_led_hw_ctrl_get(phydev, index, rules,\n-\t\t\t\t MTK_GPHY_LED_ON_SET,\n-\t\t\t\t MTK_GPHY_LED_RX_BLINK_SET,\n-\t\t\t\t MTK_GPHY_LED_TX_BLINK_SET);\n-};\n-\n-static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,\n-\t\t\t\t\t unsigned long rules)\n-{\n-\treturn mtk_phy_led_hw_ctrl_set(phydev, index, rules,\n-\t\t\t\t MTK_GPHY_LED_ON_SET,\n-\t\t\t\t MTK_GPHY_LED_RX_BLINK_SET,\n-\t\t\t\t MTK_GPHY_LED_TX_BLINK_SET);\n-};\n-\n static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)\n {\n \tstruct mtk_socphy_shared *priv = phy_package_get_priv(phydev);\n@@ -1418,58 +1023,6 @@ static int mt7981_phy_probe(struct phy_device *phydev)\n \treturn mt798x_phy_calibration(phydev);\n }\n \n-static int an7581_phy_probe(struct phy_device *phydev)\n-{\n-\tstruct mtk_socphy_priv *priv;\n-\tstruct pinctrl *pinctrl;\n-\n-\t/* Toggle pinctrl to enable PHY LED */\n-\tpinctrl = devm_pinctrl_get_select(\u0026phydev-\u003emdio.dev, \"gbe-led\");\n-\tif (IS_ERR(pinctrl))\n-\t\tdev_err(\u0026phydev-\u003emdio.bus-\u003edev,\n-\t\t\t\"Failed to setup PHY LED pinctrl\\n\");\n-\n-\tpriv = devm_kzalloc(\u0026phydev-\u003emdio.dev, sizeof(*priv), GFP_KERNEL);\n-\tif (!priv)\n-\t\treturn -ENOMEM;\n-\n-\tphydev-\u003epriv = priv;\n-\n-\treturn 0;\n-}\n-\n-static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,\n-\t\t\t\t unsigned long modes)\n-{\n-\tu16 val = 0;\n-\tu32 mode;\n-\n-\tif (index \u003e= MTK_PHY_MAX_LEDS)\n-\t\treturn -EINVAL;\n-\n-\tfor_each_set_bit(mode, \u0026modes, __PHY_LED_MODES_NUM) {\n-\t\tswitch (mode) {\n-\t\tcase PHY_LED_ACTIVE_LOW:\n-\t\t\tval = MTK_PHY_LED_ON_POLARITY;\n-\t\t\tbreak;\n-\t\tcase PHY_LED_ACTIVE_HIGH:\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn -EINVAL;\n-\t\t}\n-\t}\n-\n-\treturn phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?\n-\t\t\t MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,\n-\t\t\t MTK_PHY_LED_ON_POLARITY, val);\n-}\n-\n-static int an7583_phy_config_init(struct phy_device *phydev)\n-{\n-\t/* BMCR_PDOWN is enabled by default */\n-\treturn phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);\n-}\n-\n static struct phy_driver mtk_socphy_driver[] = {\n \t{\n \t\tPHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),\n@@ -1505,31 +1058,6 @@ static struct phy_driver mtk_socphy_driver[] = {\n \t\t.led_hw_control_set = mt798x_phy_led_hw_control_set,\n \t\t.led_hw_control_get = mt798x_phy_led_hw_control_get,\n \t},\n-\t{\n-\t\tPHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581),\n-\t\t.name\t\t= \"Airoha AN7581 PHY\",\n-\t\t.config_intr\t= genphy_no_config_intr,\n-\t\t.handle_interrupt = genphy_handle_interrupt_no_ack,\n-\t\t.probe\t\t= an7581_phy_probe,\n-\t\t.led_blink_set\t= mt798x_phy_led_blink_set,\n-\t\t.led_brightness_set = mt798x_phy_led_brightness_set,\n-\t\t.led_hw_is_supported = mt798x_phy_led_hw_is_supported,\n-\t\t.led_hw_control_set = mt798x_phy_led_hw_control_set,\n-\t\t.led_hw_control_get = mt798x_phy_led_hw_control_get,\n-\t\t.led_polarity_set = an7581_phy_led_polarity_set,\n-\t},\n-\t{\n-\t\tPHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7583),\n-\t\t.name\t\t= \"Airoha AN7583 PHY\",\n-\t\t.config_init\t= an7583_phy_config_init,\n-\t\t.probe\t\t= an7581_phy_probe,\n-\t\t.led_blink_set\t= mt798x_phy_led_blink_set,\n-\t\t.led_brightness_set = mt798x_phy_led_brightness_set,\n-\t\t.led_hw_is_supported = mt798x_phy_led_hw_is_supported,\n-\t\t.led_hw_control_set = mt798x_phy_led_hw_control_set,\n-\t\t.led_hw_control_get = mt798x_phy_led_hw_control_get,\n-\t\t.led_polarity_set = an7581_phy_led_polarity_set,\n-\t},\n };\n \n module_phy_driver(mtk_socphy_driver);\n@@ -1537,8 +1065,6 @@ module_phy_driver(mtk_socphy_driver);\n static const struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {\n \t{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },\n \t{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },\n-\t{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581) },\n-\t{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7583) },\n \t{ }\n };\n \ndiff --git a/drivers/net/phy/mediatek/mtk-ge-soc.h b/drivers/net/phy/mediatek/mtk-ge-soc.h\nnew file mode 100644\nindex 00000000000000..5e9d24a9833c77\n--- /dev/null\n+++ b/drivers/net/phy/mediatek/mtk-ge-soc.h\n@@ -0,0 +1,364 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+\n+#ifndef _MTK_GE_SOC_H_\n+#define _MTK_GE_SOC_H_\n+\n+#include \u003clinux/bitfield.h\u003e\n+\n+#define MTK_GPHY_ID_MT7981\t\t\t0x03a29461\n+#define MTK_GPHY_ID_MT7988\t\t\t0x03a29481\n+#define AIROHA_GPHY_ID_AN7581\t\t\t0x03a294c1\n+#define AIROHA_GPHY_ID_AN7583\t\t\t0xc0ff0420\n+\n+#define MTK_EXT_PAGE_ACCESS\t\t\t0x1f\n+#define MTK_PHY_PAGE_STANDARD\t\t\t0x0000\n+#define MTK_PHY_PAGE_EXTENDED_1\t\t\t0x0001\n+#define MTK_PHY_PAGE_EXTENDED_3\t\t\t0x0003\n+\n+#define MTK_PHY_LPI_REG_14\t\t\t0x14\n+#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK\tGENMASK(8, 0)\n+\n+#define MTK_PHY_LPI_REG_1c\t\t\t0x1c\n+#define MTK_PHY_SMI_DET_ON_THRESH_MASK\t\tGENMASK(13, 8)\n+\n+#define MTK_PHY_PAGE_EXTENDED_2A30\t\t0x2a30\n+\n+/* Registers on Token Ring debug nodes */\n+/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */\n+/* NormMseLoThresh */\n+#define NORMAL_MSE_LO_THRESH_MASK\t\tGENMASK(15, 8)\n+\n+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */\n+/* RemAckCntLimitCtrl */\n+#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK\tGENMASK(2, 1)\n+\n+/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */\n+/* VcoSlicerThreshBitsHigh */\n+#define VCO_SLICER_THRESH_HIGH_MASK\t\tGENMASK(23, 0)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */\n+/* DfeTailEnableVgaThresh1000 */\n+#define DFE_TAIL_EANBLE_VGA_TRHESH_1000\t\tGENMASK(5, 1)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */\n+/* MrvlTrFix100Kp */\n+#define MRVL_TR_FIX_100KP_MASK\t\t\tGENMASK(22, 20)\n+/* MrvlTrFix100Kf */\n+#define MRVL_TR_FIX_100KF_MASK\t\t\tGENMASK(19, 17)\n+/* MrvlTrFix1000Kp */\n+#define MRVL_TR_FIX_1000KP_MASK\t\t\tGENMASK(16, 14)\n+/* MrvlTrFix1000Kf */\n+#define MRVL_TR_FIX_1000KF_MASK\t\t\tGENMASK(13, 11)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */\n+/* VgaDecRate */\n+#define VGA_DECIMATION_RATE_MASK\t\tGENMASK(8, 5)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */\n+/* SlvDSPreadyTime */\n+#define SLAVE_DSP_READY_TIME_MASK\t\tGENMASK(22, 15)\n+/* MasDSPreadyTime */\n+#define MASTER_DSP_READY_TIME_MASK\t\tGENMASK(14, 7)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */\n+/* EnabRandUpdTrig */\n+#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER\tBIT(8)\n+\n+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */\n+/* ResetSyncOffset */\n+#define RESET_SYNC_OFFSET_MASK\t\t\tGENMASK(11, 8)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */\n+/* FfeUpdGainForceVal */\n+#define FFE_UPDATE_GAIN_FORCE_VAL_MASK\t\tGENMASK(9, 7)\n+/* FfeUpdGainForce */\n+#define FFE_UPDATE_GAIN_FORCE\t\t\tBIT(6)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */\n+/* TrFreeze */\n+#define TR_FREEZE_MASK\t\t\t\tGENMASK(11, 0)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */\n+/* SS: Steady-state, KP: Proportional Gain */\n+/* SSTrKp100 */\n+#define SS_TR_KP100_MASK\t\t\tGENMASK(21, 19)\n+/* SSTrKf100 */\n+#define SS_TR_KF100_MASK\t\t\tGENMASK(18, 16)\n+/* SSTrKp1000Mas */\n+#define SS_TR_KP1000_MASTER_MASK\t\tGENMASK(15, 13)\n+/* SSTrKf1000Mas */\n+#define SS_TR_KF1000_MASTER_MASK\t\tGENMASK(12, 10)\n+/* SSTrKp1000Slv */\n+#define SS_TR_KP1000_SLAVE_MASK\t\t\tGENMASK(9, 7)\n+/* SSTrKf1000Slv */\n+#define SS_TR_KF1000_SLAVE_MASK\t\t\tGENMASK(6, 4)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */\n+/* clear this bit if wanna select from AFE */\n+/* Regsigdet_sel_1000 */\n+#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE\tBIT(4)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */\n+/* RegEEE_st2TrKf1000 */\n+#define EEE1000_STAGE2_TR_KF_MASK\t\tGENMASK(13, 11)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */\n+/* RegEEE_slv_waketr_timer_tar */\n+#define SLAVE_WAKETR_TIMER_MASK\t\t\tGENMASK(20, 11)\n+/* RegEEE_slv_remtx_timer_tar */\n+#define SLAVE_REMTX_TIMER_MASK\t\t\tGENMASK(10, 1)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */\n+/* RegEEE_slv_wake_int_timer_tar */\n+#define SLAVE_WAKEINT_TIMER_MASK\t\tGENMASK(10, 1)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */\n+/* RegEEE_trfreeze_timer2 */\n+#define TR_FREEZE_TIMER2_MASK\t\t\tGENMASK(9, 0)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */\n+/* RegEEE100Stg1_tar */\n+#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK\tGENMASK(8, 0)\n+\n+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */\n+/* REGEEE_wake_slv_tr_wait_dfesigdet_en */\n+#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN\tBIT(11)\n+\n+#define ANALOG_INTERNAL_OPERATION_MAX_US\t20\n+#define TXRESERVE_MIN\t\t\t\t0\n+#define TXRESERVE_MAX\t\t\t\t7\n+\n+#define MTK_PHY_ANARG_RG\t\t\t0x10\n+#define MTK_PHY_TCLKOFFSET_MASK\t\tGENMASK(12, 8)\n+\n+/* Registers on MDIO_MMD_VEND1 */\n+#define MTK_PHY_TXVLD_DA_RG\t\t\t0x12\n+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK\tGENMASK(15, 10)\n+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2\t\t0x16\n+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK\tGENMASK(15, 10)\n+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1\t\t0x17\n+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2\t\t0x18\n+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1\t\t0x19\n+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2\t\t0x20\n+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1\t\t0x21\n+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2\t\t0x22\n+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_RXADC_CTRL_RG7\t\t\t0xc6\n+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK\tGENMASK(9, 8)\n+\n+#define MTK_PHY_RXADC_CTRL_RG9\t\t\t0xc8\n+#define MTK_PHY_DA_RX_PSBN_TBT_MASK\t\tGENMASK(14, 12)\n+#define MTK_PHY_DA_RX_PSBN_HBT_MASK\t\tGENMASK(10, 8)\n+#define MTK_PHY_DA_RX_PSBN_GBE_MASK\t\tGENMASK(6, 4)\n+#define MTK_PHY_DA_RX_PSBN_LP_MASK\t\tGENMASK(2, 0)\n+\n+#define MTK_PHY_LDO_OUTPUT_V\t\t\t0xd7\n+\n+#define MTK_PHY_RG_ANA_CAL_RG0\t\t\t0xdb\n+#define MTK_PHY_RG_CAL_CKINV\t\t\tBIT(12)\n+#define MTK_PHY_RG_ANA_CALEN\t\t\tBIT(8)\n+#define MTK_PHY_RG_REXT_CALEN\t\t\tBIT(4)\n+#define MTK_PHY_RG_ZCALEN_A\t\t\tBIT(0)\n+\n+#define MTK_PHY_RG_ANA_CAL_RG1\t\t\t0xdc\n+#define MTK_PHY_RG_ZCALEN_B\t\t\tBIT(12)\n+#define MTK_PHY_RG_ZCALEN_C\t\t\tBIT(8)\n+#define MTK_PHY_RG_ZCALEN_D\t\t\tBIT(4)\n+#define MTK_PHY_RG_TXVOS_CALEN\t\tBIT(0)\n+\n+#define MTK_PHY_RG_ANA_CAL_RG5\t\t\t0xe0\n+#define MTK_PHY_RG_REXT_TRIM_MASK\t\tGENMASK(13, 8)\n+#define MTK_PHY_RG_REXT_ZCAL_CTRL_MASK\tGENMASK(5, 0)\n+\n+#define MTK_PHY_RG_ANA_CAL_RG6\t\t\t0xe1\n+\n+#define MTK_PHY_RG_TX_FILTER\t\t\t0xfe\n+\n+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120\t0x120\n+#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK\tGENMASK(12, 8)\n+#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK\tGENMASK(4, 0)\n+\n+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122\t0x122\n+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK\tGENMASK(7, 0)\n+\n+#define MTK_PHY_RG_TESTMUX_ADC_CTRL\t\t0x144\n+#define MTK_PHY_RG_TXEN_DIG_MASK\t\tGENMASK(5, 5)\n+\n+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B\t\t0x172\n+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK\tGENMASK(6, 0)\n+\n+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D\t\t0x173\n+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK\tGENMASK(6, 0)\n+\n+#define MTK_PHY_RG_CR_TX_R50_OFFSET_A_B\t\t0x174\n+#define MTK_PHY_CR_TX_R50_OFFSET_A_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_CR_TX_R50_OFFSET_B_MASK\tGENMASK(6, 0)\n+\n+#define MTK_PHY_RG_CR_TX_R50_OFFSET_C_D\t\t0x175\n+#define MTK_PHY_CR_TX_R50_OFFSET_C_MASK\tGENMASK(13, 8)\n+#define MTK_PHY_CR_TX_R50_OFFSET_D_MASK\tGENMASK(6, 0)\n+\n+#define MTK_PHY_RG_AD_CAL_COMP\t\t\t0x17a\n+#define MTK_PHY_AD_CAL_COMP_OUT_MASK\t\tGENMASK(8, 8)\n+\n+#define MTK_PHY_RG_AD_CAL_CLK\t\t\t0x17b\n+#define MTK_PHY_DA_CAL_CLK\t\t\tBIT(0)\n+\n+#define MTK_PHY_RG_AD_CALIN\t\t\t0x17c\n+#define MTK_PHY_DA_CALIN_FLAG\t\t\tBIT(0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN0_A\t\t0x17d\n+#define MTK_PHY_DASN_DAC_IN0_A_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN0_B\t\t0x17e\n+#define MTK_PHY_DASN_DAC_IN0_B_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN0_C\t\t0x17f\n+#define MTK_PHY_DASN_DAC_IN0_C_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN0_D\t\t0x180\n+#define MTK_PHY_DASN_DAC_IN0_D_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN1_A\t\t0x181\n+#define MTK_PHY_DASN_DAC_IN1_A_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN1_B\t\t0x182\n+#define MTK_PHY_DASN_DAC_IN1_B_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN1_C\t\t0x183\n+#define MTK_PHY_DASN_DAC_IN1_C_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DASN_DAC_IN1_D\t\t0x184\n+#define MTK_PHY_DASN_DAC_IN1_D_MASK\t\tGENMASK(9, 0)\n+\n+#define MTK_PHY_RG_DEV1E_REG19b\t\t\t0x19b\n+#define MTK_PHY_BYPASS_DSP_LPI_READY\t\tBIT(8)\n+\n+#define MTK_PHY_RG_LP_IIR2_K1_L\t\t\t0x22a\n+#define MTK_PHY_RG_LP_IIR2_K1_U\t\t\t0x22b\n+#define MTK_PHY_RG_LP_IIR2_K2_L\t\t\t0x22c\n+#define MTK_PHY_RG_LP_IIR2_K2_U\t\t\t0x22d\n+#define MTK_PHY_RG_LP_IIR2_K3_L\t\t\t0x22e\n+#define MTK_PHY_RG_LP_IIR2_K3_U\t\t\t0x22f\n+#define MTK_PHY_RG_LP_IIR2_K4_L\t\t\t0x230\n+#define MTK_PHY_RG_LP_IIR2_K4_U\t\t\t0x231\n+#define MTK_PHY_RG_LP_IIR2_K5_L\t\t\t0x232\n+#define MTK_PHY_RG_LP_IIR2_K5_U\t\t\t0x233\n+\n+#define MTK_PHY_RG_DEV1E_REG234\t\t\t0x234\n+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK\t\tGENMASK(0, 0)\n+#define MTK_PHY_LPF_X_AVERAGE_MASK\t\tGENMASK(7, 4)\n+#define MTK_PHY_TR_LP_IIR_EEE_EN\t\tBIT(12)\n+\n+#define MTK_PHY_RG_LPF_CNT_VAL\t\t\t0x235\n+\n+#define MTK_PHY_RG_DEV1E_REG238\t\t\t0x238\n+#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK\tGENMASK(8, 0)\n+#define MTK_PHY_LPI_SLV_SEND_TX_EN\t\tBIT(12)\n+\n+#define MTK_PHY_RG_DEV1E_REG239\t\t\t0x239\n+#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK\tGENMASK(8, 0)\n+#define MTK_PHY_LPI_TXPCS_LOC_RCV\t\tBIT(12)\n+\n+#define MTK_PHY_RG_DEV1E_REG27C\t\t\t0x27c\n+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK\tGENMASK(12, 8)\n+#define MTK_PHY_RG_DEV1E_REG27D\t\t\t0x27d\n+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK\tGENMASK(4, 0)\n+\n+#define MTK_PHY_RG_DEV1E_REG2C7\t\t\t0x2c7\n+#define MTK_PHY_MAX_GAIN_MASK\t\t\tGENMASK(4, 0)\n+#define MTK_PHY_MIN_GAIN_MASK\t\t\tGENMASK(12, 8)\n+\n+#define MTK_PHY_RG_DEV1E_REG2D1\t\t\t0x2d1\n+#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK\tGENMASK(7, 0)\n+#define MTK_PHY_LPI_SKIP_SD_SLV_TR\t\tBIT(8)\n+#define MTK_PHY_LPI_TR_READY\t\t\tBIT(9)\n+#define MTK_PHY_LPI_VCO_EEE_STG0_EN\t\tBIT(10)\n+\n+#define MTK_PHY_RG_DEV1E_REG323\t\t\t0x323\n+#define MTK_PHY_EEE_WAKE_MAS_INT_DC\t\tBIT(0)\n+#define MTK_PHY_EEE_WAKE_SLV_INT_DC\t\tBIT(4)\n+\n+#define MTK_PHY_RG_DEV1E_REG324\t\t\t0x324\n+#define MTK_PHY_SMI_DETCNT_MAX_MASK\t\tGENMASK(5, 0)\n+#define MTK_PHY_SMI_DET_MAX_EN\t\tBIT(8)\n+\n+#define MTK_PHY_RG_DEV1E_REG326\t\t\t0x326\n+#define MTK_PHY_LPI_MODE_SD_ON\t\tBIT(0)\n+#define MTK_PHY_RESET_RANDUPD_CNT\t\tBIT(1)\n+#define MTK_PHY_TREC_UPDATE_ENAB_CLR\t\tBIT(2)\n+#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF\tBIT(4)\n+#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP\tBIT(5)\n+\n+#define MTK_PHY_LDO_PUMP_EN_PAIRAB\t\t0x502\n+#define MTK_PHY_LDO_PUMP_EN_PAIRCD\t\t0x503\n+\n+#define MTK_PHY_DA_TX_R50_PAIR_A\t\t0x53d\n+#define MTK_PHY_DA_TX_R50_PAIR_B\t\t0x53e\n+#define MTK_PHY_DA_TX_R50_PAIR_C\t\t0x53f\n+#define MTK_PHY_DA_TX_R50_PAIR_D\t\t0x540\n+\n+/* Registers on MDIO_MMD_VEND2 */\n+#define MTK_PHY_LED1_DEFAULT_POLARITIES\t\tBIT(1)\n+\n+#define MTK_PHY_RG_BG_RASEL\t\t\t0x115\n+#define MTK_PHY_RG_BG_RASEL_MASK\t\tGENMASK(2, 0)\n+\n+/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */\n+#define RG_GPIO_MISC_TPBANK0\t\t\t0x6f0\n+#define RG_GPIO_MISC_TPBANK0_BOOTMODE\t\tGENMASK(11, 8)\n+\n+enum CAL_ITEM {\n+\tREXT,\n+\tTX_OFFSET,\n+\tTX_AMP,\n+\tTX_R50,\n+\tTX_VCM,\n+\tRX_OFFSET,\n+};\n+\n+enum {\n+\tNO_PAIR,\n+\tPAIR_A,\n+\tPAIR_B,\n+\tPAIR_C,\n+\tPAIR_D,\n+};\n+\n+enum calibration_mode {\n+\tEFUSE_K,\n+\tSW_K\n+};\n+\n+enum CAL_MODE {\n+\tEFUSE_M,\n+\tSW_M\n+};\n+\n+/* MTK GE SoC common functions */\n+int mtk_cal_cycle_wait(struct phy_device *phydev);\n+\n+#endif /* _MTK_GE_SOC_H_ */\ndiff --git a/drivers/net/phy/mediatek/mtk-phy-lib.c b/drivers/net/phy/mediatek/mtk-phy-lib.c\nindex dfd0f4e439a214..8c2b26f9b8403b 100644\n--- a/drivers/net/phy/mediatek/mtk-phy-lib.c\n+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c\n@@ -36,8 +36,8 @@ static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n \t\t*tr_high, *tr_low);\n }\n \n-static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n-\t\t\t u8 data_addr, u32 tr_data)\n+void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n+\t\t u8 data_addr, u32 tr_data)\n {\n \t__phy_write(phydev, 0x11, tr_data \u0026 0xffff);\n \t__phy_write(phydev, 0x12, tr_data \u003e\u003e 16);\n@@ -45,6 +45,7 @@ static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n \t\ttr_data \u003e\u003e 16, tr_data \u0026 0xffff);\n \t__mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);\n }\n+EXPORT_SYMBOL_GPL(__mtk_tr_write);\n \n void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n \t\t u8 data_addr, u32 mask, u32 set)\n@@ -341,6 +342,78 @@ void mtk_phy_leds_state_init(struct phy_device *phydev)\n }\n EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);\n \n+int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,\n+\t\t\t unsigned long *delay_on,\n+\t\t\t unsigned long *delay_off)\n+{\n+\tbool blinking = false;\n+\tint err;\n+\n+\terr = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, \u0026blinking);\n+\tif (err \u003c 0)\n+\t\treturn err;\n+\n+\terr = mtk_phy_hw_led_blink_set(phydev, index, blinking);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,\n+\t\t\t\t false);\n+}\n+EXPORT_SYMBOL_GPL(mt798x_phy_led_blink_set);\n+\n+int mt798x_phy_led_brightness_set(struct phy_device *phydev,\n+\t\t\t\t u8 index, enum led_brightness value)\n+{\n+\tint err;\n+\n+\terr = mtk_phy_hw_led_blink_set(phydev, index, false);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,\n+\t\t\t\t (value != LED_OFF));\n+}\n+EXPORT_SYMBOL_GPL(mt798x_phy_led_brightness_set);\n+\n+static const unsigned long supported_triggers =\n+\tBIT(TRIGGER_NETDEV_FULL_DUPLEX) |\n+\tBIT(TRIGGER_NETDEV_HALF_DUPLEX) |\n+\tBIT(TRIGGER_NETDEV_LINK) |\n+\tBIT(TRIGGER_NETDEV_LINK_10) |\n+\tBIT(TRIGGER_NETDEV_LINK_100) |\n+\tBIT(TRIGGER_NETDEV_LINK_1000) |\n+\tBIT(TRIGGER_NETDEV_RX) |\n+\tBIT(TRIGGER_NETDEV_TX);\n+\n+int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long rules)\n+{\n+\treturn mtk_phy_led_hw_is_supported(phydev, index, rules,\n+\t\t\t\t\t supported_triggers);\n+}\n+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_is_supported);\n+\n+int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long *rules)\n+{\n+\treturn mtk_phy_led_hw_ctrl_get(phydev, index, rules,\n+\t\t\t\t MTK_GPHY_LED_ON_SET,\n+\t\t\t\t MTK_GPHY_LED_RX_BLINK_SET,\n+\t\t\t\t MTK_GPHY_LED_TX_BLINK_SET);\n+};\n+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_control_get);\n+\n+int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long rules)\n+{\n+\treturn mtk_phy_led_hw_ctrl_set(phydev, index, rules,\n+\t\t\t\t MTK_GPHY_LED_ON_SET,\n+\t\t\t\t MTK_GPHY_LED_RX_BLINK_SET,\n+\t\t\t\t MTK_GPHY_LED_TX_BLINK_SET);\n+};\n+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_control_set);\n+\n MODULE_DESCRIPTION(\"MediaTek Ethernet PHY driver common\");\n MODULE_AUTHOR(\"Sky Huang \u003cSkyLake.Huang@mediatek.com\u003e\");\n MODULE_AUTHOR(\"Daniel Golle \u003cdaniel@makrotopia.org\u003e\");\ndiff --git a/drivers/net/phy/mediatek/mtk.h b/drivers/net/phy/mediatek/mtk.h\nindex 320f76ffa81fa2..cd9d4c5550c3b7 100644\n--- a/drivers/net/phy/mediatek/mtk.h\n+++ b/drivers/net/phy/mediatek/mtk.h\n@@ -13,6 +13,7 @@\n \n #define MTK_EXT_PAGE_ACCESS\t\t\t0x1f\n #define MTK_PHY_PAGE_EXTENDED_1\t\t\t0x0001\n+#define MTK_PHY_PAGE_EXTENDED_3\t\t\t0x0003\n #define MTK_PHY_PAGE_STANDARD\t\t\t0x0000\n #define MTK_PHY_PAGE_EXTENDED_52B5\t\t0x52b5\n \n@@ -72,6 +73,8 @@ struct mtk_socphy_priv {\n \tunsigned long\t\tled_state;\n };\n \n+void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n+\t\t u8 data_addr, u32 tr_data);\n void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n \t\t u8 data_addr, u32 mask, u32 set);\n void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,\n@@ -101,4 +104,16 @@ int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,\n \t\t\t bool blinking);\n void mtk_phy_leds_state_init(struct phy_device *phydev);\n \n+int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,\n+\t\t\t unsigned long *delay_on,\n+\t\t\t unsigned long *delay_off);\n+int mt798x_phy_led_brightness_set(struct phy_device *phydev,\n+\t\t\t\t u8 index, enum led_brightness value);\n+int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long rules);\n+int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long *rules);\n+int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,\n+\t\t\t\t unsigned long rules);\n+\n #endif /* _MTK_EPHY_H_ */\n"
} |
| 2/1 | 2026/07/26 07:44 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific Ethernet PHY driver for Airoha SoCs and refactors shared MediaTek PHY library code. This code requires physical Airoha/MediaTek hardware (or specific MDIO bus emulation) to be probed and executed, which is not available in standard QEMU or virtualized environments. Therefore, it is unreachable during fuzzing.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 4bc164341d3cd4731036d67a6c6b951bf996ed51
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Jul 26 07:44:10 2026 +0000
syz-cluster: applied patch under review
diff --git a/MAINTAINERS b/MAINTAINERS
index 60cff00953dcbe..cf06a1512101cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -760,6 +760,14 @@ S: Maintained
F: Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
F: drivers/net/ethernet/airoha/
+AIROHA ETHERNET PHY DRIVER
+M: Christian Marangi <ansuelsmth@gmail.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/phy/mediatek/airoha-ge-soc.c
+
AIROHA PCIE PHY DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -16500,6 +16508,7 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/phy/mediatek/mtk-2p5ge.c
F: drivers/net/phy/mediatek/mtk-ge-soc.c
+F: drivers/net/phy/mediatek/mtk-ge-soc.h
F: drivers/net/phy/mediatek/mtk-phy-lib.c
F: drivers/net/phy/mediatek/mtk-ge.c
F: drivers/net/phy/mediatek/mtk.h
diff --git a/drivers/net/phy/mediatek/Kconfig b/drivers/net/phy/mediatek/Kconfig
index bb7dc876271e83..fe51f4616c544f 100644
--- a/drivers/net/phy/mediatek/Kconfig
+++ b/drivers/net/phy/mediatek/Kconfig
@@ -1,4 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-only
+config AIROHA_GE_SOC_PHY
+ tristate "Airoha SoC Ethernet PHYs"
+ depends on ARM64 || COMPILE_TEST
+ depends on ARCH_AIROHA || COMPILE_TEST
+ select MTK_NET_PHYLIB
+ select PHY_PACKAGE
+ help
+ Supports Airoha SoC built-in Gigabit Ethernet PHYs.
+
+ Include support for built-in Ethernet PHYs which are present in
+ the AN7581 and AN7583 SoCs. These PHYs d will dynamically
+ calibrate during startup.
+
config MEDIATEK_2P5GE_PHY
tristate "MediaTek 2.5Gb Ethernet PHYs"
depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
@@ -24,8 +37,7 @@ config MEDIATEK_GE_PHY
config MEDIATEK_GE_SOC_PHY
tristate "MediaTek SoC Ethernet PHYs"
depends on ARM64 || COMPILE_TEST
- depends on ARCH_AIROHA || (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || \
- COMPILE_TEST
+ depends on (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST
select MTK_NET_PHYLIB
select PHY_PACKAGE
help
diff --git a/drivers/net/phy/mediatek/Makefile b/drivers/net/phy/mediatek/Makefile
index ac57ecc799fc81..eb430f008169e2 100644
--- a/drivers/net/phy/mediatek/Makefile
+++ b/drivers/net/phy/mediatek/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_AIROHA_GE_SOC_PHY) += airoha-ge-soc.o
obj-$(CONFIG_MEDIATEK_2P5GE_PHY) += mtk-2p5ge.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
diff --git a/drivers/net/phy/mediatek/airoha-ge-soc.c b/drivers/net/phy/mediatek/airoha-ge-soc.c
new file mode 100644
index 00000000000000..601a64d8336542
--- /dev/null
+++ b/drivers/net/phy/mediatek/airoha-ge-soc.c
@@ -0,0 +1,1812 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/bitfield.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/phy.h>
+
+#include "../phylib.h"
+#include "mtk.h"
+#include "mtk-ge-soc.h"
+
+#define AIROHA_DEFAULT_PORT0_ADDR 0x9
+#define AIROHA_PHY_MAX_LEDS 2
+
+enum airoha_mdi_resister_type {
+ MDI_0R,
+ MDI_5R,
+
+ MDI_TYPE_MAX,
+};
+
+enum airoha_transformer_type {
+ TXMR,
+ DISCRETE,
+
+ TRANSFORMER_TYPE_MAX,
+};
+
+enum airoha_calib_const_type {
+ TX_AMP_TEST_A,
+ TX_AMP_TEST_B,
+ TX_AMP_TEST_C,
+ TX_AMP_TEST_D,
+ TX_AMP_1G_A,
+ TX_AMP_1G_B,
+ TX_AMP_1G_C,
+ TX_AMP_1G_D,
+ TX_AMP_100M_A,
+ TX_AMP_100M_B,
+ TX_AMP_10M_A,
+ TX_AMP_10M_B,
+ R50_A,
+ R50_B,
+ R50_C,
+ R50_D,
+
+ CALIB_CONST_TYPE_MAX,
+};
+
+struct airoha_socphy_shared {
+ struct phy_device *phydev_p0;
+ enum airoha_transformer_type transformer_type[4];
+ enum airoha_mdi_resister_type mdi_resister_type;
+ bool rext_sw_calib_done;
+ int (*tx_amp_compensation_tbl)[TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4];
+ u8 *r50_cal_tbl;
+};
+
+/*
+ * 2 chip revision
+ * TXMR or discrete
+ * 2 MDI type
+ * TX AMP test/TX AMP 1G/TX AMP 100M/TX AMP 10M/R50
+ * 4 PHY
+ */
+static int an7581_tx_amp_compensation_tbl[2][TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4] = {
+ { /* IC version 1 */
+ [TXMR] = {
+ { },
+ {
+ [TX_AMP_TEST_A] = { -12, -11, -9, -6 },
+ [TX_AMP_TEST_B] = { -9, -13, -9, -5 },
+ [TX_AMP_TEST_C] = { -5, -4, -3, 1 },
+ [TX_AMP_TEST_D] = { -9, -8, -7, -5 },
+ [TX_AMP_1G_A] = { -12, -11, -9, -6 },
+ [TX_AMP_1G_B] = { -9, -13, -9, -5 },
+ [TX_AMP_1G_C] = { -5, -4, -3, 1 },
+ [TX_AMP_1G_D] = { -9, -8, -7, -5 },
+ [TX_AMP_100M_A] = { -2, -2, 0, 2 },
+ [TX_AMP_100M_B] = { -2, -2, 1, 1 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 15, 15, 15, 15 },
+ [R50_B] = { 15, 15, 18, 15 },
+ [R50_C] = { -8, -8, -8, -8 },
+ [R50_D] = { -8, -8, -8, -8 },
+ },
+ },
+ [DISCRETE] = {
+ { },
+ {
+ [TX_AMP_TEST_A] = { -9, -7, -7, -5 },
+ [TX_AMP_TEST_B] = { -9, -9, -7, -4 },
+ [TX_AMP_TEST_C] = { -9, -7, -9, -6 },
+ [TX_AMP_TEST_D] = { -11, -9, -10, -8 },
+ [TX_AMP_1G_A] = { -9, -7, -7, -5 },
+ [TX_AMP_1G_B] = { -9, -8, -7, -4 },
+ [TX_AMP_1G_C] = { -9, -7, -9, -6 },
+ [TX_AMP_1G_D] = { -11, -8, -10, -8 },
+ [TX_AMP_100M_A] = { 4, 3, 4, 4 },
+ [TX_AMP_100M_B] = { 4, 4, 5, 4 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 0, 0, 0, 0 },
+ [R50_B] = { 0, 0, 0, 0 },
+ [R50_C] = { 0, 0, 0, 0 },
+ [R50_D] = { 0, 0, 0, 0 },
+ },
+ },
+ },
+ { /* IC version 2 */
+ [TXMR] = {
+ { },
+ {
+ [TX_AMP_TEST_A] = { -10, -12, -12, -11 },
+ [TX_AMP_TEST_B] = { -10, -11, -11, -10 },
+ [TX_AMP_TEST_C] = { -5, -7, -9, -3 },
+ [TX_AMP_TEST_D] = { -8, -10, -7, -8 },
+ [TX_AMP_1G_A] = { -12, -6, -6, 4 },
+ [TX_AMP_1G_B] = { -10, -5, -5, 1 },
+ [TX_AMP_1G_C] = { -5, -3, -4, 11 },
+ [TX_AMP_1G_D] = { -8, -3, -3, 4 },
+ [TX_AMP_100M_A] = { 2, 1, 0, 3 },
+ [TX_AMP_100M_B] = { 0, 0, 0, 3 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 15, 15, 15, 15 },
+ [R50_B] = { 15, 15, 18, 15 },
+ [R50_C] = { 4, 4, 4, 4 },
+ [R50_D] = { 4, 4, 4, 4 },
+ },
+ },
+ [DISCRETE] = {
+ { },
+ {
+ [TX_AMP_TEST_A] = { -11, 11, -12, -7 },
+ [TX_AMP_TEST_B] = { -9, -10, -9, -8 },
+ [TX_AMP_TEST_C] = { -6, -3, -7, -4 },
+ [TX_AMP_TEST_D] = { -7, -8, -10, -7 },
+ [TX_AMP_1G_A] = { -11, -11, -12, -7 },
+ [TX_AMP_1G_B] = { -9, -10, -9, -8 },
+ [TX_AMP_1G_C] = { -6, -3, -7, -4 },
+ [TX_AMP_1G_D] = { -7, -8, -10, -7 },
+ [TX_AMP_100M_A] = { 2, 2, 1, 2 },
+ [TX_AMP_100M_B] = { 3, 3, 3, 3 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 12, 12, 12, 12 },
+ [R50_B] = { 7, 7, 7, 7 },
+ [R50_C] = { 2, 2, 0, 0 },
+ [R50_D] = { 0, 0, 2, 2 },
+ },
+ },
+ },
+};
+
+static u8 an7581_zcal_to_r45ohm[64] = {
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 123, 119, 115, 112, 108, 104, 100, 96,
+ 94, 92, 88, 85, 82, 80, 76, 74, 72, 68, 66, 64, 62, 60, 56, 55,
+ 52, 50, 48, 46, 44, 42, 40, 39, 36, 35, 32, 32, 30, 28, 27, 25
+};
+
+/*
+ * 2 chip revision
+ * TXMR or discrete
+ * 2 MDI type
+ * TX AMP test/TX AMP 1G/TX AMP 100M/TX AMP 10M/R50
+ * 4 PHY
+ */
+static int an7583_tx_amp_compensation_tbl[TRANSFORMER_TYPE_MAX][MDI_TYPE_MAX][CALIB_CONST_TYPE_MAX][4] = {
+ [TXMR] = {
+ [MDI_0R] = {
+ [TX_AMP_TEST_A] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_B] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_C] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_D] = { -3, -3, -3, -3 },
+ [TX_AMP_1G_A] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_B] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_C] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_D] = { 0, 0, 0, 0 },
+ [TX_AMP_100M_A] = { 4, 4, 4, 4 },
+ [TX_AMP_100M_B] = { 4, 4, 4, 4 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 4, 4, 0, 0 },
+ [R50_B] = { 4, 4, 0, 0 },
+ [R50_C] = { 5, 5, 3, 4 },
+ [R50_D] = { 4, 4, 4, 0 },
+ },
+ [MDI_5R] = {
+ [TX_AMP_TEST_A] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_B] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_C] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_D] = { -3, -3, -3, -3 },
+ [TX_AMP_1G_A] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_B] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_C] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_D] = { 0, 0, 0, 0 },
+ [TX_AMP_100M_A] = { 4, 4, 4, 4 },
+ [TX_AMP_100M_B] = { 4, 4, 4, 4 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { -4, -4, -4, -4 },
+ [R50_B] = { -4, -4, -4, -4 },
+ [R50_C] = { -2, -2, -2, -2 },
+ [R50_D] = { -3, -3, -2, -2 },
+ },
+ },
+ [DISCRETE] = {
+ [MDI_0R] = {
+ [TX_AMP_TEST_A] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_B] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_C] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_D] = { -3, -3, -3, -3 },
+ [TX_AMP_1G_A] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_B] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_C] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_D] = { 0, 0, 0, 0 },
+ [TX_AMP_100M_A] = { 4, 4, 4, 4 },
+ [TX_AMP_100M_B] = { 4, 4, 4, 4 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 4, 4, 4, 4 },
+ [R50_B] = { 4, 4, 4, 4 },
+ [R50_C] = { 6, 6, 6, 6 },
+ [R50_D] = { 4, 4, 4, 4 },
+ },
+ [MDI_5R] = {
+ [TX_AMP_TEST_A] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_B] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_C] = { -3, -3, -3, -3 },
+ [TX_AMP_TEST_D] = { -3, -3, -3, -3 },
+ [TX_AMP_1G_A] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_B] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_C] = { 0, 0, 0, 0 },
+ [TX_AMP_1G_D] = { 0, 0, 0, 0 },
+ [TX_AMP_100M_A] = { 4, 4, 4, 4 },
+ [TX_AMP_100M_B] = { 4, 4, 4, 4 },
+ [TX_AMP_10M_A] = { 0, 0, 0, 0 },
+ [TX_AMP_10M_B] = { 0, 0, 0, 0 },
+ [R50_A] = { 0, 0, 0, 0 },
+ [R50_B] = { 0, 0, 0, 0 },
+ [R50_C] = { 0, 0, 0, 0 },
+ [R50_D] = { 0, 0, 0, 0 },
+ },
+ },
+};
+
+static u8 an7583_zcal_to_r50ohm_0R[64] = {
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 122, 118, 114, 110, 106, 102, 98, 96, 92, 88, 85, 82, 80,
+ 76, 72, 70, 68, 64, 62, 60, 57, 55, 52, 50, 48, 46, 44, 41, 40,
+ 38, 36, 33, 32, 30, 28, 26, 24, 24, 22, 20, 18, 16, 16, 14, 12,
+};
+
+static u8 an7583_zcal_to_r50ohm_5R[64] = {
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 120, 116, 112, 110, 106, 102,
+ 99, 96, 93, 90, 88, 84, 81, 79, 76, 73, 71, 68, 66, 64, 61, 59,
+ 56, 54, 52, 50, 48, 46, 44, 42, 40, 39, 37, 36, 33, 32, 31, 29,
+};
+
+static int airoha_cal_cycle(struct phy_device *phydev, int devad,
+ u32 regnum, u16 mask, u16 cal_val)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+
+ phy_modify_mmd(phydev, devad, regnum, mask, cal_val);
+
+ ret = mtk_cal_cycle_wait(phydev_p0);
+ phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+
+ return ret;
+}
+
+static int airoha_rext_cal_sw(struct phy_device *phydev)
+{
+ int calibration_polarity;
+ u8 zcal_ctrl = 32;
+ int first_calib;
+ int ret;
+
+ /* BG voltage output */
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x100, 0xc000);
+ /* tst_mode2 */
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xff, 0x2);
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 0xff,
+ GENMASK(15, 4) | GENMASK(1, 0));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN |
+ MTK_PHY_RG_REXT_CALEN);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0);
+
+ phydev_dbg(phydev, "Start REXT SW cal.\n");
+ first_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);
+
+ if (first_calib < 0) {
+ phydev_err(phydev, "REXT SW calibration failed.\n");
+ return -EINVAL;
+ }
+
+ /* If REXT calibration failed:
+ * - increase dB until calibration succeed.
+ * If REXT calibration succeeded:
+ * - decrease dB until calibration fail to fine tune it.
+ */
+ if (first_calib == 1)
+ calibration_polarity = -1;
+ else
+ calibration_polarity = 1;
+
+ while (zcal_ctrl > 0 &&
+ zcal_ctrl < FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {
+ zcal_ctrl += calibration_polarity;
+
+ ret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);
+ /* Exit if we either failed or succeeded compared to the
+ * first calibration result. (aka we finished fine tuning or
+ * we succeeded with calibration)
+ */
+ if (ret != first_calib)
+ break;
+ }
+
+ if (ret < 0) {
+ phydev_err(phydev, "REXT SW calibration failed.\n");
+ return -EINVAL;
+ }
+
+ if (zcal_ctrl == 0 ||
+ zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {
+ zcal_ctrl = 32;
+ phydev_err(phydev, "REXT SW calibration saturation. Defaulting to %x.\n",
+ zcal_ctrl);
+ }
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_TRIM_MASK,
+ FIELD_PREP(MTK_PHY_RG_REXT_TRIM_MASK, zcal_ctrl));
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
+ MTK_PHY_RG_BG_RASEL_MASK,
+ FIELD_PREP(MTK_PHY_RG_BG_RASEL_MASK, zcal_ctrl >> 3));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+
+ return 0;
+}
+
+static int airoha_tx_offset_cal_sw(struct phy_device *phydev, u8 txg_calen_x)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ u16 dev1e_145_tmp, bmcr_tmp;
+ int calibration_polarity;
+ u16 reg_dac1, reg_dac2;
+ int zcal_ctrl = 0;
+ int first_calib;
+ u16 reg, mask;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+
+ /* BG voltage output */
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+
+ /* Force 1G full duplex for calibration */
+ bmcr_tmp = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);
+
+ /* Force MDI */
+ dev1e_145_tmp = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x0145);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, 0x1010);
+
+ /* 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96,
+ 0x8000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e,
+ 0xf808);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_A;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_A;
+ reg = MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B;
+ mask = MTK_PHY_CR_TX_AMP_OFFSET_A_MASK;
+ break;
+ case PAIR_B:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(8));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_B;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_B;
+ reg = MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B;
+ mask = MTK_PHY_CR_TX_AMP_OFFSET_B_MASK;
+ break;
+ case PAIR_C:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(4));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_C;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_C;
+ reg = MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D;
+ mask = MTK_PHY_CR_TX_AMP_OFFSET_C_MASK;
+ break;
+ case PAIR_D:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(0));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_D;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_D;
+ reg = MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D;
+ mask = MTK_PHY_CR_TX_AMP_OFFSET_D_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac1,
+ 0x8000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac2,
+ 0x8000);
+
+ phydev_dbg(phydev, "Start TX Offset SW cal.\n");
+
+ first_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg, mask,
+ zcal_ctrl << __ffs(mask));
+
+ /* If TX Offset calibration failed:
+ * - increase dB until calibration succeed.
+ * If TX Offset calibration succeeded:
+ * - decrease dB until calibration fail to fine tune it.
+ */
+ if (first_calib == 1)
+ calibration_polarity = -1;
+ else
+ calibration_polarity = 1;
+
+ while (zcal_ctrl > -32 && zcal_ctrl < 32) {
+ u32 val;
+
+ zcal_ctrl += calibration_polarity;
+ if (zcal_ctrl >= 0)
+ val = zcal_ctrl;
+ else
+ /* BIT(5) signal negative number for TX Offset */
+ val = BIT(5) | abs(zcal_ctrl);
+
+ ret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg, mask,
+ val << __ffs(mask));
+ /* Exit if we either failed or succeeded compared to the
+ * first calibration result. (aka we finished fine tuning or
+ * we succeeded with calibration)
+ */
+ if (ret != first_calib)
+ break;
+ }
+
+ if (ret < 0) {
+ phydev_err(phydev, "TX Offset calibration failed.\n");
+ return -EINVAL;
+ }
+
+ if (zcal_ctrl == -32 ||
+ zcal_ctrl == 32) {
+ zcal_ctrl = 0;
+ phydev_err(phydev, "TX Offset SW calibration saturation. Defaulting to %x.\n",
+ zcal_ctrl);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, reg, mask,
+ zcal_ctrl << __ffs(mask));
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x100, 0x0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D, 0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0);
+
+ /* Restore BMCR */
+ phy_write(phydev, MII_BMCR, bmcr_tmp);
+
+ /* Restore MDI */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, dev1e_145_tmp);
+
+ return 0;
+}
+
+static int airoha_tx_amp_cal_sw(struct phy_device *phydev, u8 txg_calen_x)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ u16 mask_gbe, mask_tbt, mask_tst, mask_hbt;
+ u16 reg, reg_100, reg_dac1, reg_dac2;
+ struct phy_device *phydev_p0;
+ int calibration_polarity;
+ u8 zcal_ctrl = 32;
+ int first_calib;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+
+ /* BG voltage output */
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x145, 0x1010);
+
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+
+ /* select 1V */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);
+
+ /* enable Tx VLD*/
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xf808);
+
+ /* Force 1G full duplex for calibration */
+ phy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_A;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_A;
+ reg = MTK_PHY_TXVLD_DA_RG;
+ mask_gbe = MTK_PHY_DA_TX_I2MPB_A_GBE_MASK;
+ mask_tbt = MTK_PHY_DA_TX_I2MPB_A_TBT_MASK;
+ reg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_A2;
+ mask_hbt = MTK_PHY_DA_TX_I2MPB_A_HBT_MASK;
+ mask_tst = MTK_PHY_DA_TX_I2MPB_A_TST_MASK;
+ break;
+ case PAIR_B:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(8));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_B;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_B;
+ reg = MTK_PHY_TX_I2MPB_TEST_MODE_B1;
+ mask_gbe = MTK_PHY_DA_TX_I2MPB_B_GBE_MASK;
+ mask_tbt = MTK_PHY_DA_TX_I2MPB_B_TBT_MASK;
+ reg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_B2;
+ mask_hbt = MTK_PHY_DA_TX_I2MPB_B_HBT_MASK;
+ mask_tst = MTK_PHY_DA_TX_I2MPB_B_TST_MASK;
+ break;
+ case PAIR_C:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(4));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_C;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_C;
+ reg = MTK_PHY_TX_I2MPB_TEST_MODE_C1;
+ mask_gbe = MTK_PHY_DA_TX_I2MPB_C_GBE_MASK;
+ mask_tbt = MTK_PHY_DA_TX_I2MPB_C_TBT_MASK;
+ reg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_C2;
+ mask_hbt = MTK_PHY_DA_TX_I2MPB_C_HBT_MASK;
+ mask_tst = MTK_PHY_DA_TX_I2MPB_C_TST_MASK;
+ break;
+ case PAIR_D:
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(0));
+ reg_dac1 = MTK_PHY_RG_DASN_DAC_IN0_D;
+ reg_dac2 = MTK_PHY_RG_DASN_DAC_IN1_D;
+ reg = MTK_PHY_TX_I2MPB_TEST_MODE_D1;
+ mask_gbe = MTK_PHY_DA_TX_I2MPB_D_GBE_MASK;
+ mask_tbt = MTK_PHY_DA_TX_I2MPB_D_TBT_MASK;
+ reg_100 = MTK_PHY_TX_I2MPB_TEST_MODE_D2;
+ mask_hbt = MTK_PHY_DA_TX_I2MPB_D_HBT_MASK;
+ mask_tst = MTK_PHY_DA_TX_I2MPB_D_TST_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac1,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg_dac2,
+ 0x8000 | 0xf0);
+
+ phydev_dbg(phydev, "Start TX Amp SW cal.\n");
+ first_calib = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg,
+ mask_gbe, zcal_ctrl << __ffs(mask_gbe));
+
+ /* If TX Amp calibration failed:
+ * - increase dB until calibration succeed.
+ * If TX Amp calibration succeeded:
+ * - decrease dB until calibration fail to fine tune it.
+ */
+ if (first_calib == 1)
+ calibration_polarity = -1;
+ else
+ calibration_polarity = 1;
+
+ while (zcal_ctrl > 0 &&
+ zcal_ctrl < FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {
+ zcal_ctrl += calibration_polarity;
+
+ ret = airoha_cal_cycle(phydev, MDIO_MMD_VEND1, reg,
+ mask_gbe, zcal_ctrl << __ffs(mask_gbe));
+ /* Exit if we either failed or succeeded compared to the
+ * first calibration result. (aka we finished fine tuning or
+ * we succeeded with calibration)
+ */
+ if (ret != first_calib)
+ break;
+ }
+
+ if (ret < 0) {
+ phydev_err(phydev, "TX AMP calibration failed.\n");
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, reg,
+ mask_gbe | mask_tbt,
+ (zcal_ctrl << __ffs(mask_gbe)) |
+ (zcal_ctrl << __ffs(mask_tbt)));
+
+ return -EINVAL;
+ }
+
+ if (zcal_ctrl == 0 ||
+ zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK))
+ phydev_warn(phydev, "TX AMP SW calibration saturation.\n");
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, reg,
+ mask_gbe | mask_tbt,
+ (zcal_ctrl << __ffs(mask_gbe)) |
+ (zcal_ctrl << __ffs(mask_tbt)));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, reg_100,
+ mask_hbt | mask_tst,
+ (zcal_ctrl << __ffs(mask_hbt)) |
+ (zcal_ctrl << __ffs(mask_tst)));
+
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, 0x145, 0x1000);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0);
+
+ /* Restore AN enable */
+ phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+
+ return 0;
+}
+
+static int airoha_tx_r50_cal_sw(struct phy_device *phydev, u8 txg_calen_x)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ u16 dev1e_145_tmp, bmcr_tmp;
+ int calibration_polarity;
+ u8 zcal_ctrl = 32;
+ int first_calib;
+ u16 reg;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+
+ /* BG voltage output */
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0xc000);
+
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ /* select 1V */
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ /* select 1V */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x10);
+
+ /* Force 1G full duplex for calibration */
+ bmcr_tmp = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);
+
+ /* Force MDI */
+ dev1e_145_tmp = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x0145);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, 0x1010);
+
+ /* disable tx slew control */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0185, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00fb, 0x0100);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ break;
+ case PAIR_B:
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B);
+ break;
+ case PAIR_C:
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_C);
+ break;
+ case PAIR_D:
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_D);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phydev_dbg(phydev, "Start TX r50 SW cal.\n");
+ first_calib = airoha_cal_cycle(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);
+
+ if (first_calib < 0) {
+ phydev_err(phydev, "TX r50 SW calibration failed.\n");
+ return -EINVAL;
+ }
+
+ /* If TX r50 calibration failed:
+ * - increase dB until calibration succeed.
+ * If TX r50 calibration succeeded:
+ * - decrease dB until calibration fail to fine tune it.
+ */
+ if (first_calib == 1)
+ calibration_polarity = -1;
+ else
+ calibration_polarity = 1;
+
+ while (zcal_ctrl > 0 &&
+ zcal_ctrl < FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK)) {
+ zcal_ctrl += calibration_polarity;
+
+ ret = airoha_cal_cycle(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_ZCAL_CTRL_MASK, zcal_ctrl);
+ /* Exit if we either failed or succeeded compared to the
+ * first calibration result. (aka we finished fine tuning or
+ * we succeeded with calibration)
+ */
+ if (ret != first_calib)
+ break;
+ }
+
+ if (ret < 0) {
+ phydev_err(phydev, "TX r50 SW calibration failed.\n");
+ return -EINVAL;
+ }
+
+ if (zcal_ctrl == 0 ||
+ zcal_ctrl == FIELD_MAX(MTK_PHY_RG_REXT_ZCAL_CTRL_MASK))
+ phydev_warn(phydev, "TX r50 SW calibration saturation.\n");
+
+ zcal_ctrl = shared->r50_cal_tbl[zcal_ctrl];
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ reg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_A_MASK, zcal_ctrl);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_CR_TX_R50_OFFSET_A_B,
+ BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_A_MASK, reg);
+ break;
+ case PAIR_B:
+ reg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_B_MASK, zcal_ctrl);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_CR_TX_R50_OFFSET_A_B,
+ BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_B_MASK, reg);
+ break;
+ case PAIR_C:
+ reg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_C_MASK, zcal_ctrl);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_CR_TX_R50_OFFSET_C_D,
+ BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_C_MASK, reg);
+ break;
+ case PAIR_D:
+ reg = BIT(7) | FIELD_PREP(MTK_PHY_CR_TX_R50_OFFSET_D_MASK, zcal_ctrl);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_CR_TX_R50_OFFSET_C_D,
+ BIT(7) | MTK_PHY_CR_TX_R50_OFFSET_D_MASK, reg);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, 0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, 0);
+
+ /* Enable tx slew control */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0185, 0x0001);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00fb, 0x0000);
+
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x0);
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG6, 0x0);
+
+ /* Restore BMCR */
+ phy_write(phydev, MII_BMCR, bmcr_tmp);
+
+ /* Restore MDI */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0145, dev1e_145_tmp);
+
+ return 0;
+}
+
+static int airoha_rx_offset_cal_sw(struct phy_device *phydev)
+{
+ /* Hw bypass, Fw cal */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x96, 0x8000);
+ /* tx/rx_cal_criteria_value */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x37, 0x0033);
+
+ /* rx offset cal by Hw setup */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,
+ BIT(14) | BIT(11));
+
+ /* disable rtune calibration */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 0x107,
+ BIT(12));
+
+ /* bypass tx/rx dc offset cancellation process */
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 0x171,
+ BIT(8) | BIT(7));
+
+ /* rx offset calibration start */
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,
+ BIT(13));
+
+ /* rx offset calibration stop */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x39,
+ BIT(13));
+
+ mdelay(10);
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0x171,
+ BIT(8) | BIT(7));
+
+ if (phydev->drv->phy_id == AIROHA_GPHY_ID_AN7581)
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG6, 0x1);
+
+ return 0;
+}
+
+static int airoha_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++) {
+ switch (cal_item) {
+ case REXT:
+ ret = airoha_rext_cal_sw(phydev);
+ break;
+ case TX_OFFSET:
+ ret = airoha_tx_offset_cal_sw(phydev, pair_n);
+ break;
+ case TX_AMP:
+ ret = airoha_tx_amp_cal_sw(phydev, pair_n);
+ break;
+ case TX_R50:
+ ret = airoha_tx_r50_cal_sw(phydev, pair_n);
+ break;
+ case RX_OFFSET:
+ ret = airoha_rx_offset_cal_sw(phydev);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int airoha_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 SW_M:
+ ret = airoha_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 airoha_phy_calib(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+
+ /* PreCalibrate Set */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x5c, 0x6666);
+
+ if (!shared->rext_sw_calib_done) {
+ ret = airoha_start_cal(phydev, REXT, SW_M, NO_PAIR, NO_PAIR, NULL);
+ if (ret)
+ return ret;
+
+ shared->rext_sw_calib_done = true;
+ }
+
+ ret = airoha_start_cal(phydev, TX_R50, SW_M, PAIR_A, PAIR_D, NULL);
+ if (ret)
+ return ret;
+
+ ret = airoha_start_cal(phydev, TX_OFFSET, SW_M, PAIR_A, PAIR_D, NULL);
+ if (ret)
+ return ret;
+
+ ret = airoha_start_cal(phydev, TX_AMP, SW_M, PAIR_A, PAIR_D, NULL);
+ if (ret)
+ return ret;
+
+ ret = airoha_start_cal(phydev, RX_OFFSET, SW_M, NO_PAIR, NO_PAIR, NULL);
+ if (ret)
+ return ret;
+
+ /* Gating, short with other pair */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x15, 0x0);
+
+ phy_write_mmd(phydev_p0, MDIO_MMD_VEND2, 0x100, 0x0);
+
+ return 0;
+}
+
+static int airoha_phy_auto_select_transformer(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ u8 phy_offset;
+ u16 bmcr_tmp;
+ u16 val;
+ int i;
+
+ phydev_p0 = shared->phydev_p0;
+ phy_offset = phydev->mdio.addr - phydev_p0->mdio.addr;
+
+ /* Force 1G full duplex for calibration */
+ bmcr_tmp = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED1000);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x271, GENMASK(4, 0),
+ FIELD_PREP(GENMASK(4, 0), 0x3));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x269, GENMASK(15, 12),
+ FIELD_PREP(GENMASK(15, 12), 0x2));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, 0x26f, GENMASK(14, 12),
+ FIELD_PREP(GENMASK(14, 12), 0x0));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, BIT(12));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D,
+ 0x8000 | 0xf0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D,
+ 0x8000 | 0xf0);
+
+ /* Force pGA gain */
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x10,
+ GENMASK(20, 15),
+ FIELD_PREP(GENMASK(20, 15), 0x1f));
+
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x11,
+ GENMASK(23, 18) | GENMASK(15, 10) | GENMASK(7, 2),
+ FIELD_PREP(GENMASK(23, 18), 0x1f) |
+ FIELD_PREP(GENMASK(15, 10), 0x1f) |
+ FIELD_PREP(GENMASK(7, 2), 0x1f));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xc9, 0xffff);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x151, 0x12);
+
+ switch (phy_offset) {
+ case 0:
+ val = 0x1;
+ break;
+ case 1:
+ val = 0x3;
+ break;
+ case 2:
+ val = 0x5;
+ break;
+ case 3:
+ val = 0x7;
+ break;
+ default:
+ return -EINVAL;
+ }
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x15,
+ FIELD_PREP(GENMASK(14, 12), val) | 0x161);
+ mdelay(500);
+
+ for (i = 0; i < 3; i++)
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0x1a);
+
+ /* Check the value and report transformer type for later */
+ shared->transformer_type[phy_offset] = val < 0xe0;
+
+ /* Switch to Default */
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x15, 0x1000);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xdd, 0x0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_A,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_A,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_B,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_B,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_C,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_C,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN0_D,
+ 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DASN_DAC_IN1_D,
+ 0x0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xc9, 0xfff);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x151, 0x0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x10,
+ GENMASK(20, 15),
+ FIELD_PREP(GENMASK(20, 15), 0x4));
+
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x11,
+ GENMASK(23, 18) | GENMASK(15, 10) | GENMASK(7, 2),
+ FIELD_PREP(GENMASK(23, 18), 0x0) |
+ FIELD_PREP(GENMASK(15, 10), 0x0) |
+ FIELD_PREP(GENMASK(7, 2), 0x0));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ /* Restore BMCR */
+ phy_write(phydev, MII_BMCR, bmcr_tmp);
+
+ return 0;
+}
+
+static int airoha_phy_tx_amp_compensation(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+
+ u16 reg_1e_12_read;
+ u16 reg_1e_16_read;
+ u16 reg_1e_17_read;
+ u16 reg_1e_18_read;
+ u16 reg_1e_19_read;
+ u16 reg_1e_20_read;
+ u16 reg_1e_21_read;
+ u16 reg_1e_22_read;
+ u16 reg_1e_174_read;
+ u16 reg_1e_175_read;
+
+ int reg_1e_12_header;
+ int reg_1e_16_header;
+ int reg_1e_17_header;
+ int reg_1e_18_header;
+ int reg_1e_19_header;
+ int reg_1e_21_header;
+ int reg_1e_174_header;
+ int reg_1e_175_header;
+
+ int reg_1e_12_end;
+ int reg_1e_16_end;
+ int reg_1e_17_end;
+ int reg_1e_18_end;
+ int reg_1e_20_end;
+ int reg_1e_22_end;
+ int reg_1e_174_end;
+ int reg_1e_175_end;
+
+ struct phy_device *phydev_p0;
+ u8 phy_offset;
+
+ int txamp_low_limit = -3;
+ int txamp_high_limit = 0x42;
+
+ int r50_low_limit = -8;
+ int r50_high_limit = 0x88;
+
+ bool overflow;
+ int (*tx_amp_table)[CALIB_CONST_TYPE_MAX][4];
+ int transformer_type, mdi_resister_type;
+
+ phydev_p0 = shared->phydev_p0;
+ phy_offset = phydev->mdio.addr - phydev_p0->mdio.addr;
+
+ transformer_type = shared->transformer_type[phy_offset];
+ mdi_resister_type = shared->mdi_resister_type;
+ tx_amp_table = shared->tx_amp_compensation_tbl[transformer_type][mdi_resister_type];
+
+ reg_1e_12_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x12);
+ reg_1e_16_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x16);
+ reg_1e_17_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x17);
+ reg_1e_18_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x18);
+ reg_1e_19_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x19);
+ reg_1e_20_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x20);
+ reg_1e_21_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x21);
+ reg_1e_22_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x22);
+ reg_1e_174_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x174);
+ reg_1e_175_read = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x175);
+
+ reg_1e_12_header = ((reg_1e_12_read & 0xfc00) / 1024) + *tx_amp_table[TX_AMP_1G_A][phy_offset];
+ reg_1e_17_header = ((reg_1e_17_read & 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_B][phy_offset];
+ reg_1e_19_header = ((reg_1e_19_read & 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_C][phy_offset];
+ reg_1e_21_header = ((reg_1e_21_read & 0x3f00) / 256) + *tx_amp_table[TX_AMP_1G_D][phy_offset];
+
+ overflow = false;
+ if (reg_1e_12_header < txamp_low_limit ||
+ reg_1e_12_header > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_17_header < txamp_low_limit ||
+ reg_1e_17_header > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_19_header < txamp_low_limit ||
+ reg_1e_19_header > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_21_header < txamp_low_limit ||
+ reg_1e_21_header > txamp_high_limit)
+ overflow = true;
+
+ if (overflow) {
+ reg_1e_12_header = 0x20;
+ reg_1e_17_header = 0x20;
+ reg_1e_19_header = 0x20;
+ reg_1e_21_header = 0x20;
+ } else {
+ if (reg_1e_12_header < 0)
+ reg_1e_12_header = 0;
+ else if (reg_1e_12_header > 0x3f)
+ reg_1e_12_header = 0x3f;
+ if (reg_1e_17_header < 0)
+ reg_1e_17_header = 0;
+ else if (reg_1e_17_header > 0x3f)
+ reg_1e_17_header = 0x3f;
+ if (reg_1e_19_header < 0)
+ reg_1e_19_header = 0;
+ else if (reg_1e_19_header > 0x3f)
+ reg_1e_19_header = 0x3f;
+ if (reg_1e_21_header < 0)
+ reg_1e_21_header = 0;
+ else if (reg_1e_21_header > 0x3f)
+ reg_1e_21_header = 0x3f;
+ }
+
+ reg_1e_16_end = (reg_1e_16_read & 0x003f) + *tx_amp_table[TX_AMP_TEST_A][phy_offset];
+ reg_1e_18_end = (reg_1e_18_read & 0x003f) + *tx_amp_table[TX_AMP_TEST_B][phy_offset];
+ reg_1e_20_end = (reg_1e_20_read & 0x003f) + *tx_amp_table[TX_AMP_TEST_C][phy_offset];
+ reg_1e_22_end = (reg_1e_22_read & 0x003f) + *tx_amp_table[TX_AMP_TEST_D][phy_offset];
+
+ overflow = false;
+ if (reg_1e_16_end < txamp_low_limit ||
+ reg_1e_16_end > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_18_end < txamp_low_limit ||
+ reg_1e_18_end > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_20_end < txamp_low_limit ||
+ reg_1e_20_end > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_22_end < txamp_low_limit ||
+ reg_1e_22_end > txamp_high_limit)
+ overflow = true;
+
+ if (overflow) {
+ reg_1e_16_end = 0x20;
+ reg_1e_18_end = 0x20;
+ reg_1e_20_end = 0x20;
+ reg_1e_22_end = 0x20;
+ } else {
+ if (reg_1e_16_end < 0)
+ reg_1e_16_end = 0;
+ else if (reg_1e_16_end > 0x3f)
+ reg_1e_16_end = 0x3f;
+ if (reg_1e_18_end < 0)
+ reg_1e_18_end = 0;
+ else if (reg_1e_18_end > 0x3f)
+ reg_1e_18_end = 0x3f;
+ if (reg_1e_20_end < 0)
+ reg_1e_20_end = 0;
+ else if (reg_1e_20_end > 0x3f)
+ reg_1e_20_end = 0x3f;
+ if (reg_1e_22_end < 0)
+ reg_1e_22_end = 0;
+ else if (reg_1e_22_end > 0x3f)
+ reg_1e_22_end = 0x3f;
+ }
+
+ reg_1e_16_header = ((reg_1e_16_read & 0xfc00) / 1024) + *tx_amp_table[TX_AMP_100M_A][phy_offset];
+ reg_1e_18_header = ((reg_1e_18_read & 0x3f00) / 256) + *tx_amp_table[TX_AMP_100M_B][phy_offset];
+
+ overflow = false;
+ if (reg_1e_16_header < txamp_low_limit ||
+ reg_1e_16_header > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_18_header < txamp_low_limit ||
+ reg_1e_18_header > txamp_high_limit)
+ overflow = true;
+
+ if (overflow) {
+ reg_1e_16_header = 0x20;
+ reg_1e_18_header = 0x20;
+ } else {
+ if (reg_1e_16_header < 0)
+ reg_1e_16_header = 0;
+ else if (reg_1e_16_header > 0x3f)
+ reg_1e_16_header = 0x3f;
+ if (reg_1e_18_header < 0)
+ reg_1e_18_header = 0;
+ else if (reg_1e_18_header > 0x3f)
+ reg_1e_18_header = 0x3f;
+ }
+
+ reg_1e_12_end = (reg_1e_12_read & 0x003f) + *tx_amp_table[TX_AMP_10M_A][phy_offset];
+ reg_1e_17_end = (reg_1e_17_read & 0x003f) + *tx_amp_table[TX_AMP_10M_B][phy_offset];
+
+ overflow = false;
+ if (reg_1e_12_end < txamp_low_limit ||
+ reg_1e_12_end > txamp_high_limit)
+ overflow = true;
+ if (reg_1e_17_end < txamp_low_limit ||
+ reg_1e_17_end > txamp_high_limit)
+ overflow = true;
+
+ if (overflow) {
+ reg_1e_12_end = 0x20;
+ reg_1e_17_end = 0x20;
+ } else {
+ if (reg_1e_12_end < 0)
+ reg_1e_12_end = 0;
+ else if (reg_1e_12_end > 0x3f)
+ reg_1e_12_end = 0x3f;
+ if (reg_1e_17_end < 0)
+ reg_1e_17_end = 0;
+ else if (reg_1e_17_end > 0x3f)
+ reg_1e_17_end = 0x3f;
+ }
+
+ reg_1e_174_header = ((reg_1e_174_read & 0x7f00) / 256) + *tx_amp_table[R50_A][phy_offset];
+ reg_1e_174_end = (reg_1e_174_read & 0x007f) + *tx_amp_table[R50_B][phy_offset];
+ reg_1e_175_header = ((reg_1e_175_read & 0x7f00) / 256) + *tx_amp_table[R50_C][phy_offset];
+ reg_1e_175_end = (reg_1e_175_read & 0x007f) + *tx_amp_table[R50_D][phy_offset];
+
+ overflow = false;
+ if (reg_1e_174_header < r50_low_limit ||
+ reg_1e_174_header > r50_high_limit)
+ overflow = true;
+ if (reg_1e_174_end < r50_low_limit ||
+ reg_1e_174_end > r50_high_limit)
+ overflow = true;
+ if (reg_1e_175_header < r50_low_limit ||
+ reg_1e_175_header > r50_high_limit)
+ overflow = true;
+ if (reg_1e_175_end < r50_low_limit ||
+ reg_1e_175_end > r50_high_limit)
+ overflow = true;
+
+ if (overflow) {
+ reg_1e_174_header = 0x34;
+ reg_1e_174_end = 0x34;
+ reg_1e_175_header = 0x34;
+ reg_1e_175_end = 0x34;
+ } else {
+ if (reg_1e_174_header < 0)
+ reg_1e_174_header = 0;
+ else if (reg_1e_174_header > 0x7f)
+ reg_1e_174_header = 0x7f;
+ if (reg_1e_174_end < 0)
+ reg_1e_174_end = 0;
+ else if (reg_1e_174_end > 0x7f)
+ reg_1e_174_end = 0x7f;
+ if (reg_1e_175_header < 0)
+ reg_1e_175_header = 0;
+ else if (reg_1e_175_header > 0x7f)
+ reg_1e_175_header = 0x7f;
+ if (reg_1e_175_end < 0)
+ reg_1e_175_end = 0;
+ else if (reg_1e_175_end > 0x7f)
+ reg_1e_175_end = 0x7f;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x12,
+ (reg_1e_12_header * 1024) + reg_1e_12_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x16,
+ (reg_1e_16_header * 1024) + reg_1e_16_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x17,
+ (reg_1e_17_header * 256) + reg_1e_17_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x18,
+ (reg_1e_18_header * 256) + reg_1e_18_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x19,
+ (reg_1e_19_read & 0x00ff) + (reg_1e_19_header * 256));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x20,
+ (reg_1e_20_read & 0xff00) + reg_1e_20_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x21,
+ (reg_1e_21_read & 0x00ff) + (reg_1e_21_header * 256));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x22,
+ (reg_1e_22_read & 0xff00) + reg_1e_22_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x174,
+ 0x8080 + (reg_1e_174_header * 256) + reg_1e_174_end);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x175,
+ 0x8080 + (reg_1e_175_header * 256) + reg_1e_175_end);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x176, 0x4400);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x177, 0x0044);
+
+ return 0;
+}
+
+static int an7581_phy_config_init(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ u32 soc_pdidr;
+ u8 phy_offset;
+ int ret;
+
+ phydev_p0 = shared->phydev_p0;
+ phy_offset = phydev->mdio.addr - phydev_p0->mdio.addr;
+
+ /* FIXME: Read SoC PDIDR if available or default to 1 */
+ soc_pdidr = 1;
+
+ shared->mdi_resister_type = MDI_5R;
+ if (soc_pdidr == 1)
+ shared->tx_amp_compensation_tbl = &an7581_tx_amp_compensation_tbl[0];
+ else
+ shared->tx_amp_compensation_tbl = &an7581_tx_amp_compensation_tbl[1];
+ shared->r50_cal_tbl = an7581_zcal_to_r45ohm;
+
+ ret = airoha_phy_calib(phydev);
+ if (ret)
+ return ret;
+
+ ret = airoha_phy_auto_select_transformer(phydev);
+ if (ret)
+ return ret;
+
+ ret = airoha_phy_tx_amp_compensation(phydev);
+ if (ret)
+ return ret;
+
+ /* RX setting for 5R_TXMR before AN setting */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe6, 0x1111);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe7, 0x5555);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe9, 0x0001);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xfe, 0x0000);
+
+ /* Long Loop Reach setting */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x11, 0xff00);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x202, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x203, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x204, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x205, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x206, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x207, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x208, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x209, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20a, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20b, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20e, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x20f, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x210, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x211, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x212, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x213, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x214, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x215, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x216, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x217, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21a, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21b, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21c, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21d, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21e, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x21f, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x220, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x221, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x222, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x223, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x226, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x227, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x228, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x229, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22a, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22b, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22c, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22d, 0x0025);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22e, 0x2310);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x22f, 0x0025);
+
+ /* RX Setting */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3c, 0xc000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3d, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);
+
+ /* EEE setting */
+ phy_write_mmd(phydev, MDIO_MMD_AN, 0x3c, 0x0000);
+
+ /* RX */
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x41, 0x3333);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x44, 0x00c0);
+
+ /* 10M settings */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a3, 0x00d2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a4, 0x010e);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27b, 0x1177);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27c, 0x0808);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);
+ __phy_write(phydev, 0x14, 0x3a18);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_write(phydev, 0x9, 0x1e00);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x269, 0x2114);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26a, 0x1113);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26f, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x2c63);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x272, 0x0c2b);
+
+ /* EEE set because power down can't set tokenring */
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ __mtk_tr_write(phydev, 0x0, 0x7, 0x15, 0x0055a0);
+ __mtk_tr_write(phydev, 0x0, 0x7, 0x17, 0x07ff3f);
+ __mtk_tr_write(phydev, 0x1, 0xf, 0x0, 0x00001e);
+ __mtk_tr_write(phydev, 0x1, 0xf, 0x1, 0x6fb90a);
+ __mtk_tr_write(phydev, 0x1, 0xf, 0x18, 0x0e2f00);
+ __mtk_tr_write(phydev, 0x1, 0xd, 0x26, 0x444444);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x3, 0x000004);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x6, 0x2ebaef);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x8, 0x00000b);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0xc, 0x00504d);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0xd, 0x02314f);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0xf, 0x003028);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x10, 0x00000a);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x11, 0x040001);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x14, 0x00024a);
+ __mtk_tr_write(phydev, 0x2, 0xd, 0x1c, 0x003210);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x120, 0x8014);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x122, 0xffff);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x144, 0x0200);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14a, 0xee20);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x19b, 0x0111);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x234, 0x1181);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x238, 0x0120);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x239, 0x0117);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x2d1, 0x0733);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x323, 0x0011);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x324, 0x013f);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x326, 0x0037);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x268, 0x07f4);
+
+ if (shared->transformer_type[phy_offset] == TXMR) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0187);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cc);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0109);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x020b);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0202);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03c5);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0309);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x000e);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0002);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0880);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0880);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0880);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0880);
+ } else {
+ if (soc_pdidr == 2) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x269, 0x1114);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26a, 0x1113);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x26f, 0x2000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x4c88);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x272, 0x0c2b);
+
+ /* 100M sharp */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0190);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01c8);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0030);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0208);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0318);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03c8);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0230);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x0008);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0200);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0885);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0885);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0885);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0885);
+ } else {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0190);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cf);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0030);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x020f);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0318);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03cf);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x09, 0x0230);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x000f);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0200);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0003);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0003);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0003);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0003);
+ }
+ }
+
+ return 0;
+}
+
+static int an7581_phy_probe(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared;
+ struct mtk_socphy_priv *priv;
+ struct pinctrl *pinctrl;
+ int ret;
+
+ /* 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");
+
+ ret = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
+ sizeof(struct airoha_socphy_shared));
+ if (ret)
+ return ret;
+
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ if (phydev->mdio.addr == AIROHA_DEFAULT_PORT0_ADDR)
+ shared->phydev_p0 = phydev;
+
+ phydev->priv = priv;
+
+ return 0;
+}
+
+static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,
+ unsigned long modes)
+{
+ u16 val = 0;
+ u32 mode;
+
+ if (index >= AIROHA_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:
+ 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 int an7583_phy_config_init(struct phy_device *phydev)
+{
+ struct airoha_socphy_shared *shared = phy_package_get_priv(phydev);
+ struct phy_device *phydev_p0;
+ u8 phy_offset;
+ int ret;
+
+ /* BMCR_PDOWN is enabled by default */
+ phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
+
+ phydev_p0 = shared->phydev_p0;
+ phy_offset = phydev->mdio.addr - phydev_p0->mdio.addr;
+
+ /* FIXME: Read SoC MDI Resister Type if available or default to 5R */
+ shared->mdi_resister_type = MDI_5R;
+
+ shared->mdi_resister_type = MDI_5R;
+ if (shared->mdi_resister_type == MDI_0R)
+ shared->r50_cal_tbl = an7583_zcal_to_r50ohm_0R;
+ if (shared->mdi_resister_type == MDI_5R)
+ shared->r50_cal_tbl = an7583_zcal_to_r50ohm_5R;
+ shared->tx_amp_compensation_tbl = &an7583_tx_amp_compensation_tbl;
+
+ ret = airoha_phy_calib(phydev);
+ if (ret)
+ return ret;
+
+ ret = airoha_phy_auto_select_transformer(phydev);
+ if (ret)
+ return ret;
+
+ ret = airoha_phy_tx_amp_compensation(phydev);
+ if (ret)
+ return ret;
+
+ /* Enable Idle Mode Power Setting */
+ if (phy_offset == 0) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x268, 0x07F1);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x703, 0x3111);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x271, 0x3C24);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x701, 0x1023);
+ }
+
+ if (shared->transformer_type[phy_offset] == TXMR) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0881);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0881);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0881);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0881);
+
+ if (shared->mdi_resister_type == MDI_0R)
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);
+ else
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0200);
+ } else {
+ if (shared->mdi_resister_type == MDI_0R) {
+ /* RX setting for 5R_TXMR before AN setting */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe7, 0x6666);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe9, 0x0003);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xfe, 0x0006);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xe6, 0x1111);
+ /* 100M sharp */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0c86);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0c86);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0c86);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0c86);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cb);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0108);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0211);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03ce);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c8);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0005);
+ } else {
+ /* 100M sharp */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x23, 0x0886);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x24, 0x0886);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x25, 0x0886);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x26, 0x0886);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x00, 0x0195);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01, 0x01cb);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x02, 0x01c2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x03, 0x0108);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x04, 0x0211);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x05, 0x0205);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x06, 0x0387);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x07, 0x03ce);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x08, 0x03c3);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0a, 0x0010);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0b, 0x0005);
+ }
+ }
+
+ /* RX Setting */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3c, 0xc000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3d, 0x0000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x3e, 0xc000);
+
+ /* EEE setting */
+ phy_write_mmd(phydev, MDIO_MMD_AN, 0x3c, 0x0000);
+
+ /* 10M settings */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a3, 0x00d2);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x1a4, 0x010e);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27b, 0x1177);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x27c, 0x0808);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+ __phy_write(phydev, 0x14, 0x190);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);
+ __phy_write(phydev, 0x14, 0x3a18);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_write(phydev, 0x9, 0x0600);
+
+ /* EEE keep only Pair A ON */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x630, 0x006E);
+
+ return 0;
+}
+
+static struct phy_driver mtk_socphy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7581),
+ .name = "Airoha AN7581 PHY",
+ .config_init = an7581_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+ .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,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
+ },
+ {
+ PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7583),
+ .name = "Airoha AN7583 PHY",
+ .config_init = an7583_phy_config_init,
+ .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,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
+ },
+};
+
+module_phy_driver(mtk_socphy_driver);
+
+static const struct mdio_device_id __maybe_unused airoha_socphy_tbl[] = {
+ { PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7581) },
+ { PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7583) },
+ { }
+};
+
+MODULE_DESCRIPTION("Airoha SoC Gigabit Ethernet PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("01.01.20260306");
+
+MODULE_DEVICE_TABLE(mdio, airoha_socphy_tbl);
diff --git a/drivers/net/phy/mediatek/mtk-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c
index 9a54949644d5a5..4132ac40358355 100644
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -11,322 +11,10 @@
#include "../phylib.h"
#include "mtk.h"
+#include "mtk-ge-soc.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_GPHY_ID_AN7583 0xc0ff0420
-
-#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
-
-/* 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 = 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)
-
-/* 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 = 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 */
-#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 = 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)
-
-/* 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)
-
-/* 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
-
-#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_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))
@@ -346,51 +34,16 @@
#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
-};
-
struct mtk_socphy_shared {
u32 boottrap;
struct mtk_socphy_priv priv[4];
};
-/* 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 mtk_cal_cycle_wait(struct phy_device *phydev)
{
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);
@@ -409,7 +62,26 @@ static int cal_cycle(struct phy_device *phydev, int devad,
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);
+
+ return FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);
+}
+EXPORT_SYMBOL_GPL(mtk_cal_cycle_wait);
+
+/* 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 ret;
+
+ phy_modify_mmd(phydev, devad, regnum,
+ mask, cal_val);
+
+ ret = mtk_cal_cycle_wait(phydev);
phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
return ret;
@@ -1215,73 +887,6 @@ static int mt798x_phy_config_init(struct phy_device *phydev)
return mt798x_phy_calibration(phydev);
}
-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;
-
- err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
- if (err < 0)
- return err;
-
- err = mtk_phy_hw_led_blink_set(phydev, index, blinking);
- if (err)
- return err;
-
- 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,
- u8 index, enum led_brightness value)
-{
- int err;
-
- err = mtk_phy_hw_led_blink_set(phydev, index, false);
- if (err)
- return err;
-
- return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
- (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)
-{
- 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)
-{
- 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)
-{
- 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)
{
struct mtk_socphy_shared *priv = phy_package_get_priv(phydev);
@@ -1418,58 +1023,6 @@ static int mt7981_phy_probe(struct phy_device *phydev)
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)
-{
- u16 val = 0;
- u32 mode;
-
- 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:
- 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 int an7583_phy_config_init(struct phy_device *phydev)
-{
- /* BMCR_PDOWN is enabled by default */
- return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
-}
-
static struct phy_driver mtk_socphy_driver[] = {
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
@@ -1505,31 +1058,6 @@ static struct phy_driver mtk_socphy_driver[] = {
.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",
- .config_intr = genphy_no_config_intr,
- .handle_interrupt = genphy_handle_interrupt_no_ack,
- .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,
- },
- {
- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7583),
- .name = "Airoha AN7583 PHY",
- .config_init = an7583_phy_config_init,
- .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);
@@ -1537,8 +1065,6 @@ 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) },
- { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7583) },
{ }
};
diff --git a/drivers/net/phy/mediatek/mtk-ge-soc.h b/drivers/net/phy/mediatek/mtk-ge-soc.h
new file mode 100644
index 00000000000000..5e9d24a9833c77
--- /dev/null
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.h
@@ -0,0 +1,364 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _MTK_GE_SOC_H_
+#define _MTK_GE_SOC_H_
+
+#include <linux/bitfield.h>
+
+#define MTK_GPHY_ID_MT7981 0x03a29461
+#define MTK_GPHY_ID_MT7988 0x03a29481
+#define AIROHA_GPHY_ID_AN7581 0x03a294c1
+#define AIROHA_GPHY_ID_AN7583 0xc0ff0420
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+#define MTK_PHY_PAGE_STANDARD 0x0000
+#define MTK_PHY_PAGE_EXTENDED_1 0x0001
+#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
+
+/* 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 = 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)
+
+/* 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 = 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 */
+#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 = 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)
+
+/* 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)
+
+/* 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
+
+#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_REXT_CALEN BIT(4)
+#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_REXT_ZCAL_CTRL_MASK GENMASK(5, 0)
+
+#define MTK_PHY_RG_ANA_CAL_RG6 0xe1
+
+#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_CR_TX_R50_OFFSET_A_B 0x174
+#define MTK_PHY_CR_TX_R50_OFFSET_A_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_R50_OFFSET_B_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_CR_TX_R50_OFFSET_C_D 0x175
+#define MTK_PHY_CR_TX_R50_OFFSET_C_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_R50_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_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)
+
+enum CAL_ITEM {
+ REXT,
+ TX_OFFSET,
+ TX_AMP,
+ TX_R50,
+ TX_VCM,
+ RX_OFFSET,
+};
+
+enum {
+ NO_PAIR,
+ PAIR_A,
+ PAIR_B,
+ PAIR_C,
+ PAIR_D,
+};
+
+enum calibration_mode {
+ EFUSE_K,
+ SW_K
+};
+
+enum CAL_MODE {
+ EFUSE_M,
+ SW_M
+};
+
+/* MTK GE SoC common functions */
+int mtk_cal_cycle_wait(struct phy_device *phydev);
+
+#endif /* _MTK_GE_SOC_H_ */
diff --git a/drivers/net/phy/mediatek/mtk-phy-lib.c b/drivers/net/phy/mediatek/mtk-phy-lib.c
index dfd0f4e439a214..8c2b26f9b8403b 100644
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
@@ -36,8 +36,8 @@ static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
*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)
+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);
@@ -45,6 +45,7 @@ static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
tr_data >> 16, tr_data & 0xffff);
__mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
}
+EXPORT_SYMBOL_GPL(__mtk_tr_write);
void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
u8 data_addr, u32 mask, u32 set)
@@ -341,6 +342,78 @@ void mtk_phy_leds_state_init(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
+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;
+
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
+ if (err < 0)
+ return err;
+
+ err = mtk_phy_hw_led_blink_set(phydev, index, blinking);
+ if (err)
+ return err;
+
+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
+ false);
+}
+EXPORT_SYMBOL_GPL(mt798x_phy_led_blink_set);
+
+int mt798x_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ int err;
+
+ err = mtk_phy_hw_led_blink_set(phydev, index, false);
+ if (err)
+ return err;
+
+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
+ (value != LED_OFF));
+}
+EXPORT_SYMBOL_GPL(mt798x_phy_led_brightness_set);
+
+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);
+
+int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
+ supported_triggers);
+}
+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_is_supported);
+
+int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules)
+{
+ 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);
+};
+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_control_get);
+
+int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ 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);
+};
+EXPORT_SYMBOL_GPL(mt798x_phy_led_hw_control_set);
+
MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
diff --git a/drivers/net/phy/mediatek/mtk.h b/drivers/net/phy/mediatek/mtk.h
index 320f76ffa81fa2..cd9d4c5550c3b7 100644
--- a/drivers/net/phy/mediatek/mtk.h
+++ b/drivers/net/phy/mediatek/mtk.h
@@ -13,6 +13,7 @@
#define MTK_EXT_PAGE_ACCESS 0x1f
#define MTK_PHY_PAGE_EXTENDED_1 0x0001
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
#define MTK_PHY_PAGE_STANDARD 0x0000
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
@@ -72,6 +73,8 @@ struct mtk_socphy_priv {
unsigned long led_state;
};
+void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 tr_data);
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,
@@ -101,4 +104,16 @@ 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);
+int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
+ unsigned long *delay_on,
+ unsigned long *delay_off);
+int mt798x_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value);
+int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules);
+int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules);
+int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ unsigned long rules);
+
#endif /* _MTK_EPHY_H_ */
|
| 3/2 | 2026/07/26 07:44 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 55905 output: 19 thoughts: 1086 Thoughts: **Worth Fuzzing Assessment for Airoha SoC Ethernet PHY Driver** Okay, so we have this new patch adding the `airoha-ge-soc.c` driver for Airoha SoC Ethernet PHYs (AN7581 and AN7583), including the `CONFIG_AIROHA_GE_SOC_PHY` option and modifications to related Kconfig and Makefile files, and some code reorganization. My initial thought is to assess its fuzzing potential. As an Ethernet PHY driver, the typical reachability is through instantiation via an MDIO bus or during probing. The immediate question is whether we can effectively trigger this in a standard environment like QEMU. Usually, syzkaller relies on a physical or emulated MDIO bus for PHY probing, but it's not always straightforward. Often, PHY drivers are hardware-dependent and require the presence of actual hardware or a very specific emulation. While syzkaller has some abilities with virtual devices, direct PHY instantiation isn't its strong suit unless there's a specific driver support. My thought process then veers into considering how the driver gets probed. It uses `module_phy_driver(mtk_socphy_driver)` and matches `PHY_ID_MATCH_EXACT(AIROHA_GPHY_ID_AN7581)` and `AIROHA_GPHY_ID_AN7583`. The critical path here is the MDIO bus scanning and the reading of PHY ID registers (MII_PHYSID1 and MII_PHYSID2). In the absence of an Airoha SoC or a faithful emulation, the MDIO bus won't detect the PHY ID, and the driver won't be probed. I then remember there might be mock drivers or user-space control over MDIO buses. Could we create `mdio` devices from user space or use software MDIO bus implementations? Syzkaller's ability to trigger PHY probing could hinge on a software MDIO bus registration via device tree overlays. However, usually these drivers are considered hardware-specific. Based on the instructions, I'm now evaluating this against the "WorthFuzzing=false" criteria. Specifically, is this driver's code "impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware?" My conclusion is that unless QEMU specifically emulates the Airoha SoC's MDIO bus and PHY, this driver is likely unreachable. I can't inject an arbitrary PHY ID through `fixed-phy`, and even `syz_genetlink` may not be the way to go here. `ioctl(SIOCSMIIREG)` just sends commands to an *existing* PHY. The MDIO bus must read the correct PHY ID registers to match the driver. There is a moment of hope, however. After further review, I remember `drivers/net/phy/mdio-mockup.c`. This could be the solution, as it allows for fake MDIO buses and PHYs. I'll need to investigate how `mdio-mockup` functions and its availability. This could change the entire assessment, but as things stand, the Airoha PHY is likely unreachable without the right kind of emulation. |
| 4/2 | 2026/07/26 07:44 | tool | grepper |
0mError:no matches Args: {
"Expression": "mdio-mockup"
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/07/26 07:44 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57712 output: 17 thoughts: 20 Thoughts: Okay, here's the summary, rendered as a first-person thought process, keeping in mind the user is an expert: **Refining the PHY Hypothesis** Hmm, that initial thought, that it was the `mdio-mockup` driver causing the issue... I'm starting to doubt that. It doesn't quite feel right, intuitively. Time to recalibrate. Let's shift gears. Maybe, *just maybe*, the root cause lies within something related to the `fixed-phy` driver. It’s worth exploring that as a stronger possibility for now. I need to re-examine the system from that angle. |
| 6/2 | 2026/07/26 07:44 | tool | grepper |
0mError:no matches Args: {
"Expression": "fixed-phy"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/07/26 07:44 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57897 output: 17 thoughts: 8 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it's my own internal dialogue: **Initial Assessment: A Contradiction?** Wait, "fixed_phy"? That's a curious term, and it immediately sets off a flag. My immediate thought is, what are we *fixing* exactly? In the context of my work, "phy" typically refers to the physical layer, the very foundation. The implications of trying to "fix" something at that level are complex. It either suggests a deeper understanding of the system, at the level of the silicon itself, or some kind of bandage solution. This forces me to immediately begin assessing, do I know enough to interpret that phrase or am I missing vital context? |
| 8/2 | 2026/07/26 07:44 | tool | grepper |
0mArgs:{
"Expression": "fixed_phy"
}Results: {
"Output": "drivers/net/dsa/dsa_loop.c=438=static void dsa_loop_phydevs_unregister(void)\n--\ndrivers/net/dsa/dsa_loop.c-441-\t\tif (!IS_ERR(phydevs[i]))\ndrivers/net/dsa/dsa_loop.c:442:\t\t\tfixed_phy_unregister(phydevs[i]);\ndrivers/net/dsa/dsa_loop.c-443-\t}\n--\ndrivers/net/dsa/dsa_loop.c=482=static int __init dsa_loop_init(void)\n--\ndrivers/net/dsa/dsa_loop.c-491-\tfor (i = 0; i \u003c NUM_FIXED_PHYS; i++)\ndrivers/net/dsa/dsa_loop.c:492:\t\tphydevs[i] = fixed_phy_register_100fd();\ndrivers/net/dsa/dsa_loop.c-493-\n--\ndrivers/net/ethernet/broadcom/b44.c=2234=static int b44_register_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2272-\ndrivers/net/ethernet/broadcom/b44.c:2273:\t\tphydev = fixed_phy_register_100fd();\ndrivers/net/ethernet/broadcom/b44.c-2274-\t\tif (!IS_ERR(phydev))\n--\ndrivers/net/ethernet/broadcom/b44.c=2313=static void b44_unregister_phy_one(struct b44 *bp)\n--\ndrivers/net/ethernet/broadcom/b44.c-2322-\tif (phy_is_pseudo_fixed_link(phydev))\ndrivers/net/ethernet/broadcom/b44.c:2323:\t\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/broadcom/b44.c-2324-\tmdiobus_unregister(mii_bus);\n--\ndrivers/net/ethernet/broadcom/bgmac.c=1439=int bgmac_phy_connect_direct(struct bgmac *bgmac)\ndrivers/net/ethernet/broadcom/bgmac.c-1440-{\ndrivers/net/ethernet/broadcom/bgmac.c:1441:\tstruct fixed_phy_status fphy_status = {\ndrivers/net/ethernet/broadcom/bgmac.c-1442-\t\t.link = 1,\n--\ndrivers/net/ethernet/broadcom/bgmac.c-1448-\ndrivers/net/ethernet/broadcom/bgmac.c:1449:\tphy_dev = fixed_phy_register(\u0026fphy_status, NULL);\ndrivers/net/ethernet/broadcom/bgmac.c-1450-\tif (IS_ERR(phy_dev)) {\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=97=void bcmgenet_mii_setup(struct net_device *dev)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-116-\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:117:static int bcmgenet_fixed_phy_link_update(struct net_device *dev,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:118:\t\t\t\t\t struct fixed_phy_status *status)\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-119-{\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c=186=static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)\n--\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-188-\tif (bcmgenet_has_moca_link_det(priv))\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:189:\t\tfixed_phy_set_link_update(priv-\u003edev-\u003ephydev,\ndrivers/net/ethernet/broadcom/genet/bcmmii.c:190:\t\t\t\t\t bcmgenet_fixed_phy_link_update);\ndrivers/net/ethernet/broadcom/genet/bcmmii.c-191-}\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=43=struct ftgmac100_match_data {\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-66-/* For NC-SI to register a fixed-link phy device */\ndrivers/net/ethernet/faraday/ftgmac100.c:67:static struct fixed_phy_status ncsi_phy_status = {\ndrivers/net/ethernet/faraday/ftgmac100.c-68-\t.link = 1,\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1780=static void ftgmac100_phy_disconnect(struct net_device *netdev)\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1792-\tif (priv-\u003euse_ncsi)\ndrivers/net/ethernet/faraday/ftgmac100.c:1793:\t\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/faraday/ftgmac100.c-1794-}\n--\ndrivers/net/ethernet/faraday/ftgmac100.c=1848=static int ftgmac100_probe_ncsi(struct net_device *netdev,\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1866-\ndrivers/net/ethernet/faraday/ftgmac100.c:1867:\tphydev = fixed_phy_register(\u0026ncsi_phy_status, np);\ndrivers/net/ethernet/faraday/ftgmac100.c-1868-\tif (IS_ERR(phydev)) {\n--\ndrivers/net/ethernet/faraday/ftgmac100.c-1881-err_register_phy:\ndrivers/net/ethernet/faraday/ftgmac100.c:1882:\tfixed_phy_unregister(phydev);\ndrivers/net/ethernet/faraday/ftgmac100.c-1883-err_register_ndev:\n--\ndrivers/net/ethernet/freescale/fec_main.c=2981=static int fec_enet_mii_probe(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-3002-\t\t\tnetdev_info(ndev, \"no PHY, assuming direct connection to switch\\n\");\ndrivers/net/ethernet/freescale/fec_main.c:3003:\t\t\tphy_dev = fixed_phy_register_100fd();\ndrivers/net/ethernet/freescale/fec_main.c-3004-\t\t\tif (IS_ERR(phy_dev)) {\n--\ndrivers/net/ethernet/freescale/fec_main.c-3013-\t\t\tif (phy_is_pseudo_fixed_link(phy_dev))\ndrivers/net/ethernet/freescale/fec_main.c:3014:\t\t\t\tfixed_phy_unregister(phy_dev);\ndrivers/net/ethernet/freescale/fec_main.c-3015-\t\t\tnetdev_err(ndev, \"could not attach to PHY\\n\");\n--\ndrivers/net/ethernet/freescale/fec_main.c=4228=fec_enet_close(struct net_device *ndev)\n--\ndrivers/net/ethernet/freescale/fec_main.c-4243-\tif (!fep-\u003ephy_node \u0026\u0026 phy_is_pseudo_fixed_link(phy_dev))\ndrivers/net/ethernet/freescale/fec_main.c:4244:\t\tfixed_phy_unregister(phy_dev);\ndrivers/net/ethernet/freescale/fec_main.c-4245-\n--\ndrivers/net/ethernet/freescale/gianfar.c=3138=static const struct net_device_ops gfar_netdev_ops = {\n--\ndrivers/net/ethernet/freescale/gianfar.c-3147-\t.ndo_get_stats64 = gfar_get_stats64,\ndrivers/net/ethernet/freescale/gianfar.c:3148:\t.ndo_change_carrier = fixed_phy_change_carrier,\ndrivers/net/ethernet/freescale/gianfar.c-3149-\t.ndo_set_mac_address = gfar_set_mac_addr,\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=228=void hbg_phy_stop(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-232-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:233:static void hbg_fixed_phy_uninit(void *data)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-234-{\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:235:\tfixed_phy_unregister((struct phy_device *)data);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-236-}\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-237-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:238:static int hbg_fixed_phy_init(struct hbg_priv *priv)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-239-{\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:240:\tstruct fixed_phy_status hbg_fixed_phy_status = {\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-241-\t\t.link = 1,\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-250-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:251:\tphydev = fixed_phy_register(\u0026hbg_fixed_phy_status, NULL);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-252-\tif (IS_ERR(phydev)) {\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-257-\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:258:\tret = devm_add_action_or_reset(dev, hbg_fixed_phy_uninit, phydev);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-259-\tif (ret)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c=266=int hbg_mdio_init(struct hbg_priv *priv)\n--\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-275-\tif (mac-\u003ephy_addr == HBG_NO_PHY)\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c:276:\t\treturn hbg_fixed_phy_init(priv);\ndrivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c-277-\n--\ndrivers/net/mdio/of_mdio.c=412=int of_phy_register_fixed_link(struct device_node *np)\ndrivers/net/mdio/of_mdio.c-413-{\ndrivers/net/mdio/of_mdio.c:414:\tstruct fixed_phy_status status = {};\ndrivers/net/mdio/of_mdio.c-415-\tstruct device_node *fixed_link_node;\n--\ndrivers/net/mdio/of_mdio.c-459-register_phy:\ndrivers/net/mdio/of_mdio.c:460:\treturn PTR_ERR_OR_ZERO(fixed_phy_register(\u0026status, np));\ndrivers/net/mdio/of_mdio.c-461-}\n--\ndrivers/net/mdio/of_mdio.c=464=void of_phy_deregister_fixed_link(struct device_node *np)\n--\ndrivers/net/mdio/of_mdio.c-471-\ndrivers/net/mdio/of_mdio.c:472:\tfixed_phy_unregister(phydev);\ndrivers/net/mdio/of_mdio.c-473-\n--\ndrivers/net/phy/Makefile=64=obj-$(CONFIG_DP83TG720_PHY)\t+= dp83tg720.o\ndrivers/net/phy/Makefile:65:obj-$(CONFIG_FIXED_PHY)\t\t+= fixed_phy.o\ndrivers/net/phy/Makefile-66-obj-$(CONFIG_ICPLUS_PHY)\t+= icplus.o\n--\ndrivers/net/phy/fixed_phy.c-27-\ndrivers/net/phy/fixed_phy.c:28:struct fixed_phy {\ndrivers/net/phy/fixed_phy.c-29-\tstruct phy_device *phydev;\ndrivers/net/phy/fixed_phy.c:30:\tstruct fixed_phy_status status;\ndrivers/net/phy/fixed_phy.c:31:\tint (*link_update)(struct net_device *, struct fixed_phy_status *);\ndrivers/net/phy/fixed_phy.c-32-};\ndrivers/net/phy/fixed_phy.c-33-\ndrivers/net/phy/fixed_phy.c:34:static DECLARE_BITMAP(fixed_phy_ids, NUM_FP);\ndrivers/net/phy/fixed_phy.c:35:static struct fixed_phy fmb_fixed_phys[NUM_FP];\ndrivers/net/phy/fixed_phy.c-36-static struct mii_bus *fmb_mii_bus;\ndrivers/net/phy/fixed_phy.c-37-\ndrivers/net/phy/fixed_phy.c:38:static struct fixed_phy *fixed_phy_find(int addr)\ndrivers/net/phy/fixed_phy.c-39-{\ndrivers/net/phy/fixed_phy.c:40:\treturn test_bit(addr, fixed_phy_ids) ? fmb_fixed_phys + addr : NULL;\ndrivers/net/phy/fixed_phy.c-41-}\ndrivers/net/phy/fixed_phy.c-42-\ndrivers/net/phy/fixed_phy.c:43:int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier)\ndrivers/net/phy/fixed_phy.c-44-{\ndrivers/net/phy/fixed_phy.c-45-\tstruct phy_device *phydev = dev-\u003ephydev;\ndrivers/net/phy/fixed_phy.c:46:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-47-\n--\ndrivers/net/phy/fixed_phy.c-50-\ndrivers/net/phy/fixed_phy.c:51:\tfp = fixed_phy_find(phydev-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-52-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-58-}\ndrivers/net/phy/fixed_phy.c:59:EXPORT_SYMBOL_GPL(fixed_phy_change_carrier);\ndrivers/net/phy/fixed_phy.c-60-\ndrivers/net/phy/fixed_phy.c=61=static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)\ndrivers/net/phy/fixed_phy.c-62-{\ndrivers/net/phy/fixed_phy.c:63:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-64-\ndrivers/net/phy/fixed_phy.c:65:\tfp = fixed_phy_find(phy_addr);\ndrivers/net/phy/fixed_phy.c-66-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c=75=static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num,\n--\ndrivers/net/phy/fixed_phy.c-85- */\ndrivers/net/phy/fixed_phy.c:86:int fixed_phy_set_link_update(struct phy_device *phydev,\ndrivers/net/phy/fixed_phy.c-87-\t\t\t int (*link_update)(struct net_device *,\ndrivers/net/phy/fixed_phy.c:88:\t\t\t\t\t\t struct fixed_phy_status *))\ndrivers/net/phy/fixed_phy.c-89-{\ndrivers/net/phy/fixed_phy.c:90:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-91-\n--\ndrivers/net/phy/fixed_phy.c-94-\ndrivers/net/phy/fixed_phy.c:95:\tfp = fixed_phy_find(phydev-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-96-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-103-}\ndrivers/net/phy/fixed_phy.c:104:EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);\ndrivers/net/phy/fixed_phy.c-105-\ndrivers/net/phy/fixed_phy.c:106:static void fixed_phy_del(int phy_addr)\ndrivers/net/phy/fixed_phy.c-107-{\ndrivers/net/phy/fixed_phy.c:108:\tstruct fixed_phy *fp;\ndrivers/net/phy/fixed_phy.c-109-\ndrivers/net/phy/fixed_phy.c:110:\tfp = fixed_phy_find(phy_addr);\ndrivers/net/phy/fixed_phy.c-111-\tif (!fp)\n--\ndrivers/net/phy/fixed_phy.c-114-\tmemset(fp, 0, sizeof(*fp));\ndrivers/net/phy/fixed_phy.c:115:\tclear_bit(phy_addr, fixed_phy_ids);\ndrivers/net/phy/fixed_phy.c-116-}\ndrivers/net/phy/fixed_phy.c-117-\ndrivers/net/phy/fixed_phy.c:118:static int fixed_phy_get_free_addr(void)\ndrivers/net/phy/fixed_phy.c-119-{\n--\ndrivers/net/phy/fixed_phy.c-122-\tdo {\ndrivers/net/phy/fixed_phy.c:123:\t\taddr = find_first_zero_bit(fixed_phy_ids, NUM_FP);\ndrivers/net/phy/fixed_phy.c-124-\t\tif (addr == NUM_FP)\ndrivers/net/phy/fixed_phy.c-125-\t\t\treturn -ENOSPC;\ndrivers/net/phy/fixed_phy.c:126:\t} while (test_and_set_bit(addr, fixed_phy_ids));\ndrivers/net/phy/fixed_phy.c-127-\n--\ndrivers/net/phy/fixed_phy.c-130-\ndrivers/net/phy/fixed_phy.c:131:struct phy_device *fixed_phy_register(const struct fixed_phy_status *status,\ndrivers/net/phy/fixed_phy.c-132-\t\t\t\t struct device_node *np)\n--\ndrivers/net/phy/fixed_phy.c-145-\t/* Get the next available PHY address, up to NUM_FP */\ndrivers/net/phy/fixed_phy.c:146:\tphy_addr = fixed_phy_get_free_addr();\ndrivers/net/phy/fixed_phy.c-147-\tif (phy_addr \u003c 0)\n--\ndrivers/net/phy/fixed_phy.c-149-\ndrivers/net/phy/fixed_phy.c:150:\tfmb_fixed_phys[phy_addr].status = *status;\ndrivers/net/phy/fixed_phy.c:151:\tfmb_fixed_phys[phy_addr].status.link = true;\ndrivers/net/phy/fixed_phy.c-152-\n--\ndrivers/net/phy/fixed_phy.c-154-\tif (IS_ERR(phy)) {\ndrivers/net/phy/fixed_phy.c:155:\t\tfixed_phy_del(phy_addr);\ndrivers/net/phy/fixed_phy.c-156-\t\treturn ERR_PTR(-EINVAL);\n--\ndrivers/net/phy/fixed_phy.c-166-\t\tof_node_put(np);\ndrivers/net/phy/fixed_phy.c:167:\t\tfixed_phy_del(phy_addr);\ndrivers/net/phy/fixed_phy.c-168-\t\treturn ERR_PTR(ret);\n--\ndrivers/net/phy/fixed_phy.c-172-}\ndrivers/net/phy/fixed_phy.c:173:EXPORT_SYMBOL_GPL(fixed_phy_register);\ndrivers/net/phy/fixed_phy.c-174-\ndrivers/net/phy/fixed_phy.c:175:struct phy_device *fixed_phy_register_100fd(void)\ndrivers/net/phy/fixed_phy.c-176-{\ndrivers/net/phy/fixed_phy.c:177:\tstatic const struct fixed_phy_status status = {\ndrivers/net/phy/fixed_phy.c-178-\t\t.speed\t= SPEED_100,\n--\ndrivers/net/phy/fixed_phy.c-181-\ndrivers/net/phy/fixed_phy.c:182:\treturn fixed_phy_register(\u0026status, NULL);\ndrivers/net/phy/fixed_phy.c-183-}\ndrivers/net/phy/fixed_phy.c:184:EXPORT_SYMBOL_GPL(fixed_phy_register_100fd);\ndrivers/net/phy/fixed_phy.c-185-\ndrivers/net/phy/fixed_phy.c:186:void fixed_phy_unregister(struct phy_device *phy)\ndrivers/net/phy/fixed_phy.c-187-{\n--\ndrivers/net/phy/fixed_phy.c-189-\tof_node_put(phy-\u003emdio.dev.of_node);\ndrivers/net/phy/fixed_phy.c:190:\tfixed_phy_del(phy-\u003emdio.addr);\ndrivers/net/phy/fixed_phy.c-191-\tphy_device_free(phy);\ndrivers/net/phy/fixed_phy.c-192-}\ndrivers/net/phy/fixed_phy.c:193:EXPORT_SYMBOL_GPL(fixed_phy_unregister);\ndrivers/net/phy/fixed_phy.c-194-\n--\ndrivers/net/phy/phylink.c=3360=static int phylink_mii_emul_read(unsigned int reg,\n--\ndrivers/net/phy/phylink.c-3362-{\ndrivers/net/phy/phylink.c:3363:\tstruct fixed_phy_status fs;\ndrivers/net/phy/phylink.c-3364-\tunsigned long *lpa = state-\u003elp_advertising;\n--\ndrivers/net/phy/swphy.c-4- *\ndrivers/net/phy/swphy.c:5: * Code taken from fixed_phy.c by Russell King.\ndrivers/net/phy/swphy.c-6- *\n--\ndrivers/net/phy/swphy.c=71=static int swphy_decode_speed(int speed)\n--\ndrivers/net/phy/swphy.c-92- */\ndrivers/net/phy/swphy.c:93:int swphy_validate_state(const struct fixed_phy_status *state)\ndrivers/net/phy/swphy.c-94-{\n--\ndrivers/net/phy/swphy.c=106=EXPORT_SYMBOL_GPL(swphy_validate_state);\n--\ndrivers/net/phy/swphy.c-114- */\ndrivers/net/phy/swphy.c:115:int swphy_read_reg(int reg, const struct fixed_phy_status *state)\ndrivers/net/phy/swphy.c-116-{\n--\ndrivers/net/phy/swphy.h-4-\ndrivers/net/phy/swphy.h:5:struct fixed_phy_status;\ndrivers/net/phy/swphy.h-6-\ndrivers/net/phy/swphy.h:7:int swphy_validate_state(const struct fixed_phy_status *state);\ndrivers/net/phy/swphy.h:8:int swphy_read_reg(int reg, const struct fixed_phy_status *state);\ndrivers/net/phy/swphy.h-9-\n--\ninclude/linux/phy_fixed.h-6-\ninclude/linux/phy_fixed.h:7:struct fixed_phy_status {\ninclude/linux/phy_fixed.h-8-\tint speed;\n--\ninclude/linux/phy_fixed.h=16=struct net_device;\n--\ninclude/linux/phy_fixed.h-18-#if IS_ENABLED(CONFIG_FIXED_PHY)\ninclude/linux/phy_fixed.h:19:extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier);\ninclude/linux/phy_fixed.h:20:struct phy_device *fixed_phy_register(const struct fixed_phy_status *status,\ninclude/linux/phy_fixed.h-21-\t\t\t\t struct device_node *np);\ninclude/linux/phy_fixed.h:22:struct phy_device *fixed_phy_register_100fd(void);\ninclude/linux/phy_fixed.h-23-\ninclude/linux/phy_fixed.h:24:extern void fixed_phy_unregister(struct phy_device *phydev);\ninclude/linux/phy_fixed.h:25:extern int fixed_phy_set_link_update(struct phy_device *phydev,\ninclude/linux/phy_fixed.h-26-\t\t\tint (*link_update)(struct net_device *,\ninclude/linux/phy_fixed.h:27:\t\t\t\t\t struct fixed_phy_status *));\ninclude/linux/phy_fixed.h-28-#else\ninclude/linux/phy_fixed.h=29=static inline struct phy_device *\ninclude/linux/phy_fixed.h:30:fixed_phy_register(const struct fixed_phy_status *status,\ninclude/linux/phy_fixed.h-31-\t\t struct device_node *np)\n--\ninclude/linux/phy_fixed.h-35-\ninclude/linux/phy_fixed.h:36:static inline struct phy_device *fixed_phy_register_100fd(void)\ninclude/linux/phy_fixed.h-37-{\n--\ninclude/linux/phy_fixed.h-40-\ninclude/linux/phy_fixed.h:41:static inline void fixed_phy_unregister(struct phy_device *phydev)\ninclude/linux/phy_fixed.h-42-{\n"
} |
| 9/2 | 2026/07/26 07:44 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 65175 output: 106 thoughts: 1381 Thoughts: **Analysis of the Airoha Ethernet PHY Driver Patch** Okay, let's break this down. My initial thought is that `fixed_phy` won't apply here; this is for a specific PHY driver, not a fixed link. How do we even *reach* a PHY driver without a real MDIO bus? The standard probe mechanism relies on the MDIO bus scanning and matching the PHY ID with a driver's ID. Without a physical MDIO bus, or an emulated one that can *report* specific PHY IDs, we're stuck. I thought about `mdio-mockup`, but that's a dead end. I glanced at other `mdio-bcm-unimac` style drivers, no luck there. Could we maybe instantiate a PHY device through sysfs? Nope, PHYs are usually brought up by the MDIO bus. What about `mdio-gpio` or `mdio-bitbang`? Possible avenues, but unlikely in a standard fuzzing setup. The ideal scenario would be if syzkaller could create a virtual MDIO bus. But, syzkaller doesn't have that general MDIO injection right now, or at least I don't know of a generic way to inject any specific PHY IDs. There's `drivers/net/dummy.c`... no PHY there. And things like `macsec.c` or `macvlan.c` are also not PHYs. And, no PHY in `tun.c`. So, the general rule is that PHY drivers are *hardware-specific*. To actually test this, we need the hardware *or* an emulator that is very specific to this hardware. The instructions clearly state that code unreachable in virtual environments should get `WorthFuzzing=false`. This patch adds `drivers/net/phy/mediatek/airoha-ge-soc.c`, which is explicitly a vendor-specific Ethernet PHY driver for Airoha SoCs. It hinges on the Airoha SoC hardware (or at least its MDIO bus and PHY). Standard QEMU doesn't emulate Airoha SoCs or their Ethernet PHYs. Bingo. This code is *impossible* to reach in GCE or standard QEMU. Let me just double-check the probe method of the driver. It registers using `module_phy_driver(mtk_socphy_driver);`. Looking at the `mtk_socphy_driver`, the driver uses `PHY_ID_MATCH_EXACT` for `AIROHA_GPHY_ID_AN7581` (0x03a294c1) and `AIROHA_GPHY_ID_AN7583` (0xc0ff0420). This means the kernel needs to create a `phy_device` with a matching `phy_id`. `phy_device` are made by `get_phy_device()`, which reads the PHY ID from the MDIO bus. Without an MDIO bus spitting out those specific IDs, this driver never gets probed. Does syzkaller even *have* a way to inject MDIO reads? No, not a generic one. Even if it did, it'd be a very narrow and specific configuration. Therefore, the driver will never be reached in the standard QEMU setup. I'm setting `WorthFuzzing=false`. Let me just go over the patch again. I see it touches `MAINTAINERS`, `Kconfig`, `Makefile`, and the `airoha-ge-soc.c` file as well as moves existing code around in `mtk-ge-soc.c`, `mtk-ge-soc.h`, `mtk-phy-lib.c`, and `mtk.h`. The changes to `mtk-ge-soc.c` and `mtk-phy-lib.c` are just moving existing functions (`mtk_cal_cycle_wait`, `__mtk_tr_write`, `mt798x_phy_led_blink_set`, etc.) to be shared with the new driver. All these functions, though, are only called by the MediaTek and Airoha PHY drivers, and again, those are hardware-specific. `mtk-phy-lib.c` is used by other MediaTek PHY drivers, but that doesn't change the fact that they all depend on the MediaTek hardware. Okay, the *entire* patch is hardware-specific and can't be reached in QEMU. I will set WorthFuzzing=false. Reasoning: The patch adds a new vendor-specific Ethernet PHY driver for Airoha SoCs and refactors some shared MediaTek PHY library code. This code relies on physical Airoha/MediaTek hardware for probing |
| 10/2 | 2026/07/26 07:44 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific Ethernet PHY driver for Airoha SoCs and refactors shared MediaTek PHY library code. This code requires physical Airoha/MediaTek hardware (or specific MDIO bus emulation) to be probed and executed, which is not available in standard QEMU or virtualized environments. Therefore, it is unreachable during fuzzing.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new vendor-specific Ethernet PHY driver for Airoha SoCs and refactors shared MediaTek PHY library code. This code requires physical Airoha/MediaTek hardware (or specific MDIO bus emulation) to be probed and executed, which is not available in standard QEMU or virtualized environments. Therefore, it is unreachable during fuzzing.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|