Commit 1db85870 authored by Michael Walle's avatar Michael Walle Committed by David S. Miller
Browse files

net: phy: mxl-gpy: cache PHY firmware version



Cache the firmware version during probe. There is no need to read the
firmware version on every autonegotiation.

Signed-off-by: default avatarMichael Walle <michael@walle.cc>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fc3dd036
Loading
Loading
Loading
Loading
+20 −19
Original line number Diff line number Diff line
@@ -77,6 +77,11 @@
#define VPSPEC2_WOL_AD45	0x0E0A
#define WOL_EN			BIT(0)

struct gpy_priv {
	u8 fw_type;
	u8 fw_minor;
};

static const struct {
	int type;
	int minor;
@@ -198,6 +203,8 @@ static int gpy_config_init(struct phy_device *phydev)

static int gpy_probe(struct phy_device *phydev)
{
	struct device *dev = &phydev->mdio.dev;
	struct gpy_priv *priv;
	int fw_version;
	int ret;

@@ -207,15 +214,22 @@ static int gpy_probe(struct phy_device *phydev)
			return ret;
	}

	/* Show GPY PHY FW version in dmesg */
	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	phydev->priv = priv;

	fw_version = phy_read(phydev, PHY_FWV);
	if (fw_version < 0)
		return fw_version;
	priv->fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_version);
	priv->fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_version);

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

	/* Show GPY PHY FW version in dmesg */
	phydev_info(phydev, "Firmware Version: 0x%04X (%s)\n", fw_version,
		    (fw_version & PHY_FWV_REL_MASK) ? "release" : "test");

@@ -224,20 +238,13 @@ static int gpy_probe(struct phy_device *phydev)

static bool gpy_sgmii_need_reaneg(struct phy_device *phydev)
{
	int fw_ver, fw_type, fw_minor;
	struct gpy_priv *priv = phydev->priv;
	size_t i;

	fw_ver = phy_read(phydev, PHY_FWV);
	if (fw_ver < 0)
		return true;

	fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_ver);
	fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_ver);

	for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) {
		if (fw_type != ver_need_sgmii_reaneg[i].type)
		if (priv->fw_type != ver_need_sgmii_reaneg[i].type)
			continue;
		if (fw_minor < ver_need_sgmii_reaneg[i].minor)
		if (priv->fw_minor < ver_need_sgmii_reaneg[i].minor)
			return true;
		break;
	}
@@ -605,18 +612,12 @@ static int gpy_loopback(struct phy_device *phydev, bool enable)

static int gpy115_loopback(struct phy_device *phydev, bool enable)
{
	int ret;
	int fw_minor;
	struct gpy_priv *priv = phydev->priv;

	if (enable)
		return gpy_loopback(phydev, enable);

	ret = phy_read(phydev, PHY_FWV);
	if (ret < 0)
		return ret;

	fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, ret);
	if (fw_minor > 0x0076)
	if (priv->fw_minor > 0x76)
		return gpy_loopback(phydev, 0);

	return genphy_soft_reset(phydev);