Skip to content

Commit

Permalink
amd-xgbe: Add support for 10 Mbps speed
Browse files Browse the repository at this point in the history
Add the necessary changes to support 10 Mbps speed for BaseT and SFP
port modes. This is supported in MAC ver >= 30H.

Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Link: https://lore.kernel.org/r/20230109101819.747572-1-Raju.Rangoju@amd.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Raju Rangoju authored and Paolo Abeni committed Jan 10, 2023
1 parent cbdbb58 commit 07445f3
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 10 deletions.
3 changes: 3 additions & 0 deletions drivers/net/ethernet/amd/xgbe/xgbe-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,9 @@ static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed)
unsigned int ss;

switch (speed) {
case SPEED_10:
ss = 0x07;
break;
case SPEED_1000:
ss = 0x03;
break;
Expand Down
24 changes: 24 additions & 0 deletions drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@ static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_1000);
}

static void xgbe_sgmii_10_mode(struct xgbe_prv_data *pdata)
{
/* Set MAC to 10M speed */
pdata->hw_if.set_speed(pdata, SPEED_10);

/* Call PHY implementation support to complete rate change */
pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_10);
}

static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
{
/* Set MAC to 1G speed */
Expand Down Expand Up @@ -306,6 +315,9 @@ static void xgbe_change_mode(struct xgbe_prv_data *pdata,
case XGBE_MODE_KR:
xgbe_kr_mode(pdata);
break;
case XGBE_MODE_SGMII_10:
xgbe_sgmii_10_mode(pdata);
break;
case XGBE_MODE_SGMII_100:
xgbe_sgmii_100_mode(pdata);
break;
Expand Down Expand Up @@ -1074,6 +1086,8 @@ static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
static const char *xgbe_phy_speed_string(int speed)
{
switch (speed) {
case SPEED_10:
return "10Mbps";
case SPEED_100:
return "100Mbps";
case SPEED_1000:
Expand Down Expand Up @@ -1161,6 +1175,7 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
case XGBE_MODE_KX_1000:
case XGBE_MODE_KX_2500:
case XGBE_MODE_KR:
case XGBE_MODE_SGMII_10:
case XGBE_MODE_SGMII_100:
case XGBE_MODE_SGMII_1000:
case XGBE_MODE_X:
Expand Down Expand Up @@ -1222,6 +1237,8 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode)
xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_10)) {
xgbe_set_mode(pdata, XGBE_MODE_SGMII_10);
} else {
enable_irq(pdata->an_irq);
ret = -EINVAL;
Expand Down Expand Up @@ -1301,6 +1318,9 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
mode = xgbe_phy_status_aneg(pdata);

switch (mode) {
case XGBE_MODE_SGMII_10:
pdata->phy.speed = SPEED_10;
break;
case XGBE_MODE_SGMII_100:
pdata->phy.speed = SPEED_100;
break;
Expand Down Expand Up @@ -1443,6 +1463,8 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
xgbe_sgmii_1000_mode(pdata);
} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
xgbe_sgmii_100_mode(pdata);
} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_10)) {
xgbe_sgmii_10_mode(pdata);
} else {
ret = -EINVAL;
goto err_irq;
Expand Down Expand Up @@ -1540,6 +1562,8 @@ static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
return SPEED_1000;
else if (XGBE_ADV(lks, 100baseT_Full))
return SPEED_100;
else if (XGBE_ADV(lks, 10baseT_Full))
return SPEED_10;

return SPEED_UNKNOWN;
}
Expand Down
107 changes: 97 additions & 10 deletions drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
#include "xgbe.h"
#include "xgbe-common.h"

#define XGBE_PHY_PORT_SPEED_10 BIT(0)
#define XGBE_PHY_PORT_SPEED_100 BIT(1)
#define XGBE_PHY_PORT_SPEED_1000 BIT(2)
#define XGBE_PHY_PORT_SPEED_2500 BIT(3)
Expand Down Expand Up @@ -759,6 +760,8 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
XGBE_SET_SUP(lks, Pause);
XGBE_SET_SUP(lks, Asym_Pause);
if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T) {
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)
XGBE_SET_SUP(lks, 10baseT_Full);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
XGBE_SET_SUP(lks, 100baseT_Full);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
Expand Down Expand Up @@ -1542,6 +1545,16 @@ static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
xgbe_phy_phydev_flowctrl(pdata);

switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) {
case XGBE_SGMII_AN_LINK_SPEED_10:
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
XGBE_SET_LP_ADV(lks, 10baseT_Full);
mode = XGBE_MODE_SGMII_10;
} else {
/* Half-duplex not supported */
XGBE_SET_LP_ADV(lks, 10baseT_Half);
mode = XGBE_MODE_UNKNOWN;
}
break;
case XGBE_SGMII_AN_LINK_SPEED_100:
if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
XGBE_SET_LP_ADV(lks, 100baseT_Full);
Expand Down Expand Up @@ -1658,7 +1671,10 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
switch (phy_data->sfp_base) {
case XGBE_SFP_BASE_1000_T:
if (phy_data->phydev &&
(phy_data->phydev->speed == SPEED_100))
(phy_data->phydev->speed == SPEED_10))
mode = XGBE_MODE_SGMII_10;
else if (phy_data->phydev &&
(phy_data->phydev->speed == SPEED_100))
mode = XGBE_MODE_SGMII_100;
else
mode = XGBE_MODE_SGMII_1000;
Expand All @@ -1673,7 +1689,10 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
break;
default:
if (phy_data->phydev &&
(phy_data->phydev->speed == SPEED_100))
(phy_data->phydev->speed == SPEED_10))
mode = XGBE_MODE_SGMII_10;
else if (phy_data->phydev &&
(phy_data->phydev->speed == SPEED_100))
mode = XGBE_MODE_SGMII_100;
else
mode = XGBE_MODE_SGMII_1000;
Expand Down Expand Up @@ -2127,6 +2146,20 @@ static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata)
netif_dbg(pdata, link, pdata->netdev, "100MbE SGMII mode set\n");
}

static void xgbe_phy_sgmii_10_mode(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;

xgbe_phy_set_redrv_mode(pdata);

/* 10M/SGMII */
xgbe_phy_perform_ratechange(pdata, XGBE_MB_CMD_SET_1G, XGBE_MB_SUBCMD_10MBITS);

phy_data->cur_mode = XGBE_MODE_SGMII_10;

netif_dbg(pdata, link, pdata->netdev, "10MbE SGMII mode set\n");
}

static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
Expand Down Expand Up @@ -2185,6 +2218,7 @@ static enum xgbe_mode xgbe_phy_switch_baset_mode(struct xgbe_prv_data *pdata)
return xgbe_phy_cur_mode(pdata);

