[openwrt/openwrt] generic: add fix for AQR113 PMD Global Transmit Disable bit

LEDE Commits lede-commits at lists.infradead.org
Tue Jul 9 03:33:40 PDT 2024


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/bb907d8d449a32da0f075e188cb22694c89e2281

commit bb907d8d449a32da0f075e188cb22694c89e2281
Author: Robert Marko <robimarko at gmail.com>
AuthorDate: Sun Feb 11 18:56:54 2024 +0100

    generic: add fix for AQR113 PMD Global Transmit Disable bit
    
    PMD Global Transmit Disable bit should be cleared for normal operation.
    This should be HW default, however I found that on Asus RT-AX89X that uses
    AQR113C PHY and firmware 5.4 this bit is set by default.
    
    With this bit set the AQR cannot achieve a link with its link-partner and
    it took me multiple hours of digging through the vendor GPL source to find
    this out, so lets always clear this bit during .config_init() to avoid a
    situation like this in the future.
    
    aqr107_wait_processor_intensive_op() is moved up because datasheet notes
    that any changes to this bit are processor intensive.
    
    This is a modified version of patch that got merged upstream as AQR113C
    has a separate config_init() upstream.
    
    Link: https://github.com/openwrt/openwrt/pull/15840
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 ...antia-clear-PMD-Global-Transmit-Disable-b.patch | 103 +++++++++++++++++++++
 ...antia-clear-PMD-Global-Transmit-Disable-b.patch | 103 +++++++++++++++++++++
 ...net-phy-aquantia-enable-AQR112-and-AQR412.patch |   4 +-
 ...-aquantia-add-PHY_IDs-for-AQR112-variants.patch |   4 +-
 ...net-phy-aquantia-enable-AQR112-and-AQR412.patch |   4 +-
 ...-aquantia-add-PHY_IDs-for-AQR112-variants.patch |   4 +-
 6 files changed, 214 insertions(+), 8 deletions(-)

