From: Alexander Duyck Add support for 25G-CR, 50G-CR, 50G-CR2, and 100G-CR2 the c45 genphy. Note that 3 of the 4 are IEEE compliant so they are a direct copy from the clause 45 specification, the only exception to this is 50G-CR2 which is part of the Ethernet Consortium specification which never referenced how to handle this in the MDIO registers. Since 50GBase-CR2 isn't an IEEE standard it doesn't have a value in the extended capabilities registers. To account for that I am adding a define that is aliasing the 100GBase-CR4 to represent it as that is the media type used to carry data for 50R2, it is just that the PHY is carrying two 2 with 2 lanes each over the 4 lane cable. For now I am representing it with ctrl1 set to 50G and ctrl2 being set to 100R4, and using the 100R4 capability to identify if it is supported or not. Signed-off-by: Alexander Duyck --- drivers/net/phy/phy-c45.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/mdio.h | 34 +++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 4210863c1b6e..65d6f45c898d 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -161,6 +161,38 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev) /* Assume 10Gbase-T */ ctrl2 |= MDIO_PMA_CTRL2_10GBT; break; + case SPEED_25000: + ctrl1 |= MDIO_CTRL1_SPEED25G; + /* Assume 25Gbase-CR */ + ctrl2 |= MDIO_PMA_CTRL2_25GBCR; + break; + case SPEED_50000: + ctrl1 |= MDIO_CTRL1_SPEED50G; + /* There are currently 2 supported modes for 50G. + * The first is 50Gbase-CR which is in the IEEE standard. + * The second is 50Gbase-CR2 which isn't. It is intended + * to piggy-back on 100Gbase-CR4 and only use 2 lanes, so + * we can use the interface type to identify which is which. + */ + if (phydev->interface == PHY_INTERFACE_MODE_50GBASER) + ctrl2 |= MDIO_PMA_CTRL2_50GBCR; + else if (phydev->interface == PHY_INTERFACE_MODE_LAUI) + ctrl2 |= MDIO_PMA_CTRL2_50GBCR2; + else + return -EINVAL; + break; + case SPEED_100000: + ctrl1 |= MDIO_CTRL1_SPEED100G; + /* For now we only have support for 2 lane devices, so + * 100Gbase-CR2 is the limit. We might look at enabling + * 100Gbase-CR4 in the future with additional devices to + * test this code on. + */ + if (phydev->interface == PHY_INTERFACE_MODE_100GBASEP) + ctrl2 |= MDIO_PMA_CTRL2_100GBCR2; + else + return -EINVAL; + break; default: return -EINVAL; } @@ -958,6 +990,34 @@ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_an_config_eee_aneg); +static int genphy_c45_pma_40_100g_read_abilities(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_40G_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + phydev->supported, + val & MDIO_PMA_40G_EXTABLE_100GBCR4); + linkmode_mod_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, + phydev->supported, + val & MDIO_PMA_40G_EXTABLE_50GBCR2); + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_100G_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, + phydev->supported, + val & MDIO_PMA_100G_EXTABLE_100GBCR2); + + return 0; +} + static int genphy_c45_pma_ng_read_abilities(struct phy_device *phydev) { int val; @@ -978,6 +1038,22 @@ static int genphy_c45_pma_ng_read_abilities(struct phy_device *phydev) return 0; } +static int genphy_c45_pma_25g_read_abilities(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_25G_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + phydev->supported, + val & MDIO_PMA_25G_EXTABLE_25GBCR); + + return 0; +} + /** * genphy_c45_pma_baset1_read_abilities - read supported baset1 link modes from PMA * @phydev: target phy_device struct @@ -1016,6 +1092,22 @@ int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_pma_baset1_read_abilities); +static int genphy_c45_pma_50g_read_abilities(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_50G_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, + phydev->supported, + val & MDIO_PMA_50G_EXTABLE_50GBCR); + + return 0; +} + /** * genphy_c45_pma_read_ext_abilities - read supported link modes from PMA * @phydev: target phy_device struct @@ -1064,18 +1156,40 @@ int genphy_c45_pma_read_ext_abilities(struct phy_device *phydev) phydev->supported, val & MDIO_PMA_EXTABLE_10BT); + if (val & MDIO_PMA_EXTABLE_40_100G) { + err = genphy_c45_pma_40_100g_read_abilities(phydev); + if (err < 0) + return err; + } + if (val & MDIO_PMA_EXTABLE_NBT) { err = genphy_c45_pma_ng_read_abilities(phydev); if (err < 0) return err; } + if (val & MDIO_PMA_EXTABLE_25G) { + err = genphy_c45_pma_25g_read_abilities(phydev); + if (err < 0) + return err; + } + if (val & MDIO_PMA_EXTABLE_BT1) { err = genphy_c45_pma_baset1_read_abilities(phydev); if (err < 0) return err; } + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE2); + if (val < 0) + return val; + + if (val & MDIO_PMA_EXTABLE2_50G) { + err = genphy_c45_pma_50g_read_abilities(phydev); + if (err < 0) + return err; + } + return 0; } EXPORT_SYMBOL_GPL(genphy_c45_pma_read_ext_abilities); diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index ff8b6423bd1e..8f9a4328daf9 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -41,15 +41,20 @@ #define MDIO_PMA_TXDIS 9 /* 10G PMA/PMD transmit disable */ #define MDIO_PMA_RXDET 10 /* 10G PMA/PMD receive signal detect */ #define MDIO_PMA_EXTABLE 11 /* 10G PMA/PMD extended ability */ +#define MDIO_PMA_40G_EXTABLE 13 /* 40G/100G PMA/PMD extended ability */ #define MDIO_PKGID1 14 /* Package identifier */ #define MDIO_PKGID2 15 #define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ #define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ +#define MDIO_PMA_25G_EXTABLE 19 /* 25G PMA/PMD extended ability */ #define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */ +#define MDIO_PMA_50G_EXTABLE 20 /* 50G PMA/PMD extended ability */ #define MDIO_PCS_EEE_ABLE2 21 /* EEE Capability register 2 */ #define MDIO_PMA_NG_EXTABLE 21 /* 2.5G/5G PMA/PMD extended ability */ #define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */ #define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ +#define MDIO_PMA_EXTABLE2 25 /* PMA/PMD extended ability 2 */ +#define MDIO_PMA_100G_EXTABLE 26 /* 40G/100G PMA/PMD extended ability 2 */ #define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ #define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */ #define MDIO_AN_EEE_ADV2 62 /* EEE advertisement 2 */ @@ -187,9 +192,18 @@ #define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */ #define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */ #define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */ +#define MDIO_PMA_CTRL2_100GBCR4 0x002e /* 100GBASE-CR4 type */ +/* 50GBase-CR2 isn't an IEEE media type, as such there isn't a defined + * value for it. However as it is meant to be a reuse of 100GBase-CR4 we + * will reuse the value here so that both report the same value. + */ +#define MDIO_PMA_CTRL2_50GBCR2 MDIO_PMA_CTRL2_100GBCR4 #define MDIO_PMA_CTRL2_2_5GBT 0x0030 /* 2.5GBaseT type */ #define MDIO_PMA_CTRL2_5GBT 0x0031 /* 5GBaseT type */ +#define MDIO_PMA_CTRL2_25GBCR 0x0038 /* 25GBASE-CR type */ #define MDIO_PMA_CTRL2_BASET1 0x003D /* BASE-T1 type */ +#define MDIO_PMA_CTRL2_50GBCR 0x0041 /* 50GBASE-CR type */ +#define MDIO_PMA_CTRL2_100GBCR2 0x0049 /* 100GBASE-CR2 type */ #define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */ #define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */ #define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */ @@ -233,7 +247,7 @@ #define MDIO_PMD_RXDET_2 0x0008 /* PMD RX signal detect 2 */ #define MDIO_PMD_RXDET_3 0x0010 /* PMD RX signal detect 3 */ -/* Extended abilities register. */ +/* PMA/PMD extended ability register. */ #define MDIO_PMA_EXTABLE_10GCX4 0x0001 /* 10GBASE-CX4 ability */ #define MDIO_PMA_EXTABLE_10GBLRM 0x0002 /* 10GBASE-LRM ability */ #define MDIO_PMA_EXTABLE_10GBT 0x0004 /* 10GBASE-T ability */ @@ -243,9 +257,14 @@ #define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */ #define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */ #define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */ +#define MDIO_PMA_EXTABLE_40_100G 0x0400 /* 40G/100G ability */ #define MDIO_PMA_EXTABLE_BT1 0x0800 /* BASE-T1 ability */ +#define MDIO_PMA_EXTABLE_25G 0x1000 /* 25G ability */ #define MDIO_PMA_EXTABLE_NBT 0x4000 /* 2.5/5GBASE-T ability */ +/* PMA/PMD extended ability 2 register. */ +#define MDIO_PMA_EXTABLE2_50G 0x0001 /* 50G ability */ + /* AN Clause 73 linkword */ #define MDIO_AN_C73_0_S_MASK GENMASK(4, 0) #define MDIO_AN_C73_0_E_MASK GENMASK(9, 5) @@ -436,10 +455,23 @@ /* AN MultiGBASE-T AN control 2 */ #define MDIO_AN_THP_BP2_5GT 0x0008 /* 2.5GT THP bypass request */ +/* 40G/100G PMA/PMD Extended ability register */ +#define MDIO_PMA_40G_EXTABLE_100GBCR4 0x4000 /* 100GBASE-CR4 ability */ +#define MDIO_PMA_40G_EXTABLE_50GBCR2 MDIO_PMA_40G_EXTABLE_100GBCR4 + +/* 25G PMA/PMD Extended ability register */ +#define MDIO_PMA_25G_EXTABLE_25GBCR 0x0008 /* 25GBASE-CR ability */ + +/* 50G PMA/PMD Extended ability register */ +#define MDIO_PMA_50G_EXTABLE_50GBCR 0x0002 /* 50GBASE-CR ability */ + /* 2.5G/5G Extended abilities register. */ #define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */ #define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */ +/* 40G/100G PMA/PMD Extended ability 2 register */ +#define MDIO_PMA_100G_EXTABLE_100GBCR2 0x0100 /* 100GBASE-CR2 ability */ + /* LASI RX_ALARM control/status registers. */ #define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ #define MDIO_PMA_LASI_RX_PCSLFLT 0x0008 /* PCS RX local fault */