switch (xgbe_phy_cur_mode(pdata)) {
case XGBE_MODE_SGMII_10:
case XGBE_MODE_SGMII_100:
case XGBE_MODE_SGMII_1000:
return XGBE_MODE_KR;
Expand Down Expand Up @@ -2252,6 +2286,8 @@ static enum xgbe_mode xgbe_phy_get_baset_mode(struct xgbe_phy_data *phy_data,
int speed)
{
switch (speed) {
case SPEED_10:
return XGBE_MODE_SGMII_10;
case SPEED_100:
return XGBE_MODE_SGMII_100;
case SPEED_1000:
Expand All @@ -2269,6 +2305,8 @@ static enum xgbe_mode xgbe_phy_get_sfp_mode(struct xgbe_phy_data *phy_data,
int speed)
{
switch (speed) {
case SPEED_10:
return XGBE_MODE_SGMII_10;
case SPEED_100:
return XGBE_MODE_SGMII_100;
case SPEED_1000:
Expand Down Expand Up @@ -2343,6 +2381,9 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
case XGBE_MODE_KR:
xgbe_phy_kr_mode(pdata);
break;
case XGBE_MODE_SGMII_10:
xgbe_phy_sgmii_10_mode(pdata);
break;
case XGBE_MODE_SGMII_100:
xgbe_phy_sgmii_100_mode(pdata);
break;
Expand Down Expand Up @@ -2399,6 +2440,9 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
struct ethtool_link_ksettings *lks = &pdata->phy.lks;

switch (mode) {
case XGBE_MODE_SGMII_10:
return xgbe_phy_check_mode(pdata, mode,
XGBE_ADV(lks, 10baseT_Full));
case XGBE_MODE_SGMII_100:
return xgbe_phy_check_mode(pdata, mode,
XGBE_ADV(lks, 100baseT_Full));
Expand Down Expand Up @@ -2428,6 +2472,11 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
return false;
return xgbe_phy_check_mode(pdata, mode,
XGBE_ADV(lks, 1000baseX_Full));
case XGBE_MODE_SGMII_10:
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
return false;
return xgbe_phy_check_mode(pdata, mode,
XGBE_ADV(lks, 10baseT_Full));
case XGBE_MODE_SGMII_100:
if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
return false;
Expand Down Expand Up @@ -2520,10 +2569,17 @@ static bool xgbe_phy_valid_speed_basex_mode(struct xgbe_phy_data *phy_data,
}
}

static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data,
static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_prv_data *pdata,
int speed)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int ver;

switch (speed) {
case SPEED_10:
/* Supported in ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
return (ver >= 0x30) ? true : false;
case SPEED_100:
case SPEED_1000:
return true;
Expand All @@ -2536,10 +2592,17 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data,
}
}

static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_phy_data *phy_data,
static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_prv_data *pdata,
int speed)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int ver;

switch (speed) {
case SPEED_10:
/* Supported in ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
return (ver >= 0x30) && (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
case SPEED_100:
return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
case SPEED_1000:
Expand Down Expand Up @@ -2586,12 +2649,12 @@ static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
case XGBE_PORT_MODE_1000BASE_T:
case XGBE_PORT_MODE_NBASE_T:
case XGBE_PORT_MODE_10GBASE_T:
return xgbe_phy_valid_speed_baset_mode(phy_data, speed);
return xgbe_phy_valid_speed_baset_mode(pdata, speed);
case XGBE_PORT_MODE_1000BASE_X:
case XGBE_PORT_MODE_10GBASE_R:
return xgbe_phy_valid_speed_basex_mode(phy_data, speed);
case XGBE_PORT_MODE_SFP:
return xgbe_phy_valid_speed_sfp_mode(phy_data, speed);
return xgbe_phy_valid_speed_sfp_mode(pdata, speed);
default:
return false;
}
Expand Down Expand Up @@ -2862,6 +2925,12 @@ static int xgbe_phy_mdio_reset_setup(struct xgbe_prv_data *pdata)
static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int ver;

/* 10 Mbps speed is not supported in ver < 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
if (ver < 0x30 && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10))
return true;

switch (phy_data->port_mode) {
case XGBE_PORT_MODE_BACKPLANE:
Expand All @@ -2875,7 +2944,8 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
return false;
break;
case XGBE_PORT_MODE_1000BASE_T:
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000))
return false;
break;
Expand All @@ -2884,13 +2954,15 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
return false;
break;
case XGBE_PORT_MODE_NBASE_T:
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500))
return false;
break;
case XGBE_PORT_MODE_10GBASE_T:
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
return false;
Expand All @@ -2900,7 +2972,8 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
return false;
break;
case XGBE_PORT_MODE_SFP:
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
(phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
return false;
Expand Down Expand Up @@ -3269,6 +3342,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
XGBE_SET_SUP(lks, Pause);
XGBE_SET_SUP(lks, Asym_Pause);
XGBE_SET_SUP(lks, TP);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) {
XGBE_SET_SUP(lks, 10baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_10;
}
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
XGBE_SET_SUP(lks, 100baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_100;
Expand Down Expand Up @@ -3299,6 +3376,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
XGBE_SET_SUP(lks, Pause);
XGBE_SET_SUP(lks, Asym_Pause);
XGBE_SET_SUP(lks, TP);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) {
XGBE_SET_SUP(lks, 10baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_10;
}
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
XGBE_SET_SUP(lks, 100baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_100;
Expand All @@ -3321,6 +3402,10 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
XGBE_SET_SUP(lks, Pause);
XGBE_SET_SUP(lks, Asym_Pause);
XGBE_SET_SUP(lks, TP);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10) {
XGBE_SET_SUP(lks, 10baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_10;
}
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
XGBE_SET_SUP(lks, 100baseT_Full);
phy_data->start_mode = XGBE_MODE_SGMII_100;
Expand Down Expand Up @@ -3361,6 +3446,8 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
XGBE_SET_SUP(lks, Asym_Pause);
XGBE_SET_SUP(lks, TP);
XGBE_SET_SUP(lks, FIBRE);
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)
phy_data->start_mode = XGBE_MODE_SGMII_10;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
phy_data->start_mode = XGBE_MODE_SGMII_100;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/amd/xgbe/xgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@

#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
#define XGBE_SGMII_AN_LINK_SPEED_10 0x00
#define XGBE_SGMII_AN_LINK_SPEED_100 0x04
#define XGBE_SGMII_AN_LINK_SPEED_1000 0x08
#define XGBE_SGMII_AN_LINK_DUPLEX BIT(4)
Expand Down Expand Up @@ -594,6 +595,7 @@ enum xgbe_mode {
XGBE_MODE_KX_2500,
XGBE_MODE_KR,
XGBE_MODE_X,
XGBE_MODE_SGMII_10,
XGBE_MODE_SGMII_100,
XGBE_MODE_SGMII_1000,
XGBE_MODE_SFI,
Expand Down

0 comments on commit 07445f3

Please sign in to comment.