[][kernel][mt7988][eth][Add 10G rate adaption support for MV88X3310 SFP+ modules]

[Description]
Add 10G rate adaption support for MV88X3310 SFP+ modules.
    - Support OEM TNBYV02-C0X-C3 module
    - Support JESS-LINK P60000BBC001-1 module

If without this patch, MV88X3310 SFP+ modules cannot link with
non-10G link partners.

Note: This feature backport from Linux-6.1.
https://elixir.bootlin.com/linux/v6.1/source/drivers/net/phy/marvell10g.c

[Release-log]
N/A


Change-Id: If7182fdb3ba43d8b8d6ed87956858ac7bdc1eb5a
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7023892
diff --git a/target/linux/mediatek/patches-5.4/754-net-phy-sfp-add-rollball-support.patch b/target/linux/mediatek/patches-5.4/754-net-phy-sfp-add-rollball-support.patch
index ef1f3cb..cfbc28f 100644
--- a/target/linux/mediatek/patches-5.4/754-net-phy-sfp-add-rollball-support.patch
+++ b/target/linux/mediatek/patches-5.4/754-net-phy-sfp-add-rollball-support.patch
@@ -966,10 +966,71 @@
  int sfp_module_start(struct sfp_bus *bus);
  void sfp_module_stop(struct sfp_bus *bus);
 diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
-index 512f27b..2c2d638 100644
+index 512f27b..daed73a 100644
 --- a/drivers/net/phy/marvell10g.c
 +++ b/drivers/net/phy/marvell10g.c
-@@ -155,13 +155,6 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
+@@ -32,6 +32,15 @@
+ #define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
+ 
+ enum {
++	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
++	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
++	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
++	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+ 	MV_PMA_BOOT		= 0xc050,
+ 	MV_PMA_BOOT_FATAL	= BIT(0),
+ 
+@@ -53,7 +62,18 @@ enum {
+ 
+ 	/* Vendor2 MMD registers */
+ 	MV_V2_PORT_CTRL		= 0xf001,
+-	MV_V2_PORT_CTRL_PWRDOWN = 0x0800,
++	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
++	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
++	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
++	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
++	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
++	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
+ 	MV_V2_TEMP_CTRL		= 0xf08a,
+ 	MV_V2_TEMP_CTRL_MASK	= 0xc000,
+ 	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
+@@ -62,11 +82,24 @@ enum {
+ 	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+ };
+ 
++struct mv3310_chip {
++	int (*get_mactype)(struct phy_device *phydev);
++	int (*init_interface)(struct phy_device *phydev, int mactype);
++};
++
+ struct mv3310_priv {
++	bool rate_match;
++	phy_interface_t const_interface;
++
+ 	struct device *hwmon_dev;
+ 	char *hwmon_name;
+ };
+ 
++static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
++{
++	return phydev->drv->driver_data;
++}
++
+ #ifdef CONFIG_HWMON
+ static umode_t mv3310_hwmon_is_visible(const void *data,
+ 				       enum hwmon_sensor_types type,
+@@ -155,13 +188,6 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
  			      MV_V2_TEMP_CTRL_MASK, val);
  }
  
@@ -983,7 +1044,7 @@
  static int mv3310_hwmon_probe(struct phy_device *phydev)
  {
  	struct device *dev = &phydev->mdio.dev;
-@@ -185,10 +178,6 @@ static int mv3310_hwmon_probe(struct phy_device *phydev)
+@@ -185,10 +211,6 @@ static int mv3310_hwmon_probe(struct phy_device *phydev)
  	if (ret)
  		return ret;
  
@@ -994,7 +1055,7 @@
  	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
  				priv->hwmon_name, phydev,
  				&mv3310_hwmon_chip_info, NULL);
-@@ -262,6 +251,11 @@ static int mv3310_probe(struct phy_device *phydev)
+@@ -262,6 +284,11 @@ static int mv3310_probe(struct phy_device *phydev)
  	return phy_sfp_probe(phydev, &mv3310_sfp_ops);
  }
  
