aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-02-27 08:07:33 -0500
committerDavid S. Miller <davem@davemloft.net>2009-03-02 06:15:04 -0500
commitd2d2c3731474614bff5cf47a605e59e847882f5d (patch)
treecc4f544fef07c9e5754327b4721e4f49c698197b /drivers
parent3f39a5e9bff000025c2679101b4f83e4fc21dbba (diff)
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 <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/falcon.c1
-rw-r--r--drivers/net/sfc/net_driver.h1
-rw-r--r--drivers/net/sfc/phy.h4
-rw-r--r--drivers/net/sfc/xfp_phy.c95
4 files changed, 91 insertions, 10 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index d5378e60fcdd..9e2f0f0d47a8 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -2249,6 +2249,7 @@ static int falcon_probe_phy(struct efx_nic *efx)
2249 efx->phy_op = &falcon_sft9001_phy_ops; 2249 efx->phy_op = &falcon_sft9001_phy_ops;
2250 break; 2250 break;
2251 case PHY_TYPE_QT2022C2: 2251 case PHY_TYPE_QT2022C2:
2252 case PHY_TYPE_QT2025C:
2252 efx->phy_op = &falcon_xfp_phy_ops; 2253 efx->phy_op = &falcon_xfp_phy_ops;
2253 break; 2254 break;
2254 default: 2255 default:
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 19930ff9df7b..eb768fcb3cc8 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -450,6 +450,7 @@ enum phy_type {
450 PHY_TYPE_QT2022C2 = 4, 450 PHY_TYPE_QT2022C2 = 4,
451 PHY_TYPE_PM8358 = 6, 451 PHY_TYPE_PM8358 = 6,
452 PHY_TYPE_SFT9001A = 8, 452 PHY_TYPE_SFT9001A = 8,
453 PHY_TYPE_QT2025C = 9,
453 PHY_TYPE_SFT9001B = 10, 454 PHY_TYPE_SFT9001B = 10,
454 PHY_TYPE_MAX /* Insert any new items before this */ 455 PHY_TYPE_MAX /* Insert any new items before this */
455}; 456};
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index f6e47227d245..c1cff9c0c173 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -23,11 +23,11 @@ extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
23extern int sft9001_wait_boot(struct efx_nic *efx); 23extern int sft9001_wait_boot(struct efx_nic *efx);
24 24
25/**************************************************************************** 25/****************************************************************************
26 * Exported functions from the driver for XFP optical PHYs 26 * AMCC/Quake QT20xx PHYs
27 */ 27 */
28extern struct efx_phy_operations falcon_xfp_phy_ops; 28extern struct efx_phy_operations falcon_xfp_phy_ops;
29 29
30/* The QUAKE XFP PHY provides various H/W control states for LEDs */ 30/* These PHYs provide various H/W control states for LEDs */
31#define QUAKE_LED_LINK_INVAL (0) 31#define QUAKE_LED_LINK_INVAL (0)
32#define QUAKE_LED_LINK_STAT (1) 32#define QUAKE_LED_LINK_STAT (1)
33#define QUAKE_LED_LINK_ACT (2) 33#define QUAKE_LED_LINK_ACT (2)
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 @@
7 * by the Free Software Foundation, incorporated herein by reference. 7 * by the Free Software Foundation, incorporated herein by reference.
8 */ 8 */
9/* 9/*
10 * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32) 10 * Driver for SFP+ and XFP optical PHYs plus some support specific to the
11 * See www.amcc.com for details (search for qt2032) 11 * AMCC QT20xx adapters; see www.amcc.com for details
12 */ 12 */
13 13
14#include <linux/timer.h> 14#include <linux/timer.h>
@@ -31,6 +31,21 @@
31/* Quake-specific MDIO registers */ 31/* Quake-specific MDIO registers */
32#define MDIO_QUAKE_LED0_REG (0xD006) 32#define MDIO_QUAKE_LED0_REG (0xD006)
33 33
34/* QT2025C only */
35#define PCS_FW_HEARTBEAT_REG 0xd7ee
36#define PCS_FW_HEARTB_LBN 0
37#define PCS_FW_HEARTB_WIDTH 8
38#define PCS_UC8051_STATUS_REG 0xd7fd
39#define PCS_UC_STATUS_LBN 0
40#define PCS_UC_STATUS_WIDTH 8
41#define PCS_UC_STATUS_FW_SAVE 0x20
42#define PMA_PMD_FTX_CTRL2_REG 0xc309
43#define PMA_PMD_FTX_STATIC_LBN 13
44#define PMA_PMD_VEND1_REG 0xc001
45#define PMA_PMD_VEND1_LBTXD_LBN 15
46#define PCS_VEND1_REG 0xc000
47#define PCS_VEND1_LBTXD_LBN 5
48
34void xfp_set_led(struct efx_nic *p, int led, int mode) 49void xfp_set_led(struct efx_nic *p, int led, int mode)
35{ 50{
36 int addr = MDIO_QUAKE_LED0_REG + led; 51 int addr = MDIO_QUAKE_LED0_REG + led;
@@ -45,7 +60,49 @@ struct xfp_phy_data {
45#define XFP_MAX_RESET_TIME 500 60#define XFP_MAX_RESET_TIME 500
46#define XFP_RESET_WAIT 10 61#define XFP_RESET_WAIT 10
47 62
48/* Reset the PHYXS MMD. This is documented (for the Quake PHY) as doing 63static int qt2025c_wait_reset(struct efx_nic *efx)
64{
65 unsigned long timeout = jiffies + 10 * HZ;
66 int phy_id = efx->mii.phy_id;
67 int reg, old_counter = 0;
68
69 /* Wait for firmware heartbeat to start */
70 for (;;) {
71 int counter;
72 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
73 PCS_FW_HEARTBEAT_REG);
74 if (reg < 0)
75 return reg;
76 counter = ((reg >> PCS_FW_HEARTB_LBN) &
77 ((1 << PCS_FW_HEARTB_WIDTH) - 1));
78 if (old_counter == 0)
79 old_counter = counter;
80 else if (counter != old_counter)
81 break;
82 if (time_after(jiffies, timeout))
83 return -ETIMEDOUT;
84 msleep(10);
85 }
86
87 /* Wait for firmware status to look good */
88 for (;;) {
89 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
90 PCS_UC8051_STATUS_REG);
91 if (reg < 0)
92 return reg;
93 if ((reg &
94 ((1 << PCS_UC_STATUS_WIDTH) - 1) << PCS_UC_STATUS_LBN) >=
95 PCS_UC_STATUS_FW_SAVE)
96 break;
97 if (time_after(jiffies, timeout))
98 return -ETIMEDOUT;
99 msleep(100);
100 }
101
102 return 0;
103}
104
105/* Reset the PHYXS MMD. This is documented (for the Quake PHYs) as doing
49 * a complete soft reset. 106 * a complete soft reset.
50 */ 107 */
51static int xfp_reset_phy(struct efx_nic *efx) 108static int xfp_reset_phy(struct efx_nic *efx)
@@ -58,6 +115,12 @@ static int xfp_reset_phy(struct efx_nic *efx)
58 if (rc < 0) 115 if (rc < 0)
59 goto fail; 116 goto fail;
60 117
118 if (efx->phy_type == PHY_TYPE_QT2025C) {
119 rc = qt2025c_wait_reset(efx);
120 if (rc < 0)
121 goto fail;
122 }
123
61 /* Wait 250ms for the PHY to complete bootup */ 124 /* Wait 250ms for the PHY to complete bootup */
62 msleep(250); 125 msleep(250);
63 126
@@ -131,12 +194,28 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
131{ 194{
132 struct xfp_phy_data *phy_data = efx->phy_data; 195 struct xfp_phy_data *phy_data = efx->phy_data;
133 196
134 /* Reset the PHY when moving from tx off to tx on */ 197 if (efx->phy_type == PHY_TYPE_QT2025C) {
135 if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) && 198 /* There are several different register bits which can
136 (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) 199 * disable TX (and save power) on direct-attach cables
137 xfp_reset_phy(efx); 200 * or optical transceivers, varying somewhat between
201 * firmware versions. Only 'static mode' appears to
202 * cover everything. */
203 mdio_clause45_set_flag(
204 efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
205 PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN,
206 efx->phy_mode & PHY_MODE_TX_DISABLED ||
207 efx->phy_mode & PHY_MODE_LOW_POWER ||
208 efx->loopback_mode == LOOPBACK_PCS ||
209 efx->loopback_mode == LOOPBACK_PMAPMD);
210 } else {
211 /* Reset the PHY when moving from tx off to tx on */
212 if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) &&
213 (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
214 xfp_reset_phy(efx);
215
216 mdio_clause45_transmit_disable(efx);
217 }
138 218
139 mdio_clause45_transmit_disable(efx);
140 mdio_clause45_phy_reconfigure(efx); 219 mdio_clause45_phy_reconfigure(efx);
141 220
142 phy_data->phy_mode = efx->phy_mode; 221 phy_data->phy_mode = efx->phy_mode;