diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1251_boot.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_boot.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 452d748e42c6..d5ac79aeaa73 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include "wl1251_reg.h" | 27 | #include "wl1251_reg.h" |
27 | #include "wl1251_boot.h" | 28 | #include "wl1251_boot.h" |
@@ -256,7 +257,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
256 | } | 257 | } |
257 | } | 258 | } |
258 | 259 | ||
259 | if (loop >= INIT_LOOP) { | 260 | if (loop > INIT_LOOP) { |
260 | wl1251_error("timeout waiting for the hardware to " | 261 | wl1251_error("timeout waiting for the hardware to " |
261 | "complete initialization"); | 262 | "complete initialization"); |
262 | return -EIO; | 263 | return -EIO; |
@@ -296,8 +297,12 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
296 | WL1251_ACX_INTR_INIT_COMPLETE; | 297 | WL1251_ACX_INTR_INIT_COMPLETE; |
297 | wl1251_boot_target_enable_interrupts(wl); | 298 | wl1251_boot_target_enable_interrupts(wl); |
298 | 299 | ||
299 | /* unmask all mbox events */ | 300 | wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID | |
300 | wl->event_mask = 0xffffffff; | 301 | SYNCHRONIZATION_TIMEOUT_EVENT_ID | |
302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | ||
303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | ||
304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | ||
305 | BT_PTA_PREDICTION_EVENT_ID; | ||
301 | 306 | ||
302 | ret = wl1251_event_unmask(wl); | 307 | ret = wl1251_event_unmask(wl); |
303 | if (ret < 0) { | 308 | if (ret < 0) { |
@@ -314,8 +319,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
314 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) | 319 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) |
315 | { | 320 | { |
316 | int addr, chunk_num, partition_limit; | 321 | int addr, chunk_num, partition_limit; |
317 | size_t fw_data_len; | 322 | size_t fw_data_len, len; |
318 | u8 *p; | 323 | u8 *p, *buf; |
319 | 324 | ||
320 | /* whal_FwCtrl_LoadFwImageSm() */ | 325 | /* whal_FwCtrl_LoadFwImageSm() */ |
321 | 326 | ||
@@ -334,6 +339,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
334 | return -EIO; | 339 | return -EIO; |
335 | } | 340 | } |
336 | 341 | ||
342 | buf = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
343 | if (!buf) { | ||
344 | wl1251_error("allocation for firmware upload chunk failed"); | ||
345 | return -ENOMEM; | ||
346 | } | ||
347 | |||
337 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, | 348 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, |
338 | WL1251_PART_DOWN_MEM_SIZE, | 349 | WL1251_PART_DOWN_MEM_SIZE, |
339 | WL1251_PART_DOWN_REG_START, | 350 | WL1251_PART_DOWN_REG_START, |
@@ -364,7 +375,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
364 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 375 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
365 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 376 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
366 | p, addr); | 377 | p, addr); |
367 | wl1251_mem_write(wl, addr, p, CHUNK_SIZE); | 378 | |
379 | /* need to copy the chunk for dma */ | ||
380 | len = CHUNK_SIZE; | ||
381 | memcpy(buf, p, len); | ||
382 | wl1251_mem_write(wl, addr, buf, len); | ||
368 | 383 | ||
369 | chunk_num++; | 384 | chunk_num++; |
370 | } | 385 | } |
@@ -372,9 +387,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
372 | /* 10.4 upload the last chunk */ | 387 | /* 10.4 upload the last chunk */ |
373 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; | 388 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; |
374 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 389 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
390 | |||
391 | /* need to copy the chunk for dma */ | ||
392 | len = fw_data_len % CHUNK_SIZE; | ||
393 | memcpy(buf, p, len); | ||
394 | |||
375 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", | 395 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", |
376 | fw_data_len % CHUNK_SIZE, p, addr); | 396 | len, p, addr); |
377 | wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); | 397 | wl1251_mem_write(wl, addr, buf, len); |
398 | |||
399 | kfree(buf); | ||
378 | 400 | ||
379 | return 0; | 401 | return 0; |
380 | } | 402 | } |
@@ -473,13 +495,19 @@ int wl1251_boot(struct wl1251 *wl) | |||
473 | goto out; | 495 | goto out; |
474 | 496 | ||
475 | /* 2. start processing NVS file */ | 497 | /* 2. start processing NVS file */ |
476 | ret = wl1251_boot_upload_nvs(wl); | 498 | if (wl->use_eeprom) { |
477 | if (ret < 0) | 499 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); |
478 | goto out; | 500 | msleep(4000); |
479 | 501 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | |
480 | /* write firmware's last address (ie. it's length) to | 502 | } else { |
481 | * ACX_EEPROMLESS_IND_REG */ | 503 | ret = wl1251_boot_upload_nvs(wl); |
482 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); | 504 | if (ret < 0) |
505 | goto out; | ||
506 | |||
507 | /* write firmware's last address (ie. it's length) to | ||
508 | * ACX_EEPROMLESS_IND_REG */ | ||
509 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); | ||
510 | } | ||
483 | 511 | ||
484 | /* 6. read the EEPROM parameters */ | 512 | /* 6. read the EEPROM parameters */ |
485 | tmp = wl1251_reg_read32(wl, SCR_PAD2); | 513 | tmp = wl1251_reg_read32(wl, SCR_PAD2); |