diff --git a/target/linux/generic/backport-6.1/839-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch b/target/linux/generic/backport-6.1/839-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch
new file mode 100644
index 0000000000..802cf8a128
--- /dev/null
+++ b/target/linux/generic/backport-6.1/839-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch
@@ -0,0 +1,103 @@
+From cffac22c9215f1883d3848c788f9b03656dced27 Mon Sep 17 00:00:00 2001
+From: Robert Marko <robimarko at gmail.com>
+Date: Sun, 11 Feb 2024 18:39:19 +0100
+Subject: [PATCH] net: phy: aquantia: clear PMD Global Transmit Disable bit
+ during init
+
+PMD Global Transmit Disable bit should be cleared for normal operation.
+This should be HW default, however I found that on Asus RT-AX89X that uses
+AQR113C PHY and firmware 5.4 this bit is set by default.
+
+With this bit set the AQR cannot achieve a link with its link-partner and
+it took me multiple hours of digging through the vendor GPL source to find
+this out, so lets always clear this bit during .config_init() to avoid a
+situation like this in the future.
+
+aqr107_wait_processor_intensive_op() is moved up because datasheet notes
+that any changes to this bit are processor intensive.
+
+Signed-off-by: Robert Marko <robimarko at gmail.com>
+---
+ drivers/net/phy/aquantia/aquantia_main.c | 57 ++++++++++++++----------
+ 1 file changed, 33 insertions(+), 24 deletions(-)
+
+--- a/drivers/net/phy/aquantia/aquantia_main.c
++++ b/drivers/net/phy/aquantia/aquantia_main.c
+@@ -507,6 +507,30 @@ static void aqr107_chip_info(struct phy_
+ 		   fw_major, fw_minor, build_id, prov_id);
+ }
+ 
++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
++{
++	int val, err;
++
++	/* The datasheet notes to wait at least 1ms after issuing a
++	 * processor intensive operation before checking.
++	 * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
++	 * because that just determines the maximum time slept, not the minimum.
++	 */
++	usleep_range(1000, 5000);
++
++	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
++					VEND1_GLOBAL_GEN_STAT2, val,
++					!(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
++					AQR107_OP_IN_PROG_SLEEP,
++					AQR107_OP_IN_PROG_TIMEOUT, false);
++	if (err) {
++		phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
++		return err;
++	}
++
++	return 0;
++}
++
+ static int aqr107_config_init(struct phy_device *phydev)
+ {
+ 	int ret;
+@@ -530,6 +554,15 @@ static int aqr107_config_init(struct phy
+ 	if (!ret)
+ 		aqr107_chip_info(phydev);
+ 
++	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
++				 MDIO_PMD_TXDIS_GLOBAL);
++	if (ret)
++		return ret;
++
++	ret = aqr107_wait_processor_intensive_op(phydev);
++	if (ret)
++		return ret;
++
+ 	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+ }
+ 
+@@ -600,30 +633,6 @@ static void aqr107_link_change_notify(st
+ 		phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n");
+ }
+ 
+-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
+-{
+-	int val, err;
+-
+-	/* The datasheet notes to wait at least 1ms after issuing a
+-	 * processor intensive operation before checking.
+-	 * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
+-	 * because that just determines the maximum time slept, not the minimum.
+-	 */
+-	usleep_range(1000, 5000);
+-
+-	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+-					VEND1_GLOBAL_GEN_STAT2, val,
+-					!(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
+-					AQR107_OP_IN_PROG_SLEEP,
+-					AQR107_OP_IN_PROG_TIMEOUT, false);
+-	if (err) {
+-		phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
+-		return err;
+-	}
+-
+-	return 0;
+-}
+-
+ static int aqr107_get_rate_matching(struct phy_device *phydev,
+ 				    phy_interface_t iface)
+ {
diff --git a/target/linux/generic/backport-6.6/836-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch b/target/linux/generic/backport-6.6/836-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch
new file mode 100644
index 0000000000..8b54881ab0
--- /dev/null
+++ b/target/linux/generic/backport-6.6/836-v6.9-net-phy-aquantia-clear-PMD-Global-Transmit-Disable-b.patch
@@ -0,0 +1,103 @@
+From cffac22c9215f1883d3848c788f9b03656dced27 Mon Sep 17 00:00:00 2001
+From: Robert Marko <robimarko at gmail.com>
+Date: Sun, 11 Feb 2024 18:39:19 +0100
+Subject: [PATCH] net: phy: aquantia: clear PMD Global Transmit Disable bit
+ during init
+
+PMD Global Transmit Disable bit should be cleared for normal operation.
+This should be HW default, however I found that on Asus RT-AX89X that uses
+AQR113C PHY and firmware 5.4 this bit is set by default.
+
+With this bit set the AQR cannot achieve a link with its link-partner and
+it took me multiple hours of digging through the vendor GPL source to find
+this out, so lets always clear this bit during .config_init() to avoid a
+situation like this in the future.
+
+aqr107_wait_processor_intensive_op() is moved up because datasheet notes
+that any changes to this bit are processor intensive.
+
+Signed-off-by: Robert Marko <robimarko at gmail.com>
+---
+ drivers/net/phy/aquantia/aquantia_main.c | 57 ++++++++++++++----------
+ 1 file changed, 33 insertions(+), 24 deletions(-)
+
+--- a/drivers/net/phy/aquantia/aquantia_main.c
++++ b/drivers/net/phy/aquantia/aquantia_main.c
+@@ -473,6 +473,30 @@ static void aqr107_chip_info(struct phy_
+ 		   fw_major, fw_minor, build_id, prov_id);
+ }
+ 
++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
++{
++	int val, err;
++
++	/* The datasheet notes to wait at least 1ms after issuing a
++	 * processor intensive operation before checking.
++	 * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
++	 * because that just determines the maximum time slept, not the minimum.
++	 */
++	usleep_range(1000, 5000);
++
++	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
++					VEND1_GLOBAL_GEN_STAT2, val,
++					!(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
++					AQR107_OP_IN_PROG_SLEEP,
++					AQR107_OP_IN_PROG_TIMEOUT, false);
++	if (err) {
++		phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
++		return err;
++	}
++
++	return 0;
++}
++
+ static int aqr107_config_init(struct phy_device *phydev)
+ {
+ 	struct aqr107_priv *priv = phydev->priv;
+@@ -498,6 +522,15 @@ static int aqr107_config_init(struct phy
+ 	if (!ret)
+ 		aqr107_chip_info(phydev);
+ 
++	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
++				 MDIO_PMD_TXDIS_GLOBAL);
++	if (ret)
++		return ret;
++
++	ret = aqr107_wait_processor_intensive_op(phydev);
++	if (ret)
++		return ret;
++
+ 	ret = aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+ 	if (ret)
+ 		return ret;
+@@ -580,30 +613,6 @@ static void aqr107_link_change_notify(st
+ 		phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n");
+ }
+ 
+-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
+-{
+-	int val, err;
+-
+-	/* The datasheet notes to wait at least 1ms after issuing a
+-	 * processor intensive operation before checking.
+-	 * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
+-	 * because that just determines the maximum time slept, not the minimum.
+-	 */
+-	usleep_range(1000, 5000);
+-
+-	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+-					VEND1_GLOBAL_GEN_STAT2, val,
+-					!(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
+-					AQR107_OP_IN_PROG_SLEEP,
+-					AQR107_OP_IN_PROG_TIMEOUT, false);
+-	if (err) {
+-		phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
+-		return err;
+-	}
+-
+-	return 0;
+-}
+-
+ static int aqr107_get_rate_matching(struct phy_device *phydev,
+ 				    phy_interface_t iface)
+ {
diff --git a/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
index faaa40f9bd..42b44d564d 100644
--- a/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
+++ b/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
@@ -106,7 +106,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean at nxp.com>
  static int aqr_config_intr(struct phy_device *phydev)
  {
  	bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED;
-@@ -860,6 +930,30 @@ static struct phy_driver aqr_driver[] =
+@@ -869,6 +939,30 @@ static struct phy_driver aqr_driver[] =
  	.get_stats	= aqr107_get_stats,
  	.link_change_notify = aqr107_link_change_notify,
  },
@@ -137,7 +137,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean at nxp.com>
  };
  
  module_phy_driver(aqr_driver);
-@@ -877,6 +971,8 @@ static struct mdio_device_id __maybe_unu
+@@ -886,6 +980,8 @@ static struct mdio_device_id __maybe_unu
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
diff --git a/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
index d83cc48a33..6d107c3349 100644
--- a/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
+++ b/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
@@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
  
  #define MDIO_PHYXS_VEND_IF_STATUS		0xe812
  #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK	GENMASK(7, 3)
-@@ -960,6 +962,30 @@ static struct phy_driver aqr_driver[] =
+@@ -969,6 +971,30 @@ static struct phy_driver aqr_driver[] =
  	.get_strings	= aqr107_get_strings,
  	.get_stats	= aqr107_get_stats,
  },
