Commit e722ec82 authored by Tom Lendacky's avatar Tom Lendacky Committed by David S. Miller

amd-xgbe: Update the BelFuse quirk to support SGMII

Instead of using a quirk to make the BelFuse 1GBT-SFP06 part look like
a 1000baseX part, program the SFP PHY to support SGMII and 10/100/1000
baseT.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 41874629
...@@ -860,6 +860,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) ...@@ -860,6 +860,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int phy_id = phy_data->phydev->phy_id; unsigned int phy_id = phy_data->phydev->phy_id;
if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
return false;
if ((phy_id & 0xfffffff0) != 0x01ff0cc0) if ((phy_id & 0xfffffff0) != 0x01ff0cc0)
return false; return false;
...@@ -885,8 +888,80 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) ...@@ -885,8 +888,80 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
return true; return true;
} }
static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
unsigned int phy_id = phy_data->phydev->phy_id;
int reg;
if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
return false;
if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
return false;
if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN))
return false;
if ((phy_id & 0xfffffff0) != 0x03625d10)
return false;
/* Disable RGMII mode */
phy_write(phy_data->phydev, 0x18, 0x7007);
reg = phy_read(phy_data->phydev, 0x18);
phy_write(phy_data->phydev, 0x18, reg & ~0x0080);
/* Enable fiber register bank */
phy_write(phy_data->phydev, 0x1c, 0x7c00);
reg = phy_read(phy_data->phydev, 0x1c);
reg &= 0x03ff;
reg &= ~0x0001;
phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0001);
/* Power down SerDes */
reg = phy_read(phy_data->phydev, 0x00);
phy_write(phy_data->phydev, 0x00, reg | 0x00800);
/* Configure SGMII-to-Copper mode */
phy_write(phy_data->phydev, 0x1c, 0x7c00);
reg = phy_read(phy_data->phydev, 0x1c);
reg &= 0x03ff;
reg &= ~0x0006;
phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0004);
/* Power up SerDes */
reg = phy_read(phy_data->phydev, 0x00);
phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
/* Enable copper register bank */
phy_write(phy_data->phydev, 0x1c, 0x7c00);
reg = phy_read(phy_data->phydev, 0x1c);
reg &= 0x03ff;
reg &= ~0x0001;
phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg);
/* Power up SerDes */
reg = phy_read(phy_data->phydev, 0x00);
phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
phy_data->phydev->supported = PHY_GBIT_FEATURES;
phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phy_data->phydev->advertising = phy_data->phydev->supported;
netif_dbg(pdata, drv, pdata->netdev,
"BelFuse PHY quirk in place\n");
return true;
}
static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata) static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
{ {
if (xgbe_phy_belfuse_phy_quirks(pdata))
return;
if (xgbe_phy_finisar_phy_quirks(pdata)) if (xgbe_phy_finisar_phy_quirks(pdata))
return; return;
} }
...@@ -1027,37 +1102,6 @@ static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data) ...@@ -1027,37 +1102,6 @@ static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data)
return false; return false;
} }
static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
return false;
if (!memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) {
phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
if (phy_data->sfp_changed)
netif_dbg(pdata, drv, pdata->netdev,
"Bel-Fuse SFP quirk in place\n");
return true;
}
return false;
}
static bool xgbe_phy_sfp_parse_quirks(struct xgbe_prv_data *pdata)
{
if (xgbe_phy_belfuse_parse_quirks(pdata))
return true;
return false;
}
static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
{ {
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
...@@ -1076,9 +1120,6 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) ...@@ -1076,9 +1120,6 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data); phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data);
phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data); phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data);
if (xgbe_phy_sfp_parse_quirks(pdata))
return;
/* Assume ACTIVE cable unless told it is PASSIVE */ /* Assume ACTIVE cable unless told it is PASSIVE */
if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) { if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) {
phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE; phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE;
......
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