Commit ab1dfcb5 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski
Browse files

net: phy: aquantia: fill supported_interfaces for all aqr_gen2_config_init() callers



Since aqr_gen2_config_init() and aqr_gen2_fill_interface_modes() refer to
the feature set common to the same generation, it means all callers of
aqr_gen2_config_init() also support the Global System Configuration
registers at addresses 1E.31B -> 1E.31F, and these should be read by the
driver to figure out the list of supported interfaces for phylink.

This affects the following PHYs supported by this driver:
- Gen2: AQR107
- Gen3: AQR111, AQR111B0
- Gen4: AQR114C, AQR813.

AQR113C, a Gen4 PHY, has unmodified logic after this change, because
currently, the aqr_gen2_fill_interface_modes() call is chained after
aqr_gen2_config_init(), and after this patch, it is tail-called from the
latter function, leading to the same code flow.

At the same time, move aqr_gen2_fill_interface_modes() upwards of its
new caller, aqr_gen2_config_init(), to avoid a forward declaration.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20250821152022.1065237-6-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 9731bcf2
Loading
Loading
Loading
Loading
+85 −83
Original line number Diff line number Diff line
@@ -860,9 +860,93 @@ static int aqr_gen1_config_init(struct phy_device *phydev)
	return 0;
}

static const u16 aqr_global_cfg_regs[] = {
	VEND1_GLOBAL_CFG_10M,
	VEND1_GLOBAL_CFG_100M,
	VEND1_GLOBAL_CFG_1G,
	VEND1_GLOBAL_CFG_2_5G,
	VEND1_GLOBAL_CFG_5G,
	VEND1_GLOBAL_CFG_10G,
};

static int aqr_gen2_fill_interface_modes(struct phy_device *phydev)
{
	unsigned long *possible = phydev->possible_interfaces;
	struct aqr107_priv *priv = phydev->priv;
	unsigned int serdes_mode, rate_adapt;
	phy_interface_t interface;
	int i, val, ret;

	/* It's been observed on some models that - when coming out of suspend
	 * - the FW signals that the PHY is ready but the GLOBAL_CFG registers
	 * continue on returning zeroes for some time. Let's poll the 100M
	 * register until it returns a real value as both 113c and 115c support
	 * this mode.
	 */
	if (priv->wait_on_global_cfg) {
		ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
						VEND1_GLOBAL_CFG_100M, val,
						val != 0, 1000, 100000, false);
		if (ret)
			return ret;
	}

	/* Walk the media-speed configuration registers to determine which
	 * host-side serdes modes may be used by the PHY depending on the
	 * negotiated media speed.
	 */
	for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) {
		val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
				   aqr_global_cfg_regs[i]);
		if (val < 0)
			return val;

		serdes_mode = FIELD_GET(VEND1_GLOBAL_CFG_SERDES_MODE, val);
		rate_adapt = FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val);

		switch (serdes_mode) {
		case VEND1_GLOBAL_CFG_SERDES_MODE_XFI:
			if (rate_adapt == VEND1_GLOBAL_CFG_RATE_ADAPT_USX)
				interface = PHY_INTERFACE_MODE_USXGMII;
			else
				interface = PHY_INTERFACE_MODE_10GBASER;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G:
			interface = PHY_INTERFACE_MODE_5GBASER;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII:
			interface = PHY_INTERFACE_MODE_2500BASEX;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_SGMII:
			interface = PHY_INTERFACE_MODE_SGMII;
			break;

		default:
			phydev_warn(phydev, "unrecognised serdes mode %u\n",
				    serdes_mode);
			interface = PHY_INTERFACE_MODE_NA;
			break;
		}

		if (interface != PHY_INTERFACE_MODE_NA)
			__set_bit(interface, possible);
	}

	return 0;
}

static int aqr_gen2_config_init(struct phy_device *phydev)
{
	return aqr_gen1_config_init(phydev);
	int ret;

	ret = aqr_gen1_config_init(phydev);
	if (ret)
		return ret;

	return aqr_gen2_fill_interface_modes(phydev);
}

static int aqcs109_config_init(struct phy_device *phydev)
@@ -984,84 +1068,6 @@ static int aqr_gen1_resume(struct phy_device *phydev)
	return aqr_gen1_wait_processor_intensive_op(phydev);
}

static const u16 aqr_global_cfg_regs[] = {
	VEND1_GLOBAL_CFG_10M,
	VEND1_GLOBAL_CFG_100M,
	VEND1_GLOBAL_CFG_1G,
	VEND1_GLOBAL_CFG_2_5G,
	VEND1_GLOBAL_CFG_5G,
	VEND1_GLOBAL_CFG_10G
};

static int aqr_gen2_fill_interface_modes(struct phy_device *phydev)
{
	unsigned long *possible = phydev->possible_interfaces;
	struct aqr107_priv *priv = phydev->priv;
	unsigned int serdes_mode, rate_adapt;
	phy_interface_t interface;
	int i, val, ret;

	/* It's been observed on some models that - when coming out of suspend
	 * - the FW signals that the PHY is ready but the GLOBAL_CFG registers
	 * continue on returning zeroes for some time. Let's poll the 100M
	 * register until it returns a real value as both 113c and 115c support
	 * this mode.
	 */
	if (priv->wait_on_global_cfg) {
		ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
						VEND1_GLOBAL_CFG_100M, val,
						val != 0, 1000, 100000, false);
		if (ret)
			return ret;
	}

	/* Walk the media-speed configuration registers to determine which
	 * host-side serdes modes may be used by the PHY depending on the
	 * negotiated media speed.
	 */
	for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) {
		val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
				   aqr_global_cfg_regs[i]);
		if (val < 0)
			return val;

		serdes_mode = FIELD_GET(VEND1_GLOBAL_CFG_SERDES_MODE, val);
		rate_adapt = FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val);

		switch (serdes_mode) {
		case VEND1_GLOBAL_CFG_SERDES_MODE_XFI:
			if (rate_adapt == VEND1_GLOBAL_CFG_RATE_ADAPT_USX)
				interface = PHY_INTERFACE_MODE_USXGMII;
			else
				interface = PHY_INTERFACE_MODE_10GBASER;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G:
			interface = PHY_INTERFACE_MODE_5GBASER;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII:
			interface = PHY_INTERFACE_MODE_2500BASEX;
			break;

		case VEND1_GLOBAL_CFG_SERDES_MODE_SGMII:
			interface = PHY_INTERFACE_MODE_SGMII;
			break;

		default:
			phydev_warn(phydev, "unrecognised serdes mode %u\n",
				    serdes_mode);
			interface = PHY_INTERFACE_MODE_NA;
			break;
		}

		if (interface != PHY_INTERFACE_MODE_NA)
			__set_bit(interface, possible);
	}

	return 0;
}

static int aqr115c_get_features(struct phy_device *phydev)
{
	unsigned long *supported = phydev->supported;
@@ -1098,10 +1104,6 @@ static int aqr113c_config_init(struct phy_device *phydev)
	if (ret < 0)
		return ret;

	ret = aqr_gen2_fill_interface_modes(phydev);
	if (ret)
		return ret;

	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
				 MDIO_PMD_TXDIS_GLOBAL);
	if (ret)