aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/sfe4001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/sfe4001.c')
-rw-r--r--drivers/net/sfc/sfe4001.c116
1 files changed, 53 insertions, 63 deletions
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index fe4e3fd22330..aa576c559ec8 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -21,6 +21,7 @@
21#include "falcon_hwdefs.h" 21#include "falcon_hwdefs.h"
22#include "falcon_io.h" 22#include "falcon_io.h"
23#include "mac.h" 23#include "mac.h"
24#include "workarounds.h"
24 25
25/************************************************************************** 26/**************************************************************************
26 * 27 *
@@ -65,48 +66,9 @@
65#define P1_SPARE_LBN 4 66#define P1_SPARE_LBN 4
66#define P1_SPARE_WIDTH 4 67#define P1_SPARE_WIDTH 4
67 68
68 69/* Temperature Sensor */
69/************************************************************************** 70#define MAX664X_REG_RSL 0x02
70 * 71#define MAX664X_REG_WLHO 0x0B
71 * Temperature Sensor
72 *
73 **************************************************************************/
74#define MAX6647 0x4e
75
76#define RLTS 0x00
77#define RLTE 0x01
78#define RSL 0x02
79#define RCL 0x03
80#define RCRA 0x04
81#define RLHN 0x05
82#define RLLI 0x06
83#define RRHI 0x07
84#define RRLS 0x08
85#define WCRW 0x0a
86#define WLHO 0x0b
87#define WRHA 0x0c
88#define WRLN 0x0e
89#define OSHT 0x0f
90#define REET 0x10
91#define RIET 0x11
92#define RWOE 0x19
93#define RWOI 0x20
94#define HYS 0x21
95#define QUEUE 0x22
96#define MFID 0xfe
97#define REVID 0xff
98
99/* Status bits */
100#define MAX6647_BUSY (1 << 7) /* ADC is converting */
101#define MAX6647_LHIGH (1 << 6) /* Local high temp. alarm */
102#define MAX6647_LLOW (1 << 5) /* Local low temp. alarm */
103#define MAX6647_RHIGH (1 << 4) /* Remote high temp. alarm */
104#define MAX6647_RLOW (1 << 3) /* Remote low temp. alarm */
105#define MAX6647_FAULT (1 << 2) /* DXN/DXP short/open circuit */
106#define MAX6647_EOT (1 << 1) /* Remote junction overtemp. */
107#define MAX6647_IOT (1 << 0) /* Local junction overtemp. */
108
109static const u8 xgphy_max_temperature = 90;
110 72
111static void sfe4001_poweroff(struct efx_nic *efx) 73static void sfe4001_poweroff(struct efx_nic *efx)
112{ 74{
@@ -119,7 +81,7 @@ static void sfe4001_poweroff(struct efx_nic *efx)
119 i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff); 81 i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff);
120 82
121 /* Clear any over-temperature alert */ 83 /* Clear any over-temperature alert */
122 i2c_smbus_read_byte_data(hwmon_client, RSL); 84 i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
123} 85}
124 86
125static int sfe4001_poweron(struct efx_nic *efx) 87static int sfe4001_poweron(struct efx_nic *efx)
@@ -131,7 +93,7 @@ static int sfe4001_poweron(struct efx_nic *efx)
131 u8 out; 93 u8 out;
132 94
133 /* Clear any previous over-temperature alert */ 95 /* Clear any previous over-temperature alert */
134 rc = i2c_smbus_read_byte_data(hwmon_client, RSL); 96 rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
135 if (rc < 0) 97 if (rc < 0)
136 return rc; 98 return rc;
137 99
@@ -209,6 +171,34 @@ fail_on:
209 return rc; 171 return rc;
210} 172}
211 173
174static int sfe4001_check_hw(struct efx_nic *efx)
175{
176 s32 status;
177
178 /* If XAUI link is up then do not monitor */
179 if (EFX_WORKAROUND_7884(efx) && falcon_xaui_link_ok(efx))
180 return 0;
181
182 /* Check the powered status of the PHY. Lack of power implies that
183 * the MAX6647 has shut down power to it, probably due to a temp.
184 * alarm. Reading the power status rather than the MAX6647 status
185 * directly because the later is read-to-clear and would thus
186 * start to power up the PHY again when polled, causing us to blip
187 * the power undesirably.
188 * We know we can read from the IO expander because we did
189 * it during power-on. Assume failure now is bad news. */
190 status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN);
191 if (status >= 0 &&
192 (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0)
193 return 0;
194
195 /* Use board power control, not PHY power control */
196 sfe4001_poweroff(efx);
197 efx->phy_mode = PHY_MODE_OFF;
198
199 return (status < 0) ? -EIO : -ERANGE;
200}
201
212/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin 202/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
213 * using the 3V3X output of the IO-expander. Allow the user to set 203 * using the 3V3X output of the IO-expander. Allow the user to set
214 * this when the device is stopped, and keep it stopped then. 204 * this when the device is stopped, and keep it stopped then.
@@ -261,35 +251,34 @@ static void sfe4001_fini(struct efx_nic *efx)
261 i2c_unregister_device(efx->board_info.hwmon_client); 251 i2c_unregister_device(efx->board_info.hwmon_client);
262} 252}
263 253
254static struct i2c_board_info sfe4001_hwmon_info = {
255 I2C_BOARD_INFO("max6647", 0x4e),
256 .irq = -1,
257};
258
264/* This board uses an I2C expander to provider power to the PHY, which needs to 259/* This board uses an I2C expander to provider power to the PHY, which needs to
265 * be turned on before the PHY can be used. 260 * be turned on before the PHY can be used.
266 * Context: Process context, rtnl lock held 261 * Context: Process context, rtnl lock held
267 */ 262 */
268int sfe4001_init(struct efx_nic *efx) 263int sfe4001_init(struct efx_nic *efx)
269{ 264{
270 struct i2c_client *hwmon_client;
271 int rc; 265 int rc;
272 266
273 hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647); 267#if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE)
274 if (!hwmon_client) 268 efx->board_info.hwmon_client =
269 i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
270#else
271 efx->board_info.hwmon_client =
272 i2c_new_dummy(&efx->i2c_adap, sfe4001_hwmon_info.addr);
273#endif
274 if (!efx->board_info.hwmon_client)
275 return -EIO; 275 return -EIO;
276 efx->board_info.hwmon_client = hwmon_client;
277 276
278 /* Set DSP over-temperature alert threshold */ 277 /* Raise board/PHY high limit from 85 to 90 degrees Celsius */
279 EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature); 278 rc = i2c_smbus_write_byte_data(efx->board_info.hwmon_client,
280 rc = i2c_smbus_write_byte_data(hwmon_client, WLHO, 279 MAX664X_REG_WLHO, 90);
281 xgphy_max_temperature);
282 if (rc) 280 if (rc)
283 goto fail_ioexp; 281 goto fail_hwmon;
284
285 /* Read it back and verify */
286 rc = i2c_smbus_read_byte_data(hwmon_client, RLHN);
287 if (rc < 0)
288 goto fail_ioexp;
289 if (rc != xgphy_max_temperature) {
290 rc = -EFAULT;
291 goto fail_ioexp;
292 }
293 282
294 efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539); 283 efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
295 if (!efx->board_info.ioexp_client) { 284 if (!efx->board_info.ioexp_client) {
@@ -301,6 +290,7 @@ int sfe4001_init(struct efx_nic *efx)
301 * blink code. */ 290 * blink code. */
302 efx->board_info.blink = tenxpress_phy_blink; 291 efx->board_info.blink = tenxpress_phy_blink;
303 292
293 efx->board_info.monitor = sfe4001_check_hw;
304 efx->board_info.fini = sfe4001_fini; 294 efx->board_info.fini = sfe4001_fini;
305 295
306 rc = sfe4001_poweron(efx); 296 rc = sfe4001_poweron(efx);
@@ -319,6 +309,6 @@ fail_on:
319fail_ioexp: 309fail_ioexp:
320 i2c_unregister_device(efx->board_info.ioexp_client); 310 i2c_unregister_device(efx->board_info.ioexp_client);
321fail_hwmon: 311fail_hwmon:
322 i2c_unregister_device(hwmon_client); 312 i2c_unregister_device(efx->board_info.hwmon_client);
323 return rc; 313 return rc;
324} 314}