Commit 1fe976d3 authored by Pali Rohár's avatar Pali Rohár Committed by David S. Miller
Browse files

net: phy: marvell: fix detection of PHY on Topaz switches



Since commit fee2d546 ("net: phy: marvell: mv88e6390 temperature
sensor reading"), Linux reports the temperature of Topaz hwmon as
constant -75°C.

This is because switches from the Topaz family (88E6141 / 88E6341) have
the address of the temperature sensor register different from Peridot.

This address is instead compatible with 88E1510 PHYs, as was used for
Topaz before the above mentioned commit.

Create a new mapping table between switch family and PHY ID for families
which don't have a model number. And define PHY IDs for Topaz and Peridot
families.

Create a new PHY ID and a new PHY driver for Topaz's internal PHY.
The only difference from Peridot's PHY driver is the HWMON probing
method.

Prior this change Topaz's internal PHY is detected by kernel as:

  PHY [...] driver [Marvell 88E6390] (irq=63)

And afterwards as:

  PHY [...] driver [Marvell 88E6341 Family] (irq=63)

Signed-off-by: default avatarPali Rohár <pali@kernel.org>
BugLink: https://github.com/globalscaletechnologies/linux/issues/1


Fixes: fee2d546 ("net: phy: marvell: mv88e6390 temperature sensor reading")
Reviewed-by: default avatarMarek Behún <kabel@kernel.org>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6628ddfe
Loading
Loading
Loading
Loading
+13 −17
Original line number Diff line number Diff line
@@ -3026,10 +3026,17 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
	return err;
}

/* prod_id for switch families which do not have a PHY model number */
static const u16 family_prod_id_table[] = {
	[MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
	[MV88E6XXX_FAMILY_6390] = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
};

static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
{
	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
	struct mv88e6xxx_chip *chip = mdio_bus->chip;
	u16 prod_id;
	u16 val;
	int err;

@@ -3040,23 +3047,12 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
	err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
	mv88e6xxx_reg_unlock(chip);

	if (reg == MII_PHYSID2) {
	/* Some internal PHYs don't have a model number. */
		if (chip->info->family != MV88E6XXX_FAMILY_6165)
			/* Then there is the 6165 family. It gets is
			 * PHYs correct. But it can also have two
			 * SERDES interfaces in the PHY address
			 * space. And these don't have a model
			 * number. But they are not PHYs, so we don't
			 * want to give them something a PHY driver
			 * will recognise.
			 *
			 * Use the mv88e6390 family model number
			 * instead, for anything which really could be
			 * a PHY,
			 */
			if (!(val & 0x3f0))
				val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
	if (reg == MII_PHYSID2 && !(val & 0x3f0) &&
	    chip->info->family < ARRAY_SIZE(family_prod_id_table)) {
		prod_id = family_prod_id_table[chip->info->family];
		if (prod_id)
			val |= prod_id >> 4;
	}

	return err ? err : val;
+29 −3
Original line number Diff line number Diff line
@@ -3021,9 +3021,34 @@ static struct phy_driver marvell_drivers[] = {
		.get_stats = marvell_get_stats,
	},
	{
		.phy_id = MARVELL_PHY_ID_88E6390,
		.phy_id = MARVELL_PHY_ID_88E6341_FAMILY,
		.phy_id_mask = MARVELL_PHY_ID_MASK,
		.name = "Marvell 88E6390",
		.name = "Marvell 88E6341 Family",
		/* PHY_GBIT_FEATURES */
		.flags = PHY_POLL_CABLE_TEST,
		.probe = m88e1510_probe,
		.config_init = marvell_config_init,
		.config_aneg = m88e6390_config_aneg,
		.read_status = marvell_read_status,
		.config_intr = marvell_config_intr,
		.handle_interrupt = marvell_handle_interrupt,
		.resume = genphy_resume,
		.suspend = genphy_suspend,
		.read_page = marvell_read_page,
		.write_page = marvell_write_page,
		.get_sset_count = marvell_get_sset_count,
		.get_strings = marvell_get_strings,
		.get_stats = marvell_get_stats,
		.get_tunable = m88e1540_get_tunable,
		.set_tunable = m88e1540_set_tunable,
		.cable_test_start = marvell_vct7_cable_test_start,
		.cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
		.cable_test_get_status = marvell_vct7_cable_test_get_status,
	},
	{
		.phy_id = MARVELL_PHY_ID_88E6390_FAMILY,
		.phy_id_mask = MARVELL_PHY_ID_MASK,
		.name = "Marvell 88E6390 Family",
		/* PHY_GBIT_FEATURES */
		.flags = PHY_POLL_CABLE_TEST,
		.probe = m88e6390_probe,
@@ -3107,7 +3132,8 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
	{ MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E1340S, MARVELL_PHY_ID_MASK },
	{ MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK },
	{ }
+3 −2
Original line number Diff line number Diff line
@@ -28,11 +28,12 @@
/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
#define MARVELL_PHY_ID_88E1111_FINISAR	0x01ff0cc0

/* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do
/* These Ethernet switch families contain embedded PHYs, but they do
 * not have a model ID. So the switch driver traps reads to the ID2
 * register and returns the switch family ID
 */
#define MARVELL_PHY_ID_88E6390		0x01410f90
#define MARVELL_PHY_ID_88E6341_FAMILY	0x01410f41
#define MARVELL_PHY_ID_88E6390_FAMILY	0x01410f90

#define MARVELL_PHY_FAMILY_ID(id)	((id) >> 4)