diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 01:00:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-13 01:00:49 -0500 |
commit | 6f158d5f29b420438e907d72cb111ddb9973f00a (patch) | |
tree | 38d7696c47a706447c6bf8e66f52a5854d781464 /drivers/net/sfc | |
parent | e6fa2eb789f49dc51a20d3db0d410bc8158abb43 (diff) |
sfc: Add support for SFN4111T
Add support code for the SFN4111T 100/1000/10GBASE-T reference design,
based in part on the existing code for the SFE4001.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/boards.c | 2 | ||||
-rw-r--r-- | drivers/net/sfc/boards.h | 7 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 7 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_hwdefs.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 11 | ||||
-rw-r--r-- | drivers/net/sfc/sfe4001.c | 153 | ||||
-rw-r--r-- | drivers/net/sfc/workarounds.h | 3 |
7 files changed, 150 insertions, 35 deletions
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c index 08fa4e35742b..64903496aa9a 100644 --- a/drivers/net/sfc/boards.c +++ b/drivers/net/sfc/boards.c | |||
@@ -241,6 +241,8 @@ struct efx_board_data { | |||
241 | static struct efx_board_data board_data[] = { | 241 | static struct efx_board_data board_data[] = { |
242 | { EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init }, | 242 | { EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init }, |
243 | { EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init }, | 243 | { EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init }, |
244 | { EFX_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter", | ||
245 | sfn4111t_init }, | ||
244 | }; | 246 | }; |
245 | 247 | ||
246 | void efx_set_board_info(struct efx_nic *efx, u16 revision_info) | 248 | void efx_set_board_info(struct efx_nic *efx, u16 revision_info) |
diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h index 5e0dde59c44c..d93c6c6a7548 100644 --- a/drivers/net/sfc/boards.h +++ b/drivers/net/sfc/boards.h | |||
@@ -12,11 +12,16 @@ | |||
12 | 12 | ||
13 | /* Board IDs (must fit in 8 bits) */ | 13 | /* Board IDs (must fit in 8 bits) */ |
14 | enum efx_board_type { | 14 | enum efx_board_type { |
15 | EFX_BOARD_SFE4001 = 1, /* SFE4001 (10GBASE-T) */ | 15 | EFX_BOARD_SFE4001 = 1, |
16 | EFX_BOARD_SFE4002 = 2, | 16 | EFX_BOARD_SFE4002 = 2, |
17 | EFX_BOARD_SFN4111T = 0x51, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info); | 20 | extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info); |
21 | |||
22 | /* SFE4001 (10GBASE-T) */ | ||
20 | extern int sfe4001_init(struct efx_nic *efx); | 23 | extern int sfe4001_init(struct efx_nic *efx); |
24 | /* SFN4111T (100/1000/10GBASE-T) */ | ||
25 | extern int sfn4111t_init(struct efx_nic *efx); | ||
21 | 26 | ||
22 | #endif | 27 | #endif |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index db8e147f00b2..84771a792099 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -2971,6 +2971,13 @@ int falcon_init_nic(struct efx_nic *efx) | |||
2971 | EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); | 2971 | EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); |
2972 | falcon_write(efx, &temp, NIC_STAT_REG); | 2972 | falcon_write(efx, &temp, NIC_STAT_REG); |
2973 | 2973 | ||
2974 | /* Set the source of the GMAC clock */ | ||
2975 | if (falcon_rev(efx) == FALCON_REV_B0) { | ||
2976 | falcon_read(efx, &temp, GPIO_CTL_REG_KER); | ||
2977 | EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true); | ||
2978 | falcon_write(efx, &temp, GPIO_CTL_REG_KER); | ||
2979 | } | ||
2980 | |||
2974 | /* Set buffer table mode */ | 2981 | /* Set buffer table mode */ |
2975 | EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL); | 2982 | EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL); |
2976 | falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER); | 2983 | falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER); |
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index a58c627f51aa..bda8d5bb72e4 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h | |||
@@ -136,6 +136,8 @@ | |||
136 | 136 | ||
137 | /* GPIO control register */ | 137 | /* GPIO control register */ |
138 | #define GPIO_CTL_REG_KER 0x0210 | 138 | #define GPIO_CTL_REG_KER 0x0210 |
139 | #define GPIO_USE_NIC_CLK_LBN (30) | ||
140 | #define GPIO_USE_NIC_CLK_WIDTH (1) | ||
139 | #define GPIO_OUTPUTS_LBN (16) | 141 | #define GPIO_OUTPUTS_LBN (16) |
140 | #define GPIO_OUTPUTS_WIDTH (4) | 142 | #define GPIO_OUTPUTS_WIDTH (4) |
141 | #define GPIO_INPUTS_LBN (8) | 143 | #define GPIO_INPUTS_LBN (8) |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 578b7f410ed4..6bb09f263b33 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -702,8 +702,15 @@ int efx_offline_test(struct efx_nic *efx, | |||
702 | */ | 702 | */ |
703 | mutex_lock(&efx->mac_lock); | 703 | mutex_lock(&efx->mac_lock); |
704 | efx->port_inhibited = true; | 704 | efx->port_inhibited = true; |
705 | if (efx->loopback_modes) | 705 | if (efx->loopback_modes) { |
706 | efx->loopback_mode = __ffs(efx->loopback_modes); | 706 | /* We need the 312 clock from the PHY to test the XMAC |
707 | * registers, so move into XGMII loopback if available */ | ||
708 | if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) | ||
709 | efx->loopback_mode = LOOPBACK_XGMII; | ||
710 | else | ||
711 | efx->loopback_mode = __ffs(efx->loopback_modes); | ||
712 | } | ||
713 | |||
707 | __efx_reconfigure_port(efx); | 714 | __efx_reconfigure_port(efx); |
708 | mutex_unlock(&efx->mac_lock); | 715 | mutex_unlock(&efx->mac_lock); |
709 | 716 | ||
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index af652844baee..16b80acb9992 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2007 Solarflare Communications Inc. | 3 | * Copyright 2007-2008 Solarflare Communications Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published | 6 | * under the terms of the GNU General Public License version 2 as published |
@@ -8,10 +8,21 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | /***************************************************************************** | 10 | /***************************************************************************** |
11 | * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that | 11 | * Support for the SFE4001 and SFN4111T NICs. |
12 | * controls the PHY power rails, and for the MAX6647 temp. sensor used to check | 12 | * |
13 | * the PHY | 13 | * The SFE4001 does not power-up fully at reset due to its high power |
14 | * consumption. We control its power via a PCA9539 I/O expander. | ||
15 | * Both boards have a MAX6647 temperature monitor which we expose to | ||
16 | * the lm90 driver. | ||
17 | * | ||
18 | * This also provides minimal support for reflashing the PHY, which is | ||
19 | * initiated by resetting it with the FLASH_CFG_1 pin pulled down. | ||
20 | * On SFE4001 rev A2 and later this is connected to the 3V3X output of | ||
21 | * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3. | ||
22 | * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually | ||
23 | * exclusive with the network device being open. | ||
14 | */ | 24 | */ |
25 | |||
15 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
16 | #include "net_driver.h" | 27 | #include "net_driver.h" |
17 | #include "efx.h" | 28 | #include "efx.h" |
@@ -171,39 +182,30 @@ fail_on: | |||
171 | return rc; | 182 | return rc; |
172 | } | 183 | } |
173 | 184 | ||
174 | static int sfe4001_check_hw(struct efx_nic *efx) | 185 | static int sfn4111t_reset(struct efx_nic *efx) |
175 | { | 186 | { |
176 | s32 status; | 187 | efx_oword_t reg; |
177 | 188 | ||
178 | /* If XAUI link is up then do not monitor */ | 189 | /* GPIO pins are also used for I2C, so block that temporarily */ |
179 | if (EFX_WORKAROUND_7884(efx) && efx->mac_up) | 190 | mutex_lock(&efx->i2c_adap.bus_lock); |
180 | return 0; | ||
181 | 191 | ||
182 | /* Check the powered status of the PHY. Lack of power implies that | 192 | falcon_read(efx, ®, GPIO_CTL_REG_KER); |
183 | * the MAX6647 has shut down power to it, probably due to a temp. | 193 | EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); |
184 | * alarm. Reading the power status rather than the MAX6647 status | 194 | EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false); |
185 | * directly because the later is read-to-clear and would thus | 195 | falcon_write(efx, ®, GPIO_CTL_REG_KER); |
186 | * start to power up the PHY again when polled, causing us to blip | 196 | msleep(1000); |
187 | * the power undesirably. | 197 | EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true); |
188 | * We know we can read from the IO expander because we did | 198 | EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true); |
189 | * it during power-on. Assume failure now is bad news. */ | 199 | EFX_SET_OWORD_FIELD(reg, GPIO3_OUT, |
190 | status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN); | 200 | !(efx->phy_mode & PHY_MODE_SPECIAL)); |
191 | if (status >= 0 && | 201 | falcon_write(efx, ®, GPIO_CTL_REG_KER); |
192 | (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0) | ||
193 | return 0; | ||
194 | 202 | ||
195 | /* Use board power control, not PHY power control */ | 203 | mutex_unlock(&efx->i2c_adap.bus_lock); |
196 | sfe4001_poweroff(efx); | ||
197 | efx->phy_mode = PHY_MODE_OFF; | ||
198 | 204 | ||
199 | return (status < 0) ? -EIO : -ERANGE; | 205 | ssleep(1); |
206 | return 0; | ||
200 | } | 207 | } |
201 | 208 | ||
202 | /* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin | ||
203 | * using the 3V3X output of the IO-expander. Allow the user to set | ||
204 | * this when the device is stopped, and keep it stopped then. | ||
205 | */ | ||
206 | |||
207 | static ssize_t show_phy_flash_cfg(struct device *dev, | 209 | static ssize_t show_phy_flash_cfg(struct device *dev, |
208 | struct device_attribute *attr, char *buf) | 210 | struct device_attribute *attr, char *buf) |
209 | { | 211 | { |
@@ -231,7 +233,10 @@ static ssize_t set_phy_flash_cfg(struct device *dev, | |||
231 | err = -EBUSY; | 233 | err = -EBUSY; |
232 | } else { | 234 | } else { |
233 | efx->phy_mode = new_mode; | 235 | efx->phy_mode = new_mode; |
234 | err = sfe4001_poweron(efx); | 236 | if (efx->board_info.type == EFX_BOARD_SFE4001) |
237 | err = sfe4001_poweron(efx); | ||
238 | else | ||
239 | err = sfn4111t_reset(efx); | ||
235 | efx_reconfigure_port(efx); | 240 | efx_reconfigure_port(efx); |
236 | } | 241 | } |
237 | rtnl_unlock(); | 242 | rtnl_unlock(); |
@@ -251,6 +256,34 @@ static void sfe4001_fini(struct efx_nic *efx) | |||
251 | i2c_unregister_device(efx->board_info.hwmon_client); | 256 | i2c_unregister_device(efx->board_info.hwmon_client); |
252 | } | 257 | } |
253 | 258 | ||
259 | static int sfe4001_check_hw(struct efx_nic *efx) | ||
260 | { | ||
261 | s32 status; | ||
262 | |||
263 | /* If XAUI link is up then do not monitor */ | ||
264 | if (EFX_WORKAROUND_7884(efx) && efx->mac_up) | ||
265 | return 0; | ||
266 | |||
267 | /* Check the powered status of the PHY. Lack of power implies that | ||
268 | * the MAX6647 has shut down power to it, probably due to a temp. | ||
269 | * alarm. Reading the power status rather than the MAX6647 status | ||
270 | * directly because the later is read-to-clear and would thus | ||
271 | * start to power up the PHY again when polled, causing us to blip | ||
272 | * the power undesirably. | ||
273 | * We know we can read from the IO expander because we did | ||
274 | * it during power-on. Assume failure now is bad news. */ | ||
275 | status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN); | ||
276 | if (status >= 0 && | ||
277 | (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0) | ||
278 | return 0; | ||
279 | |||
280 | /* Use board power control, not PHY power control */ | ||
281 | sfe4001_poweroff(efx); | ||
282 | efx->phy_mode = PHY_MODE_OFF; | ||
283 | |||
284 | return (status < 0) ? -EIO : -ERANGE; | ||
285 | } | ||
286 | |||
254 | static struct i2c_board_info sfe4001_hwmon_info = { | 287 | static struct i2c_board_info sfe4001_hwmon_info = { |
255 | I2C_BOARD_INFO("max6647", 0x4e), | 288 | I2C_BOARD_INFO("max6647", 0x4e), |
256 | .irq = -1, | 289 | .irq = -1, |
@@ -312,3 +345,61 @@ fail_hwmon: | |||
312 | i2c_unregister_device(efx->board_info.hwmon_client); | 345 | i2c_unregister_device(efx->board_info.hwmon_client); |
313 | return rc; | 346 | return rc; |
314 | } | 347 | } |
348 | |||
349 | static int sfn4111t_check_hw(struct efx_nic *efx) | ||
350 | { | ||
351 | s32 status; | ||
352 | |||
353 | /* If XAUI link is up then do not monitor */ | ||
354 | if (EFX_WORKAROUND_7884(efx) && efx->mac_up) | ||
355 | return 0; | ||
356 | |||
357 | /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */ | ||
358 | status = i2c_smbus_read_byte_data(efx->board_info.hwmon_client, | ||
359 | MAX664X_REG_RSL); | ||
360 | if (status < 0) | ||
361 | return -EIO; | ||
362 | if (status & 0x57) | ||
363 | return -ERANGE; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static void sfn4111t_fini(struct efx_nic *efx) | ||
368 | { | ||
369 | EFX_INFO(efx, "%s\n", __func__); | ||
370 | |||
371 | device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); | ||
372 | i2c_unregister_device(efx->board_info.hwmon_client); | ||
373 | } | ||
374 | |||
375 | static struct i2c_board_info sfn4111t_hwmon_info = { | ||
376 | I2C_BOARD_INFO("max6647", 0x4e), | ||
377 | .irq = -1, | ||
378 | }; | ||
379 | |||
380 | int sfn4111t_init(struct efx_nic *efx) | ||
381 | { | ||
382 | int rc; | ||
383 | |||
384 | efx->board_info.hwmon_client = | ||
385 | i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info); | ||
386 | if (!efx->board_info.hwmon_client) | ||
387 | return -EIO; | ||
388 | |||
389 | efx->board_info.blink = tenxpress_phy_blink; | ||
390 | efx->board_info.monitor = sfn4111t_check_hw; | ||
391 | efx->board_info.fini = sfn4111t_fini; | ||
392 | |||
393 | rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); | ||
394 | if (rc) | ||
395 | goto fail_hwmon; | ||
396 | |||
397 | if (efx->phy_mode & PHY_MODE_SPECIAL) | ||
398 | sfn4111t_reset(efx); | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | fail_hwmon: | ||
403 | i2c_unregister_device(efx->board_info.hwmon_client); | ||
404 | return rc; | ||
405 | } | ||
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index ecebff211a74..82e03e1d7371 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #define EFX_WORKAROUND_ALWAYS(efx) 1 | 18 | #define EFX_WORKAROUND_ALWAYS(efx) 1 |
19 | #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) | 19 | #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) |
20 | #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) | ||
20 | #define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) | 21 | #define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) |
21 | #define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) | 22 | #define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) |
22 | 23 | ||
@@ -25,7 +26,7 @@ | |||
25 | /* RX PCIe double split performance issue */ | 26 | /* RX PCIe double split performance issue */ |
26 | #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS | 27 | #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS |
27 | /* Bit-bashed I2C reads cause performance drop */ | 28 | /* Bit-bashed I2C reads cause performance drop */ |
28 | #define EFX_WORKAROUND_7884 EFX_WORKAROUND_ALWAYS | 29 | #define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G |
29 | /* TX pkt parser problem with <= 16 byte TXes */ | 30 | /* TX pkt parser problem with <= 16 byte TXes */ |
30 | #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS | 31 | #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS |
31 | /* Low rate CRC errors require XAUI reset */ | 32 | /* Low rate CRC errors require XAUI reset */ |