@@ -1006,7 +1067,156 @@
  static int mv3310_suspend(struct phy_device *phydev)
  {
  	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
-@@ -513,6 +507,7 @@ static struct phy_driver mv3310_drivers[] = {
+@@ -297,8 +324,84 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
+ 		MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
+ }
+ 
++static int mv2110_get_mactype(struct phy_device *phydev)
++{
++	int mactype;
++
++	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
++	if (mactype < 0)
++		return mactype;
++
++	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
++}
++
++static int mv3310_get_mactype(struct phy_device *phydev)
++{
++	int mactype;
++
++	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
++	if (mactype < 0)
++		return mactype;
++
++	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
++}
++
++static int mv2110_init_interface(struct phy_device *phydev, int mactype)
++{
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
++
++	priv->rate_match = false;
++
++	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
++		priv->rate_match = true;
++
++	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII)
++		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
++	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
++		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
++	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER ||
++		 mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN)
++		priv->const_interface = PHY_INTERFACE_MODE_NA;
++	else
++		return -EINVAL;
++
++	return 0;
++}
++
++static int mv3310_init_interface(struct phy_device *phydev, int mactype)
++{
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
++
++	priv->rate_match = false;
++
++	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
++	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
++	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
++		priv->rate_match = true;
++
++	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII)
++		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
++	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER)
++		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
++	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI)
++		priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
++	else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH ||
++		 mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI)
++		priv->const_interface = PHY_INTERFACE_MODE_XAUI;
++	else
++		return -EINVAL;
++
++	return 0;
++}
++
+ static int mv3310_config_init(struct phy_device *phydev)
+ {
++	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
++	int err, mactype;
++
+ 	/* Check that the PHY interface type is compatible */
+ 	if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ 	    phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
+@@ -307,6 +410,16 @@ static int mv3310_config_init(struct phy_device *phydev)
+ 	    phydev->interface != PHY_INTERFACE_MODE_10GKR)
+ 		return -ENODEV;
+ 
++	mactype = chip->get_mactype(phydev);
++	if (mactype < 0)
++		return mactype;
++
++	err = chip->init_interface(phydev, mactype);
++	if (err) {
++		phydev_err(phydev, "MACTYPE configuration invalid\n");
++		return err;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -384,6 +497,23 @@ static int mv3310_aneg_done(struct phy_device *phydev)
+ 
+ static void mv3310_update_interface(struct phy_device *phydev)
+ {
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
++
++	if (!phydev->link)
++		return;
++
++	/* In all of the "* with Rate Matching" modes the PHY interface is fixed
++	 * at 10Gb. The PHY adapts the rate to actual wire speed with help of
++	 * internal 16KB buffer.
++	 *
++	 * In USXGMII mode the PHY interface mode is also fixed.
++	 */
++	if (priv->rate_match ||
++	    priv->const_interface == PHY_INTERFACE_MODE_USXGMII) {
++		phydev->interface = priv->const_interface;
++		return;
++	}
++
+ 	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
+ 	     phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
+ 	     phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
+@@ -499,11 +629,22 @@ static int mv3310_read_status(struct phy_device *phydev)
+ 	return 0;
+ }
+ 
++static const struct mv3310_chip mv3310_type = {
++	.get_mactype = mv3310_get_mactype,
++	.init_interface = mv3310_init_interface,
++};
++
++static const struct mv3310_chip mv2111_type = {
++	.get_mactype = mv2110_get_mactype,
++	.init_interface = mv2110_init_interface,
++};
++
+ static struct phy_driver mv3310_drivers[] = {
+ 	{
+ 		.phy_id		= MARVELL_PHY_ID_88X3310,
+ 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
+ 		.name		= "mv88x3310",
++		.driver_data	= &mv3310_type,
+ 		.get_features	= mv3310_get_features,
+ 		.soft_reset	= genphy_no_soft_reset,
+ 		.config_init	= mv3310_config_init,
+@@ -513,11 +654,13 @@ static struct phy_driver mv3310_drivers[] = {
  		.config_aneg	= mv3310_config_aneg,
  		.aneg_done	= mv3310_aneg_done,
  		.read_status	= mv3310_read_status,
@@ -1014,7 +1224,13 @@
  	},
  	{
  		.phy_id		= MARVELL_PHY_ID_88E2110,
-@@ -526,6 +521,7 @@ static struct phy_driver mv3310_drivers[] = {
+ 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
+ 		.name		= "mv88x2110",
++		.driver_data	= &mv2111_type,
+ 		.probe		= mv3310_probe,
+ 		.suspend	= mv3310_suspend,
+ 		.resume		= mv3310_resume,
+@@ -526,6 +669,7 @@ static struct phy_driver mv3310_drivers[] = {
  		.config_aneg	= mv3310_config_aneg,
  		.aneg_done	= mv3310_aneg_done,
  		.read_status	= mv3310_read_status,