Commit d4b242a7 authored by David S. Miller's avatar David S. Miller

Merge branch 'phy-25g'

Maxime Chevallier says:

====================
net: phy: Add 2.5G/5GBASET PHYs support

The 802.3bz standard defines 2 modes based on the NBASET alliance work
that allow to use 2.5Gbps and 5Gbps speeds on Cat 5e, 6 and 7 cables.

This series adds the necessary infrastructure to handle these modes with
C45 PHYs. This series was originally part of a bigger one, that has
seen 2 iterations [1] [2] that added support for these modes on Marvell
Alaska PHYs.

Following some discussions with Heiner and Andrew [3], we decided to
split-out the generic parts so that we can work together on the
following steps to get these mode fully working with Aquantia and
Marvell PHYS.

The first 3 patches are reworking some of the internal network phy
infrastructure to handle the new modes in a more generic way.

The 4th patch adds all the C45 register definition and accesses that
follows the 802.3bz standard to support 2.5GBASET and 5GBASET.

[1] : https://lore.kernel.org/netdev/20190118152352.26417-1-maxime.chevallier@bootlin.com/
[2] : https://lore.kernel.org/netdev/20190207094939.27369-1-maxime.chevallier@bootlin.com/
[3] : https://lore.kernel.org/netdev/81c340ea-54b0-1abf-94af-b8dc4ee83e3a@gmail.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d2d37444 7fd8afa8
......@@ -233,8 +233,7 @@ static int mv3310_resume(struct phy_device *phydev)
static int mv3310_config_init(struct phy_device *phydev)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
int val;
int ret, val;
/* Check that the PHY interface type is compatible */
if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
......@@ -243,8 +242,8 @@ static int mv3310_config_init(struct phy_device *phydev)
phydev->interface != PHY_INTERFACE_MODE_10GKR)
return -ENODEV;
__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported);
__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported);
if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
......@@ -252,74 +251,13 @@ static int mv3310_config_init(struct phy_device *phydev)
return val;
if (val & MDIO_AN_STAT1_ABLE)
__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->supported);
}
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
if (val < 0)
return val;
/* Ethtool does not support the WAN mode bits */
if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
MDIO_PMA_STAT2_10GBEW))
__set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
if (val & MDIO_PMA_STAT2_10GBSR)
__set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
if (val & MDIO_PMA_STAT2_10GBLR)
__set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
if (val & MDIO_PMA_STAT2_10GBER)
__set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
if (val & MDIO_PMA_STAT2_EXTABLE) {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
if (val < 0)
return val;
if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
__set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
if (val & MDIO_PMA_EXTABLE_10GBLRM)
__set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
MDIO_PMA_EXTABLE_1000BKX))
__set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
if (val & MDIO_PMA_EXTABLE_10GBLRM)
__set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_10GBT)
__set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_10GBKX4)
__set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_10GBKR)
__set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_1000BT)
__set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_1000BKX)
__set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
supported);
if (val & MDIO_PMA_EXTABLE_100BTX) {
__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
supported);
__set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
supported);
}
if (val & MDIO_PMA_EXTABLE_10BT) {
__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
supported);
__set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
supported);
}
}
linkmode_copy(phydev->supported, supported);
linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported);
ret = genphy_c45_pma_read_abilities(phydev);
if (ret)
return ret;
return 0;
}
......
......@@ -47,6 +47,16 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev)
/* Assume 1000base-T */
ctrl2 |= MDIO_PMA_CTRL2_1000BT;
break;
case SPEED_2500:
ctrl1 |= MDIO_CTRL1_SPEED2_5G;
/* Assume 2.5Gbase-T */
ctrl2 |= MDIO_PMA_CTRL2_2_5GBT;
break;
case SPEED_5000:
ctrl1 |= MDIO_CTRL1_SPEED5G;
/* Assume 5Gbase-T */
ctrl2 |= MDIO_PMA_CTRL2_5GBT;
break;
case SPEED_10000:
ctrl1 |= MDIO_CTRL1_SPEED10G;
/* Assume 10Gbase-T */
......@@ -194,6 +204,12 @@ int genphy_c45_read_lpa(struct phy_device *phydev)
if (val < 0)
return val;
if (val & MDIO_AN_10GBT_STAT_LP2_5G)
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->lp_advertising);
if (val & MDIO_AN_10GBT_STAT_LP5G)
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->lp_advertising);
if (val & MDIO_AN_10GBT_STAT_LP10G)
linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
phydev->lp_advertising);
......@@ -224,6 +240,12 @@ int genphy_c45_read_pma(struct phy_device *phydev)
case MDIO_PMA_CTRL1_SPEED1000:
phydev->speed = SPEED_1000;
break;
case MDIO_CTRL1_SPEED2_5G:
phydev->speed = SPEED_2500;
break;
case MDIO_CTRL1_SPEED5G:
phydev->speed = SPEED_5000;
break;
case MDIO_CTRL1_SPEED10G:
phydev->speed = SPEED_10000;
break;
......@@ -271,6 +293,95 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
/**
* genphy_c45_pma_read_abilities - read supported link modes from PMA
* @phydev: target phy_device struct
*
* Read the supported link modes from the PMA Status 2 (1.8) register. If bit
* 1.8.9 is set, the list of supported modes is build using the values in the
* PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related
* modes. If bit 1.11.14 is set, then the list is also extended with the modes
* in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and
* 5GBASET are supported.
*/
int genphy_c45_pma_read_abilities(struct phy_device *phydev)
{
int val;
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
if (val < 0)
return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBSR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBLR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBER);
if (val & MDIO_PMA_STAT2_EXTABLE) {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
if (val < 0)
return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBLRM);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBKX4);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBKR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_1000BT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_1000BKX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_100BTX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_100BTX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10BT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10BT);
if (val & MDIO_PMA_EXTABLE_NBT) {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
MDIO_PMA_NG_EXTABLE);
if (val < 0)
return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_NG_EXTABLE_2_5GBT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_NG_EXTABLE_5GBT);
}
}
return 0;
}
EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
/* The gen10g_* functions are the old Clause 45 stub */
int gen10g_config_aneg(struct phy_device *phydev)
......
......@@ -4,6 +4,7 @@
*/
#include <linux/export.h>
#include <linux/phy.h>
#include <linux/of.h>
const char *phy_speed_to_str(int speed)
{
......@@ -338,6 +339,77 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
return count;
}
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
{
const struct phy_setting *p;
int i;
for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
if (p->speed > max_speed)
linkmode_clear_bit(p->bit, phydev->supported);
else
break;
}
return 0;
}
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
{
int err;
err = __set_phy_supported(phydev, max_speed);
if (err)
return err;
linkmode_copy(phydev->advertising, phydev->supported);
return 0;
}
EXPORT_SYMBOL(phy_set_max_speed);
void of_set_phy_supported(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
u32 max_speed;
if (!IS_ENABLED(CONFIG_OF_MDIO))
return;
if (!node)
return;
if (!of_property_read_u32(node, "max-speed", &max_speed))
__set_phy_supported(phydev, max_speed);
}
void of_set_phy_eee_broken(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
u32 broken = 0;
if (!IS_ENABLED(CONFIG_OF_MDIO))
return;
if (!node)
return;
if (of_property_read_bool(node, "eee-broken-100tx"))
broken |= MDIO_EEE_100TX;
if (of_property_read_bool(node, "eee-broken-1000t"))
broken |= MDIO_EEE_1000T;
if (of_property_read_bool(node, "eee-broken-10gt"))
broken |= MDIO_EEE_10GT;
if (of_property_read_bool(node, "eee-broken-1000kx"))
broken |= MDIO_EEE_1000KX;
if (of_property_read_bool(node, "eee-broken-10gkx4"))
broken |= MDIO_EEE_10GKX4;
if (of_property_read_bool(node, "eee-broken-10gkr"))
broken |= MDIO_EEE_10GKR;
phydev->eee_broken_modes = broken;
}
/**
* phy_resolve_aneg_linkmode - resolve the advertisements into phy settings
* @phydev: The phy_device struct
......
......@@ -30,7 +30,6 @@
#include <linux/mdio.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/of.h>
MODULE_DESCRIPTION("PHY library");
MODULE_AUTHOR("Andy Fleming");
......@@ -1949,44 +1948,6 @@ int genphy_loopback(struct phy_device *phydev, bool enable)
}
EXPORT_SYMBOL(genphy_loopback);
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
{
switch (max_speed) {
case SPEED_10:
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
phydev->supported);
linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
phydev->supported);
/* fall through */
case SPEED_100:
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported);
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported);
break;
case SPEED_1000:
break;
default:
return -ENOTSUPP;
}
return 0;
}
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
{
int err;
err = __set_phy_supported(phydev, max_speed);
if (err)
return err;
linkmode_copy(phydev->advertising, phydev->supported);
return 0;
}
EXPORT_SYMBOL(phy_set_max_speed);
/**
* phy_remove_link_mode - Remove a supported link mode
* @phydev: phy_device structure to remove link mode from
......@@ -2117,48 +2078,6 @@ bool phy_validate_pause(struct phy_device *phydev,
}
EXPORT_SYMBOL(phy_validate_pause);
static void of_set_phy_supported(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
u32 max_speed;
if (!IS_ENABLED(CONFIG_OF_MDIO))
return;
if (!node)
return;
if (!of_property_read_u32(node, "max-speed", &max_speed))
__set_phy_supported(phydev, max_speed);
}
static void of_set_phy_eee_broken(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
u32 broken = 0;
if (!IS_ENABLED(CONFIG_OF_MDIO))
return;
if (!node)
return;
if (of_property_read_bool(node, "eee-broken-100tx"))
broken |= MDIO_EEE_100TX;
if (of_property_read_bool(node, "eee-broken-1000t"))
broken |= MDIO_EEE_1000T;
if (of_property_read_bool(node, "eee-broken-10gt"))
broken |= MDIO_EEE_10GT;
if (of_property_read_bool(node, "eee-broken-1000kx"))
broken |= MDIO_EEE_1000KX;
if (of_property_read_bool(node, "eee-broken-10gkx4"))
broken |= MDIO_EEE_10GKX4;
if (of_property_read_bool(node, "eee-broken-10gkr"))
broken |= MDIO_EEE_10GKR;
phydev->eee_broken_modes = broken;
}
static bool phy_drv_supports_irq(struct phy_driver *phydrv)
{
return phydrv->config_intr && phydrv->ack_interrupt;
......
......@@ -673,6 +673,8 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
bool exact);
size_t phy_speeds(unsigned int *speeds, size_t size,
unsigned long *mask);
void of_set_phy_supported(struct phy_device *phydev);
void of_set_phy_eee_broken(struct phy_device *phydev);
static inline bool __phy_is_started(struct phy_device *phydev)
{
......@@ -1114,6 +1116,7 @@ int genphy_c45_read_pma(struct phy_device *phydev);
int genphy_c45_pma_setup_forced(struct phy_device *phydev);
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
int genphy_c45_read_mdix(struct phy_device *phydev);
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
/* The gen10g_* functions are the old Clause 45 stub */
int gen10g_config_aneg(struct phy_device *phydev);
......
......@@ -45,6 +45,7 @@
#define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */
#define MDIO_AN_LPA 19 /* AN LP abilities (base page) */
#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */
#define MDIO_PMA_NG_EXTABLE 21 /* 2.5G/5G PMA/PMD extended ability */
#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */
#define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */
#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
......@@ -92,6 +93,10 @@
#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00)
/* 10PASS-TS/2BASE-TL */
#define MDIO_CTRL1_SPEED10P2B (MDIO_CTRL1_SPEEDSELEXT | 0x04)
/* 2.5 Gb/s */
#define MDIO_CTRL1_SPEED2_5G (MDIO_CTRL1_SPEEDSELEXT | 0x18)
/* 5 Gb/s */
#define MDIO_CTRL1_SPEED5G (MDIO_CTRL1_SPEEDSELEXT | 0x1c)
/* Status register 1. */
#define MDIO_STAT1_LPOWERABLE 0x0002 /* Low-power ability */
......@@ -145,6 +150,8 @@
#define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */
#define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */
#define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */
#define MDIO_PMA_CTRL2_2_5GBT 0x0030 /* 2.5GBaseT type */
#define MDIO_PMA_CTRL2_5GBT 0x0031 /* 5GBaseT type */
#define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */
#define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */
#define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */
......@@ -198,6 +205,7 @@
#define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */
#define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */
#define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */
#define MDIO_PMA_EXTABLE_NBT 0x4000 /* 2.5/5GBASE-T ability */
/* PHY XGXS lane state register. */
#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001
......@@ -234,9 +242,13 @@
#define MDIO_PCS_10GBRT_STAT2_BER 0x3f00
/* AN 10GBASE-T control register. */
#define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */
#define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */
#define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */
/* AN 10GBASE-T status register. */
#define MDIO_AN_10GBT_STAT_LP2_5G 0x0020 /* LP is 2.5GBT capable */
#define MDIO_AN_10GBT_STAT_LP5G 0x0040 /* LP is 5GBT capable */
#define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */
#define MDIO_AN_10GBT_STAT_LPLTABLE 0x0400 /* LP loop timing ability */
#define MDIO_AN_10GBT_STAT_LP10G 0x0800 /* LP is 10GBT capable */
......@@ -265,6 +277,10 @@
#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */
#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */
/* 2.5G/5G Extended abilities register. */
#define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */
#define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */
/* LASI RX_ALARM control/status registers. */
#define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */
#define MDIO_PMA_LASI_RX_PCSLFLT 0x0008 /* PCS RX local fault */
......
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