diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index 63f75e9591..72504d8de7 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -375,6 +375,23 @@ endef $(eval $(call KernelPackage,phy-smsc)) +define KernelPackage/phy-airoha-en8811h + SUBMENU:=$(NETWORK_DEVICES_MENU) + TITLE:=Airoha EN8811H 2.5G Ethernet PHY + DEPENDS:=+airoha-en8811h-firmware +kmod-libphy @LINUX_6_1 + KCONFIG:=CONFIG_AIR_EN8811H_PHY + FILES:= \ + $(LINUX_DIR)/drivers/net/phy/air_en8811h.ko + AUTOLOAD:=$(call AutoLoad,18,air_en8811h,1) +endef + +define KernelPackage/phy-airoha-en8811h/description + Kernel modules for Airoha EN8811H 2.5G Ethernet PHY +endef + +$(eval $(call KernelPackage,phy-airoha-en8811h)) + + define KernelPackage/phy-aquantia SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Aquantia Ethernet PHYs diff --git a/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch index b213d804aa..673082d840 100644 --- a/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch +++ b/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch @@ -92,7 +92,7 @@ Signed-off-by: Felix Fietkau + comment "MII PHY device drivers" - config AMD_PHY + config AIR_EN8811H_PHY --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -24,6 +24,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ diff --git a/target/linux/generic/pending-6.1/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch b/target/linux/generic/pending-6.1/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch new file mode 100644 index 0000000000..1dfa1366eb --- /dev/null +++ b/target/linux/generic/pending-6.1/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch @@ -0,0 +1,1115 @@ +From patchwork Tue Feb 6 19:47:51 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Eric Woudstra +X-Patchwork-Id: 13547762 +X-Patchwork-Delegate: kuba@kernel.org +From: Eric Woudstra +To: "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Andrew Lunn , + Heiner Kallweit , + Russell King , + Matthias Brugger , + AngeloGioacchino Del Regno , + "Frank Wunderlich" , + Daniel Golle , + Lucien Jheng , + Zhi-Jun You +Cc: netdev@vger.kernel.org, + devicetree@vger.kernel.org, + Eric Woudstra +Subject: [PATCH net-next 2/2] net: phy: air_en8811h: Add the Airoha EN8811H + PHY driver +Date: Tue, 6 Feb 2024 20:47:51 +0100 +Message-ID: <20240206194751.1901802-3-ericwouds@gmail.com> +X-Mailer: git-send-email 2.42.1 +In-Reply-To: <20240206194751.1901802-1-ericwouds@gmail.com> +References: <20240206194751.1901802-1-ericwouds@gmail.com> +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-Patchwork-Delegate: kuba@kernel.org + +* Source originated from airoha's en8811h v1.2.1 driver + * Moved air_en8811h.h to air_en8811h.c + * Removed air_pbus_reg_write() as it writes to another device on mdio-bus + * Load firmware from /lib/firmware/airoha/ instead of /lib/firmware/ + * Added .get_rate_matching() + * Use generic phy_read/write() and phy_read/write_mmd() + * Edited .get_features() to use generic C45 functions + * Edited .config_aneg() and .read_status() to use a mix of generic C22/C45 + * Use led handling functions from mediatek-ge-soc.c + * Simplified led handling by storing led rules + * Cleanup macro definitions + * Cleanup code to pass checkpatch.pl + * General code cleanup + +Changes from original RFC patch: + + * Use the correct order in Kconfig and Makefile + * Change some register naming to correspond with datasheet + * Use phy_driver .read_page() and .write_page() + * Use module_phy_driver() + * Use get_unaligned_le16() instead of macro + * In .config_aneg() and .read_status() use genphy_xxx() C22 + * Use another vendor register to read real speed + * Load firmware only once and store firmware version + * Apply 2.5G LPA work-around (firmware before 24011202) + * Read 2.5G LPA from vendor register (firmware 24011202 and later) + +Changes to be committed: + modified: drivers/net/phy/Kconfig + modified: drivers/net/phy/Makefile + new file: drivers/net/phy/air_en8811h.c + +Signed-off-by: Eric Woudstra +--- + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/air_en8811h.c | 1006 +++++++++++++++++++++++++++++++++ + 3 files changed, 1012 insertions(+) + create mode 100644 drivers/net/phy/air_en8811h.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -69,6 +69,11 @@ config SFP + + comment "MII PHY device drivers" + ++config AIR_EN8811H_PHY ++ tristate "Airoha EN8811H 2.5 Gigabit PHY" ++ help ++ Currently supports the Airoha EN8811H PHY. ++ + config AMD_PHY + tristate "AMD and Altima PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -32,6 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o ++obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o +--- /dev/null ++++ b/drivers/net/phy/air_en8811h.c +@@ -0,0 +1,1006 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Airoha Ethernet PHYs ++ * ++ * Currently supporting the EN8811H. ++ * ++ * Limitations of the EN8811H: ++ * - Only full duplex supported ++ * - Forced speed (AN off) is not supported by hardware (100Mbps) ++ * ++ * Source originated from airoha's en8811h.c and en8811h.h v1.2.1 ++ * ++ * Copyright (C) 2023 Airoha Technology Corp. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define EN8811H_PHY_ID 0x03a2a411 ++ ++#define EN8811H_MD32_DM "airoha/EthMD32.dm.bin" ++#define EN8811H_MD32_DSP "airoha/EthMD32.DSP.bin" ++ ++#define AIR_FW_ADDR_DM 0x00000000 ++#define AIR_FW_ADDR_DSP 0x00100000 ++ ++/* u32 (DWORD) component macros */ ++#define LOWORD(d) ((u16)(u32)(d)) ++#define HIWORD(d) ((u16)(((u32)(d)) >> 16)) ++ ++/* MII Registers */ ++#define AIR_AUX_CTRL_STATUS 0x1d ++#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2) ++#define AIR_AUX_CTRL_STATUS_SPEED_100 0x4 ++#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 ++#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc ++ ++#define AIR_EXT_PAGE_ACCESS 0x1f ++#define AIR_PHY_PAGE_STANDARD 0x0000 ++#define AIR_PHY_PAGE_EXTENDED_4 0x0004 ++ ++/* MII Registers Page 4*/ ++#define AIR_PBUS_MODE 0x10 ++#define AIR_PBUS_MODE_ADDR_FIXED 0x0000 ++#define AIR_PBUS_MODE_ADDR_INCR BIT(15) ++#define AIR_PBUS_WR_ADDR_HIGH 0x11 ++#define AIR_PBUS_WR_ADDR_LOW 0x12 ++#define AIR_PBUS_WR_DATA_HIGH 0x13 ++#define AIR_PBUS_WR_DATA_LOW 0x14 ++#define AIR_PBUS_RD_ADDR_HIGH 0x15 ++#define AIR_PBUS_RD_ADDR_LOW 0x16 ++#define AIR_PBUS_RD_DATA_HIGH 0x17 ++#define AIR_PBUS_RD_DATA_LOW 0x18 ++ ++/* Registers on MDIO_MMD_VEND1 */ ++#define EN8811H_PHY_FW_STATUS 0x8009 ++#define EN8811H_PHY_READY 0x02 ++ ++#define AIR_PHY_HOST_CMD_1 0x800c ++#define AIR_PHY_HOST_CMD_1_MODE1 0x0 ++#define AIR_PHY_HOST_CMD_2 0x800d ++#define AIR_PHY_HOST_CMD_2_MODE1 0x0 ++#define AIR_PHY_HOST_CMD_3 0x800e ++#define AIR_PHY_HOST_CMD_3_MODE1 0x1101 ++#define AIR_PHY_HOST_CMD_3_DOCMD 0x1100 ++#define AIR_PHY_HOST_CMD_4 0x800f ++#define AIR_PHY_HOST_CMD_4_MODE1 0x0002 ++#define AIR_PHY_HOST_CMD_4_INTCLR 0x00e4 ++ ++/* Registers on MDIO_MMD_VEND2 */ ++#define AIR_PHY_LED_BCR 0x021 ++#define AIR_PHY_LED_BCR_MODE_MASK GENMASK(1, 0) ++#define AIR_PHY_LED_BCR_TIME_TEST BIT(2) ++#define AIR_PHY_LED_BCR_CLK_EN BIT(3) ++#define AIR_PHY_LED_BCR_EXT_CTRL BIT(15) ++ ++#define AIR_PHY_LED_DUR_ON 0x022 ++ ++#define AIR_PHY_LED_DUR_BLINK 0x023 ++ ++#define AIR_PHY_LED_ON(i) (0x024 + ((i) * 2)) ++#define AIR_PHY_LED_ON_MASK (GENMASK(6, 0) | BIT(8)) ++#define AIR_PHY_LED_ON_LINK1000 BIT(0) ++#define AIR_PHY_LED_ON_LINK100 BIT(1) ++#define AIR_PHY_LED_ON_LINK10 BIT(2) ++#define AIR_PHY_LED_ON_LINKDOWN BIT(3) ++#define AIR_PHY_LED_ON_FDX BIT(4) /* Full duplex */ ++#define AIR_PHY_LED_ON_HDX BIT(5) /* Half duplex */ ++#define AIR_PHY_LED_ON_FORCE_ON BIT(6) ++#define AIR_PHY_LED_ON_LINK2500 BIT(8) ++#define AIR_PHY_LED_ON_POLARITY BIT(14) ++#define AIR_PHY_LED_ON_ENABLE BIT(15) ++ ++#define AIR_PHY_LED_BLINK(i) (0x025 + ((i) * 2)) ++#define AIR_PHY_LED_BLINK_1000TX BIT(0) ++#define AIR_PHY_LED_BLINK_1000RX BIT(1) ++#define AIR_PHY_LED_BLINK_100TX BIT(2) ++#define AIR_PHY_LED_BLINK_100RX BIT(3) ++#define AIR_PHY_LED_BLINK_10TX BIT(4) ++#define AIR_PHY_LED_BLINK_10RX BIT(5) ++#define AIR_PHY_LED_BLINK_COLLISION BIT(6) ++#define AIR_PHY_LED_BLINK_RX_CRC_ERR BIT(7) ++#define AIR_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) ++#define AIR_PHY_LED_BLINK_FORCE_BLINK BIT(9) ++#define AIR_PHY_LED_BLINK_2500TX BIT(10) ++#define AIR_PHY_LED_BLINK_2500RX BIT(11) ++ ++/* Registers on BUCKPBUS */ ++#define EN8811H_2P5G_LPA 0x3b30 ++#define EN8811H_2P5G_LPA_2P5G BIT(0) ++ ++#define EN8811H_FW_VERSION 0x3b3c ++ ++#define EN8811H_POLARITY 0xca0f8 ++#define EN8811H_POLARITY_TX_NORMAL BIT(0) ++#define EN8811H_POLARITY_RX_REVERSE BIT(1) ++ ++#define EN8811H_GPIO_OUTPUT 0xcf8b8 ++#define EN8811H_GPIO_OUTPUT_345 (BIT(3) | BIT(4) | BIT(5)) ++ ++#define EN8811H_FW_CTRL_1 0x0f0018 ++#define EN8811H_FW_CTRL_1_START 0x0 ++#define EN8811H_FW_CTRL_1_FINISH 0x1 ++#define EN8811H_FW_CTRL_2 0x800000 ++#define EN8811H_FW_CTRL_2_LOADING BIT(11) ++ ++#define EN8811H_LED_COUNT 3 ++ ++/* GPIO5 <-> BASE_T_LED0 ++ * GPIO4 <-> BASE_T_LED1 ++ * GPIO3 <-> BASE_T_LED2 ++ * ++ * Default setup suitable for 2 leds connected: ++ * 100M link up triggers led0, only led0 blinking on traffic ++ * 1000M link up triggers led1, only led1 blinking on traffic ++ * 2500M link up triggers led0 and led1, both blinking on traffic ++ * Also suitable for 1 led connected: ++ * any link up triggers led2 ++ */ ++#define AIR_DEFAULT_TRIGGER_LED0 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_100) | \ ++ BIT(TRIGGER_NETDEV_RX) | \ ++ BIT(TRIGGER_NETDEV_TX)) ++#define AIR_DEFAULT_TRIGGER_LED1 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_1000) | \ ++ BIT(TRIGGER_NETDEV_RX) | \ ++ BIT(TRIGGER_NETDEV_TX)) ++#define AIR_DEFAULT_TRIGGER_LED2 BIT(TRIGGER_NETDEV_LINK) ++ ++struct led { ++ unsigned long rules; ++ unsigned long state; ++}; ++ ++struct en8811h_priv { ++ u32 firmware_version; ++ struct led led[EN8811H_LED_COUNT]; ++}; ++ ++enum { ++ AIR_PHY_LED_STATE_FORCE_ON, ++ AIR_PHY_LED_STATE_FORCE_BLINK, ++}; ++ ++enum { ++ AIR_PHY_LED_DUR_BLINK_32M, ++ AIR_PHY_LED_DUR_BLINK_64M, ++ AIR_PHY_LED_DUR_BLINK_128M, ++ AIR_PHY_LED_DUR_BLINK_256M, ++ AIR_PHY_LED_DUR_BLINK_512M, ++ AIR_PHY_LED_DUR_BLINK_1024M, ++}; ++ ++enum { ++ AIR_LED_DISABLE, ++ AIR_LED_ENABLE, ++}; ++ ++enum { ++ AIR_ACTIVE_LOW, ++ AIR_ACTIVE_HIGH, ++}; ++ ++enum { ++ AIR_LED_MODE_DISABLE, ++ AIR_LED_MODE_USER_DEFINE, ++}; ++ ++#define AIR_PHY_LED_DUR_UNIT 1024 ++#define AIR_PHY_LED_DUR (AIR_PHY_LED_DUR_UNIT << AIR_PHY_LED_DUR_BLINK_64M) ++ ++static const unsigned long en8811h_led_trig = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | ++ BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_LINK_2500) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)); ++ ++static int air_phy_read_page(struct phy_device *phydev) ++{ ++ return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); ++} ++ ++static int air_phy_write_page(struct phy_device *phydev, int page) ++{ ++ return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page); ++} ++ ++static int __air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_HIGH, HIWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_LOW, LOWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_HIGH, HIWORD(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_LOW, LOWORD(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_buckpbus_reg_write(phydev, pbus_address, pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++; ++} ++ ++static int __air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int pbus_data_low, pbus_data_high; ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_RD_ADDR_HIGH, HIWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_RD_ADDR_LOW, LOWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ pbus_data_high = __phy_read(phydev, AIR_PBUS_RD_DATA_HIGH); ++ if (pbus_data_high < 0) ++ return ret; ++ ++ pbus_data_low = __phy_read(phydev, AIR_PBUS_RD_DATA_LOW); ++ if (pbus_data_low < 0) ++ return ret; ++ ++ *pbus_data = (u16)pbus_data_low | ((u32)(u16)pbus_data_high << 16); ++ return 0; ++} ++ ++static int air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int __air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ unsigned int offset; ++ int ret; ++ u16 val; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_INCR); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_HIGH, HIWORD(address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_LOW, LOWORD(address)); ++ if (ret < 0) ++ return ret; ++ ++ for (offset = 0; offset < fw->size; offset += 4) { ++ val = get_unaligned_le16(&fw->data[offset + 2]); ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_HIGH, val); ++ if (ret < 0) ++ return ret; ++ ++ val = get_unaligned_le16(&fw->data[offset]); ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_LOW, val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_write_buf(phydev, address, fw); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int en8811h_load_firmware(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw1, *fw2; ++ u32 pbus_value; ++ int ret; ++ ++ ret = request_firmware_direct(&fw1, EN8811H_MD32_DM, dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = request_firmware_direct(&fw2, EN8811H_MD32_DSP, dev); ++ if (ret < 0) ++ goto en8811h_load_firmware_rel1; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_CTRL_2, &pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ pbus_value |= EN8811H_FW_CTRL_2_LOADING; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_2, pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DM, fw1); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, fw2); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_CTRL_2, &pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ pbus_value &= ~EN8811H_FW_CTRL_2_LOADING; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_2, pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = 0; ++ ++en8811h_load_firmware_out: ++ release_firmware(fw2); ++ ++en8811h_load_firmware_rel1: ++ release_firmware(fw1); ++ ++ if (ret < 0) ++ phydev_err(phydev, "Load firmware failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int en8811h_restart_host(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ return ret; ++ ++ return air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++} ++ ++static int air_hw_led_on_set(struct phy_device *phydev, u8 index, bool on) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (on) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, ++ on ? AIR_PHY_LED_ON_FORCE_ON : 0); ++ ++ return 0; ++} ++ ++static int air_hw_led_blink_set(struct phy_device *phydev, u8 index, ++ bool blinking) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (blinking) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_BLINK(index), ++ blinking ? ++ AIR_PHY_LED_BLINK_FORCE_BLINK : 0); ++ else ++ return 0; ++} ++ ++static int air_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool blinking = false; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { ++ blinking = true; ++ *delay_on = 50; ++ *delay_off = 50; ++ } ++ ++ err = air_hw_led_blink_set(phydev, index, blinking); ++ if (err) ++ return err; ++ ++ /* led-blink set, so switch led-on off */ ++ err = air_hw_led_on_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ /* hw-control is off*/ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_brightness_set(struct phy_device *phydev, u8 index, ++ enum led_brightness value) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* led-on set, so switch led-blink off */ ++ err = air_hw_led_blink_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ err = air_hw_led_on_set(phydev, index, (value != LED_OFF)); ++ if (err) ++ return err; ++ ++ /* hw-control is off */ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ *rules = priv->led[index].rules; ++ ++ return 0; ++}; ++ ++static int air_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u16 on = 0, blink = 0; ++ int ret; ++ ++ priv->led[index].rules = rules; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK10; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_10RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_10TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK100; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_100RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_100TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK1000; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_1000RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_1000TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK2500; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_2500RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_2500TX; ++ } ++ ++ if (on == 0) { ++ if (rules & BIT(TRIGGER_NETDEV_RX)) { ++ blink |= AIR_PHY_LED_BLINK_10RX | ++ AIR_PHY_LED_BLINK_100RX | ++ AIR_PHY_LED_BLINK_1000RX | ++ AIR_PHY_LED_BLINK_2500RX; ++ } ++ if (rules & BIT(TRIGGER_NETDEV_TX)) { ++ blink |= AIR_PHY_LED_BLINK_10TX | ++ AIR_PHY_LED_BLINK_100TX | ++ AIR_PHY_LED_BLINK_1000TX | ++ AIR_PHY_LED_BLINK_2500TX; ++ } ++ } ++ ++ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) ++ on |= AIR_PHY_LED_ON_FDX; ++ ++ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) ++ on |= AIR_PHY_LED_ON_HDX; ++ ++ if (blink || on) { ++ /* switch hw-control on, so led-on and led-blink are off */ ++ clear_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state); ++ clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state); ++ } else { ++ priv->led[index].rules = 0; ++ } ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, on); ++ ++ if (ret < 0) ++ return ret; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BLINK(index), ++ blink); ++}; ++ ++static int air_led_init(struct phy_device *phydev, u8 index, u8 state, u8 pol) ++{ ++ int cl45_data; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ cl45_data = phy_read_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index)); ++ if (cl45_data < 0) ++ return cl45_data; ++ ++ if (state == AIR_LED_ENABLE) ++ cl45_data |= AIR_PHY_LED_ON_ENABLE; ++ else ++ cl45_data &= ~AIR_PHY_LED_ON_ENABLE; ++ ++ if (pol == AIR_ACTIVE_HIGH) ++ cl45_data |= AIR_PHY_LED_ON_POLARITY; ++ else ++ cl45_data &= ~AIR_PHY_LED_ON_POLARITY; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ cl45_data); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int air_leds_init(struct phy_device *phydev, int num, int dur, int mode) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int cl45_data = dur; ++ int ret, i; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK, ++ cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ cl45_data >>= 1; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_ON, ++ cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ cl45_data = phy_read_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR); ++ if (cl45_data < 0) ++ return cl45_data; ++ ++ switch (mode) { ++ case AIR_LED_MODE_DISABLE: ++ cl45_data &= ~AIR_PHY_LED_BCR_EXT_CTRL; ++ cl45_data &= ~AIR_PHY_LED_BCR_MODE_MASK; ++ break; ++ case AIR_LED_MODE_USER_DEFINE: ++ cl45_data |= AIR_PHY_LED_BCR_EXT_CTRL; ++ cl45_data |= AIR_PHY_LED_BCR_CLK_EN; ++ break; ++ default: ++ phydev_err(phydev, "LED mode %d is not supported\n", mode); ++ return -EINVAL; ++ } ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR, cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < num; ++i) { ++ ret = air_led_init(phydev, i, AIR_LED_ENABLE, AIR_ACTIVE_HIGH); ++ if (ret < 0) { ++ phydev_err(phydev, "LED%d init failed: %d\n", i, ret); ++ return ret; ++ } ++ air_led_hw_control_set(phydev, i, priv->led[i].rules); ++ } ++ ++ return 0; ++} ++ ++static int en8811h_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* All combinations of the supported triggers are allowed */ ++ if (rules & ~en8811h_led_trig) ++ return -EOPNOTSUPP; ++ ++ return 0; ++}; ++ ++static int en8811h_probe(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv; ++ ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct en8811h_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->led[0].rules = AIR_DEFAULT_TRIGGER_LED0; ++ priv->led[1].rules = AIR_DEFAULT_TRIGGER_LED1; ++ priv->led[2].rules = AIR_DEFAULT_TRIGGER_LED2; ++ ++ phydev->priv = priv; ++ ++ /* MDIO_DEVS1/2 empty, so set mmds_present bits here */ ++ phydev->c45_ids.mmds_present |= MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; ++ ++ return 0; ++} ++ ++static int en8811h_config_init(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ int ret, pollret, reg_value; ++ u32 pbus_value; ++ ++ if (!priv->firmware_version) ++ ret = en8811h_load_firmware(phydev); ++ else ++ ret = en8811h_restart_host(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Because of mdio-lock, may have to wait for multiple loads */ ++ pollret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ EN8811H_PHY_FW_STATUS, reg_value, ++ reg_value == EN8811H_PHY_READY, ++ 20000, 7500000, true); ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, &pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ if (pollret || !pbus_value) { ++ phydev_err(phydev, "Firmware not ready: 0x%x\n", reg_value); ++ return -ENODEV; ++ } ++ ++ if (!priv->firmware_version) { ++ phydev_info(phydev, "MD32 firmware version: %08x\n", pbus_value); ++ priv->firmware_version = pbus_value; ++ } ++ ++ /* Select mode 1, the only mode supported */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_1, ++ AIR_PHY_HOST_CMD_1_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_2, ++ AIR_PHY_HOST_CMD_2_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_3, ++ AIR_PHY_HOST_CMD_3_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_4, ++ AIR_PHY_HOST_CMD_4_MODE1); ++ if (ret < 0) ++ return ret; ++ ++ /* Serdes polarity */ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_POLARITY, &pbus_value); ++ if (ret < 0) ++ return ret; ++ if (device_property_read_bool(dev, "airoha,pnswap-rx")) ++ pbus_value |= EN8811H_POLARITY_RX_REVERSE; ++ else ++ pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; ++ if (device_property_read_bool(dev, "airoha,pnswap-tx")) ++ pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; ++ else ++ pbus_value |= EN8811H_POLARITY_TX_NORMAL; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_POLARITY, pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, ++ AIR_LED_MODE_USER_DEFINE); ++ if (ret < 0) { ++ phydev_err(phydev, "Failed to initialize leds: %d\n", ret); ++ return ret; ++ } ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_GPIO_OUTPUT, &pbus_value); ++ if (ret < 0) ++ return ret; ++ pbus_value |= EN8811H_GPIO_OUTPUT_345; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_GPIO_OUTPUT, pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int en8811h_get_features(struct phy_device *phydev) ++{ ++ linkmode_set_bit_array(phy_basic_ports_array, ++ ARRAY_SIZE(phy_basic_ports_array), ++ phydev->supported); ++ ++ return genphy_c45_pma_read_abilities(phydev); ++} ++ ++static int en8811h_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ return RATE_MATCH_PAUSE; ++} ++ ++static int en8811h_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ int err, val; ++ ++ val = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ val |= MDIO_AN_10GBT_CTRL_ADV2_5G; ++ err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, val); ++ if (err < 0) ++ return err; ++ if (err > 0) ++ changed = true; ++ ++ return __genphy_config_aneg(phydev, changed); ++} ++ ++static int en8811h_read_status(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u32 pbus_value; ++ int ret, val; ++ ++ ret = genphy_update_link(phydev); ++ if (ret) ++ return ret; ++ ++ phydev->master_slave_get = MASTER_SLAVE_CFG_UNSUPPORTED; ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_read_lpa(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Get link partner 2.5GBASE-T ability from vendor register */ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, &pbus_value); ++ if (ret < 0) ++ return ret; ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ pbus_value & EN8811H_2P5G_LPA_2P5G); ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ if (!phydev->link) ++ return 0; ++ ++ /* Get real speed from vendor register */ ++ val = phy_read(phydev, AIR_AUX_CTRL_STATUS); ++ if (val < 0) ++ return val; ++ switch (val & AIR_AUX_CTRL_STATUS_SPEED_MASK) { ++ case AIR_AUX_CTRL_STATUS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ } ++ ++ /* BUG in PHY firmware: MDIO_AN_10GBT_STAT_LP2_5G does not get set. ++ * Firmware before version 24011202 has no vendor register 2P5G_LPA. ++ * Assume link partner advertised it if connected at 2500Mbps. ++ */ ++ if (priv->firmware_version < 0x24011202) { ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ phydev->speed == SPEED_2500); ++ } ++ ++ /* Only supports full duplex */ ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static int en8811h_clear_intr(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_3, ++ AIR_PHY_HOST_CMD_3_DOCMD); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_4, ++ AIR_PHY_HOST_CMD_4_INTCLR); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static irqreturn_t en8811h_handle_interrupt(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = en8811h_clear_intr(phydev); ++ if (ret < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct phy_driver en8811h_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID), ++ .name = "Airoha EN8811H", ++ .probe = en8811h_probe, ++ .get_features = en8811h_get_features, ++ .config_init = en8811h_config_init, ++ .get_rate_matching = en8811h_get_rate_matching, ++ .config_aneg = en8811h_config_aneg, ++ .read_status = en8811h_read_status, ++ .config_intr = en8811h_clear_intr, ++ .handle_interrupt = en8811h_handle_interrupt, ++ .led_hw_is_supported = en8811h_led_hw_is_supported, ++ .read_page = air_phy_read_page, ++ .write_page = air_phy_write_page, ++ .led_blink_set = air_led_blink_set, ++ .led_brightness_set = air_led_brightness_set, ++ .led_hw_control_set = air_led_hw_control_set, ++ .led_hw_control_get = air_led_hw_control_get, ++} }; ++ ++module_phy_driver(en8811h_driver); ++ ++static struct mdio_device_id __maybe_unused en8811h_tbl[] = { ++ { PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(mdio, en8811h_tbl); ++MODULE_FIRMWARE(EN8811H_MD32_DM); ++MODULE_FIRMWARE(EN8811H_MD32_DSP); ++ ++MODULE_DESCRIPTION("Airoha EN8811H PHY drivers"); ++MODULE_AUTHOR("Airoha"); ++MODULE_AUTHOR("Eric Woudstra "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch index e96abd5170..487990ab77 100644 --- a/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch +++ b/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -379,6 +379,12 @@ config ROCKCHIP_PHY +@@ -384,6 +384,12 @@ config ROCKCHIP_PHY help Currently supports the integrated Ethernet PHY. @@ -15,7 +15,7 @@ help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -94,6 +94,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o +@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 3385edd39d..0bbf9ac773 100644 --- a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -42,7 +42,7 @@ Signed-off-by: David S. Miller L: linux-i2c@vger.kernel.org --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -309,6 +309,18 @@ config MEDIATEK_GE_PHY +@@ -314,6 +314,18 @@ config MEDIATEK_GE_PHY help Supports the MediaTek Gigabit Ethernet PHYs. @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller depends on PTP_1588_CLOCK_OPTIONAL --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -79,6 +79,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o +@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o diff --git a/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch index da316049ac..b4c07a4b1f 100644 --- a/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ b/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -321,6 +321,13 @@ config MEDIATEK_GE_SOC_PHY +@@ -326,6 +326,13 @@ config MEDIATEK_GE_SOC_PHY present in the SoCs efuse and will dynamically calibrate VCM (common-mode voltage) during startup. @@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle depends on PTP_1588_CLOCK_OPTIONAL --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -78,6 +78,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell +@@ -79,6 +79,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o