| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- From 3c42563b30417afc8855a3b4c1b38c2f36f78657 Mon Sep 17 00:00:00 2001
- From: Sean Anderson <[email protected]>
- 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 <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- 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,
|