mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
net: phy: marvell: fix detection of PHY on Topaz switches
commit1fe976d308
upstream. Since commitfee2d54641
("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: Pali Rohár <pali@kernel.org> BugLink: https://github.com/globalscaletechnologies/linux/issues/1 Fixes:fee2d54641
("net: phy: marvell: mv88e6390 temperature sensor reading") Reviewed-by: Marek Behún <kabel@kernel.org> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
fbe6603e7c
commit
6ac98ee9cb
3 changed files with 46 additions and 22 deletions
|
@ -2994,10 +2994,17 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||||
return err;
|
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)
|
static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
|
struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
|
||||||
struct mv88e6xxx_chip *chip = mdio_bus->chip;
|
struct mv88e6xxx_chip *chip = mdio_bus->chip;
|
||||||
|
u16 prod_id;
|
||||||
u16 val;
|
u16 val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -3008,23 +3015,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);
|
err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
|
||||||
mv88e6xxx_reg_unlock(chip);
|
mv88e6xxx_reg_unlock(chip);
|
||||||
|
|
||||||
if (reg == MII_PHYSID2) {
|
/* Some internal PHYs don't have a model number. */
|
||||||
/* Some internal PHYs don't have a model number. */
|
if (reg == MII_PHYSID2 && !(val & 0x3f0) &&
|
||||||
if (chip->info->family != MV88E6XXX_FAMILY_6165)
|
chip->info->family < ARRAY_SIZE(family_prod_id_table)) {
|
||||||
/* Then there is the 6165 family. It gets is
|
prod_id = family_prod_id_table[chip->info->family];
|
||||||
* PHYs correct. But it can also have two
|
if (prod_id)
|
||||||
* SERDES interfaces in the PHY address
|
val |= prod_id >> 4;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err ? err : val;
|
return err ? err : val;
|
||||||
|
|
|
@ -2913,9 +2913,35 @@ static struct phy_driver marvell_drivers[] = {
|
||||||
.get_stats = marvell_get_stats,
|
.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,
|
.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,
|
||||||
|
.ack_interrupt = marvell_ack_interrupt,
|
||||||
|
.config_intr = marvell_config_intr,
|
||||||
|
.did_interrupt = m88e1121_did_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 */
|
/* PHY_GBIT_FEATURES */
|
||||||
.flags = PHY_POLL_CABLE_TEST,
|
.flags = PHY_POLL_CABLE_TEST,
|
||||||
.probe = m88e6390_probe,
|
.probe = m88e6390_probe,
|
||||||
|
@ -3001,7 +3027,8 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
|
||||||
{ MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
|
{ MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
|
||||||
{ MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
|
{ MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
|
||||||
{ MARVELL_PHY_ID_88E3016, 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_88E1340S, MARVELL_PHY_ID_MASK },
|
||||||
{ MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK },
|
{ MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK },
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
#define MARVELL_PHY_ID_88X3310 0x002b09a0
|
#define MARVELL_PHY_ID_88X3310 0x002b09a0
|
||||||
#define MARVELL_PHY_ID_88E2110 0x002b09b0
|
#define MARVELL_PHY_ID_88E2110 0x002b09b0
|
||||||
|
|
||||||
/* 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
|
* not have a model ID. So the switch driver traps reads to the ID2
|
||||||
* register and returns the switch family ID
|
* 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)
|
#define MARVELL_PHY_FAMILY_ID(id) ((id) >> 4)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue