diff options
Diffstat (limited to 'drivers/net/sfc/sfe4001.c')
-rw-r--r-- | drivers/net/sfc/sfe4001.c | 248 |
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 | ||
123 | static void sfe4001_fini(struct efx_nic *efx) | 125 | static 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; | ||
207 | fail_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 | */ |
136 | unsigned int sfe4001_phy_flash_cfg; | 216 | |
137 | module_param_named(phy_flash_cfg, sfe4001_phy_flash_cfg, uint, 0444); | 217 | static ssize_t show_phy_flash_cfg(struct device *dev, |
138 | MODULE_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 | |||
224 | static 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 | |||
252 | static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg); | ||
253 | |||
254 | static 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 | */ |
145 | int sfe4001_init(struct efx_nic *efx) | 268 | int 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, ®, 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 | |||
261 | done: | ||
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 | ||
265 | fail_on: | 317 | fail_on: |
266 | sfe4001_poweroff(efx); | 318 | sfe4001_poweroff(efx); |
267 | fail_ioexp: | 319 | fail_ioexp: |
268 | i2c_unregister_device(ioexp_client); | 320 | i2c_unregister_device(efx->board_info.ioexp_client); |
269 | fail_hwmon: | 321 | fail_hwmon: |
270 | i2c_unregister_device(hwmon_client); | 322 | i2c_unregister_device(hwmon_client); |
271 | return rc; | 323 | return rc; |
272 | } | 324 | } |