Commit 9ba7ffa6 authored by David S. Miller's avatar David S. Miller

Merge branch 'marvell10g-updates'

Marek Behún says:

====================
net: phy: marvell10g updates

Here are some updates for marvell10g PHY driver.

I am still working on some more changes for this driver, but I would
like to have at least something reviewed / applied.

Changes since v3:
- added Andrew's Reviewed-by tags
- removed patches adding variadic-macro library and bitmap
  initialization macro - it causes warning that we are not currently
  able to fix easily. Instead the supported_interfaces bitmap is now
  initialized via a chip specific method
- added explanation of mactype initialization to commit message of patch
  07/16
- fixed repeated word in commit message of second to last patch

Changes since v2:
- code refactored to use an additional structure mv3310_chip describing
  mv3310 specific properties / operations for PHYs supported by this
  driver
- added separate phy_driver structures for 88X3340 and 88E2111
- removed 88E2180 specific code (dual-port and quad-port SXGMII modes
  are ignored for now)

Changes since v1:
- added various MACTYPEs support also for 88E21XX
- differentiate between specific models with same PHY_ID
- better check for compatible interface
- print exact model
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3cd52c1e 9187b6cf
...@@ -10695,6 +10695,7 @@ F: include/linux/mv643xx.h ...@@ -10695,6 +10695,7 @@ F: include/linux/mv643xx.h
MARVELL MV88X3310 PHY DRIVER MARVELL MV88X3310 PHY DRIVER
M: Russell King <linux@armlinux.org.uk> M: Russell King <linux@armlinux.org.uk>
M: Marek Behun <marek.behun@nic.cz>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/phy/marvell10g.c F: drivers/net/phy/marvell10g.c
......
...@@ -35,6 +35,15 @@ ...@@ -35,6 +35,15 @@
enum { enum {
MV_PMA_FW_VER0 = 0xc011, MV_PMA_FW_VER0 = 0xc011,
MV_PMA_FW_VER1 = 0xc012, MV_PMA_FW_VER1 = 0xc012,
MV_PMA_21X0_PORT_CTRL = 0xc04a,
MV_PMA_21X0_PORT_CTRL_SWRST = BIT(15),
MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK = 0x7,
MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII = 0x0,
MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII = 0x1,
MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII = 0x2,
MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER = 0x4,
MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN = 0x5,
MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
MV_PMA_BOOT = 0xc050, MV_PMA_BOOT = 0xc050,
MV_PMA_BOOT_FATAL = BIT(0), MV_PMA_BOOT_FATAL = BIT(0),
...@@ -78,10 +87,18 @@ enum { ...@@ -78,10 +87,18 @@ enum {
/* Vendor2 MMD registers */ /* Vendor2 MMD registers */
MV_V2_PORT_CTRL = 0xf001, MV_V2_PORT_CTRL = 0xf001,
MV_V2_PORT_CTRL_SWRST = BIT(15),
MV_V2_PORT_CTRL_PWRDOWN = BIT(11), MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
MV_V2_PORT_MAC_TYPE_MASK = 0x7, MV_V2_33X0_PORT_CTRL_SWRST = BIT(15),
MV_V2_PORT_MAC_TYPE_RATE_MATCH = 0x6, MV_V2_33X0_PORT_CTRL_MACTYPE_MASK = 0x7,
MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI = 0x0,
MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH = 0x1,
MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN = 0x1,
MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH = 0x2,
MV_V2_3310_PORT_CTRL_MACTYPE_XAUI = 0x3,
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER = 0x4,
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,
/* Temperature control/read registers (88X3310 only) */ /* Temperature control/read registers (88X3310 only) */
MV_V2_TEMP_CTRL = 0xf08a, MV_V2_TEMP_CTRL = 0xf08a,
MV_V2_TEMP_CTRL_MASK = 0xc000, MV_V2_TEMP_CTRL_MASK = 0xc000,
...@@ -91,14 +108,32 @@ enum { ...@@ -91,14 +108,32 @@ enum {
MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */ MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */
}; };
struct mv3310_chip {
void (*init_supported_interfaces)(unsigned long *mask);
int (*get_mactype)(struct phy_device *phydev);
int (*init_interface)(struct phy_device *phydev, int mactype);
#ifdef CONFIG_HWMON
int (*hwmon_read_temp_reg)(struct phy_device *phydev);
#endif
};
struct mv3310_priv { struct mv3310_priv {
DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
u32 firmware_ver; u32 firmware_ver;
bool rate_match; bool rate_match;
phy_interface_t const_interface;
struct device *hwmon_dev; struct device *hwmon_dev;
char *hwmon_name; char *hwmon_name;
}; };
static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
{
return phydev->drv->driver_data;
}
#ifdef CONFIG_HWMON #ifdef CONFIG_HWMON
static umode_t mv3310_hwmon_is_visible(const void *data, static umode_t mv3310_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type, enum hwmon_sensor_types type,
...@@ -121,18 +156,11 @@ static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev) ...@@ -121,18 +156,11 @@ static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)
return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP); return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);
} }
static int mv10g_hwmon_read_temp_reg(struct phy_device *phydev)
{
if (phydev->drv->phy_id == MARVELL_PHY_ID_88X3310)
return mv3310_hwmon_read_temp_reg(phydev);
else /* MARVELL_PHY_ID_88E2110 */
return mv2110_hwmon_read_temp_reg(phydev);
}
static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type, static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *value) u32 attr, int channel, long *value)
{ {
struct phy_device *phydev = dev_get_drvdata(dev); struct phy_device *phydev = dev_get_drvdata(dev);
const struct mv3310_chip *chip = to_mv3310_chip(phydev);
int temp; int temp;
if (type == hwmon_chip && attr == hwmon_chip_update_interval) { if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
...@@ -141,7 +169,7 @@ static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ...@@ -141,7 +169,7 @@ static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
} }
if (type == hwmon_temp && attr == hwmon_temp_input) { if (type == hwmon_temp && attr == hwmon_temp_input) {
temp = mv10g_hwmon_read_temp_reg(phydev); temp = chip->hwmon_read_temp_reg(phydev);
if (temp < 0) if (temp < 0)
return temp; return temp;
...@@ -268,7 +296,7 @@ static int mv3310_power_up(struct phy_device *phydev) ...@@ -268,7 +296,7 @@ static int mv3310_power_up(struct phy_device *phydev)
return ret; return ret;
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
MV_V2_PORT_CTRL_SWRST); MV_V2_33X0_PORT_CTRL_SWRST);
} }
static int mv3310_reset(struct phy_device *phydev, u32 unit) static int mv3310_reset(struct phy_device *phydev, u32 unit)
...@@ -363,6 +391,7 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = { ...@@ -363,6 +391,7 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = {
static int mv3310_probe(struct phy_device *phydev) static int mv3310_probe(struct phy_device *phydev)
{ {
const struct mv3310_chip *chip = to_mv3310_chip(phydev);
struct mv3310_priv *priv; struct mv3310_priv *priv;
u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
int ret; int ret;
...@@ -412,6 +441,8 @@ static int mv3310_probe(struct phy_device *phydev) ...@@ -412,6 +441,8 @@ static int mv3310_probe(struct phy_device *phydev)
if (ret) if (ret)
return ret; return ret;
chip->init_supported_interfaces(priv->supported_interfaces);
return phy_sfp_probe(phydev, &mv3310_sfp_ops); return phy_sfp_probe(phydev, &mv3310_sfp_ops);
} }
...@@ -453,18 +484,102 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev) ...@@ -453,18 +484,102 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV; MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
} }
static int mv2110_get_mactype(struct phy_device *phydev)
{
int mactype;
mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
if (mactype < 0)
return mactype;
return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
}
static int mv3310_get_mactype(struct phy_device *phydev)
{
int mactype;
mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
if (mactype < 0)
return mactype;
return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
}
static int mv2110_init_interface(struct phy_device *phydev, int mactype)
{
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
priv->rate_match = false;
if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
priv->rate_match = true;
if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII)
priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
priv->const_interface = PHY_INTERFACE_MODE_10GBASER;
else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER ||
mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN)
priv->const_interface = PHY_INTERFACE_MODE_NA;
else
return -EINVAL;
return 0;
}
static int mv3310_init_interface(struct phy_device *phydev, int mactype)
{
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
priv->rate_match = false;
if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
priv->rate_match = true;
if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII)
priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN ||
mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER)
priv->const_interface = PHY_INTERFACE_MODE_10GBASER;
else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI)
priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH ||
mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI)
priv->const_interface = PHY_INTERFACE_MODE_XAUI;
else
return -EINVAL;
return 0;
}
static int mv3340_init_interface(struct phy_device *phydev, int mactype)
{
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
int err = 0;
priv->rate_match = false;
if (mactype == MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
else
err = mv3310_init_interface(phydev, mactype);
return err;
}
static int mv3310_config_init(struct phy_device *phydev) static int mv3310_config_init(struct phy_device *phydev)
{ {
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
int err; const struct mv3310_chip *chip = to_mv3310_chip(phydev);
int val; int err, mactype;
/* Check that the PHY interface type is compatible */ /* Check that the PHY interface type is compatible */
if (phydev->interface != PHY_INTERFACE_MODE_SGMII && if (!test_bit(phydev->interface, priv->supported_interfaces))
phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
phydev->interface != PHY_INTERFACE_MODE_XAUI &&
phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
phydev->interface != PHY_INTERFACE_MODE_10GBASER)
return -ENODEV; return -ENODEV;
phydev->mdix_ctrl = ETH_TP_MDI_AUTO; phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
...@@ -474,11 +589,15 @@ static int mv3310_config_init(struct phy_device *phydev) ...@@ -474,11 +589,15 @@ static int mv3310_config_init(struct phy_device *phydev)
if (err) if (err)
return err; return err;
val = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL); mactype = chip->get_mactype(phydev);
if (val < 0) if (mactype < 0)
return val; return mactype;
priv->rate_match = ((val & MV_V2_PORT_MAC_TYPE_MASK) ==
MV_V2_PORT_MAC_TYPE_RATE_MATCH); err = chip->init_interface(phydev, mactype);
if (err) {
phydev_err(phydev, "MACTYPE configuration invalid\n");
return err;
}
/* Enable EDPD mode - saving 600mW */ /* Enable EDPD mode - saving 600mW */
return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
...@@ -588,28 +707,33 @@ static void mv3310_update_interface(struct phy_device *phydev) ...@@ -588,28 +707,33 @@ static void mv3310_update_interface(struct phy_device *phydev)
{ {
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
/* In "XFI with Rate Matching" mode the PHY interface is fixed at if (!phydev->link)
* 10Gb. The PHY adapts the rate to actual wire speed with help of return;
/* In all of the "* with Rate Matching" modes the PHY interface is fixed
* at 10Gb. The PHY adapts the rate to actual wire speed with help of
* internal 16KB buffer. * internal 16KB buffer.
*
* In USXGMII mode the PHY interface mode is also fixed.
*/ */
if (priv->rate_match) { if (priv->rate_match ||
phydev->interface = PHY_INTERFACE_MODE_10GBASER; priv->const_interface == PHY_INTERFACE_MODE_USXGMII) {
phydev->interface = priv->const_interface;
return; return;
} }
if ((phydev->interface == PHY_INTERFACE_MODE_SGMII || /* The PHY automatically switches its serdes interface (and active PHYXS
phydev->interface == PHY_INTERFACE_MODE_2500BASEX || * instance) between Cisco SGMII, 2500BaseX, 5GBase-R and 10GBase-R /
phydev->interface == PHY_INTERFACE_MODE_10GBASER) && * xaui / rxaui modes according to the speed.
phydev->link) { * Florian suggests setting phydev->interface to communicate this to the
/* The PHY automatically switches its serdes interface (and * MAC. Only do this if we are already in one of the above modes.
* active PHYXS instance) between Cisco SGMII, 10GBase-R and
* 2500BaseX modes according to the speed. Florian suggests
* setting phydev->interface to communicate this to the MAC.
* Only do this if we are already in one of the above modes.
*/ */
switch (phydev->speed) { switch (phydev->speed) {
case SPEED_10000: case SPEED_10000:
phydev->interface = PHY_INTERFACE_MODE_10GBASER; phydev->interface = priv->const_interface;
break;
case SPEED_5000:
phydev->interface = PHY_INTERFACE_MODE_5GBASER;
break; break;
case SPEED_2500: case SPEED_2500:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX; phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
...@@ -622,7 +746,6 @@ static void mv3310_update_interface(struct phy_device *phydev) ...@@ -622,7 +746,6 @@ static void mv3310_update_interface(struct phy_device *phydev)
default: default:
break; break;
} }
}
} }
/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */ /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
...@@ -765,11 +888,115 @@ static int mv3310_set_tunable(struct phy_device *phydev, ...@@ -765,11 +888,115 @@ static int mv3310_set_tunable(struct phy_device *phydev,
} }
} }
static void mv3310_init_supported_interfaces(unsigned long *mask)
{
__set_bit(PHY_INTERFACE_MODE_SGMII, mask);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
__set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_XAUI, mask);
__set_bit(PHY_INTERFACE_MODE_RXAUI, mask);
__set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
}
static void mv3340_init_supported_interfaces(unsigned long *mask)
{
__set_bit(PHY_INTERFACE_MODE_SGMII, mask);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
__set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_RXAUI, mask);
__set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
}
static void mv2110_init_supported_interfaces(unsigned long *mask)
{
__set_bit(PHY_INTERFACE_MODE_SGMII, mask);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
__set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
}
static void mv2111_init_supported_interfaces(unsigned long *mask)
{
__set_bit(PHY_INTERFACE_MODE_SGMII, mask);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
__set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
__set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
}
static const struct mv3310_chip mv3310_type = {
.init_supported_interfaces = mv3310_init_supported_interfaces,
.get_mactype = mv3310_get_mactype,
.init_interface = mv3310_init_interface,
#ifdef CONFIG_HWMON
.hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,
#endif
};
static const struct mv3310_chip mv3340_type = {
.init_supported_interfaces = mv3340_init_supported_interfaces,
.get_mactype = mv3310_get_mactype,
.init_interface = mv3340_init_interface,
#ifdef CONFIG_HWMON
.hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,
#endif
};
static const struct mv3310_chip mv2110_type = {
.init_supported_interfaces = mv2110_init_supported_interfaces,
.get_mactype = mv2110_get_mactype,
.init_interface = mv2110_init_interface,
#ifdef CONFIG_HWMON
.hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,
#endif
};
static const struct mv3310_chip mv2111_type = {
.init_supported_interfaces = mv2111_init_supported_interfaces,
.get_mactype = mv2110_get_mactype,
.init_interface = mv2110_init_interface,
#ifdef CONFIG_HWMON
.hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,
#endif
};
static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
{
int val;
if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
return 0;
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
if (val < 0)
return val;
return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
}
static int mv2110_match_phy_device(struct phy_device *phydev)
{
return mv211x_match_phy_device(phydev, true);
}
static int mv2111_match_phy_device(struct phy_device *phydev)
{
return mv211x_match_phy_device(phydev, false);
}
static struct phy_driver mv3310_drivers[] = { static struct phy_driver mv3310_drivers[] = {
{ {
.phy_id = MARVELL_PHY_ID_88X3310, .phy_id = MARVELL_PHY_ID_88X3310,
.phy_id_mask = MARVELL_PHY_ID_MASK, .phy_id_mask = MARVELL_PHY_ID_88X33X0_MASK,
.name = "mv88x3310", .name = "mv88x3310",
.driver_data = &mv3310_type,
.get_features = mv3310_get_features, .get_features = mv3310_get_features,
.config_init = mv3310_config_init, .config_init = mv3310_config_init,
.probe = mv3310_probe, .probe = mv3310_probe,
...@@ -783,10 +1010,48 @@ static struct phy_driver mv3310_drivers[] = { ...@@ -783,10 +1010,48 @@ static struct phy_driver mv3310_drivers[] = {
.remove = mv3310_remove, .remove = mv3310_remove,
.set_loopback = genphy_c45_loopback, .set_loopback = genphy_c45_loopback,
}, },
{
.phy_id = MARVELL_PHY_ID_88X3340,
.phy_id_mask = MARVELL_PHY_ID_88X33X0_MASK,
.name = "mv88x3340",
.driver_data = &mv3340_type,
.get_features = mv3310_get_features,
.config_init = mv3310_config_init,
.probe = mv3310_probe,
.suspend = mv3310_suspend,
.resume = mv3310_resume,
.config_aneg = mv3310_config_aneg,
.aneg_done = mv3310_aneg_done,
.read_status = mv3310_read_status,
.get_tunable = mv3310_get_tunable,
.set_tunable = mv3310_set_tunable,
.remove = mv3310_remove,
.set_loopback = genphy_c45_loopback,
},
{
.phy_id = MARVELL_PHY_ID_88E2110,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.match_phy_device = mv2110_match_phy_device,
.name = "mv88e2110",
.driver_data = &mv2110_type,
.probe = mv3310_probe,
.suspend = mv3310_suspend,
.resume = mv3310_resume,
.config_init = mv3310_config_init,
.config_aneg = mv3310_config_aneg,
.aneg_done = mv3310_aneg_done,
.read_status = mv3310_read_status,
.get_tunable = mv3310_get_tunable,
.set_tunable = mv3310_set_tunable,
.remove = mv3310_remove,
.set_loopback = genphy_c45_loopback,
},
{ {
.phy_id = MARVELL_PHY_ID_88E2110, .phy_id = MARVELL_PHY_ID_88E2110,
.phy_id_mask = MARVELL_PHY_ID_MASK, .phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "mv88x2110", .match_phy_device = mv2111_match_phy_device,
.name = "mv88e2111",
.driver_data = &mv2111_type,
.probe = mv3310_probe, .probe = mv3310_probe,
.suspend = mv3310_suspend, .suspend = mv3310_suspend,
.resume = mv3310_resume, .resume = mv3310_resume,
...@@ -804,10 +1069,11 @@ static struct phy_driver mv3310_drivers[] = { ...@@ -804,10 +1069,11 @@ static struct phy_driver mv3310_drivers[] = {
module_phy_driver(mv3310_drivers); module_phy_driver(mv3310_drivers);
static struct mdio_device_id __maybe_unused mv3310_tbl[] = { static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
{ MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_88X33X0_MASK },
{ MARVELL_PHY_ID_88X3340, MARVELL_PHY_ID_88X33X0_MASK },
{ MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
{ }, { },
}; };
MODULE_DEVICE_TABLE(mdio, mv3310_tbl); MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)"); MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -22,10 +22,14 @@ ...@@ -22,10 +22,14 @@
#define MARVELL_PHY_ID_88E1545 0x01410ea0 #define MARVELL_PHY_ID_88E1545 0x01410ea0
#define MARVELL_PHY_ID_88E1548P 0x01410ec0 #define MARVELL_PHY_ID_88E1548P 0x01410ec0
#define MARVELL_PHY_ID_88E3016 0x01410e60 #define MARVELL_PHY_ID_88E3016 0x01410e60
#define MARVELL_PHY_ID_88X3310 0x002b09a0
#define MARVELL_PHY_ID_88E2110 0x002b09b0 #define MARVELL_PHY_ID_88E2110 0x002b09b0
#define MARVELL_PHY_ID_88X2222 0x01410f10 #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 */ /* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
#define MARVELL_PHY_ID_88E1111_FINISAR 0x01ff0cc0 #define MARVELL_PHY_ID_88E1111_FINISAR 0x01ff0cc0
......
...@@ -120,6 +120,8 @@ ...@@ -120,6 +120,8 @@
#define MDIO_PMA_SPEED_100 0x0020 /* 100M capable */ #define MDIO_PMA_SPEED_100 0x0020 /* 100M capable */
#define MDIO_PMA_SPEED_10 0x0040 /* 10M capable */ #define MDIO_PMA_SPEED_10 0x0040 /* 10M capable */
#define MDIO_PCS_SPEED_10P2B 0x0002 /* 10PASS-TS/2BASE-TL capable */ #define MDIO_PCS_SPEED_10P2B 0x0002 /* 10PASS-TS/2BASE-TL capable */
#define MDIO_PCS_SPEED_2_5G 0x0040 /* 2.5G capable */
#define MDIO_PCS_SPEED_5G 0x0080 /* 5G capable */
/* Device present registers. */ /* Device present registers. */
#define MDIO_DEVS_PRESENT(devad) (1 << (devad)) #define MDIO_DEVS_PRESENT(devad) (1 << (devad))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment