[][kernel][common][eth][Update Airoha EN8811H 2.5G PHY driver to v1.2.8 pre-release]
[Description]
Change Airoha EN8811H 2.5G PHY driver to v1.2.8 pre-release.
Change Log:
[2024/11/01] v1.2.8_pre-release
1.Add airoha,phy-handle parameter to ensure that the settings for
phy-handle and fixed-link can coexist.
=====================================================================
If your board that GMAC2 connects with Airoha EN8811H, please change
the eth node as following.
ð {
...
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "2500base-x";
phy-handle = <&phy15>;
};
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
phy15: phy@15 {
compatible = "ethernet-phy-id03a2.a411";
reg = <15>;
phy-mode = "2500base-x";
airoha,polarity = <1>;
airoha,surge = <0>;
airoha,phy-handle;
};
...
};
};
Note:
SerDes polarity setting could be configured in dts. Please refer to the
following description.
Tx Reverse, Rx Normal:
airoha,polarity = <0>;
Tx Normal, Rx Normal:
airoha,polarity = <1>;
Tx Reverse, Rx Reverse:
airoha,polarity = <2>;
Tx Normal, Rx Reverse:
airoha,polarity = <3>;
Surge protection setting could be configured in dts. Please refer to the
following description.
Surge protection - 0R
airoha,surge = <0>;
Surge protection - 5R
airoha,surge = <1>;
=====================================================================
In addition, if EN8811H connects with a RESET GPIO, please check the
GPIO number, and then add reset-gpio related definition to above phy
node.
=====================================================================
reset-gpios = <&gpio 6 1>;
reset-assert-us = <10000>;
reset-deassert-us = <10000>;
=====================================================================
If without this patch, kernel cannot load up-to-date PHY driver
for the Airoha EN8811H.
[Release-log]
N/A
Change-Id: I3feb4a16d6c794db792f108a0655b1f0dd1e12b3
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9885835
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
index 5f5ec38..bd06877 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
@@ -46,7 +46,7 @@
#define MII_MMD_ADDR_DATA_REG 0x0e
#define MMD_OP_MODE_DATA BIT(14)
-#define EN8811H_DRIVER_VERSION "v1.2.7"
+#define EN8811H_DRIVER_VERSION "v1.2.8_pre_release"
#define LED_ON_CTRL(i) (0x024 + ((i)*2))
#define LED_ON_EN (1 << 15)
@@ -138,6 +138,7 @@
bool mcu_needs_restart;
bool mcu_reload;
int debug;
+ int phy_handle;
};
struct air_base_t_led_cfg {
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
index 9ea0b70..3d5cbb8 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
@@ -26,12 +26,6 @@
#include "air_en8811h.h"
#include "air_en8811h_api.h"
-/*
-struct air_phy_debug {
- struct dentry *root;
-};
-struct air_phy_debug air_debug;
-*/
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
static const char * const tx_rx_string[32] = {
"Tx Reverse, Rx Normal",
@@ -471,6 +465,11 @@
} else
priv->cko = AIR_CKO_DIS;
+ if (of_find_property(of_node, "airoha,phy-handle", NULL))
+ priv->phy_handle = true;
+ else
+ priv->phy_handle = false;
+
return 0;
}
#else
@@ -1268,7 +1267,7 @@
{
struct phy_device *phydev = seq->private;
struct mii_bus *mbus = phydev_mdio_bus(phydev);
- int addr = phydev_addr(phydev);
+ int addr = phydev_addr(phydev), ret;
seq_puts(seq, "\t<<DEBUG REG DUMP>>\n");
seq_printf(seq, "| RG_MII_BMCR : 0x%08x |\n",
@@ -1287,8 +1286,10 @@
air_mii_cl22_read(mbus, addr, MII_STAT1000));
seq_printf(seq, "| RG_LINK_PARTNER_2G5 : 0x%08x |\n",
air_buckpbus_reg_read(phydev, 0x3b30));
+ ret = air_mii_cl22_write(mbus, addr, 0x1f, 0x0);
+ ret = air_mii_cl22_read(mbus, addr, 0x1d);
seq_printf(seq, "| RG_MII_REF_CLK : 0x%08x |\n",
- air_mii_cl22_read(mbus, addr, 0x1d));
+ ret);
seq_printf(seq, "| RG_HW_STRAP1 : 0x%08x |\n",
air_buckpbus_reg_read(phydev, 0xcf910));
seq_printf(seq, "| RG_HW_STRAP2 : 0x%08x |\n",
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
index b0b4290..7dbf66d 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
@@ -36,7 +36,6 @@
**************************/
/* User-defined.B */
/* #define AIR_MD32_FW_CHECK */
-#define AIR_PHY_HANDLE_SUPPORT
#define AIR_LED_SUPPORT
#ifdef AIR_LED_SUPPORT
static const struct air_base_t_led_cfg led_cfg[3] = {
@@ -422,8 +421,10 @@
return -ENOMEM;
phydev->priv = priv;
ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
- if (ret < 0)
- goto priv_free;
+ if (ret < 0) {
+ kfree(priv);
+ return ret;
+ }
pid1 = air_mii_cl22_read(mbus, addr, MII_PHYSID1);
pid2 = air_mii_cl22_read(mbus, addr, MII_PHYSID2);
dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
@@ -436,21 +437,30 @@
pbus_value = air_buckpbus_reg_read(phydev, 0xcf914);
dev_info(dev, "Bootmode: %s\n",
(GET_BIT(pbus_value, 24) ? "Flash" : "Download Code"));
+ ret = en8811h_of_init(phydev);
+ if (ret < 0) {
+ kfree(priv);
+ return ret;
+ }
ret = air_buckpbus_reg_write(phydev, 0x1e00d0, 0xf);
ret |= air_buckpbus_reg_write(phydev, 0x1e0228, 0xf0);
- if (ret < 0)
- goto priv_free;
+ if (ret < 0) {
+ kfree(priv);
+ return ret;
+ }
ret = en8811h_load_firmware(phydev);
if (ret < 0) {
dev_err(dev, "EN8811H load firmware fail.\n");
- goto priv_free;
+ kfree(priv);
+ return ret;
}
#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
ret = airphy_debugfs_init(phydev);
if (ret < 0) {
dev_err(dev, "air_debug_procfs_init fail. (ret=%d)\n", ret);
airphy_debugfs_remove(phydev);
- goto priv_free;
+ kfree(priv);
+ return ret;
}
#endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
retry = MAX_RETRY;
@@ -461,7 +471,6 @@
dev_info(dev, "EN8811H PHY ready!\n");
break;
}
- retry--;
if (retry == 0) {
dev_err(dev, "MD32 FW is not ready.(Status 0x%x)\n", reg_value);
pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
@@ -469,66 +478,65 @@
"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
dev_err(dev,
"EN8811H initialize fail!\n");
- goto priv_free;
+ kfree(priv);
+ return ret;
}
- } while (retry);
-#ifdef AIR_PHY_HANDLE_SUPPORT
- priv->mcu_needs_restart = false;
- dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
- return 0;
-priv_free:
- kfree(priv);
- return ret;
-#else
- ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
- ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
- ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
- ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
- if (ret < 0)
- goto priv_free;
- /* Serdes polarity */
- ret = en8811h_of_init(phydev);
- if (ret < 0)
- goto priv_free;
- pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
- pbus_value &= ~0x3;
+ } while (retry--);
+
+ if (priv->phy_handle) {
+ priv->mcu_needs_restart = false;
+ dev_info(dev, "EN8811H Probe OK! (%s)\n", EN8811H_DRIVER_VERSION);
+ } else {
+ ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
+ ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
+ ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
+ ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
+ if (ret < 0) {
+ kfree(priv);
+ return ret;
+ }
+ pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
+ pbus_value &= ~0x3;
#if defined(CONFIG_OF)
- pbus_value |= priv->pol;
+ pbus_value |= priv->pol;
#else
- pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
+ pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
#endif
- ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
- if (ret < 0)
- goto priv_free;
- pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
- dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
- priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
- dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
- ret = air_surge_protect_cfg(phydev);
- if (ret < 0) {
- dev_err(dev,
- "air_surge_protect_cfg fail. (ret=%d)\n", ret);
- goto priv_free;
- }
- ret = air_cko_cfg(phydev);
- if (ret < 0) {
- dev_err(dev,
- "air_cko_cfg fail. (ret=%d)\n", ret);
- goto priv_free;
- }
+ ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
+ if (ret < 0) {
+ kfree(priv);
+ return ret;
+ }
+ pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
+ dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
+ priv->firmware_version = air_buckpbus_reg_read(phydev, 0x3b3c);
+ dev_info(dev, "MD32 FW Version : %08x\n", priv->firmware_version);
+ ret = air_surge_protect_cfg(phydev);
+ if (ret < 0) {
+ dev_err(dev,
+ "air_surge_protect_cfg fail. (ret=%d)\n", ret);
+ kfree(priv);
+ return ret;
+ }
+ ret = air_cko_cfg(phydev);
+ if (ret < 0) {
+ dev_err(dev,
+ "air_cko_cfg fail. (ret=%d)\n", ret);
+ kfree(priv);
+ return ret;
+ }
#if defined(AIR_LED_SUPPORT)
- ret = en8811h_led_init(phydev);
- if (ret < 0) {
- dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
- goto priv_free;
- }
+ ret = en8811h_led_init(phydev);
+ if (ret < 0) {
+ dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
+ kfree(priv);
+ return ret;
+ }
#endif
- dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
+
+ dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
+ }
return 0;
-priv_free:
- kfree(priv);
- return ret;
-#endif
}
void en8811h_remove(struct phy_device *phydev)
@@ -547,7 +555,6 @@
}
}
-#ifdef AIR_PHY_HANDLE_SUPPORT
static int en8811h_restart_mcu(struct phy_device *phydev)
{
int ret, retry, reg_value;
@@ -635,6 +642,8 @@
u32 pbus_value = 0;
struct device *dev = phydev_dev(phydev);
struct en8811h_priv *priv = phydev->priv;
+ int addr = phydev_addr(phydev);
+ struct mii_bus *mbus = phydev_mdio_bus(phydev);
ret = en8811h_check_mcu(phydev);
if (ret < 0) {
@@ -699,6 +708,12 @@
goto priv_free;
}
#endif
+ ret = air_mii_cl22_read(mbus, addr, MII_BMCR);
+ ret |= (BMCR_ANRESTART | BMCR_ANENABLE);
+ ret = air_mii_cl22_write(mbus, addr, MII_BMCR, ret);
+ if (ret < 0)
+ goto priv_free;
+
dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
return 0;
priv_free:
@@ -777,10 +792,11 @@
phydev->lp_advertising,
phydev->speed == SPEED_2500);
}
+ if (phydev->speed <= SPEED_1000)
+ phydev->pause = 1;
return 0;
}
-#endif /*AIR_PHY_HANDLE_SUPPORT*/
static struct phy_driver en8811h_driver[] = {
{
@@ -794,14 +810,12 @@
.read_mmd = __air_mii_cl45_read,
.write_mmd = __air_mii_cl45_write,
#endif
-#ifdef AIR_PHY_HANDLE_SUPPORT
.config_init = en8811h_config_init,
.read_status = en8811h_read_status,
.get_rate_matching = en8811h_get_rate_matching,
.config_aneg = en8811h_config_aneg,
.resume = genphy_resume,
.suspend = genphy_suspend,
-#endif
} };
int __init en8811h_phy_driver_register(void)