aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/pcie/trans.c
diff options
context:
space:
mode:
authorEran Harary <eran.harary@intel.com>2014-01-23 09:26:32 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-02-03 15:23:32 -0500
commit189fa2faac49bce07c6c6d83eca21cbe5bf47411 (patch)
tree359d94bf34ed99a36e201bc5f35190ec5ee9e1f5 /drivers/net/wireless/iwlwifi/pcie/trans.c
parente4a9f8cea50406a57c8dc5429d9aca6429d82436 (diff)
iwlwifi: pcie: fix secure section / dual cpu firmware loading
Also handle the bypass mode in which the second CPU doesn't interfere. Signed-off-by: Eran Harary <eran.harary@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/trans.c')
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c191
1 files changed, 103 insertions, 88 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index ff7d70da64f9..7290f422be65 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -441,78 +441,87 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
441 return ret; 441 return ret;
442} 442}
443 443
444static int iwl_pcie_secure_set(struct iwl_trans *trans, int cpu) 444static int iwl_pcie_load_cpu_secured_sections(struct iwl_trans *trans,
445 const struct fw_img *image,
446 int cpu)
445{ 447{
446 int shift_param; 448 int shift_param;
447 u32 address; 449 u32 first_idx, last_idx;
448 int ret = 0; 450 int i, ret = 0;
449 451
450 if (cpu == 1) { 452 if (cpu == 1) {
451 shift_param = 0; 453 shift_param = 0;
452 address = CSR_SECURE_BOOT_CPU1_STATUS_ADDR; 454 first_idx = 0;
455 last_idx = 2;
453 } else { 456 } else {
454 shift_param = 16; 457 shift_param = 16;
455 address = CSR_SECURE_BOOT_CPU2_STATUS_ADDR; 458 first_idx = 3;
459 last_idx = 5;
456 } 460 }
457 461
458 /* set CPU to started */ 462 for (i = first_idx; i <= last_idx; i++) {
459 iwl_trans_set_bits_mask(trans, 463 if (!image->sec[i].data)
460 CSR_UCODE_LOAD_STATUS_ADDR, 464 break;
461 CSR_CPU_STATUS_LOADING_STARTED << shift_param, 465 if (i == first_idx + 1)
462 1); 466 /* set CPU to started */
463 467 iwl_set_bits_prph(trans,
464 /* set last complete descriptor number */ 468 CSR_UCODE_LOAD_STATUS_ADDR,
465 iwl_trans_set_bits_mask(trans, 469 LMPM_CPU_HDRS_LOADING_COMPLETED
466 CSR_UCODE_LOAD_STATUS_ADDR, 470 << shift_param);
467 CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED
468 << shift_param,
469 1);
470
471 /* set last loaded block */
472 iwl_trans_set_bits_mask(trans,
473 CSR_UCODE_LOAD_STATUS_ADDR,
474 CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK
475 << shift_param,
476 1);
477 471
478 /* image loading complete */ 472 ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
479 iwl_trans_set_bits_mask(trans, 473 if (ret)
480 CSR_UCODE_LOAD_STATUS_ADDR, 474 return ret;
481 CSR_CPU_STATUS_LOADING_COMPLETED
482 << shift_param,
483 1);
484
485 /* set FH_TCSR_0_REG */
486 iwl_trans_set_bits_mask(trans, FH_TCSR_0_REG0, 0x00400000, 1);
487
488 /* verify image verification started */
489 ret = iwl_poll_bit(trans, address,
490 CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS,
491 CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS,
492 CSR_SECURE_TIME_OUT);
493 if (ret < 0) {
494 IWL_ERR(trans, "secure boot process didn't start\n");
495 return ret;
496 } 475 }
476 /* image loading complete */
477 iwl_set_bits_prph(trans,
478 CSR_UCODE_LOAD_STATUS_ADDR,
479 LMPM_CPU_UCODE_LOADING_COMPLETED << shift_param);
497 480
498 /* wait for image verification to complete */ 481 return 0;
499 ret = iwl_poll_bit(trans, address, 482}
500 CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED,
501 CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED,
502 CSR_SECURE_TIME_OUT);
503 483
504 if (ret < 0) { 484static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
505 IWL_ERR(trans, "Time out on secure boot process\n"); 485 const struct fw_img *image,
506 return ret; 486 int cpu)
487{
488 int shift_param;
489 u32 first_idx, last_idx;
490 int i, ret = 0;
491
492 if (cpu == 1) {
493 shift_param = 0;
494 first_idx = 0;
495 last_idx = 1;
496 } else {
497 shift_param = 16;
498 first_idx = 2;
499 last_idx = 3;
507 } 500 }
508 501
502 for (i = first_idx; i <= last_idx; i++) {
503 if (!image->sec[i].data)
504 break;
505 ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
506 if (ret)
507 return ret;
508 }
509
510 if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
511 iwl_set_bits_prph(trans,
512 CSR_UCODE_LOAD_STATUS_ADDR,
513 (LMPM_CPU_UCODE_LOADING_COMPLETED |
514 LMPM_CPU_HDRS_LOADING_COMPLETED |
515 LMPM_CPU_UCODE_LOADING_STARTED) <<
516 shift_param);
517
509 return 0; 518 return 0;
510} 519}
511 520
512static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, 521static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
513 const struct fw_img *image) 522 const struct fw_img *image)
514{ 523{
515 int i, ret = 0; 524 int ret = 0;
516 525
517 IWL_DEBUG_FW(trans, 526 IWL_DEBUG_FW(trans,
518 "working with %s image\n", 527 "working with %s image\n",
@@ -524,54 +533,46 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
524 /* configure the ucode to be ready to get the secured image */ 533 /* configure the ucode to be ready to get the secured image */
525 if (image->is_secure) { 534 if (image->is_secure) {
526 /* set secure boot inspector addresses */ 535 /* set secure boot inspector addresses */
527 iwl_write32(trans, CSR_SECURE_INSPECTOR_CODE_ADDR, 0); 536 iwl_write_prph(trans,
528 iwl_write32(trans, CSR_SECURE_INSPECTOR_DATA_ADDR, 0); 537 LMPM_SECURE_INSPECTOR_CODE_ADDR,
538 LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE);
529 539
530 /* release CPU1 reset if secure inspector image burned in OTP */ 540 iwl_write_prph(trans,
531 iwl_write32(trans, CSR_RESET, 0); 541 LMPM_SECURE_INSPECTOR_DATA_ADDR,
532 } 542 LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE);
533 543
534 /* load to FW the binary sections of CPU1 */ 544 /* set CPU1 header address */
535 IWL_DEBUG_INFO(trans, "Loading CPU1\n"); 545 iwl_write_prph(trans,
536 for (i = 0; 546 LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR,
537 i < IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; 547 LMPM_SECURE_CPU1_HDR_MEM_SPACE);
538 i++) { 548
539 if (!image->sec[i].data) 549 /* load to FW the binary Secured sections of CPU1 */
540 break; 550 ret = iwl_pcie_load_cpu_secured_sections(trans, image, 1);
541 ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
542 if (ret) 551 if (ret)
543 return ret; 552 return ret;
544 }
545 553
546 /* configure the ucode to start secure process on CPU1 */ 554 } else {
547 if (image->is_secure) { 555 /* load to FW the binary Non secured sections of CPU1 */
548 /* config CPU1 to start secure protocol */ 556 ret = iwl_pcie_load_cpu_sections(trans, image, 1);
549 ret = iwl_pcie_secure_set(trans, 1);
550 if (ret) 557 if (ret)
551 return ret; 558 return ret;
552 } else {
553 /* Remove all resets to allow NIC to operate */
554 iwl_write32(trans, CSR_RESET, 0);
555 } 559 }
556 560
557 if (image->is_dual_cpus) { 561 if (image->is_dual_cpus) {
558 /* load to FW the binary sections of CPU2 */ 562 /* set CPU2 header address */
559 IWL_DEBUG_INFO(trans, "working w/ DUAL CPUs - Loading CPU2\n"); 563 iwl_write_prph(trans,
560 for (i = IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; 564 LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR,
561 i < IWL_UCODE_SECTION_MAX; i++) { 565 LMPM_SECURE_CPU2_HDR_MEM_SPACE);
562 if (!image->sec[i].data)
563 break;
564 ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
565 if (ret)
566 return ret;
567 }
568 566
569 if (image->is_secure) { 567 /* load to FW the binary sections of CPU2 */
570 /* set CPU2 for secure protocol */ 568 if (image->is_secure)
571 ret = iwl_pcie_secure_set(trans, 2); 569 ret = iwl_pcie_load_cpu_secured_sections(trans,
572 if (ret) 570 image,
573 return ret; 571 2);
574 } 572 else
573 ret = iwl_pcie_load_cpu_sections(trans, image, 2);
574 if (ret)
575 return ret;
575 } 576 }
576 577
577 /* release CPU reset */ 578 /* release CPU reset */
@@ -580,6 +581,20 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
580 else 581 else
581 iwl_write32(trans, CSR_RESET, 0); 582 iwl_write32(trans, CSR_RESET, 0);
582 583
584 if (image->is_secure) {
585 /* wait for image verification to complete */
586 ret = iwl_poll_prph_bit(trans,
587 LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
588 LMPM_SECURE_BOOT_STATUS_SUCCESS,
589 LMPM_SECURE_BOOT_STATUS_SUCCESS,
590 LMPM_SECURE_TIME_OUT);
591
592 if (ret < 0) {
593 IWL_ERR(trans, "Time out on secure boot process\n");
594 return ret;
595 }
596 }
597
583 return 0; 598 return 0;
584} 599}
585 600