aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1251_boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1251_boot.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c266
1 files changed, 248 insertions, 18 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index d8a155dc2fa1..592c3b5cc8f8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -23,15 +23,12 @@
23 23
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25 25
26#include "reg.h" 26#include "wl1251_reg.h"
27#include "wl1251_boot.h" 27#include "wl1251_boot.h"
28#include "wl1251_io.h"
28#include "wl1251_spi.h" 29#include "wl1251_spi.h"
29#include "wl1251_event.h" 30#include "wl1251_event.h"
30 31#include "wl1251_acx.h"
31static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
32{
33 enable_irq(wl->irq);
34}
35 32
36void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) 33void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
37{ 34{
@@ -212,18 +209,30 @@ int wl1251_boot_init_seq(struct wl1251 *wl)
212 return 0; 209 return 0;
213} 210}
214 211
212static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
213{
214 u32 cpu_ctrl;
215
216 /* 10.5.0 run the firmware (I) */
217 cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
218
219 /* 10.5.1 run the firmware (II) */
220 cpu_ctrl &= ~flag;
221 wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
222}
223
215int wl1251_boot_run_firmware(struct wl1251 *wl) 224int wl1251_boot_run_firmware(struct wl1251 *wl)
216{ 225{
217 int loop, ret; 226 int loop, ret;
218 u32 chip_id, interrupt; 227 u32 chip_id, interrupt;
219 228
220 wl->chip.op_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); 229 wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
221 230
222 chip_id = wl1251_reg_read32(wl, CHIP_ID_B); 231 chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
223 232
224 wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); 233 wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
225 234
226 if (chip_id != wl->chip.id) { 235 if (chip_id != wl->chip_id) {
227 wl1251_error("chip id doesn't match after firmware boot"); 236 wl1251_error("chip id doesn't match after firmware boot");
228 return -EIO; 237 return -EIO;
229 } 238 }
@@ -240,9 +249,9 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
240 return -EIO; 249 return -EIO;
241 } 250 }
242 /* check that ACX_INTR_INIT_COMPLETE is enabled */ 251 /* check that ACX_INTR_INIT_COMPLETE is enabled */
243 else if (interrupt & wl->chip.intr_init_complete) { 252 else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) {
244 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, 253 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
245 wl->chip.intr_init_complete); 254 WL1251_ACX_INTR_INIT_COMPLETE);
246 break; 255 break;
247 } 256 }
248 } 257 }
@@ -260,16 +269,15 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
260 wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); 269 wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
261 270
262 /* set the working partition to its "running" mode offset */ 271 /* set the working partition to its "running" mode offset */
263 wl1251_set_partition(wl, 272 wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
264 wl->chip.p_table[PART_WORK].mem.start, 273 WL1251_PART_WORK_MEM_SIZE,
265 wl->chip.p_table[PART_WORK].mem.size, 274 WL1251_PART_WORK_REG_START,
266 wl->chip.p_table[PART_WORK].reg.start, 275 WL1251_PART_WORK_REG_SIZE);
267 wl->chip.p_table[PART_WORK].reg.size);
268 276
269 wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", 277 wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
270 wl->cmd_box_addr, wl->event_box_addr); 278 wl->cmd_box_addr, wl->event_box_addr);
271 279
272 wl->chip.op_fw_version(wl); 280 wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
273 281
274 /* 282 /*
275 * in case of full asynchronous mode the firmware event must be 283 * in case of full asynchronous mode the firmware event must be
@@ -277,9 +285,16 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
277 */ 285 */
278 286
279 /* enable gpio interrupts */ 287 /* enable gpio interrupts */
280 wl1251_boot_enable_interrupts(wl); 288 wl1251_enable_interrupts(wl);
281 289
282 wl->chip.op_target_enable_interrupts(wl); 290 /* Enable target's interrupts */
291 wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
292 WL1251_ACX_INTR_RX1_DATA |
293 WL1251_ACX_INTR_TX_RESULT |
294 WL1251_ACX_INTR_EVENT_A |
295 WL1251_ACX_INTR_EVENT_B |
296 WL1251_ACX_INTR_INIT_COMPLETE;
297 wl1251_boot_target_enable_interrupts(wl);
283 298
284 /* unmask all mbox events */ 299 /* unmask all mbox events */
285 wl->event_mask = 0xffffffff; 300 wl->event_mask = 0xffffffff;
@@ -295,3 +310,218 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
295 /* firmware startup completed */ 310 /* firmware startup completed */
296 return 0; 311 return 0;
297} 312}
313
314static int wl1251_boot_upload_firmware(struct wl1251 *wl)
315{
316 int addr, chunk_num, partition_limit;
317 size_t fw_data_len;
318 u8 *p;
319
320 /* whal_FwCtrl_LoadFwImageSm() */
321
322 wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
323 wl1251_reg_read32(wl, CHIP_ID_B));
324
325 /* 10.0 check firmware length and set partition */
326 fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
327 (wl->fw[6] << 8) | (wl->fw[7]);
328
329 wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
330 CHUNK_SIZE);
331
332 if ((fw_data_len % 4) != 0) {
333 wl1251_error("firmware length not multiple of four");
334 return -EIO;
335 }
336
337 wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
338 WL1251_PART_DOWN_MEM_SIZE,
339 WL1251_PART_DOWN_REG_START,
340 WL1251_PART_DOWN_REG_SIZE);
341
342 /* 10.1 set partition limit and chunk num */
343 chunk_num = 0;
344 partition_limit = WL1251_PART_DOWN_MEM_SIZE;
345
346 while (chunk_num < fw_data_len / CHUNK_SIZE) {
347 /* 10.2 update partition, if needed */
348 addr = WL1251_PART_DOWN_MEM_START +
349 (chunk_num + 2) * CHUNK_SIZE;
350 if (addr > partition_limit) {
351 addr = WL1251_PART_DOWN_MEM_START +
352 chunk_num * CHUNK_SIZE;
353 partition_limit = chunk_num * CHUNK_SIZE +
354 WL1251_PART_DOWN_MEM_SIZE;
355 wl1251_set_partition(wl,
356 addr,
357 WL1251_PART_DOWN_MEM_SIZE,
358 WL1251_PART_DOWN_REG_START,
359 WL1251_PART_DOWN_REG_SIZE);
360 }
361
362 /* 10.3 upload the chunk */
363 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
364 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
365 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
366 p, addr);
367 wl1251_mem_write(wl, addr, p, CHUNK_SIZE);
368
369 chunk_num++;
370 }
371
372 /* 10.4 upload the last chunk */
373 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
374 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
375 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
376 fw_data_len % CHUNK_SIZE, p, addr);
377 wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
378
379 return 0;
380}
381
382static int wl1251_boot_upload_nvs(struct wl1251 *wl)
383{
384 size_t nvs_len, nvs_bytes_written, burst_len;
385 int nvs_start, i;
386 u32 dest_addr, val;
387 u8 *nvs_ptr, *nvs;
388
389 nvs = wl->nvs;
390 if (nvs == NULL)
391 return -ENODEV;
392
393 nvs_ptr = nvs;
394
395 nvs_len = wl->nvs_len;
396 nvs_start = wl->fw_len;
397
398 /*
399 * Layout before the actual NVS tables:
400 * 1 byte : burst length.
401 * 2 bytes: destination address.
402 * n bytes: data to burst copy.
403 *
404 * This is ended by a 0 length, then the NVS tables.
405 */
406
407 while (nvs_ptr[0]) {
408 burst_len = nvs_ptr[0];
409 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
410
411 /* We move our pointer to the data */
412 nvs_ptr += 3;
413
414 for (i = 0; i < burst_len; i++) {
415 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
416 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
417
418 wl1251_debug(DEBUG_BOOT,
419 "nvs burst write 0x%x: 0x%x",
420 dest_addr, val);
421 wl1251_mem_write32(wl, dest_addr, val);
422
423 nvs_ptr += 4;
424 dest_addr += 4;
425 }
426 }
427
428 /*
429 * We've reached the first zero length, the first NVS table
430 * is 7 bytes further.
431 */
432 nvs_ptr += 7;
433 nvs_len -= nvs_ptr - nvs;
434 nvs_len = ALIGN(nvs_len, 4);
435
436 /* Now we must set the partition correctly */
437 wl1251_set_partition(wl, nvs_start,
438 WL1251_PART_DOWN_MEM_SIZE,
439 WL1251_PART_DOWN_REG_START,
440 WL1251_PART_DOWN_REG_SIZE);
441
442 /* And finally we upload the NVS tables */
443 nvs_bytes_written = 0;
444 while (nvs_bytes_written < nvs_len) {
445 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
446 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
447
448 val = cpu_to_le32(val);
449
450 wl1251_debug(DEBUG_BOOT,
451 "nvs write table 0x%x: 0x%x",
452 nvs_start, val);
453 wl1251_mem_write32(wl, nvs_start, val);
454
455 nvs_ptr += 4;
456 nvs_bytes_written += 4;
457 nvs_start += 4;
458 }
459
460 return 0;
461}
462
463int wl1251_boot(struct wl1251 *wl)
464{
465 int ret = 0, minor_minor_e2_ver;
466 u32 tmp, boot_data;
467
468 ret = wl1251_boot_soft_reset(wl);
469 if (ret < 0)
470 goto out;
471
472 /* 2. start processing NVS file */
473 ret = wl1251_boot_upload_nvs(wl);
474 if (ret < 0)
475 goto out;
476
477 /* write firmware's last address (ie. it's length) to
478 * ACX_EEPROMLESS_IND_REG */
479 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
480
481 /* 6. read the EEPROM parameters */
482 tmp = wl1251_reg_read32(wl, SCR_PAD2);
483
484 /* 7. read bootdata */
485 wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
486 wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
487 tmp = wl1251_reg_read32(wl, SCR_PAD3);
488
489 /* 8. check bootdata and call restart sequence */
490 wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
491 minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
492
493 wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
494 "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
495 wl->boot_attr.radio_type, wl->boot_attr.major,
496 wl->boot_attr.minor, minor_minor_e2_ver);
497
498 ret = wl1251_boot_init_seq(wl);
499 if (ret < 0)
500 goto out;
501
502 /* 9. NVS processing done */
503 boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
504
505 wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
506
507 /* 10. check that ECPU_CONTROL_HALT bits are set in
508 * pWhalBus->uBootData and start uploading firmware
509 */
510 if ((boot_data & ECPU_CONTROL_HALT) == 0) {
511 wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
512 ret = -EIO;
513 goto out;
514 }
515
516 ret = wl1251_boot_upload_firmware(wl);
517 if (ret < 0)
518 goto out;
519
520 /* 10.5 start firmware */
521 ret = wl1251_boot_run_firmware(wl);
522 if (ret < 0)
523 goto out;
524
525out:
526 return ret;
527}