kernel: 5.15: update Aquantia PHY driver to v6.1 code
[openwrt/openwrt.git] / target / linux / generic / backport-5.15 / 736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch
diff --git a/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch b/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch
new file mode 100644 (file)
index 0000000..d5d5876
--- /dev/null
@@ -0,0 +1,148 @@
+From 3c42563b30417afc8855a3b4c1b38c2f36f78657 Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@seco.com>
+Date: Tue, 20 Sep 2022 18:12:35 -0400
+Subject: [PATCH] net: phy: aquantia: Add support for rate matching
+
+This adds support for rate matching for phys similar to the AQR107. We
+assume that all phys using aqr107_read_status support rate matching.
+However, it could be possible to determine support based on the firmware
+revision if there are phys discovered which do not support rate
+matching.  However, as rate matching is advertised in the datasheets for
+these phys, I suspect it is supported most boards.
+
+Despite the name, the "config" registers are updated with the current
+rate matching method (if any). Because they appear to be updated
+automatically, I don't know if these registers can be used to disable
+rate matching.
+
+Signed-off-by: Sean Anderson <sean.anderson@seco.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/aquantia_main.c | 51 ++++++++++++++++++++++++++++++---
+ 1 file changed, 47 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/aquantia_main.c
++++ b/drivers/net/phy/aquantia_main.c
+@@ -97,6 +97,19 @@
+ #define VEND1_GLOBAL_GEN_STAT2                        0xc831
+ #define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG     BIT(15)
++/* The following registers all have similar layouts; first the registers... */
++#define VEND1_GLOBAL_CFG_10M                  0x0310
++#define VEND1_GLOBAL_CFG_100M                 0x031b
++#define VEND1_GLOBAL_CFG_1G                   0x031c
++#define VEND1_GLOBAL_CFG_2_5G                 0x031d
++#define VEND1_GLOBAL_CFG_5G                   0x031e
++#define VEND1_GLOBAL_CFG_10G                  0x031f
++/* ...and now the fields */
++#define VEND1_GLOBAL_CFG_RATE_ADAPT           GENMASK(8, 7)
++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE      0
++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX               1
++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE     2
++
+ #define VEND1_GLOBAL_RSVD_STAT1                       0xc885
+ #define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID   GENMASK(7, 4)
+ #define VEND1_GLOBAL_RSVD_STAT1_PROV_ID               GENMASK(3, 0)
+@@ -347,40 +360,57 @@ static int aqr_read_status(struct phy_de
+ static int aqr107_read_rate(struct phy_device *phydev)
+ {
++      u32 config_reg;
+       int val;
+       val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1);
+       if (val < 0)
+               return val;
++      if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX)
++              phydev->duplex = DUPLEX_FULL;
++      else
++              phydev->duplex = DUPLEX_HALF;
++
+       switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) {
+       case MDIO_AN_TX_VEND_STATUS1_10BASET:
+               phydev->speed = SPEED_10;
++              config_reg = VEND1_GLOBAL_CFG_10M;
+               break;
+       case MDIO_AN_TX_VEND_STATUS1_100BASETX:
+               phydev->speed = SPEED_100;
++              config_reg = VEND1_GLOBAL_CFG_100M;
+               break;
+       case MDIO_AN_TX_VEND_STATUS1_1000BASET:
+               phydev->speed = SPEED_1000;
++              config_reg = VEND1_GLOBAL_CFG_1G;
+               break;
+       case MDIO_AN_TX_VEND_STATUS1_2500BASET:
+               phydev->speed = SPEED_2500;
++              config_reg = VEND1_GLOBAL_CFG_2_5G;
+               break;
+       case MDIO_AN_TX_VEND_STATUS1_5000BASET:
+               phydev->speed = SPEED_5000;
++              config_reg = VEND1_GLOBAL_CFG_5G;
+               break;
+       case MDIO_AN_TX_VEND_STATUS1_10GBASET:
+               phydev->speed = SPEED_10000;
++              config_reg = VEND1_GLOBAL_CFG_10G;
+               break;
+       default:
+               phydev->speed = SPEED_UNKNOWN;
+-              break;
++              return 0;
+       }
+-      if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX)
+-              phydev->duplex = DUPLEX_FULL;
++      val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg);
++      if (val < 0)
++              return val;
++
++      if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) ==
++          VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE)
++              phydev->rate_matching = RATE_MATCH_PAUSE;
+       else
+-              phydev->duplex = DUPLEX_HALF;
++              phydev->rate_matching = RATE_MATCH_NONE;
+       return 0;
+ }
+@@ -647,6 +677,16 @@ static int aqr107_wait_processor_intensi
+       return 0;
+ }
++static int aqr107_get_rate_matching(struct phy_device *phydev,
++                                  phy_interface_t iface)
++{
++      if (iface == PHY_INTERFACE_MODE_10GBASER ||
++          iface == PHY_INTERFACE_MODE_2500BASEX ||
++          iface == PHY_INTERFACE_MODE_NA)
++              return RATE_MATCH_PAUSE;
++      return RATE_MATCH_NONE;
++}
++
+ static int aqr107_suspend(struct phy_device *phydev)
+ {
+       int err;
+@@ -720,6 +760,7 @@ static struct phy_driver aqr_driver[] =
+       PHY_ID_MATCH_MODEL(PHY_ID_AQR107),
+       .name           = "Aquantia AQR107",
+       .probe          = aqr107_probe,
++      .get_rate_matching = aqr107_get_rate_matching,
+       .config_init    = aqr107_config_init,
+       .config_aneg    = aqr_config_aneg,
+       .config_intr    = aqr_config_intr,
+@@ -738,6 +779,7 @@ static struct phy_driver aqr_driver[] =
+       PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
+       .name           = "Aquantia AQCS109",
+       .probe          = aqr107_probe,
++      .get_rate_matching = aqr107_get_rate_matching,
+       .config_init    = aqcs109_config_init,
+       .config_aneg    = aqr_config_aneg,
+       .config_intr    = aqr_config_intr,
+@@ -764,6 +806,7 @@ static struct phy_driver aqr_driver[] =
+       PHY_ID_MATCH_MODEL(PHY_ID_AQR113C),
+       .name           = "Aquantia AQR113C",
+       .probe          = aqr107_probe,
++      .get_rate_matching = aqr107_get_rate_matching,
+       .config_init    = aqr107_config_init,
+       .config_aneg    = aqr_config_aneg,
+       .config_intr    = aqr_config_intr,