diff options
Diffstat (limited to 'drivers/net/wireless/rsi')
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_hal.c | 199 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_mac80211.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_mgmt.c | 232 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_sdio.c | 129 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_usb.c | 96 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_boot_params.h | 63 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_hal.h | 44 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_main.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_mgmt.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_sdio.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_usb.h | 3 |
11 files changed, 750 insertions, 98 deletions
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index 1dbaab2a96b7..f84250bdb8cf 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -31,6 +31,13 @@ static struct ta_metadata metadata_flash_content[] = { }; +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; @@ -829,21 +836,18 @@ static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content, return 0; } -static int rsi_load_firmware(struct rsi_hw *adapter) +static int rsi_hal_prepare_fwload(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 = NULL; - u32 regout_val = 0, content_size; - u16 tmp_regout_val = 0; - struct ta_metadata *metadata_p; + u32 regout_val = 0; int status; bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT); while (!adapter->blcmd_timer_expired) { status = hif_ops->master_reg_read(adapter, SWBL_REGOUT, - ®out_val, 2); + ®out_val, + RSI_COMMON_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "%s: REGOUT read failed\n", __func__); @@ -865,13 +869,26 @@ static int rsi_load_firmware(struct rsi_hw *adapter) (regout_val & 0xff)); status = hif_ops->master_reg_write(adapter, SWBL_REGOUT, - (REGOUT_INVALID | REGOUT_INVALID << 8), - 2); - if (status < 0) { + (REGOUT_INVALID | + REGOUT_INVALID << 8), + RSI_COMMON_REG_SIZE); + if (status < 0) rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__); - return status; - } - mdelay(1); + else + rsi_dbg(INFO_ZONE, + "===> Device is ready to load firmware <===\n"); + + return status; +} + +static int rsi_load_9113_firmware(struct rsi_hw *adapter) +{ + struct rsi_common *common = adapter->priv; + const struct firmware *fw_entry = NULL; + u32 content_size; + u16 tmp_regout_val = 0; + struct ta_metadata *metadata_p; + int status; status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS, "AUTO_READ_CMD"); @@ -902,13 +919,15 @@ static int rsi_load_firmware(struct rsi_hw *adapter) /* Get the firmware version */ common->lmac_ver.ver.info.fw_ver[0] = - fw_entry->data[LMAC_VER_OFFSET] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113] & 0xFF; common->lmac_ver.ver.info.fw_ver[1] = - fw_entry->data[LMAC_VER_OFFSET + 1] & 0xFF; - common->lmac_ver.major = fw_entry->data[LMAC_VER_OFFSET + 2] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113 + 1] & 0xFF; + common->lmac_ver.major = + fw_entry->data[LMAC_VER_OFFSET_9113 + 2] & 0xFF; common->lmac_ver.release_num = - fw_entry->data[LMAC_VER_OFFSET + 3] & 0xFF; - common->lmac_ver.minor = fw_entry->data[LMAC_VER_OFFSET + 4] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113 + 3] & 0xFF; + common->lmac_ver.minor = + fw_entry->data[LMAC_VER_OFFSET_9113 + 4] & 0xFF; common->lmac_ver.patch_num = 0; rsi_print_version(common); @@ -977,19 +996,161 @@ fail: 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; + int status; switch (adapter->device_model) { case RSI_DEV_9113: - if (rsi_load_firmware(adapter)) { + status = rsi_hal_prepare_fwload(adapter); + if (status < 0) + return status; + if (rsi_load_9113_firmware(adapter)) { rsi_dbg(ERR_ZONE, "%s: Failed to load TA instructions\n", __func__); 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; } diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 831046e760f8..49df3bb08d41 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -188,27 +188,27 @@ bool rsi_is_cipher_wep(struct rsi_common *common) * @adapter: Pointer to the adapter structure. * @band: Operating band to be set. * - * Return: None. + * Return: int - 0 on success, negative error on failure. */ -static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) +static int rsi_register_rates_channels(struct rsi_hw *adapter, int band) { struct ieee80211_supported_band *sbands = &adapter->sbands[band]; void *channels = NULL; if (band == NL80211_BAND_2GHZ) { - channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL); - memcpy(channels, - rsi_2ghz_channels, - sizeof(rsi_2ghz_channels)); + channels = kmemdup(rsi_2ghz_channels, sizeof(rsi_2ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; sbands->band = NL80211_BAND_2GHZ; sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels); sbands->bitrates = rsi_rates; sbands->n_bitrates = ARRAY_SIZE(rsi_rates); } else { - channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL); - memcpy(channels, - rsi_5ghz_channels, - sizeof(rsi_5ghz_channels)); + channels = kmemdup(rsi_5ghz_channels, sizeof(rsi_5ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; sbands->band = NL80211_BAND_5GHZ; sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels); sbands->bitrates = &rsi_rates[4]; @@ -227,6 +227,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) sbands->ht_cap.mcs.rx_mask[0] = 0xff; sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; /* sbands->ht_cap.mcs.rx_highest = 0x82; */ + return 0; } static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw, @@ -2064,11 +2065,16 @@ int rsi_mac80211_attach(struct rsi_common *common) wiphy->available_antennas_rx = 1; wiphy->available_antennas_tx = 1; - rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ); + status = rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ); + if (status) + return status; wiphy->bands[NL80211_BAND_2GHZ] = &adapter->sbands[NL80211_BAND_2GHZ]; if (common->num_supp_bands > 1) { - rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ); + status = rsi_register_rates_channels(adapter, + NL80211_BAND_5GHZ); + if (status) + return status; wiphy->bands[NL80211_BAND_5GHZ] = &adapter->sbands[NL80211_BAND_5GHZ]; } diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 844f2fac298f..6c7f26ef6476 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -209,6 +209,59 @@ static struct bootup_params boot_params_40 = { .beacon_resedue_alg_en = 0, }; +static struct bootup_params_9116 boot_params_9116_20 = { + .magic_number = cpu_to_le16(LOADED_TOKEN), + .valid = cpu_to_le32(VALID_20), + .device_clk_info_9116 = {{ + .pll_config_9116_g = { + .pll_ctrl_set_reg = cpu_to_le16(0xd518), + .pll_ctrl_clr_reg = cpu_to_le16(0x2ae7), + .pll_modem_conig_reg = cpu_to_le16(0x2000), + .soc_clk_config_reg = cpu_to_le16(0x0c18), + .adc_dac_strm1_config_reg = cpu_to_le16(0x1100), + .adc_dac_strm2_config_reg = cpu_to_le16(0x6600), + }, + .switch_clk_9116_g = { + .switch_clk_info = + cpu_to_le32((RSI_SWITCH_TASS_CLK | + RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG | + RSI_SWITCH_BBP_LMAC_CLK_REG)), + .tass_clock_reg = cpu_to_le32(0x083C0503), + .wlan_bbp_lmac_clk_reg_val = cpu_to_le32(0x01042001), + .zbbt_bbp_lmac_clk_reg_val = cpu_to_le32(0x02010001), + .bbp_lmac_clk_en_val = cpu_to_le32(0x0000003b), + } + }, + }, +}; + +static struct bootup_params_9116 boot_params_9116_40 = { + .magic_number = cpu_to_le16(LOADED_TOKEN), + .valid = cpu_to_le32(VALID_40), + .device_clk_info_9116 = {{ + .pll_config_9116_g = { + .pll_ctrl_set_reg = cpu_to_le16(0xd518), + .pll_ctrl_clr_reg = cpu_to_le16(0x2ae7), + .pll_modem_conig_reg = cpu_to_le16(0x3000), + .soc_clk_config_reg = cpu_to_le16(0x0c18), + .adc_dac_strm1_config_reg = cpu_to_le16(0x0000), + .adc_dac_strm2_config_reg = cpu_to_le16(0x6600), + }, + .switch_clk_9116_g = { + .switch_clk_info = + cpu_to_le32((RSI_SWITCH_TASS_CLK | + RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG | + RSI_SWITCH_BBP_LMAC_CLK_REG | + RSI_MODEM_CLK_160MHZ)), + .tass_clock_reg = cpu_to_le32(0x083C0503), + .wlan_bbp_lmac_clk_reg_val = cpu_to_le32(0x01042002), + .zbbt_bbp_lmac_clk_reg_val = cpu_to_le32(0x04010002), + .bbp_lmac_clk_en_val = cpu_to_le32(0x0000003b), + } + }, + }, +}; + static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130}; /** @@ -235,6 +288,14 @@ static void rsi_set_default_parameters(struct rsi_common *common) common->obm_ant_sel_val = 2; common->beacon_interval = RSI_BEACON_INTERVAL; common->dtim_cnt = RSI_DTIM_COUNT; + common->w9116_features.pll_mode = 0x0; + common->w9116_features.rf_type = 1; + common->w9116_features.wireless_mode = 0; + common->w9116_features.enable_ppe = 0; + common->w9116_features.afe_type = 1; + common->w9116_features.dpd = 0; + common->w9116_features.sifs_tx_enable = 0; + common->w9116_features.ps_options = 0; } void init_bgscan_params(struct rsi_common *common) @@ -363,6 +424,10 @@ static int rsi_load_radio_caps(struct rsi_common *common) } radio_caps->radio_info |= radio_id; + if (adapter->device_model == RSI_DEV_9116 && + common->channel_width == BW_20MHZ) + radio_caps->radio_cfg_info &= ~0x3; + radio_caps->sifs_tx_11n = cpu_to_le16(SIFS_TX_11N_VALUE); radio_caps->sifs_tx_11b = cpu_to_le16(SIFS_TX_11B_VALUE); radio_caps->slot_rx_11n = cpu_to_le16(SHORT_SLOT_VALUE); @@ -378,14 +443,16 @@ static int rsi_load_radio_caps(struct rsi_common *common) } for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { - radio_caps->qos_params[ii].cont_win_min_q = - cpu_to_le16(common->edca_params[ii].cw_min); - radio_caps->qos_params[ii].cont_win_max_q = - cpu_to_le16(common->edca_params[ii].cw_max); - radio_caps->qos_params[ii].aifsn_val_q = - cpu_to_le16((common->edca_params[ii].aifs) << 8); - radio_caps->qos_params[ii].txop_q = - cpu_to_le16(common->edca_params[ii].txop); + if (common->edca_params[ii].cw_max > 0) { + radio_caps->qos_params[ii].cont_win_min_q = + cpu_to_le16(common->edca_params[ii].cw_min); + radio_caps->qos_params[ii].cont_win_max_q = + cpu_to_le16(common->edca_params[ii].cw_max); + radio_caps->qos_params[ii].aifsn_val_q = + cpu_to_le16(common->edca_params[ii].aifs << 8); + radio_caps->qos_params[ii].txop_q = + cpu_to_le16(common->edca_params[ii].txop); + } } radio_caps->qos_params[BROADCAST_HW_Q].txop_q = cpu_to_le16(0xffff); @@ -893,6 +960,50 @@ static int rsi_load_bootup_params(struct rsi_common *common) return rsi_send_internal_mgmt_frame(common, skb); } +static int rsi_load_9116_bootup_params(struct rsi_common *common) +{ + struct sk_buff *skb; + struct rsi_boot_params_9116 *boot_params; + + rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__); + + skb = dev_alloc_skb(sizeof(struct rsi_boot_params_9116)); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, sizeof(struct rsi_boot_params)); + boot_params = (struct rsi_boot_params_9116 *)skb->data; + + if (common->channel_width == BW_40MHZ) { + memcpy(&boot_params->bootup_params, + &boot_params_9116_40, + sizeof(struct bootup_params_9116)); + rsi_dbg(MGMT_TX_ZONE, "%s: Packet 40MHZ <=== %d\n", __func__, + UMAC_CLK_40BW); + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_40BW); + } else { + memcpy(&boot_params->bootup_params, + &boot_params_9116_20, + sizeof(struct bootup_params_9116)); + if (boot_params_20.valid != cpu_to_le32(VALID_20)) { + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_20BW); + rsi_dbg(MGMT_TX_ZONE, + "%s: Packet 20MHZ <=== %d\n", __func__, + UMAC_CLK_20BW); + } else { + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_40MHZ); + rsi_dbg(MGMT_TX_ZONE, + "%s: Packet 20MHZ <=== %d\n", __func__, + UMAC_CLK_40MHZ); + } + } + rsi_set_len_qno(&boot_params->desc_dword0.len_qno, + sizeof(struct bootup_params_9116), RSI_WIFI_MGMT_Q); + boot_params->desc_dword0.frame_type = BOOTUP_PARAMS_REQUEST; + skb_put(skb, sizeof(struct rsi_boot_params_9116)); + + return rsi_send_internal_mgmt_frame(common, skb); +} + /** * rsi_send_reset_mac() - This function prepares reset MAC request and sends an * internal management frame to indicate it to firmware. @@ -921,6 +1032,11 @@ static int rsi_send_reset_mac(struct rsi_common *common) mgmt_frame->desc_word[1] = cpu_to_le16(RESET_MAC_REQ); mgmt_frame->desc_word[4] = cpu_to_le16(RETRY_COUNT << 8); +#define RSI_9116_DEF_TA_AGGR 3 + if (common->priv->device_model == RSI_DEV_9116) + mgmt_frame->desc_word[3] |= + cpu_to_le16(RSI_9116_DEF_TA_AGGR << 8); + skb_put(skb, FRAME_DESC_SZ); return rsi_send_internal_mgmt_frame(common, skb); @@ -971,7 +1087,10 @@ int rsi_band_check(struct rsi_common *common, } if (common->channel_width != prev_bw) { - status = rsi_load_bootup_params(common); + if (adapter->device_model == RSI_DEV_9116) + status = rsi_load_9116_bootup_params(common); + else + status = rsi_load_bootup_params(common); if (status) return status; @@ -1546,6 +1665,47 @@ int rsi_send_ps_request(struct rsi_hw *adapter, bool enable, return rsi_send_internal_mgmt_frame(common, skb); } +static int rsi_send_w9116_features(struct rsi_common *common) +{ + struct rsi_wlan_9116_features *w9116_features; + u16 frame_len = sizeof(struct rsi_wlan_9116_features); + struct sk_buff *skb; + + rsi_dbg(MGMT_TX_ZONE, + "%s: Sending wlan 9116 features\n", __func__); + + skb = dev_alloc_skb(frame_len); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, frame_len); + + w9116_features = (struct rsi_wlan_9116_features *)skb->data; + + w9116_features->pll_mode = common->w9116_features.pll_mode; + w9116_features->rf_type = common->w9116_features.rf_type; + w9116_features->wireless_mode = common->w9116_features.wireless_mode; + w9116_features->enable_ppe = common->w9116_features.enable_ppe; + w9116_features->afe_type = common->w9116_features.afe_type; + if (common->w9116_features.dpd) + w9116_features->feature_enable |= cpu_to_le32(RSI_DPD); + if (common->w9116_features.sifs_tx_enable) + w9116_features->feature_enable |= + cpu_to_le32(RSI_SIFS_TX_ENABLE); + if (common->w9116_features.ps_options & RSI_DUTY_CYCLING) + w9116_features->feature_enable |= cpu_to_le32(RSI_DUTY_CYCLING); + if (common->w9116_features.ps_options & RSI_END_OF_FRAME) + w9116_features->feature_enable |= cpu_to_le32(RSI_END_OF_FRAME); + w9116_features->feature_enable |= + cpu_to_le32((common->w9116_features.ps_options & ~0x3) << 2); + + rsi_set_len_qno(&w9116_features->desc.desc_dword0.len_qno, + frame_len - FRAME_DESC_SZ, RSI_WIFI_MGMT_Q); + w9116_features->desc.desc_dword0.frame_type = FEATURES_ENABLE; + skb_put(skb, frame_len); + + return rsi_send_internal_mgmt_frame(common, skb); +} + /** * rsi_set_antenna() - This function send antenna configuration request * to device @@ -1766,15 +1926,26 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, rsi_dbg(FSM_ZONE, "%s: Boot up params confirm received\n", __func__); if (common->fsm_state == FSM_BOOT_PARAMS_SENT) { - adapter->eeprom.length = (IEEE80211_ADDR_LEN + - WLAN_MAC_MAGIC_WORD_LEN + - WLAN_HOST_MODE_LEN); - adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR; - if (rsi_eeprom_read(common)) { - common->fsm_state = FSM_CARD_NOT_READY; - goto out; + if (adapter->device_model == RSI_DEV_9116) { + common->band = NL80211_BAND_5GHZ; + common->num_supp_bands = 2; + + if (rsi_send_reset_mac(common)) + goto out; + else + common->fsm_state = FSM_RESET_MAC_SENT; + } else { + adapter->eeprom.length = + (IEEE80211_ADDR_LEN + + WLAN_MAC_MAGIC_WORD_LEN + + WLAN_HOST_MODE_LEN); + adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR; + if (rsi_eeprom_read(common)) { + common->fsm_state = FSM_CARD_NOT_READY; + goto out; + } + common->fsm_state = FSM_EEPROM_READ_MAC_ADDR; } - common->fsm_state = FSM_EEPROM_READ_MAC_ADDR; } else { rsi_dbg(INFO_ZONE, "%s: Received bootup params cfm in %d state\n", @@ -1853,6 +2024,12 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, case RADIO_CAPABILITIES: if (common->fsm_state == FSM_RADIO_CAPS_SENT) { common->rf_reset = 1; + if (adapter->device_model == RSI_DEV_9116 && + rsi_send_w9116_features(common)) { + rsi_dbg(ERR_ZONE, + "Failed to send 9116 features\n"); + goto out; + } if (rsi_program_bb_rf(common)) { goto out; } else { @@ -1925,6 +2102,8 @@ out: int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) { + int status; + switch (common->fsm_state) { case FSM_CARD_NOT_READY: rsi_dbg(INIT_ZONE, "Card ready indication from Common HAL\n"); @@ -1936,14 +2115,29 @@ int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) case FSM_COMMON_DEV_PARAMS_SENT: rsi_dbg(INIT_ZONE, "Card ready indication from WLAN HAL\n"); + if (common->priv->device_model == RSI_DEV_9116) { + if (msg[16] != MAGIC_WORD) { + rsi_dbg(FSM_ZONE, + "%s: [EEPROM_READ] Invalid token\n", + __func__); + common->fsm_state = FSM_CARD_NOT_READY; + return -EINVAL; + } + memcpy(common->mac_addr, &msg[20], ETH_ALEN); + rsi_dbg(INIT_ZONE, "MAC Addr %pM", common->mac_addr); + } /* Get usb buffer status register address */ common->priv->usb_buffer_status_reg = *(u32 *)&msg[8]; rsi_dbg(INFO_ZONE, "USB buffer status register = %x\n", common->priv->usb_buffer_status_reg); - if (rsi_load_bootup_params(common)) { + if (common->priv->device_model == RSI_DEV_9116) + status = rsi_load_9116_bootup_params(common); + else + status = rsi_load_bootup_params(common); + if (status < 0) { common->fsm_state = FSM_CARD_NOT_READY; - return -EINVAL; + return status; } common->fsm_state = FSM_BOOT_PARAMS_SENT; break; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 3430d7a0899e..f9c67ed473d1 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -923,6 +923,70 @@ static int rsi_sdio_reinit_device(struct rsi_hw *adapter) 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, @@ -933,6 +997,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = { .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, }; /** @@ -949,7 +1014,7 @@ static int rsi_probe(struct sdio_func *pfunction, { struct rsi_hw *adapter; struct rsi_91x_sdiodev *sdev; - int status; + int status = -EINVAL; rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__); @@ -968,6 +1033,20 @@ static int rsi_probe(struct sdio_func *pfunction, status = -EIO; goto fail_free_adapter; } + + if (pfunction->device == RSI_SDIO_PID_9113) { + rsi_dbg(ERR_ZONE, "%s: 9113 module detected\n", __func__); + adapter->device_model = RSI_DEV_9113; + } else if (pfunction->device == RSI_SDIO_PID_9116) { + rsi_dbg(ERR_ZONE, "%s: 9116 module detected\n", __func__); + adapter->device_model = RSI_DEV_9116; + } else { + rsi_dbg(ERR_ZONE, + "%s: Unsupported RSI device id 0x%x\n", __func__, + pfunction->device); + goto fail_free_adapter; + } + sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; rsi_init_event(&sdev->rx_thread.event); status = rsi_create_kthread(adapter->priv, &sdev->rx_thread, @@ -1088,16 +1167,41 @@ static void rsi_reset_chip(struct rsi_hw *adapter) * and any pending dma transfers to rf spi in device to finish. */ msleep(100); - - ulp_read_write(adapter, RSI_ULP_RESET_REG, RSI_ULP_WRITE_0, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, RSI_ULP_WRITE_2, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, RSI_ULP_WRITE_0, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, RSI_ULP_WRITE_50, - 32); - ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, RSI_ULP_WRITE_0, - 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, - RSI_ULP_TIMER_ENABLE, 32); + if (adapter->device_model != RSI_DEV_9116) { + ulp_read_write(adapter, RSI_ULP_RESET_REG, RSI_ULP_WRITE_0, 32); + ulp_read_write(adapter, + RSI_WATCH_DOG_TIMER_1, RSI_ULP_WRITE_2, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, RSI_ULP_WRITE_0, + 32); + ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, + RSI_ULP_WRITE_50, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, + RSI_ULP_WRITE_0, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, + RSI_ULP_TIMER_ENABLE, 32); + } else { + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_INTERRUPT_TIMER, + NWP_WWD_INT_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, "Failed to write to intr timer\n"); + } + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_SYSTEM_RESET_TIMER, + NWP_WWD_SYS_RESET_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, + "Failed to write to system reset timer\n"); + } + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_MODE_AND_RSTART, + NWP_WWD_TIMER_DISABLE, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, + "Failed to write to mode and restart\n"); + } + rsi_dbg(ERR_ZONE, "***** Watch Dog Reset Successful *****\n"); + } /* This msleep will be sufficient for the ulp * read write operations to complete for chip reset. */ @@ -1415,7 +1519,8 @@ static const struct dev_pm_ops rsi_pm_ops = { #endif static const struct sdio_device_id rsi_dev_table[] = { - { SDIO_DEVICE(RSI_SDIO_VID_9113, RSI_SDIO_PID_9113) }, + { SDIO_DEVICE(RSI_SDIO_VENDOR_ID, RSI_SDIO_PID_9113) }, + { SDIO_DEVICE(RSI_SDIO_VENDOR_ID, RSI_SDIO_PID_9116) }, { /* Blank */}, }; diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index ac0ef5ea6ffb..f5048d4b8cb6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -213,7 +213,7 @@ static int rsi_usb_reg_read(struct usb_device *usbdev, */ static int rsi_usb_reg_write(struct usb_device *usbdev, u32 reg, - u16 value, + u32 value, u16 len) { u8 *usb_reg_buf; @@ -226,17 +226,17 @@ static int rsi_usb_reg_write(struct usb_device *usbdev, if (!usb_reg_buf) return status; - usb_reg_buf[0] = (value & 0x00ff); - usb_reg_buf[1] = (value & 0xff00) >> 8; - usb_reg_buf[2] = 0x0; - usb_reg_buf[3] = 0x0; + usb_reg_buf[0] = (cpu_to_le32(value) & 0x00ff); + usb_reg_buf[1] = (cpu_to_le32(value) & 0xff00) >> 8; + usb_reg_buf[2] = (cpu_to_le32(value) & 0x00ff0000) >> 16; + usb_reg_buf[3] = (cpu_to_le32(value) & 0xff000000) >> 24; status = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), USB_VENDOR_REGISTER_WRITE, RSI_USB_REQ_OUT, - ((reg & 0xffff0000) >> 16), - (reg & 0xffff), + ((cpu_to_le32(reg) & 0xffff0000) >> 16), + (cpu_to_le32(reg) & 0xffff), (void *)usb_reg_buf, len, USB_CTRL_SET_TIMEOUT); @@ -263,8 +263,10 @@ static void rsi_rx_done_handler(struct urb *urb) struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data; int status = -EINVAL; - if (urb->status) - goto out; + if (urb->status) { + dev_kfree_skb(rx_cb->rx_skb); + return; + } if (urb->actual_length <= 0 || urb->actual_length > rx_cb->rx_skb->len) { @@ -698,26 +700,47 @@ static int rsi_reset_card(struct rsi_hw *adapter) goto fail; } - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, - RSI_ULP_WRITE_2, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, - RSI_ULP_WRITE_0, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, - RSI_ULP_WRITE_50, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, - RSI_ULP_WRITE_0, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, - RSI_ULP_TIMER_ENABLE, 32); - if (ret < 0) - goto fail; + if (adapter->device_model != RSI_DEV_9116) { + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, + RSI_ULP_WRITE_2, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, + RSI_ULP_WRITE_0, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, + RSI_ULP_WRITE_50, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, + RSI_ULP_WRITE_0, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, + RSI_ULP_TIMER_ENABLE, 32); + if (ret < 0) + goto fail; + } else { + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_INTERRUPT_TIMER, + NWP_WWD_INT_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_SYSTEM_RESET_TIMER, + NWP_WWD_SYS_RESET_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_MODE_AND_RSTART, + NWP_WWD_TIMER_DISABLE, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + } rsi_dbg(INFO_ZONE, "Reset card done\n"); return ret; @@ -763,6 +786,18 @@ static int rsi_probe(struct usb_interface *pfunction, rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__); + if (id && id->idProduct == RSI_USB_PID_9113) { + rsi_dbg(INIT_ZONE, "%s: 9113 module detected\n", __func__); + adapter->device_model = RSI_DEV_9113; + } else if (id && id->idProduct == RSI_USB_PID_9116) { + rsi_dbg(INIT_ZONE, "%s: 9116 module detected\n", __func__); + adapter->device_model = RSI_DEV_9116; + } else { + rsi_dbg(ERR_ZONE, "%s: Unsupported RSI device id 0x%x\n", + __func__, id->idProduct); + goto err1; + } + dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2); @@ -845,7 +880,8 @@ static int rsi_resume(struct usb_interface *intf) #endif static const struct usb_device_id rsi_dev_table[] = { - { USB_DEVICE(RSI_USB_VID_9113, RSI_USB_PID_9113) }, + { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9113) }, + { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9116) }, { /* Blank */}, }; diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h index ad903b22440e..c1cf19d1e376 100644 --- a/drivers/net/wireless/rsi/rsi_boot_params.h +++ b/drivers/net/wireless/rsi/rsi_boot_params.h @@ -80,6 +80,15 @@ struct pll_config { struct afepll_info afepll_info_g; } __packed; +struct pll_config_9116 { + __le16 pll_ctrl_set_reg; + __le16 pll_ctrl_clr_reg; + __le16 pll_modem_conig_reg; + __le16 soc_clk_config_reg; + __le16 adc_dac_strm1_config_reg; + __le16 adc_dac_strm2_config_reg; +} __packed; + /* structure to store configs related to UMAC clk programming */ struct switch_clk { __le16 switch_clk_info; @@ -93,11 +102,32 @@ struct switch_clk { __le16 qspi_uart_clock_reg_config; } __packed; +#define RSI_SWITCH_TASS_CLK BIT(0) +#define RSI_SWITCH_QSPI_CLK BIT(1) +#define RSI_SWITCH_SLP_CLK_2_32 BIT(2) +#define RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG BIT(3) +#define RSI_SWITCH_ZBBT_BBP_LMAC_CLK_REG BIT(4) +#define RSI_SWITCH_BBP_LMAC_CLK_REG BIT(5) +#define RSI_MODEM_CLK_160MHZ BIT(6) + +struct switch_clk_9116 { + __le32 switch_clk_info; + __le32 tass_clock_reg; + __le32 wlan_bbp_lmac_clk_reg_val; + __le32 zbbt_bbp_lmac_clk_reg_val; + __le32 bbp_lmac_clk_en_val; +} __packed; + struct device_clk_info { struct pll_config pll_config_g; struct switch_clk switch_clk_g; } __packed; +struct device_clk_info_9116 { + struct pll_config_9116 pll_config_9116_g; + struct switch_clk_9116 switch_clk_9116_g; +} __packed; + struct bootup_params { __le16 magic_number; __le16 crystal_good_time; @@ -127,4 +157,37 @@ struct bootup_params { __le32 max_threshold_to_avoid_sleep; u8 beacon_resedue_alg_en; } __packed; + +struct bootup_params_9116 { + __le16 magic_number; +#define LOADED_TOKEN 0x5AA5 /* Bootup params are installed by host + * or OTP/FLASH (Bootloader) + */ +#define ROM_TOKEN 0x55AA /* Bootup params are taken from ROM + * itself in MCU mode. + */ + __le16 crystal_good_time; + __le32 valid; + __le32 reserved_for_valids; + __le16 bootup_mode_info; +#define BT_COEXIST BIT(0) +#define BOOTUP_MODE (BIT(2) | BIT(1)) +#define CUR_DEV_MODE_9116 (bootup_params_9116.bootup_mode_info >> 1) + __le16 digital_loop_back_params; + __le16 rtls_timestamp_en; + __le16 host_spi_intr_cfg; + struct device_clk_info_9116 device_clk_info_9116[1]; + __le32 buckboost_wakeup_cnt; + __le16 pmu_wakeup_wait; + u8 shutdown_wait_time; + u8 pmu_slp_clkout_sel; + __le32 wdt_prog_value; + __le32 wdt_soc_rst_delay; + __le32 dcdc_operation_mode; + __le32 soc_reset_wait_cnt; + __le32 waiting_time_at_fresh_sleep; + __le32 max_threshold_to_avoid_sleep; + u8 beacon_resedue_alg_en; +} __packed; + #endif diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h index 327638cdd30b..46e36df9e8e3 100644 --- a/drivers/net/wireless/rsi/rsi_hal.h +++ b/drivers/net/wireless/rsi/rsi_hal.h @@ -70,6 +70,21 @@ #define RSI_WATCH_DOG_DELAY_TIMER_2 0x16f #define RSI_WATCH_DOG_TIMER_ENABLE 0x170 +/* Watchdog timer addresses for 9116 */ +#define NWP_AHB_BASE_ADDR 0x41300000 +#define NWP_WWD_INTERRUPT_TIMER (NWP_AHB_BASE_ADDR + 0x300) +#define NWP_WWD_SYSTEM_RESET_TIMER (NWP_AHB_BASE_ADDR + 0x304) +#define NWP_WWD_WINDOW_TIMER (NWP_AHB_BASE_ADDR + 0x308) +#define NWP_WWD_TIMER_SETTINGS (NWP_AHB_BASE_ADDR + 0x30C) +#define NWP_WWD_MODE_AND_RSTART (NWP_AHB_BASE_ADDR + 0x310) +#define NWP_WWD_RESET_BYPASS (NWP_AHB_BASE_ADDR + 0x314) +#define NWP_FSM_INTR_MASK_REG (NWP_AHB_BASE_ADDR + 0x104) + +/* Watchdog timer values */ +#define NWP_WWD_INT_TIMER_CLKS 5 +#define NWP_WWD_SYS_RESET_TIMER_CLKS 4 +#define NWP_WWD_TIMER_DISABLE 0xAA0001 + #define RSI_ULP_WRITE_0 00 #define RSI_ULP_WRITE_2 02 #define RSI_ULP_WRITE_50 50 @@ -113,9 +128,18 @@ #define BBP_INFO_40MHZ 0x6 #define FW_FLASH_OFFSET 0x820 -#define LMAC_VER_OFFSET (FW_FLASH_OFFSET + 0x200) +#define LMAC_VER_OFFSET_9113 (FW_FLASH_OFFSET + 0x200) +#define LMAC_VER_OFFSET_9116 0x22C2 #define MAX_DWORD_ALIGN_BYTES 64 #define RSI_COMMON_REG_SIZE 2 +#define RSI_9116_REG_SIZE 4 +#define FW_ALIGN_SIZE 4 +#define RSI_9116_FW_MAGIC_WORD 0x5aa5 + +#define MEM_ACCESS_CTRL_FROM_HOST 0x41300000 +#define RAM_384K_ACCESS_FROM_TA (BIT(2) | BIT(3) | BIT(4) | BIT(5) | \ + BIT(20) | BIT(21) | BIT(22) | \ + BIT(23) | BIT(24) | BIT(25)) struct bl_header { __le32 flags; @@ -130,6 +154,24 @@ struct ta_metadata { unsigned int address; }; +#define RSI_BL_CTRL_LEN_MASK 0xFFFFFF +#define RSI_BL_CTRL_SPI_32BIT_MODE BIT(27) +#define RSI_BL_CTRL_REL_TA_SOFTRESET BIT(28) +#define RSI_BL_CTRL_START_FROM_ROM_PC BIT(29) +#define RSI_BL_CTRL_SPI_8BIT_MODE BIT(30) +#define RSI_BL_CTRL_LAST_ENTRY BIT(31) +struct bootload_entry { + __le32 control; + __le32 dst_addr; +} __packed; + +struct bootload_ds { + __le16 fixed_pattern; + __le16 offset; + __le32 reserved; + struct bootload_entry bl_entry[7]; +} __packed; + struct rsi_mgmt_desc { __le16 len_qno; u8 frame_type; diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 35d13f35e9b0..73a19e43106b 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -111,9 +111,13 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...); #define RSI_WOW_ENABLED BIT(0) #define RSI_WOW_NO_CONNECTION BIT(1) -#define RSI_DEV_9113 1 #define RSI_MAX_RX_PKTS 64 +enum rsi_dev_model { + RSI_DEV_9113 = 0, + RSI_DEV_9116 +}; + struct version_info { u16 major; u16 minor; @@ -215,6 +219,17 @@ enum rsi_dfs_regions { RSI_REGION_WORLD }; +struct rsi_9116_features { + u8 pll_mode; + u8 rf_type; + u8 wireless_mode; + u8 afe_type; + u8 enable_ppe; + u8 dpd; + u32 sifs_tx_enable; + u32 ps_options; +}; + struct rsi_common { struct rsi_hw *priv; struct vif_priv vif_info[RSI_MAX_VIFS]; @@ -310,6 +325,7 @@ struct rsi_common { struct cfg80211_scan_request *hwscan; struct rsi_bgscan_params bgscan; + struct rsi_9116_features w9116_features; u8 bgscan_en; u8 mac_ops_resumed; }; @@ -329,7 +345,7 @@ struct eeprom_read { struct rsi_hw { struct rsi_common *priv; - u8 device_model; + enum rsi_dev_model device_model; struct ieee80211_hw *hw; struct ieee80211_vif *vifs[RSI_MAX_VIFS]; struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES]; @@ -381,6 +397,7 @@ struct rsi_host_intf_ops { u32 instructions_size, u16 block_size, u8 *fw); int (*reinit_device)(struct rsi_hw *adapter); + int (*ta_reset)(struct rsi_hw *adapter); }; enum rsi_host_intf rsi_get_host_intf(void *priv); diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index ea83faa15c7e..2ce2dcf57441 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h @@ -294,6 +294,7 @@ enum cmd_frame_type { COMMON_DEV_CONFIG = 0x28, RADIO_PARAMS_UPDATE = 0x29, WOWLAN_CONFIG_PARAMS = 0x2B, + FEATURES_ENABLE = 0x33, WOWLAN_WAKEUP_REASON = 0xc5 }; @@ -351,6 +352,15 @@ struct rsi_boot_params { struct bootup_params bootup_params; } __packed; +struct rsi_boot_params_9116 { + struct rsi_cmd_desc_dword0 desc_dword0; + struct rsi_cmd_desc_dword1 desc_dword1; + struct rsi_cmd_desc_dword2 desc_dword2; + __le16 reserved; + __le16 umac_clk; + struct bootup_params_9116 bootup_params; +} __packed; + struct rsi_peer_notify { struct rsi_cmd_desc desc; u8 mac_addr[6]; @@ -654,6 +664,22 @@ struct rsi_bgscan_probe { __le16 probe_req_length; } __packed; +#define RSI_DUTY_CYCLING BIT(0) +#define RSI_END_OF_FRAME BIT(1) +#define RSI_SIFS_TX_ENABLE BIT(2) +#define RSI_DPD BIT(3) +struct rsi_wlan_9116_features { + struct rsi_cmd_desc desc; + u8 pll_mode; + u8 rf_type; + u8 wireless_mode; + u8 enable_ppe; + u8 afe_type; + u8 reserved1; + __le16 reserved2; + __le32 feature_enable; +}; + static inline u32 rsi_get_queueno(u8 *addr, u16 offset) { return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12; diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index 66dcd2ec9051..c5cfb6238f73 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -28,8 +28,9 @@ #include <linux/mmc/sdio_ids.h> #include "rsi_main.h" -#define RSI_SDIO_VID_9113 0x041B +#define RSI_SDIO_VENDOR_ID 0x041B #define RSI_SDIO_PID_9113 0x9330 +#define RSI_SDIO_PID_9116 0x9116 enum sdio_interrupt_type { BUFFER_FULL = 0x0, @@ -91,7 +92,7 @@ enum sdio_interrupt_type { #define TA_SOFT_RST_SET BIT(0) #define TA_PC_ZERO 0 #define TA_HOLD_THREAD_VALUE 0xF -#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF) +#define TA_RELEASE_THREAD_VALUE 0xF #define TA_BASE_ADDR 0x2200 #define MISC_CFG_BASE_ADDR 0x4105 diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h index 5b2eddd1a2ee..8702f434b569 100644 --- a/drivers/net/wireless/rsi/rsi_usb.h +++ b/drivers/net/wireless/rsi/rsi_usb.h @@ -22,8 +22,9 @@ #include "rsi_main.h" #include "rsi_common.h" -#define RSI_USB_VID_9113 0x1618 +#define RSI_USB_VENDOR_ID 0x1618 #define RSI_USB_PID_9113 0x9113 +#define RSI_USB_PID_9116 0x9116 #define USB_INTERNAL_REG_1 0x25000 #define RSI_USB_READY_MAGIC_NUM 0xab |