From 1e3c4492354ae1c7f7842d7ae46dceed0ccdcb45 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 26 Apr 2024 18:04:55 +0200 Subject: [PATCH] mediatek: drop 5.15 eap111 support Signed-off-by: John Crispin --- ...mediatek-add-edgecore-eap111-support.patch | 1759 ----------------- 1 file changed, 1759 deletions(-) delete mode 100644 patches/0060-mediatek-add-edgecore-eap111-support.patch diff --git a/patches/0060-mediatek-add-edgecore-eap111-support.patch b/patches/0060-mediatek-add-edgecore-eap111-support.patch deleted file mode 100644 index adfb7cd2d..000000000 --- a/patches/0060-mediatek-add-edgecore-eap111-support.patch +++ /dev/null @@ -1,1759 +0,0 @@ -From b27819bae1c767f9c2b7b2654ac3cc34bcbc15fd Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 5 Sep 2023 08:58:23 +0200 -Subject: [PATCH] mediatek: add edgecore eap111 support - -Signed-off-by: John Crispin ---- - .../uboot-envtools/files/mediatek_filogic | 1 + - .../mediatek/dts/mt7981a-edgecore-eap111.dts | 194 +++ - .../mediatek/files/drivers/net/phy/en8801sc.c | 1152 +++++++++++++++++ - .../mediatek/files/drivers/net/phy/en8801sc.h | 255 ++++ - .../filogic/base-files/etc/board.d/01_leds | 4 + - .../filogic/base-files/etc/board.d/02_network | 3 + - target/linux/mediatek/filogic/config-5.15 | 1 + - target/linux/mediatek/image/filogic.mk | 18 + - .../mediatek/patches-5.15/999-en8801sc.patch | 28 + - 9 files changed, 1651 insertions(+) - create mode 100644 target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts - create mode 100644 target/linux/mediatek/files/drivers/net/phy/en8801sc.c - create mode 100644 target/linux/mediatek/files/drivers/net/phy/en8801sc.h - create mode 100644 target/linux/mediatek/patches-5.15/999-en8801sc.patch - -diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic -index f13beed526..1e596f3063 100644 ---- a/package/boot/uboot-envtools/files/mediatek_filogic -+++ b/package/boot/uboot-envtools/files/mediatek_filogic -@@ -44,6 +44,7 @@ mercusys,mr90x-v1) - local envdev=/dev/mtd$(find_mtd_index "u-boot-env") - ubootenv_add_uci_config "$envdev" "0x0" "0x20000" "0x20000" "1" - ;; -+edgecore,eap111|\ - netgear,wax220) - ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000" - ;; -diff --git a/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts b/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts -new file mode 100644 -index 0000000000..e22c099b34 ---- /dev/null -+++ b/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts -@@ -0,0 +1,194 @@ -+/dts-v1/; -+ -+#include "mt7981.dtsi" -+ -+/ { -+ model = "EdgeCore EAP111"; -+ compatible = "edgecore,eap111", "mediatek,mt7981"; -+ -+ aliases { -+ led-boot = &led_green; -+ led-failsafe = &led_green; -+ led-running = &led_green; -+ led-upgrade = &led_green; -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ -+ reset { -+ label = "reset"; -+ linux,code = ; -+ gpios = <&pio 1 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led_green: led@0 { -+ label = "green:power"; -+ gpios = <&pio 9 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led_orange: led@1 { -+ label = "orange:wan"; -+ gpios = <&pio 34 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led_blue: led@2 { -+ label = "blue:wlan5g"; -+ gpios = <&pio 35 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&watchdog { -+ status = "okay"; -+}; -+ -+ð { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mdio_pins>; -+ -+ status = "okay"; -+ -+ gmac0: mac@0 { -+ compatible = "mediatek,eth-mac"; -+ reg = <0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&phy0>; -+ nvmem-cells = <&macaddr1>; -+ nvmem-cell-names = "mac-address"; -+ managed = "in-band-status"; -+ }; -+ -+ gmac1: mac@1 { -+ compatible = "mediatek,eth-mac"; -+ reg = <1>; -+ phy-mode = "gmii"; -+ phy-handle = <&int_gbe_phy>; -+ nvmem-cells = <&macaddr2>; -+ nvmem-cell-names = "mac-address"; -+ }; -+}; -+ -+&mdio_bus { -+ reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>; -+ reset-delay-us = <10000>; -+ reset-post-delay-us = <10000>; -+ -+ phy0: ethernet-phy@24 { -+ reg = <24>; -+ //compatible = "ethernet-phy-ieee802.3-c45"; -+ //compatible = "ethernet-phy-ieee802.3-c22"; -+ compatible = "ethernet-phy-id03a2.9471"; -+ phy-mode = "sgmii"; -+ full-duplex; -+ pause; -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_flash_pins>; -+ status = "okay"; -+ -+ spi_nand: flash@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <52000000>; -+ -+ spi-cal-enable; -+ spi-cal-mode = "read-data"; -+ spi-cal-datalen = <7>; -+ spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; -+ spi-cal-addrlen = <5>; -+ spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; -+ -+ spi-tx-buswidth = <4>; -+ spi-rx-buswidth = <4>; -+ mediatek,nmbm; -+ mediatek,bmt-max-ratio = <1>; -+ mediatek,bmt-max-reserved-blocks = <64>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "BL2"; -+ reg = <0x00000 0x0100000>; -+ read-only; -+ }; -+ -+ partition@100000 { -+ label = "u-boot-env"; -+ reg = <0x0100000 0x0080000>; -+ }; -+ -+ factory: partition@180000 { -+ label = "Factory"; -+ reg = <0x180000 0x0200000>; -+ read-only; -+ -+ compatible = "nvmem-cells"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ macaddr: macaddr@a { -+ reg = <0xa 0x6>; -+ }; -+ macaddr1: macaddr@2a { -+ reg = <0x2a 0x6>; -+ }; -+ macaddr2: macaddr@24 { -+ reg = <0x24 0x6>; -+ }; -+ }; -+ -+ partition@380000 { -+ label = "FIP"; -+ reg = <0x380000 0x0200000>; -+ read-only; -+ }; -+ -+ partition@580000 { -+ label = "ubi"; -+ reg = <0x580000 0x4000000>; -+ compatible = "linux,ubi"; -+ }; -+ }; -+ }; -+}; -+ -+&pio { -+ spi0_flash_pins: spi0-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+}; -+ -+&wifi { -+ mediatek,mtd-eeprom = <&factory 0x0>; -+ -+ status = "okay"; -+}; -diff --git a/target/linux/mediatek/files/drivers/net/phy/en8801sc.c b/target/linux/mediatek/files/drivers/net/phy/en8801sc.c -new file mode 100644 -index 0000000000..d88350ffc4 ---- /dev/null -+++ b/target/linux/mediatek/files/drivers/net/phy/en8801sc.c -@@ -0,0 +1,1152 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* FILE NAME: en8801sc.c -+ * PURPOSE: -+ * EN8801SC phy driver for Linux -+ * NOTES: -+ * -+ */ -+ -+/* INCLUDE FILE DECLARATIONS -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE) -+#include -+#include -+#endif -+ -+#include "en8801sc.h" -+ -+MODULE_DESCRIPTION("Airoha EN8801S PHY drivers for MediaTek SoC"); -+MODULE_AUTHOR("Airoha"); -+MODULE_LICENSE("GPL"); -+ -+#define airoha_mdio_lock(bus) mutex_lock(&((bus)->mdio_lock)) -+#define airoha_mdio_unlock(bus) mutex_unlock(&((bus)->mdio_lock)) -+ -+#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) -+#define phydev_mdio_bus(_dev) (_dev->bus) -+#define phydev_phy_addr(_dev) (_dev->addr) -+#define phydev_dev(_dev) (&_dev->dev) -+#define phydev_pbus_addr(dev) ((dev)->addr + 1) -+#else -+#define phydev_mdio_bus(_dev) (_dev->mdio.bus) -+#define phydev_phy_addr(_dev) (_dev->mdio.addr) -+#define phydev_dev(_dev) (&_dev->mdio.dev) -+#define phydev_pbus_addr(dev) ((dev)->mdio.addr + 1) -+#endif -+ -+enum { -+ PHY_STATE_DONE = 0, -+ PHY_STATE_INIT = 1, -+ PHY_STATE_PROCESS = 2, -+ PHY_STATE_FAIL = 3, -+}; -+ -+struct en8801s_priv { -+ bool first_init; -+ u16 count; -+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE) -+ struct gpio_desc *hw_reset; -+#endif -+}; -+ -+/* -+The following led_cfg example is for reference only. -+LED5 1000M/LINK/ACT (GPIO5) <-> BASE_T_LED0, -+LED6 10/100M/LINK/ACT (GPIO9) <-> BASE_T_LED1, -+LED4 100M/LINK/ACT (GPIO8) <-> BASE_T_LED2, -+*/ -+/* User-defined.B */ -+#define AIR_LED_SUPPORT -+#ifdef AIR_LED_SUPPORT -+static const struct AIR_BASE_T_LED_CFG_S led_cfg[4] = { -+/* -+* {LED Enable, GPIO, LED Polarity, LED ON, LED Blink} -+*/ -+ /* BASE-T LED0 */ -+ {LED_ENABLE, 5, AIR_ACTIVE_LOW, -+ BASE_T_LED0_ON_CFG, BASE_T_LED0_BLK_CFG}, -+ /* BASE-T LED1 */ -+ {LED_ENABLE, 9, AIR_ACTIVE_LOW, -+ BASE_T_LED1_ON_CFG, BASE_T_LED1_BLK_CFG}, -+ /* BASE-T LED2 */ -+ {LED_ENABLE, 8, AIR_ACTIVE_LOW, -+ BASE_T_LED2_ON_CFG, BASE_T_LED2_BLK_CFG}, -+ /* BASE-T LED3 */ -+ {LED_DISABLE, 1, AIR_ACTIVE_LOW, -+ BASE_T_LED3_ON_CFG, BASE_T_LED3_BLK_CFG}, -+}; -+static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M; -+#endif -+ -+/* User-defined.E */ -+ -+/************************************************************************ -+* F U N C T I O N S -+************************************************************************/ -+/*static unsigned int airoha_cl22_read(struct mii_bus *ebus, int phy_addr, -+ unsigned int phy_register, unsigned int *read_data) -+{ -+ *read_data = mdiobus_read(ebus, phy_addr, phy_register); -+ return 0; -+} -+ -+static int airoha_cl22_write(struct mii_bus *ebus, int phy_addr, -+ unsigned int phy_register, unsigned int write_data) -+{ -+ int ret = 0; -+ struct device *dev = &ebus->dev; -+ -+ ret = mdiobus_write(ebus, phy_addr, phy_register, write_data); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ -+ return ret; -+} -+*/ -+static int __airoha_cl45_write(struct mii_bus *bus, int port, -+ u32 devad, u32 reg, u16 val) -+{ -+ int ret = 0; -+ struct device *dev = &bus->dev; -+ -+ ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, -+ MMD_OP_MODE_DATA | devad); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, val); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static int __airoha_cl45_read(struct mii_bus *bus, int port, -+ u32 devad, u32 reg, u16 *read_data) -+{ -+ int ret = 0; -+ struct device *dev = &bus->dev; -+ -+ ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, -+ MMD_OP_MODE_DATA | devad); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return ret; -+ } -+ *read_data = __mdiobus_read(bus, port, MII_MMD_ADDR_DATA_REG); -+ -+ return ret; -+} -+ -+static int airoha_cl45_write(struct mii_bus *bus, int port, -+ u32 devad, u32 reg, u16 val) -+{ -+ int ret = 0; -+ -+ airoha_mdio_lock(bus); -+ ret = __airoha_cl45_write(bus, port, devad, reg, val); -+ airoha_mdio_unlock(bus); -+ -+ return ret; -+} -+ -+static int airoha_cl45_read(struct mii_bus *bus, int port, -+ u32 devad, u32 reg, u16 *read_data) -+{ -+ int ret = 0; -+ -+ airoha_mdio_lock(bus); -+ ret = __airoha_cl45_read(bus, port, devad, reg, read_data); -+ airoha_mdio_unlock(bus); -+ -+ return ret; -+} -+ -+static int __airoha_pbus_write(struct mii_bus *ebus, int pbus_id, -+ unsigned long pbus_address, unsigned long pbus_data) -+{ -+ int ret = 0; -+ -+ ret = __mdiobus_write(ebus, pbus_id, 0x1F, -+ (unsigned int)(pbus_address >> 6)); -+ if (ret < 0) -+ return ret; -+ ret = __mdiobus_write(ebus, pbus_id, -+ (unsigned int)((pbus_address >> 2) & 0xf), -+ (unsigned int)(pbus_data & 0xFFFF)); -+ if (ret < 0) -+ return ret; -+ ret = __mdiobus_write(ebus, pbus_id, 0x10, -+ (unsigned int)(pbus_data >> 16)); -+ if (ret < 0) -+ return ret; -+ return ret; -+} -+ -+static unsigned long __airoha_pbus_read(struct mii_bus *ebus, int pbus_id, -+ unsigned long pbus_address) -+{ -+ unsigned long pbus_data; -+ unsigned int pbus_data_low, pbus_data_high; -+ int ret = 0; -+ struct device *dev = &ebus->dev; -+ -+ ret = __mdiobus_write(ebus, pbus_id, 0x1F, -+ (unsigned int)(pbus_address >> 6)); -+ if (ret < 0) { -+ dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret); -+ return INVALID_DATA; -+ } -+ pbus_data_low = __mdiobus_read(ebus, pbus_id, -+ (unsigned int)((pbus_address >> 2) & 0xf)); -+ pbus_data_high = __mdiobus_read(ebus, pbus_id, 0x10); -+ pbus_data = (pbus_data_high << 16) + pbus_data_low; -+ return pbus_data; -+} -+ -+static int airoha_pbus_write(struct mii_bus *ebus, int pbus_id, -+ unsigned long pbus_address, unsigned long pbus_data) -+{ -+ int ret = 0; -+ -+ airoha_mdio_lock(ebus); -+ ret = __airoha_pbus_write(ebus, pbus_id, pbus_address, pbus_data); -+ airoha_mdio_unlock(ebus); -+ -+ return ret; -+} -+ -+static unsigned long airoha_pbus_read(struct mii_bus *ebus, int pbus_id, -+ unsigned long pbus_address) -+{ -+ unsigned long pbus_data; -+ -+ airoha_mdio_lock(ebus); -+ pbus_data = __airoha_pbus_read(ebus, pbus_id, pbus_address); -+ airoha_mdio_unlock(ebus); -+ -+ return pbus_data; -+} -+ -+/* Airoha Token Ring Write function */ -+static int airoha_tr_reg_write(struct phy_device *phydev, -+ unsigned long tr_address, unsigned long tr_data) -+{ -+ int ret = 0; -+ int phy_addr = phydev_phy_addr(phydev); -+ struct mii_bus *ebus = phydev_mdio_bus(phydev); -+ -+ airoha_mdio_lock(ebus); -+ ret = __mdiobus_write(ebus, phy_addr, 0x1F, 0x52b5); /* page select */ -+ ret = __mdiobus_write(ebus, phy_addr, 0x11, -+ (unsigned int)(tr_data & 0xffff)); -+ ret = __mdiobus_write(ebus, phy_addr, 0x12, -+ (unsigned int)(tr_data >> 16)); -+ ret = __mdiobus_write(ebus, phy_addr, 0x10, -+ (unsigned int)(tr_address | TrReg_WR)); -+ ret = __mdiobus_write(ebus, phy_addr, 0x1F, 0x0); /* page resetore */ -+ airoha_mdio_unlock(ebus); -+ -+ return ret; -+} -+ -+#ifdef AIR_LED_SUPPORT -+static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity, -+ int polar, u16 on_evt, u16 blk_evt) -+{ -+ int ret = 0; -+ int phy_addr = phydev_phy_addr(phydev); -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ -+ if (polar == AIR_ACTIVE_HIGH) -+ on_evt |= LED_ON_POL; -+ else -+ on_evt &= ~LED_ON_POL; -+ -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1f, -+ LED_ON_CTRL(entity), on_evt | LED_ON_EN); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1f, -+ LED_BLK_CTRL(entity), blk_evt); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int airoha_led_set_mode(struct phy_device *phydev, u8 mode) -+{ -+ u16 cl45_data; -+ int err = 0; -+ int phy_addr = phydev_phy_addr(phydev); -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ -+ err = airoha_cl45_read(mbus, phy_addr, 0x1f, LED_BCR, &cl45_data); -+ if (err < 0) -+ return err; -+ -+ switch (mode) { -+ case AIR_LED_MODE_DISABLE: -+ cl45_data &= ~LED_BCR_EXT_CTRL; -+ cl45_data &= ~LED_BCR_MODE_MASK; -+ cl45_data |= LED_BCR_MODE_DISABLE; -+ break; -+ case AIR_LED_MODE_USER_DEFINE: -+ cl45_data |= LED_BCR_EXT_CTRL; -+ cl45_data |= LED_BCR_CLK_EN; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ err = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_BCR, cl45_data); -+ if (err < 0) -+ return err; -+ return 0; -+} -+ -+static int airoha_led_set_state(struct phy_device *phydev, u8 entity, u8 state) -+{ -+ u16 cl45_data; -+ int err; -+ int phy_addr = phydev_phy_addr(phydev); -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ -+ err = airoha_cl45_read(mbus, phy_addr, 0x1f, -+ LED_ON_CTRL(entity), &cl45_data); -+ if (err < 0) -+ return err; -+ if (state == LED_ENABLE) -+ cl45_data |= LED_ON_EN; -+ else -+ cl45_data &= ~LED_ON_EN; -+ -+ err = airoha_cl45_write(mbus, phy_addr, 0x1f, -+ LED_ON_CTRL(entity), cl45_data); -+ if (err < 0) -+ return err; -+ return 0; -+} -+ -+static int en8801s_led_init(struct phy_device *phydev) -+{ -+ -+ unsigned long led_gpio = 0, reg_value = 0; -+ int ret = 0, led_id; -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ int gpio_led_rg[3] = {0x1870, 0x1874, 0x1878}; -+ u16 cl45_data = led_dur; -+ struct device *dev = phydev_dev(phydev); -+ int phy_addr = phydev_phy_addr(phydev); -+ int pbus_addr = phydev_pbus_addr(phydev); -+ -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_BLK_DUR, cl45_data); -+ if (ret < 0) -+ return ret; -+ cl45_data >>= 1; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_ON_DUR, cl45_data); -+ if (ret < 0) -+ return ret; -+ ret = airoha_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE); -+ if (ret != 0) { -+ dev_err(dev, "LED fail to set mode, ret %d !\n", ret); -+ return ret; -+ } -+ for (led_id = 0; led_id < EN8801S_LED_COUNT; led_id++) { -+ reg_value = 0; -+ ret = airoha_led_set_state(phydev, led_id, led_cfg[led_id].en); -+ if (ret != 0) { -+ dev_err(dev, "LED fail to set state, ret %d !\n", ret); -+ return ret; -+ } -+ if (led_cfg[led_id].en == LED_ENABLE) { -+ if ((led_cfg[led_id].gpio < 0) -+ || led_cfg[led_id].gpio > 9) { -+ dev_err(dev, "GPIO%d is out of range!! GPIO number is 0~9.\n", -+ led_cfg[led_id].gpio); -+ return -EIO; -+ } -+ led_gpio |= BIT(led_cfg[led_id].gpio); -+ reg_value = airoha_pbus_read(mbus, pbus_addr, -+ gpio_led_rg[led_cfg[led_id].gpio / 4]); -+ LED_SET_GPIO_SEL(led_cfg[led_id].gpio, -+ led_id, reg_value); -+ dev_dbg(dev, "[Airoha] gpio%d, reg_value 0x%lx\n", -+ led_cfg[led_id].gpio, reg_value); -+ ret = airoha_pbus_write(mbus, pbus_addr, -+ gpio_led_rg[led_cfg[led_id].gpio / 4], -+ reg_value); -+ if (ret < 0) -+ return ret; -+ ret = airoha_led_set_usr_def(phydev, led_id, -+ led_cfg[led_id].pol, -+ led_cfg[led_id].on_cfg, -+ led_cfg[led_id].blk_cfg); -+ if (ret != 0) { -+ dev_err(dev, "LED fail to set usr def, ret %d !\n", -+ ret); -+ return ret; -+ } -+ } -+ } -+ reg_value = (airoha_pbus_read(mbus, pbus_addr, 0x1880) & ~led_gpio); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1880, reg_value); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x186c, led_gpio); -+ if (ret < 0) -+ return ret; -+ dev_info(dev, "LED initialize OK !\n"); -+ return 0; -+} -+#endif -+static int en8801s_phy_process(struct phy_device *phydev) -+{ -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ unsigned long reg_value = 0; -+ int ret = 0; -+ int pbus_addr = phydev_pbus_addr(phydev); -+ -+ reg_value = airoha_pbus_read(mbus, pbus_addr, 0x19e0); -+ reg_value |= BIT(0); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, reg_value); -+ if (ret < 0) -+ return ret; -+ reg_value = airoha_pbus_read(mbus, pbus_addr, 0x19e0); -+ reg_value &= ~BIT(0); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, reg_value); -+ if (ret < 0) -+ return ret; -+ return ret; -+} -+ -+static int en8801s_phase1_init(struct phy_device *phydev) -+{ -+ unsigned long pbus_data; -+ int pbusAddress = EN8801S_PBUS_DEFAULT_ID; -+ u16 reg_value; -+ int retry, ret = 0; -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ struct device *dev = phydev_dev(phydev); -+ struct en8801s_priv *priv = phydev->priv; -+ -+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE) -+ /* Deassert the reset signal */ -+ if (priv->hw_reset) -+ gpiod_set_value(priv->hw_reset, 0); -+#endif -+ priv->count = 1; -+ msleep(1000); -+ -+ retry = MAX_OUI_CHECK; -+ while (1) { -+ pbus_data = airoha_pbus_read(mbus, pbusAddress, -+ EN8801S_RG_ETHER_PHY_OUI); /* PHY OUI */ -+ if (pbus_data == EN8801S_PBUS_OUI) { -+ dev_info(dev, "PBUS addr 0x%x: Start initialized.\n", -+ pbusAddress); -+ break; -+ } -+ pbusAddress = phydev_pbus_addr(phydev); -+ if (0 == --retry) { -+ dev_err(dev, "Probe fail !\n"); -+ return 0; -+ } -+ } -+ -+ ret = airoha_pbus_write(mbus, pbusAddress, EN8801S_RG_BUCK_CTL, 0x03); -+ if (ret < 0) -+ return ret; -+ mdelay(10); -+ pbus_data = (airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_LTR_CTL) -+ & 0xfffffffc) | BIT(2); -+ ret = airoha_pbus_write(mbus, pbusAddress, -+ EN8801S_RG_LTR_CTL, pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(500); -+ pbus_data = (pbus_data & ~BIT(2)) | -+ EN8801S_RX_POLARITY_NORMAL | -+ EN8801S_TX_POLARITY_NORMAL; -+ ret = airoha_pbus_write(mbus, pbusAddress, -+ EN8801S_RG_LTR_CTL, pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(500); -+ -+ pbus_data = airoha_pbus_read(mbus, pbusAddress, -+ EN8801S_RG_SMI_ADDR); /* SMI ADDR */ -+ pbus_data = (pbus_data & 0xffff0000) | -+ (unsigned long)(phydev_pbus_addr(phydev) << 8) | -+ (unsigned long)(phydev_phy_addr(phydev)); -+ dev_info(phydev_dev(phydev), "SMI_ADDR=%lx (renew)\n", pbus_data); -+ ret = airoha_pbus_write(mbus, pbusAddress, -+ EN8801S_RG_SMI_ADDR, pbus_data); -+ mdelay(10); -+ -+ retry = MAX_RETRY; -+ while (1) { -+ mdelay(10); -+ reg_value = phy_read(phydev, MII_PHYSID2); -+ if (reg_value == EN8801S_PHY_ID2) -+ break; /* wait GPHY ready */ -+ -+ retry--; -+ if (retry == 0) { -+ dev_err(dev, "Initialize fail !\n"); -+ return 0; -+ } -+ } -+ /* Software Reset PHY */ -+ reg_value = phy_read(phydev, MII_BMCR); -+ reg_value |= BMCR_RESET; -+ ret = phy_write(phydev, MII_BMCR, reg_value); -+ if (ret < 0) -+ return ret; -+ retry = MAX_RETRY; -+ do { -+ mdelay(10); -+ reg_value = phy_read(phydev, MII_BMCR); -+ retry--; -+ if (retry == 0) { -+ dev_err(dev, "Reset fail !\n"); -+ return 0; -+ } -+ } while (reg_value & BMCR_RESET); -+ -+ phydev->dev_flags = PHY_STATE_INIT; -+ -+ dev_info(dev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION); -+ -+ return 0; -+} -+ -+static int en8801s_phase2_init(struct phy_device *phydev) -+{ -+ union gephy_all_REG_LpiReg1Ch GPHY_RG_LPI_1C; -+ union gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324; -+ union gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012; -+ union gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017; -+ unsigned long pbus_data; -+ int phy_addr = phydev_phy_addr(phydev); -+ int pbus_addr = phydev_pbus_addr(phydev); -+ u16 cl45_value; -+ int retry, ret = 0; -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ struct device *dev = phydev_dev(phydev); -+ struct en8801s_priv *priv = phydev->priv; -+ -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1690); -+ pbus_data |= BIT(31); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1690, pbus_data); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD801); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0, 0x9140); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x0003); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00); -+ if (ret < 0) -+ return ret; -+ /* Set FCM control */ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x004b); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x142c, 0x05050505); -+ if (ret < 0) -+ return ret; -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1440); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1440, pbus_data & ~BIT(11)); -+ if (ret < 0) -+ return ret; -+ -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1408); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1408, pbus_data | BIT(5)); -+ if (ret < 0) -+ return ret; -+ -+ /* Set GPHY Perfomance*/ -+ /* Token Ring */ -+ ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_15h, 0x0055A0); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_17h, 0x07FF3F); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_PMA_00h, 0x00001E); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_PMA_01h, 0x6FB90A); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_PMA_17h, 0x060671); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_PMA_18h, 0x0E2F00); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_TR_26h, 0x444444); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_03h, 0x000000); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_06h, 0x2EBAEF); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_08h, 0x00000B); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Ch, 0x00504D); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Dh, 0x02314F); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Fh, 0x003028); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_10h, 0x005010); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_11h, 0x040001); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_13h, 0x018670); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_14h, 0x00024A); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Bh, 0x000072); -+ if (ret < 0) -+ return ret; -+ ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Ch, 0x003210); -+ if (ret < 0) -+ return ret; -+ -+ /* CL22 & CL45 */ -+ ret = phy_write(phydev, 0x1f, 0x03); -+ if (ret < 0) -+ return ret; -+ GPHY_RG_LPI_1C.DATA = phy_read(phydev, RgAddr_LPI_1Ch); -+ GPHY_RG_LPI_1C.DataBitField.smi_deton_th = 0x0C; -+ ret = phy_write(phydev, RgAddr_LPI_1Ch, GPHY_RG_LPI_1C.DATA); -+ if (ret < 0) -+ return ret; -+ ret = phy_write(phydev, RgAddr_LPI_1Ch, 0xC92); -+ if (ret < 0) -+ return ret; -+ ret = phy_write(phydev, RgAddr_AUXILIARY_1Dh, 0x1); -+ if (ret < 0) -+ return ret; -+ ret = phy_write(phydev, 0x1f, 0x0); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x120, 0x8014); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x122, 0xffff); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x123, 0xffff); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x144, 0x0200); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x14A, 0xEE20); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x189, 0x0110); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x19B, 0x0111); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x234, 0x0181); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x238, 0x0120); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x239, 0x0117); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x268, 0x07F4); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x2D1, 0x0733); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x323, 0x0011); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324, 0x013F); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x326, 0x0037); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x324, &cl45_value); -+ if (ret < 0) -+ return ret; -+ GPHY_RG_1E_324.DATA = cl45_value; -+ GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = 0; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324, -+ GPHY_RG_1E_324.DATA); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x19E, 0xC2); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x013, 0x0); -+ if (ret < 0) -+ return ret; -+ -+ /* EFUSE */ -+ airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40000040); -+ retry = MAX_RETRY; -+ while (retry != 0) { -+ mdelay(1); -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C08); -+ if ((pbus_data & BIT(30)) == 0) -+ break; -+ -+ retry--; -+ } -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C38); /* RAW#2 */ -+ ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x12, &cl45_value); -+ if (ret < 0) -+ return ret; -+ GPHY_RG_1E_012.DATA = cl45_value; -+ GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt = -+ (u16)(pbus_data & 0x03f); -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x12, -+ GPHY_RG_1E_012.DATA); -+ if (ret < 0) -+ return ret; -+ ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x17, &cl45_value); -+ if (ret < 0) -+ return ret; -+ GPHY_RG_1E_017.DATA = cl45_value; -+ GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt = -+ (u16)((pbus_data >> 8) & 0x03f); -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x17, -+ GPHY_RG_1E_017.DATA); -+ if (ret < 0) -+ return ret; -+ -+ airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40400040); -+ retry = MAX_RETRY; -+ while (retry != 0) { -+ mdelay(1); -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C08); -+ if ((pbus_data & BIT(30)) == 0) -+ break; -+ -+ retry--; -+ } -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C30); /* RAW#16 */ -+ GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = -+ (u16)((pbus_data >> 12) & 0x01); -+ ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324, -+ GPHY_RG_1E_324.DATA); -+ if (ret < 0) -+ return ret; -+#ifdef AIR_LED_SUPPORT -+ ret = en8801s_led_init(phydev); -+ if (ret != 0) -+ dev_err(dev, "en8801s_led_init fail (ret:%d) !\n", ret); -+#endif -+ -+ ret = airoha_cl45_read(mbus, phy_addr, MDIO_MMD_AN, -+ MDIO_AN_EEE_ADV, &cl45_value); -+ if (ret < 0) -+ return ret; -+ if (cl45_value == 0) { -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1960); -+ if (0xA == ((pbus_data & 0x07c00000) >> 22)) { -+ pbus_data = (pbus_data & 0xf83fffff) | (0xC << 22); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(10); -+ pbus_data = (pbus_data & 0xf83fffff) | (0xE << 22); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(10); -+ } -+ } else { -+ pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1960); -+ if (0xE == ((pbus_data & 0x07c00000) >> 22)) { -+ pbus_data = (pbus_data & 0xf83fffff) | (0xC << 22); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(10); -+ pbus_data = (pbus_data & 0xf83fffff) | (0xA << 22); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ if (ret < 0) -+ return ret; -+ mdelay(10); -+ } -+ } -+ -+ priv->first_init = false; -+ dev_info(phydev_dev(phydev), "Phase2 initialize OK !\n"); -+ return 0; -+} -+ -+static int en8801s_read_status(struct phy_device *phydev) -+{ -+ int ret = 0, preSpeed = phydev->speed; -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ u32 reg_value; -+ struct device *dev = phydev_dev(phydev); -+ int pbus_addr = phydev_pbus_addr(phydev); -+ struct en8801s_priv *priv = phydev->priv; -+ -+ ret = genphy_read_status(phydev); -+ if (phydev->link == LINK_DOWN) -+ preSpeed = phydev->speed = 0; -+ -+ if (phydev->dev_flags == PHY_STATE_PROCESS) { -+ en8801s_phy_process(phydev); -+ phydev->dev_flags = PHY_STATE_DONE; -+ } -+ -+ if (phydev->dev_flags == PHY_STATE_INIT) { -+ dev_dbg(dev, "phydev->link %d, count %d\n", -+ phydev->link, priv->count); -+ if ((phydev->link) || (priv->count == 5)) { -+ ret = en8801s_phase2_init(phydev); -+ if (ret != 0) { -+ dev_info(dev, "en8801_phase2_init failed\n"); -+ phydev->dev_flags = PHY_STATE_FAIL; -+ return 0; -+ } -+ phydev->dev_flags = PHY_STATE_PROCESS; -+ } -+ priv->count++; -+ } -+ -+ if ((preSpeed != phydev->speed) && (phydev->link == LINK_UP)) { -+ preSpeed = phydev->speed; -+ -+ if (preSpeed == SPEED_10) { -+ reg_value = airoha_pbus_read(mbus, pbus_addr, 0x1694); -+ reg_value |= BIT(31); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1694, -+ reg_value); -+ if (ret < 0) -+ return ret; -+ phydev->dev_flags = PHY_STATE_PROCESS; -+ } else { -+ reg_value = airoha_pbus_read(mbus, pbus_addr, 0x1694); -+ reg_value &= ~BIT(31); -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1694, -+ reg_value); -+ if (ret < 0) -+ return ret; -+ phydev->dev_flags = PHY_STATE_PROCESS; -+ } -+ -+ airoha_pbus_write(mbus, pbus_addr, 0x0600, -+ 0x0c000c00); -+ if (preSpeed == SPEED_1000) { -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x10, -+ 0xD801); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0, -+ 0x9140); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, -+ 0x0003); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, -+ 0x0c000c00); -+ if (ret < 0) -+ return ret; -+ mdelay(2); /* delay 2 ms */ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, -+ 0x004b); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, -+ 0x0007); -+ if (ret < 0) -+ return ret; -+ } else if (preSpeed == SPEED_100) { -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x10, -+ 0xD401); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0, -+ 0x9140); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, -+ 0x0007); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, -+ 0x0c11); -+ if (ret < 0) -+ return ret; -+ mdelay(2); /* delay 2 ms */ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, -+ 0x0027); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, -+ 0x0007); -+ if (ret < 0) -+ return ret; -+ } else if (preSpeed == SPEED_10) { -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x10, -+ 0xD001); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0, -+ 0x9140); -+ if (ret < 0) -+ return ret; -+ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, -+ 0x000b); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, -+ 0x0c11); -+ if (ret < 0) -+ return ret; -+ mdelay(2); /* delay 2 ms */ -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, -+ 0x0027); -+ if (ret < 0) -+ return ret; -+ ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, -+ 0x0007); -+ if (ret < 0) -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static int en8801s_probe(struct phy_device *phydev) -+{ -+ struct en8801s_priv *priv; -+ unsigned long phy_addr = phydev_phy_addr(phydev); -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ struct device *dev = &mbus->dev; -+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE) -+ struct gpio_desc *en8801s_reset; -+ int err = 0; -+#else -+ struct mdio_device *mdiodev = &phydev->mdio; -+#endif -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->count = 0; -+ priv->first_init = true; -+ -+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE) -+ /* Assert the optional reset signal */ -+ en8801s_reset = gpiod_get_optional(&phydev->dev, -+ "reset", GPIOD_OUT_HIGH); -+ err = PTR_ERR_OR_ZERO(en8801s_reset); -+ if (err) { -+ dev_dbg(phydev_dev(phydev), -+ "PHY %lx have no reset pin in device tree.\n", -+ phy_addr); -+ } else { -+ dev_dbg(phydev_dev(phydev), -+ "Assert PHY %lx HWRST until config_init\n", -+ phy_addr); -+ priv->hw_reset = en8801s_reset; -+ } -+ -+#else -+ if (mdiodev->reset_gpio) { -+ dev_dbg(phydev_dev(phydev), -+ "Assert PHY %lx HWRST until phy_init_hw\n", -+ phy_addr); -+ phy_device_reset(phydev, 1); -+ } -+#endif -+ -+ phydev->priv = priv; -+ -+ return 0; -+} -+ -+#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE) -+static int airoha_mmd_read(struct phy_device *phydev, -+ int devad, u16 reg) -+{ -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ int phy_addr = phydev_phy_addr(phydev); -+ int ret = 0; -+ u16 cl45_value; -+ -+ ret = __airoha_cl45_read(mbus, phy_addr, devad, reg, &cl45_value); -+ if (ret < 0) -+ return ret; -+ -+ return cl45_value; -+} -+ -+static int airoha_mmd_write(struct phy_device *phydev, -+ int devad, u16 reg, u16 val) -+{ -+ struct mii_bus *mbus = phydev_mdio_bus(phydev); -+ int phy_addr = phydev_phy_addr(phydev); -+ int pbus_addr = phydev_pbus_addr(phydev); -+ unsigned long pbus_data; -+ int ret = 0; -+ -+ if (MDIO_MMD_AN == devad && MDIO_AN_EEE_ADV == reg) { -+ if (val == 0) { -+ pbus_data = __airoha_pbus_read(mbus, pbus_addr, 0x1960); -+ if (0xA == ((pbus_data & 0x07c00000) >> 22)) { -+ pbus_data = (pbus_data & 0xf83fffff) | -+ (0xC << 22); -+ __airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ mdelay(10); -+ pbus_data = (pbus_data & 0xf83fffff) | -+ (0xE << 22); -+ __airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ mdelay(10); -+ } -+ } else { -+ pbus_data = __airoha_pbus_read(mbus, pbus_addr, 0x1960); -+ if (0xE == ((pbus_data & 0x07c00000) >> 22)) { -+ pbus_data = (pbus_data & 0xf83fffff) | -+ (0xC << 22); -+ __airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ mdelay(10); -+ pbus_data = (pbus_data & 0xf83fffff) | -+ (0xA << 22); -+ __airoha_pbus_write(mbus, pbus_addr, 0x1960, -+ pbus_data); -+ mdelay(10); -+ } -+ } -+ } -+ -+ ret = __airoha_cl45_write(mbus, phy_addr, devad, reg, val); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+#endif -+ -+static struct phy_driver Airoha_driver[] = { -+ { -+ .phy_id = EN8801SC_PHY_ID, -+ .name = "Airoha EN8801SC", -+ .phy_id_mask = 0x0ffffff0, -+ .features = PHY_GBIT_FEATURES, -+ .probe = en8801s_probe, -+ .config_init = en8801s_phase1_init, -+ .config_aneg = genphy_config_aneg, -+ .read_status = en8801s_read_status, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE) -+ .read_mmd = airoha_mmd_read, -+ .write_mmd = airoha_mmd_write, -+#endif -+ } -+}; -+ -+module_phy_driver(Airoha_driver); -+ -+static struct mdio_device_id __maybe_unused Airoha_tbl[] = { -+ { EN8801SC_PHY_ID, 0x0ffffff0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(mdio, Airoha_tbl); -diff --git a/target/linux/mediatek/files/drivers/net/phy/en8801sc.h b/target/linux/mediatek/files/drivers/net/phy/en8801sc.h -new file mode 100644 -index 0000000000..0a077c34ab ---- /dev/null -+++ b/target/linux/mediatek/files/drivers/net/phy/en8801sc.h -@@ -0,0 +1,255 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* FILE NAME: en8801sc.h -+ * PURPOSE: -+ * Define EN8801SC driver function -+ * -+ * NOTES: -+ * -+ */ -+ -+#ifndef __EN8801SC_H -+#define __EN8801SC_H -+ -+/* NAMING DECLARATIONS -+ */ -+#define EN8801S_DRIVER_VERSION "1.1.7_Generic" -+#define EN8801S_PBUS_DEFAULT_ID 0x1e -+#define EN8801S_RG_ETHER_PHY_OUI 0x19a4 -+#define EN8801S_RG_SMI_ADDR 0x19a8 -+#define EN8801S_RG_BUCK_CTL 0x1a20 -+#define EN8801S_RG_LTR_CTL 0x0cf8 -+ -+#define EN8801S_PBUS_OUI 0x17a5 -+#define EN8801S_PHY_ID1 0x03a2 -+#define EN8801S_PHY_ID2 0x9461 -+#define EN8801SC_PHY_ID 0x03a29471 -+ -+#define LED_ON_CTRL(i) (0x024 + ((i)*2)) -+#define LED_ON_EN (1 << 15) -+#define LED_ON_POL (1 << 14) -+#define LED_ON_EVT_MASK (0x7f) -+/* LED ON Event Option.B */ -+#define LED_ON_EVT_FORCE (1 << 6) -+#define LED_ON_EVT_LINK_DOWN (1 << 3) -+#define LED_ON_EVT_LINK_10M (1 << 2) -+#define LED_ON_EVT_LINK_100M (1 << 1) -+#define LED_ON_EVT_LINK_1000M (1 << 0) -+/* LED ON Event Option.E */ -+ -+#define LED_BLK_CTRL(i) (0x025 + ((i)*2)) -+#define LED_BLK_EVT_MASK (0x3ff) -+/* LED Blinking Event Option.B*/ -+#define LED_BLK_EVT_FORCE (1 << 9) -+#define LED_BLK_EVT_10M_RX_ACT (1 << 5) -+#define LED_BLK_EVT_10M_TX_ACT (1 << 4) -+#define LED_BLK_EVT_100M_RX_ACT (1 << 3) -+#define LED_BLK_EVT_100M_TX_ACT (1 << 2) -+#define LED_BLK_EVT_1000M_RX_ACT (1 << 1) -+#define LED_BLK_EVT_1000M_TX_ACT (1 << 0) -+/* LED Blinking Event Option.E*/ -+#define LED_ENABLE 1 -+#define LED_DISABLE 0 -+ -+#define LINK_UP 1 -+#define LINK_DOWN 0 -+ -+/* -+SFP Sample for verification -+Tx Reverse, Rx Reverse -+*/ -+#define EN8801S_TX_POLARITY_NORMAL 0x0 -+#define EN8801S_TX_POLARITY_REVERSE 0x1 -+ -+#define EN8801S_RX_POLARITY_NORMAL (0x1 << 1) -+#define EN8801S_RX_POLARITY_REVERSE (0x0 << 1) -+ -+/* -+The following led_cfg example is for reference only. -+LED5 1000M/LINK/ACT (GPIO5) <-> BASE_T_LED0, -+LED6 10/100M/LINK/ACT(GPIO9) <-> BASE_T_LED1, -+LED4 100M/LINK/ACT (GPIO8) <-> BASE_T_LED2, -+*/ -+/* User-defined.B */ -+#define BASE_T_LED0_ON_CFG (LED_ON_EVT_LINK_1000M) -+#define BASE_T_LED0_BLK_CFG \ -+ (LED_BLK_EVT_1000M_TX_ACT | \ -+ LED_BLK_EVT_1000M_RX_ACT) -+#define BASE_T_LED1_ON_CFG \ -+ (LED_ON_EVT_LINK_100M | \ -+ LED_ON_EVT_LINK_10M) -+#define BASE_T_LED1_BLK_CFG \ -+ (LED_BLK_EVT_100M_TX_ACT | \ -+ LED_BLK_EVT_100M_RX_ACT | \ -+ LED_BLK_EVT_10M_TX_ACT | \ -+ LED_BLK_EVT_10M_RX_ACT) -+#define BASE_T_LED2_ON_CFG \ -+ (LED_ON_EVT_LINK_100M) -+#define BASE_T_LED2_BLK_CFG \ -+ (LED_BLK_EVT_100M_TX_ACT | \ -+ LED_BLK_EVT_100M_RX_ACT) -+#define BASE_T_LED3_ON_CFG (0x0) -+#define BASE_T_LED3_BLK_CFG (0x0) -+/* User-defined.E */ -+ -+#define EN8801S_LED_COUNT 4 -+ -+#define MAX_RETRY 5 -+#define MAX_OUI_CHECK 2 -+/* CL45 MDIO control */ -+#define MII_MMD_ACC_CTL_REG 0x0d -+#define MII_MMD_ADDR_DATA_REG 0x0e -+#define MMD_OP_MODE_DATA BIT(14) -+ -+#define MAX_TRG_COUNTER 5 -+ -+/* CL22 Reg Support Page Select */ -+#define RgAddr_Reg1Fh 0x1f -+#define CL22_Page_Reg 0x0000 -+#define CL22_Page_ExtReg 0x0001 -+#define CL22_Page_MiscReg 0x0002 -+#define CL22_Page_LpiReg 0x0003 -+#define CL22_Page_tReg 0x02A3 -+#define CL22_Page_TrReg 0x52B5 -+ -+/* CL45 Reg Support DEVID */ -+#define DEVID_03 0x03 -+#define DEVID_07 0x07 -+#define DEVID_1E 0x1E -+#define DEVID_1F 0x1F -+ -+/* TokenRing Reg Access */ -+#define TrReg_PKT_XMT_STA 0x8000 -+#define TrReg_WR 0x8000 -+#define TrReg_RD 0xA000 -+ -+#define RgAddr_LPI_1Ch 0x1c -+#define RgAddr_AUXILIARY_1Dh 0x1d -+#define RgAddr_PMA_00h 0x0f80 -+#define RgAddr_PMA_01h 0x0f82 -+#define RgAddr_PMA_17h 0x0fae -+#define RgAddr_PMA_18h 0x0fb0 -+#define RgAddr_DSPF_03h 0x1686 -+#define RgAddr_DSPF_06h 0x168c -+#define RgAddr_DSPF_08h 0x1690 -+#define RgAddr_DSPF_0Ch 0x1698 -+#define RgAddr_DSPF_0Dh 0x169a -+#define RgAddr_DSPF_0Fh 0x169e -+#define RgAddr_DSPF_10h 0x16a0 -+#define RgAddr_DSPF_11h 0x16a2 -+#define RgAddr_DSPF_13h 0x16a6 -+#define RgAddr_DSPF_14h 0x16a8 -+#define RgAddr_DSPF_1Bh 0x16b6 -+#define RgAddr_DSPF_1Ch 0x16b8 -+#define RgAddr_TR_26h 0x0ecc -+#define RgAddr_R1000DEC_15h 0x03aa -+#define RgAddr_R1000DEC_17h 0x03ae -+ -+#define LED_BCR (0x021) -+#define LED_BCR_EXT_CTRL (1 << 15) -+#define LED_BCR_CLK_EN (1 << 3) -+#define LED_BCR_TIME_TEST (1 << 2) -+#define LED_BCR_MODE_MASK (3) -+#define LED_BCR_MODE_DISABLE (0) -+ -+#define LED_ON_DUR (0x022) -+#define LED_ON_DUR_MASK (0xffff) -+ -+#define LED_BLK_DUR (0x023) -+#define LED_BLK_DUR_MASK (0xffff) -+ -+#define LED_GPIO_SEL_MASK 0x7FFFFFF -+ -+#define UNIT_LED_BLINK_DURATION 1024 -+ -+/* Invalid data */ -+#define INVALID_DATA 0xffffffff -+ -+#define LED_SET_EVT(reg, cod, result, bit) do \ -+ { \ -+ if (reg & cod) { \ -+ result |= bit; \ -+ } \ -+ } while (0) -+ -+#define LED_SET_GPIO_SEL(gpio, led, val) \ -+ (val |= (led << (8 * (gpio % 4)))) \ -+ -+ -+/* DATA TYPE DECLARATIONS -+ */ -+struct AIR_BASE_T_LED_CFG_S { -+ u16 en; -+ u16 gpio; -+ u16 pol; -+ u16 on_cfg; -+ u16 blk_cfg; -+}; -+ -+union gephy_all_REG_LpiReg1Ch { -+ struct { -+ /* b[15:00] */ -+ u16 smi_deton_wt : 3; -+ u16 smi_det_mdi_inv : 1; -+ u16 smi_detoff_wt : 3; -+ u16 smi_sigdet_debouncing_en : 1; -+ u16 smi_deton_th : 6; -+ u16 rsv_14 : 2; -+ } DataBitField; -+ u16 DATA; -+}; -+ -+union gephy_all_REG_dev1Eh_reg324h { -+ struct { -+ /* b[15:00] */ -+ u16 rg_smi_detcnt_max : 6; -+ u16 rsv_6 : 2; -+ u16 rg_smi_det_max_en : 1; -+ u16 smi_det_deglitch_off : 1; -+ u16 rsv_10 : 6; -+ } DataBitField; -+ u16 DATA; -+}; -+ -+union gephy_all_REG_dev1Eh_reg012h { -+ struct { -+ /* b[15:00] */ -+ u16 da_tx_i2mpb_a_tbt : 6; -+ u16 rsv_6 : 4; -+ u16 da_tx_i2mpb_a_gbe : 6; -+ } DataBitField; -+ u16 DATA; -+}; -+ -+union gephy_all_REG_dev1Eh_reg017h { -+ struct { -+ /* b[15:00] */ -+ u16 da_tx_i2mpb_b_tbt : 6; -+ u16 rsv_6 : 2; -+ u16 da_tx_i2mpb_b_gbe : 6; -+ u16 rsv_14 : 2; -+ } DataBitField; -+ u16 DATA; -+}; -+ -+enum { -+ AIR_LED_BLK_DUR_32M, -+ AIR_LED_BLK_DUR_64M, -+ AIR_LED_BLK_DUR_128M, -+ AIR_LED_BLK_DUR_256M, -+ AIR_LED_BLK_DUR_512M, -+ AIR_LED_BLK_DUR_1024M, -+ AIR_LED_BLK_DUR_LAST -+}; -+ -+enum { -+ AIR_ACTIVE_LOW, -+ AIR_ACTIVE_HIGH, -+}; -+ -+enum { -+ AIR_LED_MODE_DISABLE, -+ AIR_LED_MODE_USER_DEFINE, -+ AIR_LED_MODE_LAST -+}; -+ -+#endif /* End of __EN8801SC_H */ -diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds -index ea126bc46f..c2744661a8 100644 ---- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds -+++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds -@@ -9,6 +9,10 @@ case $board in - cudy,wr3000-v1) - ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" - ;; -+edgecore,eap111) -+ ucidef_set_led_netdev "wan" "wan" "orange:wan" "eth1" -+ ucidef_set_led_netdev "wlan5g" "WLAN5G" "blue:wlan5g" "phy1-ap0" -+ ;; - mercusys,mr90x-v1) - ucidef_set_led_netdev "lan0" "lan0" "green:lan0" "lan0" "link tx rx" - ucidef_set_led_netdev "lan1" "lan2" "green:lan1" "lan1" "link tx rx" -diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network -index e5872e7fe4..78364e6787 100644 ---- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network -+++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network -@@ -24,6 +24,9 @@ mediatek_setup_interfaces() - cudy,wr3000-v1) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" - ;; -+ edgecore,eap111) -+ ucidef_set_interfaces_lan_wan eth0 eth1 -+ ;; - glinet,gl-mt3000) - ucidef_set_interfaces_lan_wan eth1 eth0 - ;; -diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 -index 2ffc466b7c..8aca4f15d2 100644 ---- a/target/linux/mediatek/filogic/config-5.15 -+++ b/target/linux/mediatek/filogic/config-5.15 -@@ -1,5 +1,6 @@ - CONFIG_64BIT=y - # CONFIG_AHCI_MTK is not set -+CONFIG_AIROHA_EN8801SC_PHY=y - CONFIG_AQUANTIA_PHY=y - CONFIG_ARCH_DMA_ADDR_T_64BIT=y - CONFIG_ARCH_KEEP_MEMBLOCK=y -diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk -index 846fbcbf2c..5e88492d3d 100644 ---- a/target/linux/mediatek/image/filogic.mk -+++ b/target/linux/mediatek/image/filogic.mk -@@ -191,6 +191,24 @@ define Device/cudy_wr3000-v1 - endef - TARGET_DEVICES += cudy_wr3000-v1 - -+define Device/edgecore_eap111 -+ DEVICE_VENDOR := Edgecore -+ DEVICE_MODEL := eap111 -+ DEVICE_DTS := mt7981a-edgecore-eap111 -+ DEVICE_DTS_DIR := ../dts -+ SUPPORTED_DEVICES += edgecore,eap111 -+ DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware -+ UBINIZE_OPTS := -E 5 -+ BLOCKSIZE := 128k -+ PAGESIZE := 2048 -+ IMAGE_SIZE := 246272k -+ KERNEL_IN_UBI := 1 -+ IMAGES += factory.bin -+ IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) -+ IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata -+endef -+TARGET_DEVICES += edgecore_eap111 -+ - define Device/glinet_gl-mt3000 - DEVICE_VENDOR := GL.iNet - DEVICE_MODEL := GL-MT3000 -diff --git a/target/linux/mediatek/patches-5.15/999-en8801sc.patch b/target/linux/mediatek/patches-5.15/999-en8801sc.patch -new file mode 100644 -index 0000000000..fdfa3ded72 ---- /dev/null -+++ b/target/linux/mediatek/patches-5.15/999-en8801sc.patch -@@ -0,0 +1,28 @@ -+Index: linux-5.15.120/drivers/net/phy/Kconfig -+=================================================================== -+--- linux-5.15.120.orig/drivers/net/phy/Kconfig -++++ linux-5.15.120/drivers/net/phy/Kconfig -+@@ -242,6 +242,11 @@ config DAVICOM_PHY -+ help -+ Currently supports dm9161e and dm9131 -+ -++config AIROHA_EN8801SC_PHY -++ tristate "Drivers for Airoha EN8801S Gigabit PHYs for MediaTek SoC." -++ help -++ Currently supports the Airoha EN8801S PHY for MediaTek SoC. -++ -+ config ICPLUS_PHY -+ tristate "ICPlus PHYs" -+ help -+Index: linux-5.15.120/drivers/net/phy/Makefile -+=================================================================== -+--- linux-5.15.120.orig/drivers/net/phy/Makefile -++++ linux-5.15.120/drivers/net/phy/Makefile -+@@ -71,6 +71,7 @@ obj-$(CONFIG_DP83848_PHY) += dp83848.o -+ obj-$(CONFIG_DP83867_PHY) += dp83867.o -+ obj-$(CONFIG_DP83869_PHY) += dp83869.o -+ obj-$(CONFIG_DP83TC811_PHY) += dp83tc811.o -++obj-$(CONFIG_AIROHA_EN8801SC_PHY) += en8801sc.o -+ obj-$(CONFIG_FIXED_PHY) += fixed_phy.o -+ obj-$(CONFIG_ICPLUS_PHY) += icplus.o -+ obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o --- -2.34.1 -