sfc: Remove efx_nic_dummy_op_int() as redundant with efx_port_dummy_op_int()
[deliverable/linux.git] / drivers / net / sfc / sfe4001.c
CommitLineData
8ceee660
BH
1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2007 Solarflare Communications Inc.
4 *
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
7 * by the Free Software Foundation, incorporated herein by reference.
8 */
9
10/*****************************************************************************
11 * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that
12 * controls the PHY power rails, and for the MAX6647 temp. sensor used to check
13 * the PHY
14 */
15#include <linux/delay.h>
f8b87c17 16#include "net_driver.h"
8ceee660
BH
17#include "efx.h"
18#include "phy.h"
19#include "boards.h"
20#include "falcon.h"
21#include "falcon_hwdefs.h"
22#include "mac.h"
23
24/**************************************************************************
25 *
26 * I2C IO Expander device
27 *
28 **************************************************************************/
29#define PCA9539 0x74
30
31#define P0_IN 0x00
32#define P0_OUT 0x02
33#define P0_INVERT 0x04
34#define P0_CONFIG 0x06
35
36#define P0_EN_1V0X_LBN 0
37#define P0_EN_1V0X_WIDTH 1
38#define P0_EN_1V2_LBN 1
39#define P0_EN_1V2_WIDTH 1
40#define P0_EN_2V5_LBN 2
41#define P0_EN_2V5_WIDTH 1
42#define P0_EN_3V3X_LBN 3
43#define P0_EN_3V3X_WIDTH 1
44#define P0_EN_5V_LBN 4
45#define P0_EN_5V_WIDTH 1
46#define P0_SHORTEN_JTAG_LBN 5
47#define P0_SHORTEN_JTAG_WIDTH 1
48#define P0_X_TRST_LBN 6
49#define P0_X_TRST_WIDTH 1
50#define P0_DSP_RESET_LBN 7
51#define P0_DSP_RESET_WIDTH 1
52
53#define P1_IN 0x01
54#define P1_OUT 0x03
55#define P1_INVERT 0x05
56#define P1_CONFIG 0x07
57
58#define P1_AFE_PWD_LBN 0
59#define P1_AFE_PWD_WIDTH 1
60#define P1_DSP_PWD25_LBN 1
61#define P1_DSP_PWD25_WIDTH 1
62#define P1_RESERVED_LBN 2
63#define P1_RESERVED_WIDTH 2
64#define P1_SPARE_LBN 4
65#define P1_SPARE_WIDTH 4
66
67
68/**************************************************************************
69 *
70 * Temperature Sensor
71 *
72 **************************************************************************/
73#define MAX6647 0x4e
74
75#define RLTS 0x00
76#define RLTE 0x01
77#define RSL 0x02
78#define RCL 0x03
79#define RCRA 0x04
80#define RLHN 0x05
81#define RLLI 0x06
82#define RRHI 0x07
83#define RRLS 0x08
84#define WCRW 0x0a
85#define WLHO 0x0b
86#define WRHA 0x0c
87#define WRLN 0x0e
88#define OSHT 0x0f
89#define REET 0x10
90#define RIET 0x11
91#define RWOE 0x19
92#define RWOI 0x20
93#define HYS 0x21
94#define QUEUE 0x22
95#define MFID 0xfe
96#define REVID 0xff
97
98/* Status bits */
99#define MAX6647_BUSY (1 << 7) /* ADC is converting */
100#define MAX6647_LHIGH (1 << 6) /* Local high temp. alarm */
101#define MAX6647_LLOW (1 << 5) /* Local low temp. alarm */
102#define MAX6647_RHIGH (1 << 4) /* Remote high temp. alarm */
103#define MAX6647_RLOW (1 << 3) /* Remote low temp. alarm */
104#define MAX6647_FAULT (1 << 2) /* DXN/DXP short/open circuit */
105#define MAX6647_EOT (1 << 1) /* Remote junction overtemp. */
106#define MAX6647_IOT (1 << 0) /* Local junction overtemp. */
107
108static const u8 xgphy_max_temperature = 90;
109
37b5a603 110static void sfe4001_poweroff(struct efx_nic *efx)
8ceee660 111{
37b5a603
BH
112 struct i2c_client *ioexp_client = efx->board_info.ioexp_client;
113 struct i2c_client *hwmon_client = efx->board_info.hwmon_client;
8ceee660 114
37b5a603
BH
115 /* Turn off all power rails and disable outputs */
116 i2c_smbus_write_byte_data(ioexp_client, P0_OUT, 0xff);
117 i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, 0xff);
118 i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff);
8ceee660 119
37b5a603
BH
120 /* Clear any over-temperature alert */
121 i2c_smbus_read_byte_data(hwmon_client, RSL);
122}
8ceee660 123
f8b87c17 124static int sfe4001_poweron(struct efx_nic *efx)
37b5a603 125{
f8b87c17
BH
126 struct i2c_client *hwmon_client = efx->board_info.hwmon_client;
127 struct i2c_client *ioexp_client = efx->board_info.ioexp_client;
11f34e69 128 unsigned int i, j;
8ceee660 129 int rc;
37b5a603 130 u8 out;
8ceee660
BH
131 efx_dword_t reg;
132
8ceee660
BH
133 /* Ensure that XGXS and XAUI SerDes are held in reset */
134 EFX_POPULATE_DWORD_7(reg, XX_PWRDNA_EN, 1,
135 XX_PWRDNB_EN, 1,
136 XX_RSTPLLAB_EN, 1,
137 XX_RESETA_EN, 1,
138 XX_RESETB_EN, 1,
139 XX_RSTXGXSRX_EN, 1,
140 XX_RSTXGXSTX_EN, 1);
141 falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
142 udelay(10);
143
8ceee660 144 /* Clear any previous over-temperature alert */
37b5a603
BH
145 rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
146 if (rc < 0)
f8b87c17 147 return rc;
8ceee660
BH
148
149 /* Enable port 0 and port 1 outputs on IO expander */
37b5a603 150 rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00);
8ceee660 151 if (rc)
f8b87c17 152 return rc;
37b5a603
BH
153 rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
154 0xff & ~(1 << P1_SPARE_LBN));
8ceee660 155 if (rc)
37b5a603 156 goto fail_on;
8ceee660 157
11f34e69
BH
158 /* If PHY power is on, turn it all off and wait 1 second to
159 * ensure a full reset.
160 */
161 rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT);
162 if (rc < 0)
163 goto fail_on;
8ceee660
BH
164 out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
165 (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
166 (0 << P0_EN_1V0X_LBN));
11f34e69
BH
167 if (rc != out) {
168 EFX_INFO(efx, "power-cycling PHY\n");
169 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
170 if (rc)
171 goto fail_on;
172 schedule_timeout_uninterruptible(HZ);
173 }
8ceee660 174
11f34e69 175 for (i = 0; i < 20; ++i) {
8ceee660
BH
176 /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
177 out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
178 (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
179 (1 << P0_X_TRST_LBN));
f8b87c17 180 if (efx->phy_mode & PHY_MODE_SPECIAL)
75f2d3ea 181 out |= 1 << P0_EN_3V3X_LBN;
8ceee660 182
37b5a603 183 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
8ceee660 184 if (rc)
37b5a603 185 goto fail_on;
8ceee660
BH
186 msleep(10);
187
188 /* Turn on 1V power rail */
189 out &= ~(1 << P0_EN_1V0X_LBN);
37b5a603 190 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
8ceee660 191 if (rc)
37b5a603 192 goto fail_on;
8ceee660 193
11f34e69 194 EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i);
8ceee660 195
11f34e69
BH
196 /* In flash config mode, DSP does not turn on AFE, so
197 * just wait 1 second.
198 */
f8b87c17 199 if (efx->phy_mode & PHY_MODE_SPECIAL) {
11f34e69 200 schedule_timeout_uninterruptible(HZ);
f8b87c17 201 return 0;
11f34e69
BH
202 }
203
204 for (j = 0; j < 10; ++j) {
205 msleep(100);
206
207 /* Check DSP has asserted AFE power line */
208 rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
209 if (rc < 0)
210 goto fail_on;
211 if (rc & (1 << P1_AFE_PWD_LBN))
f8b87c17 212 return 0;
11f34e69
BH
213 }
214 }
8ceee660 215
11f34e69 216 EFX_INFO(efx, "timed out waiting for DSP boot\n");
8ceee660 217 rc = -ETIMEDOUT;
f8b87c17
BH
218fail_on:
219 sfe4001_poweroff(efx);
220 return rc;
221}
222
223/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
224 * using the 3V3X output of the IO-expander. Allow the user to set
225 * this when the device is stopped, and keep it stopped then.
226 */
227
228static ssize_t show_phy_flash_cfg(struct device *dev,
229 struct device_attribute *attr, char *buf)
230{
231 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
232 return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL));
233}
234
235static ssize_t set_phy_flash_cfg(struct device *dev,
236 struct device_attribute *attr,
237 const char *buf, size_t count)
238{
239 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
240 enum efx_phy_mode old_mode, new_mode;
241 int err;
242
243 rtnl_lock();
244 old_mode = efx->phy_mode;
245 if (count == 0 || *buf == '0')
246 new_mode = old_mode & ~PHY_MODE_SPECIAL;
247 else
248 new_mode = PHY_MODE_SPECIAL;
249 if (old_mode == new_mode) {
250 err = 0;
251 } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
252 err = -EBUSY;
253 } else {
254 efx->phy_mode = new_mode;
255 err = sfe4001_poweron(efx);
256 efx_reconfigure_port(efx);
257 }
258 rtnl_unlock();
259
260 return err ? err : count;
261}
262
263static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg);
264
265static void sfe4001_fini(struct efx_nic *efx)
266{
267 EFX_INFO(efx, "%s\n", __func__);
268
269 device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
270 sfe4001_poweroff(efx);
271 i2c_unregister_device(efx->board_info.ioexp_client);
272 i2c_unregister_device(efx->board_info.hwmon_client);
273}
274
275/* This board uses an I2C expander to provider power to the PHY, which needs to
276 * be turned on before the PHY can be used.
277 * Context: Process context, rtnl lock held
278 */
279int sfe4001_init(struct efx_nic *efx)
280{
281 struct i2c_client *hwmon_client;
282 int rc;
283
284 hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647);
285 if (!hwmon_client)
286 return -EIO;
287 efx->board_info.hwmon_client = hwmon_client;
288
289 /* Set DSP over-temperature alert threshold */
290 EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
291 rc = i2c_smbus_write_byte_data(hwmon_client, WLHO,
292 xgphy_max_temperature);
293 if (rc)
294 goto fail_ioexp;
295
296 /* Read it back and verify */
297 rc = i2c_smbus_read_byte_data(hwmon_client, RLHN);
298 if (rc < 0)
299 goto fail_ioexp;
300 if (rc != xgphy_max_temperature) {
301 rc = -EFAULT;
302 goto fail_ioexp;
303 }
304
305 efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
306 if (!efx->board_info.ioexp_client) {
307 rc = -EIO;
308 goto fail_hwmon;
309 }
310
311 /* 10Xpress has fixed-function LED pins, so there is no board-specific
312 * blink code. */
313 efx->board_info.blink = tenxpress_phy_blink;
314
315 efx->board_info.fini = sfe4001_fini;
316
317 rc = sfe4001_poweron(efx);
318 if (rc)
319 goto fail_ioexp;
320
321 rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
322 if (rc)
323 goto fail_on;
8ceee660 324
8ceee660
BH
325 EFX_INFO(efx, "PHY is powered on\n");
326 return 0;
327
37b5a603
BH
328fail_on:
329 sfe4001_poweroff(efx);
330fail_ioexp:
f8b87c17 331 i2c_unregister_device(efx->board_info.ioexp_client);
37b5a603 332fail_hwmon:
f8b87c17 333 i2c_unregister_device(hwmon_client);
8ceee660
BH
334 return rc;
335}
This page took 0.135356 seconds and 5 git commands to generate.