diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/init.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 380 |
1 files changed, 225 insertions, 155 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 5acb4a4b93b..7f55be3092d 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -33,6 +33,80 @@ module_param(debug_mask, uint, 0644); | |||
33 | module_param(testmode, uint, 0644); | 33 | module_param(testmode, uint, 0644); |
34 | module_param(suspend_cutpower, bool, 0444); | 34 | module_param(suspend_cutpower, bool, 0444); |
35 | 35 | ||
36 | static const struct ath6kl_hw hw_list[] = { | ||
37 | { | ||
38 | .id = AR6003_HW_2_0_VERSION, | ||
39 | .name = "ar6003 hw 2.0", | ||
40 | .dataset_patch_addr = 0x57e884, | ||
41 | .app_load_addr = 0x543180, | ||
42 | .board_ext_data_addr = 0x57e500, | ||
43 | .reserved_ram_size = 6912, | ||
44 | .refclk_hz = 26000000, | ||
45 | .uarttx_pin = 8, | ||
46 | |||
47 | /* hw2.0 needs override address hardcoded */ | ||
48 | .app_start_override_addr = 0x944C00, | ||
49 | |||
50 | .fw_otp = AR6003_HW_2_0_OTP_FILE, | ||
51 | .fw = AR6003_HW_2_0_FIRMWARE_FILE, | ||
52 | .fw_tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, | ||
53 | .fw_patch = AR6003_HW_2_0_PATCH_FILE, | ||
54 | .fw_api2 = AR6003_HW_2_0_FIRMWARE_2_FILE, | ||
55 | .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, | ||
56 | .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, | ||
57 | }, | ||
58 | { | ||
59 | .id = AR6003_HW_2_1_1_VERSION, | ||
60 | .name = "ar6003 hw 2.1.1", | ||
61 | .dataset_patch_addr = 0x57ff74, | ||
62 | .app_load_addr = 0x1234, | ||
63 | .board_ext_data_addr = 0x542330, | ||
64 | .reserved_ram_size = 512, | ||
65 | .refclk_hz = 26000000, | ||
66 | .uarttx_pin = 8, | ||
67 | |||
68 | .fw_otp = AR6003_HW_2_1_1_OTP_FILE, | ||
69 | .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, | ||
70 | .fw_tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, | ||
71 | .fw_patch = AR6003_HW_2_1_1_PATCH_FILE, | ||
72 | .fw_api2 = AR6003_HW_2_1_1_FIRMWARE_2_FILE, | ||
73 | .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, | ||
74 | .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, | ||
75 | }, | ||
76 | { | ||
77 | .id = AR6004_HW_1_0_VERSION, | ||
78 | .name = "ar6004 hw 1.0", | ||
79 | .dataset_patch_addr = 0x57e884, | ||
80 | .app_load_addr = 0x1234, | ||
81 | .board_ext_data_addr = 0x437000, | ||
82 | .reserved_ram_size = 19456, | ||
83 | .board_addr = 0x433900, | ||
84 | .refclk_hz = 26000000, | ||
85 | .uarttx_pin = 11, | ||
86 | |||
87 | .fw = AR6004_HW_1_0_FIRMWARE_FILE, | ||
88 | .fw_api2 = AR6004_HW_1_0_FIRMWARE_2_FILE, | ||
89 | .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, | ||
90 | .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, | ||
91 | }, | ||
92 | { | ||
93 | .id = AR6004_HW_1_1_VERSION, | ||
94 | .name = "ar6004 hw 1.1", | ||
95 | .dataset_patch_addr = 0x57e884, | ||
96 | .app_load_addr = 0x1234, | ||
97 | .board_ext_data_addr = 0x437000, | ||
98 | .reserved_ram_size = 11264, | ||
99 | .board_addr = 0x43d400, | ||
100 | .refclk_hz = 40000000, | ||
101 | .uarttx_pin = 11, | ||
102 | |||
103 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, | ||
104 | .fw_api2 = AR6004_HW_1_1_FIRMWARE_2_FILE, | ||
105 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, | ||
106 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, | ||
107 | }, | ||
108 | }; | ||
109 | |||
36 | /* | 110 | /* |
37 | * Include definitions here that can be used to tune the WLAN module | 111 | * Include definitions here that can be used to tune the WLAN module |
38 | * behavior. Different customers can tune the behavior as per their needs, | 112 | * behavior. Different customers can tune the behavior as per their needs, |
@@ -58,7 +132,6 @@ module_param(suspend_cutpower, bool, 0444); | |||
58 | */ | 132 | */ |
59 | #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 | 133 | #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 |
60 | 134 | ||
61 | #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 | ||
62 | 135 | ||
63 | #define ATH6KL_DATA_OFFSET 64 | 136 | #define ATH6KL_DATA_OFFSET 64 |
64 | struct sk_buff *ath6kl_buf_alloc(int size) | 137 | struct sk_buff *ath6kl_buf_alloc(int size) |
@@ -348,11 +421,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
348 | status = -EIO; | 421 | status = -EIO; |
349 | } | 422 | } |
350 | 423 | ||
351 | /* | 424 | if (ar->p2p && (ar->vif_max == 1 || idx)) { |
352 | * FIXME: Make sure p2p configurations are not applied to | ||
353 | * non-p2p capable interfaces when multivif support is enabled. | ||
354 | */ | ||
355 | if (ar->p2p) { | ||
356 | ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx, | 425 | ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx, |
357 | P2P_FLAG_CAPABILITIES_REQ | | 426 | P2P_FLAG_CAPABILITIES_REQ | |
358 | P2P_FLAG_MACADDR_REQ | | 427 | P2P_FLAG_MACADDR_REQ | |
@@ -365,11 +434,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
365 | } | 434 | } |
366 | } | 435 | } |
367 | 436 | ||
368 | /* | 437 | if (ar->p2p && (ar->vif_max == 1 || idx)) { |
369 | * FIXME: Make sure p2p configurations are not applied to | ||
370 | * non-p2p capable interfaces when multivif support is enabled. | ||
371 | */ | ||
372 | if (ar->p2p) { | ||
373 | /* Enable Probe Request reporting for P2P */ | 438 | /* Enable Probe Request reporting for P2P */ |
374 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); | 439 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); |
375 | if (ret) { | 440 | if (ret) { |
@@ -385,7 +450,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
385 | { | 450 | { |
386 | u32 param, ram_reserved_size; | 451 | u32 param, ram_reserved_size; |
387 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; | 452 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; |
388 | int i; | 453 | int i, status; |
389 | 454 | ||
390 | /* | 455 | /* |
391 | * Note: Even though the firmware interface type is | 456 | * Note: Even though the firmware interface type is |
@@ -397,7 +462,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
397 | */ | 462 | */ |
398 | fw_iftype = HI_OPTION_FW_MODE_BSS_STA; | 463 | fw_iftype = HI_OPTION_FW_MODE_BSS_STA; |
399 | 464 | ||
400 | for (i = 0; i < MAX_NUM_VIF; i++) | 465 | for (i = 0; i < ar->vif_max; i++) |
401 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); | 466 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); |
402 | 467 | ||
403 | /* | 468 | /* |
@@ -411,15 +476,11 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
411 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << | 476 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << |
412 | (i * HI_OPTION_FW_SUBMODE_BITS); | 477 | (i * HI_OPTION_FW_SUBMODE_BITS); |
413 | 478 | ||
414 | for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++) | 479 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) |
415 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << | 480 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << |
416 | (i * HI_OPTION_FW_SUBMODE_BITS); | 481 | (i * HI_OPTION_FW_SUBMODE_BITS); |
417 | 482 | ||
418 | /* | 483 | if (ar->p2p && ar->vif_max == 1) |
419 | * FIXME: This needs to be removed once the multivif | ||
420 | * support is enabled. | ||
421 | */ | ||
422 | if (ar->p2p) | ||
423 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; | 484 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; |
424 | 485 | ||
425 | param = HTC_PROTOCOL_VERSION; | 486 | param = HTC_PROTOCOL_VERSION; |
@@ -442,7 +503,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
442 | return -EIO; | 503 | return -EIO; |
443 | } | 504 | } |
444 | 505 | ||
445 | param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT); | 506 | param |= (ar->vif_max << HI_OPTION_NUM_DEV_SHIFT); |
446 | param |= fw_mode << HI_OPTION_FW_MODE_SHIFT; | 507 | param |= fw_mode << HI_OPTION_FW_MODE_SHIFT; |
447 | param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT; | 508 | param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT; |
448 | 509 | ||
@@ -491,6 +552,24 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
491 | /* use default number of control buffers */ | 552 | /* use default number of control buffers */ |
492 | return -EIO; | 553 | return -EIO; |
493 | 554 | ||
555 | /* Configure GPIO AR600x UART */ | ||
556 | param = ar->hw.uarttx_pin; | ||
557 | status = ath6kl_bmi_write(ar, | ||
558 | ath6kl_get_hi_item_addr(ar, | ||
559 | HI_ITEM(hi_dbg_uart_txpin)), | ||
560 | (u8 *)¶m, 4); | ||
561 | if (status) | ||
562 | return status; | ||
563 | |||
564 | /* Configure target refclk_hz */ | ||
565 | param = ar->hw.refclk_hz; | ||
566 | status = ath6kl_bmi_write(ar, | ||
567 | ath6kl_get_hi_item_addr(ar, | ||
568 | HI_ITEM(hi_refclk_hz)), | ||
569 | (u8 *)¶m, 4); | ||
570 | if (status) | ||
571 | return status; | ||
572 | |||
494 | return 0; | 573 | return 0; |
495 | } | 574 | } |
496 | 575 | ||
@@ -550,11 +629,11 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | |||
550 | static const char *get_target_ver_dir(const struct ath6kl *ar) | 629 | static const char *get_target_ver_dir(const struct ath6kl *ar) |
551 | { | 630 | { |
552 | switch (ar->version.target_ver) { | 631 | switch (ar->version.target_ver) { |
553 | case AR6003_REV1_VERSION: | 632 | case AR6003_HW_1_0_VERSION: |
554 | return "ath6k/AR6003/hw1.0"; | 633 | return "ath6k/AR6003/hw1.0"; |
555 | case AR6003_REV2_VERSION: | 634 | case AR6003_HW_2_0_VERSION: |
556 | return "ath6k/AR6003/hw2.0"; | 635 | return "ath6k/AR6003/hw2.0"; |
557 | case AR6003_REV3_VERSION: | 636 | case AR6003_HW_2_1_1_VERSION: |
558 | return "ath6k/AR6003/hw2.1.1"; | 637 | return "ath6k/AR6003/hw2.1.1"; |
559 | } | 638 | } |
560 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, | 639 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, |
@@ -612,17 +691,10 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
612 | if (ar->fw_board != NULL) | 691 | if (ar->fw_board != NULL) |
613 | return 0; | 692 | return 0; |
614 | 693 | ||
615 | switch (ar->version.target_ver) { | 694 | if (WARN_ON(ar->hw.fw_board == NULL)) |
616 | case AR6003_REV2_VERSION: | 695 | return -EINVAL; |
617 | filename = AR6003_REV2_BOARD_DATA_FILE; | 696 | |
618 | break; | 697 | filename = ar->hw.fw_board; |
619 | case AR6004_REV1_VERSION: | ||
620 | filename = AR6004_REV1_BOARD_DATA_FILE; | ||
621 | break; | ||
622 | default: | ||
623 | filename = AR6003_REV3_BOARD_DATA_FILE; | ||
624 | break; | ||
625 | } | ||
626 | 698 | ||
627 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, | 699 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, |
628 | &ar->fw_board_len); | 700 | &ar->fw_board_len); |
@@ -640,17 +712,7 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
640 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", | 712 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", |
641 | filename, ret); | 713 | filename, ret); |
642 | 714 | ||
643 | switch (ar->version.target_ver) { | 715 | filename = ar->hw.fw_default_board; |
644 | case AR6003_REV2_VERSION: | ||
645 | filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; | ||
646 | break; | ||
647 | case AR6004_REV1_VERSION: | ||
648 | filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE; | ||
649 | break; | ||
650 | default: | ||
651 | filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; | ||
652 | break; | ||
653 | } | ||
654 | 716 | ||
655 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, | 717 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, |
656 | &ar->fw_board_len); | 718 | &ar->fw_board_len); |
@@ -674,19 +736,14 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) | |||
674 | if (ar->fw_otp != NULL) | 736 | if (ar->fw_otp != NULL) |
675 | return 0; | 737 | return 0; |
676 | 738 | ||
677 | switch (ar->version.target_ver) { | 739 | if (ar->hw.fw_otp == NULL) { |
678 | case AR6003_REV2_VERSION: | 740 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
679 | filename = AR6003_REV2_OTP_FILE; | 741 | "no OTP file configured for this hw\n"); |
680 | break; | ||
681 | case AR6004_REV1_VERSION: | ||
682 | ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n"); | ||
683 | return 0; | 742 | return 0; |
684 | break; | ||
685 | default: | ||
686 | filename = AR6003_REV3_OTP_FILE; | ||
687 | break; | ||
688 | } | 743 | } |
689 | 744 | ||
745 | filename = ar->hw.fw_otp; | ||
746 | |||
690 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, | 747 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, |
691 | &ar->fw_otp_len); | 748 | &ar->fw_otp_len); |
692 | if (ret) { | 749 | if (ret) { |
@@ -707,38 +764,22 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) | |||
707 | return 0; | 764 | return 0; |
708 | 765 | ||
709 | if (testmode) { | 766 | if (testmode) { |
710 | switch (ar->version.target_ver) { | 767 | if (ar->hw.fw_tcmd == NULL) { |
711 | case AR6003_REV2_VERSION: | 768 | ath6kl_warn("testmode not supported\n"); |
712 | filename = AR6003_REV2_TCMD_FIRMWARE_FILE; | ||
713 | break; | ||
714 | case AR6003_REV3_VERSION: | ||
715 | filename = AR6003_REV3_TCMD_FIRMWARE_FILE; | ||
716 | break; | ||
717 | case AR6004_REV1_VERSION: | ||
718 | ath6kl_warn("testmode not supported with ar6004\n"); | ||
719 | return -EOPNOTSUPP; | 769 | return -EOPNOTSUPP; |
720 | default: | ||
721 | ath6kl_warn("unknown target version: 0x%x\n", | ||
722 | ar->version.target_ver); | ||
723 | return -EINVAL; | ||
724 | } | 770 | } |
725 | 771 | ||
772 | filename = ar->hw.fw_tcmd; | ||
773 | |||
726 | set_bit(TESTMODE, &ar->flag); | 774 | set_bit(TESTMODE, &ar->flag); |
727 | 775 | ||
728 | goto get_fw; | 776 | goto get_fw; |
729 | } | 777 | } |
730 | 778 | ||
731 | switch (ar->version.target_ver) { | 779 | if (WARN_ON(ar->hw.fw == NULL)) |
732 | case AR6003_REV2_VERSION: | 780 | return -EINVAL; |
733 | filename = AR6003_REV2_FIRMWARE_FILE; | 781 | |
734 | break; | 782 | filename = ar->hw.fw; |
735 | case AR6004_REV1_VERSION: | ||
736 | filename = AR6004_REV1_FIRMWARE_FILE; | ||
737 | break; | ||
738 | default: | ||
739 | filename = AR6003_REV3_FIRMWARE_FILE; | ||
740 | break; | ||
741 | } | ||
742 | 783 | ||
743 | get_fw: | 784 | get_fw: |
744 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); | 785 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); |
@@ -756,27 +797,20 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar) | |||
756 | const char *filename; | 797 | const char *filename; |
757 | int ret; | 798 | int ret; |
758 | 799 | ||
759 | switch (ar->version.target_ver) { | 800 | if (ar->fw_patch != NULL) |
760 | case AR6003_REV2_VERSION: | ||
761 | filename = AR6003_REV2_PATCH_FILE; | ||
762 | break; | ||
763 | case AR6004_REV1_VERSION: | ||
764 | /* FIXME: implement for AR6004 */ | ||
765 | return 0; | 801 | return 0; |
766 | break; | ||
767 | default: | ||
768 | filename = AR6003_REV3_PATCH_FILE; | ||
769 | break; | ||
770 | } | ||
771 | 802 | ||
772 | if (ar->fw_patch == NULL) { | 803 | if (ar->hw.fw_patch == NULL) |
773 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, | 804 | return 0; |
774 | &ar->fw_patch_len); | 805 | |
775 | if (ret) { | 806 | filename = ar->hw.fw_patch; |
776 | ath6kl_err("Failed to get patch file %s: %d\n", | 807 | |
777 | filename, ret); | 808 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, |
778 | return ret; | 809 | &ar->fw_patch_len); |
779 | } | 810 | if (ret) { |
811 | ath6kl_err("Failed to get patch file %s: %d\n", | ||
812 | filename, ret); | ||
813 | return ret; | ||
780 | } | 814 | } |
781 | 815 | ||
782 | return 0; | 816 | return 0; |
@@ -811,19 +845,10 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
811 | int ret, ie_id, i, index, bit; | 845 | int ret, ie_id, i, index, bit; |
812 | __le32 *val; | 846 | __le32 *val; |
813 | 847 | ||
814 | switch (ar->version.target_ver) { | 848 | if (ar->hw.fw_api2 == NULL) |
815 | case AR6003_REV2_VERSION: | ||
816 | filename = AR6003_REV2_FIRMWARE_2_FILE; | ||
817 | break; | ||
818 | case AR6003_REV3_VERSION: | ||
819 | filename = AR6003_REV3_FIRMWARE_2_FILE; | ||
820 | break; | ||
821 | case AR6004_REV1_VERSION: | ||
822 | filename = AR6004_REV1_FIRMWARE_2_FILE; | ||
823 | break; | ||
824 | default: | ||
825 | return -EOPNOTSUPP; | 849 | return -EOPNOTSUPP; |
826 | } | 850 | |
851 | filename = ar->hw.fw_api2; | ||
827 | 852 | ||
828 | ret = request_firmware(&fw, filename, ar->dev); | 853 | ret = request_firmware(&fw, filename, ar->dev); |
829 | if (ret) | 854 | if (ret) |
@@ -913,12 +938,15 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
913 | ar->hw.reserved_ram_size); | 938 | ar->hw.reserved_ram_size); |
914 | break; | 939 | break; |
915 | case ATH6KL_FW_IE_CAPABILITIES: | 940 | case ATH6KL_FW_IE_CAPABILITIES: |
941 | if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8)) | ||
942 | break; | ||
943 | |||
916 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 944 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
917 | "found firmware capabilities ie (%zd B)\n", | 945 | "found firmware capabilities ie (%zd B)\n", |
918 | ie_len); | 946 | ie_len); |
919 | 947 | ||
920 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { | 948 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { |
921 | index = ALIGN(i, 8) / 8; | 949 | index = i / 8; |
922 | bit = i % 8; | 950 | bit = i % 8; |
923 | 951 | ||
924 | if (data[index] & (1 << bit)) | 952 | if (data[index] & (1 << bit)) |
@@ -937,9 +965,34 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
937 | ar->hw.dataset_patch_addr = le32_to_cpup(val); | 965 | ar->hw.dataset_patch_addr = le32_to_cpup(val); |
938 | 966 | ||
939 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 967 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
940 | "found patch address ie 0x%d\n", | 968 | "found patch address ie 0x%x\n", |
941 | ar->hw.dataset_patch_addr); | 969 | ar->hw.dataset_patch_addr); |
942 | break; | 970 | break; |
971 | case ATH6KL_FW_IE_BOARD_ADDR: | ||
972 | if (ie_len != sizeof(*val)) | ||
973 | break; | ||
974 | |||
975 | val = (__le32 *) data; | ||
976 | ar->hw.board_addr = le32_to_cpup(val); | ||
977 | |||
978 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
979 | "found board address ie 0x%x\n", | ||
980 | ar->hw.board_addr); | ||
981 | break; | ||
982 | case ATH6KL_FW_IE_VIF_MAX: | ||
983 | if (ie_len != sizeof(*val)) | ||
984 | break; | ||
985 | |||
986 | val = (__le32 *) data; | ||
987 | ar->vif_max = min_t(unsigned int, le32_to_cpup(val), | ||
988 | ATH6KL_VIF_MAX); | ||
989 | |||
990 | if (ar->vif_max > 1 && !ar->p2p) | ||
991 | ar->max_norm_iface = 2; | ||
992 | |||
993 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
994 | "found vif max ie %d\n", ar->vif_max); | ||
995 | break; | ||
943 | default: | 996 | default: |
944 | ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", | 997 | ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", |
945 | le32_to_cpup(&hdr->id)); | 998 | le32_to_cpup(&hdr->id)); |
@@ -994,8 +1047,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
994 | * For AR6004, host determine Target RAM address for | 1047 | * For AR6004, host determine Target RAM address for |
995 | * writing board data. | 1048 | * writing board data. |
996 | */ | 1049 | */ |
997 | if (ar->target_type == TARGET_TYPE_AR6004) { | 1050 | if (ar->hw.board_addr != 0) { |
998 | board_address = AR6004_REV1_BOARD_DATA_ADDRESS; | 1051 | board_address = ar->hw.board_addr; |
999 | ath6kl_bmi_write(ar, | 1052 | ath6kl_bmi_write(ar, |
1000 | ath6kl_get_hi_item_addr(ar, | 1053 | ath6kl_get_hi_item_addr(ar, |
1001 | HI_ITEM(hi_board_data)), | 1054 | HI_ITEM(hi_board_data)), |
@@ -1013,7 +1066,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1013 | HI_ITEM(hi_board_ext_data)), | 1066 | HI_ITEM(hi_board_ext_data)), |
1014 | (u8 *) &board_ext_address, 4); | 1067 | (u8 *) &board_ext_address, 4); |
1015 | 1068 | ||
1016 | if (board_ext_address == 0) { | 1069 | if (ar->target_type == TARGET_TYPE_AR6003 && |
1070 | board_ext_address == 0) { | ||
1017 | ath6kl_err("Failed to get board file target address.\n"); | 1071 | ath6kl_err("Failed to get board file target address.\n"); |
1018 | return -EINVAL; | 1072 | return -EINVAL; |
1019 | } | 1073 | } |
@@ -1033,8 +1087,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1033 | break; | 1087 | break; |
1034 | } | 1088 | } |
1035 | 1089 | ||
1036 | if (ar->fw_board_len == (board_data_size + | 1090 | if (board_ext_address && |
1037 | board_ext_data_size)) { | 1091 | ar->fw_board_len == (board_data_size + board_ext_data_size)) { |
1038 | 1092 | ||
1039 | /* write extended board data */ | 1093 | /* write extended board data */ |
1040 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1094 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
@@ -1092,8 +1146,8 @@ static int ath6kl_upload_otp(struct ath6kl *ar) | |||
1092 | bool from_hw = false; | 1146 | bool from_hw = false; |
1093 | int ret; | 1147 | int ret; |
1094 | 1148 | ||
1095 | if (WARN_ON(ar->fw_otp == NULL)) | 1149 | if (ar->fw_otp == NULL) |
1096 | return -ENOENT; | 1150 | return 0; |
1097 | 1151 | ||
1098 | address = ar->hw.app_load_addr; | 1152 | address = ar->hw.app_load_addr; |
1099 | 1153 | ||
@@ -1142,7 +1196,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar) | |||
1142 | int ret; | 1196 | int ret; |
1143 | 1197 | ||
1144 | if (WARN_ON(ar->fw == NULL)) | 1198 | if (WARN_ON(ar->fw == NULL)) |
1145 | return -ENOENT; | 1199 | return 0; |
1146 | 1200 | ||
1147 | address = ar->hw.app_load_addr; | 1201 | address = ar->hw.app_load_addr; |
1148 | 1202 | ||
@@ -1172,8 +1226,8 @@ static int ath6kl_upload_patch(struct ath6kl *ar) | |||
1172 | u32 address, param; | 1226 | u32 address, param; |
1173 | int ret; | 1227 | int ret; |
1174 | 1228 | ||
1175 | if (WARN_ON(ar->fw_patch == NULL)) | 1229 | if (ar->fw_patch == NULL) |
1176 | return -ENOENT; | 1230 | return 0; |
1177 | 1231 | ||
1178 | address = ar->hw.dataset_patch_addr; | 1232 | address = ar->hw.dataset_patch_addr; |
1179 | 1233 | ||
@@ -1258,7 +1312,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1258 | return status; | 1312 | return status; |
1259 | 1313 | ||
1260 | /* WAR to avoid SDIO CRC err */ | 1314 | /* WAR to avoid SDIO CRC err */ |
1261 | if (ar->version.target_ver == AR6003_REV2_VERSION) { | 1315 | if (ar->version.target_ver == AR6003_HW_2_0_VERSION) { |
1262 | ath6kl_err("temporary war to avoid sdio crc error\n"); | 1316 | ath6kl_err("temporary war to avoid sdio crc error\n"); |
1263 | 1317 | ||
1264 | param = 0x20; | 1318 | param = 0x20; |
@@ -1315,47 +1369,29 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1315 | if (status) | 1369 | if (status) |
1316 | return status; | 1370 | return status; |
1317 | 1371 | ||
1318 | /* Configure GPIO AR6003 UART */ | ||
1319 | param = CONFIG_AR600x_DEBUG_UART_TX_PIN; | ||
1320 | status = ath6kl_bmi_write(ar, | ||
1321 | ath6kl_get_hi_item_addr(ar, | ||
1322 | HI_ITEM(hi_dbg_uart_txpin)), | ||
1323 | (u8 *)¶m, 4); | ||
1324 | |||
1325 | return status; | 1372 | return status; |
1326 | } | 1373 | } |
1327 | 1374 | ||
1328 | static int ath6kl_init_hw_params(struct ath6kl *ar) | 1375 | static int ath6kl_init_hw_params(struct ath6kl *ar) |
1329 | { | 1376 | { |
1330 | switch (ar->version.target_ver) { | 1377 | const struct ath6kl_hw *hw; |
1331 | case AR6003_REV2_VERSION: | 1378 | int i; |
1332 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1333 | ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS; | ||
1334 | ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; | ||
1335 | ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE; | ||
1336 | 1379 | ||
1337 | /* hw2.0 needs override address hardcoded */ | 1380 | for (i = 0; i < ARRAY_SIZE(hw_list); i++) { |
1338 | ar->hw.app_start_override_addr = 0x944C00; | 1381 | hw = &hw_list[i]; |
1339 | 1382 | ||
1340 | break; | 1383 | if (hw->id == ar->version.target_ver) |
1341 | case AR6003_REV3_VERSION: | 1384 | break; |
1342 | ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS; | 1385 | } |
1343 | ar->hw.app_load_addr = 0x1234; | 1386 | |
1344 | ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; | 1387 | if (i == ARRAY_SIZE(hw_list)) { |
1345 | ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE; | ||
1346 | break; | ||
1347 | case AR6004_REV1_VERSION: | ||
1348 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1349 | ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS; | ||
1350 | ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS; | ||
1351 | ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE; | ||
1352 | break; | ||
1353 | default: | ||
1354 | ath6kl_err("Unsupported hardware version: 0x%x\n", | 1388 | ath6kl_err("Unsupported hardware version: 0x%x\n", |
1355 | ar->version.target_ver); | 1389 | ar->version.target_ver); |
1356 | return -EINVAL; | 1390 | return -EINVAL; |
1357 | } | 1391 | } |
1358 | 1392 | ||
1393 | ar->hw = *hw; | ||
1394 | |||
1359 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1395 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
1360 | "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", | 1396 | "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", |
1361 | ar->version.target_ver, ar->target_type, | 1397 | ar->version.target_ver, ar->target_type, |
@@ -1364,10 +1400,25 @@ static int ath6kl_init_hw_params(struct ath6kl *ar) | |||
1364 | "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", | 1400 | "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", |
1365 | ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, | 1401 | ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, |
1366 | ar->hw.reserved_ram_size); | 1402 | ar->hw.reserved_ram_size); |
1403 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1404 | "refclk_hz %d uarttx_pin %d", | ||
1405 | ar->hw.refclk_hz, ar->hw.uarttx_pin); | ||
1367 | 1406 | ||
1368 | return 0; | 1407 | return 0; |
1369 | } | 1408 | } |
1370 | 1409 | ||
1410 | static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type) | ||
1411 | { | ||
1412 | switch (type) { | ||
1413 | case ATH6KL_HIF_TYPE_SDIO: | ||
1414 | return "sdio"; | ||
1415 | case ATH6KL_HIF_TYPE_USB: | ||
1416 | return "usb"; | ||
1417 | } | ||
1418 | |||
1419 | return NULL; | ||
1420 | } | ||
1421 | |||
1371 | int ath6kl_init_hw_start(struct ath6kl *ar) | 1422 | int ath6kl_init_hw_start(struct ath6kl *ar) |
1372 | { | 1423 | { |
1373 | long timeleft; | 1424 | long timeleft; |
@@ -1428,6 +1479,15 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1428 | 1479 | ||
1429 | ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); | 1480 | ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); |
1430 | 1481 | ||
1482 | |||
1483 | if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { | ||
1484 | ath6kl_info("%s %s fw %s%s\n", | ||
1485 | ar->hw.name, | ||
1486 | ath6kl_init_get_hif_name(ar->hif_type), | ||
1487 | ar->wiphy->fw_version, | ||
1488 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | ||
1489 | } | ||
1490 | |||
1431 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { | 1491 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { |
1432 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", | 1492 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", |
1433 | ATH6KL_ABI_VERSION, ar->version.abi_ver); | 1493 | ATH6KL_ABI_VERSION, ar->version.abi_ver); |
@@ -1448,7 +1508,7 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1448 | if ((ath6kl_set_host_app_area(ar)) != 0) | 1508 | if ((ath6kl_set_host_app_area(ar)) != 0) |
1449 | ath6kl_err("unable to set the host app area\n"); | 1509 | ath6kl_err("unable to set the host app area\n"); |
1450 | 1510 | ||
1451 | for (i = 0; i < MAX_NUM_VIF; i++) { | 1511 | for (i = 0; i < ar->vif_max; i++) { |
1452 | ret = ath6kl_target_config_wlan_params(ar, i); | 1512 | ret = ath6kl_target_config_wlan_params(ar, i); |
1453 | if (ret) | 1513 | if (ret) |
1454 | goto err_htc_stop; | 1514 | goto err_htc_stop; |
@@ -1558,7 +1618,7 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1558 | goto err_node_cleanup; | 1618 | goto err_node_cleanup; |
1559 | } | 1619 | } |
1560 | 1620 | ||
1561 | for (i = 0; i < MAX_NUM_VIF; i++) | 1621 | for (i = 0; i < ar->vif_max; i++) |
1562 | ar->avail_idx_map |= BIT(i); | 1622 | ar->avail_idx_map |= BIT(i); |
1563 | 1623 | ||
1564 | rtnl_lock(); | 1624 | rtnl_lock(); |
@@ -1603,7 +1663,17 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1603 | 1663 | ||
1604 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 1664 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
1605 | WIPHY_FLAG_HAVE_AP_SME | | 1665 | WIPHY_FLAG_HAVE_AP_SME | |
1606 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 1666 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
1667 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
1668 | |||
1669 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | ||
1670 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
1671 | |||
1672 | ar->wiphy->probe_resp_offload = | ||
1673 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
1674 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
1675 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | ||
1676 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
1607 | 1677 | ||
1608 | set_bit(FIRST_BOOT, &ar->flag); | 1678 | set_bit(FIRST_BOOT, &ar->flag); |
1609 | 1679 | ||