@@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
  };
  
  module_phy_driver(aqr_driver);
-@@ -979,6 +1005,8 @@ static struct mdio_device_id __maybe_unu
+@@ -988,6 +1014,8 @@ static struct mdio_device_id __maybe_unu
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
diff --git a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
index ea5c700702..dee901fbe3 100644
--- a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
+++ b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch
@@ -97,7 +97,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean at nxp.com>
  static int aqr_config_intr(struct phy_device *phydev)
  {
  	bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED;
-@@ -807,7 +875,7 @@ static struct phy_driver aqr_driver[] =
+@@ -816,7 +884,7 @@ static struct phy_driver aqr_driver[] =
  	PHY_ID_MATCH_MODEL(PHY_ID_AQR112),
  	.name		= "Aquantia AQR112",
  	.probe		= aqr107_probe,
@@ -106,7 +106,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean at nxp.com>
  	.config_intr	= aqr_config_intr,
  	.handle_interrupt = aqr_handle_interrupt,
  	.get_tunable    = aqr107_get_tunable,
-@@ -830,7 +898,7 @@ static struct phy_driver aqr_driver[] =
+@@ -839,7 +907,7 @@ static struct phy_driver aqr_driver[] =
  	PHY_ID_MATCH_MODEL(PHY_ID_AQR412),
  	.name		= "Aquantia AQR412",
  	.probe		= aqr107_probe,
diff --git a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
index 66298b89ed..075b0fc8e2 100644
--- a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
+++ b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch
@@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
  
  #define MDIO_PHYXS_VEND_IF_STATUS		0xe812
  #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK	GENMASK(7, 3)
-@@ -1014,6 +1016,30 @@ static struct phy_driver aqr_driver[] =
+@@ -1023,6 +1025,30 @@ static struct phy_driver aqr_driver[] =
  	.led_hw_control_get = aqr_phy_led_hw_control_get,
  	.led_polarity_set = aqr_phy_led_polarity_set,
  },
@@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle <daniel at makrotopia.org>
  };
  
  module_phy_driver(aqr_driver);
-@@ -1034,6 +1060,8 @@ static struct mdio_device_id __maybe_unu
+@@ -1043,6 +1069,8 @@ static struct mdio_device_id __maybe_unu
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR114C) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },




More information about the lede-commits mailing list