From f794fd440066ccd7d601f405f80aa514b95f15d1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 27 Feb 2009 13:06:58 +0000 Subject: sfc: Remove "XFP" from log messages that are not specific to XFP Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/xfp_phy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/sfc/xfp_phy.c') diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 2d50b6ecf5f9..5d1c7f800007 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -73,7 +73,7 @@ static int xfp_reset_phy(struct efx_nic *efx) return rc; fail: - EFX_ERR(efx, "XFP: reset timed out!\n"); + EFX_ERR(efx, "PHY reset timed out\n"); return rc; } @@ -88,15 +88,15 @@ static int xfp_phy_init(struct efx_nic *efx) return -ENOMEM; efx->phy_data = phy_data; - EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" - " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), + EFX_INFO(efx, "PHY ID reg %x (OUI %x model %x revision %x)\n", + devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), MDIO_ID_REV(devid)); phy_data->phy_mode = efx->phy_mode; rc = xfp_reset_phy(efx); - EFX_INFO(efx, "XFP: PHY init %s.\n", + EFX_INFO(efx, "PHY init %s.\n", rc ? "failed" : "successful"); if (rc < 0) goto fail; -- cgit From 3f39a5e9bff000025c2679101b4f83e4fc21dbba Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 27 Feb 2009 13:07:15 +0000 Subject: sfc: Fix reporting of PHY id Shuffle bits of the OUI into the conventional written order. Replace PHY id component macros with functions. Zero-pad PHY id components in log messages. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/xfp_phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/sfc/xfp_phy.c') diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 5d1c7f800007..2df467d28064 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -88,9 +88,9 @@ static int xfp_phy_init(struct efx_nic *efx) return -ENOMEM; efx->phy_data = phy_data; - EFX_INFO(efx, "PHY ID reg %x (OUI %x model %x revision %x)\n", - devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), - MDIO_ID_REV(devid)); + EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", + devid, mdio_id_oui(devid), mdio_id_model(devid), + mdio_id_rev(devid)); phy_data->phy_mode = efx->phy_mode; -- cgit From d2d2c3731474614bff5cf47a605e59e847882f5d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 27 Feb 2009 13:07:33 +0000 Subject: sfc: Add support for QT2025C PHY This is a new PHY supporting SFP+ modules, used in the SFN4112F reference design. It is similar to the QT2022C2 and shares much of its support code. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/xfp_phy.c | 95 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 8 deletions(-) (limited to 'drivers/net/sfc/xfp_phy.c') diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 2df467d28064..bb1ef77d5f56 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -7,8 +7,8 @@ * by the Free Software Foundation, incorporated herein by reference. */ /* - * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32) - * See www.amcc.com for details (search for qt2032) + * Driver for SFP+ and XFP optical PHYs plus some support specific to the + * AMCC QT20xx adapters; see www.amcc.com for details */ #include @@ -31,6 +31,21 @@ /* Quake-specific MDIO registers */ #define MDIO_QUAKE_LED0_REG (0xD006) +/* QT2025C only */ +#define PCS_FW_HEARTBEAT_REG 0xd7ee +#define PCS_FW_HEARTB_LBN 0 +#define PCS_FW_HEARTB_WIDTH 8 +#define PCS_UC8051_STATUS_REG 0xd7fd +#define PCS_UC_STATUS_LBN 0 +#define PCS_UC_STATUS_WIDTH 8 +#define PCS_UC_STATUS_FW_SAVE 0x20 +#define PMA_PMD_FTX_CTRL2_REG 0xc309 +#define PMA_PMD_FTX_STATIC_LBN 13 +#define PMA_PMD_VEND1_REG 0xc001 +#define PMA_PMD_VEND1_LBTXD_LBN 15 +#define PCS_VEND1_REG 0xc000 +#define PCS_VEND1_LBTXD_LBN 5 + void xfp_set_led(struct efx_nic *p, int led, int mode) { int addr = MDIO_QUAKE_LED0_REG + led; @@ -45,7 +60,49 @@ struct xfp_phy_data { #define XFP_MAX_RESET_TIME 500 #define XFP_RESET_WAIT 10 -/* Reset the PHYXS MMD. This is documented (for the Quake PHY) as doing +static int qt2025c_wait_reset(struct efx_nic *efx) +{ + unsigned long timeout = jiffies + 10 * HZ; + int phy_id = efx->mii.phy_id; + int reg, old_counter = 0; + + /* Wait for firmware heartbeat to start */ + for (;;) { + int counter; + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, + PCS_FW_HEARTBEAT_REG); + if (reg < 0) + return reg; + counter = ((reg >> PCS_FW_HEARTB_LBN) & + ((1 << PCS_FW_HEARTB_WIDTH) - 1)); + if (old_counter == 0) + old_counter = counter; + else if (counter != old_counter) + break; + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + msleep(10); + } + + /* Wait for firmware status to look good */ + for (;;) { + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, + PCS_UC8051_STATUS_REG); + if (reg < 0) + return reg; + if ((reg & + ((1 << PCS_UC_STATUS_WIDTH) - 1) << PCS_UC_STATUS_LBN) >= + PCS_UC_STATUS_FW_SAVE) + break; + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + msleep(100); + } + + return 0; +} + +/* Reset the PHYXS MMD. This is documented (for the Quake PHYs) as doing * a complete soft reset. */ static int xfp_reset_phy(struct efx_nic *efx) @@ -58,6 +115,12 @@ static int xfp_reset_phy(struct efx_nic *efx) if (rc < 0) goto fail; + if (efx->phy_type == PHY_TYPE_QT2025C) { + rc = qt2025c_wait_reset(efx); + if (rc < 0) + goto fail; + } + /* Wait 250ms for the PHY to complete bootup */ msleep(250); @@ -131,12 +194,28 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) { struct xfp_phy_data *phy_data = efx->phy_data; - /* Reset the PHY when moving from tx off to tx on */ - if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) && - (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) - xfp_reset_phy(efx); + if (efx->phy_type == PHY_TYPE_QT2025C) { + /* There are several different register bits which can + * disable TX (and save power) on direct-attach cables + * or optical transceivers, varying somewhat between + * firmware versions. Only 'static mode' appears to + * cover everything. */ + mdio_clause45_set_flag( + efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN, + efx->phy_mode & PHY_MODE_TX_DISABLED || + efx->phy_mode & PHY_MODE_LOW_POWER || + efx->loopback_mode == LOOPBACK_PCS || + efx->loopback_mode == LOOPBACK_PMAPMD); + } else { + /* Reset the PHY when moving from tx off to tx on */ + if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) && + (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) + xfp_reset_phy(efx); + + mdio_clause45_transmit_disable(efx); + } - mdio_clause45_transmit_disable(efx); mdio_clause45_phy_reconfigure(efx); phy_data->phy_mode = efx->phy_mode; -- cgit