Commit a5de4be0 authored by Marek Behún's avatar Marek Behún Committed by David S. Miller
Browse files

net: phy: marvell10g: fix differentiation of 88X3310 from 88X3340



It seems that we cannot differentiate 88X3310 from 88X3340 by simply
looking at bit 3 of revision ID. This only works on revisions A0 and A1.
On revision B0, this bit is always 1.

Instead use the 3.d00d register for differentiation, since this register
contains information about number of ports on the device.

Fixes: 9885d016 ("net: phy: marvell10g: add separate structure for 88X3340")
Signed-off-by: default avatarMarek Behún <kabel@kernel.org>
Reported-by: default avatarMatteo Croce <mcroce@linux.microsoft.com>
Tested-by: default avatarMatteo Croce <mcroce@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 84f7e0bb
Loading
Loading
Loading
Loading
+35 −5
Original line number Diff line number Diff line
@@ -78,6 +78,11 @@ enum {
	/* Temperature read register (88E2110 only) */
	MV_PCS_TEMP		= 0x8042,

	/* Number of ports on the device */
	MV_PCS_PORT_INFO	= 0xd00d,
	MV_PCS_PORT_INFO_NPORTS_MASK	= 0x0380,
	MV_PCS_PORT_INFO_NPORTS_SHIFT	= 7,

	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
	 * registers appear to set themselves to the 0x800X when AN is
	 * restarted, but status registers appear readable from either.
@@ -966,6 +971,30 @@ static const struct mv3310_chip mv2111_type = {
#endif
};

static int mv3310_get_number_of_ports(struct phy_device *phydev)
{
	int ret;

	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
	if (ret < 0)
		return ret;

	ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
	ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;

	return ret + 1;
}

static int mv3310_match_phy_device(struct phy_device *phydev)
{
	return mv3310_get_number_of_ports(phydev) == 1;
}

static int mv3340_match_phy_device(struct phy_device *phydev)
{
	return mv3310_get_number_of_ports(phydev) == 4;
}

static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
{
	int val;
@@ -994,7 +1023,8 @@ static int mv2111_match_phy_device(struct phy_device *phydev)
static struct phy_driver mv3310_drivers[] = {
	{
		.phy_id		= MARVELL_PHY_ID_88X3310,
		.phy_id_mask	= MARVELL_PHY_ID_88X33X0_MASK,
		.phy_id_mask	= MARVELL_PHY_ID_MASK,
		.match_phy_device = mv3310_match_phy_device,
		.name		= "mv88x3310",
		.driver_data	= &mv3310_type,
		.get_features	= mv3310_get_features,
@@ -1011,8 +1041,9 @@ static struct phy_driver mv3310_drivers[] = {
		.set_loopback	= genphy_c45_loopback,
	},
	{
		.phy_id		= MARVELL_PHY_ID_88X3340,
		.phy_id_mask	= MARVELL_PHY_ID_88X33X0_MASK,
		.phy_id		= MARVELL_PHY_ID_88X3310,
		.phy_id_mask	= MARVELL_PHY_ID_MASK,
		.match_phy_device = mv3340_match_phy_device,
		.name		= "mv88x3340",
		.driver_data	= &mv3340_type,
		.get_features	= mv3310_get_features,
@@ -1069,8 +1100,7 @@ static struct phy_driver mv3310_drivers[] = {
module_phy_driver(mv3310_drivers);

static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
	{ MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_88X33X0_MASK },
	{ MARVELL_PHY_ID_88X3340, MARVELL_PHY_ID_88X33X0_MASK },
	{ MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
	{ },
};
+1 −5
Original line number Diff line number Diff line
@@ -22,14 +22,10 @@
#define MARVELL_PHY_ID_88E1545		0x01410ea0
#define MARVELL_PHY_ID_88E1548P		0x01410ec0
#define MARVELL_PHY_ID_88E3016		0x01410e60
#define MARVELL_PHY_ID_88X3310		0x002b09a0
#define MARVELL_PHY_ID_88E2110		0x002b09b0
#define MARVELL_PHY_ID_88X2222		0x01410f10

/* PHY IDs and mask for Alaska 10G PHYs */
#define MARVELL_PHY_ID_88X33X0_MASK	0xfffffff8
#define MARVELL_PHY_ID_88X3310		0x002b09a0
#define MARVELL_PHY_ID_88X3340		0x002b09a8

/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
#define MARVELL_PHY_ID_88E1111_FINISAR	0x01ff0cc0