| .. | .. |
|---|
| 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); |
|---|
| .. | .. |
|---|
| 285 | 295 | struct rsi_hw *adapter = common->priv; |
|---|
| 286 | 296 | struct ieee80211_vif *vif; |
|---|
| 287 | 297 | struct ieee80211_tx_info *info; |
|---|
| 288 | | - struct skb_info *tx_params; |
|---|
| 289 | 298 | struct ieee80211_bss_conf *bss; |
|---|
| 290 | 299 | int status = -EINVAL; |
|---|
| 291 | | - u8 header_size; |
|---|
| 292 | 300 | |
|---|
| 293 | 301 | if (!skb) |
|---|
| 294 | 302 | return 0; |
|---|
| .. | .. |
|---|
| 300 | 308 | goto err; |
|---|
| 301 | 309 | vif = info->control.vif; |
|---|
| 302 | 310 | bss = &vif->bss_conf; |
|---|
| 303 | | - tx_params = (struct skb_info *)info->driver_data; |
|---|
| 304 | | - header_size = tx_params->internal_hdr_size; |
|---|
| 305 | 311 | |
|---|
| 306 | 312 | if (((vif->type == NL80211_IFTYPE_STATION) || |
|---|
| 307 | 313 | (vif->type == NL80211_IFTYPE_P2P_CLIENT)) && |
|---|
| .. | .. |
|---|
| 832 | 838 | return 0; |
|---|
| 833 | 839 | } |
|---|
| 834 | 840 | |
|---|
| 835 | | -static int rsi_load_firmware(struct rsi_hw *adapter) |
|---|
| 841 | +static int rsi_hal_prepare_fwload(struct rsi_hw *adapter) |
|---|
| 836 | 842 | { |
|---|
| 837 | | - struct rsi_common *common = adapter->priv; |
|---|
| 838 | 843 | 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; |
|---|
| 844 | + u32 regout_val = 0; |
|---|
| 843 | 845 | int status; |
|---|
| 844 | 846 | |
|---|
| 845 | 847 | bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT); |
|---|
| 846 | 848 | |
|---|
| 847 | 849 | while (!adapter->blcmd_timer_expired) { |
|---|
| 848 | 850 | status = hif_ops->master_reg_read(adapter, SWBL_REGOUT, |
|---|
| 849 | | - ®out_val, 2); |
|---|
| 851 | + ®out_val, |
|---|
| 852 | + RSI_COMMON_REG_SIZE); |
|---|
| 850 | 853 | if (status < 0) { |
|---|
| 851 | 854 | bl_stop_cmd_timer(adapter); |
|---|
| 852 | 855 | rsi_dbg(ERR_ZONE, |
|---|
| .. | .. |
|---|
| 869 | 872 | (regout_val & 0xff)); |
|---|
| 870 | 873 | |
|---|
| 871 | 874 | status = hif_ops->master_reg_write(adapter, SWBL_REGOUT, |
|---|
| 872 | | - (REGOUT_INVALID | REGOUT_INVALID << 8), |
|---|
| 873 | | - 2); |
|---|
| 874 | | - if (status < 0) { |
|---|
| 875 | + (REGOUT_INVALID | |
|---|
| 876 | + REGOUT_INVALID << 8), |
|---|
| 877 | + RSI_COMMON_REG_SIZE); |
|---|
| 878 | + if (status < 0) |
|---|
| 875 | 879 | rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__); |
|---|
| 876 | | - return status; |
|---|
| 877 | | - } |
|---|
| 878 | | - mdelay(1); |
|---|
| 880 | + else |
|---|
| 881 | + rsi_dbg(INFO_ZONE, |
|---|
| 882 | + "===> Device is ready to load firmware <===\n"); |
|---|
| 883 | + |
|---|
| 884 | + return status; |
|---|
| 885 | +} |
|---|
| 886 | + |
|---|
| 887 | +static int rsi_load_9113_firmware(struct rsi_hw *adapter) |
|---|
| 888 | +{ |
|---|
| 889 | + struct rsi_common *common = adapter->priv; |
|---|
| 890 | + const struct firmware *fw_entry = NULL; |
|---|
| 891 | + u32 content_size; |
|---|
| 892 | + u16 tmp_regout_val = 0; |
|---|
| 893 | + struct ta_metadata *metadata_p; |
|---|
| 894 | + int status; |
|---|
| 879 | 895 | |
|---|
| 880 | 896 | status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS, |
|---|
| 881 | 897 | "AUTO_READ_CMD"); |
|---|
| .. | .. |
|---|
| 906 | 922 | |
|---|
| 907 | 923 | /* Get the firmware version */ |
|---|
| 908 | 924 | common->lmac_ver.ver.info.fw_ver[0] = |
|---|
| 909 | | - fw_entry->data[LMAC_VER_OFFSET] & 0xFF; |
|---|
| 925 | + fw_entry->data[LMAC_VER_OFFSET_9113] & 0xFF; |
|---|
| 910 | 926 | 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; |
|---|
| 927 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 1] & 0xFF; |
|---|
| 928 | + common->lmac_ver.major = |
|---|
| 929 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 2] & 0xFF; |
|---|
| 913 | 930 | 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; |
|---|
| 931 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 3] & 0xFF; |
|---|
| 932 | + common->lmac_ver.minor = |
|---|
| 933 | + fw_entry->data[LMAC_VER_OFFSET_9113 + 4] & 0xFF; |
|---|
| 916 | 934 | common->lmac_ver.patch_num = 0; |
|---|
| 917 | 935 | rsi_print_version(common); |
|---|
| 918 | 936 | |
|---|
| .. | .. |
|---|
| 981 | 999 | return status; |
|---|
| 982 | 1000 | } |
|---|
| 983 | 1001 | |
|---|
| 1002 | +static int rsi_load_9116_firmware(struct rsi_hw *adapter) |
|---|
| 1003 | +{ |
|---|
| 1004 | + struct rsi_common *common = adapter->priv; |
|---|
| 1005 | + struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops; |
|---|
| 1006 | + const struct firmware *fw_entry; |
|---|
| 1007 | + struct ta_metadata *metadata_p; |
|---|
| 1008 | + u8 *ta_firmware, *fw_p; |
|---|
| 1009 | + struct bootload_ds bootload_ds; |
|---|
| 1010 | + u32 instructions_sz, base_address; |
|---|
| 1011 | + u16 block_size = adapter->block_size; |
|---|
| 1012 | + u32 dest, len; |
|---|
| 1013 | + int status, cnt; |
|---|
| 1014 | + |
|---|
| 1015 | + rsi_dbg(INIT_ZONE, "***** Load 9116 TA Instructions *****\n"); |
|---|
| 1016 | + |
|---|
| 1017 | + if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) { |
|---|
| 1018 | + status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, |
|---|
| 1019 | + "POLLING_MODE"); |
|---|
| 1020 | + if (status < 0) |
|---|
| 1021 | + return status; |
|---|
| 1022 | + } |
|---|
| 1023 | + |
|---|
| 1024 | + status = hif_ops->master_reg_write(adapter, MEM_ACCESS_CTRL_FROM_HOST, |
|---|
| 1025 | + RAM_384K_ACCESS_FROM_TA, |
|---|
| 1026 | + RSI_9116_REG_SIZE); |
|---|
| 1027 | + if (status < 0) { |
|---|
| 1028 | + rsi_dbg(ERR_ZONE, "%s: Unable to access full RAM memory\n", |
|---|
| 1029 | + __func__); |
|---|
| 1030 | + return status; |
|---|
| 1031 | + } |
|---|
| 1032 | + |
|---|
| 1033 | + metadata_p = &metadata[adapter->priv->coex_mode]; |
|---|
| 1034 | + rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name); |
|---|
| 1035 | + status = request_firmware(&fw_entry, metadata_p->name, adapter->device); |
|---|
| 1036 | + if (status < 0) { |
|---|
| 1037 | + rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n", |
|---|
| 1038 | + __func__, metadata_p->name); |
|---|
| 1039 | + return status; |
|---|
| 1040 | + } |
|---|
| 1041 | + |
|---|
| 1042 | + ta_firmware = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); |
|---|
| 1043 | + if (!ta_firmware) { |
|---|
| 1044 | + status = -ENOMEM; |
|---|
| 1045 | + goto fail_release_fw; |
|---|
| 1046 | + } |
|---|
| 1047 | + fw_p = ta_firmware; |
|---|
| 1048 | + instructions_sz = fw_entry->size; |
|---|
| 1049 | + rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", instructions_sz); |
|---|
| 1050 | + |
|---|
| 1051 | + common->lmac_ver.major = ta_firmware[LMAC_VER_OFFSET_9116]; |
|---|
| 1052 | + common->lmac_ver.minor = ta_firmware[LMAC_VER_OFFSET_9116 + 1]; |
|---|
| 1053 | + common->lmac_ver.release_num = ta_firmware[LMAC_VER_OFFSET_9116 + 2]; |
|---|
| 1054 | + common->lmac_ver.patch_num = ta_firmware[LMAC_VER_OFFSET_9116 + 3]; |
|---|
| 1055 | + common->lmac_ver.ver.info.fw_ver[0] = |
|---|
| 1056 | + ta_firmware[LMAC_VER_OFFSET_9116 + 4]; |
|---|
| 1057 | + |
|---|
| 1058 | + if (instructions_sz % FW_ALIGN_SIZE) |
|---|
| 1059 | + instructions_sz += |
|---|
| 1060 | + (FW_ALIGN_SIZE - (instructions_sz % FW_ALIGN_SIZE)); |
|---|
| 1061 | + rsi_dbg(INFO_ZONE, "instructions_sz : %d\n", instructions_sz); |
|---|
| 1062 | + |
|---|
| 1063 | + if (*(u16 *)fw_p == RSI_9116_FW_MAGIC_WORD) { |
|---|
| 1064 | + memcpy(&bootload_ds, fw_p, sizeof(struct bootload_ds)); |
|---|
| 1065 | + fw_p += le16_to_cpu(bootload_ds.offset); |
|---|
| 1066 | + rsi_dbg(INFO_ZONE, "FW start = %x\n", *(u32 *)fw_p); |
|---|
| 1067 | + |
|---|
| 1068 | + cnt = 0; |
|---|
| 1069 | + do { |
|---|
| 1070 | + rsi_dbg(ERR_ZONE, "%s: Loading chunk %d\n", |
|---|
| 1071 | + __func__, cnt); |
|---|
| 1072 | + |
|---|
| 1073 | + dest = le32_to_cpu(bootload_ds.bl_entry[cnt].dst_addr); |
|---|
| 1074 | + len = le32_to_cpu(bootload_ds.bl_entry[cnt].control) & |
|---|
| 1075 | + RSI_BL_CTRL_LEN_MASK; |
|---|
| 1076 | + rsi_dbg(INFO_ZONE, "length %d destination %x\n", |
|---|
| 1077 | + len, dest); |
|---|
| 1078 | + |
|---|
| 1079 | + status = hif_ops->load_data_master_write(adapter, dest, |
|---|
| 1080 | + len, |
|---|
| 1081 | + block_size, |
|---|
| 1082 | + fw_p); |
|---|
| 1083 | + if (status < 0) { |
|---|
| 1084 | + rsi_dbg(ERR_ZONE, |
|---|
| 1085 | + "Failed to load chunk %d\n", cnt); |
|---|
| 1086 | + break; |
|---|
| 1087 | + } |
|---|
| 1088 | + fw_p += len; |
|---|
| 1089 | + if (le32_to_cpu(bootload_ds.bl_entry[cnt].control) & |
|---|
| 1090 | + RSI_BL_CTRL_LAST_ENTRY) |
|---|
| 1091 | + break; |
|---|
| 1092 | + cnt++; |
|---|
| 1093 | + } while (1); |
|---|
| 1094 | + } else { |
|---|
| 1095 | + base_address = metadata_p->address; |
|---|
| 1096 | + status = hif_ops->load_data_master_write(adapter, |
|---|
| 1097 | + base_address, |
|---|
| 1098 | + instructions_sz, |
|---|
| 1099 | + block_size, |
|---|
| 1100 | + ta_firmware); |
|---|
| 1101 | + } |
|---|
| 1102 | + if (status) { |
|---|
| 1103 | + rsi_dbg(ERR_ZONE, |
|---|
| 1104 | + "%s: Unable to load %s blk\n", |
|---|
| 1105 | + __func__, metadata_p->name); |
|---|
| 1106 | + goto fail_free_fw; |
|---|
| 1107 | + } |
|---|
| 1108 | + |
|---|
| 1109 | + rsi_dbg(INIT_ZONE, "%s: Successfully loaded %s instructions\n", |
|---|
| 1110 | + __func__, metadata_p->name); |
|---|
| 1111 | + |
|---|
| 1112 | + if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) { |
|---|
| 1113 | + if (hif_ops->ta_reset(adapter)) |
|---|
| 1114 | + rsi_dbg(ERR_ZONE, "Unable to put ta in reset\n"); |
|---|
| 1115 | + } else { |
|---|
| 1116 | + if (bl_cmd(adapter, JUMP_TO_ZERO_PC, |
|---|
| 1117 | + CMD_PASS, "JUMP_TO_ZERO") < 0) |
|---|
| 1118 | + rsi_dbg(INFO_ZONE, "Jump to zero command failed\n"); |
|---|
| 1119 | + else |
|---|
| 1120 | + rsi_dbg(INFO_ZONE, "Jump to zero command successful\n"); |
|---|
| 1121 | + } |
|---|
| 1122 | + |
|---|
| 1123 | +fail_free_fw: |
|---|
| 1124 | + kfree(ta_firmware); |
|---|
| 1125 | +fail_release_fw: |
|---|
| 1126 | + release_firmware(fw_entry); |
|---|
| 1127 | + |
|---|
| 1128 | + return status; |
|---|
| 1129 | +} |
|---|
| 1130 | + |
|---|
| 984 | 1131 | int rsi_hal_device_init(struct rsi_hw *adapter) |
|---|
| 985 | 1132 | { |
|---|
| 986 | 1133 | struct rsi_common *common = adapter->priv; |
|---|
| 1134 | + int status; |
|---|
| 987 | 1135 | |
|---|
| 988 | 1136 | switch (adapter->device_model) { |
|---|
| 989 | 1137 | case RSI_DEV_9113: |
|---|
| 990 | | - if (rsi_load_firmware(adapter)) { |
|---|
| 1138 | + status = rsi_hal_prepare_fwload(adapter); |
|---|
| 1139 | + if (status < 0) |
|---|
| 1140 | + return status; |
|---|
| 1141 | + if (rsi_load_9113_firmware(adapter)) { |
|---|
| 991 | 1142 | rsi_dbg(ERR_ZONE, |
|---|
| 992 | 1143 | "%s: Failed to load TA instructions\n", |
|---|
| 993 | 1144 | __func__); |
|---|
| 994 | 1145 | return -EINVAL; |
|---|
| 995 | 1146 | } |
|---|
| 996 | 1147 | break; |
|---|
| 1148 | + case RSI_DEV_9116: |
|---|
| 1149 | + status = rsi_hal_prepare_fwload(adapter); |
|---|
| 1150 | + if (status < 0) |
|---|
| 1151 | + return status; |
|---|
| 1152 | + if (rsi_load_9116_firmware(adapter)) { |
|---|
| 1153 | + rsi_dbg(ERR_ZONE, |
|---|
| 1154 | + "%s: Failed to load firmware to 9116 device\n", |
|---|
| 1155 | + __func__); |
|---|
| 1156 | + return -EINVAL; |
|---|
| 1157 | + } |
|---|
| 1158 | + break; |
|---|
| 997 | 1159 | default: |
|---|
| 998 | 1160 | return -EINVAL; |
|---|
| 999 | 1161 | } |
|---|