diff options
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio.c')
-rw-r--r-- | drivers/net/wimax/i2400m/sdio.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 777c981676fc..2538825d1c66 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c | |||
@@ -78,6 +78,14 @@ static const char *i2400ms_bus_fw_names[] = { | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | 80 | ||
81 | static const struct i2400m_poke_table i2400ms_pokes[] = { | ||
82 | I2400M_FW_POKE(0x6BE260, 0x00000088), | ||
83 | I2400M_FW_POKE(0x080550, 0x00000005), | ||
84 | I2400M_FW_POKE(0xAE0000, 0x00000000), | ||
85 | I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad | ||
86 | * things will happen */ | ||
87 | }; | ||
88 | |||
81 | /* | 89 | /* |
82 | * Enable the SDIO function | 90 | * Enable the SDIO function |
83 | * | 91 | * |
@@ -148,19 +156,14 @@ int i2400ms_bus_dev_start(struct i2400m *i2400m) | |||
148 | 156 | ||
149 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 157 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
150 | msleep(200); | 158 | msleep(200); |
151 | result = i2400ms_rx_setup(i2400ms); | ||
152 | if (result < 0) | ||
153 | goto error_rx_setup; | ||
154 | result = i2400ms_tx_setup(i2400ms); | 159 | result = i2400ms_tx_setup(i2400ms); |
155 | if (result < 0) | 160 | if (result < 0) |
156 | goto error_tx_setup; | 161 | goto error_tx_setup; |
157 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | 162 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); |
158 | return result; | 163 | return result; |
159 | 164 | ||
160 | i2400ms_tx_release(i2400ms); | ||
161 | error_tx_setup: | 165 | error_tx_setup: |
162 | i2400ms_rx_release(i2400ms); | 166 | i2400ms_tx_release(i2400ms); |
163 | error_rx_setup: | ||
164 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | 167 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); |
165 | return result; | 168 | return result; |
166 | } | 169 | } |
@@ -174,7 +177,6 @@ void i2400ms_bus_dev_stop(struct i2400m *i2400m) | |||
174 | struct device *dev = &func->dev; | 177 | struct device *dev = &func->dev; |
175 | 178 | ||
176 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 179 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
177 | i2400ms_rx_release(i2400ms); | ||
178 | i2400ms_tx_release(i2400ms); | 180 | i2400ms_tx_release(i2400ms); |
179 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | 181 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); |
180 | } | 182 | } |
@@ -255,7 +257,7 @@ error_kzalloc: | |||
255 | static | 257 | static |
256 | int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | 258 | int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) |
257 | { | 259 | { |
258 | int result; | 260 | int result = 0; |
259 | struct i2400ms *i2400ms = | 261 | struct i2400ms *i2400ms = |
260 | container_of(i2400m, struct i2400ms, i2400m); | 262 | container_of(i2400m, struct i2400ms, i2400m); |
261 | struct device *dev = i2400m_dev(i2400m); | 263 | struct device *dev = i2400m_dev(i2400m); |
@@ -280,8 +282,25 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | |||
280 | sizeof(i2400m_COLD_BOOT_BARKER)); | 282 | sizeof(i2400m_COLD_BOOT_BARKER)); |
281 | else if (rt == I2400M_RT_BUS) { | 283 | else if (rt == I2400M_RT_BUS) { |
282 | do_bus_reset: | 284 | do_bus_reset: |
283 | dev_err(dev, "FIXME: SDIO bus reset not implemented\n"); | 285 | /* call netif_tx_disable() before sending IOE disable, |
284 | result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS; | 286 | * so that all the tx from network layer are stopped |
287 | * while IOE is being reset. Make sure it is called | ||
288 | * only after register_netdev() was issued. | ||
289 | */ | ||
290 | if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) | ||
291 | netif_tx_disable(i2400m->wimax_dev.net_dev); | ||
292 | |||
293 | i2400ms_rx_release(i2400ms); | ||
294 | sdio_claim_host(i2400ms->func); | ||
295 | sdio_disable_func(i2400ms->func); | ||
296 | sdio_release_host(i2400ms->func); | ||
297 | |||
298 | /* Wait for the device to settle */ | ||
299 | msleep(40); | ||
300 | |||
301 | result = i2400ms_enable_function(i2400ms->func); | ||
302 | if (result >= 0) | ||
303 | i2400ms_rx_setup(i2400ms); | ||
285 | } else | 304 | } else |
286 | BUG(); | 305 | BUG(); |
287 | if (result < 0 && rt != I2400M_RT_BUS) { | 306 | if (result < 0 && rt != I2400M_RT_BUS) { |
@@ -404,10 +423,14 @@ int i2400ms_probe(struct sdio_func *func, | |||
404 | i2400m->bus_dev_stop = i2400ms_bus_dev_stop; | 423 | i2400m->bus_dev_stop = i2400ms_bus_dev_stop; |
405 | i2400m->bus_tx_kick = i2400ms_bus_tx_kick; | 424 | i2400m->bus_tx_kick = i2400ms_bus_tx_kick; |
406 | i2400m->bus_reset = i2400ms_bus_reset; | 425 | i2400m->bus_reset = i2400ms_bus_reset; |
426 | /* The iwmc3200-wimax sometimes requires the driver to try | ||
427 | * hard when we paint it into a corner. */ | ||
428 | i2400m->bus_bm_retries = I3200_BOOT_RETRIES; | ||
407 | i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; | 429 | i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; |
408 | i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; | 430 | i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; |
409 | i2400m->bus_fw_names = i2400ms_bus_fw_names; | 431 | i2400m->bus_fw_names = i2400ms_bus_fw_names; |
410 | i2400m->bus_bm_mac_addr_impaired = 1; | 432 | i2400m->bus_bm_mac_addr_impaired = 1; |
433 | i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; | ||
411 | 434 | ||
412 | sdio_claim_host(func); | 435 | sdio_claim_host(func); |
413 | result = sdio_set_block_size(func, I2400MS_BLK_SIZE); | 436 | result = sdio_set_block_size(func, I2400MS_BLK_SIZE); |
@@ -423,6 +446,10 @@ int i2400ms_probe(struct sdio_func *func, | |||
423 | goto error_func_enable; | 446 | goto error_func_enable; |
424 | } | 447 | } |
425 | 448 | ||
449 | result = i2400ms_rx_setup(i2400ms); | ||
450 | if (result < 0) | ||
451 | goto error_rx_setup; | ||
452 | |||
426 | result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); | 453 | result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); |
427 | if (result < 0) { | 454 | if (result < 0) { |
428 | dev_err(dev, "cannot setup device: %d\n", result); | 455 | dev_err(dev, "cannot setup device: %d\n", result); |
@@ -440,6 +467,8 @@ int i2400ms_probe(struct sdio_func *func, | |||
440 | error_debugfs_add: | 467 | error_debugfs_add: |
441 | i2400m_release(i2400m); | 468 | i2400m_release(i2400m); |
442 | error_setup: | 469 | error_setup: |
470 | i2400ms_rx_release(i2400ms); | ||
471 | error_rx_setup: | ||
443 | sdio_claim_host(func); | 472 | sdio_claim_host(func); |
444 | sdio_disable_func(func); | 473 | sdio_disable_func(func); |
445 | sdio_release_host(func); | 474 | sdio_release_host(func); |
@@ -462,6 +491,7 @@ void i2400ms_remove(struct sdio_func *func) | |||
462 | 491 | ||
463 | d_fnstart(3, dev, "SDIO func %p\n", func); | 492 | d_fnstart(3, dev, "SDIO func %p\n", func); |
464 | debugfs_remove_recursive(i2400ms->debugfs_dentry); | 493 | debugfs_remove_recursive(i2400ms->debugfs_dentry); |
494 | i2400ms_rx_release(i2400ms); | ||
465 | i2400m_release(i2400m); | 495 | i2400m_release(i2400m); |
466 | sdio_set_drvdata(func, NULL); | 496 | sdio_set_drvdata(func, NULL); |
467 | sdio_claim_host(func); | 497 | sdio_claim_host(func); |