.. | .. |
---|
1 | | -/** |
---|
| 1 | +/* |
---|
2 | 2 | * Copyright (c) 2014 Redpine Signals Inc. |
---|
3 | 3 | * |
---|
4 | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
---|
.. | .. |
---|
29 | 29 | {"flash_content", 0x00010000}, |
---|
30 | 30 | {"rsi/rs9113_ap_bt_dual_mode.rps", 0x00010000}, |
---|
31 | 31 | |
---|
| 32 | +}; |
---|
| 33 | + |
---|
| 34 | +static struct ta_metadata metadata[] = {{"pmemdata_dummy", 0x00000000}, |
---|
| 35 | + {"rsi/rs9116_wlan.rps", 0x00000000}, |
---|
| 36 | + {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000}, |
---|
| 37 | + {"rsi/pmemdata_dummy", 0x00000000}, |
---|
| 38 | + {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000} |
---|
32 | 39 | }; |
---|
33 | 40 | |
---|
34 | 41 | int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb) |
---|
.. | .. |
---|
100 | 107 | mgmt_desc->frame_type = TX_DOT11_MGMT; |
---|
101 | 108 | mgmt_desc->header_len = MIN_802_11_HDR_LEN; |
---|
102 | 109 | mgmt_desc->xtend_desc_size = header_size - FRAME_DESC_SZ; |
---|
| 110 | + |
---|
| 111 | + if (ieee80211_is_probe_req(wh->frame_control)) |
---|
| 112 | + mgmt_desc->frame_info = cpu_to_le16(RSI_INSERT_SEQ_IN_FW); |
---|
103 | 113 | mgmt_desc->frame_info |= cpu_to_le16(RATE_INFO_ENABLE); |
---|
104 | 114 | if (is_broadcast_ether_addr(wh->addr1)) |
---|
105 | 115 | mgmt_desc->frame_info |= cpu_to_le16(RSI_BROADCAST_PKT); |
---|
.. | .. |
---|
152 | 162 | u8 header_size; |
---|
153 | 163 | u8 vap_id = 0; |
---|
154 | 164 | u8 dword_align_bytes; |
---|
| 165 | + bool tx_eapol; |
---|
155 | 166 | u16 seq_num; |
---|
156 | 167 | |
---|
157 | 168 | info = IEEE80211_SKB_CB(skb); |
---|
158 | 169 | vif = info->control.vif; |
---|
159 | 170 | tx_params = (struct skb_info *)info->driver_data; |
---|
| 171 | + |
---|
| 172 | + tx_eapol = IEEE80211_SKB_CB(skb)->control.flags & |
---|
| 173 | + IEEE80211_TX_CTRL_PORT_CTRL_PROTO; |
---|
160 | 174 | |
---|
161 | 175 | header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc); |
---|
162 | 176 | if (header_size > skb_headroom(skb)) { |
---|
.. | .. |
---|
221 | 235 | } |
---|
222 | 236 | } |
---|
223 | 237 | |
---|
224 | | - if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { |
---|
| 238 | + if (tx_eapol) { |
---|
225 | 239 | rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n"); |
---|
226 | 240 | |
---|
227 | 241 | data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); |
---|
.. | .. |
---|
285 | 299 | struct rsi_hw *adapter = common->priv; |
---|
286 | 300 | struct ieee80211_vif *vif; |
---|
287 | 301 | struct ieee80211_tx_info *info; |
---|
288 | | - struct skb_info *tx_params; |
---|
289 | 302 | struct ieee80211_bss_conf *bss; |
---|
290 | 303 | int status = -EINVAL; |
---|
291 | | - u8 header_size; |
---|
292 | 304 | |
---|
293 | 305 | if (!skb) |
---|
294 | 306 | return 0; |
---|
.. | .. |
---|
300 | 312 | goto err; |
---|
301 | 313 | vif = info->control.vif; |
---|
302 | 314 | bss = &vif->bss_conf; |
---|
303 | | - tx_params = (struct skb_info *)info->driver_data; |
---|
304 | | - header_size = tx_params->internal_hdr_size; |
---|
305 | 315 | |
---|
306 | 316 | if (((vif->type == NL80211_IFTYPE_STATION) || |
---|
307 | 317 | (vif->type == NL80211_IFTYPE_P2P_CLIENT)) && |
---|
.. | .. |
---|
832 | 842 | return 0; |
---|
833 | 843 | } |
---|
834 | 844 | |
---|
835 | | -static int rsi_load_firmware(struct rsi_hw *adapter) |
---|
| 845 | +static int rsi_hal_prepare_fwload(struct rsi_hw *adapter) |
---|
836 | 846 | { |
---|
837 | | - struct rsi_common *common = adapter->priv; |
---|
838 | 847 | struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops; |
---|
839 | | - const struct firmware *fw_entry = NULL; |
---|
840 | | - u32 regout_val = 0, content_size; |
---|
841 | | - u16 tmp_regout_val = 0; |
---|
842 | | - struct ta_metadata *metadata_p; |
---|
| 848 | + u32 regout_val = 0; |
---|
843 | 849 | int status; |
---|
844 | 850 | |
---|
845 | 851 | bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT); |
---|
846 | 852 | |
---|
847 | 853 | while (!adapter->blcmd_timer_expired) { |
---|
848 | 854 | status = hif_ops->master_reg_read(adapter, SWBL_REGOUT, |
---|
849 | | - ®out_val, 2); |
---|
| 855 | + ®out_val, |
---|
| 856 | + RSI_COMMON_REG_SIZE); |
---|
850 | 857 | if (status < 0) { |
---|
851 | 858 | bl_stop_cmd_timer(adapter); |
---|
852 | 859 | rsi_dbg(ERR_ZONE, |
---|
.. | .. |
---|
869 | 876 | (regout_val & 0xff)); |
---|
870 | 877 | |
---|
871 | 878 | status = hif_ops->master_reg_write(adapter, SWBL_REGOUT, |
---|
872 | | - (REGOUT_INVALID | REGOUT_INVALID << 8), |
---|
873 | | - 2); |
---|
874 | | - if (status < 0) { |
---|
| 879 | + (REGOUT_INVALID | |
---|
| 880 | + REGOUT_INVALID << 8), |
---|
| 881 | + RSI_COMMON_REG_SIZE); |
---|
| 882 | + if (status < 0) |
---|
875 | 883 | rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__); |
---|
876 | | - return status; |
---|
877 | | - } |
---|
878 | | - mdelay(1); |
---|
| 884 | + else |
---|
| 885 | + rsi_dbg(INFO_ZONE, |
---|
| 886 | + "===> Device is ready to load firmware <===\n"); |
---|
| 887 | + |
---|
| 888 | + return status; |
---|
| 889 | +} |
---|
| 890 | + |
---|
| 891 | +static int rsi_load_9113_firmware(struct rsi_hw *adapter) |
---|
| 892 | +{ |
---|
| 893 | + struct rsi_common *common = adapter->priv; |
---|
| 894 | + const struct firmware *fw_entry = NULL; |
---|
| 895 | + u32 content_size; |
---|
| 896 | + u16 tmp_regout_val = 0; |
---|
| 897 | + struct ta_metadata *metadata_p; |
---|
| 898 | + int status; |
---|
879 | 899 | |
---|
880 | 900 | status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS, |
---|
881 | 901 | "AUTO_READ_CMD"); |
---|
.. | .. |
---|
906 | 926 | |
---|
907 | 927 | /* Get the firmware version */ |
---|
908 | 928 | common->lmac_ver.ver.info.fw_ver[0] = |
---|
909 | | - fw_entry->data[LMAC_VER_OFFSET] & 0xFF; |
---|
| 929 | + fw_entry->data[LMAC_VER_OFFSET_9113] & 0xFF; |
---|
910 | 930 | common->lmac_ver.ver.info.fw_ver[1] = |
---|
911 | | - fw_entry->data[LMAC_VER_OFFSET + 1] & 0xFF; |
---|
912 | | - common->lmac_ver.major = fw_entry->data[LMAC_VER_OFFSET + 2] & 0xFF; |
---|
| 931 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 1] & 0xFF; |
---|
| 932 | + common->lmac_ver.major = |
---|
| 933 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 2] & 0xFF; |
---|
913 | 934 | common->lmac_ver.release_num = |
---|
914 | | - fw_entry->data[LMAC_VER_OFFSET + 3] & 0xFF; |
---|
915 | | - common->lmac_ver.minor = fw_entry->data[LMAC_VER_OFFSET + 4] & 0xFF; |
---|
| 935 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 3] & 0xFF; |
---|
| 936 | + common->lmac_ver.minor = |
---|
| 937 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 4] & 0xFF; |
---|
916 | 938 | common->lmac_ver.patch_num = 0; |
---|
917 | 939 | rsi_print_version(common); |
---|
918 | 940 | |
---|
.. | .. |
---|
981 | 1003 | return status; |
---|
982 | 1004 | } |
---|
983 | 1005 | |
---|
| 1006 | +static int rsi_load_9116_firmware(struct rsi_hw *adapter) |
---|
| 1007 | +{ |
---|
| 1008 | + struct rsi_common *common = adapter->priv; |
---|
| 1009 | + struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops; |
---|
| 1010 | + const struct firmware *fw_entry; |
---|
| 1011 | + struct ta_metadata *metadata_p; |
---|
| 1012 | + u8 *ta_firmware, *fw_p; |
---|
| 1013 | + struct bootload_ds bootload_ds; |
---|
| 1014 | + u32 instructions_sz, base_address; |
---|
| 1015 | + u16 block_size = adapter->block_size; |
---|
| 1016 | + u32 dest, len; |
---|
| 1017 | + int status, cnt; |
---|
| 1018 | + |
---|
| 1019 | + rsi_dbg(INIT_ZONE, "***** Load 9116 TA Instructions *****\n"); |
---|
| 1020 | + |
---|
| 1021 | + if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) { |
---|
| 1022 | + status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, |
---|
| 1023 | + "POLLING_MODE"); |
---|
| 1024 | + if (status < 0) |
---|
| 1025 | + return status; |
---|
| 1026 | + } |
---|
| 1027 | + |
---|
| 1028 | + status = hif_ops->master_reg_write(adapter, MEM_ACCESS_CTRL_FROM_HOST, |
---|
| 1029 | + RAM_384K_ACCESS_FROM_TA, |
---|
| 1030 | + RSI_9116_REG_SIZE); |
---|
| 1031 | + if (status < 0) { |
---|
| 1032 | + rsi_dbg(ERR_ZONE, "%s: Unable to access full RAM memory\n", |
---|
| 1033 | + __func__); |
---|
| 1034 | + return status; |
---|
| 1035 | + } |
---|
| 1036 | + |
---|
| 1037 | + metadata_p = &metadata[adapter->priv->coex_mode]; |
---|
| 1038 | + rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name); |
---|
| 1039 | + status = request_firmware(&fw_entry, metadata_p->name, adapter->device); |
---|
| 1040 | + if (status < 0) { |
---|
| 1041 | + rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n", |
---|
| 1042 | + __func__, metadata_p->name); |
---|
| 1043 | + return status; |
---|
| 1044 | + } |
---|
| 1045 | + |
---|
| 1046 | + ta_firmware = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); |
---|
| 1047 | + if (!ta_firmware) { |
---|
| 1048 | + status = -ENOMEM; |
---|
| 1049 | + goto fail_release_fw; |
---|
| 1050 | + } |
---|
| 1051 | + fw_p = ta_firmware; |
---|
| 1052 | + instructions_sz = fw_entry->size; |
---|
| 1053 | + rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", instructions_sz); |
---|
| 1054 | + |
---|
| 1055 | + common->lmac_ver.major = ta_firmware[LMAC_VER_OFFSET_9116]; |
---|
| 1056 | + common->lmac_ver.minor = ta_firmware[LMAC_VER_OFFSET_9116 + 1]; |
---|
| 1057 | + common->lmac_ver.release_num = ta_firmware[LMAC_VER_OFFSET_9116 + 2]; |
---|
| 1058 | + common->lmac_ver.patch_num = ta_firmware[LMAC_VER_OFFSET_9116 + 3]; |
---|
| 1059 | + common->lmac_ver.ver.info.fw_ver[0] = |
---|
| 1060 | + ta_firmware[LMAC_VER_OFFSET_9116 + 4]; |
---|
| 1061 | + |
---|
| 1062 | + if (instructions_sz % FW_ALIGN_SIZE) |
---|
| 1063 | + instructions_sz += |
---|
| 1064 | + (FW_ALIGN_SIZE - (instructions_sz % FW_ALIGN_SIZE)); |
---|
| 1065 | + rsi_dbg(INFO_ZONE, "instructions_sz : %d\n", instructions_sz); |
---|
| 1066 | + |
---|
| 1067 | + if (*(u16 *)fw_p == RSI_9116_FW_MAGIC_WORD) { |
---|
| 1068 | + memcpy(&bootload_ds, fw_p, sizeof(struct bootload_ds)); |
---|
| 1069 | + fw_p += le16_to_cpu(bootload_ds.offset); |
---|
| 1070 | + rsi_dbg(INFO_ZONE, "FW start = %x\n", *(u32 *)fw_p); |
---|
| 1071 | + |
---|
| 1072 | + cnt = 0; |
---|
| 1073 | + do { |
---|
| 1074 | + rsi_dbg(ERR_ZONE, "%s: Loading chunk %d\n", |
---|
| 1075 | + __func__, cnt); |
---|
| 1076 | + |
---|
| 1077 | + dest = le32_to_cpu(bootload_ds.bl_entry[cnt].dst_addr); |
---|
| 1078 | + len = le32_to_cpu(bootload_ds.bl_entry[cnt].control) & |
---|
| 1079 | + RSI_BL_CTRL_LEN_MASK; |
---|
| 1080 | + rsi_dbg(INFO_ZONE, "length %d destination %x\n", |
---|
| 1081 | + len, dest); |
---|
| 1082 | + |
---|
| 1083 | + status = hif_ops->load_data_master_write(adapter, dest, |
---|
| 1084 | + len, |
---|
| 1085 | + block_size, |
---|
| 1086 | + fw_p); |
---|
| 1087 | + if (status < 0) { |
---|
| 1088 | + rsi_dbg(ERR_ZONE, |
---|
| 1089 | + "Failed to load chunk %d\n", cnt); |
---|
| 1090 | + break; |
---|
| 1091 | + } |
---|
| 1092 | + fw_p += len; |
---|
| 1093 | + if (le32_to_cpu(bootload_ds.bl_entry[cnt].control) & |
---|
| 1094 | + RSI_BL_CTRL_LAST_ENTRY) |
---|
| 1095 | + break; |
---|
| 1096 | + cnt++; |
---|
| 1097 | + } while (1); |
---|
| 1098 | + } else { |
---|
| 1099 | + base_address = metadata_p->address; |
---|
| 1100 | + status = hif_ops->load_data_master_write(adapter, |
---|
| 1101 | + base_address, |
---|
| 1102 | + instructions_sz, |
---|
| 1103 | + block_size, |
---|
| 1104 | + ta_firmware); |
---|
| 1105 | + } |
---|
| 1106 | + if (status) { |
---|
| 1107 | + rsi_dbg(ERR_ZONE, |
---|
| 1108 | + "%s: Unable to load %s blk\n", |
---|
| 1109 | + __func__, metadata_p->name); |
---|
| 1110 | + goto fail_free_fw; |
---|
| 1111 | + } |
---|
| 1112 | + |
---|
| 1113 | + rsi_dbg(INIT_ZONE, "%s: Successfully loaded %s instructions\n", |
---|
| 1114 | + __func__, metadata_p->name); |
---|
| 1115 | + |
---|
| 1116 | + if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) { |
---|
| 1117 | + if (hif_ops->ta_reset(adapter)) |
---|
| 1118 | + rsi_dbg(ERR_ZONE, "Unable to put ta in reset\n"); |
---|
| 1119 | + } else { |
---|
| 1120 | + if (bl_cmd(adapter, JUMP_TO_ZERO_PC, |
---|
| 1121 | + CMD_PASS, "JUMP_TO_ZERO") < 0) |
---|
| 1122 | + rsi_dbg(INFO_ZONE, "Jump to zero command failed\n"); |
---|
| 1123 | + else |
---|
| 1124 | + rsi_dbg(INFO_ZONE, "Jump to zero command successful\n"); |
---|
| 1125 | + } |
---|
| 1126 | + |
---|
| 1127 | +fail_free_fw: |
---|
| 1128 | + kfree(ta_firmware); |
---|
| 1129 | +fail_release_fw: |
---|
| 1130 | + release_firmware(fw_entry); |
---|
| 1131 | + |
---|
| 1132 | + return status; |
---|
| 1133 | +} |
---|
| 1134 | + |
---|
984 | 1135 | int rsi_hal_device_init(struct rsi_hw *adapter) |
---|
985 | 1136 | { |
---|
986 | 1137 | struct rsi_common *common = adapter->priv; |
---|
| 1138 | + int status; |
---|
987 | 1139 | |
---|
988 | 1140 | switch (adapter->device_model) { |
---|
989 | 1141 | case RSI_DEV_9113: |
---|
990 | | - if (rsi_load_firmware(adapter)) { |
---|
| 1142 | + status = rsi_hal_prepare_fwload(adapter); |
---|
| 1143 | + if (status < 0) |
---|
| 1144 | + return status; |
---|
| 1145 | + if (rsi_load_9113_firmware(adapter)) { |
---|
991 | 1146 | rsi_dbg(ERR_ZONE, |
---|
992 | 1147 | "%s: Failed to load TA instructions\n", |
---|
993 | 1148 | __func__); |
---|
994 | 1149 | return -EINVAL; |
---|
995 | 1150 | } |
---|
996 | 1151 | break; |
---|
| 1152 | + case RSI_DEV_9116: |
---|
| 1153 | + status = rsi_hal_prepare_fwload(adapter); |
---|
| 1154 | + if (status < 0) |
---|
| 1155 | + return status; |
---|
| 1156 | + if (rsi_load_9116_firmware(adapter)) { |
---|
| 1157 | + rsi_dbg(ERR_ZONE, |
---|
| 1158 | + "%s: Failed to load firmware to 9116 device\n", |
---|
| 1159 | + __func__); |
---|
| 1160 | + return -EINVAL; |
---|
| 1161 | + } |
---|
| 1162 | + break; |
---|
997 | 1163 | default: |
---|
998 | 1164 | return -EINVAL; |
---|
999 | 1165 | } |
---|