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.c248
1 files changed, 150 insertions, 98 deletions
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index b27849523990..fe4e3fd22330 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -13,11 +13,13 @@
13 * the PHY 13 * the PHY
14 */ 14 */
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include "net_driver.h"
16#include "efx.h" 17#include "efx.h"
17#include "phy.h" 18#include "phy.h"
18#include "boards.h" 19#include "boards.h"
19#include "falcon.h" 20#include "falcon.h"
20#include "falcon_hwdefs.h" 21#include "falcon_hwdefs.h"
22#include "falcon_io.h"
21#include "mac.h" 23#include "mac.h"
22 24
23/************************************************************************** 25/**************************************************************************
@@ -120,23 +122,144 @@ static void sfe4001_poweroff(struct efx_nic *efx)
120 i2c_smbus_read_byte_data(hwmon_client, RSL); 122 i2c_smbus_read_byte_data(hwmon_client, RSL);
121} 123}
122 124
123static void sfe4001_fini(struct efx_nic *efx) 125static int sfe4001_poweron(struct efx_nic *efx)
124{ 126{
125 EFX_INFO(efx, "%s\n", __func__); 127 struct i2c_client *hwmon_client = efx->board_info.hwmon_client;
128 struct i2c_client *ioexp_client = efx->board_info.ioexp_client;
129 unsigned int i, j;
130 int rc;
131 u8 out;
132
133 /* Clear any previous over-temperature alert */
134 rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
135 if (rc < 0)
136 return rc;
137
138 /* Enable port 0 and port 1 outputs on IO expander */
139 rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00);
140 if (rc)
141 return rc;
142 rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
143 0xff & ~(1 << P1_SPARE_LBN));
144 if (rc)
145 goto fail_on;
146
147 /* If PHY power is on, turn it all off and wait 1 second to
148 * ensure a full reset.
149 */
150 rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT);
151 if (rc < 0)
152 goto fail_on;
153 out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
154 (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
155 (0 << P0_EN_1V0X_LBN));
156 if (rc != out) {
157 EFX_INFO(efx, "power-cycling PHY\n");
158 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
159 if (rc)
160 goto fail_on;
161 schedule_timeout_uninterruptible(HZ);
162 }
126 163
164 for (i = 0; i < 20; ++i) {
165 /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
166 out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
167 (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
168 (1 << P0_X_TRST_LBN));
169 if (efx->phy_mode & PHY_MODE_SPECIAL)
170 out |= 1 << P0_EN_3V3X_LBN;
171
172 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
173 if (rc)
174 goto fail_on;
175 msleep(10);
176
177 /* Turn on 1V power rail */
178 out &= ~(1 << P0_EN_1V0X_LBN);
179 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
180 if (rc)
181 goto fail_on;
182
183 EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i);
184
185 /* In flash config mode, DSP does not turn on AFE, so
186 * just wait 1 second.
187 */
188 if (efx->phy_mode & PHY_MODE_SPECIAL) {
189 schedule_timeout_uninterruptible(HZ);
190 return 0;
191 }
192
193 for (j = 0; j < 10; ++j) {
194 msleep(100);
195
196 /* Check DSP has asserted AFE power line */
197 rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
198 if (rc < 0)
199 goto fail_on;
200 if (rc & (1 << P1_AFE_PWD_LBN))
201 return 0;
202 }
203 }
204
205 EFX_INFO(efx, "timed out waiting for DSP boot\n");
206 rc = -ETIMEDOUT;
207fail_on:
127 sfe4001_poweroff(efx); 208 sfe4001_poweroff(efx);
128 i2c_unregister_device(efx->board_info.ioexp_client); 209 return rc;
129 i2c_unregister_device(efx->board_info.hwmon_client);
130} 210}
131 211
132/* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected 212/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
133 * to the FLASH_CFG_1 input on the DSP. We must keep it high at power- 213 * using the 3V3X output of the IO-expander. Allow the user to set
134 * up to allow writing the flash (done through MDIO from userland). 214 * this when the device is stopped, and keep it stopped then.
135 */ 215 */
136unsigned int sfe4001_phy_flash_cfg; 216
137module_param_named(phy_flash_cfg, sfe4001_phy_flash_cfg, uint, 0444); 217static ssize_t show_phy_flash_cfg(struct device *dev,
138MODULE_PARM_DESC(phy_flash_cfg, 218 struct device_attribute *attr, char *buf)
139 "Force PHY to enter flash configuration mode"); 219{
220 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
221 return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL));
222}
223
224static ssize_t set_phy_flash_cfg(struct device *dev,
225 struct device_attribute *attr,
226 const char *buf, size_t count)
227{
228 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
229 enum efx_phy_mode old_mode, new_mode;
230 int err;
231
232 rtnl_lock();
233 old_mode = efx->phy_mode;
234 if (count == 0 || *buf == '0')
235 new_mode = old_mode & ~PHY_MODE_SPECIAL;
236 else
237 new_mode = PHY_MODE_SPECIAL;
238 if (old_mode == new_mode) {
239 err = 0;
240 } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
241 err = -EBUSY;
242 } else {
243 efx->phy_mode = new_mode;
244 err = sfe4001_poweron(efx);
245 efx_reconfigure_port(efx);
246 }
247 rtnl_unlock();
248
249 return err ? err : count;
250}
251
252static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg);
253
254static void sfe4001_fini(struct efx_nic *efx)
255{
256 EFX_INFO(efx, "%s\n", __func__);
257
258 device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
259 sfe4001_poweroff(efx);
260 i2c_unregister_device(efx->board_info.ioexp_client);
261 i2c_unregister_device(efx->board_info.hwmon_client);
262}
140 263
141/* This board uses an I2C expander to provider power to the PHY, which needs to 264/* This board uses an I2C expander to provider power to the PHY, which needs to
142 * be turned on before the PHY can be used. 265 * be turned on before the PHY can be used.
@@ -144,41 +267,14 @@ MODULE_PARM_DESC(phy_flash_cfg,
144 */ 267 */
145int sfe4001_init(struct efx_nic *efx) 268int sfe4001_init(struct efx_nic *efx)
146{ 269{
147 struct i2c_client *hwmon_client, *ioexp_client; 270 struct i2c_client *hwmon_client;
148 unsigned int count;
149 int rc; 271 int rc;
150 u8 out;
151 efx_dword_t reg;
152 272
153 hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647); 273 hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647);
154 if (!hwmon_client) 274 if (!hwmon_client)
155 return -EIO; 275 return -EIO;
156 efx->board_info.hwmon_client = hwmon_client; 276 efx->board_info.hwmon_client = hwmon_client;
157 277
158 ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
159 if (!ioexp_client) {
160 rc = -EIO;
161 goto fail_hwmon;
162 }
163 efx->board_info.ioexp_client = ioexp_client;
164
165 /* 10Xpress has fixed-function LED pins, so there is no board-specific
166 * blink code. */
167 efx->board_info.blink = tenxpress_phy_blink;
168
169 /* Ensure that XGXS and XAUI SerDes are held in reset */
170 EFX_POPULATE_DWORD_7(reg, XX_PWRDNA_EN, 1,
171 XX_PWRDNB_EN, 1,
172 XX_RSTPLLAB_EN, 1,
173 XX_RESETA_EN, 1,
174 XX_RESETB_EN, 1,
175 XX_RSTXGXSRX_EN, 1,
176 XX_RSTXGXSTX_EN, 1);
177 falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
178 udelay(10);
179
180 efx->board_info.fini = sfe4001_fini;
181
182 /* Set DSP over-temperature alert threshold */ 278 /* Set DSP over-temperature alert threshold */
183 EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature); 279 EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
184 rc = i2c_smbus_write_byte_data(hwmon_client, WLHO, 280 rc = i2c_smbus_write_byte_data(hwmon_client, WLHO,
@@ -195,78 +291,34 @@ int sfe4001_init(struct efx_nic *efx)
195 goto fail_ioexp; 291 goto fail_ioexp;
196 } 292 }
197 293
198 /* Clear any previous over-temperature alert */ 294 efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
199 rc = i2c_smbus_read_byte_data(hwmon_client, RSL); 295 if (!efx->board_info.ioexp_client) {
200 if (rc < 0) 296 rc = -EIO;
201 goto fail_ioexp; 297 goto fail_hwmon;
298 }
202 299
203 /* Enable port 0 and port 1 outputs on IO expander */ 300 /* 10Xpress has fixed-function LED pins, so there is no board-specific
204 rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00); 301 * blink code. */
302 efx->board_info.blink = tenxpress_phy_blink;
303
304 efx->board_info.fini = sfe4001_fini;
305
306 rc = sfe4001_poweron(efx);
205 if (rc) 307 if (rc)
206 goto fail_ioexp; 308 goto fail_ioexp;
207 rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
208 0xff & ~(1 << P1_SPARE_LBN));
209 if (rc)
210 goto fail_on;
211 309
212 /* Turn all power off then wait 1 sec. This ensures PHY is reset */ 310 rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
213 out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
214 (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
215 (0 << P0_EN_1V0X_LBN));
216 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
217 if (rc) 311 if (rc)
218 goto fail_on; 312 goto fail_on;
219 313
220 schedule_timeout_uninterruptible(HZ);
221 count = 0;
222 do {
223 /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
224 out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
225 (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
226 (1 << P0_X_TRST_LBN));
227 if (sfe4001_phy_flash_cfg)
228 out |= 1 << P0_EN_3V3X_LBN;
229
230 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
231 if (rc)
232 goto fail_on;
233 msleep(10);
234
235 /* Turn on 1V power rail */
236 out &= ~(1 << P0_EN_1V0X_LBN);
237 rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
238 if (rc)
239 goto fail_on;
240
241 EFX_INFO(efx, "waiting for power (attempt %d)...\n", count);
242
243 schedule_timeout_uninterruptible(HZ);
244
245 /* Check DSP is powered */
246 rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
247 if (rc < 0)
248 goto fail_on;
249 if (rc & (1 << P1_AFE_PWD_LBN))
250 goto done;
251
252 /* DSP doesn't look powered in flash config mode */
253 if (sfe4001_phy_flash_cfg)
254 goto done;
255 } while (++count < 20);
256
257 EFX_INFO(efx, "timed out waiting for power\n");
258 rc = -ETIMEDOUT;
259 goto fail_on;
260
261done:
262 EFX_INFO(efx, "PHY is powered on\n"); 314 EFX_INFO(efx, "PHY is powered on\n");
263 return 0; 315 return 0;
264 316
265fail_on: 317fail_on:
266 sfe4001_poweroff(efx); 318 sfe4001_poweroff(efx);
267fail_ioexp: 319fail_ioexp:
268 i2c_unregister_device(ioexp_client); 320 i2c_unregister_device(efx->board_info.ioexp_client);
269fail_hwmon: 321fail_hwmon:
270 i2c_unregister_device(hwmon_client); 322 i2c_unregister_device(hwmon_client);
271 return rc; 323 return rc;
272} 324}