blob: 544f638ed3efb94a6639e214da9bc10f2c6aee23 [file] [log] [blame]
/******************************************************************************
*
* Copyright(c) 2016 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "halmac_88xx_cfg.h"
static enum halmac_ret_status
halmac_dump_efuse_fw_88xx(struct halmac_adapter *halmac_adapter);
static enum halmac_ret_status
halmac_dump_efuse_drv_88xx(struct halmac_adapter *halmac_adapter);
static enum halmac_ret_status
halmac_update_eeprom_mask_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated);
static enum halmac_ret_status
halmac_check_efuse_enough_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated);
static enum halmac_ret_status
halmac_program_efuse_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated);
static enum halmac_ret_status
halmac_pwr_sub_seq_parer_88xx(struct halmac_adapter *halmac_adapter, u8 cut,
u8 fab, u8 intf,
struct halmac_wl_pwr_cfg_ *pwr_sub_seq_cfg);
static enum halmac_ret_status
halmac_parse_c2h_debug_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size);
static enum halmac_ret_status
halmac_parse_scan_status_rpt_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_psd_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size);
static enum halmac_ret_status
halmac_parse_efuse_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size);
static enum halmac_ret_status
halmac_enqueue_para_buff_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_phy_parameter_info *para_info,
u8 *curr_buff_wptr, bool *end_cmd);
static enum halmac_ret_status
halmac_parse_h2c_ack_phy_efuse_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_cfg_para_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_gen_cfg_para_h2c_88xx(struct halmac_adapter *halmac_adapter,
u8 *h2c_buff);
static enum halmac_ret_status
halmac_parse_h2c_ack_update_packet_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_update_datapack_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_run_datapack_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_channel_switch_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_iqk_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
static enum halmac_ret_status
halmac_parse_h2c_ack_power_tracking_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size);
void halmac_init_offload_feature_state_machine_88xx(
struct halmac_adapter *halmac_adapter)
{
struct halmac_state *state = &halmac_adapter->halmac_state;
state->efuse_state_set.efuse_cmd_construct_state =
HALMAC_EFUSE_CMD_CONSTRUCT_IDLE;
state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->efuse_state_set.seq_num = halmac_adapter->h2c_packet_seq;
state->cfg_para_state_set.cfg_para_cmd_construct_state =
HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE;
state->cfg_para_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->cfg_para_state_set.seq_num = halmac_adapter->h2c_packet_seq;
state->scan_state_set.scan_cmd_construct_state =
HALMAC_SCAN_CMD_CONSTRUCT_IDLE;
state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->scan_state_set.seq_num = halmac_adapter->h2c_packet_seq;
state->update_packet_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->update_packet_set.seq_num = halmac_adapter->h2c_packet_seq;
state->iqk_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->iqk_set.seq_num = halmac_adapter->h2c_packet_seq;
state->power_tracking_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->power_tracking_set.seq_num = halmac_adapter->h2c_packet_seq;
state->psd_set.process_status = HALMAC_CMD_PROCESS_IDLE;
state->psd_set.seq_num = halmac_adapter->h2c_packet_seq;
state->psd_set.data_size = 0;
state->psd_set.segment_size = 0;
state->psd_set.data = NULL;
}
enum halmac_ret_status
halmac_dump_efuse_88xx(struct halmac_adapter *halmac_adapter,
enum halmac_efuse_read_cfg cfg)
{
u32 chk_h2c_init;
void *driver_adapter = NULL;
struct halmac_api *halmac_api =
(struct halmac_api *)halmac_adapter->halmac_api;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
enum halmac_cmd_process_status *process_status =
&halmac_adapter->halmac_state.efuse_state_set.process_status;
driver_adapter = halmac_adapter->driver_adapter;
*process_status = HALMAC_CMD_PROCESS_SENDING;
if (halmac_transition_efuse_state_88xx(
halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_H2C_SENT) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
if (cfg == HALMAC_EFUSE_R_AUTO) {
chk_h2c_init = HALMAC_REG_READ_32(halmac_adapter,
REG_H2C_PKT_READADDR);
if (halmac_adapter->halmac_state.dlfw_state ==
HALMAC_DLFW_NONE ||
chk_h2c_init == 0)
status = halmac_dump_efuse_drv_88xx(halmac_adapter);
else
status = halmac_dump_efuse_fw_88xx(halmac_adapter);
} else if (cfg == HALMAC_EFUSE_R_FW) {
status = halmac_dump_efuse_fw_88xx(halmac_adapter);
} else {
status = halmac_dump_efuse_drv_88xx(halmac_adapter);
}
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_read_efuse error = %x\n", status);
return status;
}
return status;
}
enum halmac_ret_status
halmac_func_read_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset,
u32 size, u8 *efuse_map)
{
void *driver_adapter = NULL;
driver_adapter = halmac_adapter->driver_adapter;
if (!efuse_map) {
pr_err("Malloc for dump efuse map error\n");
return HALMAC_RET_NULL_POINTER;
}
if (halmac_adapter->hal_efuse_map_valid)
memcpy(efuse_map, halmac_adapter->hal_efuse_map + offset, size);
else if (halmac_read_hw_efuse_88xx(halmac_adapter, offset, size,
efuse_map) != HALMAC_RET_SUCCESS)
return HALMAC_RET_EFUSE_R_FAIL;
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_read_hw_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset,
u32 size, u8 *efuse_map)
{
u8 value8;
u32 value32;
u32 address;
u32 tmp32, counter;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
/* Read efuse no need 2.5V LDO */
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3);
if (value8 & BIT(7))
HALMAC_REG_WRITE_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3,
(u8)(value8 & ~(BIT(7))));
value32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL);
for (address = offset; address < offset + size; address++) {
value32 = value32 &
~((BIT_MASK_EF_DATA) |
(BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR));
value32 = value32 |
((address & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR);
HALMAC_REG_WRITE_32(halmac_adapter, REG_EFUSE_CTRL,
value32 & (~BIT_EF_FLAG));
counter = 1000000;
do {
udelay(1);
tmp32 = HALMAC_REG_READ_32(halmac_adapter,
REG_EFUSE_CTRL);
counter--;
if (counter == 0) {
pr_err("HALMAC_RET_EFUSE_R_FAIL\n");
return HALMAC_RET_EFUSE_R_FAIL;
}
} while ((tmp32 & BIT_EF_FLAG) == 0);
*(efuse_map + address - offset) =
(u8)(tmp32 & BIT_MASK_EF_DATA);
}
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_dump_efuse_drv_88xx(struct halmac_adapter *halmac_adapter)
{
u8 *efuse_map = NULL;
u32 efuse_size;
void *driver_adapter = NULL;
driver_adapter = halmac_adapter->driver_adapter;
efuse_size = halmac_adapter->hw_config_info.efuse_size;
if (!halmac_adapter->hal_efuse_map) {
halmac_adapter->hal_efuse_map = kzalloc(efuse_size, GFP_KERNEL);
if (!halmac_adapter->hal_efuse_map) {
pr_err("[ERR]halmac allocate efuse map Fail!!\n");
return HALMAC_RET_MALLOC_FAIL;
}
}
efuse_map = kzalloc(efuse_size, GFP_KERNEL);
if (!efuse_map) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
if (halmac_read_hw_efuse_88xx(halmac_adapter, 0, efuse_size,
efuse_map) != HALMAC_RET_SUCCESS) {
kfree(efuse_map);
return HALMAC_RET_EFUSE_R_FAIL;
}
spin_lock(&halmac_adapter->efuse_lock);
memcpy(halmac_adapter->hal_efuse_map, efuse_map, efuse_size);
halmac_adapter->hal_efuse_map_valid = true;
spin_unlock(&halmac_adapter->efuse_lock);
kfree(efuse_map);
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_dump_efuse_fw_88xx(struct halmac_adapter *halmac_adapter)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
h2c_header_info.sub_cmd_id = SUB_CMD_ID_DUMP_PHYSICAL_EFUSE;
h2c_header_info.content_size = 0;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
halmac_adapter->halmac_state.efuse_state_set.seq_num = h2c_seq_mum;
if (!halmac_adapter->hal_efuse_map) {
halmac_adapter->hal_efuse_map = kzalloc(
halmac_adapter->hw_config_info.efuse_size, GFP_KERNEL);
if (!halmac_adapter->hal_efuse_map) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
}
if (!halmac_adapter->hal_efuse_map_valid) {
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX,
true);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_read_efuse_fw Fail = %x!!\n", status);
return status;
}
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_func_write_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset,
u8 value)
{
const u8 wite_protect_code = 0x69;
u32 value32, tmp32, counter;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
spin_lock(&halmac_adapter->efuse_lock);
halmac_adapter->hal_efuse_map_valid = false;
spin_unlock(&halmac_adapter->efuse_lock);
HALMAC_REG_WRITE_8(halmac_adapter, REG_PMC_DBG_CTRL2 + 3,
wite_protect_code);
/* Enable 2.5V LDO */
HALMAC_REG_WRITE_8(
halmac_adapter, REG_LDO_EFUSE_CTRL + 3,
(u8)(HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3) |
BIT(7)));
value32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL);
value32 =
value32 &
~((BIT_MASK_EF_DATA) | (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR));
value32 = value32 | ((offset & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR) |
(value & BIT_MASK_EF_DATA);
HALMAC_REG_WRITE_32(halmac_adapter, REG_EFUSE_CTRL,
value32 | BIT_EF_FLAG);
counter = 1000000;
do {
udelay(1);
tmp32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL);
counter--;
if (counter == 0) {
pr_err("halmac_write_efuse Fail !!\n");
return HALMAC_RET_EFUSE_W_FAIL;
}
} while ((tmp32 & BIT_EF_FLAG) == BIT_EF_FLAG);
HALMAC_REG_WRITE_8(halmac_adapter, REG_PMC_DBG_CTRL2 + 3, 0x00);
/* Disable 2.5V LDO */
HALMAC_REG_WRITE_8(
halmac_adapter, REG_LDO_EFUSE_CTRL + 3,
(u8)(HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3) &
~(BIT(7))));
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_func_switch_efuse_bank_88xx(struct halmac_adapter *halmac_adapter,
enum halmac_efuse_bank efuse_bank)
{
u8 reg_value;
struct halmac_api *halmac_api;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
if (halmac_transition_efuse_state_88xx(
halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_BUSY) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
reg_value = HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1);
if (efuse_bank == (reg_value & (BIT(0) | BIT(1))))
return HALMAC_RET_SUCCESS;
reg_value &= ~(BIT(0) | BIT(1));
reg_value |= efuse_bank;
HALMAC_REG_WRITE_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1, reg_value);
if ((HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1) &
(BIT(0) | BIT(1))) != efuse_bank)
return HALMAC_RET_SWITCH_EFUSE_BANK_FAIL;
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_eeprom_parser_88xx(struct halmac_adapter *halmac_adapter,
u8 *physical_efuse_map, u8 *logical_efuse_map)
{
u8 j;
u8 value8;
u8 block_index;
u8 valid_word_enable, word_enable;
u8 efuse_read_header, efuse_read_header2 = 0;
u32 eeprom_index;
u32 efuse_index = 0;
u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
void *driver_adapter = NULL;
driver_adapter = halmac_adapter->driver_adapter;
memset(logical_efuse_map, 0xFF, eeprom_size);
do {
value8 = *(physical_efuse_map + efuse_index);
efuse_read_header = value8;
if ((efuse_read_header & 0x1f) == 0x0f) {
efuse_index++;
value8 = *(physical_efuse_map + efuse_index);
efuse_read_header2 = value8;
block_index = ((efuse_read_header2 & 0xF0) >> 1) |
((efuse_read_header >> 5) & 0x07);
word_enable = efuse_read_header2 & 0x0F;
} else {
block_index = (efuse_read_header & 0xF0) >> 4;
word_enable = efuse_read_header & 0x0F;
}
if (efuse_read_header == 0xff)
break;
efuse_index++;
if (efuse_index >= halmac_adapter->hw_config_info.efuse_size -
HALMAC_PROTECTED_EFUSE_SIZE_88XX - 1)
return HALMAC_RET_EEPROM_PARSING_FAIL;
for (j = 0; j < 4; j++) {
valid_word_enable =
(u8)((~(word_enable >> j)) & BIT(0));
if (valid_word_enable != 1)
continue;
eeprom_index = (block_index << 3) + (j << 1);
if ((eeprom_index + 1) > eeprom_size) {
pr_err("Error: EEPROM addr exceeds eeprom_size:0x%X, at eFuse 0x%X\n",
eeprom_size, efuse_index - 1);
if ((efuse_read_header & 0x1f) == 0x0f)
pr_err("Error: EEPROM header: 0x%X, 0x%X,\n",
efuse_read_header,
efuse_read_header2);
else
pr_err("Error: EEPROM header: 0x%X,\n",
efuse_read_header);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
value8 = *(physical_efuse_map + efuse_index);
*(logical_efuse_map + eeprom_index) = value8;
eeprom_index++;
efuse_index++;
if (efuse_index >
halmac_adapter->hw_config_info.efuse_size -
HALMAC_PROTECTED_EFUSE_SIZE_88XX - 1)
return HALMAC_RET_EEPROM_PARSING_FAIL;
value8 = *(physical_efuse_map + efuse_index);
*(logical_efuse_map + eeprom_index) = value8;
efuse_index++;
if (efuse_index >
halmac_adapter->hw_config_info.efuse_size -
HALMAC_PROTECTED_EFUSE_SIZE_88XX)
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
} while (1);
halmac_adapter->efuse_end = efuse_index;
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_read_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter,
u8 *map)
{
u8 *efuse_map = NULL;
u32 efuse_size;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
efuse_size = halmac_adapter->hw_config_info.efuse_size;
if (!halmac_adapter->hal_efuse_map_valid) {
efuse_map = kzalloc(efuse_size, GFP_KERNEL);
if (!efuse_map) {
pr_err("[ERR]halmac allocate local efuse map Fail!!\n");
return HALMAC_RET_MALLOC_FAIL;
}
status = halmac_func_read_efuse_88xx(halmac_adapter, 0,
efuse_size, efuse_map);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_read_efuse error = %x\n", status);
kfree(efuse_map);
return status;
}
if (!halmac_adapter->hal_efuse_map) {
halmac_adapter->hal_efuse_map =
kzalloc(efuse_size, GFP_KERNEL);
if (!halmac_adapter->hal_efuse_map) {
pr_err("[ERR]halmac allocate efuse map Fail!!\n");
kfree(efuse_map);
return HALMAC_RET_MALLOC_FAIL;
}
}
spin_lock(&halmac_adapter->efuse_lock);
memcpy(halmac_adapter->hal_efuse_map, efuse_map, efuse_size);
halmac_adapter->hal_efuse_map_valid = true;
spin_unlock(&halmac_adapter->efuse_lock);
kfree(efuse_map);
}
if (halmac_eeprom_parser_88xx(halmac_adapter,
halmac_adapter->hal_efuse_map,
map) != HALMAC_RET_SUCCESS)
return HALMAC_RET_EEPROM_PARSING_FAIL;
return status;
}
enum halmac_ret_status
halmac_func_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter,
u32 offset, u8 value)
{
u8 pg_efuse_byte1, pg_efuse_byte2;
u8 pg_block, pg_block_index;
u8 pg_efuse_header, pg_efuse_header2;
u8 *eeprom_map = NULL;
u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
u32 efuse_end, pg_efuse_num;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
eeprom_map = kzalloc(eeprom_size, GFP_KERNEL);
if (!eeprom_map) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
memset(eeprom_map, 0xFF, eeprom_size);
status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_read_logical_efuse_map_88xx error = %x\n",
status);
kfree(eeprom_map);
return status;
}
if (*(eeprom_map + offset) != value) {
efuse_end = halmac_adapter->efuse_end;
pg_block = (u8)(offset >> 3);
pg_block_index = (u8)((offset & (8 - 1)) >> 1);
if (offset > 0x7f) {
pg_efuse_header =
(((pg_block & 0x07) << 5) & 0xE0) | 0x0F;
pg_efuse_header2 =
(u8)(((pg_block & 0x78) << 1) +
((0x1 << pg_block_index) ^ 0x0F));
} else {
pg_efuse_header =
(u8)((pg_block << 4) +
((0x01 << pg_block_index) ^ 0x0F));
}
if ((offset & 1) == 0) {
pg_efuse_byte1 = value;
pg_efuse_byte2 = *(eeprom_map + offset + 1);
} else {
pg_efuse_byte1 = *(eeprom_map + offset - 1);
pg_efuse_byte2 = value;
}
if (offset > 0x7f) {
pg_efuse_num = 4;
if (halmac_adapter->hw_config_info.efuse_size <=
(pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX +
halmac_adapter->efuse_end)) {
kfree(eeprom_map);
return HALMAC_RET_EFUSE_NOT_ENOUGH;
}
halmac_func_write_efuse_88xx(halmac_adapter, efuse_end,
pg_efuse_header);
halmac_func_write_efuse_88xx(halmac_adapter,
efuse_end + 1,
pg_efuse_header2);
halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 2, pg_efuse_byte1);
status = halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 3, pg_efuse_byte2);
} else {
pg_efuse_num = 3;
if (halmac_adapter->hw_config_info.efuse_size <=
(pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX +
halmac_adapter->efuse_end)) {
kfree(eeprom_map);
return HALMAC_RET_EFUSE_NOT_ENOUGH;
}
halmac_func_write_efuse_88xx(halmac_adapter, efuse_end,
pg_efuse_header);
halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 1, pg_efuse_byte1);
status = halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 2, pg_efuse_byte2);
}
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_write_logical_efuse error = %x\n",
status);
kfree(eeprom_map);
return status;
}
}
kfree(eeprom_map);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_func_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
enum halmac_efuse_read_cfg cfg)
{
u8 *eeprom_mask_updated = NULL;
u32 eeprom_mask_size = halmac_adapter->hw_config_info.eeprom_size >> 4;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
eeprom_mask_updated = kzalloc(eeprom_mask_size, GFP_KERNEL);
if (!eeprom_mask_updated) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
status = halmac_update_eeprom_mask_88xx(halmac_adapter, pg_efuse_info,
eeprom_mask_updated);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_update_eeprom_mask_88xx error = %x\n",
status);
kfree(eeprom_mask_updated);
return status;
}
status = halmac_check_efuse_enough_88xx(halmac_adapter, pg_efuse_info,
eeprom_mask_updated);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_check_efuse_enough_88xx error = %x\n",
status);
kfree(eeprom_mask_updated);
return status;
}
status = halmac_program_efuse_88xx(halmac_adapter, pg_efuse_info,
eeprom_mask_updated);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[ERR]halmac_program_efuse_88xx error = %x\n", status);
kfree(eeprom_mask_updated);
return status;
}
kfree(eeprom_mask_updated);
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_update_eeprom_mask_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated)
{
u8 *eeprom_map = NULL;
u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
u8 *eeprom_map_pg, *eeprom_mask;
u16 i, j;
u16 map_byte_offset, mask_byte_offset;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
void *driver_adapter = NULL;
driver_adapter = halmac_adapter->driver_adapter;
eeprom_map = kzalloc(eeprom_size, GFP_KERNEL);
if (!eeprom_map) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
memset(eeprom_map, 0xFF, eeprom_size);
memset(eeprom_mask_updated, 0x00, pg_efuse_info->efuse_mask_size);
status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map);
if (status != HALMAC_RET_SUCCESS) {
kfree(eeprom_map);
return status;
}
eeprom_map_pg = pg_efuse_info->efuse_map;
eeprom_mask = pg_efuse_info->efuse_mask;
for (i = 0; i < pg_efuse_info->efuse_mask_size; i++)
*(eeprom_mask_updated + i) = *(eeprom_mask + i);
for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 16) {
for (j = 0; j < 16; j = j + 2) {
map_byte_offset = i + j;
mask_byte_offset = i >> 4;
if (*(eeprom_map_pg + map_byte_offset) ==
*(eeprom_map + map_byte_offset)) {
if (*(eeprom_map_pg + map_byte_offset + 1) ==
*(eeprom_map + map_byte_offset + 1)) {
switch (j) {
case 0:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(4) ^ 0xFF);
break;
case 2:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(5) ^ 0xFF);
break;
case 4:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(6) ^ 0xFF);
break;
case 6:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(7) ^ 0xFF);
break;
case 8:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(0) ^ 0xFF);
break;
case 10:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(1) ^ 0xFF);
break;
case 12:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(2) ^ 0xFF);
break;
case 14:
*(eeprom_mask_updated +
mask_byte_offset) =
*(eeprom_mask_updated +
mask_byte_offset) &
(BIT(3) ^ 0xFF);
break;
default:
break;
}
}
}
}
}
kfree(eeprom_map);
return status;
}
static enum halmac_ret_status
halmac_check_efuse_enough_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated)
{
u8 pre_word_enb, word_enb;
u8 pg_efuse_header, pg_efuse_header2;
u8 pg_block;
u16 i, j;
u32 efuse_end;
u32 tmp_eeprom_offset, pg_efuse_num = 0;
efuse_end = halmac_adapter->efuse_end;
for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 8) {
tmp_eeprom_offset = i;
if ((tmp_eeprom_offset & 7) > 0) {
pre_word_enb =
(*(eeprom_mask_updated + (i >> 4)) & 0x0F);
word_enb = pre_word_enb ^ 0x0F;
} else {
pre_word_enb = (*(eeprom_mask_updated + (i >> 4)) >> 4);
word_enb = pre_word_enb ^ 0x0F;
}
pg_block = (u8)(tmp_eeprom_offset >> 3);
if (pre_word_enb > 0) {
if (tmp_eeprom_offset > 0x7f) {
pg_efuse_header =
(((pg_block & 0x07) << 5) & 0xE0) |
0x0F;
pg_efuse_header2 = (u8)(
((pg_block & 0x78) << 1) + word_enb);
} else {
pg_efuse_header =
(u8)((pg_block << 4) + word_enb);
}
if (tmp_eeprom_offset > 0x7f) {
pg_efuse_num++;
pg_efuse_num++;
efuse_end = efuse_end + 2;
for (j = 0; j < 4; j++) {
if (((pre_word_enb >> j) & 0x1) > 0) {
pg_efuse_num++;
pg_efuse_num++;
efuse_end = efuse_end + 2;
}
}
} else {
pg_efuse_num++;
efuse_end = efuse_end + 1;
for (j = 0; j < 4; j++) {
if (((pre_word_enb >> j) & 0x1) > 0) {
pg_efuse_num++;
pg_efuse_num++;
efuse_end = efuse_end + 2;
}
}
}
}
}
if (halmac_adapter->hw_config_info.efuse_size <=
(pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX +
halmac_adapter->efuse_end))
return HALMAC_RET_EFUSE_NOT_ENOUGH;
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_program_efuse_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_pg_efuse_info *pg_efuse_info,
u8 *eeprom_mask_updated)
{
u8 pre_word_enb, word_enb;
u8 pg_efuse_header, pg_efuse_header2;
u8 pg_block;
u16 i, j;
u32 efuse_end;
u32 tmp_eeprom_offset;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
efuse_end = halmac_adapter->efuse_end;
for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 8) {
tmp_eeprom_offset = i;
if (((tmp_eeprom_offset >> 3) & 1) > 0) {
pre_word_enb =
(*(eeprom_mask_updated + (i >> 4)) & 0x0F);
word_enb = pre_word_enb ^ 0x0F;
} else {
pre_word_enb = (*(eeprom_mask_updated + (i >> 4)) >> 4);
word_enb = pre_word_enb ^ 0x0F;
}
pg_block = (u8)(tmp_eeprom_offset >> 3);
if (pre_word_enb <= 0)
continue;
if (tmp_eeprom_offset > 0x7f) {
pg_efuse_header =
(((pg_block & 0x07) << 5) & 0xE0) | 0x0F;
pg_efuse_header2 =
(u8)(((pg_block & 0x78) << 1) + word_enb);
} else {
pg_efuse_header = (u8)((pg_block << 4) + word_enb);
}
if (tmp_eeprom_offset > 0x7f) {
halmac_func_write_efuse_88xx(halmac_adapter, efuse_end,
pg_efuse_header);
status = halmac_func_write_efuse_88xx(halmac_adapter,
efuse_end + 1,
pg_efuse_header2);
efuse_end = efuse_end + 2;
for (j = 0; j < 4; j++) {
if (((pre_word_enb >> j) & 0x1) > 0) {
halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end,
*(pg_efuse_info->efuse_map +
tmp_eeprom_offset +
(j << 1)));
status = halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 1,
*(pg_efuse_info->efuse_map +
tmp_eeprom_offset + (j << 1) +
1));
efuse_end = efuse_end + 2;
}
}
} else {
status = halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end, pg_efuse_header);
efuse_end = efuse_end + 1;
for (j = 0; j < 4; j++) {
if (((pre_word_enb >> j) & 0x1) > 0) {
halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end,
*(pg_efuse_info->efuse_map +
tmp_eeprom_offset +
(j << 1)));
status = halmac_func_write_efuse_88xx(
halmac_adapter, efuse_end + 1,
*(pg_efuse_info->efuse_map +
tmp_eeprom_offset + (j << 1) +
1));
efuse_end = efuse_end + 2;
}
}
}
}
return status;
}
enum halmac_ret_status
halmac_dlfw_to_mem_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code,
u32 dest, u32 code_size)
{
u8 *code_ptr;
u8 first_part;
u32 mem_offset;
u32 pkt_size_tmp, send_pkt_size;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
code_ptr = ram_code;
mem_offset = 0;
first_part = 1;
pkt_size_tmp = code_size;
HALMAC_REG_WRITE_32(
halmac_adapter, REG_DDMA_CH0CTRL,
HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) |
BIT_DDMACH0_RESET_CHKSUM_STS);
while (pkt_size_tmp != 0) {
if (pkt_size_tmp >= halmac_adapter->max_download_size)
send_pkt_size = halmac_adapter->max_download_size;
else
send_pkt_size = pkt_size_tmp;
if (halmac_send_fwpkt_88xx(
halmac_adapter, code_ptr + mem_offset,
send_pkt_size) != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_fwpkt_88xx fail!!");
return HALMAC_RET_DLFW_FAIL;
}
if (halmac_iddma_dlfw_88xx(
halmac_adapter,
HALMAC_OCPBASE_TXBUF_88XX +
halmac_adapter->hw_config_info.txdesc_size,
dest + mem_offset, send_pkt_size,
first_part) != HALMAC_RET_SUCCESS) {
pr_err("halmac_iddma_dlfw_88xx fail!!");
return HALMAC_RET_DLFW_FAIL;
}
first_part = 0;
mem_offset += send_pkt_size;
pkt_size_tmp -= send_pkt_size;
}
if (halmac_check_fw_chksum_88xx(halmac_adapter, dest) !=
HALMAC_RET_SUCCESS) {
pr_err("halmac_check_fw_chksum_88xx fail!!");
return HALMAC_RET_DLFW_FAIL;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_fwpkt_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code,
u32 code_size)
{
if (halmac_download_rsvd_page_88xx(halmac_adapter, ram_code,
code_size) != HALMAC_RET_SUCCESS) {
pr_err("PLATFORM_SEND_RSVD_PAGE 0 error!!\n");
return HALMAC_RET_DL_RSVD_PAGE_FAIL;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_iddma_dlfw_88xx(struct halmac_adapter *halmac_adapter, u32 source,
u32 dest, u32 length, u8 first)
{
u32 counter;
u32 ch0_control = (u32)(BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN);
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
counter = HALMC_DDMA_POLLING_COUNT;
while (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) &
BIT_DDMACH0_OWN) {
counter--;
if (counter == 0) {
pr_err("%s error-1!!\n", __func__);
return HALMAC_RET_DDMA_FAIL;
}
}
ch0_control |= (length & BIT_MASK_DDMACH0_DLEN);
if (first == 0)
ch0_control |= BIT_DDMACH0_CHKSUM_CONT;
HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0SA, source);
HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0DA, dest);
HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0CTRL, ch0_control);
counter = HALMC_DDMA_POLLING_COUNT;
while (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) &
BIT_DDMACH0_OWN) {
counter--;
if (counter == 0) {
pr_err("%s error-2!!\n", __func__);
return HALMAC_RET_DDMA_FAIL;
}
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_check_fw_chksum_88xx(struct halmac_adapter *halmac_adapter,
u32 memory_address)
{
u8 mcu_fw_ctrl;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
enum halmac_ret_status status;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
mcu_fw_ctrl = HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL);
if (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) &
BIT_DDMACH0_CHKSUM_STS) {
if (memory_address < HALMAC_OCPBASE_DMEM_88XX) {
mcu_fw_ctrl |= BIT_IMEM_DW_OK;
HALMAC_REG_WRITE_8(
halmac_adapter, REG_MCUFW_CTRL,
(u8)(mcu_fw_ctrl & ~(BIT_IMEM_CHKSUM_OK)));
} else {
mcu_fw_ctrl |= BIT_DMEM_DW_OK;
HALMAC_REG_WRITE_8(
halmac_adapter, REG_MCUFW_CTRL,
(u8)(mcu_fw_ctrl & ~(BIT_DMEM_CHKSUM_OK)));
}
pr_err("%s error!!\n", __func__);
status = HALMAC_RET_FW_CHECKSUM_FAIL;
} else {
if (memory_address < HALMAC_OCPBASE_DMEM_88XX) {
mcu_fw_ctrl |= BIT_IMEM_DW_OK;
HALMAC_REG_WRITE_8(
halmac_adapter, REG_MCUFW_CTRL,
(u8)(mcu_fw_ctrl | BIT_IMEM_CHKSUM_OK));
} else {
mcu_fw_ctrl |= BIT_DMEM_DW_OK;
HALMAC_REG_WRITE_8(
halmac_adapter, REG_MCUFW_CTRL,
(u8)(mcu_fw_ctrl | BIT_DMEM_CHKSUM_OK));
}
status = HALMAC_RET_SUCCESS;
}
return status;
}
enum halmac_ret_status
halmac_dlfw_end_flow_88xx(struct halmac_adapter *halmac_adapter)
{
u8 value8;
u32 counter;
void *driver_adapter = halmac_adapter->driver_adapter;
struct halmac_api *halmac_api =
(struct halmac_api *)halmac_adapter->halmac_api;
HALMAC_REG_WRITE_32(halmac_adapter, REG_TXDMA_STATUS, BIT(2));
/* Check IMEM & DMEM checksum is OK or not */
if ((HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) & 0x50) == 0x50)
HALMAC_REG_WRITE_16(halmac_adapter, REG_MCUFW_CTRL,
(u16)(HALMAC_REG_READ_16(halmac_adapter,
REG_MCUFW_CTRL) |
BIT_FW_DW_RDY));
else
return HALMAC_RET_DLFW_FAIL;
HALMAC_REG_WRITE_8(
halmac_adapter, REG_MCUFW_CTRL,
(u8)(HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) &
~(BIT(0))));
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RSV_CTRL + 1);
value8 = (u8)(value8 | BIT(0));
HALMAC_REG_WRITE_8(halmac_adapter, REG_RSV_CTRL + 1, value8);
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN + 1);
value8 = (u8)(value8 | BIT(2));
HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1,
value8); /* Release MCU reset */
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
"Download Finish, Reset CPU\n");
counter = 10000;
while (HALMAC_REG_READ_16(halmac_adapter, REG_MCUFW_CTRL) != 0xC078) {
if (counter == 0) {
pr_err("Check 0x80 = 0xC078 fail\n");
if ((HALMAC_REG_READ_32(halmac_adapter, REG_FW_DBG7) &
0xFFFFFF00) == 0xFAAAAA00)
pr_err("Key fail\n");
return HALMAC_RET_DLFW_FAIL;
}
counter--;
usleep_range(50, 60);
}
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
"Check 0x80 = 0xC078 counter = %d\n", counter);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_free_dl_fw_end_flow_88xx(struct halmac_adapter *halmac_adapter)
{
u32 counter;
struct halmac_api *halmac_api =
(struct halmac_api *)halmac_adapter->halmac_api;
counter = 100;
while (HALMAC_REG_READ_8(halmac_adapter, REG_HMETFR + 3) != 0) {
counter--;
if (counter == 0) {
pr_err("[ERR]0x1CF != 0\n");
return HALMAC_RET_DLFW_FAIL;
}
usleep_range(50, 60);
}
HALMAC_REG_WRITE_8(halmac_adapter, REG_HMETFR + 3,
ID_INFORM_DLEMEM_RDY);
counter = 10000;
while (HALMAC_REG_READ_8(halmac_adapter, REG_C2HEVT_3 + 3) !=
ID_INFORM_DLEMEM_RDY) {
counter--;
if (counter == 0) {
pr_err("[ERR]0x1AF != 0x80\n");
return HALMAC_RET_DLFW_FAIL;
}
usleep_range(50, 60);
}
HALMAC_REG_WRITE_8(halmac_adapter, REG_C2HEVT_3 + 3, 0);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_pwr_seq_parser_88xx(struct halmac_adapter *halmac_adapter, u8 cut,
u8 fab, u8 intf,
struct halmac_wl_pwr_cfg_ **pp_pwr_seq_cfg)
{
u32 seq_idx = 0;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
struct halmac_wl_pwr_cfg_ *seq_cmd;
driver_adapter = halmac_adapter->driver_adapter;
do {
seq_cmd = pp_pwr_seq_cfg[seq_idx];
if (!seq_cmd)
break;
status = halmac_pwr_sub_seq_parer_88xx(halmac_adapter, cut, fab,
intf, seq_cmd);
if (status != HALMAC_RET_SUCCESS) {
pr_err("[Err]pwr sub seq parser fail, status = 0x%X!\n",
status);
return status;
}
seq_idx++;
} while (1);
return status;
}
static enum halmac_ret_status
halmac_pwr_sub_seq_parer_do_cmd_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_wl_pwr_cfg_ *sub_seq_cmd,
bool *reti)
{
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
u8 value, flag;
u8 polling_bit;
u32 polling_count;
static u32 poll_to_static;
u32 offset;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
*reti = true;
switch (sub_seq_cmd->cmd) {
case HALMAC_PWR_CMD_WRITE:
if (sub_seq_cmd->base == HALMAC_PWR_BASEADDR_SDIO)
offset = sub_seq_cmd->offset | SDIO_LOCAL_OFFSET;
else
offset = sub_seq_cmd->offset;
value = HALMAC_REG_READ_8(halmac_adapter, offset);
value = (u8)(value & (u8)(~(sub_seq_cmd->msk)));
value = (u8)(value |
(u8)(sub_seq_cmd->value & sub_seq_cmd->msk));
HALMAC_REG_WRITE_8(halmac_adapter, offset, value);
break;
case HALMAC_PWR_CMD_POLLING:
polling_bit = 0;
polling_count = HALMAC_POLLING_READY_TIMEOUT_COUNT;
flag = 0;
if (sub_seq_cmd->base == HALMAC_PWR_BASEADDR_SDIO)
offset = sub_seq_cmd->offset | SDIO_LOCAL_OFFSET;
else
offset = sub_seq_cmd->offset;
do {
polling_count--;
value = HALMAC_REG_READ_8(halmac_adapter, offset);
value = (u8)(value & sub_seq_cmd->msk);
if (value == (sub_seq_cmd->value & sub_seq_cmd->msk)) {
polling_bit = 1;
continue;
}
if (polling_count != 0) {
usleep_range(50, 60);
continue;
}
if (halmac_adapter->halmac_interface ==
HALMAC_INTERFACE_PCIE &&
flag == 0) {
/* For PCIE + USB package poll power bit
* timeout issue
*/
poll_to_static++;
HALMAC_RT_TRACE(
driver_adapter, HALMAC_MSG_PWR,
DBG_WARNING,
"[WARN]PCIE polling timeout : %d!!\n",
poll_to_static);
HALMAC_REG_WRITE_8(
halmac_adapter, REG_SYS_PW_CTRL,
HALMAC_REG_READ_8(halmac_adapter,
REG_SYS_PW_CTRL) |
BIT(3));
HALMAC_REG_WRITE_8(
halmac_adapter, REG_SYS_PW_CTRL,
HALMAC_REG_READ_8(halmac_adapter,
REG_SYS_PW_CTRL) &
~BIT(3));
polling_bit = 0;
polling_count =
HALMAC_POLLING_READY_TIMEOUT_COUNT;
flag = 1;
} else {
pr_err("[ERR]Pwr cmd polling timeout!!\n");
pr_err("[ERR]Pwr cmd offset : %X!!\n",
sub_seq_cmd->offset);
pr_err("[ERR]Pwr cmd value : %X!!\n",
sub_seq_cmd->value);
pr_err("[ERR]Pwr cmd msk : %X!!\n",
sub_seq_cmd->msk);
pr_err("[ERR]Read offset = %X value = %X!!\n",
offset, value);
return HALMAC_RET_PWRSEQ_POLLING_FAIL;
}
} while (!polling_bit);
break;
case HALMAC_PWR_CMD_DELAY:
if (sub_seq_cmd->value == HALMAC_PWRSEQ_DELAY_US)
udelay(sub_seq_cmd->offset);
else
usleep_range(1000 * sub_seq_cmd->offset,
1000 * sub_seq_cmd->offset + 100);
break;
case HALMAC_PWR_CMD_READ:
break;
case HALMAC_PWR_CMD_END:
return HALMAC_RET_SUCCESS;
default:
return HALMAC_RET_PWRSEQ_CMD_INCORRECT;
}
*reti = false;
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_pwr_sub_seq_parer_88xx(struct halmac_adapter *halmac_adapter, u8 cut,
u8 fab, u8 intf,
struct halmac_wl_pwr_cfg_ *pwr_sub_seq_cfg)
{
struct halmac_wl_pwr_cfg_ *sub_seq_cmd;
bool reti;
enum halmac_ret_status status;
for (sub_seq_cmd = pwr_sub_seq_cfg;; sub_seq_cmd++) {
if ((sub_seq_cmd->interface_msk & intf) &&
(sub_seq_cmd->fab_msk & fab) &&
(sub_seq_cmd->cut_msk & cut)) {
status = halmac_pwr_sub_seq_parer_do_cmd_88xx(
halmac_adapter, sub_seq_cmd, &reti);
if (reti)
return status;
}
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_get_h2c_buff_free_space_88xx(struct halmac_adapter *halmac_adapter)
{
u32 hw_wptr, fw_rptr;
struct halmac_api *halmac_api =
(struct halmac_api *)halmac_adapter->halmac_api;
hw_wptr = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_PKT_WRITEADDR) &
BIT_MASK_H2C_WR_ADDR;
fw_rptr = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_PKT_READADDR) &
BIT_MASK_H2C_READ_ADDR;
if (hw_wptr >= fw_rptr)
halmac_adapter->h2c_buf_free_space =
halmac_adapter->h2c_buff_size - (hw_wptr - fw_rptr);
else
halmac_adapter->h2c_buf_free_space = fw_rptr - hw_wptr;
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_h2c_pkt_88xx(struct halmac_adapter *halmac_adapter, u8 *hal_h2c_cmd,
u32 size, bool ack)
{
u32 counter = 100;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
while (halmac_adapter->h2c_buf_free_space <=
HALMAC_H2C_CMD_SIZE_UNIT_88XX) {
halmac_get_h2c_buff_free_space_88xx(halmac_adapter);
counter--;
if (counter == 0) {
pr_err("h2c free space is not enough!!\n");
return HALMAC_RET_H2C_SPACE_FULL;
}
}
/* Send TxDesc + H2C_CMD */
if (!PLATFORM_SEND_H2C_PKT(driver_adapter, hal_h2c_cmd, size)) {
pr_err("Send H2C_CMD pkt error!!\n");
return HALMAC_RET_SEND_H2C_FAIL;
}
halmac_adapter->h2c_buf_free_space -= HALMAC_H2C_CMD_SIZE_UNIT_88XX;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"H2C free space : %d\n",
halmac_adapter->h2c_buf_free_space);
return status;
}
enum halmac_ret_status
halmac_download_rsvd_page_88xx(struct halmac_adapter *halmac_adapter,
u8 *hal_buf, u32 size)
{
u8 restore[3];
u8 value8;
u32 counter;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
if (size == 0) {
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"Rsvd page packet size is zero!!\n");
return HALMAC_RET_ZERO_LEN_RSVD_PACKET;
}
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1);
value8 = (u8)(value8 | BIT(7));
HALMAC_REG_WRITE_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1, value8);
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR + 1);
restore[0] = value8;
value8 = (u8)(value8 | BIT(0));
HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1, value8);
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL);
restore[1] = value8;
value8 = (u8)((value8 & ~(BIT(3))) | BIT(4));
HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL, value8);
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2);
restore[2] = value8;
value8 = (u8)(value8 & ~(BIT(6)));
HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2, value8);
if (!PLATFORM_SEND_RSVD_PAGE(driver_adapter, hal_buf, size)) {
pr_err("PLATFORM_SEND_RSVD_PAGE 1 error!!\n");
status = HALMAC_RET_DL_RSVD_PAGE_FAIL;
}
/* Check Bcn_Valid_Bit */
counter = 1000;
while (!(HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1) &
BIT(7))) {
udelay(10);
counter--;
if (counter == 0) {
pr_err("Polling Bcn_Valid_Fail error!!\n");
status = HALMAC_RET_POLLING_BCN_VALID_FAIL;
break;
}
}
value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1);
HALMAC_REG_WRITE_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1,
(value8 | BIT(7)));
HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2, restore[2]);
HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL, restore[1]);
HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1, restore[0]);
return status;
}
enum halmac_ret_status
halmac_set_h2c_header_88xx(struct halmac_adapter *halmac_adapter,
u8 *hal_h2c_hdr, u16 *seq, bool ack)
{
void *driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
H2C_CMD_HEADER_SET_CATEGORY(hal_h2c_hdr, 0x00);
H2C_CMD_HEADER_SET_TOTAL_LEN(hal_h2c_hdr, 16);
spin_lock(&halmac_adapter->h2c_seq_lock);
H2C_CMD_HEADER_SET_SEQ_NUM(hal_h2c_hdr, halmac_adapter->h2c_packet_seq);
*seq = halmac_adapter->h2c_packet_seq;
halmac_adapter->h2c_packet_seq++;
spin_unlock(&halmac_adapter->h2c_seq_lock);
if (ack)
H2C_CMD_HEADER_SET_ACK(hal_h2c_hdr, 1);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status halmac_set_fw_offload_h2c_header_88xx(
struct halmac_adapter *halmac_adapter, u8 *hal_h2c_hdr,
struct halmac_h2c_header_info *h2c_header_info, u16 *seq_num)
{
void *driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
FW_OFFLOAD_H2C_SET_TOTAL_LEN(hal_h2c_hdr,
8 + h2c_header_info->content_size);
FW_OFFLOAD_H2C_SET_SUB_CMD_ID(hal_h2c_hdr, h2c_header_info->sub_cmd_id);
FW_OFFLOAD_H2C_SET_CATEGORY(hal_h2c_hdr, 0x01);
FW_OFFLOAD_H2C_SET_CMD_ID(hal_h2c_hdr, 0xFF);
spin_lock(&halmac_adapter->h2c_seq_lock);
FW_OFFLOAD_H2C_SET_SEQ_NUM(hal_h2c_hdr, halmac_adapter->h2c_packet_seq);
*seq_num = halmac_adapter->h2c_packet_seq;
halmac_adapter->h2c_packet_seq++;
spin_unlock(&halmac_adapter->h2c_seq_lock);
if (h2c_header_info->ack)
FW_OFFLOAD_H2C_SET_ACK(hal_h2c_hdr, 1);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_h2c_set_pwr_mode_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_fwlps_option *hal_fw_lps_opt)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX];
u8 *h2c_header, *h2c_cmd;
u16 seq = 0;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
h2c_header = h2c_buff;
h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
memset(h2c_buff, 0x00, HALMAC_H2C_CMD_SIZE_88XX);
SET_PWR_MODE_SET_CMD_ID(h2c_cmd, CMD_ID_SET_PWR_MODE);
SET_PWR_MODE_SET_CLASS(h2c_cmd, CLASS_SET_PWR_MODE);
SET_PWR_MODE_SET_MODE(h2c_cmd, hal_fw_lps_opt->mode);
SET_PWR_MODE_SET_CLK_REQUEST(h2c_cmd, hal_fw_lps_opt->clk_request);
SET_PWR_MODE_SET_RLBM(h2c_cmd, hal_fw_lps_opt->rlbm);
SET_PWR_MODE_SET_SMART_PS(h2c_cmd, hal_fw_lps_opt->smart_ps);
SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_cmd,
hal_fw_lps_opt->awake_interval);
SET_PWR_MODE_SET_B_ALL_QUEUE_UAPSD(h2c_cmd,
hal_fw_lps_opt->all_queue_uapsd);
SET_PWR_MODE_SET_PWR_STATE(h2c_cmd, hal_fw_lps_opt->pwr_state);
SET_PWR_MODE_SET_ANT_AUTO_SWITCH(h2c_cmd,
hal_fw_lps_opt->ant_auto_switch);
SET_PWR_MODE_SET_PS_ALLOW_BT_HIGH_PRIORITY(
h2c_cmd, hal_fw_lps_opt->ps_allow_bt_high_priority);
SET_PWR_MODE_SET_PROTECT_BCN(h2c_cmd, hal_fw_lps_opt->protect_bcn);
SET_PWR_MODE_SET_SILENCE_PERIOD(h2c_cmd,
hal_fw_lps_opt->silence_period);
SET_PWR_MODE_SET_FAST_BT_CONNECT(h2c_cmd,
hal_fw_lps_opt->fast_bt_connect);
SET_PWR_MODE_SET_TWO_ANTENNA_EN(h2c_cmd,
hal_fw_lps_opt->two_antenna_en);
SET_PWR_MODE_SET_ADOPT_USER_SETTING(h2c_cmd,
hal_fw_lps_opt->adopt_user_setting);
SET_PWR_MODE_SET_DRV_BCN_EARLY_SHIFT(
h2c_cmd, hal_fw_lps_opt->drv_bcn_early_shift);
halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, true);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS) {
pr_err("%s Fail = %x!!\n", __func__, status);
return status;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_func_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter,
u8 *original_h2c, u16 *seq, u8 ack)
{
u8 H2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u8 *h2c_header, *h2c_cmd;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"halmac_send_original_h2c ==========>\n");
h2c_header = H2c_buff;
h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
memcpy(h2c_cmd, original_h2c, 8); /* Original H2C 8 byte */
halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, seq, ack);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, H2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, ack);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_original_h2c Fail = %x!!\n", status);
return status;
}
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"halmac_send_original_h2c <==========\n");
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_media_status_rpt_88xx(struct halmac_adapter *halmac_adapter, u8 op_mode,
u8 mac_id_ind, u8 mac_id, u8 mac_id_end)
{
u8 H2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u8 *h2c_header, *h2c_cmd;
u16 seq = 0;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"halmac_send_h2c_set_pwr_mode_88xx!!\n");
h2c_header = H2c_buff;
h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
memset(H2c_buff, 0x00, HALMAC_H2C_CMD_SIZE_88XX);
MEDIA_STATUS_RPT_SET_CMD_ID(h2c_cmd, CMD_ID_MEDIA_STATUS_RPT);
MEDIA_STATUS_RPT_SET_CLASS(h2c_cmd, CLASS_MEDIA_STATUS_RPT);
MEDIA_STATUS_RPT_SET_OP_MODE(h2c_cmd, op_mode);
MEDIA_STATUS_RPT_SET_MACID_IN(h2c_cmd, mac_id_ind);
MEDIA_STATUS_RPT_SET_MACID(h2c_cmd, mac_id);
MEDIA_STATUS_RPT_SET_MACID_END(h2c_cmd, mac_id_end);
halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, true);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, H2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS) {
pr_err("%s Fail = %x!!\n", __func__, status);
return status;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_h2c_update_packet_88xx(struct halmac_adapter *halmac_adapter,
enum halmac_packet_id pkt_id, u8 *pkt,
u32 pkt_size)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation
.rsvd_h2c_extra_info_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
ret_status =
halmac_download_rsvd_page_88xx(halmac_adapter, pkt, pkt_size);
if (ret_status != HALMAC_RET_SUCCESS) {
pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n",
ret_status);
HALMAC_REG_WRITE_16(
halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
return ret_status;
}
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
UPDATE_PACKET_SET_SIZE(
h2c_buff,
pkt_size + halmac_adapter->hw_config_info.txdesc_size);
UPDATE_PACKET_SET_PACKET_ID(h2c_buff, pkt_id);
UPDATE_PACKET_SET_PACKET_LOC(
h2c_buff,
halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy -
halmac_adapter->txff_allocation.rsvd_pg_bndy);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_UPDATE_PACKET;
h2c_header_info.content_size = 8;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
halmac_adapter->halmac_state.update_packet_set.seq_num = h2c_seq_mum;
ret_status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (ret_status != HALMAC_RET_SUCCESS) {
pr_err("%s Fail = %x!!\n", __func__, ret_status);
return ret_status;
}
return ret_status;
}
enum halmac_ret_status
halmac_send_h2c_phy_parameter_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_phy_parameter_info *para_info,
bool full_fifo)
{
bool drv_trigger_send = false;
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
u32 info_size = 0;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
struct halmac_config_para_info *config_para_info;
driver_adapter = halmac_adapter->driver_adapter;
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
config_para_info = &halmac_adapter->config_para_info;
if (!config_para_info->cfg_para_buf) {
if (full_fifo)
config_para_info->para_buf_size =
HALMAC_EXTRA_INFO_BUFF_SIZE_FULL_FIFO_88XX;
else
config_para_info->para_buf_size =
HALMAC_EXTRA_INFO_BUFF_SIZE_88XX;
config_para_info->cfg_para_buf =
kzalloc(config_para_info->para_buf_size, GFP_KERNEL);
if (config_para_info->cfg_para_buf) {
memset(config_para_info->cfg_para_buf, 0x00,
config_para_info->para_buf_size);
config_para_info->full_fifo_mode = full_fifo;
config_para_info->para_buf_w =
config_para_info->cfg_para_buf;
config_para_info->para_num = 0;
config_para_info->avai_para_buf_size =
config_para_info->para_buf_size;
config_para_info->value_accumulation = 0;
config_para_info->offset_accumulation = 0;
} else {
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C,
DBG_DMESG,
"Allocate cfg_para_buf fail!!\n");
return HALMAC_RET_MALLOC_FAIL;
}
}
if (halmac_transition_cfg_para_state_88xx(
halmac_adapter,
HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
halmac_enqueue_para_buff_88xx(halmac_adapter, para_info,
config_para_info->para_buf_w,
&drv_trigger_send);
if (para_info->cmd_id != HALMAC_PARAMETER_CMD_END) {
config_para_info->para_num++;
config_para_info->para_buf_w += HALMAC_FW_OFFLOAD_CMD_SIZE_88XX;
config_para_info->avai_para_buf_size =
config_para_info->avai_para_buf_size -
HALMAC_FW_OFFLOAD_CMD_SIZE_88XX;
}
if ((config_para_info->avai_para_buf_size -
halmac_adapter->hw_config_info.txdesc_size) >
HALMAC_FW_OFFLOAD_CMD_SIZE_88XX &&
!drv_trigger_send)
return HALMAC_RET_SUCCESS;
if (config_para_info->para_num == 0) {
kfree(config_para_info->cfg_para_buf);
config_para_info->cfg_para_buf = NULL;
config_para_info->para_buf_w = NULL;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_WARNING,
"no cfg parameter element!!\n");
if (halmac_transition_cfg_para_state_88xx(
halmac_adapter,
HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
return HALMAC_RET_SUCCESS;
}
if (halmac_transition_cfg_para_state_88xx(
halmac_adapter, HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
halmac_adapter->halmac_state.cfg_para_state_set.process_status =
HALMAC_CMD_PROCESS_SENDING;
if (config_para_info->full_fifo_mode)
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, 0);
else
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation
.rsvd_h2c_extra_info_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
info_size =
config_para_info->para_num * HALMAC_FW_OFFLOAD_CMD_SIZE_88XX;
status = halmac_download_rsvd_page_88xx(
halmac_adapter, (u8 *)config_para_info->cfg_para_buf,
info_size);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_download_rsvd_page_88xx Fail!!\n");
} else {
halmac_gen_cfg_para_h2c_88xx(halmac_adapter, h2c_buff);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_CFG_PARAMETER;
h2c_header_info.content_size = 4;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info,
&h2c_seq_mum);
halmac_adapter->halmac_state.cfg_para_state_set.seq_num =
h2c_seq_mum;
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX,
true);
if (status != HALMAC_RET_SUCCESS)
pr_err("halmac_send_h2c_pkt_88xx Fail!!\n");
HALMAC_RT_TRACE(
driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"config parameter time = %d\n",
HALMAC_REG_READ_32(halmac_adapter, REG_FW_DBG6));
}
kfree(config_para_info->cfg_para_buf);
config_para_info->cfg_para_buf = NULL;
config_para_info->para_buf_w = NULL;
/* Restore bcn head */
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
if (halmac_transition_cfg_para_state_88xx(
halmac_adapter, HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
if (!drv_trigger_send) {
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
"Buffer full trigger sending H2C!!\n");
return HALMAC_RET_PARA_SENDING;
}
return status;
}
static enum halmac_ret_status
halmac_enqueue_para_buff_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_phy_parameter_info *para_info,
u8 *curr_buff_wptr, bool *end_cmd)
{
struct halmac_config_para_info *config_para_info =
&halmac_adapter->config_para_info;
*end_cmd = false;
PHY_PARAMETER_INFO_SET_LENGTH(curr_buff_wptr,
HALMAC_FW_OFFLOAD_CMD_SIZE_88XX);
PHY_PARAMETER_INFO_SET_IO_CMD(curr_buff_wptr, para_info->cmd_id);
switch (para_info->cmd_id) {
case HALMAC_PARAMETER_CMD_BB_W8:
case HALMAC_PARAMETER_CMD_BB_W16:
case HALMAC_PARAMETER_CMD_BB_W32:
case HALMAC_PARAMETER_CMD_MAC_W8:
case HALMAC_PARAMETER_CMD_MAC_W16:
case HALMAC_PARAMETER_CMD_MAC_W32:
PHY_PARAMETER_INFO_SET_IO_ADDR(
curr_buff_wptr, para_info->content.MAC_REG_W.offset);
PHY_PARAMETER_INFO_SET_DATA(curr_buff_wptr,
para_info->content.MAC_REG_W.value);
PHY_PARAMETER_INFO_SET_MASK(curr_buff_wptr,
para_info->content.MAC_REG_W.msk);
PHY_PARAMETER_INFO_SET_MSK_EN(
curr_buff_wptr, para_info->content.MAC_REG_W.msk_en);
config_para_info->value_accumulation +=
para_info->content.MAC_REG_W.value;
config_para_info->offset_accumulation +=
para_info->content.MAC_REG_W.offset;
break;
case HALMAC_PARAMETER_CMD_RF_W:
/*In rf register, the address is only 1 byte*/
PHY_PARAMETER_INFO_SET_RF_ADDR(
curr_buff_wptr, para_info->content.RF_REG_W.offset);
PHY_PARAMETER_INFO_SET_RF_PATH(
curr_buff_wptr, para_info->content.RF_REG_W.rf_path);
PHY_PARAMETER_INFO_SET_DATA(curr_buff_wptr,
para_info->content.RF_REG_W.value);
PHY_PARAMETER_INFO_SET_MASK(curr_buff_wptr,
para_info->content.RF_REG_W.msk);
PHY_PARAMETER_INFO_SET_MSK_EN(
curr_buff_wptr, para_info->content.RF_REG_W.msk_en);
config_para_info->value_accumulation +=
para_info->content.RF_REG_W.value;
config_para_info->offset_accumulation +=
(para_info->content.RF_REG_W.offset +
(para_info->content.RF_REG_W.rf_path << 8));
break;
case HALMAC_PARAMETER_CMD_DELAY_US:
case HALMAC_PARAMETER_CMD_DELAY_MS:
PHY_PARAMETER_INFO_SET_DELAY_VALUE(
curr_buff_wptr,
para_info->content.DELAY_TIME.delay_time);
break;
case HALMAC_PARAMETER_CMD_END:
*end_cmd = true;
break;
default:
pr_err(" halmac_send_h2c_phy_parameter_88xx illegal cmd_id!!\n");
break;
}
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_gen_cfg_para_h2c_88xx(struct halmac_adapter *halmac_adapter,
u8 *h2c_buff)
{
struct halmac_config_para_info *config_para_info =
&halmac_adapter->config_para_info;
CFG_PARAMETER_SET_NUM(h2c_buff, config_para_info->para_num);
if (config_para_info->full_fifo_mode) {
CFG_PARAMETER_SET_INIT_CASE(h2c_buff, 0x1);
CFG_PARAMETER_SET_PHY_PARAMETER_LOC(h2c_buff, 0);
} else {
CFG_PARAMETER_SET_INIT_CASE(h2c_buff, 0x0);
CFG_PARAMETER_SET_PHY_PARAMETER_LOC(
h2c_buff,
halmac_adapter->txff_allocation
.rsvd_h2c_extra_info_pg_bndy -
halmac_adapter->txff_allocation.rsvd_pg_bndy);
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_h2c_run_datapack_88xx(struct halmac_adapter *halmac_adapter,
enum halmac_data_type halmac_data_type)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
RUN_DATAPACK_SET_DATAPACK_ID(h2c_buff, halmac_data_type);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_RUN_DATAPACK;
h2c_header_info.content_size = 4;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
return status;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_send_bt_coex_cmd_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf,
u32 bt_size, u8 ack)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
memcpy(h2c_buff + 8, bt_buf, bt_size);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_BT_COEX;
h2c_header_info.content_size = (u16)bt_size;
h2c_header_info.ack = ack;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, ack);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
return status;
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
halmac_func_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_ch_switch_option *cs_option)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_api *halmac_api;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
enum halmac_cmd_process_status *process_status =
&halmac_adapter->halmac_state.scan_state_set.process_status;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"halmac_ctrl_ch_switch!!\n");
halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
if (halmac_transition_scan_state_88xx(
halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
*process_status = HALMAC_CMD_PROCESS_SENDING;
if (cs_option->switch_en != 0) {
HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation
.rsvd_h2c_extra_info_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
status = halmac_download_rsvd_page_88xx(
halmac_adapter, halmac_adapter->ch_sw_info.ch_info_buf,
halmac_adapter->ch_sw_info.total_size);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n",
status);
HALMAC_REG_WRITE_16(
halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation
.rsvd_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
return status;
}
HALMAC_REG_WRITE_16(
halmac_adapter, REG_FIFOPAGE_CTRL_2,
(u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
BIT_MASK_BCN_HEAD_1_V1));
}
CHANNEL_SWITCH_SET_SWITCH_START(h2c_buff, cs_option->switch_en);
CHANNEL_SWITCH_SET_CHANNEL_NUM(h2c_buff,
halmac_adapter->ch_sw_info.ch_num);
CHANNEL_SWITCH_SET_CHANNEL_INFO_LOC(
h2c_buff,
halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy -
halmac_adapter->txff_allocation.rsvd_pg_bndy);
CHANNEL_SWITCH_SET_DEST_CH_EN(h2c_buff, cs_option->dest_ch_en);
CHANNEL_SWITCH_SET_DEST_CH(h2c_buff, cs_option->dest_ch);
CHANNEL_SWITCH_SET_PRI_CH_IDX(h2c_buff, cs_option->dest_pri_ch_idx);
CHANNEL_SWITCH_SET_ABSOLUTE_TIME(h2c_buff, cs_option->absolute_time_en);
CHANNEL_SWITCH_SET_TSF_LOW(h2c_buff, cs_option->tsf_low);
CHANNEL_SWITCH_SET_PERIODIC_OPTION(h2c_buff,
cs_option->periodic_option);
CHANNEL_SWITCH_SET_NORMAL_CYCLE(h2c_buff, cs_option->normal_cycle);
CHANNEL_SWITCH_SET_NORMAL_PERIOD(h2c_buff, cs_option->normal_period);
CHANNEL_SWITCH_SET_SLOW_PERIOD(h2c_buff, cs_option->phase_2_period);
CHANNEL_SWITCH_SET_CHANNEL_INFO_SIZE(
h2c_buff, halmac_adapter->ch_sw_info.total_size);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_CHANNEL_SWITCH;
h2c_header_info.content_size = 20;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
halmac_adapter->halmac_state.scan_state_set.seq_num = h2c_seq_mum;
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS)
pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
kfree(halmac_adapter->ch_sw_info.ch_info_buf);
halmac_adapter->ch_sw_info.ch_info_buf = NULL;
halmac_adapter->ch_sw_info.ch_info_buf_w = NULL;
halmac_adapter->ch_sw_info.extra_info_en = 0;
halmac_adapter->ch_sw_info.buf_size = 0;
halmac_adapter->ch_sw_info.avai_buf_size = 0;
halmac_adapter->ch_sw_info.total_size = 0;
halmac_adapter->ch_sw_info.ch_num = 0;
if (halmac_transition_scan_state_88xx(halmac_adapter,
HALMAC_SCAN_CMD_CONSTRUCT_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
return status;
}
enum halmac_ret_status
halmac_func_send_general_info_88xx(struct halmac_adapter *halmac_adapter,
struct halmac_general_info *general_info)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = NULL;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"halmac_send_general_info!!\n");
GENERAL_INFO_SET_REF_TYPE(h2c_buff, general_info->rfe_type);
GENERAL_INFO_SET_RF_TYPE(h2c_buff, general_info->rf_type);
GENERAL_INFO_SET_FW_TX_BOUNDARY(
h2c_buff,
halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy -
halmac_adapter->txff_allocation.rsvd_pg_bndy);
h2c_header_info.sub_cmd_id = SUB_CMD_ID_GENERAL_INFO;
h2c_header_info.content_size = 4;
h2c_header_info.ack = false;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS)
pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
return status;
}
enum halmac_ret_status halmac_send_h2c_update_bcn_parse_info_88xx(
struct halmac_adapter *halmac_adapter,
struct halmac_bcn_ie_info *bcn_ie_info)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u16 h2c_seq_mum = 0;
void *driver_adapter = halmac_adapter->driver_adapter;
struct halmac_h2c_header_info h2c_header_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
UPDATE_BEACON_PARSING_INFO_SET_FUNC_EN(h2c_buff, bcn_ie_info->func_en);
UPDATE_BEACON_PARSING_INFO_SET_SIZE_TH(h2c_buff, bcn_ie_info->size_th);
UPDATE_BEACON_PARSING_INFO_SET_TIMEOUT(h2c_buff, bcn_ie_info->timeout);
UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_0(
h2c_buff, (u32)(bcn_ie_info->ie_bmp[0]));
UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_1(
h2c_buff, (u32)(bcn_ie_info->ie_bmp[1]));
UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_2(
h2c_buff, (u32)(bcn_ie_info->ie_bmp[2]));
UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_3(
h2c_buff, (u32)(bcn_ie_info->ie_bmp[3]));
UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_4(
h2c_buff, (u32)(bcn_ie_info->ie_bmp[4]));
h2c_header_info.sub_cmd_id = SUB_CMD_ID_UPDATE_BEACON_PARSING_INFO;
h2c_header_info.content_size = 24;
h2c_header_info.ack = true;
halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
&h2c_header_info, &h2c_seq_mum);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, true);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_h2c_pkt_88xx Fail =%x !!\n", status);
return status;
}
return status;
}
enum halmac_ret_status
halmac_send_h2c_ps_tuning_para_88xx(struct halmac_adapter *halmac_adapter)
{
u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
u8 *h2c_header, *h2c_cmd;
u16 seq = 0;
void *driver_adapter = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
driver_adapter = halmac_adapter->driver_adapter;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"%s!!\n", __func__);
h2c_header = h2c_buff;
h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, false);
status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
HALMAC_H2C_CMD_SIZE_88XX, false);
if (status != HALMAC_RET_SUCCESS) {
pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
return status;
}
return status;
}
enum halmac_ret_status
halmac_parse_c2h_packet_88xx(struct halmac_adapter *halmac_adapter,
u8 *halmac_buf, u32 halmac_size)
{
u8 c2h_cmd, c2h_sub_cmd_id;
u8 *c2h_buf = halmac_buf + halmac_adapter->hw_config_info.rxdesc_size;
u32 c2h_size = halmac_size - halmac_adapter->hw_config_info.rxdesc_size;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
c2h_cmd = (u8)C2H_HDR_GET_CMD_ID(c2h_buf);
/* FW offload C2H cmd is 0xFF */
if (c2h_cmd != 0xFF) {
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"C2H_PKT not for FwOffloadC2HFormat!!\n");
return HALMAC_RET_C2H_NOT_HANDLED;
}
/* Get C2H sub cmd ID */
c2h_sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_buf);
switch (c2h_sub_cmd_id) {
case C2H_SUB_CMD_ID_C2H_DBG:
status = halmac_parse_c2h_debug_88xx(halmac_adapter, c2h_buf,
c2h_size);
break;
case C2H_SUB_CMD_ID_H2C_ACK_HDR:
status = halmac_parse_h2c_ack_88xx(halmac_adapter, c2h_buf,
c2h_size);
break;
case C2H_SUB_CMD_ID_BT_COEX_INFO:
status = HALMAC_RET_C2H_NOT_HANDLED;
break;
case C2H_SUB_CMD_ID_SCAN_STATUS_RPT:
status = halmac_parse_scan_status_rpt_88xx(halmac_adapter,
c2h_buf, c2h_size);
break;
case C2H_SUB_CMD_ID_PSD_DATA:
status = halmac_parse_psd_data_88xx(halmac_adapter, c2h_buf,
c2h_size);
break;
case C2H_SUB_CMD_ID_EFUSE_DATA:
status = halmac_parse_efuse_data_88xx(halmac_adapter, c2h_buf,
c2h_size);
break;
default:
pr_err("c2h_sub_cmd_id switch case out of boundary!!\n");
pr_err("[ERR]c2h pkt : %.8X %.8X!!\n", *(u32 *)c2h_buf,
*(u32 *)(c2h_buf + 4));
status = HALMAC_RET_C2H_NOT_HANDLED;
break;
}
return status;
}
static enum halmac_ret_status
halmac_parse_c2h_debug_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size)
{
void *driver_adapter = NULL;
u8 *c2h_buf_local = (u8 *)NULL;
u32 c2h_size_local = 0;
u8 dbg_content_length = 0;
u8 dbg_seq_num = 0;
driver_adapter = halmac_adapter->driver_adapter;
c2h_buf_local = c2h_buf;
c2h_size_local = c2h_size;
dbg_content_length = (u8)C2H_HDR_GET_LEN((u8 *)c2h_buf_local);
if (dbg_content_length > C2H_DBG_CONTENT_MAX_LENGTH)
return HALMAC_RET_SUCCESS;
*(c2h_buf_local + C2H_DBG_HEADER_LENGTH + dbg_content_length - 2) =
'\n';
dbg_seq_num = (u8)(*(c2h_buf_local + C2H_DBG_HEADER_LENGTH));
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"[RTKFW, SEQ=%d]: %s", dbg_seq_num,
(char *)(c2h_buf_local + C2H_DBG_HEADER_LENGTH + 1));
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_parse_scan_status_rpt_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size)
{
u8 h2c_return_code;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_cmd_process_status process_status;
h2c_return_code = (u8)SCAN_STATUS_RPT_GET_H2C_RETURN_CODE(c2h_buf);
process_status = (enum halmac_h2c_return_code)h2c_return_code ==
HALMAC_H2C_RETURN_SUCCESS ?
HALMAC_CMD_PROCESS_DONE :
HALMAC_CMD_PROCESS_ERROR;
PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_CHANNEL_SWITCH,
process_status, NULL, 0);
halmac_adapter->halmac_state.scan_state_set.process_status =
process_status;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"[TRACE]scan status : %X\n", process_status);
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_parse_psd_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size)
{
u8 segment_id = 0, segment_size = 0, h2c_seq = 0;
u16 total_size;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_cmd_process_status process_status;
struct halmac_psd_state_set *psd_set =
&halmac_adapter->halmac_state.psd_set;
h2c_seq = (u8)PSD_DATA_GET_H2C_SEQ(c2h_buf);
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"[TRACE]Seq num : h2c -> %d c2h -> %d\n",
psd_set->seq_num, h2c_seq);
if (h2c_seq != psd_set->seq_num) {
pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n",
psd_set->seq_num, h2c_seq);
return HALMAC_RET_SUCCESS;
}
if (psd_set->process_status != HALMAC_CMD_PROCESS_SENDING) {
pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n");
return HALMAC_RET_SUCCESS;
}
total_size = (u16)PSD_DATA_GET_TOTAL_SIZE(c2h_buf);
segment_id = (u8)PSD_DATA_GET_SEGMENT_ID(c2h_buf);
segment_size = (u8)PSD_DATA_GET_SEGMENT_SIZE(c2h_buf);
psd_set->data_size = total_size;
if (!psd_set->data)
psd_set->data = kzalloc(psd_set->data_size, GFP_KERNEL);
if (segment_id == 0)
psd_set->segment_size = segment_size;
memcpy(psd_set->data + segment_id * psd_set->segment_size,
c2h_buf + HALMAC_C2H_DATA_OFFSET_88XX, segment_size);
if (!PSD_DATA_GET_END_SEGMENT(c2h_buf))
return HALMAC_RET_SUCCESS;
process_status = HALMAC_CMD_PROCESS_DONE;
psd_set->process_status = process_status;
PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_PSD,
process_status, psd_set->data,
psd_set->data_size);
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_parse_efuse_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size)
{
u8 segment_id = 0, segment_size = 0, h2c_seq = 0;
u8 *eeprom_map = NULL;
u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
u8 h2c_return_code = 0;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_cmd_process_status process_status;
h2c_seq = (u8)EFUSE_DATA_GET_H2C_SEQ(c2h_buf);
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"[TRACE]Seq num : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.efuse_state_set.seq_num,
h2c_seq);
if (h2c_seq != halmac_adapter->halmac_state.efuse_state_set.seq_num) {
pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.efuse_state_set.seq_num,
h2c_seq);
return HALMAC_RET_SUCCESS;
}
if (halmac_adapter->halmac_state.efuse_state_set.process_status !=
HALMAC_CMD_PROCESS_SENDING) {
pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n");
return HALMAC_RET_SUCCESS;
}
segment_id = (u8)EFUSE_DATA_GET_SEGMENT_ID(c2h_buf);
segment_size = (u8)EFUSE_DATA_GET_SEGMENT_SIZE(c2h_buf);
if (segment_id == 0)
halmac_adapter->efuse_segment_size = segment_size;
eeprom_map = kzalloc(eeprom_size, GFP_KERNEL);
if (!eeprom_map) {
/* out of memory */
return HALMAC_RET_MALLOC_FAIL;
}
memset(eeprom_map, 0xFF, eeprom_size);
spin_lock(&halmac_adapter->efuse_lock);
memcpy(halmac_adapter->hal_efuse_map +
segment_id * halmac_adapter->efuse_segment_size,
c2h_buf + HALMAC_C2H_DATA_OFFSET_88XX, segment_size);
spin_unlock(&halmac_adapter->efuse_lock);
if (!EFUSE_DATA_GET_END_SEGMENT(c2h_buf)) {
kfree(eeprom_map);
return HALMAC_RET_SUCCESS;
}
h2c_return_code =
halmac_adapter->halmac_state.efuse_state_set.fw_return_code;
if ((enum halmac_h2c_return_code)h2c_return_code ==
HALMAC_H2C_RETURN_SUCCESS) {
process_status = HALMAC_CMD_PROCESS_DONE;
halmac_adapter->halmac_state.efuse_state_set.process_status =
process_status;
spin_lock(&halmac_adapter->efuse_lock);
halmac_adapter->hal_efuse_map_valid = true;
spin_unlock(&halmac_adapter->efuse_lock);
if (halmac_adapter->event_trigger.physical_efuse_map == 1) {
PLATFORM_EVENT_INDICATION(
driver_adapter,
HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE,
process_status, halmac_adapter->hal_efuse_map,
halmac_adapter->hw_config_info.efuse_size);
halmac_adapter->event_trigger.physical_efuse_map = 0;
}
if (halmac_adapter->event_trigger.logical_efuse_map == 1) {
if (halmac_eeprom_parser_88xx(
halmac_adapter,
halmac_adapter->hal_efuse_map,
eeprom_map) != HALMAC_RET_SUCCESS) {
kfree(eeprom_map);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
PLATFORM_EVENT_INDICATION(
driver_adapter,
HALMAC_FEATURE_DUMP_LOGICAL_EFUSE,
process_status, eeprom_map, eeprom_size);
halmac_adapter->event_trigger.logical_efuse_map = 0;
}
} else {
process_status = HALMAC_CMD_PROCESS_ERROR;
halmac_adapter->halmac_state.efuse_state_set.process_status =
process_status;
if (halmac_adapter->event_trigger.physical_efuse_map == 1) {
PLATFORM_EVENT_INDICATION(
driver_adapter,
HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE,
process_status,
&halmac_adapter->halmac_state.efuse_state_set
.fw_return_code,
1);
halmac_adapter->event_trigger.physical_efuse_map = 0;
}
if (halmac_adapter->event_trigger.logical_efuse_map == 1) {
if (halmac_eeprom_parser_88xx(
halmac_adapter,
halmac_adapter->hal_efuse_map,
eeprom_map) != HALMAC_RET_SUCCESS) {
kfree(eeprom_map);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
PLATFORM_EVENT_INDICATION(
driver_adapter,
HALMAC_FEATURE_DUMP_LOGICAL_EFUSE,
process_status,
&halmac_adapter->halmac_state.efuse_state_set
.fw_return_code,
1);
halmac_adapter->event_trigger.logical_efuse_map = 0;
}
}
kfree(eeprom_map);
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_parse_h2c_ack_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf,
u32 c2h_size)
{
u8 h2c_cmd_id, h2c_sub_cmd_id;
u8 h2c_return_code;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"Ack for C2H!!\n");
h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf);
if ((enum halmac_h2c_return_code)h2c_return_code !=
HALMAC_H2C_RETURN_SUCCESS)
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"C2H_PKT Status Error!! Status = %d\n",
h2c_return_code);
h2c_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_CMD_ID(c2h_buf);
if (h2c_cmd_id != 0xFF) {
pr_err("original h2c ack is not handled!!\n");
status = HALMAC_RET_C2H_NOT_HANDLED;
} else {
h2c_sub_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_SUB_CMD_ID(c2h_buf);
switch (h2c_sub_cmd_id) {
case H2C_SUB_CMD_ID_DUMP_PHYSICAL_EFUSE_ACK:
status = halmac_parse_h2c_ack_phy_efuse_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_CFG_PARAMETER_ACK:
status = halmac_parse_h2c_ack_cfg_para_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_UPDATE_PACKET_ACK:
status = halmac_parse_h2c_ack_update_packet_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_UPDATE_DATAPACK_ACK:
status = halmac_parse_h2c_ack_update_datapack_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_RUN_DATAPACK_ACK:
status = halmac_parse_h2c_ack_run_datapack_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_CHANNEL_SWITCH_ACK:
status = halmac_parse_h2c_ack_channel_switch_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_IQK_ACK:
status = halmac_parse_h2c_ack_iqk_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_POWER_TRACKING_ACK:
status = halmac_parse_h2c_ack_power_tracking_88xx(
halmac_adapter, c2h_buf, c2h_size);
break;
case H2C_SUB_CMD_ID_PSD_ACK:
break;
default:
pr_err("h2c_sub_cmd_id switch case out of boundary!!\n");
status = HALMAC_RET_C2H_NOT_HANDLED;
break;
}
}
return status;
}
static enum halmac_ret_status
halmac_parse_h2c_ack_phy_efuse_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size)
{
u8 h2c_seq = 0;
u8 h2c_return_code;
void *driver_adapter = halmac_adapter->driver_adapter;
h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf);
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"[TRACE]Seq num : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.efuse_state_set.seq_num,
h2c_seq);
if (h2c_seq != halmac_adapter->halmac_state.efuse_state_set.seq_num) {
pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.efuse_state_set.seq_num,
h2c_seq);
return HALMAC_RET_SUCCESS;
}
if (halmac_adapter->halmac_state.efuse_state_set.process_status !=
HALMAC_CMD_PROCESS_SENDING) {
pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n");
return HALMAC_RET_SUCCESS;
}
h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf);
halmac_adapter->halmac_state.efuse_state_set.fw_return_code =
h2c_return_code;
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
halmac_parse_h2c_ack_cfg_para_88xx(struct halmac_adapter *halmac_adapter,
u8 *c2h_buf, u32 c2h_size)
{
u8 h2c_seq = 0;
u8 h2c_return_code;
u32 offset_accu = 0, value_accu = 0;
void *driver_adapter = halmac_adapter->driver_adapter;
enum halmac_cmd_process_status process_status =
HALMAC_CMD_PROCESS_UNDEFINE;
h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf);
HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
"Seq num : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.cfg_para_state_set.seq_num,
h2c_seq);
if (h2c_seq !=
halmac_adapter->halmac_state.cfg_para_state_set.seq_num) {
pr_err("Seq num mismatch : h2c -> %d c2h -> %d\n",
halmac_adapter->halmac_state.cfg_para_state_set.seq_num,
h2c_seq);
return HALMAC_RET_SUCCESS;
}
if (halmac_adapter->halmac_state.cfg_para_state_set.process_status !=
HALMAC_CMD_PROCESS_SENDING) {
pr_err("Not in HALMAC_CMD_PROCESS_SENDING\n");
return HALMAC_RET_SUCCESS;
}
h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf);
halmac_adapter->halmac_state.cfg_para_state_set.fw_return_code =
h2c_return_code;
offset_accu = CFG_PARAMETER_ACK_GET_OFFSET_ACCUMULATION(c2h_buf);
value_accu = CFG_PARAMETER_ACK_GET_VALUE_ACCUMULATION(c2h_buf);
if ((offset_accu !=
halmac_adapter->config_para_info.offset_accumulation) ||
(value_accu !=
halmac_adapter->config_para_info.value_accumulation)) {
pr_err("[C2H]offset_accu : %x, value_accu : %x!!\n",
offset_accu,