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/sfe4001.c | |
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/sfe4001.c')
-rw-r--r-- | drivers/net/sfc/sfe4001.c | 153 |
1 files changed, 122 insertions, 31 deletions
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 | } | ||