[][kernel][common][eth][Update Airoha EN8801S driver v1.10]
[Description]
Add Airoha EN8801S Ethernet Phy driver v1.10.
[Release-log]
N/A
Change-Id: I7200202a999a4657d28abc517d6d523657c3dd31
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6333075
diff --git a/target/linux/mediatek/patches-5.4/744-en8801s-gphy-support.patch b/target/linux/mediatek/patches-5.4/744-en8801s-gphy-support.patch
index 23a0333..ae9fe7f 100644
--- a/target/linux/mediatek/patches-5.4/744-en8801s-gphy-support.patch
+++ b/target/linux/mediatek/patches-5.4/744-en8801s-gphy-support.patch
@@ -30,9 +30,9 @@
===================================================================
--- /dev/null
+++ b/drivers/net/phy/en8801s.c
-@@ -0,0 +1,394 @@
+@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: GPL-2.0
-+/* FILE NAME: airoha.c
++/* FILE NAME: en8801s.c
+ * PURPOSE:
+ * EN8801S phy driver for Linux
+ * NOTES:
@@ -60,23 +60,31 @@
+#include <linux/phy.h>
+#include <linux/delay.h>
+
-+//#include <linux/bitfield.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+
+#include "en8801s.h"
+
-+/* #define TEST_BOARD */
-+
+MODULE_DESCRIPTION("Airoha EN8801S PHY drivers");
+MODULE_AUTHOR("Airoha");
+MODULE_LICENSE("GPL");
+
-+static int preSpeed = 0;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
++#define phydev_mdio_bus(dev) ((dev)->bus)
++#else
++#define phydev_mdio_bus(dev) ((dev)->mdio.bus)
++#endif
++
++enum {
++ PHY_STATE_DONE = 0,
++ PHY_STATE_INIT = 1,
++ PHY_STATE_PROCESS = 2,
++};
++
+/************************************************************************
+* F U N C T I O N S
+************************************************************************/
-+unsigned int mdiobus_write45(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u16 val)
++static unsigned int airoha_cl45_write(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u16 val)
+{
+ mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
+ mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
@@ -85,7 +93,7 @@
+ return 0;
+}
+
-+unsigned int mdiobus_read45(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u32 *read_data)
++static unsigned int airoha_cl45_read(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u32 *read_data)
+{
+ mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
+ mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
@@ -94,155 +102,148 @@
+ return 0;
+}
+
-+/* Airoha MII read function */
-+unsigned int ecnt_mii_cl22_read(struct mii_bus *ebus, unsigned int phy_addr,unsigned int phy_register,unsigned int *read_data)
++static unsigned int airoha_cl22_read(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register, unsigned int *read_data)
+{
+ *read_data = mdiobus_read(ebus, phy_addr, phy_register);
+ return 0;
+}
+
-+/* Airoha MII write function */
-+unsigned int ecnt_mii_cl22_write(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register,unsigned int write_data)
++static unsigned int airoha_cl22_write(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register, unsigned int write_data)
+{
+ mdiobus_write(ebus, phy_addr, phy_register, write_data);
+ return 0;
+}
+
-+/* EN8801 PBUS write function */
-+void En8801_PbusRegWr(struct mii_bus *ebus, unsigned long pbus_address, unsigned long pbus_data)
++static void airoha_pbus_write(struct mii_bus *ebus, unsigned long pbus_id, unsigned long pbus_address, unsigned long pbus_data)
+{
-+ ecnt_mii_cl22_write(ebus, EN8801S_PBUS_PHY_ID, 0x1F, (unsigned int)(pbus_address >> 6));
-+ ecnt_mii_cl22_write(ebus, EN8801S_PBUS_PHY_ID, (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
-+ ecnt_mii_cl22_write(ebus, EN8801S_PBUS_PHY_ID, 0x10, (unsigned int)(pbus_data >> 16));
++ airoha_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
++ airoha_cl22_write(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
++ airoha_cl22_write(ebus, pbus_id, 0x10, (unsigned int)(pbus_data >> 16));
+ return;
+}
+
-+/* EN8801 PBUS read function */
-+unsigned long En8801_PbusRegRd(struct mii_bus *ebus, unsigned long pbus_address)
++static unsigned long airoha_pbus_read(struct mii_bus *ebus, unsigned long pbus_id, unsigned long pbus_address)
+{
+ unsigned long pbus_data;
+ unsigned int pbus_data_low, pbus_data_high;
+
-+ ecnt_mii_cl22_write(ebus, EN8801S_PBUS_PHY_ID, 0x1F, (unsigned int)(pbus_address >> 6));
-+ ecnt_mii_cl22_read(ebus, EN8801S_PBUS_PHY_ID, (unsigned int)((pbus_address >> 2) & 0xf), &pbus_data_low);
-+ ecnt_mii_cl22_read(ebus, EN8801S_PBUS_PHY_ID, 0x10, &pbus_data_high);
++ airoha_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
++ airoha_cl22_read(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), &pbus_data_low);
++ airoha_cl22_read(ebus, pbus_id, 0x10, &pbus_data_high);
+ pbus_data = (pbus_data_high << 16) + pbus_data_low;
+ return pbus_data;
+}
+
-+/* Use default PBUS_PHY_ID */
-+/* EN8801 PBUS write function */
-+void En8801_varPbusRegWr(struct mii_bus *ebus, unsigned long pbus_id,unsigned long pbus_address, unsigned long pbus_data)
++/* Airoha Token Ring Write function */
++static void airoha_tr_reg_write(struct mii_bus *ebus, unsigned long tr_address, unsigned long tr_data)
+{
-+ ecnt_mii_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
-+ ecnt_mii_cl22_write(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
-+ ecnt_mii_cl22_write(ebus, pbus_id, 0x10, (unsigned int)(pbus_data >> 16));
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5); /* page select */
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x11, (unsigned int)(tr_data & 0xffff));
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x12, (unsigned int)(tr_data >> 16));
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_WR));
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0); /* page resetore */
+ return;
+}
+
-+/* EN8801 PBUS read function */
-+unsigned long En8801_varPbusRegRd(struct mii_bus *ebus, unsigned long pbus_id, unsigned long pbus_address)
++/* Airoha Token Ring Read function */
++static unsigned long airoha_tr_reg_read(struct mii_bus *ebus, unsigned long tr_address)
+{
-+ unsigned long pbus_data;
-+ unsigned int pbus_data_low, pbus_data_high;
++ unsigned long tr_data;
++ unsigned int tr_data_low, tr_data_high;
+
-+ ecnt_mii_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
-+ ecnt_mii_cl22_read(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), &pbus_data_low);
-+ ecnt_mii_cl22_read(ebus, pbus_id, 0x10, &pbus_data_high);
-+ pbus_data = (pbus_data_high << 16) + pbus_data_low;
-+ return pbus_data;
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5); /* page select */
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_RD));
++ airoha_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x11, &tr_data_low);
++ airoha_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x12, &tr_data_high);
++ airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0); /* page resetore */
++ tr_data = (tr_data_high << 16) + tr_data_low;
++ return tr_data;
+}
+
-+/* EN8801 Token Ring Write function */
-+void En8801_TR_RegWr(struct mii_bus *ebus, unsigned long tr_address, unsigned long tr_data)
++static void en8801s_led_init(struct phy_device *phydev)
+{
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5); /* page select */
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x11, (unsigned int)(tr_data & 0xffff));
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x12, (unsigned int)(tr_data >> 16));
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_WR));
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0); /* page resetore */
-+ return;
++ struct mii_bus *mbus = phydev_mdio_bus(phydev);
++ u32 reg_value;
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x186c, 0x3);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0X1870, 0x100);
++ reg_value = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1880) & ~(0x3));
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1880, reg_value);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x21, 0x8008);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x22, 0x600);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x23, 0xc00);
++ /* LED0: 10M/100M */
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x24, 0x8006);
++ /* LED0: blink 10M/100M Tx/Rx */
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x25, 0x3c);
++ /* LED1: 1000M */
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x26, 0x8001);
++ /* LED1: blink 1000M Tx/Rx */
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, 0x27, 0x3);
+}
+
-+/* EN8801 Token Ring Read function */
-+unsigned long En8801_TR_RegRd(struct mii_bus *ebus, unsigned long tr_address)
++static int en8801s_phy_process(struct phy_device *phydev)
+{
-+ unsigned long tr_data;
-+ unsigned int tr_data_low, tr_data_high;
++ struct mii_bus *mbus = phydev_mdio_bus(phydev);
++ u32 reg_value = 0;
+
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5); /* page select */
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_RD));
-+ ecnt_mii_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x11, &tr_data_low);
-+ ecnt_mii_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x12, &tr_data_high);
-+ ecnt_mii_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0); /* page resetore */
-+ tr_data = (tr_data_high << 16) + tr_data_low;
-+ return tr_data;
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x19e0);
++ reg_value |= (1 << 0);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x19e0, reg_value);
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x19e0);
++ reg_value &= ~(1 << 0);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x19e0, reg_value);
++ return 0;
+}
+
-+static int en8801s_config_init(struct phy_device *phydev)
++static int en8801s_phase1_init(struct phy_device *phydev)
+{
-+ gephy_all_REG_LpiReg1Ch GPHY_RG_LPI_1C;
-+ gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324;
-+ gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012;
-+ gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017;
+ unsigned long pbus_data;
+ unsigned int pbusAddress;
+ u32 reg_value;
+ int retry;
-+ struct mii_bus *mbus;
++ struct mii_bus *mbus = phydev_mdio_bus(phydev);
+
-+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-+ mbus = phydev->bus;
-+ #else
-+ mbus = phydev->mdio.bus;
-+ #endif
++ msleep(1500);
+
+ pbusAddress = EN8801S_PBUS_DEFAULT_ID;
+ retry = MAX_OUI_CHECK;
-+ while(1)
-+ {
-+ pbus_data = En8801_varPbusRegRd(mbus, pbusAddress, EN8801S_RG_ETHER_PHY_OUI); /* PHY OUI */
-+ if(EN8801S_PBUS_OUI == pbus_data)
-+ {
-+ pbus_data = En8801_varPbusRegRd(mbus, pbusAddress, EN8801S_RG_SMI_ADDR); /* SMI ADDR */
-+ pbus_data = (pbus_data & 0xffff0000) | (unsigned long)(EN8801S_PBUS_PHY_ID << 8) | (unsigned long)(EN8801S_MDIO_PHY_ID );
-+ printk("[Airoha] EN8801S SMI_ADDR=%lx (renew)\n", pbus_data);
-+ En8801_varPbusRegWr(mbus, pbusAddress, EN8801S_RG_SMI_ADDR, pbus_data);
-+ En8801_varPbusRegWr(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_BUCK_CTL, 0x03);
++ while (1) {
++ pbus_data = airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_ETHER_PHY_OUI); /* PHY OUI */
++ if (EN8801S_PBUS_OUI == pbus_data) {
++ pbus_data = airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_SMI_ADDR); /* SMI ADDR */
++ pbus_data = (pbus_data & 0xffff0000) | (unsigned long)(EN8801S_PBUS_PHY_ID << 8) | (unsigned long)(EN8801S_MDIO_PHY_ID);
++ phydev_info(phydev, "SMI_ADDR=%lx (renew)\n", pbus_data);
++ airoha_pbus_write(mbus, pbusAddress, EN8801S_RG_SMI_ADDR, pbus_data);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_BUCK_CTL, 0x03);
+ mdelay(10);
+ break;
-+ }
-+ else
-+ {
++ } else {
+ pbusAddress = EN8801S_PBUS_PHY_ID;
+ }
+ retry --;
-+ if (0 == retry)
-+ {
-+ printk("[Airoha] EN8801S probe fail !\n");
++ if (0 == retry) {
++ phydev_err(phydev, "Probe fail !\n");
+ return 0;
+ }
+ }
+
-+ reg_value = (En8801_PbusRegRd(mbus, EN8801S_RG_LTR_CTL) & 0xfffffffc) | 0x10 | (EN8801S_RX_POLARITY << 1) | EN8801S_TX_POLARITY;
-+ En8801_PbusRegWr(mbus, 0xcf8, reg_value);
++ reg_value = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL) & 0xfffffffc) | 0x10 | (EN8801S_RX_POLARITY << 1) | EN8801S_TX_POLARITY;
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, reg_value);
+ mdelay(10);
+ reg_value &= 0xffffffef;
-+ En8801_PbusRegWr(mbus, 0xcf8, reg_value);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, reg_value);
+
+ retry = MAX_RETRY;
-+ while (1)
-+ {
++ while (1) {
+ mdelay(10);
+ reg_value = phy_read(phydev, MII_PHYSID2);
-+ if (reg_value == EN8801S_PHY_ID2)
-+ {
++ if (reg_value == EN8801S_PHY_ID2) {
+ break; /* wait GPHY ready */
+ }
+ retry--;
-+ if (0 == retry)
-+ {
-+ printk("[Airoha] EN8801S initialize fail !\n");
++ if (0 == retry) {
++ phydev_err(phydev, "Initialize fail !\n");
+ return 0;
+ }
+ }
@@ -251,170 +252,210 @@
+ reg_value |= BMCR_RESET;
+ phy_write(phydev, MII_BMCR, reg_value);
+ retry = MAX_RETRY;
-+ do
-+ {
++ do {
+ mdelay(10);
+ reg_value = phy_read(phydev, MII_BMCR);
+ retry--;
-+ if (0 == retry)
-+ {
-+ printk("[Airoha] EN8801S reset fail !\n");
++ if (0 == retry) {
++ phydev_err(phydev, "Reset fail !\n");
+ return 0;
+ }
+ } while (reg_value & BMCR_RESET);
+
++ phydev->dev_flags = PHY_STATE_INIT;
++
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c000c00);
-+ En8801_PbusRegWr(mbus, 0x10, 0xD801);
-+ En8801_PbusRegWr(mbus, 0x0, 0x9140);
++ phydev_info(phydev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
++ return 0;
++}
+
-+ En8801_PbusRegWr(mbus, 0x0A14, 0x0003);
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c000c00);
++static int en8801s_phase2_init(struct phy_device *phydev)
++{
++ gephy_all_REG_LpiReg1Ch GPHY_RG_LPI_1C;
++ gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324;
++ gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012;
++ gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017;
++ unsigned long pbus_data;
++ u32 reg_value;
++ int retry;
++ struct mii_bus *mbus = phydev_mdio_bus(phydev);
++
++ reg_value = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL) & 0xfffffffc) | 0x10 | (EN8801S_RX_POLARITY << 1) | EN8801S_TX_POLARITY;
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, reg_value);
++ mdelay(10);
++ reg_value &= 0xffffffef;
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, reg_value);
++
++ pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1690);
++ pbus_data |= (1 << 31);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1690, pbus_data);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD801);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0, 0x9140);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0003);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
+ /* Set FCM control */
-+ En8801_PbusRegWr(mbus, 0x1404, 0x004b);
-+ En8801_PbusRegWr(mbus, 0x140c, 0x0007);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x004b);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x142c, 0x05050505);
++ pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1440);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1440, pbus_data & ~(1 << 11));
+ /* Set GPHY Perfomance*/
+ /* Token Ring */
-+ En8801_TR_RegWr(mbus, RgAddr_PMA_01h, 0x6FB90A);
-+ En8801_TR_RegWr(mbus, RgAddr_PMA_18h, 0x0E2F00);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_06h, 0x2EBAEF);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_11h, 0x040001);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_03h, 0x000004);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_1Ch, 0x003210);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_14h, 0x00024A);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_0Ch, 0x00704D);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_0Dh, 0x02314F);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_10h, 0x005010);
-+ En8801_TR_RegWr(mbus, RgAddr_DSPF_0Fh, 0x003028);
-+ En8801_TR_RegWr(mbus, RgAddr_TR_26h, 0x444444);
-+ En8801_TR_RegWr(mbus, RgAddr_R1000DEC_15h,0x0055A0);
++ airoha_tr_reg_write(mbus, RgAddr_PMA_01h, 0x6FB90A);
++ airoha_tr_reg_write(mbus, RgAddr_PMA_18h, 0x0E2F00);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_06h, 0x2EBAEF);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_11h, 0x040001);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_03h, 0x000004);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_1Ch, 0x003210);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_14h, 0x00024A);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_0Ch, 0x00704D);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_0Dh, 0x02314F);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_10h, 0x005010);
++ airoha_tr_reg_write(mbus, RgAddr_DSPF_0Fh, 0x003028);
++ airoha_tr_reg_write(mbus, RgAddr_TR_26h, 0x444444);
++ airoha_tr_reg_write(mbus, RgAddr_R1000DEC_15h, 0x0055A0);
+ /* CL22 & CL45 */
+ phy_write(phydev, 0x1f, 0x03);
+ GPHY_RG_LPI_1C.DATA = phy_read(phydev, RgAddr_LpiReg1Ch);
+ GPHY_RG_LPI_1C.DataBitField.smi_deton_th = 0x0C;
+ phy_write(phydev, RgAddr_LpiReg1Ch, GPHY_RG_LPI_1C.DATA);
+ phy_write(phydev, 0x1f, 0x0);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x122, 0xffff);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x234, 0x0180);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x238, 0x0120);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x120, 0x9014);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x239, 0x0117);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x14A, 0xEE20);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19B, 0x0111);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1F, 0x268, 0x07F4);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x122, 0xffff);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x234, 0x0180);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x238, 0x0120);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x120, 0x9014);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x239, 0x0117);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x14A, 0xEE20);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19B, 0x0111);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1F, 0x268, 0x07F4);
+
-+ mdiobus_read45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, ®_value);
-+ GPHY_RG_1E_324.DATA=(u16)reg_value;
++ airoha_cl45_read(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, ®_value);
++ GPHY_RG_1E_324.DATA = (u16)reg_value;
+ GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = 0;
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, (u32)GPHY_RG_1E_324.DATA);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19E, 0xC2);
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x013, 0x0);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, (u32)GPHY_RG_1E_324.DATA);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19E, 0xC2);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x013, 0x0);
+
+ /* EFUSE */
-+ En8801_PbusRegWr(mbus, 0x1C08, 0x40000040);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1C08, 0x40000040);
+ retry = MAX_RETRY;
-+ while (0 != retry)
-+ {
++ while (0 != retry) {
+ mdelay(1);
-+ reg_value = En8801_PbusRegRd(mbus, 0x1C08);
-+ if ((reg_value & (1 << 30)) == 0)
-+ {
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C08);
++ if ((reg_value & (1 << 30)) == 0) {
+ break;
+ }
+ retry--;
+ }
-+ reg_value = En8801_PbusRegRd(mbus, 0x1C38); /* RAW#2 */
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C38); /* RAW#2 */
+ GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt = reg_value & 0x03f;
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, (u32)GPHY_RG_1E_012.DATA);
-+ GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt=(reg_value >> 8) & 0x03f;
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, (u32)GPHY_RG_1E_017.DATA);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, (u32)GPHY_RG_1E_012.DATA);
++ GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt = (reg_value >> 8) & 0x03f;
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, (u32)GPHY_RG_1E_017.DATA);
+
-+ En8801_PbusRegWr(mbus, 0x1C08, 0x40400040);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1C08, 0x40400040);
+ retry = MAX_RETRY;
-+ while (0 != retry)
-+ {
++ while (0 != retry) {
+ mdelay(1);
-+ reg_value = En8801_PbusRegRd(mbus, 0x1C08);
-+ if ((reg_value & (1 << 30)) == 0)
-+ {
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C08);
++ if ((reg_value & (1 << 30)) == 0) {
+ break;
+ }
+ retry--;
+ }
-+ reg_value = En8801_PbusRegRd(mbus, 0x1C30); /* RAW#16 */
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C30); /* RAW#16 */
+ GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = (reg_value >> 12) & 0x01;
-+ mdiobus_write45(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, (u32)GPHY_RG_1E_324.DATA);
++ airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, (u32)GPHY_RG_1E_324.DATA);
+
-+ printk("[Airoha] EN8801S initialize OK ! (1.0.5)\n");
++ en8801s_led_init(phydev);
++
++ phydev_info(phydev, "Phase2 initialize OK !\n");
+ return 0;
+}
+
+static int en8801s_read_status(struct phy_device *phydev)
+{
-+ int ret;
-+ struct mii_bus *mbus;
-+
-+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-+ mbus = phydev->bus;
-+ #else
-+ mbus = phydev->mdio.bus;
-+ #endif
++ int ret, preSpeed = phydev->speed;
++ struct mii_bus *mbus = phydev_mdio_bus(phydev);
++ u32 reg_value;
+
+ ret = genphy_read_status(phydev);
-+ if (LINK_DOWN == phydev->link) preSpeed =0;
++ if (LINK_DOWN == phydev->link) preSpeed = phydev->speed = 0;
+
-+ if ((preSpeed != phydev->speed) && (LINK_UP == phydev->link))
-+ {
++ if (phydev->dev_flags == PHY_STATE_PROCESS) {
++ en8801s_phy_process(phydev);
++ phydev->dev_flags = PHY_STATE_DONE;
++ }
++
++ if ((preSpeed != phydev->speed) && (LINK_UP == phydev->link)) {
+ preSpeed = phydev->speed;
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c000c00);
-+ if (SPEED_1000 == preSpeed)
-+ {
-+ En8801_PbusRegWr(mbus, 0x10, 0xD801);
-+ En8801_PbusRegWr(mbus, 0x0, 0x9140);
+
-+ En8801_PbusRegWr(mbus, 0x0A14, 0x0003);
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c000c00);
-+ mdelay(2); /* delay 2 ms */
-+ En8801_PbusRegWr(mbus, 0x1404, 0x004b);
-+ En8801_PbusRegWr(mbus, 0x140c, 0x0007);
++ if (phydev->dev_flags == PHY_STATE_INIT) {
++ en8801s_phase2_init(phydev);
++ phydev->dev_flags = PHY_STATE_PROCESS;
+ }
-+ else if (SPEED_100 == preSpeed)
-+ {
-+ En8801_PbusRegWr(mbus, 0x10, 0xD401);
-+ En8801_PbusRegWr(mbus, 0x0, 0x9140);
+
-+ En8801_PbusRegWr(mbus, 0x0A14, 0x0007);
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c11);
-+ mdelay(2); /* delay 2 ms */
-+ En8801_PbusRegWr(mbus, 0x1404, 0x0027);
-+ En8801_PbusRegWr(mbus, 0x140c, 0x0007);
++ if (preSpeed == SPEED_10) {
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1694);
++ reg_value |= (1 << 31);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1694, reg_value);
++ phydev->dev_flags = PHY_STATE_PROCESS;
++ } else {
++ reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1694);
++ reg_value &= ~(1 << 31);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1694, reg_value);
++ phydev->dev_flags = PHY_STATE_PROCESS;
+ }
-+ else if (SPEED_10 == preSpeed)
-+ {
-+ En8801_PbusRegWr(mbus, 0x10, 0xD001);
-+ En8801_PbusRegWr(mbus, 0x0, 0x9140);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
++ if (SPEED_1000 == preSpeed) {
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD801);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0, 0x9140);
+
-+ En8801_PbusRegWr(mbus, 0x0A14, 0x000b);
-+ En8801_PbusRegWr(mbus, 0x0600, 0x0c11);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0003);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
+ mdelay(2); /* delay 2 ms */
-+ En8801_PbusRegWr(mbus, 0x1404, 0x0027);
-+ En8801_PbusRegWr(mbus, 0x140c, 0x0007);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x004b);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
++ } else if (SPEED_100 == preSpeed) {
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD401);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0, 0x9140);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0007);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c11);
++ mdelay(2); /* delay 2 ms */
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x0027);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
++ } else if (SPEED_10 == preSpeed) {
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD001);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0, 0x9140);
++
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x000b);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c11);
++ mdelay(2); /* delay 2 ms */
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x0027);
++ airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
+ }
+ }
+ return ret;
+}
+
+static struct phy_driver Airoha_driver[] = {
-+{
-+ .phy_id = EN8801S_PHY_ID,
-+ .name = "Airoha EN8801S",
-+ .phy_id_mask = 0x0ffffff0,
-+ .features = PHY_GBIT_FEATURES,
-+ .config_init = en8801s_config_init,
-+ .config_aneg = genphy_config_aneg,
-+ .read_status = en8801s_read_status,
-+ .suspend = genphy_suspend,
-+ .resume = genphy_resume,
-+} };
++ {
++ .phy_id = EN8801S_PHY_ID,
++ .name = "Airoha EN8801S",
++ .phy_id_mask = 0x0ffffff0,
++ .features = PHY_GBIT_FEATURES,
++ .config_init = en8801s_phase1_init,
++ .config_aneg = genphy_config_aneg,
++ .read_status = en8801s_read_status,
++ .suspend = genphy_suspend,
++ .resume = genphy_resume,
++ }
++};
+
+module_phy_driver(Airoha_driver);
+
@@ -424,14 +465,13 @@
+};
+
+MODULE_DEVICE_TABLE(mdio, Airoha_tbl);
-+MODULE_LICENSE("GPL");
Index: drivers/net/phy/en8801s.h
===================================================================
--- /dev/null
+++ b/drivers/net/phy/en8801s.h
-@@ -0,0 +1,153 @@
+@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
-+/* FILE NAME: airoha.h
++/* FILE NAME: en8801s.h
+ * PURPOSE:
+ * Define EN8801S driver function
+ *
@@ -439,11 +479,13 @@
+ *
+ */
+
-+#ifndef __AIROHA_H
-+#define __AIROHA_H
++#ifndef __EN8801S_H
++#define __EN8801S_H
+
+/* NAMING DECLARATIONS
+ */
++#define EN8801S_DRIVER_VERSION "1.1.0"
++
+#define PHY_ADDRESS_RANGE 0x18
+#define EN8801S_PBUS_DEFAULT_ID 0x1e
+#define EN8801S_MDIO_PHY_ID 0x18 /* Range PHY_ADDRESS_RANGE .. 0x1e */
@@ -468,12 +510,15 @@
+#define LINK_UP 1
+#define LINK_DOWN 0
+
++//#define TEST_BOARD
+#if defined(TEST_BOARD)
++/* SFP sample for verification */
+#define EN8801S_TX_POLARITY 1
+#define EN8801S_RX_POLARITY 0
+#else
++/* chip on board */
+#define EN8801S_TX_POLARITY 0
-+#define EN8801S_RX_POLARITY 1 /* The ping default assignment is set to 1 */
++#define EN8801S_RX_POLARITY 1 /* The pin default assignment is set to 1 */
+#endif
+
+#define MAX_RETRY 5
@@ -582,4 +627,4 @@
+ u16 DATA;
+} gephy_all_REG_dev1Eh_reg017h, *Pgephy_all_REG_dev1Eh_reg017h;
+
-+#endif /* End of __AIROHA_H */
++#endif /* End of __EN8801S_H */