[][kernel][common][eth][Update firmware download feature for Aquantia PHY driver]
[Description]
Refactor firmware download feature for Aquantia PHY driver.
- Add duplicate phydev check in the gangload mode.
- Add phy_start to re-configure PHY setting after downloading.
- Revise PHY reset sequence.
If without this patch, PHY might lose Flow Control setting
that cause Flow Control mismatch.
[Release-log]
Change-Id: I714ea9de7864857934cce656ca3a32facb6f7976
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6896901
diff --git a/target/linux/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch b/target/linux/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
index 1ed206c..b31b40d 100644
--- a/target/linux/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
+++ b/target/linux/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
@@ -142,7 +142,7 @@
index 0000000..7aeec86
--- /dev/null
+++ b/drivers/net/phy/aquantia_firmware.c
-@@ -0,0 +1,995 @@
+@@ -0,0 +1,1023 @@
+// SPDX-License-Identifier: GPL-2.0
+/* FW download driver for Aquantia PHY
+ */
@@ -977,11 +977,22 @@
+ int j;
+
+ for (j = 0; j < num_phydevs; j++) {
++ /* stall the uP */
++ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2);
++ val |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
++ val |= VEND1_CONTROL2_UP_RUNSTALL;
++ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, val);
++
+ /* disable the S/W reset to the Global MMD registers */
+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL);
+ val |= VEND1_RESET_CONTROL_MMD_RESET_DISABLE;
+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL, val);
+
++ /* de-assert Global S/W reset */
++ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
++ val &= ~VEND1_STD_CONTROL1_SOFT_RESET;
++ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
++
+ /* assert Global S/W reset */
+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
+ val |= VEND1_STD_CONTROL1_SOFT_RESET;
@@ -1018,6 +1029,11 @@
+ if (!fw)
+ return;
+
++ for (i = 0; i < MAX_GANGLOAD_DEVICES; i++) {
++ if (phy_is_started(phydevs[i]))
++ phy_stop(phydevs[i]);
++ }
++
+retry:
+ memset(result, 0, sizeof(result));
+
@@ -1042,9 +1058,13 @@
+ if (result[i] == 0) {
+ priv = phydevs[i]->priv;
+ priv->fw_initialized = true;
++
+#ifdef CONFIG_AQUANTIA_PHY_MDI_SWAP
+ aqr107_config_mdi(phydevs[i]);
+#endif
++
++ if (!phy_is_started(phydevs[i]))
++ phy_start(phydevs[i]);
+ }
+ }
+
@@ -1104,6 +1124,7 @@
+{
+ struct aqr107_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
++ int i;
+
+ if (priv->fw_initialized == true)
+ return 0;
@@ -1122,6 +1143,13 @@
+ wake_up_process(gangload_kthread);
+ }
+
++ for (i = 0; i < gangload; i++) {
++ if (gangload_phydevs[i] == phydev) {
++ dev_err(dev, "Detect duplicate gangload phydev\n");
++ return -EINVAL;
++ }
++ }
++
+ gangload_phydevs[gangload] = phydev;
+ gangload++;
+