};
+static struct ta_metadata metadata[] = {{"pmemdata_dummy", 0x00000000},
+ {"rsi/rs9116_wlan.rps", 0x00000000},
+ {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000},
+ {"rsi/pmemdata_dummy", 0x00000000},
+ {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000}
+};
+
int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
return status;
}
+static int rsi_load_9116_firmware(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ const struct firmware *fw_entry;
+ struct ta_metadata *metadata_p;
+ u8 *ta_firmware, *fw_p;
+ struct bootload_ds bootload_ds;
+ u32 instructions_sz, base_address;
+ u16 block_size = adapter->block_size;
+ u32 dest, len;
+ int status, cnt;
+
+ rsi_dbg(INIT_ZONE, "***** Load 9116 TA Instructions *****\n");
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+ status = bl_cmd(adapter, POLLING_MODE, CMD_PASS,
+ "POLLING_MODE");
+ if (status < 0)
+ return status;
+ }
+
+ status = hif_ops->master_reg_write(adapter, MEM_ACCESS_CTRL_FROM_HOST,
+ RAM_384K_ACCESS_FROM_TA,
+ RSI_9116_REG_SIZE);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to access full RAM memory\n",
+ __func__);
+ return status;
+ }
+
+ metadata_p = &metadata[adapter->priv->coex_mode];
+ rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name);
+ status = request_firmware(&fw_entry, metadata_p->name, adapter->device);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ __func__, metadata_p->name);
+ return status;
+ }
+
+ ta_firmware = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!ta_firmware)
+ goto fail_release_fw;
+ fw_p = ta_firmware;
+ instructions_sz = fw_entry->size;
+ rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", instructions_sz);
+
+ common->lmac_ver.major = ta_firmware[LMAC_VER_OFFSET_9116];
+ common->lmac_ver.minor = ta_firmware[LMAC_VER_OFFSET_9116 + 1];
+ common->lmac_ver.release_num = ta_firmware[LMAC_VER_OFFSET_9116 + 2];
+ common->lmac_ver.patch_num = ta_firmware[LMAC_VER_OFFSET_9116 + 3];
+ common->lmac_ver.ver.info.fw_ver[0] =
+ ta_firmware[LMAC_VER_OFFSET_9116 + 4];
+
+ if (instructions_sz % FW_ALIGN_SIZE)
+ instructions_sz +=
+ (FW_ALIGN_SIZE - (instructions_sz % FW_ALIGN_SIZE));
+ rsi_dbg(INFO_ZONE, "instructions_sz : %d\n", instructions_sz);
+
+ if (*(u16 *)fw_p == RSI_9116_FW_MAGIC_WORD) {
+ memcpy(&bootload_ds, fw_p, sizeof(struct bootload_ds));
+ fw_p += le16_to_cpu(bootload_ds.offset);
+ rsi_dbg(INFO_ZONE, "FW start = %x\n", *(u32 *)fw_p);
+
+ cnt = 0;
+ do {
+ rsi_dbg(ERR_ZONE, "%s: Loading chunk %d\n",
+ __func__, cnt);
+
+ dest = le32_to_cpu(bootload_ds.bl_entry[cnt].dst_addr);
+ len = le32_to_cpu(bootload_ds.bl_entry[cnt].control) &
+ RSI_BL_CTRL_LEN_MASK;
+ rsi_dbg(INFO_ZONE, "length %d destination %x\n",
+ len, dest);
+
+ status = hif_ops->load_data_master_write(adapter, dest,
+ len,
+ block_size,
+ fw_p);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Failed to load chunk %d\n", cnt);
+ break;
+ }
+ fw_p += len;
+ if (le32_to_cpu(bootload_ds.bl_entry[cnt].control) &
+ RSI_BL_CTRL_LAST_ENTRY)
+ break;
+ cnt++;
+ } while (1);
+ } else {
+ base_address = metadata_p->address;
+ status = hif_ops->load_data_master_write(adapter,
+ base_address,
+ instructions_sz,
+ block_size,
+ ta_firmware);
+ }
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to load %s blk\n",
+ __func__, metadata_p->name);
+ goto fail_free_fw;
+ }
+
+ rsi_dbg(INIT_ZONE, "%s: Successfully loaded %s instructions\n",
+ __func__, metadata_p->name);
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) {
+ if (hif_ops->ta_reset(adapter))
+ rsi_dbg(ERR_ZONE, "Unable to put ta in reset\n");
+ } else {
+ if (bl_cmd(adapter, JUMP_TO_ZERO_PC,
+ CMD_PASS, "JUMP_TO_ZERO") < 0)
+ rsi_dbg(INFO_ZONE, "Jump to zero command failed\n");
+ else
+ rsi_dbg(INFO_ZONE, "Jump to zero command successful\n");
+ }
+
+fail_free_fw:
+ kfree(ta_firmware);
+fail_release_fw:
+ release_firmware(fw_entry);
+
+ return status;
+}
+
int rsi_hal_device_init(struct rsi_hw *adapter)
{
struct rsi_common *common = adapter->priv;
return -EINVAL;
}
break;
+ case RSI_DEV_9116:
+ status = rsi_hal_prepare_fwload(adapter);
+ if (status < 0)
+ return status;
+ if (rsi_load_9116_firmware(adapter)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load firmware to 9116 device\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
default:
return -EINVAL;
}
return 0;
}
+static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
+{
+ int status;
+ u32 addr;
+ u8 *data;
+
+ status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Unable to set ms word to common reg\n");
+ return status;
+ }
+
+ rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
+ put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
+ addr = TA_HOLD_THREAD_REG | RSI_SD_REQUEST_MASTER;
+ status = rsi_sdio_write_register_multiple(adapter, addr,
+ (u8 *)&data,
+ RSI_9116_REG_SIZE);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n");
+ return status;
+ }
+
+ put_unaligned_le32(TA_SOFT_RST_CLR, data);
+ addr = TA_SOFT_RESET_REG | RSI_SD_REQUEST_MASTER;
+ status = rsi_sdio_write_register_multiple(adapter, addr,
+ (u8 *)&data,
+ RSI_9116_REG_SIZE);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n");
+ return status;
+ }
+
+ put_unaligned_le32(TA_PC_ZERO, data);
+ addr = TA_TH0_PC_REG | RSI_SD_REQUEST_MASTER;
+ status = rsi_sdio_write_register_multiple(adapter, addr,
+ (u8 *)&data,
+ RSI_9116_REG_SIZE);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n");
+ return -EINVAL;
+ }
+
+ put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
+ addr = TA_RELEASE_THREAD_REG | RSI_SD_REQUEST_MASTER;
+ status = rsi_sdio_write_register_multiple(adapter, addr,
+ (u8 *)&data,
+ RSI_9116_REG_SIZE);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "Unable to release TA threads\n");
+ return status;
+ }
+
+ status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n");
+ return status;
+ }
+ rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n");
+
+ return 0;
+}
+
static struct rsi_host_intf_ops sdio_host_intf_ops = {
.write_pkt = rsi_sdio_host_intf_write_pkt,
.read_pkt = rsi_sdio_host_intf_read_pkt,
.master_reg_write = rsi_sdio_master_reg_write,
.load_data_master_write = rsi_sdio_load_data_master_write,
.reinit_device = rsi_sdio_reinit_device,
+ .ta_reset = rsi_sdio_ta_reset,
};
/**