linux/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2016  Realtek Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * The full GNU General Public License is included in this distribution in the
  15 * file called LICENSE.
  16 *
  17 * Contact Information:
  18 * wlanfae <wlanfae@realtek.com>
  19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20 * Hsinchu 300, Taiwan.
  21 *
  22 * Larry Finger <Larry.Finger@lwfinger.net>
  23 *
  24 *****************************************************************************/
  25#include "halmac_88xx_cfg.h"
  26
  27/**
  28 * halmac_init_adapter_para_88xx() - int halmac adapter
  29 * @halmac_adapter
  30 *
  31 * SD1 internal use
  32 *
  33 * Author : KaiYuan Chang/Ivan Lin
  34 * Return : void
  35 */
  36void halmac_init_adapter_para_88xx(struct halmac_adapter *halmac_adapter)
  37{
  38        halmac_adapter->api_record.array_wptr = 0;
  39        halmac_adapter->hal_adapter_backup = halmac_adapter;
  40        halmac_adapter->hal_efuse_map = (u8 *)NULL;
  41        halmac_adapter->hal_efuse_map_valid = false;
  42        halmac_adapter->efuse_end = 0;
  43        halmac_adapter->hal_mac_addr[0].address_l_h.address_low = 0;
  44        halmac_adapter->hal_mac_addr[0].address_l_h.address_high = 0;
  45        halmac_adapter->hal_mac_addr[1].address_l_h.address_low = 0;
  46        halmac_adapter->hal_mac_addr[1].address_l_h.address_high = 0;
  47        halmac_adapter->hal_bss_addr[0].address_l_h.address_low = 0;
  48        halmac_adapter->hal_bss_addr[0].address_l_h.address_high = 0;
  49        halmac_adapter->hal_bss_addr[1].address_l_h.address_low = 0;
  50        halmac_adapter->hal_bss_addr[1].address_l_h.address_high = 0;
  51
  52        halmac_adapter->low_clk = false;
  53        halmac_adapter->max_download_size = HALMAC_FW_MAX_DL_SIZE_88XX;
  54
  55        /* Init LPS Option */
  56        halmac_adapter->fwlps_option.mode = 0x01; /*0:Active 1:LPS 2:WMMPS*/
  57        halmac_adapter->fwlps_option.awake_interval = 1;
  58        halmac_adapter->fwlps_option.enter_32K = 1;
  59        halmac_adapter->fwlps_option.clk_request = 0;
  60        halmac_adapter->fwlps_option.rlbm = 0;
  61        halmac_adapter->fwlps_option.smart_ps = 0;
  62        halmac_adapter->fwlps_option.awake_interval = 1;
  63        halmac_adapter->fwlps_option.all_queue_uapsd = 0;
  64        halmac_adapter->fwlps_option.pwr_state = 0;
  65        halmac_adapter->fwlps_option.low_pwr_rx_beacon = 0;
  66        halmac_adapter->fwlps_option.ant_auto_switch = 0;
  67        halmac_adapter->fwlps_option.ps_allow_bt_high_priority = 0;
  68        halmac_adapter->fwlps_option.protect_bcn = 0;
  69        halmac_adapter->fwlps_option.silence_period = 0;
  70        halmac_adapter->fwlps_option.fast_bt_connect = 0;
  71        halmac_adapter->fwlps_option.two_antenna_en = 0;
  72        halmac_adapter->fwlps_option.adopt_user_setting = 1;
  73        halmac_adapter->fwlps_option.drv_bcn_early_shift = 0;
  74
  75        halmac_adapter->config_para_info.cfg_para_buf = NULL;
  76        halmac_adapter->config_para_info.para_buf_w = NULL;
  77        halmac_adapter->config_para_info.para_num = 0;
  78        halmac_adapter->config_para_info.full_fifo_mode = false;
  79        halmac_adapter->config_para_info.para_buf_size = 0;
  80        halmac_adapter->config_para_info.avai_para_buf_size = 0;
  81        halmac_adapter->config_para_info.offset_accumulation = 0;
  82        halmac_adapter->config_para_info.value_accumulation = 0;
  83        halmac_adapter->config_para_info.datapack_segment = 0;
  84
  85        halmac_adapter->ch_sw_info.ch_info_buf = NULL;
  86        halmac_adapter->ch_sw_info.ch_info_buf_w = NULL;
  87        halmac_adapter->ch_sw_info.extra_info_en = 0;
  88        halmac_adapter->ch_sw_info.buf_size = 0;
  89        halmac_adapter->ch_sw_info.avai_buf_size = 0;
  90        halmac_adapter->ch_sw_info.total_size = 0;
  91        halmac_adapter->ch_sw_info.ch_num = 0;
  92
  93        halmac_adapter->drv_info_size = 0;
  94
  95        memset(halmac_adapter->api_record.api_array, HALMAC_API_STUFF,
  96               sizeof(halmac_adapter->api_record.api_array));
  97
  98        halmac_adapter->txff_allocation.tx_fifo_pg_num = 0;
  99        halmac_adapter->txff_allocation.ac_q_pg_num = 0;
 100        halmac_adapter->txff_allocation.rsvd_pg_bndy = 0;
 101        halmac_adapter->txff_allocation.rsvd_drv_pg_bndy = 0;
 102        halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy = 0;
 103        halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy = 0;
 104        halmac_adapter->txff_allocation.rsvd_cpu_instr_pg_bndy = 0;
 105        halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy = 0;
 106        halmac_adapter->txff_allocation.pub_queue_pg_num = 0;
 107        halmac_adapter->txff_allocation.high_queue_pg_num = 0;
 108        halmac_adapter->txff_allocation.low_queue_pg_num = 0;
 109        halmac_adapter->txff_allocation.normal_queue_pg_num = 0;
 110        halmac_adapter->txff_allocation.extra_queue_pg_num = 0;
 111
 112        halmac_adapter->txff_allocation.la_mode = HALMAC_LA_MODE_DISABLE;
 113        halmac_adapter->txff_allocation.rx_fifo_expanding_mode =
 114                HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
 115
 116        halmac_init_adapter_dynamic_para_88xx(halmac_adapter);
 117        halmac_init_state_machine_88xx(halmac_adapter);
 118}
 119
 120/**
 121 * halmac_init_adapter_dynamic_para_88xx() - int halmac adapter
 122 * @halmac_adapter
 123 *
 124 * SD1 internal use
 125 *
 126 * Author : KaiYuan Chang/Ivan Lin
 127 * Return : void
 128 */
 129void halmac_init_adapter_dynamic_para_88xx(
 130        struct halmac_adapter *halmac_adapter)
 131{
 132        halmac_adapter->h2c_packet_seq = 0;
 133        halmac_adapter->h2c_buf_free_space = 0;
 134        halmac_adapter->gen_info_valid = false;
 135}
 136
 137/**
 138 * halmac_init_state_machine_88xx() - init halmac software state machine
 139 * @halmac_adapter
 140 *
 141 * SD1 internal use.
 142 *
 143 * Author : KaiYuan Chang/Ivan Lin
 144 * Return : void
 145 */
 146void halmac_init_state_machine_88xx(struct halmac_adapter *halmac_adapter)
 147{
 148        struct halmac_state *state = &halmac_adapter->halmac_state;
 149
 150        halmac_init_offload_feature_state_machine_88xx(halmac_adapter);
 151
 152        state->api_state = HALMAC_API_STATE_INIT;
 153
 154        state->dlfw_state = HALMAC_DLFW_NONE;
 155        state->mac_power = HALMAC_MAC_POWER_OFF;
 156        state->ps_state = HALMAC_PS_STATE_UNDEFINE;
 157}
 158
 159/**
 160 * halmac_mount_api_88xx() - attach functions to function pointer
 161 * @halmac_adapter
 162 *
 163 * SD1 internal use
 164 *
 165 * Author : KaiYuan Chang/Ivan Lin
 166 * Return : enum halmac_ret_status
 167 */
 168enum halmac_ret_status
 169halmac_mount_api_88xx(struct halmac_adapter *halmac_adapter)
 170{
 171        void *driver_adapter = halmac_adapter->driver_adapter;
 172        struct halmac_api *halmac_api = (struct halmac_api *)NULL;
 173
 174        halmac_adapter->halmac_api =
 175                kzalloc(sizeof(struct halmac_api), GFP_KERNEL);
 176        if (!halmac_adapter->halmac_api)
 177                return HALMAC_RET_MALLOC_FAIL;
 178        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 179
 180        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 181                        HALMAC_SVN_VER_88XX "\n");
 182        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 183                        "HALMAC_MAJOR_VER_88XX = %x\n", HALMAC_MAJOR_VER_88XX);
 184        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 185                        "HALMAC_PROTOTYPE_88XX = %x\n",
 186                        HALMAC_PROTOTYPE_VER_88XX);
 187        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 188                        "HALMAC_MINOR_VER_88XX = %x\n", HALMAC_MINOR_VER_88XX);
 189        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 190                        "HALMAC_PATCH_VER_88XX = %x\n", HALMAC_PATCH_VER_88XX);
 191
 192        /* Mount function pointer */
 193        halmac_api->halmac_download_firmware = halmac_download_firmware_88xx;
 194        halmac_api->halmac_free_download_firmware =
 195                halmac_free_download_firmware_88xx;
 196        halmac_api->halmac_get_fw_version = halmac_get_fw_version_88xx;
 197        halmac_api->halmac_cfg_mac_addr = halmac_cfg_mac_addr_88xx;
 198        halmac_api->halmac_cfg_bssid = halmac_cfg_bssid_88xx;
 199        halmac_api->halmac_cfg_multicast_addr = halmac_cfg_multicast_addr_88xx;
 200        halmac_api->halmac_pre_init_system_cfg =
 201                halmac_pre_init_system_cfg_88xx;
 202        halmac_api->halmac_init_system_cfg = halmac_init_system_cfg_88xx;
 203        halmac_api->halmac_init_edca_cfg = halmac_init_edca_cfg_88xx;
 204        halmac_api->halmac_cfg_operation_mode = halmac_cfg_operation_mode_88xx;
 205        halmac_api->halmac_cfg_ch_bw = halmac_cfg_ch_bw_88xx;
 206        halmac_api->halmac_cfg_bw = halmac_cfg_bw_88xx;
 207        halmac_api->halmac_init_wmac_cfg = halmac_init_wmac_cfg_88xx;
 208        halmac_api->halmac_init_mac_cfg = halmac_init_mac_cfg_88xx;
 209        halmac_api->halmac_init_sdio_cfg = halmac_init_sdio_cfg_88xx;
 210        halmac_api->halmac_init_usb_cfg = halmac_init_usb_cfg_88xx;
 211        halmac_api->halmac_init_pcie_cfg = halmac_init_pcie_cfg_88xx;
 212        halmac_api->halmac_deinit_sdio_cfg = halmac_deinit_sdio_cfg_88xx;
 213        halmac_api->halmac_deinit_usb_cfg = halmac_deinit_usb_cfg_88xx;
 214        halmac_api->halmac_deinit_pcie_cfg = halmac_deinit_pcie_cfg_88xx;
 215        halmac_api->halmac_dump_efuse_map = halmac_dump_efuse_map_88xx;
 216        halmac_api->halmac_dump_efuse_map_bt = halmac_dump_efuse_map_bt_88xx;
 217        halmac_api->halmac_write_efuse_bt = halmac_write_efuse_bt_88xx;
 218        halmac_api->halmac_dump_logical_efuse_map =
 219                halmac_dump_logical_efuse_map_88xx;
 220        halmac_api->halmac_pg_efuse_by_map = halmac_pg_efuse_by_map_88xx;
 221        halmac_api->halmac_get_efuse_size = halmac_get_efuse_size_88xx;
 222        halmac_api->halmac_get_efuse_available_size =
 223                halmac_get_efuse_available_size_88xx;
 224        halmac_api->halmac_get_c2h_info = halmac_get_c2h_info_88xx;
 225
 226        halmac_api->halmac_get_logical_efuse_size =
 227                halmac_get_logical_efuse_size_88xx;
 228
 229        halmac_api->halmac_write_logical_efuse =
 230                halmac_write_logical_efuse_88xx;
 231        halmac_api->halmac_read_logical_efuse = halmac_read_logical_efuse_88xx;
 232
 233        halmac_api->halmac_cfg_fwlps_option = halmac_cfg_fwlps_option_88xx;
 234        halmac_api->halmac_cfg_fwips_option = halmac_cfg_fwips_option_88xx;
 235        halmac_api->halmac_enter_wowlan = halmac_enter_wowlan_88xx;
 236        halmac_api->halmac_leave_wowlan = halmac_leave_wowlan_88xx;
 237        halmac_api->halmac_enter_ps = halmac_enter_ps_88xx;
 238        halmac_api->halmac_leave_ps = halmac_leave_ps_88xx;
 239        halmac_api->halmac_h2c_lb = halmac_h2c_lb_88xx;
 240        halmac_api->halmac_debug = halmac_debug_88xx;
 241        halmac_api->halmac_cfg_parameter = halmac_cfg_parameter_88xx;
 242        halmac_api->halmac_update_datapack = halmac_update_datapack_88xx;
 243        halmac_api->halmac_run_datapack = halmac_run_datapack_88xx;
 244        halmac_api->halmac_cfg_drv_info = halmac_cfg_drv_info_88xx;
 245        halmac_api->halmac_send_bt_coex = halmac_send_bt_coex_88xx;
 246        halmac_api->halmac_verify_platform_api =
 247                halmac_verify_platform_api_88xx;
 248        halmac_api->halmac_update_packet = halmac_update_packet_88xx;
 249        halmac_api->halmac_bcn_ie_filter = halmac_bcn_ie_filter_88xx;
 250        halmac_api->halmac_cfg_txbf = halmac_cfg_txbf_88xx;
 251        halmac_api->halmac_cfg_mumimo = halmac_cfg_mumimo_88xx;
 252        halmac_api->halmac_cfg_sounding = halmac_cfg_sounding_88xx;
 253        halmac_api->halmac_del_sounding = halmac_del_sounding_88xx;
 254        halmac_api->halmac_su_bfer_entry_init = halmac_su_bfer_entry_init_88xx;
 255        halmac_api->halmac_su_bfee_entry_init = halmac_su_bfee_entry_init_88xx;
 256        halmac_api->halmac_mu_bfer_entry_init = halmac_mu_bfer_entry_init_88xx;
 257        halmac_api->halmac_mu_bfee_entry_init = halmac_mu_bfee_entry_init_88xx;
 258        halmac_api->halmac_su_bfer_entry_del = halmac_su_bfer_entry_del_88xx;
 259        halmac_api->halmac_su_bfee_entry_del = halmac_su_bfee_entry_del_88xx;
 260        halmac_api->halmac_mu_bfer_entry_del = halmac_mu_bfer_entry_del_88xx;
 261        halmac_api->halmac_mu_bfee_entry_del = halmac_mu_bfee_entry_del_88xx;
 262
 263        halmac_api->halmac_add_ch_info = halmac_add_ch_info_88xx;
 264        halmac_api->halmac_add_extra_ch_info = halmac_add_extra_ch_info_88xx;
 265        halmac_api->halmac_ctrl_ch_switch = halmac_ctrl_ch_switch_88xx;
 266        halmac_api->halmac_p2pps = halmac_p2pps_88xx;
 267        halmac_api->halmac_clear_ch_info = halmac_clear_ch_info_88xx;
 268        halmac_api->halmac_send_general_info = halmac_send_general_info_88xx;
 269
 270        halmac_api->halmac_start_iqk = halmac_start_iqk_88xx;
 271        halmac_api->halmac_ctrl_pwr_tracking = halmac_ctrl_pwr_tracking_88xx;
 272        halmac_api->halmac_psd = halmac_psd_88xx;
 273        halmac_api->halmac_cfg_la_mode = halmac_cfg_la_mode_88xx;
 274        halmac_api->halmac_cfg_rx_fifo_expanding_mode =
 275                halmac_cfg_rx_fifo_expanding_mode_88xx;
 276
 277        halmac_api->halmac_config_security = halmac_config_security_88xx;
 278        halmac_api->halmac_get_used_cam_entry_num =
 279                halmac_get_used_cam_entry_num_88xx;
 280        halmac_api->halmac_read_cam_entry = halmac_read_cam_entry_88xx;
 281        halmac_api->halmac_write_cam = halmac_write_cam_88xx;
 282        halmac_api->halmac_clear_cam_entry = halmac_clear_cam_entry_88xx;
 283
 284        halmac_api->halmac_get_hw_value = halmac_get_hw_value_88xx;
 285        halmac_api->halmac_set_hw_value = halmac_set_hw_value_88xx;
 286
 287        halmac_api->halmac_cfg_drv_rsvd_pg_num =
 288                halmac_cfg_drv_rsvd_pg_num_88xx;
 289        halmac_api->halmac_get_chip_version = halmac_get_chip_version_88xx;
 290
 291        halmac_api->halmac_query_status = halmac_query_status_88xx;
 292        halmac_api->halmac_reset_feature = halmac_reset_feature_88xx;
 293        halmac_api->halmac_check_fw_status = halmac_check_fw_status_88xx;
 294        halmac_api->halmac_dump_fw_dmem = halmac_dump_fw_dmem_88xx;
 295        halmac_api->halmac_cfg_max_dl_size = halmac_cfg_max_dl_size_88xx;
 296
 297        halmac_api->halmac_dump_fifo = halmac_dump_fifo_88xx;
 298        halmac_api->halmac_get_fifo_size = halmac_get_fifo_size_88xx;
 299
 300        halmac_api->halmac_chk_txdesc = halmac_chk_txdesc_88xx;
 301        halmac_api->halmac_dl_drv_rsvd_page = halmac_dl_drv_rsvd_page_88xx;
 302        halmac_api->halmac_cfg_csi_rate = halmac_cfg_csi_rate_88xx;
 303
 304        halmac_api->halmac_sdio_cmd53_4byte = halmac_sdio_cmd53_4byte_88xx;
 305        halmac_api->halmac_txfifo_is_empty = halmac_txfifo_is_empty_88xx;
 306
 307        if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
 308                halmac_api->halmac_cfg_rx_aggregation =
 309                        halmac_cfg_rx_aggregation_88xx_sdio;
 310                halmac_api->halmac_init_interface_cfg =
 311                        halmac_init_sdio_cfg_88xx;
 312                halmac_api->halmac_deinit_interface_cfg =
 313                        halmac_deinit_sdio_cfg_88xx;
 314                halmac_api->halmac_reg_read_8 = halmac_reg_read_8_sdio_88xx;
 315                halmac_api->halmac_reg_write_8 = halmac_reg_write_8_sdio_88xx;
 316                halmac_api->halmac_reg_read_16 = halmac_reg_read_16_sdio_88xx;
 317                halmac_api->halmac_reg_write_16 = halmac_reg_write_16_sdio_88xx;
 318                halmac_api->halmac_reg_read_32 = halmac_reg_read_32_sdio_88xx;
 319                halmac_api->halmac_reg_write_32 = halmac_reg_write_32_sdio_88xx;
 320                halmac_api->halmac_reg_read_indirect_32 =
 321                        halmac_reg_read_indirect_32_sdio_88xx;
 322                halmac_api->halmac_reg_sdio_cmd53_read_n =
 323                        halmac_reg_read_nbyte_sdio_88xx;
 324        } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) {
 325                halmac_api->halmac_cfg_rx_aggregation =
 326                        halmac_cfg_rx_aggregation_88xx_usb;
 327                halmac_api->halmac_init_interface_cfg =
 328                        halmac_init_usb_cfg_88xx;
 329                halmac_api->halmac_deinit_interface_cfg =
 330                        halmac_deinit_usb_cfg_88xx;
 331                halmac_api->halmac_reg_read_8 = halmac_reg_read_8_usb_88xx;
 332                halmac_api->halmac_reg_write_8 = halmac_reg_write_8_usb_88xx;
 333                halmac_api->halmac_reg_read_16 = halmac_reg_read_16_usb_88xx;
 334                halmac_api->halmac_reg_write_16 = halmac_reg_write_16_usb_88xx;
 335                halmac_api->halmac_reg_read_32 = halmac_reg_read_32_usb_88xx;
 336                halmac_api->halmac_reg_write_32 = halmac_reg_write_32_usb_88xx;
 337        } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_PCIE) {
 338                halmac_api->halmac_cfg_rx_aggregation =
 339                        halmac_cfg_rx_aggregation_88xx_pcie;
 340                halmac_api->halmac_init_interface_cfg =
 341                        halmac_init_pcie_cfg_88xx;
 342                halmac_api->halmac_deinit_interface_cfg =
 343                        halmac_deinit_pcie_cfg_88xx;
 344                halmac_api->halmac_reg_read_8 = halmac_reg_read_8_pcie_88xx;
 345                halmac_api->halmac_reg_write_8 = halmac_reg_write_8_pcie_88xx;
 346                halmac_api->halmac_reg_read_16 = halmac_reg_read_16_pcie_88xx;
 347                halmac_api->halmac_reg_write_16 = halmac_reg_write_16_pcie_88xx;
 348                halmac_api->halmac_reg_read_32 = halmac_reg_read_32_pcie_88xx;
 349                halmac_api->halmac_reg_write_32 = halmac_reg_write_32_pcie_88xx;
 350        } else {
 351                pr_err("Set halmac io function Error!!\n");
 352        }
 353
 354        halmac_api->halmac_set_bulkout_num = halmac_set_bulkout_num_88xx;
 355        halmac_api->halmac_get_sdio_tx_addr = halmac_get_sdio_tx_addr_88xx;
 356        halmac_api->halmac_get_usb_bulkout_id = halmac_get_usb_bulkout_id_88xx;
 357        halmac_api->halmac_timer_2s = halmac_timer_2s_88xx;
 358        halmac_api->halmac_fill_txdesc_checksum =
 359                halmac_fill_txdesc_check_sum_88xx;
 360
 361        if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8822B) {
 362                /*mount 8822b function and data*/
 363                halmac_mount_api_8822b(halmac_adapter);
 364
 365        } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8821C) {
 366        } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8814B) {
 367        } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8197F) {
 368        } else {
 369                pr_err("Chip ID undefine!!\n");
 370                return HALMAC_RET_CHIP_NOT_SUPPORT;
 371        }
 372        return HALMAC_RET_SUCCESS;
 373}
 374
 375/**
 376 * halmac_download_firmware_88xx() - download Firmware
 377 * @halmac_adapter : the adapter of halmac
 378 * @hamacl_fw : firmware bin
 379 * @halmac_fw_size : firmware size
 380 * Author : KaiYuan Chang/Ivan Lin
 381 * Return : enum halmac_ret_status
 382 * More details of status code can be found in prototype document
 383 */
 384enum halmac_ret_status
 385halmac_download_firmware_88xx(struct halmac_adapter *halmac_adapter,
 386                              u8 *hamacl_fw, u32 halmac_fw_size)
 387{
 388        u8 value8;
 389        u8 *file_ptr;
 390        u32 dest;
 391        u16 value16;
 392        u32 restore_index = 0;
 393        u32 halmac_h2c_ver = 0, fw_h2c_ver = 0;
 394        u32 iram_pkt_size, dmem_pkt_size, eram_pkt_size = 0;
 395        void *driver_adapter = NULL;
 396        struct halmac_api *halmac_api;
 397        struct halmac_restore_info restore_info[DLFW_RESTORE_REG_NUM_88XX];
 398        u32 temp;
 399
 400        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 401                return HALMAC_RET_ADAPTER_INVALID;
 402
 403        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 404                return HALMAC_RET_API_INVALID;
 405
 406        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DOWNLOAD_FIRMWARE);
 407
 408        driver_adapter = halmac_adapter->driver_adapter;
 409        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 410
 411        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 412                        "%s ==========>\n", __func__);
 413        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 414                        "%s start!!\n", __func__);
 415
 416        if (halmac_fw_size > HALMAC_FW_SIZE_MAX_88XX ||
 417            halmac_fw_size < HALMAC_FWHDR_SIZE_88XX) {
 418                pr_err("FW size error!\n");
 419                return HALMAC_RET_FW_SIZE_ERR;
 420        }
 421
 422        fw_h2c_ver = le32_to_cpu(
 423                *((__le32 *)
 424                  (hamacl_fw + HALMAC_FWHDR_OFFSET_H2C_FORMAT_VER_88XX)));
 425        halmac_h2c_ver = H2C_FORMAT_VERSION;
 426        HALMAC_RT_TRACE(
 427                driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 428                "halmac h2c/c2h format = %x, fw h2c/c2h format = %x!!\n",
 429                halmac_h2c_ver, fw_h2c_ver);
 430        if (fw_h2c_ver != halmac_h2c_ver)
 431                HALMAC_RT_TRACE(
 432                        driver_adapter, HALMAC_MSG_INIT, DBG_WARNING,
 433                        "[WARN]H2C/C2H version between HALMAC and FW is compatible!!\n");
 434
 435        halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE;
 436
 437        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN + 1);
 438        value8 = (u8)(value8 & ~(BIT(2)));
 439        HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1,
 440                           value8); /* Disable CPU reset */
 441
 442        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RSV_CTRL + 1);
 443        value8 = (u8)(value8 & ~(BIT(0)));
 444        HALMAC_REG_WRITE_8(halmac_adapter, REG_RSV_CTRL + 1, value8);
 445
 446        restore_info[restore_index].length = 1;
 447        restore_info[restore_index].mac_register = REG_TXDMA_PQ_MAP + 1;
 448        restore_info[restore_index].value =
 449                HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP + 1);
 450        restore_index++;
 451        value8 = HALMAC_DMA_MAPPING_HIGH << 6;
 452        HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP + 1,
 453                           value8); /* set HIQ to hi priority */
 454
 455        /* DLFW only use HIQ, map HIQ to hi priority */
 456        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI] =
 457                HALMAC_DMA_MAPPING_HIGH;
 458        restore_info[restore_index].length = 1;
 459        restore_info[restore_index].mac_register = REG_CR;
 460        restore_info[restore_index].value =
 461                HALMAC_REG_READ_8(halmac_adapter, REG_CR);
 462        restore_index++;
 463        restore_info[restore_index].length = 4;
 464        restore_info[restore_index].mac_register = REG_H2CQ_CSR;
 465        restore_info[restore_index].value = BIT(31);
 466        restore_index++;
 467        value8 = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN;
 468        HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8);
 469        HALMAC_REG_WRITE_32(halmac_adapter, REG_H2CQ_CSR, BIT(31));
 470
 471        /* Config hi priority queue and public priority queue page number
 472         * (only for DLFW)
 473         */
 474        restore_info[restore_index].length = 2;
 475        restore_info[restore_index].mac_register = REG_FIFOPAGE_INFO_1;
 476        restore_info[restore_index].value =
 477                HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_INFO_1);
 478        restore_index++;
 479        restore_info[restore_index].length = 4;
 480        restore_info[restore_index].mac_register = REG_RQPN_CTRL_2;
 481        restore_info[restore_index].value =
 482                HALMAC_REG_READ_32(halmac_adapter, REG_RQPN_CTRL_2) | BIT(31);
 483        restore_index++;
 484        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_1, 0x200);
 485        HALMAC_REG_WRITE_32(halmac_adapter, REG_RQPN_CTRL_2,
 486                            restore_info[restore_index - 1].value);
 487
 488        if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
 489                HALMAC_REG_READ_32(halmac_adapter, REG_SDIO_FREE_TXPG);
 490                HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_TX_CTRL,
 491                                    0x00000000);
 492        }
 493
 494        halmac_adapter->fw_version.version = le16_to_cpu(
 495                *((__le16 *)(hamacl_fw + HALMAC_FWHDR_OFFSET_VERSION_88XX)));
 496        halmac_adapter->fw_version.sub_version =
 497                *(hamacl_fw + HALMAC_FWHDR_OFFSET_SUBVERSION_88XX);
 498        halmac_adapter->fw_version.sub_index =
 499                *(hamacl_fw + HALMAC_FWHDR_OFFSET_SUBINDEX_88XX);
 500        halmac_adapter->fw_version.h2c_version = (u16)fw_h2c_ver;
 501
 502        dmem_pkt_size = le32_to_cpu(*((__le32 *)(hamacl_fw +
 503                                      HALMAC_FWHDR_OFFSET_DMEM_SIZE_88XX)));
 504        iram_pkt_size = le32_to_cpu(*((__le32 *)(hamacl_fw +
 505                                      HALMAC_FWHDR_OFFSET_IRAM_SIZE_88XX)));
 506        if (((*(hamacl_fw + HALMAC_FWHDR_OFFSET_MEM_USAGE_88XX)) & BIT(4)) != 0)
 507                eram_pkt_size =
 508                     le32_to_cpu(*((__le32 *)(hamacl_fw +
 509                                   HALMAC_FWHDR_OFFSET_ERAM_SIZE_88XX)));
 510
 511        dmem_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 512        iram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 513        if (eram_pkt_size != 0)
 514                eram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 515
 516        if (halmac_fw_size != (HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size +
 517                               iram_pkt_size + eram_pkt_size)) {
 518                pr_err("FW size mismatch the real fw size!\n");
 519                goto DLFW_FAIL;
 520        }
 521
 522        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR + 1);
 523        restore_info[restore_index].length = 1;
 524        restore_info[restore_index].mac_register = REG_CR + 1;
 525        restore_info[restore_index].value = value8;
 526        restore_index++;
 527        value8 = (u8)(value8 | BIT(0));
 528        HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1,
 529                           value8); /* Enable SW TX beacon */
 530
 531        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL);
 532        restore_info[restore_index].length = 1;
 533        restore_info[restore_index].mac_register = REG_BCN_CTRL;
 534        restore_info[restore_index].value = value8;
 535        restore_index++;
 536        value8 = (u8)((value8 & (~BIT(3))) | BIT(4));
 537        HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL,
 538                           value8); /* Disable beacon related functions */
 539
 540        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2);
 541        restore_info[restore_index].length = 1;
 542        restore_info[restore_index].mac_register = REG_FWHW_TXQ_CTRL + 2;
 543        restore_info[restore_index].value = value8;
 544        restore_index++;
 545        value8 = (u8)(value8 & ~(BIT(6)));
 546        HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2,
 547                           value8); /* Disable ptcl tx bcnq */
 548
 549        restore_info[restore_index].length = 2;
 550        restore_info[restore_index].mac_register = REG_FIFOPAGE_CTRL_2;
 551        restore_info[restore_index].value =
 552                HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_CTRL_2) |
 553                BIT(15);
 554        restore_index++;
 555        value16 = 0x8000;
 556        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
 557                            value16); /* Set beacon header to  0 */
 558
 559        value16 = (u16)(HALMAC_REG_READ_16(halmac_adapter, REG_MCUFW_CTRL) &
 560                        0x3800);
 561        value16 |= BIT(0);
 562        HALMAC_REG_WRITE_16(halmac_adapter, REG_MCUFW_CTRL,
 563                            value16); /* MCU/FW setting */
 564
 565        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CPU_DMEM_CON + 2);
 566        value8 &= ~(BIT(0));
 567        HALMAC_REG_WRITE_8(halmac_adapter, REG_CPU_DMEM_CON + 2, value8);
 568        value8 |= BIT(0);
 569        HALMAC_REG_WRITE_8(halmac_adapter, REG_CPU_DMEM_CON + 2, value8);
 570
 571        /* Download to DMEM */
 572        file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX;
 573        temp = le32_to_cpu(*((__le32 *)(hamacl_fw +
 574                           HALMAC_FWHDR_OFFSET_DMEM_ADDR_88XX))) &
 575                           ~(BIT(31));
 576        if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, temp,
 577                                    dmem_pkt_size) != HALMAC_RET_SUCCESS)
 578                goto DLFW_END;
 579
 580        /* Download to IMEM */
 581        file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size;
 582        temp = le32_to_cpu(*((__le32 *)(hamacl_fw +
 583                           HALMAC_FWHDR_OFFSET_IRAM_ADDR_88XX))) &
 584                           ~(BIT(31));
 585        if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, temp,
 586                                    iram_pkt_size) != HALMAC_RET_SUCCESS)
 587                goto DLFW_END;
 588
 589        /* Download to EMEM */
 590        if (eram_pkt_size != 0) {
 591                file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size +
 592                           iram_pkt_size;
 593                dest = le32_to_cpu((*((__le32 *)(hamacl_fw +
 594                                    HALMAC_FWHDR_OFFSET_EMEM_ADDR_88XX)))) &
 595                                   ~(BIT(31));
 596                if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, dest,
 597                                            eram_pkt_size) !=
 598                    HALMAC_RET_SUCCESS)
 599                        goto DLFW_END;
 600        }
 601
 602        halmac_init_offload_feature_state_machine_88xx(halmac_adapter);
 603DLFW_END:
 604
 605        halmac_restore_mac_register_88xx(halmac_adapter, restore_info,
 606                                         DLFW_RESTORE_REG_NUM_88XX);
 607
 608        if (halmac_dlfw_end_flow_88xx(halmac_adapter) != HALMAC_RET_SUCCESS)
 609                goto DLFW_FAIL;
 610
 611        halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_DONE;
 612
 613        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 614                        "%s <==========\n", __func__);
 615
 616        return HALMAC_RET_SUCCESS;
 617
 618DLFW_FAIL:
 619
 620        /* Disable FWDL_EN */
 621        HALMAC_REG_WRITE_8(
 622                halmac_adapter, REG_MCUFW_CTRL,
 623                (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) &
 624                     ~(BIT(0))));
 625
 626        return HALMAC_RET_DLFW_FAIL;
 627}
 628
 629/**
 630 * halmac_free_download_firmware_88xx() - download specific memory firmware
 631 * @halmac_adapter
 632 * @dlfw_mem : memory selection
 633 * @hamacl_fw : firmware bin
 634 * @halmac_fw_size : firmware size
 635 * Author : KaiYuan Chang/Ivan Lin
 636 * Return : enum halmac_ret_status
 637 */
 638enum halmac_ret_status
 639halmac_free_download_firmware_88xx(struct halmac_adapter *halmac_adapter,
 640                                   enum halmac_dlfw_mem dlfw_mem, u8 *hamacl_fw,
 641                                   u32 halmac_fw_size)
 642{
 643        u8 tx_pause_backup;
 644        u8 *file_ptr;
 645        u32 dest;
 646        u16 bcn_head_backup;
 647        u32 iram_pkt_size, dmem_pkt_size, eram_pkt_size = 0;
 648        void *driver_adapter = NULL;
 649        enum halmac_ret_status status = HALMAC_RET_DLFW_FAIL;
 650        struct halmac_api *halmac_api;
 651
 652        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 653                return HALMAC_RET_ADAPTER_INVALID;
 654
 655        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 656                return HALMAC_RET_API_INVALID;
 657
 658        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 659                return HALMAC_RET_NO_DLFW;
 660
 661        driver_adapter = halmac_adapter->driver_adapter;
 662        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 663
 664        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 665                        "[TRACE]%s ==========>\n", __func__);
 666
 667        if (halmac_fw_size > HALMAC_FW_SIZE_MAX_88XX ||
 668            halmac_fw_size < HALMAC_FWHDR_SIZE_88XX) {
 669                pr_err("[ERR]FW size error!\n");
 670                return HALMAC_RET_FW_SIZE_ERR;
 671        }
 672
 673        dmem_pkt_size =
 674            le32_to_cpu(*(__le32 *)(hamacl_fw +
 675                                    HALMAC_FWHDR_OFFSET_DMEM_SIZE_88XX));
 676        iram_pkt_size =
 677            le32_to_cpu(*(__le32 *)(hamacl_fw +
 678                                    HALMAC_FWHDR_OFFSET_IRAM_SIZE_88XX));
 679        if (((*(hamacl_fw + HALMAC_FWHDR_OFFSET_MEM_USAGE_88XX)) & BIT(4)) != 0)
 680                eram_pkt_size =
 681                  le32_to_cpu(*(__le32 *)(hamacl_fw +
 682                                          HALMAC_FWHDR_OFFSET_ERAM_SIZE_88XX));
 683
 684        dmem_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 685        iram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 686        if (eram_pkt_size != 0)
 687                eram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX;
 688
 689        if (halmac_fw_size != (HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size +
 690                               iram_pkt_size + eram_pkt_size)) {
 691                pr_err("[ERR]FW size mismatch the real fw size!\n");
 692                return HALMAC_RET_DLFW_FAIL;
 693        }
 694
 695        tx_pause_backup = HALMAC_REG_READ_8(halmac_adapter, REG_TXPAUSE);
 696        HALMAC_REG_WRITE_8(halmac_adapter, REG_TXPAUSE,
 697                           tx_pause_backup | BIT(7));
 698
 699        bcn_head_backup =
 700                HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_CTRL_2) |
 701                BIT(15);
 702        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, 0x8000);
 703
 704        if (eram_pkt_size != 0) {
 705                file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size +
 706                           iram_pkt_size;
 707                dest = le32_to_cpu(*((__le32 *)(hamacl_fw +
 708                                   HALMAC_FWHDR_OFFSET_EMEM_ADDR_88XX))) &
 709                                   ~(BIT(31));
 710                status = halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, dest,
 711                                                 eram_pkt_size);
 712                if (status != HALMAC_RET_SUCCESS)
 713                        goto DL_FREE_FW_END;
 714        }
 715
 716        status = halmac_free_dl_fw_end_flow_88xx(halmac_adapter);
 717
 718DL_FREE_FW_END:
 719        HALMAC_REG_WRITE_8(halmac_adapter, REG_TXPAUSE, tx_pause_backup);
 720        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
 721                            bcn_head_backup);
 722
 723        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 724                        "[TRACE]%s <==========\n", __func__);
 725
 726        return status;
 727}
 728
 729/**
 730 * halmac_get_fw_version_88xx() - get FW version
 731 * @halmac_adapter : the adapter of halmac
 732 * @fw_version : fw version info
 733 * Author : Ivan Lin
 734 * Return : enum halmac_ret_status
 735 * More details of status code can be found in prototype document
 736 */
 737enum halmac_ret_status
 738halmac_get_fw_version_88xx(struct halmac_adapter *halmac_adapter,
 739                           struct halmac_fw_version *fw_version)
 740{
 741        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 742                return HALMAC_RET_ADAPTER_INVALID;
 743
 744        if (halmac_adapter->halmac_state.dlfw_state == 0)
 745                return HALMAC_RET_DLFW_FAIL;
 746
 747        fw_version->version = halmac_adapter->fw_version.version;
 748        fw_version->sub_version = halmac_adapter->fw_version.sub_version;
 749        fw_version->sub_index = halmac_adapter->fw_version.sub_index;
 750
 751        return HALMAC_RET_SUCCESS;
 752}
 753
 754/**
 755 * halmac_cfg_mac_addr_88xx() - config mac address
 756 * @halmac_adapter : the adapter of halmac
 757 * @halmac_port :0 for port0, 1 for port1, 2 for port2, 3 for port3, 4 for port4
 758 * @hal_address : mac address
 759 * Author : KaiYuan Chang/Ivan Lin
 760 * Return : enum halmac_ret_status
 761 * More details of status code can be found in prototype document
 762 */
 763enum halmac_ret_status
 764halmac_cfg_mac_addr_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port,
 765                         union halmac_wlan_addr *hal_address)
 766{
 767        u16 mac_address_H;
 768        u32 mac_address_L;
 769        void *driver_adapter = NULL;
 770        struct halmac_api *halmac_api;
 771
 772        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 773                return HALMAC_RET_ADAPTER_INVALID;
 774
 775        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 776                return HALMAC_RET_API_INVALID;
 777
 778        driver_adapter = halmac_adapter->driver_adapter;
 779        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 780
 781        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 782                        "[TRACE]%s ==========>\n", __func__);
 783
 784        if (halmac_port >= HALMAC_PORTIDMAX) {
 785                pr_err("[ERR]port index > 5\n");
 786                return HALMAC_RET_PORT_NOT_SUPPORT;
 787        }
 788
 789        mac_address_L = le32_to_cpu(hal_address->address_l_h.le_address_low);
 790        mac_address_H = le16_to_cpu(hal_address->address_l_h.le_address_high);
 791
 792        halmac_adapter->hal_mac_addr[halmac_port].address_l_h.address_low =
 793                mac_address_L;
 794        halmac_adapter->hal_mac_addr[halmac_port].address_l_h.address_high =
 795                mac_address_H;
 796
 797        switch (halmac_port) {
 798        case HALMAC_PORTID0:
 799                HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID, mac_address_L);
 800                HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID + 4,
 801                                    mac_address_H);
 802                break;
 803
 804        case HALMAC_PORTID1:
 805                HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID1, mac_address_L);
 806                HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID1 + 4,
 807                                    mac_address_H);
 808                break;
 809
 810        case HALMAC_PORTID2:
 811                HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID2, mac_address_L);
 812                HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID2 + 4,
 813                                    mac_address_H);
 814                break;
 815
 816        case HALMAC_PORTID3:
 817                HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID3, mac_address_L);
 818                HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID3 + 4,
 819                                    mac_address_H);
 820                break;
 821
 822        case HALMAC_PORTID4:
 823                HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID4, mac_address_L);
 824                HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID4 + 4,
 825                                    mac_address_H);
 826                break;
 827
 828        default:
 829
 830                break;
 831        }
 832
 833        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 834                        "[TRACE]%s <==========\n", __func__);
 835
 836        return HALMAC_RET_SUCCESS;
 837}
 838
 839/**
 840 * halmac_cfg_bssid_88xx() - config BSSID
 841 * @halmac_adapter : the adapter of halmac
 842 * @halmac_port :0 for port0, 1 for port1, 2 for port2, 3 for port3, 4 for port4
 843 * @hal_address : bssid
 844 * Author : KaiYuan Chang/Ivan Lin
 845 * Return : enum halmac_ret_status
 846 * More details of status code can be found in prototype document
 847 */
 848enum halmac_ret_status
 849halmac_cfg_bssid_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port,
 850                      union halmac_wlan_addr *hal_address)
 851{
 852        u16 bssid_address_H;
 853        u32 bssid_address_L;
 854        void *driver_adapter = NULL;
 855        struct halmac_api *halmac_api;
 856
 857        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 858                return HALMAC_RET_ADAPTER_INVALID;
 859
 860        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 861                return HALMAC_RET_API_INVALID;
 862
 863        driver_adapter = halmac_adapter->driver_adapter;
 864        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 865
 866        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 867                        "[TRACE]%s ==========>\n", __func__);
 868
 869        if (halmac_port >= HALMAC_PORTIDMAX) {
 870                pr_err("[ERR]port index > 5\n");
 871                return HALMAC_RET_PORT_NOT_SUPPORT;
 872        }
 873
 874        bssid_address_L = le32_to_cpu(hal_address->address_l_h.le_address_low);
 875        bssid_address_H = le16_to_cpu(hal_address->address_l_h.le_address_high);
 876
 877        halmac_adapter->hal_bss_addr[halmac_port].address_l_h.address_low =
 878                bssid_address_L;
 879        halmac_adapter->hal_bss_addr[halmac_port].address_l_h.address_high =
 880                bssid_address_H;
 881
 882        switch (halmac_port) {
 883        case HALMAC_PORTID0:
 884                HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID, bssid_address_L);
 885                HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID + 4,
 886                                    bssid_address_H);
 887                break;
 888
 889        case HALMAC_PORTID1:
 890                HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID1,
 891                                    bssid_address_L);
 892                HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID1 + 4,
 893                                    bssid_address_H);
 894                break;
 895
 896        case HALMAC_PORTID2:
 897                HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID2,
 898                                    bssid_address_L);
 899                HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID2 + 4,
 900                                    bssid_address_H);
 901                break;
 902
 903        case HALMAC_PORTID3:
 904                HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID3,
 905                                    bssid_address_L);
 906                HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID3 + 4,
 907                                    bssid_address_H);
 908                break;
 909
 910        case HALMAC_PORTID4:
 911                HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID4,
 912                                    bssid_address_L);
 913                HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID4 + 4,
 914                                    bssid_address_H);
 915                break;
 916
 917        default:
 918
 919                break;
 920        }
 921
 922        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 923                        "[TRACE]%s <==========\n", __func__);
 924
 925        return HALMAC_RET_SUCCESS;
 926}
 927
 928/**
 929 * halmac_cfg_multicast_addr_88xx() - config multicast address
 930 * @halmac_adapter : the adapter of halmac
 931 * @hal_address : multicast address
 932 * Author : KaiYuan Chang/Ivan Lin
 933 * Return : enum halmac_ret_status
 934 * More details of status code can be found in prototype document
 935 */
 936enum halmac_ret_status
 937halmac_cfg_multicast_addr_88xx(struct halmac_adapter *halmac_adapter,
 938                               union halmac_wlan_addr *hal_address)
 939{
 940        u16 address_H;
 941        u32 address_L;
 942        void *driver_adapter = NULL;
 943        struct halmac_api *halmac_api;
 944
 945        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 946                return HALMAC_RET_ADAPTER_INVALID;
 947
 948        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 949                return HALMAC_RET_API_INVALID;
 950
 951        halmac_api_record_id_88xx(halmac_adapter,
 952                                  HALMAC_API_CFG_MULTICAST_ADDR);
 953
 954        driver_adapter = halmac_adapter->driver_adapter;
 955        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 956
 957        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 958                        "%s ==========>\n", __func__);
 959
 960        address_L = le32_to_cpu(hal_address->address_l_h.le_address_low);
 961        address_H = le16_to_cpu(hal_address->address_l_h.le_address_high);
 962
 963        HALMAC_REG_WRITE_32(halmac_adapter, REG_MAR, address_L);
 964        HALMAC_REG_WRITE_16(halmac_adapter, REG_MAR + 4, address_H);
 965
 966        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
 967                        "%s <==========\n", __func__);
 968
 969        return HALMAC_RET_SUCCESS;
 970}
 971
 972/**
 973 * halmac_pre_init_system_cfg_88xx() - pre-init system config
 974 * @halmac_adapter : the adapter of halmac
 975 * Author : KaiYuan Chang/Ivan Lin
 976 * Return : enum halmac_ret_status
 977 * More details of status code can be found in prototype document
 978 */
 979enum halmac_ret_status
 980halmac_pre_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter)
 981{
 982        u32 value32, counter;
 983        void *driver_adapter = NULL;
 984        struct halmac_api *halmac_api;
 985        bool enable_bb;
 986
 987        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 988                return HALMAC_RET_ADAPTER_INVALID;
 989
 990        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
 991                return HALMAC_RET_API_INVALID;
 992
 993        halmac_api_record_id_88xx(halmac_adapter,
 994                                  HALMAC_API_PRE_INIT_SYSTEM_CFG);
 995
 996        driver_adapter = halmac_adapter->driver_adapter;
 997        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 998
 999        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1000                        "halmac_pre_init_system_cfg ==========>\n");
1001
1002        if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
1003                HALMAC_REG_WRITE_8(
1004                        halmac_adapter, REG_SDIO_HSUS_CTRL,
1005                        HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HSUS_CTRL) &
1006                                ~(BIT(0)));
1007                counter = 10000;
1008                while (!(HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HSUS_CTRL) &
1009                         0x02)) {
1010                        counter--;
1011                        if (counter == 0)
1012                                return HALMAC_RET_SDIO_LEAVE_SUSPEND_FAIL;
1013                }
1014        } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) {
1015                if (HALMAC_REG_READ_8(halmac_adapter, REG_SYS_CFG2 + 3) ==
1016                    0x20) /* usb3.0 */
1017                        HALMAC_REG_WRITE_8(
1018                                halmac_adapter, 0xFE5B,
1019                                HALMAC_REG_READ_8(halmac_adapter, 0xFE5B) |
1020                                        BIT(4));
1021        }
1022
1023        /* Config PIN Mux */
1024        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_PAD_CTRL1);
1025        value32 = value32 & (~(BIT(28) | BIT(29)));
1026        value32 = value32 | BIT(28) | BIT(29);
1027        HALMAC_REG_WRITE_32(halmac_adapter, REG_PAD_CTRL1, value32);
1028
1029        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_LED_CFG);
1030        value32 = value32 & (~(BIT(25) | BIT(26)));
1031        HALMAC_REG_WRITE_32(halmac_adapter, REG_LED_CFG, value32);
1032
1033        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_GPIO_MUXCFG);
1034        value32 = value32 & (~(BIT(2)));
1035        value32 = value32 | BIT(2);
1036        HALMAC_REG_WRITE_32(halmac_adapter, REG_GPIO_MUXCFG, value32);
1037
1038        enable_bb = false;
1039        halmac_set_hw_value_88xx(halmac_adapter, HALMAC_HW_EN_BB_RF,
1040                                 &enable_bb);
1041
1042        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1043                        "halmac_pre_init_system_cfg <==========\n");
1044
1045        return HALMAC_RET_SUCCESS;
1046}
1047
1048/**
1049 * halmac_init_system_cfg_88xx() -  init system config
1050 * @halmac_adapter : the adapter of halmac
1051 * Author : KaiYuan Chang/Ivan Lin
1052 * Return : enum halmac_ret_status
1053 * More details of status code can be found in prototype document
1054 */
1055enum halmac_ret_status
1056halmac_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter)
1057{
1058        void *driver_adapter = NULL;
1059        struct halmac_api *halmac_api;
1060
1061        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1062                return HALMAC_RET_ADAPTER_INVALID;
1063
1064        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1065                return HALMAC_RET_API_INVALID;
1066
1067        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_SYSTEM_CFG);
1068
1069        driver_adapter = halmac_adapter->driver_adapter;
1070        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1071
1072        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1073                        "halmac_init_system_cfg ==========>\n");
1074
1075        HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1,
1076                           HALMAC_FUNCTION_ENABLE_88XX);
1077        HALMAC_REG_WRITE_32(
1078                halmac_adapter, REG_SYS_SDIO_CTRL,
1079                (u32)(HALMAC_REG_READ_32(halmac_adapter, REG_SYS_SDIO_CTRL) |
1080                      BIT_LTE_MUX_CTRL_PATH));
1081        HALMAC_REG_WRITE_32(
1082                halmac_adapter, REG_CPU_DMEM_CON,
1083                (u32)(HALMAC_REG_READ_32(halmac_adapter, REG_CPU_DMEM_CON) |
1084                      BIT_WL_PLATFORM_RST));
1085
1086        /* halmac_api->halmac_init_h2c(halmac_adapter); */
1087
1088        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1089                        "halmac_init_system_cfg <==========\n");
1090
1091        return HALMAC_RET_SUCCESS;
1092}
1093
1094/**
1095 * halmac_init_edca_cfg_88xx() - init EDCA config
1096 * @halmac_adapter : the adapter of halmac
1097 * Author : KaiYuan Chang/Ivan Lin
1098 * Return : enum halmac_ret_status
1099 * More details of status code can be found in prototype document
1100 */
1101enum halmac_ret_status
1102halmac_init_edca_cfg_88xx(struct halmac_adapter *halmac_adapter)
1103{
1104        u8 value8;
1105        u32 value32;
1106        void *driver_adapter = NULL;
1107        struct halmac_api *halmac_api;
1108
1109        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1110                return HALMAC_RET_ADAPTER_INVALID;
1111
1112        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1113                return HALMAC_RET_API_INVALID;
1114
1115        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_EDCA_CFG);
1116
1117        driver_adapter = halmac_adapter->driver_adapter;
1118        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1119
1120        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1121                        "%s ==========>\n", __func__);
1122
1123        /* Clear TX pause */
1124        HALMAC_REG_WRITE_16(halmac_adapter, REG_TXPAUSE, 0x0000);
1125
1126        HALMAC_REG_WRITE_8(halmac_adapter, REG_SLOT, HALMAC_SLOT_TIME_88XX);
1127        HALMAC_REG_WRITE_8(halmac_adapter, REG_PIFS, HALMAC_PIFS_TIME_88XX);
1128        value32 = HALMAC_SIFS_CCK_CTX_88XX |
1129                  (HALMAC_SIFS_OFDM_CTX_88XX << BIT_SHIFT_SIFS_OFDM_CTX) |
1130                  (HALMAC_SIFS_CCK_TRX_88XX << BIT_SHIFT_SIFS_CCK_TRX) |
1131                  (HALMAC_SIFS_OFDM_TRX_88XX << BIT_SHIFT_SIFS_OFDM_TRX);
1132        HALMAC_REG_WRITE_32(halmac_adapter, REG_SIFS, value32);
1133
1134        HALMAC_REG_WRITE_32(
1135                halmac_adapter, REG_EDCA_VO_PARAM,
1136                HALMAC_REG_READ_32(halmac_adapter, REG_EDCA_VO_PARAM) & 0xFFFF);
1137        HALMAC_REG_WRITE_16(halmac_adapter, REG_EDCA_VO_PARAM + 2,
1138                            HALMAC_VO_TXOP_LIMIT_88XX);
1139        HALMAC_REG_WRITE_16(halmac_adapter, REG_EDCA_VI_PARAM + 2,
1140                            HALMAC_VI_TXOP_LIMIT_88XX);
1141
1142        HALMAC_REG_WRITE_32(halmac_adapter, REG_RD_NAV_NXT,
1143                            HALMAC_RDG_NAV_88XX | (HALMAC_TXOP_NAV_88XX << 16));
1144        HALMAC_REG_WRITE_16(halmac_adapter, REG_RXTSF_OFFSET_CCK,
1145                            HALMAC_CCK_RX_TSF_88XX |
1146                                    (HALMAC_OFDM_RX_TSF_88XX) << 8);
1147
1148        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RD_CTRL + 1);
1149        value8 |=
1150                (BIT_VOQ_RD_INIT_EN | BIT_VIQ_RD_INIT_EN | BIT_BEQ_RD_INIT_EN);
1151        HALMAC_REG_WRITE_8(halmac_adapter, REG_RD_CTRL + 1, value8);
1152
1153        /* Set beacon cotnrol - enable TSF and other related functions */
1154        HALMAC_REG_WRITE_8(
1155                halmac_adapter, REG_BCN_CTRL,
1156                (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL) |
1157                     BIT_EN_BCN_FUNCTION));
1158
1159        /* Set send beacon related registers */
1160        HALMAC_REG_WRITE_32(halmac_adapter, REG_TBTT_PROHIBIT,
1161                            HALMAC_TBTT_PROHIBIT_88XX |
1162                                    (HALMAC_TBTT_HOLD_TIME_88XX
1163                                     << BIT_SHIFT_TBTT_HOLD_TIME_AP));
1164        HALMAC_REG_WRITE_8(halmac_adapter, REG_DRVERLYINT,
1165                           HALMAC_DRIVER_EARLY_INT_88XX);
1166        HALMAC_REG_WRITE_8(halmac_adapter, REG_BCNDMATIM,
1167                           HALMAC_BEACON_DMA_TIM_88XX);
1168
1169        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1170                        "%s <==========\n", __func__);
1171
1172        return HALMAC_RET_SUCCESS;
1173}
1174
1175/**
1176 * halmac_init_wmac_cfg_88xx() - init wmac config
1177 * @halmac_adapter : the adapter of halmac
1178 * Author : KaiYuan Chang/Ivan Lin
1179 * Return : enum halmac_ret_status
1180 * More details of status code can be found in prototype document
1181 */
1182enum halmac_ret_status
1183halmac_init_wmac_cfg_88xx(struct halmac_adapter *halmac_adapter)
1184{
1185        void *driver_adapter = NULL;
1186        struct halmac_api *halmac_api;
1187
1188        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1189                return HALMAC_RET_ADAPTER_INVALID;
1190
1191        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1192                return HALMAC_RET_API_INVALID;
1193
1194        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_WMAC_CFG);
1195
1196        driver_adapter = halmac_adapter->driver_adapter;
1197        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1198
1199        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1200                        "%s ==========>\n", __func__);
1201
1202        HALMAC_REG_WRITE_32(halmac_adapter, REG_RXFLTMAP0,
1203                            HALMAC_RX_FILTER0_88XX);
1204        HALMAC_REG_WRITE_16(halmac_adapter, REG_RXFLTMAP,
1205                            HALMAC_RX_FILTER_88XX);
1206
1207        HALMAC_REG_WRITE_32(halmac_adapter, REG_RCR, HALMAC_RCR_CONFIG_88XX);
1208
1209        HALMAC_REG_WRITE_8(
1210                halmac_adapter, REG_TCR + 1,
1211                (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_TCR + 1) | 0x30));
1212        HALMAC_REG_WRITE_8(halmac_adapter, REG_TCR + 2, 0x30);
1213        HALMAC_REG_WRITE_8(halmac_adapter, REG_TCR + 1, 0x00);
1214
1215        HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 8,
1216                            0x30810041);
1217        HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 4,
1218                            0x50802080);
1219
1220        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1221                        "%s <==========\n", __func__);
1222
1223        return HALMAC_RET_SUCCESS;
1224}
1225
1226/**
1227 * halmac_init_mac_cfg_88xx() - config page1~page7 register
1228 * @halmac_adapter : the adapter of halmac
1229 * @mode : trx mode
1230 * Author : KaiYuan Chang/Ivan Lin
1231 * Return : enum halmac_ret_status
1232 * More details of status code can be found in prototype document
1233 */
1234enum halmac_ret_status
1235halmac_init_mac_cfg_88xx(struct halmac_adapter *halmac_adapter,
1236                         enum halmac_trx_mode mode)
1237{
1238        void *driver_adapter = NULL;
1239        struct halmac_api *halmac_api;
1240        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1241
1242        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1243                return HALMAC_RET_ADAPTER_INVALID;
1244
1245        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1246                return HALMAC_RET_API_INVALID;
1247
1248        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_MAC_CFG);
1249
1250        driver_adapter = halmac_adapter->driver_adapter;
1251        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1252
1253        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1254                        "%s ==========>mode = %d\n", __func__,
1255                        mode);
1256
1257        status = halmac_api->halmac_init_trx_cfg(halmac_adapter, mode);
1258        if (status != HALMAC_RET_SUCCESS) {
1259                pr_err("halmac_init_trx_cfg error = %x\n", status);
1260                return status;
1261        }
1262        status = halmac_api->halmac_init_protocol_cfg(halmac_adapter);
1263        if (status != HALMAC_RET_SUCCESS) {
1264                pr_err("halmac_init_protocol_cfg_88xx error = %x\n", status);
1265                return status;
1266        }
1267
1268        status = halmac_init_edca_cfg_88xx(halmac_adapter);
1269        if (status != HALMAC_RET_SUCCESS) {
1270                pr_err("halmac_init_edca_cfg_88xx error = %x\n", status);
1271                return status;
1272        }
1273
1274        status = halmac_init_wmac_cfg_88xx(halmac_adapter);
1275        if (status != HALMAC_RET_SUCCESS) {
1276                pr_err("halmac_init_wmac_cfg_88xx error = %x\n", status);
1277                return status;
1278        }
1279        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1280                        "%s <==========\n", __func__);
1281
1282        return status;
1283}
1284
1285/**
1286 * halmac_cfg_operation_mode_88xx() - config operation mode
1287 * @halmac_adapter : the adapter of halmac
1288 * @wireless_mode : 802.11 standard(b/g/n/ac)
1289 * Author : KaiYuan Chang/Ivan Lin
1290 * Return : enum halmac_ret_status
1291 * More details of status code can be found in prototype document
1292 */
1293enum halmac_ret_status
1294halmac_cfg_operation_mode_88xx(struct halmac_adapter *halmac_adapter,
1295                               enum halmac_wireless_mode wireless_mode)
1296{
1297        void *driver_adapter = NULL;
1298        enum halmac_wireless_mode wireless_mode_local =
1299                HALMAC_WIRELESS_MODE_UNDEFINE;
1300
1301        wireless_mode_local = wireless_mode;
1302
1303        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1304                return HALMAC_RET_ADAPTER_INVALID;
1305
1306        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1307                return HALMAC_RET_API_INVALID;
1308
1309        halmac_api_record_id_88xx(halmac_adapter,
1310                                  HALMAC_API_CFG_OPERATION_MODE);
1311
1312        driver_adapter = halmac_adapter->driver_adapter;
1313
1314        HALMAC_RT_TRACE(
1315                driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1316                "%s ==========>wireless_mode = %d\n", __func__,
1317                wireless_mode);
1318
1319        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1320                        "%s <==========\n", __func__);
1321
1322        return HALMAC_RET_SUCCESS;
1323}
1324
1325/**
1326 * halmac_cfg_ch_bw_88xx() - config channel & bandwidth
1327 * @halmac_adapter : the adapter of halmac
1328 * @channel : WLAN channel, support 2.4G & 5G
1329 * @pri_ch_idx : primary channel index, idx1, idx2, idx3, idx4
1330 * @bw : band width, 20, 40, 80, 160, 5 ,10
1331 * Author : KaiYuan Chang
1332 * Return : enum halmac_ret_status
1333 * More details of status code can be found in prototype document
1334 */
1335enum halmac_ret_status
1336halmac_cfg_ch_bw_88xx(struct halmac_adapter *halmac_adapter, u8 channel,
1337                      enum halmac_pri_ch_idx pri_ch_idx, enum halmac_bw bw)
1338{
1339        void *driver_adapter = NULL;
1340        struct halmac_api *halmac_api;
1341
1342        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1343                return HALMAC_RET_ADAPTER_INVALID;
1344
1345        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1346                return HALMAC_RET_API_INVALID;
1347
1348        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW);
1349
1350        driver_adapter = halmac_adapter->driver_adapter;
1351        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1352
1353        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1354                        "%s ==========>ch = %d, idx=%d, bw=%d\n", __func__,
1355                        channel, pri_ch_idx, bw);
1356
1357        halmac_cfg_pri_ch_idx_88xx(halmac_adapter, pri_ch_idx);
1358
1359        halmac_cfg_bw_88xx(halmac_adapter, bw);
1360
1361        halmac_cfg_ch_88xx(halmac_adapter, channel);
1362
1363        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1364                        "%s <==========\n", __func__);
1365
1366        return HALMAC_RET_SUCCESS;
1367}
1368
1369enum halmac_ret_status halmac_cfg_ch_88xx(struct halmac_adapter *halmac_adapter,
1370                                          u8 channel)
1371{
1372        u8 value8;
1373        void *driver_adapter = NULL;
1374        struct halmac_api *halmac_api;
1375
1376        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1377                return HALMAC_RET_ADAPTER_INVALID;
1378
1379        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1380                return HALMAC_RET_API_INVALID;
1381
1382        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW);
1383
1384        driver_adapter = halmac_adapter->driver_adapter;
1385        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1386
1387        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1388                        "%s ==========>ch = %d\n", __func__, channel);
1389
1390        value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CCK_CHECK);
1391        value8 = value8 & (~(BIT(7)));
1392
1393        if (channel > 35)
1394                value8 = value8 | BIT(7);
1395
1396        HALMAC_REG_WRITE_8(halmac_adapter, REG_CCK_CHECK, value8);
1397
1398        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1399                        "%s <==========\n", __func__);
1400
1401        return HALMAC_RET_SUCCESS;
1402}
1403
1404enum halmac_ret_status
1405halmac_cfg_pri_ch_idx_88xx(struct halmac_adapter *halmac_adapter,
1406                           enum halmac_pri_ch_idx pri_ch_idx)
1407{
1408        u8 txsc_40 = 0, txsc_20 = 0;
1409        void *driver_adapter = NULL;
1410        struct halmac_api *halmac_api;
1411
1412        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1413                return HALMAC_RET_ADAPTER_INVALID;
1414
1415        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1416                return HALMAC_RET_API_INVALID;
1417
1418        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW);
1419
1420        driver_adapter = halmac_adapter->driver_adapter;
1421        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1422
1423        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1424                        "%s ==========> idx=%d\n", __func__,
1425                        pri_ch_idx);
1426
1427        txsc_20 = pri_ch_idx;
1428        if (txsc_20 == HALMAC_CH_IDX_1 || txsc_20 == HALMAC_CH_IDX_3)
1429                txsc_40 = 9;
1430        else
1431                txsc_40 = 10;
1432
1433        HALMAC_REG_WRITE_8(halmac_adapter, REG_DATA_SC,
1434                           BIT_TXSC_20M(txsc_20) | BIT_TXSC_40M(txsc_40));
1435
1436        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1437                        "%s <==========\n", __func__);
1438
1439        return HALMAC_RET_SUCCESS;
1440}
1441
1442/**
1443 * halmac_cfg_bw_88xx() - config bandwidth
1444 * @halmac_adapter : the adapter of halmac
1445 * @bw : band width, 20, 40, 80, 160, 5 ,10
1446 * Author : KaiYuan Chang
1447 * Return : enum halmac_ret_status
1448 * More details of status code can be found in prototype document
1449 */
1450enum halmac_ret_status halmac_cfg_bw_88xx(struct halmac_adapter *halmac_adapter,
1451                                          enum halmac_bw bw)
1452{
1453        u32 value32;
1454        void *driver_adapter = NULL;
1455        struct halmac_api *halmac_api;
1456
1457        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1458                return HALMAC_RET_ADAPTER_INVALID;
1459
1460        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1461                return HALMAC_RET_API_INVALID;
1462
1463        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_BW);
1464
1465        driver_adapter = halmac_adapter->driver_adapter;
1466        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
1467
1468        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1469                        "%s ==========>bw=%d\n", __func__, bw);
1470
1471        /* RF mode */
1472        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_WMAC_TRXPTCL_CTL);
1473        value32 = value32 & (~(BIT(7) | BIT(8)));
1474
1475        switch (bw) {
1476        case HALMAC_BW_80:
1477                value32 = value32 | BIT(7);
1478                break;
1479        case HALMAC_BW_40:
1480                value32 = value32 | BIT(8);
1481                break;
1482        case HALMAC_BW_20:
1483        case HALMAC_BW_10:
1484        case HALMAC_BW_5:
1485                break;
1486        default:
1487                pr_err("%s switch case not support\n", __func__);
1488                break;
1489        }
1490        HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_TRXPTCL_CTL, value32);
1491
1492        /* MAC CLK */
1493        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_AFE_CTRL1);
1494        value32 = (value32 & (~(BIT(20) | BIT(21)))) |
1495                  (HALMAC_MAC_CLOCK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
1496        HALMAC_REG_WRITE_32(halmac_adapter, REG_AFE_CTRL1, value32);
1497
1498        HALMAC_REG_WRITE_8(halmac_adapter, REG_USTIME_TSF,
1499                           HALMAC_MAC_CLOCK_88XX);
1500        HALMAC_REG_WRITE_8(halmac_adapter, REG_USTIME_EDCA,
1501                           HALMAC_MAC_CLOCK_88XX);
1502
1503        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1504                        "%s <==========\n", __func__);
1505
1506        return HALMAC_RET_SUCCESS;
1507}
1508
1509/**
1510 * halmac_dump_efuse_map_88xx() - dump "physical" efuse map
1511 * @halmac_adapter : the adapter of halmac
1512 * @cfg : dump efuse method
1513 * Author : Ivan Lin/KaiYuan Chang
1514 * Return : enum halmac_ret_status
1515 * More details of status code can be found in prototype document
1516 */
1517enum halmac_ret_status
1518halmac_dump_efuse_map_88xx(struct halmac_adapter *halmac_adapter,
1519                           enum halmac_efuse_read_cfg cfg)
1520{
1521        void *driver_adapter = NULL;
1522        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1523        enum halmac_cmd_process_status *process_status =
1524                &halmac_adapter->halmac_state.efuse_state_set.process_status;
1525
1526        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1527                return HALMAC_RET_ADAPTER_INVALID;
1528
1529        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1530                return HALMAC_RET_API_INVALID;
1531
1532        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_EFUSE_MAP);
1533
1534        driver_adapter = halmac_adapter->driver_adapter;
1535
1536        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1537                        "%s ==========>cfg=%d\n", __func__, cfg);
1538
1539        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
1540                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1541                                "Wait event(dump efuse)...\n");
1542                return HALMAC_RET_BUSY_STATE;
1543        }
1544
1545        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
1546            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
1547                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1548                                "Not idle state(dump efuse)...\n");
1549                return HALMAC_RET_ERROR_STATE;
1550        }
1551
1552        if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF)
1553                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_WARNING,
1554                                "[WARN]Dump efuse in suspend mode\n");
1555
1556        *process_status = HALMAC_CMD_PROCESS_IDLE;
1557        halmac_adapter->event_trigger.physical_efuse_map = 1;
1558
1559        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
1560                                                    HALMAC_EFUSE_BANK_WIFI);
1561        if (status != HALMAC_RET_SUCCESS) {
1562                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
1563                return status;
1564        }
1565
1566        status = halmac_dump_efuse_88xx(halmac_adapter, cfg);
1567
1568        if (status != HALMAC_RET_SUCCESS) {
1569                pr_err("halmac_read_efuse error = %x\n", status);
1570                return status;
1571        }
1572
1573        if (halmac_adapter->hal_efuse_map_valid) {
1574                *process_status = HALMAC_CMD_PROCESS_DONE;
1575
1576                PLATFORM_EVENT_INDICATION(
1577                        driver_adapter, HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE,
1578                        *process_status, halmac_adapter->hal_efuse_map,
1579                        halmac_adapter->hw_config_info.efuse_size);
1580                halmac_adapter->event_trigger.physical_efuse_map = 0;
1581        }
1582
1583        if (halmac_transition_efuse_state_88xx(
1584                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
1585            HALMAC_RET_SUCCESS)
1586                return HALMAC_RET_ERROR_STATE;
1587
1588        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1589                        "%s <==========\n", __func__);
1590
1591        return HALMAC_RET_SUCCESS;
1592}
1593
1594/**
1595 * halmac_dump_efuse_map_bt_88xx() - dump "BT physical" efuse map
1596 * @halmac_adapter : the adapter of halmac
1597 * @halmac_efuse_bank : bt efuse bank
1598 * @bt_efuse_map_size : bt efuse map size. get from halmac_get_efuse_size API
1599 * @bt_efuse_map : bt efuse map
1600 * Author : Soar / Ivan Lin
1601 * Return : enum halmac_ret_status
1602 * More details of status code can be found in prototype document
1603 */
1604enum halmac_ret_status
1605halmac_dump_efuse_map_bt_88xx(struct halmac_adapter *halmac_adapter,
1606                              enum halmac_efuse_bank halmac_efuse_bank,
1607                              u32 bt_efuse_map_size, u8 *bt_efuse_map)
1608{
1609        void *driver_adapter = NULL;
1610        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1611        enum halmac_cmd_process_status *process_status =
1612                &halmac_adapter->halmac_state.efuse_state_set.process_status;
1613
1614        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1615                return HALMAC_RET_ADAPTER_INVALID;
1616
1617        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1618                return HALMAC_RET_API_INVALID;
1619
1620        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_EFUSE_MAP_BT);
1621
1622        driver_adapter = halmac_adapter->driver_adapter;
1623
1624        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1625                        "%s ==========>\n", __func__);
1626
1627        if (halmac_adapter->hw_config_info.bt_efuse_size != bt_efuse_map_size)
1628                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
1629
1630        if ((halmac_efuse_bank >= HALMAC_EFUSE_BANK_MAX) ||
1631            halmac_efuse_bank == HALMAC_EFUSE_BANK_WIFI) {
1632                pr_err("Undefined BT bank\n");
1633                return HALMAC_RET_EFUSE_BANK_INCORRECT;
1634        }
1635
1636        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
1637                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1638                                "Wait event(dump efuse)...\n");
1639                return HALMAC_RET_BUSY_STATE;
1640        }
1641
1642        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
1643            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
1644                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1645                                "Not idle state(dump efuse)...\n");
1646                return HALMAC_RET_ERROR_STATE;
1647        }
1648
1649        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
1650                                                    halmac_efuse_bank);
1651        if (status != HALMAC_RET_SUCCESS) {
1652                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
1653                return status;
1654        }
1655
1656        status = halmac_read_hw_efuse_88xx(halmac_adapter, 0, bt_efuse_map_size,
1657                                           bt_efuse_map);
1658
1659        if (status != HALMAC_RET_SUCCESS) {
1660                pr_err("halmac_read_hw_efuse_88xx error = %x\n", status);
1661                return status;
1662        }
1663
1664        if (halmac_transition_efuse_state_88xx(
1665                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
1666            HALMAC_RET_SUCCESS)
1667                return HALMAC_RET_ERROR_STATE;
1668
1669        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1670                        "%s <==========\n", __func__);
1671
1672        return HALMAC_RET_SUCCESS;
1673}
1674
1675/**
1676 * halmac_write_efuse_bt_88xx() - write "BT physical" efuse offset
1677 * @halmac_adapter : the adapter of halmac
1678 * @halmac_offset : offset
1679 * @halmac_value : Write value
1680 * @bt_efuse_map : bt efuse map
1681 * Author : Soar
1682 * Return : enum halmac_ret_status
1683 * More details of status code can be found in prototype document
1684 */
1685enum halmac_ret_status
1686halmac_write_efuse_bt_88xx(struct halmac_adapter *halmac_adapter,
1687                           u32 halmac_offset, u8 halmac_value,
1688                           enum halmac_efuse_bank halmac_efuse_bank)
1689{
1690        void *driver_adapter = NULL;
1691        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1692
1693        enum halmac_cmd_process_status *process_status =
1694                &halmac_adapter->halmac_state.efuse_state_set.process_status;
1695
1696        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1697                return HALMAC_RET_ADAPTER_INVALID;
1698
1699        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1700                return HALMAC_RET_API_INVALID;
1701
1702        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_WRITE_EFUSE_BT);
1703
1704        driver_adapter = halmac_adapter->driver_adapter;
1705
1706        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1707                        "%s ==========>\n", __func__);
1708        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1709                        "offset : %X value : %X Bank : %X\n", halmac_offset,
1710                        halmac_value, halmac_efuse_bank);
1711
1712        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
1713                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1714                                "Wait/Rcvd event(dump efuse)...\n");
1715                return HALMAC_RET_BUSY_STATE;
1716        }
1717
1718        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
1719            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
1720                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1721                                "Not idle state(dump efuse)...\n");
1722                return HALMAC_RET_ERROR_STATE;
1723        }
1724
1725        if (halmac_offset >= halmac_adapter->hw_config_info.efuse_size) {
1726                pr_err("Offset is too large\n");
1727                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
1728        }
1729
1730        if (halmac_efuse_bank > HALMAC_EFUSE_BANK_MAX ||
1731            halmac_efuse_bank == HALMAC_EFUSE_BANK_WIFI) {
1732                pr_err("Undefined BT bank\n");
1733                return HALMAC_RET_EFUSE_BANK_INCORRECT;
1734        }
1735
1736        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
1737                                                    halmac_efuse_bank);
1738        if (status != HALMAC_RET_SUCCESS) {
1739                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
1740                return status;
1741        }
1742
1743        status = halmac_func_write_efuse_88xx(halmac_adapter, halmac_offset,
1744                                              halmac_value);
1745        if (status != HALMAC_RET_SUCCESS) {
1746                pr_err("halmac_func_write_efuse error = %x\n", status);
1747                return status;
1748        }
1749
1750        if (halmac_transition_efuse_state_88xx(
1751                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
1752            HALMAC_RET_SUCCESS)
1753                return HALMAC_RET_ERROR_STATE;
1754
1755        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1756                        "%s <==========\n", __func__);
1757
1758        return HALMAC_RET_SUCCESS;
1759}
1760
1761/**
1762 * halmac_get_efuse_available_size_88xx() - get efuse available size
1763 * @halmac_adapter : the adapter of halmac
1764 * @halmac_size : physical efuse available size
1765 * Author : Soar
1766 * Return : enum halmac_ret_status
1767 * More details of status code can be found in prototype document
1768 */
1769enum halmac_ret_status
1770halmac_get_efuse_available_size_88xx(struct halmac_adapter *halmac_adapter,
1771                                     u32 *halmac_size)
1772{
1773        enum halmac_ret_status status;
1774        void *driver_adapter = NULL;
1775
1776        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1777                return HALMAC_RET_ADAPTER_INVALID;
1778
1779        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1780                return HALMAC_RET_API_INVALID;
1781
1782        driver_adapter = halmac_adapter->driver_adapter;
1783
1784        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1785                        "%s ==========>\n", __func__);
1786
1787        status = halmac_dump_logical_efuse_map_88xx(halmac_adapter,
1788                                                    HALMAC_EFUSE_R_DRV);
1789
1790        if (status != HALMAC_RET_SUCCESS)
1791                return status;
1792
1793        *halmac_size = halmac_adapter->hw_config_info.efuse_size -
1794                       HALMAC_PROTECTED_EFUSE_SIZE_88XX -
1795                       halmac_adapter->efuse_end;
1796
1797        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1798                        "%s <==========\n", __func__);
1799
1800        return HALMAC_RET_SUCCESS;
1801}
1802
1803/**
1804 * halmac_get_efuse_size_88xx() - get "physical" efuse size
1805 * @halmac_adapter : the adapter of halmac
1806 * @halmac_size : physical efuse size
1807 * Author : Ivan Lin/KaiYuan Chang
1808 * Return : enum halmac_ret_status
1809 * More details of status code can be found in prototype document
1810 */
1811enum halmac_ret_status
1812halmac_get_efuse_size_88xx(struct halmac_adapter *halmac_adapter,
1813                           u32 *halmac_size)
1814{
1815        void *driver_adapter = NULL;
1816
1817        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1818                return HALMAC_RET_ADAPTER_INVALID;
1819
1820        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1821                return HALMAC_RET_API_INVALID;
1822
1823        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_EFUSE_SIZE);
1824
1825        driver_adapter = halmac_adapter->driver_adapter;
1826
1827        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1828                        "%s ==========>\n", __func__);
1829
1830        *halmac_size = halmac_adapter->hw_config_info.efuse_size;
1831
1832        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1833                        "%s <==========\n", __func__);
1834
1835        return HALMAC_RET_SUCCESS;
1836}
1837
1838/**
1839 * halmac_get_logical_efuse_size_88xx() - get "logical" efuse size
1840 * @halmac_adapter : the adapter of halmac
1841 * @halmac_size : logical efuse size
1842 * Author : Ivan Lin/KaiYuan Chang
1843 * Return : enum halmac_ret_status
1844 * More details of status code can be found in prototype document
1845 */
1846enum halmac_ret_status
1847halmac_get_logical_efuse_size_88xx(struct halmac_adapter *halmac_adapter,
1848                                   u32 *halmac_size)
1849{
1850        void *driver_adapter = NULL;
1851
1852        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1853                return HALMAC_RET_ADAPTER_INVALID;
1854
1855        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1856                return HALMAC_RET_API_INVALID;
1857
1858        halmac_api_record_id_88xx(halmac_adapter,
1859                                  HALMAC_API_GET_LOGICAL_EFUSE_SIZE);
1860
1861        driver_adapter = halmac_adapter->driver_adapter;
1862
1863        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1864                        "%s ==========>\n", __func__);
1865
1866        *halmac_size = halmac_adapter->hw_config_info.eeprom_size;
1867
1868        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1869                        "%s <==========\n", __func__);
1870
1871        return HALMAC_RET_SUCCESS;
1872}
1873
1874/**
1875 * halmac_dump_logical_efuse_map_88xx() - dump "logical" efuse map
1876 * @halmac_adapter : the adapter of halmac
1877 * @cfg : dump efuse method
1878 * Author : Soar
1879 * Return : enum halmac_ret_status
1880 * More details of status code can be found in prototype document
1881 */
1882enum halmac_ret_status
1883halmac_dump_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter,
1884                                   enum halmac_efuse_read_cfg cfg)
1885{
1886        u8 *eeprom_map = NULL;
1887        u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
1888        void *driver_adapter = NULL;
1889        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1890        enum halmac_cmd_process_status *process_status =
1891                &halmac_adapter->halmac_state.efuse_state_set.process_status;
1892
1893        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1894                return HALMAC_RET_ADAPTER_INVALID;
1895
1896        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1897                return HALMAC_RET_API_INVALID;
1898
1899        halmac_api_record_id_88xx(halmac_adapter,
1900                                  HALMAC_API_DUMP_LOGICAL_EFUSE_MAP);
1901
1902        driver_adapter = halmac_adapter->driver_adapter;
1903
1904        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1905                        "%s ==========>cfg = %d\n", __func__, cfg);
1906
1907        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
1908                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1909                                "Wait/Rcvd event(dump efuse)...\n");
1910                return HALMAC_RET_BUSY_STATE;
1911        }
1912
1913        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
1914            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
1915                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
1916                                "Not idle state(dump efuse)...\n");
1917                return HALMAC_RET_ERROR_STATE;
1918        }
1919
1920        if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF)
1921                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_WARNING,
1922                                "[WARN]Dump logical efuse in suspend mode\n");
1923
1924        *process_status = HALMAC_CMD_PROCESS_IDLE;
1925        halmac_adapter->event_trigger.logical_efuse_map = 1;
1926
1927        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
1928                                                    HALMAC_EFUSE_BANK_WIFI);
1929        if (status != HALMAC_RET_SUCCESS) {
1930                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
1931                return status;
1932        }
1933
1934        status = halmac_dump_efuse_88xx(halmac_adapter, cfg);
1935
1936        if (status != HALMAC_RET_SUCCESS) {
1937                pr_err("halmac_eeprom_parser_88xx error = %x\n", status);
1938                return status;
1939        }
1940
1941        if (halmac_adapter->hal_efuse_map_valid) {
1942                *process_status = HALMAC_CMD_PROCESS_DONE;
1943
1944                eeprom_map = kzalloc(eeprom_size, GFP_KERNEL);
1945                if (!eeprom_map) {
1946                        /* out of memory */
1947                        return HALMAC_RET_MALLOC_FAIL;
1948                }
1949                memset(eeprom_map, 0xFF, eeprom_size);
1950
1951                if (halmac_eeprom_parser_88xx(halmac_adapter,
1952                                              halmac_adapter->hal_efuse_map,
1953                                              eeprom_map) != HALMAC_RET_SUCCESS) {
1954                        kfree(eeprom_map);
1955                        return HALMAC_RET_EEPROM_PARSING_FAIL;
1956                }
1957
1958                PLATFORM_EVENT_INDICATION(
1959                        driver_adapter, HALMAC_FEATURE_DUMP_LOGICAL_EFUSE,
1960                        *process_status, eeprom_map, eeprom_size);
1961                halmac_adapter->event_trigger.logical_efuse_map = 0;
1962
1963                kfree(eeprom_map);
1964        }
1965
1966        if (halmac_transition_efuse_state_88xx(
1967                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
1968            HALMAC_RET_SUCCESS)
1969                return HALMAC_RET_ERROR_STATE;
1970
1971        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
1972                        "%s <==========\n", __func__);
1973
1974        return HALMAC_RET_SUCCESS;
1975}
1976
1977/**
1978 * halmac_read_logical_efuse_88xx() - read logical efuse map 1 byte
1979 * @halmac_adapter : the adapter of halmac
1980 * @halmac_offset : offset
1981 * @value : 1 byte efuse value
1982 * Author : Soar
1983 * Return : enum halmac_ret_status
1984 * More details of status code can be found in prototype document
1985 */
1986enum halmac_ret_status
1987halmac_read_logical_efuse_88xx(struct halmac_adapter *halmac_adapter,
1988                               u32 halmac_offset, u8 *value)
1989{
1990        u8 *eeprom_map = NULL;
1991        u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size;
1992        void *driver_adapter = NULL;
1993        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1994
1995        enum halmac_cmd_process_status *process_status =
1996                &halmac_adapter->halmac_state.efuse_state_set.process_status;
1997
1998        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
1999                return HALMAC_RET_ADAPTER_INVALID;
2000
2001        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2002                return HALMAC_RET_API_INVALID;
2003
2004        halmac_api_record_id_88xx(halmac_adapter,
2005                                  HALMAC_API_READ_LOGICAL_EFUSE);
2006
2007        driver_adapter = halmac_adapter->driver_adapter;
2008
2009        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2010                        "%s ==========>\n", __func__);
2011
2012        if (halmac_offset >= eeprom_size) {
2013                pr_err("Offset is too large\n");
2014                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
2015        }
2016
2017        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
2018                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2019                                "Wait/Rcvd event(dump efuse)...\n");
2020                return HALMAC_RET_BUSY_STATE;
2021        }
2022        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
2023            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
2024                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2025                                "Not idle state(dump efuse)...\n");
2026                return HALMAC_RET_ERROR_STATE;
2027        }
2028
2029        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
2030                                                    HALMAC_EFUSE_BANK_WIFI);
2031        if (status != HALMAC_RET_SUCCESS) {
2032                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
2033                return status;
2034        }
2035
2036        eeprom_map = kzalloc(eeprom_size, GFP_KERNEL);
2037        if (!eeprom_map) {
2038                /* out of memory */
2039                return HALMAC_RET_MALLOC_FAIL;
2040        }
2041        memset(eeprom_map, 0xFF, eeprom_size);
2042
2043        status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map);
2044        if (status != HALMAC_RET_SUCCESS) {
2045                pr_err("halmac_read_logical_efuse_map error = %x\n", status);
2046                kfree(eeprom_map);
2047                return status;
2048        }
2049
2050        *value = *(eeprom_map + halmac_offset);
2051
2052        if (halmac_transition_efuse_state_88xx(
2053                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
2054            HALMAC_RET_SUCCESS) {
2055                kfree(eeprom_map);
2056                return HALMAC_RET_ERROR_STATE;
2057        }
2058
2059        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2060                        "%s <==========\n", __func__);
2061
2062        kfree(eeprom_map);
2063
2064        return HALMAC_RET_SUCCESS;
2065}
2066
2067/**
2068 * halmac_write_logical_efuse_88xx() - write "logical" efuse offset
2069 * @halmac_adapter : the adapter of halmac
2070 * @halmac_offset : offset
2071 * @halmac_value : value
2072 * Author : Soar
2073 * Return : enum halmac_ret_status
2074 * More details of status code can be found in prototype document
2075 */
2076enum halmac_ret_status
2077halmac_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter,
2078                                u32 halmac_offset, u8 halmac_value)
2079{
2080        void *driver_adapter = NULL;
2081        struct halmac_api *halmac_api;
2082        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2083
2084        enum halmac_cmd_process_status *process_status =
2085                &halmac_adapter->halmac_state.efuse_state_set.process_status;
2086
2087        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2088                return HALMAC_RET_ADAPTER_INVALID;
2089
2090        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2091                return HALMAC_RET_API_INVALID;
2092
2093        halmac_api_record_id_88xx(halmac_adapter,
2094                                  HALMAC_API_WRITE_LOGICAL_EFUSE);
2095
2096        driver_adapter = halmac_adapter->driver_adapter;
2097        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2098
2099        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2100                        "%s ==========>\n", __func__);
2101
2102        if (halmac_offset >= halmac_adapter->hw_config_info.eeprom_size) {
2103                pr_err("Offset is too large\n");
2104                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
2105        }
2106
2107        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
2108                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2109                                "Wait/Rcvd event(dump efuse)...\n");
2110                return HALMAC_RET_BUSY_STATE;
2111        }
2112
2113        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
2114            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
2115                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2116                                "Not idle state(dump efuse)...\n");
2117                return HALMAC_RET_ERROR_STATE;
2118        }
2119
2120        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
2121                                                    HALMAC_EFUSE_BANK_WIFI);
2122        if (status != HALMAC_RET_SUCCESS) {
2123                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
2124                return status;
2125        }
2126
2127        status = halmac_func_write_logical_efuse_88xx(
2128                halmac_adapter, halmac_offset, halmac_value);
2129        if (status != HALMAC_RET_SUCCESS) {
2130                pr_err("halmac_write_logical_efuse error = %x\n", status);
2131                return status;
2132        }
2133
2134        if (halmac_transition_efuse_state_88xx(
2135                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
2136            HALMAC_RET_SUCCESS)
2137                return HALMAC_RET_ERROR_STATE;
2138
2139        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2140                        "%s <==========\n", __func__);
2141
2142        return HALMAC_RET_SUCCESS;
2143}
2144
2145/**
2146 * halmac_pg_efuse_by_map_88xx() - pg logical efuse by map
2147 * @halmac_adapter : the adapter of halmac
2148 * @pg_efuse_info : efuse map information
2149 * @cfg : dump efuse method
2150 * Author : Soar
2151 * Return : enum halmac_ret_status
2152 * More details of status code can be found in prototype document
2153 */
2154enum halmac_ret_status
2155halmac_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter,
2156                            struct halmac_pg_efuse_info *pg_efuse_info,
2157                            enum halmac_efuse_read_cfg cfg)
2158{
2159        void *driver_adapter = NULL;
2160        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2161
2162        enum halmac_cmd_process_status *process_status =
2163                &halmac_adapter->halmac_state.efuse_state_set.process_status;
2164
2165        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2166                return HALMAC_RET_ADAPTER_INVALID;
2167
2168        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2169                return HALMAC_RET_API_INVALID;
2170
2171        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PG_EFUSE_BY_MAP);
2172
2173        driver_adapter = halmac_adapter->driver_adapter;
2174
2175        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2176                        "%s ==========>\n", __func__);
2177
2178        if (pg_efuse_info->efuse_map_size !=
2179            halmac_adapter->hw_config_info.eeprom_size) {
2180                pr_err("efuse_map_size is incorrect, should be %d bytes\n",
2181                       halmac_adapter->hw_config_info.eeprom_size);
2182                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
2183        }
2184
2185        if ((pg_efuse_info->efuse_map_size & 0xF) > 0) {
2186                pr_err("efuse_map_size should be multiple of 16\n");
2187                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
2188        }
2189
2190        if (pg_efuse_info->efuse_mask_size !=
2191            pg_efuse_info->efuse_map_size >> 4) {
2192                pr_err("efuse_mask_size is incorrect, should be %d bytes\n",
2193                       pg_efuse_info->efuse_map_size >> 4);
2194                return HALMAC_RET_EFUSE_SIZE_INCORRECT;
2195        }
2196
2197        if (!pg_efuse_info->efuse_map) {
2198                pr_err("efuse_map is NULL\n");
2199                return HALMAC_RET_NULL_POINTER;
2200        }
2201
2202        if (!pg_efuse_info->efuse_mask) {
2203                pr_err("efuse_mask is NULL\n");
2204                return HALMAC_RET_NULL_POINTER;
2205        }
2206
2207        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
2208                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2209                                "Wait/Rcvd event(dump efuse)...\n");
2210                return HALMAC_RET_BUSY_STATE;
2211        }
2212
2213        if (halmac_query_efuse_curr_state_88xx(halmac_adapter) !=
2214            HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) {
2215                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2216                                "Not idle state(dump efuse)...\n");
2217                return HALMAC_RET_ERROR_STATE;
2218        }
2219
2220        status = halmac_func_switch_efuse_bank_88xx(halmac_adapter,
2221                                                    HALMAC_EFUSE_BANK_WIFI);
2222        if (status != HALMAC_RET_SUCCESS) {
2223                pr_err("halmac_func_switch_efuse_bank error = %x\n", status);
2224                return status;
2225        }
2226
2227        status = halmac_func_pg_efuse_by_map_88xx(halmac_adapter, pg_efuse_info,
2228                                                  cfg);
2229
2230        if (status != HALMAC_RET_SUCCESS) {
2231                pr_err("halmac_pg_efuse_by_map error = %x\n", status);
2232                return status;
2233        }
2234
2235        if (halmac_transition_efuse_state_88xx(
2236                    halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) !=
2237            HALMAC_RET_SUCCESS)
2238                return HALMAC_RET_ERROR_STATE;
2239
2240        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG,
2241                        "%s <==========\n", __func__);
2242
2243        return HALMAC_RET_SUCCESS;
2244}
2245
2246/**
2247 * halmac_get_c2h_info_88xx() - process halmac C2H packet
2248 * @halmac_adapter : the adapter of halmac
2249 * @halmac_buf : RX Packet pointer
2250 * @halmac_size : RX Packet size
2251 * Author : KaiYuan Chang/Ivan Lin
2252 *
2253 * Used to process c2h packet info from RX path. After receiving the packet,
2254 * user need to call this api and pass the packet pointer.
2255 *
2256 * Return : enum halmac_ret_status
2257 * More details of status code can be found in prototype document
2258 */
2259enum halmac_ret_status
2260halmac_get_c2h_info_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf,
2261                         u32 halmac_size)
2262{
2263        void *driver_adapter = NULL;
2264        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2265
2266        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2267                return HALMAC_RET_ADAPTER_INVALID;
2268
2269        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2270                return HALMAC_RET_API_INVALID;
2271
2272        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_C2H_INFO);
2273
2274        driver_adapter = halmac_adapter->driver_adapter;
2275
2276        /* Check if it is C2H packet */
2277        if (GET_RX_DESC_C2H(halmac_buf)) {
2278                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2279                                "C2H packet, start parsing!\n");
2280
2281                status = halmac_parse_c2h_packet_88xx(halmac_adapter,
2282                                                      halmac_buf, halmac_size);
2283
2284                if (status != HALMAC_RET_SUCCESS) {
2285                        pr_err("halmac_parse_c2h_packet_88xx error = %x\n",
2286                               status);
2287                        return status;
2288                }
2289        }
2290
2291        return HALMAC_RET_SUCCESS;
2292}
2293
2294enum halmac_ret_status
2295halmac_cfg_fwlps_option_88xx(struct halmac_adapter *halmac_adapter,
2296                             struct halmac_fwlps_option *lps_option)
2297{
2298        void *driver_adapter = NULL;
2299        struct halmac_fwlps_option *hal_fwlps_option;
2300
2301        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2302                return HALMAC_RET_ADAPTER_INVALID;
2303
2304        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2305                return HALMAC_RET_API_INVALID;
2306
2307        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_FWLPS_OPTION);
2308
2309        driver_adapter = halmac_adapter->driver_adapter;
2310        hal_fwlps_option = &halmac_adapter->fwlps_option;
2311
2312        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2313                        "%s ==========>\n", __func__);
2314
2315        hal_fwlps_option->mode = lps_option->mode;
2316        hal_fwlps_option->clk_request = lps_option->clk_request;
2317        hal_fwlps_option->rlbm = lps_option->rlbm;
2318        hal_fwlps_option->smart_ps = lps_option->smart_ps;
2319        hal_fwlps_option->awake_interval = lps_option->awake_interval;
2320        hal_fwlps_option->all_queue_uapsd = lps_option->all_queue_uapsd;
2321        hal_fwlps_option->pwr_state = lps_option->pwr_state;
2322        hal_fwlps_option->low_pwr_rx_beacon = lps_option->low_pwr_rx_beacon;
2323        hal_fwlps_option->ant_auto_switch = lps_option->ant_auto_switch;
2324        hal_fwlps_option->ps_allow_bt_high_priority =
2325                lps_option->ps_allow_bt_high_priority;
2326        hal_fwlps_option->protect_bcn = lps_option->protect_bcn;
2327        hal_fwlps_option->silence_period = lps_option->silence_period;
2328        hal_fwlps_option->fast_bt_connect = lps_option->fast_bt_connect;
2329        hal_fwlps_option->two_antenna_en = lps_option->two_antenna_en;
2330        hal_fwlps_option->adopt_user_setting = lps_option->adopt_user_setting;
2331        hal_fwlps_option->drv_bcn_early_shift = lps_option->drv_bcn_early_shift;
2332        hal_fwlps_option->enter_32K = lps_option->enter_32K;
2333
2334        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2335                        "%s <==========\n", __func__);
2336
2337        return HALMAC_RET_SUCCESS;
2338}
2339
2340enum halmac_ret_status
2341halmac_cfg_fwips_option_88xx(struct halmac_adapter *halmac_adapter,
2342                             struct halmac_fwips_option *ips_option)
2343{
2344        void *driver_adapter = NULL;
2345        struct halmac_fwips_option *ips_option_local;
2346
2347        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2348                return HALMAC_RET_ADAPTER_INVALID;
2349
2350        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2351                return HALMAC_RET_API_INVALID;
2352
2353        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_FWIPS_OPTION);
2354
2355        driver_adapter = halmac_adapter->driver_adapter;
2356
2357        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2358                        "%s ==========>\n", __func__);
2359
2360        ips_option_local = ips_option;
2361
2362        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2363                        "%s <==========\n", __func__);
2364
2365        return HALMAC_RET_SUCCESS;
2366}
2367
2368enum halmac_ret_status
2369halmac_enter_wowlan_88xx(struct halmac_adapter *halmac_adapter,
2370                         struct halmac_wowlan_option *wowlan_option)
2371{
2372        void *driver_adapter = NULL;
2373        struct halmac_wowlan_option *wowlan_option_local;
2374
2375        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2376                return HALMAC_RET_ADAPTER_INVALID;
2377
2378        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2379                return HALMAC_RET_API_INVALID;
2380
2381        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ENTER_WOWLAN);
2382
2383        driver_adapter = halmac_adapter->driver_adapter;
2384
2385        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2386                        "%s ==========>\n", __func__);
2387
2388        wowlan_option_local = wowlan_option;
2389
2390        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2391                        "%s <==========\n", __func__);
2392
2393        return HALMAC_RET_SUCCESS;
2394}
2395
2396enum halmac_ret_status
2397halmac_leave_wowlan_88xx(struct halmac_adapter *halmac_adapter)
2398{
2399        void *driver_adapter = NULL;
2400
2401        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2402                return HALMAC_RET_ADAPTER_INVALID;
2403
2404        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2405                return HALMAC_RET_API_INVALID;
2406
2407        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_LEAVE_WOWLAN);
2408
2409        driver_adapter = halmac_adapter->driver_adapter;
2410
2411        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2412                        "%s ==========>\n", __func__);
2413
2414        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2415                        "%s <==========\n", __func__);
2416
2417        return HALMAC_RET_SUCCESS;
2418}
2419
2420enum halmac_ret_status
2421halmac_enter_ps_88xx(struct halmac_adapter *halmac_adapter,
2422                     enum halmac_ps_state ps_state)
2423{
2424        u8 rpwm;
2425        void *driver_adapter = NULL;
2426        struct halmac_api *halmac_api;
2427        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2428
2429        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2430                return HALMAC_RET_ADAPTER_INVALID;
2431
2432        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2433                return HALMAC_RET_API_INVALID;
2434
2435        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2436                return HALMAC_RET_NO_DLFW;
2437
2438        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ENTER_PS);
2439
2440        driver_adapter = halmac_adapter->driver_adapter;
2441        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2442
2443        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2444                        "%s ==========>\n", __func__);
2445
2446        if (ps_state == halmac_adapter->halmac_state.ps_state) {
2447                pr_err("power state is already in PS State!!\n");
2448                return HALMAC_RET_SUCCESS;
2449        }
2450
2451        if (ps_state == HALMAC_PS_STATE_LPS) {
2452                status = halmac_send_h2c_set_pwr_mode_88xx(
2453                        halmac_adapter, &halmac_adapter->fwlps_option);
2454                if (status != HALMAC_RET_SUCCESS) {
2455                        pr_err("halmac_send_h2c_set_pwr_mode_88xx error = %x!!\n",
2456                               status);
2457                        return status;
2458                }
2459        } else if (ps_state == HALMAC_PS_STATE_IPS) {
2460        }
2461
2462        halmac_adapter->halmac_state.ps_state = ps_state;
2463
2464        /* Enter 32K */
2465        if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
2466                if (halmac_adapter->fwlps_option.enter_32K) {
2467                        rpwm = (u8)(((halmac_adapter->rpwm_record ^ (BIT(7))) |
2468                                     (BIT(0))) &
2469                                    0x81);
2470                        HALMAC_REG_WRITE_8(halmac_adapter, REG_SDIO_HRPWM1,
2471                                           rpwm);
2472                        halmac_adapter->low_clk = true;
2473                }
2474        } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) {
2475                if (halmac_adapter->fwlps_option.enter_32K) {
2476                        rpwm = (u8)(((halmac_adapter->rpwm_record ^ (BIT(7))) |
2477                                     (BIT(0))) &
2478                                    0x81);
2479                        HALMAC_REG_WRITE_8(halmac_adapter, 0xFE58, rpwm);
2480                        halmac_adapter->low_clk = true;
2481                }
2482        }
2483
2484        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2485                        "%s <==========\n", __func__);
2486
2487        return HALMAC_RET_SUCCESS;
2488}
2489
2490enum halmac_ret_status
2491halmac_leave_ps_88xx(struct halmac_adapter *halmac_adapter)
2492{
2493        u8 rpwm, cpwm;
2494        u32 counter;
2495        void *driver_adapter = NULL;
2496        struct halmac_api *halmac_api;
2497        struct halmac_fwlps_option fw_lps_option;
2498        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2499
2500        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2501                return HALMAC_RET_ADAPTER_INVALID;
2502
2503        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2504                return HALMAC_RET_API_INVALID;
2505
2506        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2507                return HALMAC_RET_NO_DLFW;
2508
2509        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_LEAVE_PS);
2510
2511        driver_adapter = halmac_adapter->driver_adapter;
2512        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2513
2514        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2515                        "%s ==========>\n", __func__);
2516
2517        if (halmac_adapter->halmac_state.ps_state == HALMAC_PS_STATE_ACT) {
2518                pr_err("power state is already in active!!\n");
2519                return HALMAC_RET_SUCCESS;
2520        }
2521
2522        if (halmac_adapter->low_clk) {
2523                cpwm = HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HRPWM1);
2524                rpwm = (u8)(
2525                        ((halmac_adapter->rpwm_record ^ (BIT(7))) | (BIT(6))) &
2526                        0xC0);
2527                HALMAC_REG_WRITE_8(halmac_adapter, REG_SDIO_HRPWM1, rpwm);
2528
2529                cpwm = (u8)((cpwm ^ BIT(7)) & BIT(7));
2530                counter = 100;
2531                while (cpwm !=
2532                       (HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HRPWM1) &
2533                        BIT(7))) {
2534                        usleep_range(50, 60);
2535                        counter--;
2536                        if (counter == 0)
2537                                return HALMAC_RET_CHANGE_PS_FAIL;
2538                }
2539                halmac_adapter->low_clk = false;
2540        }
2541
2542        memcpy(&fw_lps_option, &halmac_adapter->fwlps_option,
2543               sizeof(struct halmac_fwlps_option));
2544        fw_lps_option.mode = 0;
2545
2546        status = halmac_send_h2c_set_pwr_mode_88xx(halmac_adapter,
2547                                                   &fw_lps_option);
2548        if (status != HALMAC_RET_SUCCESS) {
2549                pr_err("halmac_send_h2c_set_pwr_mode_88xx error!!=%x\n",
2550                       status);
2551                return status;
2552        }
2553
2554        halmac_adapter->halmac_state.ps_state = HALMAC_PS_STATE_ACT;
2555
2556        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG,
2557                        "%s <==========\n", __func__);
2558
2559        return HALMAC_RET_SUCCESS;
2560}
2561
2562/**
2563 * (debug API)halmac_h2c_lb_88xx() - send h2c loopback packet
2564 * @halmac_adapter : the adapter of halmac
2565 * Author : KaiYuan Chang/Ivan Lin
2566 * Return : enum halmac_ret_status
2567 * More details of status code can be found in prototype document
2568 */
2569enum halmac_ret_status halmac_h2c_lb_88xx(struct halmac_adapter *halmac_adapter)
2570{
2571        void *driver_adapter = NULL;
2572
2573        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2574                return HALMAC_RET_ADAPTER_INVALID;
2575
2576        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2577                return HALMAC_RET_API_INVALID;
2578
2579        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_H2C_LB);
2580
2581        driver_adapter = halmac_adapter->driver_adapter;
2582
2583        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2584                        "%s ==========>\n", __func__);
2585
2586        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2587                        "%s <==========\n", __func__);
2588
2589        return HALMAC_RET_SUCCESS;
2590}
2591
2592/**
2593 * halmac_debug_88xx() - dump information for debugging
2594 * @halmac_adapter : the adapter of halmac
2595 * Author : KaiYuan Chang/Ivan Lin
2596 * Return : enum halmac_ret_status
2597 * More details of status code can be found in prototype document
2598 */
2599enum halmac_ret_status halmac_debug_88xx(struct halmac_adapter *halmac_adapter)
2600{
2601        u8 temp8 = 0;
2602        u32 i = 0, temp32 = 0;
2603        void *driver_adapter = NULL;
2604        struct halmac_api *halmac_api;
2605
2606        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2607                return HALMAC_RET_ADAPTER_INVALID;
2608
2609        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2610                return HALMAC_RET_API_INVALID;
2611
2612        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEBUG);
2613
2614        driver_adapter = halmac_adapter->driver_adapter;
2615        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2616
2617        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2618                        "%s ==========>\n", __func__);
2619
2620        if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
2621                /* Dump CCCR, it needs new platform api */
2622
2623                /*Dump SDIO Local Register, use CMD52*/
2624                for (i = 0x10250000; i < 0x102500ff; i++) {
2625                        temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2626                        HALMAC_RT_TRACE(
2627                                driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2628                                "halmac_debug: sdio[%x]=%x\n", i, temp8);
2629                }
2630
2631                /*Dump MAC Register*/
2632                for (i = 0x0000; i < 0x17ff; i++) {
2633                        temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2634                        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT,
2635                                        DBG_DMESG, "halmac_debug: mac[%x]=%x\n",
2636                                        i, temp8);
2637                }
2638
2639                /*Check RX Fifo status*/
2640                i = REG_RXFF_PTR_V1;
2641                temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2642                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2643                                "halmac_debug: mac[%x]=%x\n", i, temp8);
2644                i = REG_RXFF_WTR_V1;
2645                temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2646                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2647                                "halmac_debug: mac[%x]=%x\n", i, temp8);
2648                i = REG_RXFF_PTR_V1;
2649                temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2650                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2651                                "halmac_debug: mac[%x]=%x\n", i, temp8);
2652                i = REG_RXFF_WTR_V1;
2653                temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i);
2654                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2655                                "halmac_debug: mac[%x]=%x\n", i, temp8);
2656        } else {
2657                /*Dump MAC Register*/
2658                for (i = 0x0000; i < 0x17fc; i += 4) {
2659                        temp32 = HALMAC_REG_READ_32(halmac_adapter, i);
2660                        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT,
2661                                        DBG_DMESG, "halmac_debug: mac[%x]=%x\n",
2662                                        i, temp32);
2663                }
2664
2665                /*Check RX Fifo status*/
2666                i = REG_RXFF_PTR_V1;
2667                temp32 = HALMAC_REG_READ_32(halmac_adapter, i);
2668                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2669                                "halmac_debug: mac[%x]=%x\n", i, temp32);
2670                i = REG_RXFF_WTR_V1;
2671                temp32 = HALMAC_REG_READ_32(halmac_adapter, i);
2672                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2673                                "halmac_debug: mac[%x]=%x\n", i, temp32);
2674                i = REG_RXFF_PTR_V1;
2675                temp32 = HALMAC_REG_READ_32(halmac_adapter, i);
2676                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2677                                "halmac_debug: mac[%x]=%x\n", i, temp32);
2678                i = REG_RXFF_WTR_V1;
2679                temp32 = HALMAC_REG_READ_32(halmac_adapter, i);
2680                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2681                                "halmac_debug: mac[%x]=%x\n", i, temp32);
2682        }
2683
2684        /*      TODO: Add check register code, including MAC CLK, CPU CLK */
2685
2686        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2687                        "%s <==========\n", __func__);
2688
2689        return HALMAC_RET_SUCCESS;
2690}
2691
2692/**
2693 * halmac_cfg_parameter_88xx() - config parameter by FW
2694 * @halmac_adapter : the adapter of halmac
2695 * @para_info : cmd id, content
2696 * @full_fifo : parameter information
2697 *
2698 * If msk_en = true, the format of array is {reg_info, mask, value}.
2699 * If msk_en =_FAUSE, the format of array is {reg_info, value}
2700 * The format of reg_info is
2701 * reg_info[31]=rf_reg, 0: MAC_BB reg, 1: RF reg
2702 * reg_info[27:24]=rf_path, 0: path_A, 1: path_B
2703 * if rf_reg=0(MAC_BB reg), rf_path is meaningless.
2704 * ref_info[15:0]=offset
2705 *
2706 * Example: msk_en = false
2707 * {0x8100000a, 0x00001122}
2708 * =>Set RF register, path_B, offset 0xA to 0x00001122
2709 * {0x00000824, 0x11224433}
2710 * =>Set MAC_BB register, offset 0x800 to 0x11224433
2711 *
2712 * Note : full fifo mode only for init flow
2713 *
2714 * Author : KaiYuan Chang/Ivan Lin
2715 * Return : enum halmac_ret_status
2716 * More details of status code can be found in prototype document
2717 */
2718enum halmac_ret_status
2719halmac_cfg_parameter_88xx(struct halmac_adapter *halmac_adapter,
2720                          struct halmac_phy_parameter_info *para_info,
2721                          u8 full_fifo)
2722{
2723        void *driver_adapter = NULL;
2724        enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS;
2725        enum halmac_cmd_process_status *process_status =
2726                &halmac_adapter->halmac_state.cfg_para_state_set.process_status;
2727
2728        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2729                return HALMAC_RET_ADAPTER_INVALID;
2730
2731        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2732                return HALMAC_RET_API_INVALID;
2733
2734        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2735                return HALMAC_RET_NO_DLFW;
2736
2737        if (halmac_adapter->fw_version.h2c_version < 4)
2738                return HALMAC_RET_FW_NO_SUPPORT;
2739
2740        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_PARAMETER);
2741
2742        driver_adapter = halmac_adapter->driver_adapter;
2743
2744        if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) {
2745                pr_err("%s Fail due to DLFW NONE!!\n", __func__);
2746                return HALMAC_RET_DLFW_FAIL;
2747        }
2748
2749        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
2750                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2751                                "Wait event(cfg para)...\n");
2752                return HALMAC_RET_BUSY_STATE;
2753        }
2754
2755        if (halmac_query_cfg_para_curr_state_88xx(halmac_adapter) !=
2756                    HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE &&
2757            halmac_query_cfg_para_curr_state_88xx(halmac_adapter) !=
2758                    HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) {
2759                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2760                                "Not idle state(cfg para)...\n");
2761                return HALMAC_RET_BUSY_STATE;
2762        }
2763
2764        *process_status = HALMAC_CMD_PROCESS_IDLE;
2765
2766        ret_status = halmac_send_h2c_phy_parameter_88xx(halmac_adapter,
2767                                                        para_info, full_fifo);
2768
2769        if (ret_status != HALMAC_RET_SUCCESS) {
2770                pr_err("halmac_send_h2c_phy_parameter_88xx Fail!! = %x\n",
2771                       ret_status);
2772                return ret_status;
2773        }
2774
2775        return ret_status;
2776}
2777
2778/**
2779 * halmac_update_packet_88xx() - send specific packet to FW
2780 * @halmac_adapter : the adapter of halmac
2781 * @pkt_id : packet id, to know the purpose of this packet
2782 * @pkt : packet
2783 * @pkt_size : packet size
2784 *
2785 * Note : TX_DESC is not included in the pkt
2786 *
2787 * Author : KaiYuan Chang/Ivan Lin
2788 * Return : enum halmac_ret_status
2789 * More details of status code can be found in prototype document
2790 */
2791enum halmac_ret_status
2792halmac_update_packet_88xx(struct halmac_adapter *halmac_adapter,
2793                          enum halmac_packet_id pkt_id, u8 *pkt, u32 pkt_size)
2794{
2795        void *driver_adapter = NULL;
2796        struct halmac_api *halmac_api;
2797        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2798        enum halmac_cmd_process_status *process_status =
2799                &halmac_adapter->halmac_state.update_packet_set.process_status;
2800
2801        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2802                return HALMAC_RET_ADAPTER_INVALID;
2803
2804        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2805                return HALMAC_RET_API_INVALID;
2806
2807        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2808                return HALMAC_RET_NO_DLFW;
2809
2810        if (halmac_adapter->fw_version.h2c_version < 4)
2811                return HALMAC_RET_FW_NO_SUPPORT;
2812
2813        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_UPDATE_PACKET);
2814
2815        driver_adapter = halmac_adapter->driver_adapter;
2816        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2817
2818        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2819                        "%s ==========>\n", __func__);
2820
2821        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
2822                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
2823                                "Wait event(update_packet)...\n");
2824                return HALMAC_RET_BUSY_STATE;
2825        }
2826
2827        *process_status = HALMAC_CMD_PROCESS_SENDING;
2828
2829        status = halmac_send_h2c_update_packet_88xx(halmac_adapter, pkt_id, pkt,
2830                                                    pkt_size);
2831
2832        if (status != HALMAC_RET_SUCCESS) {
2833                pr_err("halmac_send_h2c_update_packet_88xx packet = %x,  fail = %x!!\n",
2834                       pkt_id, status);
2835                return status;
2836        }
2837
2838        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2839                        "%s <==========\n", __func__);
2840
2841        return HALMAC_RET_SUCCESS;
2842}
2843
2844enum halmac_ret_status
2845halmac_bcn_ie_filter_88xx(struct halmac_adapter *halmac_adapter,
2846                          struct halmac_bcn_ie_info *bcn_ie_info)
2847{
2848        void *driver_adapter = NULL;
2849        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2850
2851        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2852                return HALMAC_RET_ADAPTER_INVALID;
2853
2854        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2855                return HALMAC_RET_API_INVALID;
2856
2857        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2858                return HALMAC_RET_NO_DLFW;
2859
2860        if (halmac_adapter->fw_version.h2c_version < 4)
2861                return HALMAC_RET_FW_NO_SUPPORT;
2862
2863        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_BCN_IE_FILTER);
2864
2865        driver_adapter = halmac_adapter->driver_adapter;
2866
2867        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2868                        "%s ==========>\n", __func__);
2869
2870        status = halmac_send_h2c_update_bcn_parse_info_88xx(halmac_adapter,
2871                                                            bcn_ie_info);
2872
2873        if (status != HALMAC_RET_SUCCESS) {
2874                pr_err("halmac_send_h2c_update_bcn_parse_info_88xx fail = %x\n",
2875                       status);
2876                return status;
2877        }
2878
2879        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2880                        "%s <==========\n", __func__);
2881
2882        return HALMAC_RET_SUCCESS;
2883}
2884
2885enum halmac_ret_status
2886halmac_update_datapack_88xx(struct halmac_adapter *halmac_adapter,
2887                            enum halmac_data_type halmac_data_type,
2888                            struct halmac_phy_parameter_info *para_info)
2889{
2890        void *driver_adapter = NULL;
2891
2892        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2893                return HALMAC_RET_ADAPTER_INVALID;
2894
2895        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2896                return HALMAC_RET_API_INVALID;
2897
2898        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2899                return HALMAC_RET_NO_DLFW;
2900
2901        if (halmac_adapter->fw_version.h2c_version < 4)
2902                return HALMAC_RET_FW_NO_SUPPORT;
2903
2904        driver_adapter = halmac_adapter->driver_adapter;
2905
2906        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2907                        "[TRACE]%s ==========>\n", __func__);
2908
2909        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2910                        "[TRACE]%s <==========\n", __func__);
2911
2912        return HALMAC_RET_SUCCESS;
2913}
2914
2915enum halmac_ret_status
2916halmac_run_datapack_88xx(struct halmac_adapter *halmac_adapter,
2917                         enum halmac_data_type halmac_data_type)
2918{
2919        void *driver_adapter = NULL;
2920        enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS;
2921
2922        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2923                return HALMAC_RET_ADAPTER_INVALID;
2924
2925        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2926                return HALMAC_RET_API_INVALID;
2927
2928        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2929                return HALMAC_RET_NO_DLFW;
2930
2931        if (halmac_adapter->fw_version.h2c_version < 4)
2932                return HALMAC_RET_FW_NO_SUPPORT;
2933
2934        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_RUN_DATAPACK);
2935
2936        driver_adapter = halmac_adapter->driver_adapter;
2937
2938        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2939                        "%s ==========>\n", __func__);
2940
2941        ret_status = halmac_send_h2c_run_datapack_88xx(halmac_adapter,
2942                                                       halmac_data_type);
2943
2944        if (ret_status != HALMAC_RET_SUCCESS) {
2945                pr_err("halmac_send_h2c_run_datapack_88xx Fail, datatype = %x, status = %x!!\n",
2946                       halmac_data_type, ret_status);
2947                return ret_status;
2948        }
2949
2950        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2951                        "halmac_update_datapack_88xx <==========\n");
2952
2953        return HALMAC_RET_SUCCESS;
2954}
2955
2956/**
2957 * halmac_cfg_drv_info_88xx() - config driver info
2958 * @halmac_adapter : the adapter of halmac
2959 * @halmac_drv_info : driver information selection
2960 * Author : KaiYuan Chang/Ivan Lin
2961 * Return : enum halmac_ret_status
2962 * More details of status code can be found in prototype document
2963 */
2964enum halmac_ret_status
2965halmac_cfg_drv_info_88xx(struct halmac_adapter *halmac_adapter,
2966                         enum halmac_drv_info halmac_drv_info)
2967{
2968        u8 drv_info_size = 0;
2969        u8 phy_status_en = 0;
2970        u8 sniffer_en = 0;
2971        u8 plcp_hdr_en = 0;
2972        u32 value32;
2973        void *driver_adapter = NULL;
2974        struct halmac_api *halmac_api;
2975        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2976
2977        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2978                return HALMAC_RET_ADAPTER_INVALID;
2979
2980        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
2981                return HALMAC_RET_API_INVALID;
2982
2983        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_DRV_INFO);
2984
2985        driver_adapter = halmac_adapter->driver_adapter;
2986        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
2987
2988        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2989                        "%s ==========>\n", __func__);
2990
2991        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
2992                        "halmac_cfg_drv_info = %d\n", halmac_drv_info);
2993
2994        switch (halmac_drv_info) {
2995        case HALMAC_DRV_INFO_NONE:
2996                drv_info_size = 0;
2997                phy_status_en = 0;
2998                sniffer_en = 0;
2999                plcp_hdr_en = 0;
3000                break;
3001        case HALMAC_DRV_INFO_PHY_STATUS:
3002                drv_info_size = 4;
3003                phy_status_en = 1;
3004                sniffer_en = 0;
3005                plcp_hdr_en = 0;
3006                break;
3007        case HALMAC_DRV_INFO_PHY_SNIFFER:
3008                drv_info_size = 5; /* phy status 4byte, sniffer info 1byte */
3009                phy_status_en = 1;
3010                sniffer_en = 1;
3011                plcp_hdr_en = 0;
3012                break;
3013        case HALMAC_DRV_INFO_PHY_PLCP:
3014                drv_info_size = 6; /* phy status 4byte, plcp header 2byte */
3015                phy_status_en = 1;
3016                sniffer_en = 0;
3017                plcp_hdr_en = 1;
3018                break;
3019        default:
3020                status = HALMAC_RET_SW_CASE_NOT_SUPPORT;
3021                pr_err("%s error = %x\n", __func__, status);
3022                return status;
3023        }
3024
3025        if (halmac_adapter->txff_allocation.rx_fifo_expanding_mode !=
3026            HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE)
3027                drv_info_size = 0xF;
3028
3029        HALMAC_REG_WRITE_8(halmac_adapter, REG_RX_DRVINFO_SZ, drv_info_size);
3030
3031        halmac_adapter->drv_info_size = drv_info_size;
3032
3033        value32 = HALMAC_REG_READ_32(halmac_adapter, REG_RCR);
3034        value32 = (value32 & (~BIT_APP_PHYSTS));
3035        if (phy_status_en == 1)
3036                value32 = value32 | BIT_APP_PHYSTS;
3037        HALMAC_REG_WRITE_32(halmac_adapter, REG_RCR, value32);
3038
3039        value32 = HALMAC_REG_READ_32(halmac_adapter,
3040                                     REG_WMAC_OPTION_FUNCTION + 4);
3041        value32 = (value32 & (~(BIT(8) | BIT(9))));
3042        if (sniffer_en == 1)
3043                value32 = value32 | BIT(9);
3044        if (plcp_hdr_en == 1)
3045                value32 = value32 | BIT(8);
3046        HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 4,
3047                            value32);
3048
3049        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3050                        "%s <==========\n", __func__);
3051
3052        return HALMAC_RET_SUCCESS;
3053}
3054
3055enum halmac_ret_status
3056halmac_send_bt_coex_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf,
3057                         u32 bt_size, u8 ack)
3058{
3059        void *driver_adapter = NULL;
3060        struct halmac_api *halmac_api;
3061        enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS;
3062
3063        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3064                return HALMAC_RET_ADAPTER_INVALID;
3065
3066        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3067                return HALMAC_RET_API_INVALID;
3068
3069        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3070                return HALMAC_RET_NO_DLFW;
3071
3072        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_BT_COEX);
3073
3074        driver_adapter = halmac_adapter->driver_adapter;
3075        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3076
3077        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3078                        "%s ==========>\n", __func__);
3079
3080        ret_status = halmac_send_bt_coex_cmd_88xx(halmac_adapter, bt_buf,
3081                                                  bt_size, ack);
3082
3083        if (ret_status != HALMAC_RET_SUCCESS) {
3084                pr_err("halmac_send_bt_coex_cmd_88xx Fail = %x!!\n",
3085                       ret_status);
3086                return ret_status;
3087        }
3088
3089        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3090                        "%s <==========\n", __func__);
3091
3092        return HALMAC_RET_SUCCESS;
3093}
3094
3095/**
3096 * (debug API)halmac_verify_platform_api_88xx() - verify platform api
3097 * @halmac_adapter : the adapter of halmac
3098 * Author : KaiYuan Chang/Ivan Lin
3099 * Return : enum halmac_ret_status
3100 * More details of status code can be found in prototype document
3101 */
3102enum halmac_ret_status
3103halmac_verify_platform_api_88xx(struct halmac_adapter *halmac_adapter)
3104{
3105        void *driver_adapter = NULL;
3106        enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS;
3107
3108        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3109                return HALMAC_RET_ADAPTER_INVALID;
3110
3111        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3112                return HALMAC_RET_API_INVALID;
3113
3114        halmac_api_record_id_88xx(halmac_adapter,
3115                                  HALMAC_API_VERIFY_PLATFORM_API);
3116
3117        driver_adapter = halmac_adapter->driver_adapter;
3118
3119        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3120                        "%s ==========>\n", __func__);
3121
3122        ret_status = halmac_verify_io_88xx(halmac_adapter);
3123
3124        if (ret_status != HALMAC_RET_SUCCESS)
3125                return ret_status;
3126
3127        if (halmac_adapter->txff_allocation.la_mode != HALMAC_LA_MODE_FULL)
3128                ret_status = halmac_verify_send_rsvd_page_88xx(halmac_adapter);
3129
3130        if (ret_status != HALMAC_RET_SUCCESS)
3131                return ret_status;
3132
3133        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3134                        "%s <==========\n", __func__);
3135
3136        return ret_status;
3137}
3138
3139enum halmac_ret_status
3140halmac_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter,
3141                              u8 *original_h2c, u16 *seq, u8 ack)
3142{
3143        void *driver_adapter = NULL;
3144        struct halmac_api *halmac_api;
3145        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
3146
3147        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3148                return HALMAC_RET_ADAPTER_INVALID;
3149
3150        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3151                return HALMAC_RET_API_INVALID;
3152
3153        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3154                return HALMAC_RET_NO_DLFW;
3155
3156        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_ORIGINAL_H2C);
3157
3158        driver_adapter = halmac_adapter->driver_adapter;
3159        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3160
3161        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3162                        "%s ==========>\n", __func__);
3163
3164        status = halmac_func_send_original_h2c_88xx(halmac_adapter,
3165                                                    original_h2c, seq, ack);
3166
3167        if (status != HALMAC_RET_SUCCESS) {
3168                pr_err("halmac_send_original_h2c FAIL = %x!!\n", status);
3169                return status;
3170        }
3171
3172        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
3173                        "%s <==========\n", __func__);
3174
3175        return HALMAC_RET_SUCCESS;
3176}
3177
3178enum halmac_ret_status
3179halmac_timer_2s_88xx(struct halmac_adapter *halmac_adapter)
3180{
3181        void *driver_adapter = NULL;
3182
3183        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3184                return HALMAC_RET_ADAPTER_INVALID;
3185
3186        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3187                return HALMAC_RET_API_INVALID;
3188
3189        driver_adapter = halmac_adapter->driver_adapter;
3190
3191        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
3192                        "%s ==========>\n", __func__);
3193
3194        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
3195                        "%s <==========\n", __func__);
3196
3197        return HALMAC_RET_SUCCESS;
3198}
3199
3200/**
3201 * halmac_fill_txdesc_check_sum_88xx() -  fill in tx desc check sum
3202 * @halmac_adapter : the adapter of halmac
3203 * @cur_desc : tx desc packet
3204 * Author : KaiYuan Chang/Ivan Lin
3205 * Return : enum halmac_ret_status
3206 * More details of status code can be found in prototype document
3207 */
3208enum halmac_ret_status
3209halmac_fill_txdesc_check_sum_88xx(struct halmac_adapter *halmac_adapter,
3210                                  u8 *cur_desc)
3211{
3212        u16 chk_result = 0;
3213        u16 *data = (u16 *)NULL;
3214        u32 i;
3215        void *driver_adapter = NULL;
3216        struct halmac_api *halmac_api;
3217
3218        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3219                return HALMAC_RET_ADAPTER_INVALID;
3220
3221        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3222                return HALMAC_RET_API_INVALID;
3223
3224        halmac_api_record_id_88xx(halmac_adapter,
3225                                  HALMAC_API_FILL_TXDESC_CHECKSUM);
3226
3227        driver_adapter = halmac_adapter->driver_adapter;
3228        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3229
3230        if (!cur_desc) {
3231                pr_err("%s NULL PTR", __func__);
3232                return HALMAC_RET_NULL_POINTER;
3233        }
3234
3235        SET_TX_DESC_TXDESC_CHECKSUM(cur_desc, 0x0000);
3236
3237        data = (u16 *)(cur_desc);
3238
3239        /* HW clculates only 32byte */
3240        for (i = 0; i < 8; i++)
3241                chk_result ^= (*(data + 2 * i) ^ *(data + (2 * i + 1)));
3242
3243        SET_TX_DESC_TXDESC_CHECKSUM(cur_desc, chk_result);
3244
3245        return HALMAC_RET_SUCCESS;
3246}
3247
3248/**
3249 * halmac_dump_fifo_88xx() - dump fifo data
3250 * @halmac_adapter : the adapter of halmac
3251 * @halmac_fifo_sel : FIFO selection
3252 * @halmac_start_addr : start address of selected FIFO
3253 * @halmac_fifo_dump_size : dump size of selected FIFO
3254 * @fifo_map : FIFO data
3255 *
3256 * Note : before dump fifo, user need to call halmac_get_fifo_size to
3257 * get fifo size. Then input this size to halmac_dump_fifo.
3258 *
3259 * Author : Ivan Lin/KaiYuan Chang
3260 * Return : enum halmac_ret_status
3261 * More details of status code can be found in prototype document
3262 */
3263enum halmac_ret_status
3264halmac_dump_fifo_88xx(struct halmac_adapter *halmac_adapter,
3265                      enum hal_fifo_sel halmac_fifo_sel, u32 halmac_start_addr,
3266                      u32 halmac_fifo_dump_size, u8 *fifo_map)
3267{
3268        void *driver_adapter = NULL;
3269        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
3270
3271        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3272                return HALMAC_RET_ADAPTER_INVALID;
3273
3274        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3275                return HALMAC_RET_API_INVALID;
3276
3277        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_FIFO);
3278
3279        driver_adapter = halmac_adapter->driver_adapter;
3280
3281        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
3282                        "%s ==========>\n", __func__);
3283
3284        if (halmac_fifo_sel == HAL_FIFO_SEL_TX &&
3285            (halmac_start_addr + halmac_fifo_dump_size) >
3286                    halmac_adapter->hw_config_info.tx_fifo_size) {
3287                pr_err("TX fifo dump size is too large\n");
3288                return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
3289        }
3290
3291        if (halmac_fifo_sel == HAL_FIFO_SEL_RX &&
3292            (halmac_start_addr + halmac_fifo_dump_size) >
3293                    halmac_adapter->hw_config_info.rx_fifo_size) {
3294                pr_err("RX fifo dump size is too large\n");
3295                return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
3296        }
3297
3298        if ((halmac_fifo_dump_size & (4 - 1)) != 0) {
3299                pr_err("halmac_fifo_dump_size shall 4byte align\n");
3300                return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
3301        }
3302
3303        if (!fifo_map) {
3304                pr_err("fifo_map address is NULL\n");
3305                return HALMAC_RET_NULL_POINTER;
3306        }
3307
3308        status = halmac_buffer_read_88xx(halmac_adapter, halmac_start_addr,
3309                                         halmac_fifo_dump_size, halmac_fifo_sel,
3310                                         fifo_map);
3311
3312        if (status != HALMAC_RET_SUCCESS) {
3313                pr_err("halmac_buffer_read_88xx error = %x\n", status);
3314                return status;
3315        }
3316
3317        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
3318                        "%s <==========\n", __func__);
3319
3320        return HALMAC_RET_SUCCESS;
3321}
3322
3323/**
3324 * halmac_get_fifo_size_88xx() - get fifo size
3325 * @halmac_adapter : the adapter of halmac
3326 * @halmac_fifo_sel : FIFO selection
3327 * Author : Ivan Lin/KaiYuan Chang
3328 * Return : u32
3329 * More details of status code can be found in prototype document
3330 */
3331u32 halmac_get_fifo_size_88xx(struct halmac_adapter *halmac_adapter,
3332                              enum hal_fifo_sel halmac_fifo_sel)
3333{
3334        u32 fifo_size = 0;
3335
3336        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3337                return HALMAC_RET_ADAPTER_INVALID;
3338
3339        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3340                return HALMAC_RET_API_INVALID;
3341
3342        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_FIFO_SIZE);
3343
3344        if (halmac_fifo_sel == HAL_FIFO_SEL_TX)
3345                fifo_size = halmac_adapter->hw_config_info.tx_fifo_size;
3346        else if (halmac_fifo_sel == HAL_FIFO_SEL_RX)
3347                fifo_size = halmac_adapter->hw_config_info.rx_fifo_size;
3348        else if (halmac_fifo_sel == HAL_FIFO_SEL_RSVD_PAGE)
3349                fifo_size =
3350                        ((halmac_adapter->hw_config_info.tx_fifo_size >> 7) -
3351                         halmac_adapter->txff_allocation.rsvd_pg_bndy)
3352                        << 7;
3353        else if (halmac_fifo_sel == HAL_FIFO_SEL_REPORT)
3354                fifo_size = 65536;
3355        else if (halmac_fifo_sel == HAL_FIFO_SEL_LLT)
3356                fifo_size = 65536;
3357
3358        return fifo_size;
3359}
3360
3361/**
3362 * halmac_cfg_txbf_88xx() - enable/disable specific user's txbf
3363 * @halmac_adapter : the adapter of halmac
3364 * @userid : su bfee userid = 0 or 1 to apply TXBF
3365 * @bw : the sounding bandwidth
3366 * @txbf_en : 0: disable TXBF, 1: enable TXBF
3367 * Author : chunchu
3368 * Return : enum halmac_ret_status
3369 * More details of status code can be found in prototype document
3370 */
3371enum halmac_ret_status
3372halmac_cfg_txbf_88xx(struct halmac_adapter *halmac_adapter, u8 userid,
3373                     enum halmac_bw bw, u8 txbf_en)
3374{
3375        u16 temp42C = 0;
3376        void *driver_adapter = NULL;
3377        struct halmac_api *halmac_api;
3378
3379        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3380                return HALMAC_RET_ADAPTER_INVALID;
3381
3382        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3383                return HALMAC_RET_API_INVALID;
3384
3385        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TXBF);
3386
3387        driver_adapter = halmac_adapter->driver_adapter;
3388        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3389
3390        if (txbf_en) {
3391                switch (bw) {
3392                case HALMAC_BW_80:
3393                        temp42C |= BIT_R_TXBF0_80M;
3394                        /* fall through */
3395                case HALMAC_BW_40:
3396                        temp42C |= BIT_R_TXBF0_40M;
3397                        /* fall through */
3398                case HALMAC_BW_20:
3399                        temp42C |= BIT_R_TXBF0_20M;
3400                        break;
3401                default:
3402                        pr_err("%s invalid TXBF BW setting 0x%x of userid %d\n",
3403                               __func__, bw, userid);
3404                        return HALMAC_RET_INVALID_SOUNDING_SETTING;
3405                }
3406        }
3407
3408        switch (userid) {
3409        case 0:
3410                temp42C |=
3411                        HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3412                        ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3413                HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL, temp42C);
3414                break;
3415        case 1:
3416                temp42C |=
3417                        HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3418                        ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3419                HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2, temp42C);
3420                break;
3421        default:
3422                pr_err("%s invalid userid %d\n", __func__, userid);
3423                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3424        }
3425
3426        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3427                        "%s, txbf_en = %x <==========\n", __func__,
3428                        txbf_en);
3429
3430        return HALMAC_RET_SUCCESS;
3431}
3432
3433/**
3434 * halmac_cfg_mumimo_88xx() -config mumimo
3435 * @halmac_adapter : the adapter of halmac
3436 * @cfgmu : parameters to configure MU PPDU Tx/Rx
3437 * Author : chunchu
3438 * Return : enum halmac_ret_status
3439 * More details of status code can be found in prototype document
3440 */
3441enum halmac_ret_status
3442halmac_cfg_mumimo_88xx(struct halmac_adapter *halmac_adapter,
3443                       struct halmac_cfg_mumimo_para *cfgmu)
3444{
3445        void *driver_adapter = NULL;
3446        struct halmac_api *halmac_api;
3447        u8 i, idx, id0, id1, gid, mu_tab_sel;
3448        u8 mu_tab_valid = 0;
3449        u32 gid_valid[6] = {0};
3450        u8 temp14C0 = 0;
3451
3452        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3453                return HALMAC_RET_ADAPTER_INVALID;
3454
3455        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3456                return HALMAC_RET_API_INVALID;
3457
3458        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MUMIMO);
3459
3460        driver_adapter = halmac_adapter->driver_adapter;
3461        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3462
3463        if (cfgmu->role == HAL_BFEE) {
3464                /*config MU BFEE*/
3465                temp14C0 = HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) &
3466                           ~BIT_MASK_R_MU_TABLE_VALID;
3467                /*enable MU table 0 and 1, disable MU TX*/
3468                HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3469                                   (temp14C0 | BIT(0) | BIT(1)) & ~(BIT(7)));
3470
3471                /*config GID valid table and user position table*/
3472                mu_tab_sel =
3473                        HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) &
3474                        ~(BIT(0) | BIT(1) | BIT(2));
3475                for (i = 0; i < 2; i++) {
3476                        HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1,
3477                                           mu_tab_sel | i);
3478                        HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD,
3479                                            cfgmu->given_gid_tab[i]);
3480                        HALMAC_REG_WRITE_32(halmac_adapter,
3481                                            REG_MU_STA_USER_POS_INFO,
3482                                            cfgmu->given_user_pos[i * 2]);
3483                        HALMAC_REG_WRITE_32(halmac_adapter,
3484                                            REG_MU_STA_USER_POS_INFO + 4,
3485                                            cfgmu->given_user_pos[i * 2 + 1]);
3486                }
3487        } else {
3488                /*config MU BFER*/
3489                if (!cfgmu->mu_tx_en) {
3490                        HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3491                                           HALMAC_REG_READ_8(halmac_adapter,
3492                                                             REG_MU_TX_CTL) &
3493                                                   ~(BIT(7)));
3494                        HALMAC_RT_TRACE(
3495                                driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3496                                "%s disable mu tx <==========\n", __func__);
3497                        return HALMAC_RET_SUCCESS;
3498                }
3499
3500                /*Transform BB grouping bitmap[14:0] to MAC GID_valid table*/
3501                for (idx = 0; idx < 15; idx++) {
3502                        if (idx < 5) {
3503                                /*group_bitmap bit0~4, MU_STA0 with MUSTA1~5*/
3504                                id0 = 0;
3505                                id1 = (u8)(idx + 1);
3506                        } else if (idx < 9) {
3507                                /*group_bitmap bit5~8, MU_STA1 with MUSTA2~5*/
3508                                id0 = 1;
3509                                id1 = (u8)(idx - 3);
3510                        } else if (idx < 12) {
3511                                /*group_bitmap bit9~11, MU_STA2 with MUSTA3~5*/
3512                                id0 = 2;
3513                                id1 = (u8)(idx - 6);
3514                        } else if (idx < 14) {
3515                                /*group_bitmap bit12~13, MU_STA3 with MUSTA4~5*/
3516                                id0 = 3;
3517                                id1 = (u8)(idx - 8);
3518                        } else {
3519                                /*group_bitmap bit14, MU_STA4 with MUSTA5*/
3520                                id0 = 4;
3521                                id1 = (u8)(idx - 9);
3522                        }
3523                        if (cfgmu->grouping_bitmap & BIT(idx)) {
3524                                /*Pair 1*/
3525                                gid = (idx << 1) + 1;
3526                                gid_valid[id0] |= (BIT(gid));
3527                                gid_valid[id1] |= (BIT(gid));
3528                                /*Pair 2*/
3529                                gid += 1;
3530                                gid_valid[id0] |= (BIT(gid));
3531                                gid_valid[id1] |= (BIT(gid));
3532                        } else {
3533                                /*Pair 1*/
3534                                gid = (idx << 1) + 1;
3535                                gid_valid[id0] &= ~(BIT(gid));
3536                                gid_valid[id1] &= ~(BIT(gid));
3537                                /*Pair 2*/
3538                                gid += 1;
3539                                gid_valid[id0] &= ~(BIT(gid));
3540                                gid_valid[id1] &= ~(BIT(gid));
3541                        }
3542                }
3543
3544                /*set MU STA GID valid TABLE*/
3545                mu_tab_sel =
3546                        HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) &
3547                        ~(BIT(0) | BIT(1) | BIT(2));
3548                for (idx = 0; idx < 6; idx++) {
3549                        HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1,
3550                                           idx | mu_tab_sel);
3551                        HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD,
3552                                            gid_valid[idx]);
3553                }
3554
3555                /*To validate the sounding successful MU STA and enable MU TX*/
3556                for (i = 0; i < 6; i++) {
3557                        if (cfgmu->sounding_sts[i])
3558                                mu_tab_valid |= BIT(i);
3559                }
3560                HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3561                                   mu_tab_valid | BIT(7));
3562        }
3563        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3564                        "%s <==========\n", __func__);
3565        return HALMAC_RET_SUCCESS;
3566}
3567
3568/**
3569 * halmac_cfg_sounding_88xx() - configure general sounding
3570 * @halmac_adapter : the adapter of halmac
3571 * @role : driver's role, BFer or BFee
3572 * @datarate : set ndpa tx rate if driver is BFer, or set csi response rate
3573 *             if driver is BFee
3574 * Author : chunchu
3575 * Return : enum halmac_ret_status
3576 * More details of status code can be found in prototype document
3577 */
3578enum halmac_ret_status
3579halmac_cfg_sounding_88xx(struct halmac_adapter *halmac_adapter,
3580                         enum halmac_snd_role role,
3581                         enum halmac_data_rate datarate)
3582{
3583        void *driver_adapter = NULL;
3584        struct halmac_api *halmac_api;
3585
3586        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3587                return HALMAC_RET_ADAPTER_INVALID;
3588
3589        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3590                return HALMAC_RET_API_INVALID;
3591
3592        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_SOUNDING);
3593
3594        driver_adapter = halmac_adapter->driver_adapter;
3595        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3596
3597        switch (role) {
3598        case HAL_BFER:
3599                HALMAC_REG_WRITE_32(
3600                        halmac_adapter, REG_TXBF_CTRL,
3601                        HALMAC_REG_READ_32(halmac_adapter, REG_TXBF_CTRL) |
3602                                BIT_R_ENABLE_NDPA | BIT_USE_NDPA_PARAMETER |
3603                                BIT_R_EN_NDPA_INT | BIT_DIS_NDP_BFEN);
3604                HALMAC_REG_WRITE_8(halmac_adapter, REG_NDPA_RATE, datarate);
3605                HALMAC_REG_WRITE_8(
3606                        halmac_adapter, REG_NDPA_OPT_CTRL,
3607                        HALMAC_REG_READ_8(halmac_adapter, REG_NDPA_OPT_CTRL) &
3608                                (~(BIT(0) | BIT(1))));
3609                /*service file length 2 bytes; fix non-STA1 csi start offset */
3610                HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 1,
3611                                   0x2 | BIT(7));
3612                HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 2, 0x2);
3613                break;
3614        case HAL_BFEE:
3615                HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0xDB);
3616                HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 3, 0x50);
3617                /*use ndpa rx rate to decide csi rate*/
3618                HALMAC_REG_WRITE_8(halmac_adapter, REG_BBPSF_CTRL + 3,
3619                                   HALMAC_OFDM54 | BIT(6));
3620                HALMAC_REG_WRITE_16(
3621                        halmac_adapter, REG_RRSR,
3622                        HALMAC_REG_READ_16(halmac_adapter, REG_RRSR) |
3623                                BIT(datarate));
3624                /*RXFF do not accept BF Rpt Poll, avoid CSI crc error*/
3625                HALMAC_REG_WRITE_8(
3626                        halmac_adapter, REG_RXFLTMAP1,
3627                        HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP1) &
3628                                (~(BIT(4))));
3629                /*FWFF do not accept BF Rpt Poll, avoid CSI crc error*/
3630                HALMAC_REG_WRITE_8(
3631                        halmac_adapter, REG_RXFLTMAP4,
3632                        HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP4) &
3633                                (~(BIT(4))));
3634                break;
3635        default:
3636                pr_err("%s invalid role\n", __func__);
3637                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3638        }
3639
3640        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3641                        "%s <==========\n", __func__);
3642
3643        return HALMAC_RET_SUCCESS;
3644}
3645
3646/**
3647 * halmac_del_sounding_88xx() - reset general sounding
3648 * @halmac_adapter : the adapter of halmac
3649 * @role : driver's role, BFer or BFee
3650 * Author : chunchu
3651 * Return : enum halmac_ret_status
3652 * More details of status code can be found in prototype document
3653 */
3654enum halmac_ret_status
3655halmac_del_sounding_88xx(struct halmac_adapter *halmac_adapter,
3656                         enum halmac_snd_role role)
3657{
3658        void *driver_adapter = NULL;
3659        struct halmac_api *halmac_api;
3660
3661        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3662                return HALMAC_RET_ADAPTER_INVALID;
3663
3664        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3665                return HALMAC_RET_API_INVALID;
3666
3667        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEL_SOUNDING);
3668
3669        driver_adapter = halmac_adapter->driver_adapter;
3670        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3671
3672        switch (role) {
3673        case HAL_BFER:
3674                HALMAC_REG_WRITE_8(halmac_adapter, REG_TXBF_CTRL + 3, 0);
3675                break;
3676        case HAL_BFEE:
3677                HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0);
3678                break;
3679        default:
3680                pr_err("%s invalid role\n", __func__);
3681                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3682        }
3683
3684        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3685                        "%s <==========\n", __func__);
3686
3687        return HALMAC_RET_SUCCESS;
3688}
3689
3690/**
3691 * halmac_su_bfee_entry_init_88xx() - config SU beamformee's registers
3692 * @halmac_adapter : the adapter of halmac
3693 * @userid : SU bfee userid = 0 or 1 to be added
3694 * @paid : partial AID of this bfee
3695 * Author : chunchu
3696 * Return : enum halmac_ret_status
3697 * More details of status code can be found in prototype document
3698 */
3699enum halmac_ret_status
3700halmac_su_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, u8 userid,
3701                               u16 paid)
3702{
3703        u16 temp42C = 0;
3704        void *driver_adapter = NULL;
3705        struct halmac_api *halmac_api;
3706
3707        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3708                return HALMAC_RET_ADAPTER_INVALID;
3709
3710        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3711                return HALMAC_RET_API_INVALID;
3712
3713        halmac_api_record_id_88xx(halmac_adapter,
3714                                  HALMAC_API_SU_BFEE_ENTRY_INIT);
3715
3716        driver_adapter = halmac_adapter->driver_adapter;
3717        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3718
3719        switch (userid) {
3720        case 0:
3721                temp42C = HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3722                          ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
3723                            BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3724                HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL,
3725                                    temp42C | paid);
3726                HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL,
3727                                    paid);
3728                break;
3729        case 1:
3730                temp42C =
3731                        HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3732                        ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
3733                          BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3734                HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2,
3735                                    temp42C | paid);
3736                HALMAC_REG_WRITE_16(halmac_adapter,
3737                                    REG_ASSOCIATED_BFMEE_SEL + 2,
3738                                    paid | BIT(9));
3739                break;
3740        default:
3741                pr_err("%s invalid userid %d\n", __func__,
3742                       userid);
3743                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3744        }
3745
3746        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3747                        "%s <==========\n", __func__);
3748
3749        return HALMAC_RET_SUCCESS;
3750}
3751
3752/**
3753 * halmac_su_bfee_entry_init_88xx() - config SU beamformer's registers
3754 * @halmac_adapter : the adapter of halmac
3755 * @su_bfer_init : parameters to configure SU BFER entry
3756 * Author : chunchu
3757 * Return : enum halmac_ret_status
3758 * More details of status code can be found in prototype document
3759 */
3760enum halmac_ret_status
3761halmac_su_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3762                               struct halmac_su_bfer_init_para *su_bfer_init)
3763{
3764        u16 mac_address_H;
3765        u32 mac_address_L;
3766        void *driver_adapter = NULL;
3767        struct halmac_api *halmac_api;
3768
3769        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3770                return HALMAC_RET_ADAPTER_INVALID;
3771
3772        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3773                return HALMAC_RET_API_INVALID;
3774
3775        halmac_api_record_id_88xx(halmac_adapter,
3776                                  HALMAC_API_SU_BFER_ENTRY_INIT);
3777
3778        driver_adapter = halmac_adapter->driver_adapter;
3779        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3780
3781        /* mac_address_L = bfer_address.address_l_h.address_low; */
3782        /* mac_address_H = bfer_address.address_l_h.address_high; */
3783
3784        mac_address_L = le32_to_cpu(
3785                su_bfer_init->bfer_address.address_l_h.le_address_low);
3786        mac_address_H = le16_to_cpu(
3787                su_bfer_init->bfer_address.address_l_h.le_address_high);
3788
3789        switch (su_bfer_init->userid) {
3790        case 0:
3791                HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
3792                                    mac_address_L);
3793                HALMAC_REG_WRITE_16(halmac_adapter,
3794                                    REG_ASSOCIATED_BFMER0_INFO + 4,
3795                                    mac_address_H);
3796                HALMAC_REG_WRITE_16(halmac_adapter,
3797                                    REG_ASSOCIATED_BFMER0_INFO + 6,
3798                                    su_bfer_init->paid);
3799                HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20,
3800                                    su_bfer_init->csi_para);
3801                break;
3802        case 1:
3803                HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO,
3804                                    mac_address_L);
3805                HALMAC_REG_WRITE_16(halmac_adapter,
3806                                    REG_ASSOCIATED_BFMER1_INFO + 4,
3807                                    mac_address_H);
3808                HALMAC_REG_WRITE_16(halmac_adapter,
3809                                    REG_ASSOCIATED_BFMER1_INFO + 6,
3810                                    su_bfer_init->paid);
3811                HALMAC_REG_WRITE_16(halmac_adapter,
3812                                    REG_TX_CSI_RPT_PARAM_BW20 + 2,
3813                                    su_bfer_init->csi_para);
3814                break;
3815        default:
3816                pr_err("%s invalid userid %d\n", __func__,
3817                       su_bfer_init->userid);
3818                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3819        }
3820
3821        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3822                        "%s <==========\n", __func__);
3823
3824        return HALMAC_RET_SUCCESS;
3825}
3826
3827/**
3828 * halmac_mu_bfee_entry_init_88xx() - config MU beamformee's registers
3829 * @halmac_adapter : the adapter of halmac
3830 * @mu_bfee_init : parameters to configure MU BFEE entry
3831 * Author : chunchu
3832 * Return : enum halmac_ret_status
3833 * More details of status code can be found in prototype document
3834 */
3835enum halmac_ret_status
3836halmac_mu_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3837                               struct halmac_mu_bfee_init_para *mu_bfee_init)
3838{
3839        u16 temp168X = 0, temp14C0;
3840        void *driver_adapter = NULL;
3841        struct halmac_api *halmac_api;
3842
3843        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3844                return HALMAC_RET_ADAPTER_INVALID;
3845
3846        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3847                return HALMAC_RET_API_INVALID;
3848
3849        halmac_api_record_id_88xx(halmac_adapter,
3850                                  HALMAC_API_MU_BFEE_ENTRY_INIT);
3851
3852        driver_adapter = halmac_adapter->driver_adapter;
3853        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3854
3855        temp168X |= mu_bfee_init->paid | BIT(9);
3856        HALMAC_REG_WRITE_16(halmac_adapter, (0x1680 + mu_bfee_init->userid * 2),
3857                            temp168X);
3858
3859        temp14C0 = HALMAC_REG_READ_16(halmac_adapter, REG_MU_TX_CTL) &
3860                   ~(BIT(8) | BIT(9) | BIT(10));
3861        HALMAC_REG_WRITE_16(halmac_adapter, REG_MU_TX_CTL,
3862                            temp14C0 | ((mu_bfee_init->userid - 2) << 8));
3863        HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD, 0);
3864        HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO,
3865                            mu_bfee_init->user_position_l);
3866        HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO + 4,
3867                            mu_bfee_init->user_position_h);
3868
3869        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3870                        "%s <==========\n", __func__);
3871
3872        return HALMAC_RET_SUCCESS;
3873}
3874
3875/**
3876 * halmac_mu_bfer_entry_init_88xx() - config MU beamformer's registers
3877 * @halmac_adapter : the adapter of halmac
3878 * @mu_bfer_init : parameters to configure MU BFER entry
3879 * Author : chunchu
3880 * Return : enum halmac_ret_status
3881 * More details of status code can be found in prototype document
3882 */
3883enum halmac_ret_status
3884halmac_mu_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3885                               struct halmac_mu_bfer_init_para *mu_bfer_init)
3886{
3887        u16 temp1680 = 0;
3888        u16 mac_address_H;
3889        u32 mac_address_L;
3890        void *driver_adapter = NULL;
3891        struct halmac_api *halmac_api;
3892
3893        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3894                return HALMAC_RET_ADAPTER_INVALID;
3895
3896        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3897                return HALMAC_RET_API_INVALID;
3898
3899        halmac_api_record_id_88xx(halmac_adapter,
3900                                  HALMAC_API_MU_BFER_ENTRY_INIT);
3901
3902        driver_adapter = halmac_adapter->driver_adapter;
3903        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3904
3905        mac_address_L =
3906            le32_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_low);
3907        mac_address_H =
3908            le16_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_high);
3909
3910        HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
3911                            mac_address_L);
3912        HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4,
3913                            mac_address_H);
3914        HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 6,
3915                            mu_bfer_init->paid);
3916        HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20,
3917                            mu_bfer_init->csi_para);
3918
3919        temp1680 = HALMAC_REG_READ_16(halmac_adapter, 0x1680) & 0xC000;
3920        temp1680 |= mu_bfer_init->my_aid | (mu_bfer_init->csi_length_sel << 12);
3921        HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, temp1680);
3922
3923        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3924                        "%s <==========\n", __func__);
3925
3926        return HALMAC_RET_SUCCESS;
3927}
3928
3929/**
3930 * halmac_su_bfee_entry_del_88xx() - reset SU beamformee's registers
3931 * @halmac_adapter : the adapter of halmac
3932 * @userid : the SU BFee userid to be deleted
3933 * Author : chunchu
3934 * Return : enum halmac_ret_status
3935 * More details of status code can be found in prototype document
3936 */
3937enum halmac_ret_status
3938halmac_su_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
3939{
3940        void *driver_adapter = NULL;
3941        struct halmac_api *halmac_api;
3942
3943        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3944                return HALMAC_RET_ADAPTER_INVALID;
3945
3946        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3947                return HALMAC_RET_API_INVALID;
3948
3949        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFEE_ENTRY_DEL);
3950
3951        driver_adapter = halmac_adapter->driver_adapter;
3952        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3953
3954        switch (userid) {
3955        case 0:
3956                HALMAC_REG_WRITE_16(
3957                        halmac_adapter, REG_TXBF_CTRL,
3958                        HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3959                                ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
3960                                  BIT_R_TXBF0_40M | BIT_R_TXBF0_80M));
3961                HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL,
3962                                    0);
3963                break;
3964        case 1:
3965                HALMAC_REG_WRITE_16(
3966                        halmac_adapter, REG_TXBF_CTRL + 2,
3967                        HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3968                                ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
3969                                  BIT_R_TXBF0_40M | BIT_R_TXBF0_80M));
3970                HALMAC_REG_WRITE_16(halmac_adapter,
3971                                    REG_ASSOCIATED_BFMEE_SEL + 2, 0);
3972                break;
3973        default:
3974                pr_err("%s invalid userid %d\n", __func__,
3975                       userid);
3976                return HALMAC_RET_INVALID_SOUNDING_SETTING;
3977        }
3978
3979        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3980                        "%s <==========\n", __func__);
3981
3982        return HALMAC_RET_SUCCESS;
3983}
3984
3985/**
3986 * halmac_su_bfee_entry_del_88xx() - reset SU beamformer's registers
3987 * @halmac_adapter : the adapter of halmac
3988 * @userid : the SU BFer userid to be deleted
3989 * Author : chunchu
3990 * Return : enum halmac_ret_status
3991 * More details of status code can be found in prototype document
3992 */
3993enum halmac_ret_status
3994halmac_su_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
3995{
3996        void *driver_adapter = NULL;
3997        struct halmac_api *halmac_api;
3998
3999        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4000                return HALMAC_RET_ADAPTER_INVALID;
4001
4002        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4003                return HALMAC_RET_API_INVALID;
4004
4005        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFER_ENTRY_DEL);
4006
4007        driver_adapter = halmac_adapter->driver_adapter;
4008        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4009
4010        switch (userid) {
4011        case 0:
4012                HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
4013                                    0);
4014                HALMAC_REG_WRITE_32(halmac_adapter,
4015                                    REG_ASSOCIATED_BFMER0_INFO + 4, 0);
4016                break;
4017        case 1:
4018                HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO,
4019                                    0);
4020                HALMAC_REG_WRITE_32(halmac_adapter,
4021                                    REG_ASSOCIATED_BFMER1_INFO + 4, 0);
4022                break;
4023        default:
4024                pr_err("%s invalid userid %d\n", __func__,
4025                       userid);
4026                return HALMAC_RET_INVALID_SOUNDING_SETTING;
4027        }
4028
4029        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4030                        "%s <==========\n", __func__);
4031
4032        return HALMAC_RET_SUCCESS;
4033}
4034
4035/**
4036 * halmac_mu_bfee_entry_del_88xx() - reset MU beamformee's registers
4037 * @halmac_adapter : the adapter of halmac
4038 * @userid : the MU STA userid to be deleted
4039 * Author : chunchu
4040 * Return : enum halmac_ret_status
4041 * More details of status code can be found in prototype document
4042 */
4043enum halmac_ret_status
4044halmac_mu_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
4045{
4046        void *driver_adapter = NULL;
4047        struct halmac_api *halmac_api;
4048
4049        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4050                return HALMAC_RET_ADAPTER_INVALID;
4051
4052        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4053                return HALMAC_RET_API_INVALID;
4054
4055        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFEE_ENTRY_DEL);
4056
4057        driver_adapter = halmac_adapter->driver_adapter;
4058        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4059
4060        HALMAC_REG_WRITE_16(halmac_adapter, 0x1680 + userid * 2, 0);
4061        HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
4062                           HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) &
4063                                   ~(BIT(userid - 2)));
4064
4065        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4066                        "%s <==========\n", __func__);
4067
4068        return HALMAC_RET_SUCCESS;
4069}
4070
4071/**
4072 * halmac_mu_bfer_entry_del_88xx() -reset MU beamformer's registers
4073 * @halmac_adapter : the adapter of halmac
4074 * Author : chunchu
4075 * Return : enum halmac_ret_status
4076 * More details of status code can be found in prototype document
4077 */
4078enum halmac_ret_status
4079halmac_mu_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter)
4080{
4081        void *driver_adapter = NULL;
4082        struct halmac_api *halmac_api;
4083
4084        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4085                return HALMAC_RET_ADAPTER_INVALID;
4086
4087        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4088                return HALMAC_RET_API_INVALID;
4089
4090        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFER_ENTRY_DEL);
4091
4092        driver_adapter = halmac_adapter->driver_adapter;
4093        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4094
4095        HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, 0);
4096        HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
4097        HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, 0);
4098        HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, 0);
4099
4100        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4101                        "%s <==========\n", __func__);
4102
4103        return HALMAC_RET_SUCCESS;
4104}
4105
4106/**
4107 * halmac_add_ch_info_88xx() -add channel information
4108 * @halmac_adapter : the adapter of halmac
4109 * @ch_info : channel information
4110 * Author : KaiYuan Chang/Ivan Lin
4111 * Return : enum halmac_ret_status
4112 * More details of status code can be found in prototype document
4113 */
4114enum halmac_ret_status
4115halmac_add_ch_info_88xx(struct halmac_adapter *halmac_adapter,
4116                        struct halmac_ch_info *ch_info)
4117{
4118        void *driver_adapter = NULL;
4119        struct halmac_cs_info *ch_sw_info;
4120        enum halmac_scan_cmd_construct_state state_scan;
4121
4122        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4123                return HALMAC_RET_ADAPTER_INVALID;
4124
4125        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4126                return HALMAC_RET_API_INVALID;
4127
4128        driver_adapter = halmac_adapter->driver_adapter;
4129        ch_sw_info = &halmac_adapter->ch_sw_info;
4130
4131        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4132                        "[TRACE]%s ==========>\n", __func__);
4133
4134        if (halmac_adapter->halmac_state.dlfw_state != HALMAC_GEN_INFO_SENT) {
4135                pr_err("[ERR]%s: gen_info is not send to FW!!!!\n", __func__);
4136                return HALMAC_RET_GEN_INFO_NOT_SENT;
4137        }
4138
4139        state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter);
4140        if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED &&
4141            state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4142                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_WARNING,
4143                                "[WARN]Scan machine fail(add ch info)...\n");
4144                return HALMAC_RET_ERROR_STATE;
4145        }
4146
4147        if (!ch_sw_info->ch_info_buf) {
4148                ch_sw_info->ch_info_buf =
4149                        kzalloc(HALMAC_EXTRA_INFO_BUFF_SIZE_88XX, GFP_KERNEL);
4150                if (!ch_sw_info->ch_info_buf)
4151                        return HALMAC_RET_NULL_POINTER;
4152                ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf;
4153                ch_sw_info->buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX;
4154                ch_sw_info->avai_buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX;
4155                ch_sw_info->total_size = 0;
4156                ch_sw_info->extra_info_en = 0;
4157                ch_sw_info->ch_num = 0;
4158        }
4159
4160        if (ch_sw_info->extra_info_en == 1) {
4161                pr_err("[ERR]%s: construct sequence wrong!!\n", __func__);
4162                return HALMAC_RET_CH_SW_SEQ_WRONG;
4163        }
4164
4165        if (ch_sw_info->avai_buf_size < 4) {
4166                pr_err("[ERR]%s: no available buffer!!\n", __func__);
4167                return HALMAC_RET_CH_SW_NO_BUF;
4168        }
4169
4170        if (halmac_transition_scan_state_88xx(
4171                    halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) !=
4172            HALMAC_RET_SUCCESS)
4173                return HALMAC_RET_ERROR_STATE;
4174
4175        CHANNEL_INFO_SET_CHANNEL(ch_sw_info->ch_info_buf_w, ch_info->channel);
4176        CHANNEL_INFO_SET_PRI_CH_IDX(ch_sw_info->ch_info_buf_w,
4177                                    ch_info->pri_ch_idx);
4178        CHANNEL_INFO_SET_BANDWIDTH(ch_sw_info->ch_info_buf_w, ch_info->bw);
4179        CHANNEL_INFO_SET_TIMEOUT(ch_sw_info->ch_info_buf_w, ch_info->timeout);
4180        CHANNEL_INFO_SET_ACTION_ID(ch_sw_info->ch_info_buf_w,
4181                                   ch_info->action_id);
4182        CHANNEL_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w,
4183                                       ch_info->extra_info);
4184
4185        ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size - 4;
4186        ch_sw_info->total_size = ch_sw_info->total_size + 4;
4187        ch_sw_info->ch_num++;
4188        ch_sw_info->extra_info_en = ch_info->extra_info;
4189        ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w + 4;
4190
4191        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4192                        "[TRACE]%s <==========\n", __func__);
4193
4194        return HALMAC_RET_SUCCESS;
4195}
4196
4197/**
4198 * halmac_add_extra_ch_info_88xx() -add extra channel information
4199 * @halmac_adapter : the adapter of halmac
4200 * @ch_extra_info : extra channel information
4201 * Author : KaiYuan Chang/Ivan Lin
4202 * Return : enum halmac_ret_status
4203 * More details of status code can be found in prototype document
4204 */
4205enum halmac_ret_status
4206halmac_add_extra_ch_info_88xx(struct halmac_adapter *halmac_adapter,
4207                              struct halmac_ch_extra_info *ch_extra_info)
4208{
4209        void *driver_adapter = NULL;
4210        struct halmac_cs_info *ch_sw_info;
4211
4212        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4213                return HALMAC_RET_ADAPTER_INVALID;
4214
4215        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4216                return HALMAC_RET_API_INVALID;
4217
4218        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ADD_EXTRA_CH_INFO);
4219
4220        driver_adapter = halmac_adapter->driver_adapter;
4221        ch_sw_info = &halmac_adapter->ch_sw_info;
4222
4223        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4224                        "%s ==========>\n", __func__);
4225
4226        if (!ch_sw_info->ch_info_buf) {
4227                pr_err("%s: NULL==ch_sw_info->ch_info_buf!!\n", __func__);
4228                return HALMAC_RET_CH_SW_SEQ_WRONG;
4229        }
4230
4231        if (ch_sw_info->extra_info_en == 0) {
4232                pr_err("%s: construct sequence wrong!!\n", __func__);
4233                return HALMAC_RET_CH_SW_SEQ_WRONG;
4234        }
4235
4236        if (ch_sw_info->avai_buf_size <
4237            (u32)(ch_extra_info->extra_info_size + 2)) {
4238                /* +2: ch_extra_info_id, ch_extra_info, ch_extra_info_size
4239                 * are totally 2Byte
4240                 */
4241                pr_err("%s: no available buffer!!\n", __func__);
4242                return HALMAC_RET_CH_SW_NO_BUF;
4243        }
4244
4245        if (halmac_query_scan_curr_state_88xx(halmac_adapter) !=
4246            HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4247                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4248                                "Scan machine fail(add extra ch info)...\n");
4249                return HALMAC_RET_ERROR_STATE;
4250        }
4251
4252        if (halmac_transition_scan_state_88xx(
4253                    halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) !=
4254            HALMAC_RET_SUCCESS)
4255                return HALMAC_RET_ERROR_STATE;
4256
4257        CH_EXTRA_INFO_SET_CH_EXTRA_INFO_ID(ch_sw_info->ch_info_buf_w,
4258                                           ch_extra_info->extra_action_id);
4259        CH_EXTRA_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w,
4260                                        ch_extra_info->extra_info);
4261        CH_EXTRA_INFO_SET_CH_EXTRA_INFO_SIZE(ch_sw_info->ch_info_buf_w,
4262                                             ch_extra_info->extra_info_size);
4263        memcpy(ch_sw_info->ch_info_buf_w + 2, ch_extra_info->extra_info_data,
4264               ch_extra_info->extra_info_size);
4265
4266        ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size -
4267                                    (2 + ch_extra_info->extra_info_size);
4268        ch_sw_info->total_size =
4269                ch_sw_info->total_size + (2 + ch_extra_info->extra_info_size);
4270        ch_sw_info->extra_info_en = ch_extra_info->extra_info;
4271        ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w +
4272                                    (2 + ch_extra_info->extra_info_size);
4273
4274        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4275                        "%s <==========\n", __func__);
4276
4277        return HALMAC_RET_SUCCESS;
4278}
4279
4280/**
4281 * halmac_ctrl_ch_switch_88xx() -send channel switch cmd
4282 * @halmac_adapter : the adapter of halmac
4283 * @cs_option : channel switch config
4284 * Author : KaiYuan Chang/Ivan Lin
4285 * Return : enum halmac_ret_status
4286 * More details of status code can be found in prototype document
4287 */
4288enum halmac_ret_status
4289halmac_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter,
4290                           struct halmac_ch_switch_option *cs_option)
4291{
4292        void *driver_adapter = NULL;
4293        struct halmac_api *halmac_api;
4294        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4295        enum halmac_scan_cmd_construct_state state_scan;
4296        enum halmac_cmd_process_status *process_status =
4297                &halmac_adapter->halmac_state.scan_state_set.process_status;
4298
4299        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4300                return HALMAC_RET_ADAPTER_INVALID;
4301
4302        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4303                return HALMAC_RET_API_INVALID;
4304
4305        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4306                return HALMAC_RET_NO_DLFW;
4307
4308        if (halmac_adapter->fw_version.h2c_version < 4)
4309                return HALMAC_RET_FW_NO_SUPPORT;
4310
4311        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_CH_SWITCH);
4312
4313        driver_adapter = halmac_adapter->driver_adapter;
4314        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4315
4316        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4317                        "%s  cs_option->switch_en = %d==========>\n", __func__,
4318                        cs_option->switch_en);
4319
4320        if (!cs_option->switch_en)
4321                *process_status = HALMAC_CMD_PROCESS_IDLE;
4322
4323        if (*process_status == HALMAC_CMD_PROCESS_SENDING ||
4324            *process_status == HALMAC_CMD_PROCESS_RCVD) {
4325                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4326                                "Wait event(ctrl ch switch)...\n");
4327                return HALMAC_RET_BUSY_STATE;
4328        }
4329
4330        state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter);
4331        if (cs_option->switch_en) {
4332                if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4333                        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C,
4334                                        DBG_DMESG,
4335                                        "%s(on)  invalid in state %x\n",
4336                                        __func__, state_scan);
4337                        return HALMAC_RET_ERROR_STATE;
4338                }
4339        } else {
4340                if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) {
4341                        HALMAC_RT_TRACE(
4342                                driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4343                                "%s(off)  invalid in state %x\n", __func__,
4344                                state_scan);
4345                        return HALMAC_RET_ERROR_STATE;
4346                }
4347        }
4348
4349        status = halmac_func_ctrl_ch_switch_88xx(halmac_adapter, cs_option);
4350
4351        if (status != HALMAC_RET_SUCCESS) {
4352                pr_err("halmac_ctrl_ch_switch FAIL = %x!!\n", status);
4353                return status;
4354        }
4355
4356        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4357                        "%s <==========\n", __func__);
4358
4359        return HALMAC_RET_SUCCESS;
4360}
4361
4362/**
4363 * halmac_clear_ch_info_88xx() -clear channel information
4364 * @halmac_adapter : the adapter of halmac
4365 * Author : KaiYuan Chang/Ivan Lin
4366 * Return : enum halmac_ret_status
4367 * More details of status code can be found in prototype document
4368 */
4369enum halmac_ret_status
4370halmac_clear_ch_info_88xx(struct halmac_adapter *halmac_adapter)
4371{
4372        void *driver_adapter = NULL;
4373        struct halmac_api *halmac_api;
4374
4375        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4376                return HALMAC_RET_ADAPTER_INVALID;
4377
4378        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4379                return HALMAC_RET_API_INVALID;
4380
4381        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CLEAR_CH_INFO);
4382
4383        driver_adapter = halmac_adapter->driver_adapter;
4384        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4385
4386        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4387                        "%s ==========>\n", __func__);
4388
4389        if (halmac_query_scan_curr_state_88xx(halmac_adapter) ==
4390            HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) {
4391                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4392                                "Scan machine fail(clear ch info)...\n");
4393                return HALMAC_RET_ERROR_STATE;
4394        }
4395
4396        if (halmac_transition_scan_state_88xx(
4397                    halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) !=
4398            HALMAC_RET_SUCCESS)
4399                return HALMAC_RET_ERROR_STATE;
4400
4401        kfree(halmac_adapter->ch_sw_info.ch_info_buf);
4402        halmac_adapter->ch_sw_info.ch_info_buf = NULL;
4403        halmac_adapter->ch_sw_info.ch_info_buf_w = NULL;
4404        halmac_adapter->ch_sw_info.extra_info_en = 0;
4405        halmac_adapter->ch_sw_info.buf_size = 0;
4406        halmac_adapter->ch_sw_info.avai_buf_size = 0;
4407        halmac_adapter->ch_sw_info.total_size = 0;
4408        halmac_adapter->ch_sw_info.ch_num = 0;
4409
4410        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4411                        "%s <==========\n", __func__);
4412
4413        return HALMAC_RET_SUCCESS;
4414}
4415
4416enum halmac_ret_status halmac_p2pps_88xx(struct halmac_adapter *halmac_adapter,
4417                                         struct halmac_p2pps *p2p_ps)
4418{
4419        void *driver_adapter = NULL;
4420        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4421
4422        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4423                return HALMAC_RET_ADAPTER_INVALID;
4424
4425        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4426                return HALMAC_RET_API_INVALID;
4427
4428        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4429                return HALMAC_RET_NO_DLFW;
4430
4431        if (halmac_adapter->fw_version.h2c_version < 6)
4432                return HALMAC_RET_FW_NO_SUPPORT;
4433
4434        driver_adapter = halmac_adapter->driver_adapter;
4435
4436        status = halmac_func_p2pps_88xx(halmac_adapter, p2p_ps);
4437
4438        if (status != HALMAC_RET_SUCCESS) {
4439                pr_err("[ERR]halmac_p2pps FAIL = %x!!\n", status);
4440                return status;
4441        }
4442
4443        return HALMAC_RET_SUCCESS;
4444}
4445
4446enum halmac_ret_status
4447halmac_func_p2pps_88xx(struct halmac_adapter *halmac_adapter,
4448                       struct halmac_p2pps *p2p_ps)
4449{
4450        u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4451        u16 h2c_seq_mum = 0;
4452        void *driver_adapter = halmac_adapter->driver_adapter;
4453        struct halmac_api *halmac_api;
4454        struct halmac_h2c_header_info h2c_header_info;
4455        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4456
4457        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4458                        "[TRACE]halmac_p2pps !!\n");
4459
4460        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4461
4462        P2PPS_SET_OFFLOAD_EN(h2c_buff, p2p_ps->offload_en);
4463        P2PPS_SET_ROLE(h2c_buff, p2p_ps->role);
4464        P2PPS_SET_CTWINDOW_EN(h2c_buff, p2p_ps->ctwindow_en);
4465        P2PPS_SET_NOA_EN(h2c_buff, p2p_ps->noa_en);
4466        P2PPS_SET_NOA_SEL(h2c_buff, p2p_ps->noa_sel);
4467        P2PPS_SET_ALLSTASLEEP(h2c_buff, p2p_ps->all_sta_sleep);
4468        P2PPS_SET_DISCOVERY(h2c_buff, p2p_ps->discovery);
4469        P2PPS_SET_P2P_PORT_ID(h2c_buff, p2p_ps->p2p_port_id);
4470        P2PPS_SET_P2P_GROUP(h2c_buff, p2p_ps->p2p_group);
4471        P2PPS_SET_P2P_MACID(h2c_buff, p2p_ps->p2p_macid);
4472
4473        P2PPS_SET_CTWINDOW_LENGTH(h2c_buff, p2p_ps->ctwindow_length);
4474
4475        P2PPS_SET_NOA_DURATION_PARA(h2c_buff, p2p_ps->noa_duration_para);
4476        P2PPS_SET_NOA_INTERVAL_PARA(h2c_buff, p2p_ps->noa_interval_para);
4477        P2PPS_SET_NOA_START_TIME_PARA(h2c_buff, p2p_ps->noa_start_time_para);
4478        P2PPS_SET_NOA_COUNT_PARA(h2c_buff, p2p_ps->noa_count_para);
4479
4480        h2c_header_info.sub_cmd_id = SUB_CMD_ID_P2PPS;
4481        h2c_header_info.content_size = 24;
4482        h2c_header_info.ack = false;
4483        halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4484                                              &h2c_header_info, &h2c_seq_mum);
4485
4486        status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4487                                          HALMAC_H2C_CMD_SIZE_88XX, false);
4488
4489        if (status != HALMAC_RET_SUCCESS)
4490                pr_err("[ERR]halmac_send_h2c_p2pps_88xx Fail = %x!!\n", status);
4491
4492        return status;
4493}
4494
4495/**
4496 * halmac_send_general_info_88xx() -send general information to FW
4497 * @halmac_adapter : the adapter of halmac
4498 * @general_info : general information
4499 * Author : KaiYuan Chang/Ivan Lin
4500 * Return : enum halmac_ret_status
4501 * More details of status code can be found in prototype document
4502 */
4503enum halmac_ret_status
4504halmac_send_general_info_88xx(struct halmac_adapter *halmac_adapter,
4505                              struct halmac_general_info *general_info)
4506{
4507        void *driver_adapter = NULL;
4508        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4509
4510        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4511                return HALMAC_RET_ADAPTER_INVALID;
4512
4513        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4514                return HALMAC_RET_API_INVALID;
4515
4516        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4517                return HALMAC_RET_NO_DLFW;
4518
4519        if (halmac_adapter->fw_version.h2c_version < 4)
4520                return HALMAC_RET_FW_NO_SUPPORT;
4521
4522        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_GENERAL_INFO);
4523
4524        driver_adapter = halmac_adapter->driver_adapter;
4525
4526        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4527                        "%s ==========>\n", __func__);
4528
4529        if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) {
4530                pr_err("%s Fail due to DLFW NONE!!\n", __func__);
4531                return HALMAC_RET_DLFW_FAIL;
4532        }
4533
4534        status = halmac_func_send_general_info_88xx(halmac_adapter,
4535                                                    general_info);
4536
4537        if (status != HALMAC_RET_SUCCESS) {
4538                pr_err("halmac_send_general_info error = %x\n", status);
4539                return status;
4540        }
4541
4542        if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_DONE)
4543                halmac_adapter->halmac_state.dlfw_state = HALMAC_GEN_INFO_SENT;
4544
4545        halmac_adapter->gen_info_valid = true;
4546        memcpy(&halmac_adapter->general_info, general_info,
4547               sizeof(struct halmac_general_info));
4548
4549        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4550                        "%s <==========\n", __func__);
4551
4552        return HALMAC_RET_SUCCESS;
4553}
4554
4555/**
4556 * halmac_start_iqk_88xx() -trigger FW IQK
4557 * @halmac_adapter : the adapter of halmac
4558 * @iqk_para : IQK parameter
4559 * Author : KaiYuan Chang/Ivan Lin
4560 * Return : enum halmac_ret_status
4561 * More details of status code can be found in prototype document
4562 */
4563enum halmac_ret_status
4564halmac_start_iqk_88xx(struct halmac_adapter *halmac_adapter,
4565                      struct halmac_iqk_para_ *iqk_para)
4566{
4567        u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4568        u16 h2c_seq_num = 0;
4569        void *driver_adapter = NULL;
4570        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4571        struct halmac_h2c_header_info h2c_header_info;
4572        enum halmac_cmd_process_status *process_status =
4573                &halmac_adapter->halmac_state.iqk_set.process_status;
4574
4575        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4576                return HALMAC_RET_ADAPTER_INVALID;
4577
4578        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4579                return HALMAC_RET_API_INVALID;
4580
4581        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4582                return HALMAC_RET_NO_DLFW;
4583
4584        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_START_IQK);
4585
4586        driver_adapter = halmac_adapter->driver_adapter;
4587
4588        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4589                        "%s ==========>\n", __func__);
4590
4591        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
4592                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4593                                "Wait event(iqk)...\n");
4594                return HALMAC_RET_BUSY_STATE;
4595        }
4596
4597        *process_status = HALMAC_CMD_PROCESS_SENDING;
4598
4599        IQK_SET_CLEAR(h2c_buff, iqk_para->clear);
4600        IQK_SET_SEGMENT_IQK(h2c_buff, iqk_para->segment_iqk);
4601
4602        h2c_header_info.sub_cmd_id = SUB_CMD_ID_IQK;
4603        h2c_header_info.content_size = 1;
4604        h2c_header_info.ack = true;
4605        halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4606                                              &h2c_header_info, &h2c_seq_num);
4607
4608        halmac_adapter->halmac_state.iqk_set.seq_num = h2c_seq_num;
4609
4610        status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4611                                          HALMAC_H2C_CMD_SIZE_88XX, true);
4612
4613        if (status != HALMAC_RET_SUCCESS) {
4614                pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
4615                return status;
4616        }
4617
4618        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4619                        "%s <==========\n", __func__);
4620
4621        return HALMAC_RET_SUCCESS;
4622}
4623
4624/**
4625 * halmac_ctrl_pwr_tracking_88xx() -trigger FW power tracking
4626 * @halmac_adapter : the adapter of halmac
4627 * @pwr_tracking_opt : power tracking option
4628 * Author : KaiYuan Chang/Ivan Lin
4629 * Return : enum halmac_ret_status
4630 * More details of status code can be found in prototype document
4631 */
4632enum halmac_ret_status halmac_ctrl_pwr_tracking_88xx(
4633        struct halmac_adapter *halmac_adapter,
4634        struct halmac_pwr_tracking_option *pwr_tracking_opt)
4635{
4636        u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4637        u16 h2c_seq_mum = 0;
4638        void *driver_adapter = NULL;
4639        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4640        struct halmac_h2c_header_info h2c_header_info;
4641        enum halmac_cmd_process_status *process_status =
4642                &halmac_adapter->halmac_state.power_tracking_set.process_status;
4643
4644        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4645                return HALMAC_RET_ADAPTER_INVALID;
4646
4647        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4648                return HALMAC_RET_API_INVALID;
4649
4650        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4651                return HALMAC_RET_NO_DLFW;
4652
4653        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_PWR_TRACKING);
4654
4655        driver_adapter = halmac_adapter->driver_adapter;
4656
4657        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4658                        "halmac_start_iqk_88xx ==========>\n");
4659
4660        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
4661                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4662                                "Wait event(pwr tracking)...\n");
4663                return HALMAC_RET_BUSY_STATE;
4664        }
4665
4666        *process_status = HALMAC_CMD_PROCESS_SENDING;
4667
4668        POWER_TRACKING_SET_TYPE(h2c_buff, pwr_tracking_opt->type);
4669        POWER_TRACKING_SET_BBSWING_INDEX(h2c_buff,
4670                                         pwr_tracking_opt->bbswing_index);
4671        POWER_TRACKING_SET_ENABLE_A(
4672                h2c_buff,
4673                pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A].enable);
4674        POWER_TRACKING_SET_TX_PWR_INDEX_A(
4675                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4676                                  .tx_pwr_index);
4677        POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_A(
4678                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4679                                  .pwr_tracking_offset_value);
4680        POWER_TRACKING_SET_TSSI_VALUE_A(
4681                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4682                                  .tssi_value);
4683        POWER_TRACKING_SET_ENABLE_B(
4684                h2c_buff,
4685                pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B].enable);
4686        POWER_TRACKING_SET_TX_PWR_INDEX_B(
4687                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4688                                  .tx_pwr_index);
4689        POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_B(
4690                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4691                                  .pwr_tracking_offset_value);
4692        POWER_TRACKING_SET_TSSI_VALUE_B(
4693                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4694                                  .tssi_value);
4695        POWER_TRACKING_SET_ENABLE_C(
4696                h2c_buff,
4697                pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C].enable);
4698        POWER_TRACKING_SET_TX_PWR_INDEX_C(
4699                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4700                                  .tx_pwr_index);
4701        POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_C(
4702                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4703                                  .pwr_tracking_offset_value);
4704        POWER_TRACKING_SET_TSSI_VALUE_C(
4705                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4706                                  .tssi_value);
4707        POWER_TRACKING_SET_ENABLE_D(
4708                h2c_buff,
4709                pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D].enable);
4710        POWER_TRACKING_SET_TX_PWR_INDEX_D(
4711                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4712                                  .tx_pwr_index);
4713        POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_D(
4714                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4715                                  .pwr_tracking_offset_value);
4716        POWER_TRACKING_SET_TSSI_VALUE_D(
4717                h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4718                                  .tssi_value);
4719
4720        h2c_header_info.sub_cmd_id = SUB_CMD_ID_POWER_TRACKING;
4721        h2c_header_info.content_size = 20;
4722        h2c_header_info.ack = true;
4723        halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4724                                              &h2c_header_info, &h2c_seq_mum);
4725
4726        halmac_adapter->halmac_state.power_tracking_set.seq_num = h2c_seq_mum;
4727
4728        status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4729                                          HALMAC_H2C_CMD_SIZE_88XX, true);
4730
4731        if (status != HALMAC_RET_SUCCESS) {
4732                pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
4733                return status;
4734        }
4735
4736        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4737                        "halmac_start_iqk_88xx <==========\n");
4738
4739        return HALMAC_RET_SUCCESS;
4740}
4741
4742/**
4743 * halmac_query_status_88xx() -query the offload feature status
4744 * @halmac_adapter : the adapter of halmac
4745 * @feature_id : feature_id
4746 * @process_status : feature_status
4747 * @data : data buffer
4748 * @size : data size
4749 *
4750 * Note :
4751 * If user wants to know the data size, use can allocate zero
4752 * size buffer first. If this size less than the data size, halmac
4753 * will return  HALMAC_RET_BUFFER_TOO_SMALL. User need to
4754 * re-allocate data buffer with correct data size.
4755 *
4756 * Author : Ivan Lin/KaiYuan Chang
4757 * Return : enum halmac_ret_status
4758 * More details of status code can be found in prototype document
4759 */
4760enum halmac_ret_status
4761halmac_query_status_88xx(struct halmac_adapter *halmac_adapter,
4762                         enum halmac_feature_id feature_id,
4763                         enum halmac_cmd_process_status *process_status,
4764                         u8 *data, u32 *size)
4765{
4766        void *driver_adapter = NULL;
4767        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4768
4769        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4770                return HALMAC_RET_ADAPTER_INVALID;
4771
4772        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4773                return HALMAC_RET_API_INVALID;
4774
4775        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_QUERY_STATE);
4776
4777        driver_adapter = halmac_adapter->driver_adapter;
4778
4779        if (!process_status) {
4780                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4781                                "null pointer!!\n");
4782                return HALMAC_RET_NULL_POINTER;
4783        }
4784
4785        switch (feature_id) {
4786        case HALMAC_FEATURE_CFG_PARA:
4787                status = halmac_query_cfg_para_status_88xx(
4788                        halmac_adapter, process_status, data, size);
4789                break;
4790        case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
4791                status = halmac_query_dump_physical_efuse_status_88xx(
4792                        halmac_adapter, process_status, data, size);
4793                break;
4794        case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
4795                status = halmac_query_dump_logical_efuse_status_88xx(
4796                        halmac_adapter, process_status, data, size);
4797                break;
4798        case HALMAC_FEATURE_CHANNEL_SWITCH:
4799                status = halmac_query_channel_switch_status_88xx(
4800                        halmac_adapter, process_status, data, size);
4801                break;
4802        case HALMAC_FEATURE_UPDATE_PACKET:
4803                status = halmac_query_update_packet_status_88xx(
4804                        halmac_adapter, process_status, data, size);
4805                break;
4806        case HALMAC_FEATURE_IQK:
4807                status = halmac_query_iqk_status_88xx(
4808                        halmac_adapter, process_status, data, size);
4809                break;
4810        case HALMAC_FEATURE_POWER_TRACKING:
4811                status = halmac_query_power_tracking_status_88xx(
4812                        halmac_adapter, process_status, data, size);
4813                break;
4814        case HALMAC_FEATURE_PSD:
4815                status = halmac_query_psd_status_88xx(
4816                        halmac_adapter, process_status, data, size);
4817                break;
4818        default:
4819                pr_err("%s invalid feature id %d\n", __func__,
4820                       feature_id);
4821                return HALMAC_RET_INVALID_FEATURE_ID;
4822        }
4823
4824        return status;
4825}
4826
4827/**
4828 * halmac_reset_feature_88xx() -reset async api cmd status
4829 * @halmac_adapter : the adapter of halmac
4830 * @feature_id : feature_id
4831 * Author : Ivan Lin/KaiYuan Chang
4832 * Return : enum halmac_ret_status.
4833 * More details of status code can be found in prototype document
4834 */
4835enum halmac_ret_status
4836halmac_reset_feature_88xx(struct halmac_adapter *halmac_adapter,
4837                          enum halmac_feature_id feature_id)
4838{
4839        void *driver_adapter = NULL;
4840        struct halmac_state *state = &halmac_adapter->halmac_state;
4841
4842        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4843                return HALMAC_RET_ADAPTER_INVALID;
4844
4845        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4846                return HALMAC_RET_API_INVALID;
4847
4848        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_RESET_FEATURE);
4849
4850        driver_adapter = halmac_adapter->driver_adapter;
4851
4852        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4853                        "%s ==========>\n", __func__);
4854
4855        switch (feature_id) {
4856        case HALMAC_FEATURE_CFG_PARA:
4857                state->cfg_para_state_set.process_status =
4858                        HALMAC_CMD_PROCESS_IDLE;
4859                state->cfg_para_state_set.cfg_para_cmd_construct_state =
4860                        HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE;
4861                break;
4862        case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
4863        case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
4864                state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4865                state->efuse_state_set.efuse_cmd_construct_state =
4866                        HALMAC_EFUSE_CMD_CONSTRUCT_IDLE;
4867                break;
4868        case HALMAC_FEATURE_CHANNEL_SWITCH:
4869                state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4870                state->scan_state_set.scan_cmd_construct_state =
4871                        HALMAC_SCAN_CMD_CONSTRUCT_IDLE;
4872                break;
4873        case HALMAC_FEATURE_UPDATE_PACKET:
4874                state->update_packet_set.process_status =
4875                        HALMAC_CMD_PROCESS_IDLE;
4876                break;
4877        case HALMAC_FEATURE_ALL:
4878                state->cfg_para_state_set.process_status =
4879                        HALMAC_CMD_PROCESS_IDLE;
4880                state->cfg_para_state_set.cfg_para_cmd_construct_state =
4881                        HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE;
4882                state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4883                state->efuse_state_set.efuse_cmd_construct_state =
4884                        HALMAC_EFUSE_CMD_CONSTRUCT_IDLE;
4885                state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4886                state->scan_state_set.scan_cmd_construct_state =
4887                        HALMAC_SCAN_CMD_CONSTRUCT_IDLE;
4888                state->update_packet_set.process_status =
4889                        HALMAC_CMD_PROCESS_IDLE;
4890                break;
4891        default:
4892                pr_err("%s invalid feature id %d\n", __func__,
4893                       feature_id);
4894                return HALMAC_RET_INVALID_FEATURE_ID;
4895        }
4896
4897        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4898                        "%s <==========\n", __func__);
4899
4900        return HALMAC_RET_SUCCESS;
4901}
4902
4903/**
4904 * halmac_check_fw_status_88xx() -check fw status
4905 * @halmac_adapter : the adapter of halmac
4906 * @fw_status : fw status
4907 * Author : KaiYuan Chang/Ivan Lin
4908 * Return : enum halmac_ret_status
4909 * More details of status code can be found in prototype document
4910 */
4911enum halmac_ret_status
4912halmac_check_fw_status_88xx(struct halmac_adapter *halmac_adapter,
4913                            bool *fw_status)
4914{
4915        u32 value32 = 0, value32_backup = 0, i = 0;
4916        void *driver_adapter = NULL;
4917        struct halmac_api *halmac_api;
4918        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4919
4920        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4921                return HALMAC_RET_ADAPTER_INVALID;
4922
4923        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4924                return HALMAC_RET_API_INVALID;
4925
4926        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CHECK_FW_STATUS);
4927
4928        driver_adapter = halmac_adapter->driver_adapter;
4929        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4930
4931        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4932                        "%s ==========>\n", __func__);
4933
4934        value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG6);
4935
4936        if (value32 != 0) {
4937                pr_err("halmac_check_fw_status REG_FW_DBG6 !=0\n");
4938                *fw_status = false;
4939                return status;
4940        }
4941
4942        value32_backup = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7);
4943
4944        for (i = 0; i <= 10; i++) {
4945                value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7);
4946                if (value32_backup != value32)
4947                        break;
4948
4949                if (i == 10) {
4950                        pr_err("halmac_check_fw_status Polling FW PC fail\n");
4951                        *fw_status = false;
4952                        return status;
4953                }
4954        }
4955
4956        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4957                        "%s <==========\n", __func__);
4958
4959        return status;
4960}
4961
4962enum halmac_ret_status
4963halmac_dump_fw_dmem_88xx(struct halmac_adapter *halmac_adapter, u8 *dmem,
4964                         u32 *size)
4965{
4966        void *driver_adapter = NULL;
4967        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4968
4969        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4970                return HALMAC_RET_ADAPTER_INVALID;
4971
4972        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4973                return HALMAC_RET_API_INVALID;
4974
4975        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_FW_DMEM);
4976
4977        driver_adapter = halmac_adapter->driver_adapter;
4978
4979        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4980                        "%s ==========>\n", __func__);
4981
4982        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4983                        "%s <==========\n", __func__);
4984
4985        return status;
4986}
4987
4988/**
4989 * halmac_cfg_max_dl_size_88xx() - config max download FW size
4990 * @halmac_adapter : the adapter of halmac
4991 * @size : max download fw size
4992 *
4993 * Halmac uses this setting to set max packet size for
4994 * download FW.
4995 * If user has not called this API, halmac use default
4996 * setting for download FW
4997 * Note1 : size need multiple of 2
4998 * Note2 : max size is 31K
4999 *
5000 * Author : Ivan Lin/KaiYuan Chang
5001 * Return : enum halmac_ret_status
5002 * More details of status code can be found in prototype document
5003 */
5004enum halmac_ret_status
5005halmac_cfg_max_dl_size_88xx(struct halmac_adapter *halmac_adapter, u32 size)
5006{
5007        void *driver_adapter = NULL;
5008
5009        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5010                return HALMAC_RET_ADAPTER_INVALID;
5011
5012        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5013                return HALMAC_RET_API_INVALID;
5014
5015        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MAX_DL_SIZE);
5016
5017        driver_adapter = halmac_adapter->driver_adapter;
5018
5019        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5020                        "%s ==========>\n", __func__);
5021
5022        if (size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX_88XX) {
5023                pr_err("size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX!\n");
5024                return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
5025        }
5026
5027        if ((size & (2 - 1)) != 0) {
5028                pr_err("size is not power of 2!\n");
5029                return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
5030        }
5031
5032        halmac_adapter->max_download_size = size;
5033
5034        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5035                        "Cfg max size is : %X\n", size);
5036
5037        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5038                        "%s <==========\n", __func__);
5039
5040        return HALMAC_RET_SUCCESS;
5041}
5042
5043/**
5044 * halmac_psd_88xx() - trigger fw psd
5045 * @halmac_adapter : the adapter of halmac
5046 * @start_psd : start PSD
5047 * @end_psd : end PSD
5048 * Author : KaiYuan Chang/Ivan Lin
5049 * Return : enum halmac_ret_status
5050 * More details of status code can be found in prototype document
5051 */
5052enum halmac_ret_status halmac_psd_88xx(struct halmac_adapter *halmac_adapter,
5053                                       u16 start_psd, u16 end_psd)
5054{
5055        u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
5056        u16 h2c_seq_mum = 0;
5057        void *driver_adapter = NULL;
5058        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
5059        struct halmac_h2c_header_info h2c_header_info;
5060        enum halmac_cmd_process_status *process_status =
5061                &halmac_adapter->halmac_state.psd_set.process_status;
5062
5063        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5064                return HALMAC_RET_ADAPTER_INVALID;
5065
5066        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5067                return HALMAC_RET_API_INVALID;
5068
5069        if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5070                return HALMAC_RET_NO_DLFW;
5071
5072        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PSD);
5073
5074        driver_adapter = halmac_adapter->driver_adapter;
5075
5076        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5077                        "%s ==========>\n", __func__);
5078
5079        if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
5080                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5081                                "Wait event(psd)...\n");
5082                return HALMAC_RET_BUSY_STATE;
5083        }
5084
5085        kfree(halmac_adapter->halmac_state.psd_set.data);
5086        halmac_adapter->halmac_state.psd_set.data = (u8 *)NULL;
5087
5088        halmac_adapter->halmac_state.psd_set.data_size = 0;
5089        halmac_adapter->halmac_state.psd_set.segment_size = 0;
5090
5091        *process_status = HALMAC_CMD_PROCESS_SENDING;
5092
5093        PSD_SET_START_PSD(h2c_buff, start_psd);
5094        PSD_SET_END_PSD(h2c_buff, end_psd);
5095
5096        h2c_header_info.sub_cmd_id = SUB_CMD_ID_PSD;
5097        h2c_header_info.content_size = 4;
5098        h2c_header_info.ack = true;
5099        halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
5100                                              &h2c_header_info, &h2c_seq_mum);
5101
5102        status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
5103                                          HALMAC_H2C_CMD_SIZE_88XX, true);
5104
5105        if (status != HALMAC_RET_SUCCESS) {
5106                pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
5107                return status;
5108        }
5109
5110        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5111                        "%s <==========\n", __func__);
5112
5113        return HALMAC_RET_SUCCESS;
5114}
5115
5116/**
5117 * halmac_cfg_la_mode_88xx() - config la mode
5118 * @halmac_adapter : the adapter of halmac
5119 * @la_mode :
5120 *      disable : no TXFF space reserved for LA debug
5121 *      partial : partial TXFF space is reserved for LA debug
5122 *      full : all TXFF space is reserved for LA debug
5123 * Author : KaiYuan Chang
5124 * Return : enum halmac_ret_status
5125 * More details of status code can be found in prototype document
5126 */
5127enum halmac_ret_status
5128halmac_cfg_la_mode_88xx(struct halmac_adapter *halmac_adapter,
5129                        enum halmac_la_mode la_mode)
5130{
5131        void *driver_adapter = NULL;
5132
5133        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5134                return HALMAC_RET_ADAPTER_INVALID;
5135
5136        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5137                return HALMAC_RET_API_INVALID;
5138
5139        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_LA_MODE);
5140
5141        driver_adapter = halmac_adapter->driver_adapter;
5142
5143        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5144                        "%s ==========>la_mode = %d\n", __func__,
5145                        la_mode);
5146
5147        halmac_adapter->txff_allocation.la_mode = la_mode;
5148
5149        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5150                        "%s <==========\n", __func__);
5151
5152        return HALMAC_RET_SUCCESS;
5153}
5154
5155/**
5156 * halmac_cfg_rx_fifo_expanding_mode_88xx() - rx fifo expanding
5157 * @halmac_adapter : the adapter of halmac
5158 * @la_mode :
5159 *      disable : normal mode
5160 *      1 block : Rx FIFO + 1 FIFO block; Tx fifo - 1 FIFO block
5161 *      2 block : Rx FIFO + 2 FIFO block; Tx fifo - 2 FIFO block
5162 *      3 block : Rx FIFO + 3 FIFO block; Tx fifo - 3 FIFO block
5163 * Author : Soar
5164 * Return : enum halmac_ret_status
5165 * More details of status code can be found in prototype document
5166 */
5167enum halmac_ret_status halmac_cfg_rx_fifo_expanding_mode_88xx(
5168        struct halmac_adapter *halmac_adapter,
5169        enum halmac_rx_fifo_expanding_mode rx_fifo_expanding_mode)
5170{
5171        void *driver_adapter = NULL;
5172
5173        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5174                return HALMAC_RET_ADAPTER_INVALID;
5175
5176        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5177                return HALMAC_RET_API_INVALID;
5178
5179        halmac_api_record_id_88xx(halmac_adapter,
5180                                  HALMAC_API_CFG_RX_FIFO_EXPANDING_MODE);
5181
5182        driver_adapter = halmac_adapter->driver_adapter;
5183
5184        HALMAC_RT_TRACE(
5185                driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5186                "%s ==========>rx_fifo_expanding_mode = %d\n", __func__,
5187                rx_fifo_expanding_mode);
5188
5189        halmac_adapter->txff_allocation.rx_fifo_expanding_mode =
5190                rx_fifo_expanding_mode;
5191
5192        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5193                        "%s <==========\n", __func__);
5194
5195        return HALMAC_RET_SUCCESS;
5196}
5197
5198enum halmac_ret_status
5199halmac_config_security_88xx(struct halmac_adapter *halmac_adapter,
5200                            struct halmac_security_setting *sec_setting)
5201{
5202        struct halmac_api *halmac_api;
5203        void *driver_adapter = NULL;
5204
5205        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5206                return HALMAC_RET_ADAPTER_INVALID;
5207
5208        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5209                return HALMAC_RET_API_INVALID;
5210
5211        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5212        driver_adapter = halmac_adapter->driver_adapter;
5213
5214        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5215                        "%s ==========>\n", __func__);
5216
5217        HALMAC_REG_WRITE_16(halmac_adapter, REG_CR,
5218                            (u16)(HALMAC_REG_READ_16(halmac_adapter, REG_CR) |
5219                                  BIT_MAC_SEC_EN));
5220
5221        if (sec_setting->tx_encryption == 1)
5222                HALMAC_REG_WRITE_8(
5223                        halmac_adapter, REG_SECCFG,
5224                        HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(2));
5225        else
5226                HALMAC_REG_WRITE_8(
5227                        halmac_adapter, REG_SECCFG,
5228                        HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) &
5229                                ~(BIT(2)));
5230
5231        if (sec_setting->rx_decryption == 1)
5232                HALMAC_REG_WRITE_8(
5233                        halmac_adapter, REG_SECCFG,
5234                        HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(3));
5235        else
5236                HALMAC_REG_WRITE_8(
5237                        halmac_adapter, REG_SECCFG,
5238                        HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) &
5239                                ~(BIT(3)));
5240
5241        if (sec_setting->bip_enable == 1) {
5242                if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8822B)
5243                        return HALMAC_RET_BIP_NO_SUPPORT;
5244        }
5245
5246        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5247                        "%s <==========\n", __func__);
5248
5249        return HALMAC_RET_SUCCESS;
5250}
5251
5252u8 halmac_get_used_cam_entry_num_88xx(struct halmac_adapter *halmac_adapter,
5253                                      enum hal_security_type sec_type)
5254{
5255        u8 entry_num;
5256        void *driver_adapter = NULL;
5257
5258        driver_adapter = halmac_adapter->driver_adapter;
5259
5260        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5261                        "%s ==========>\n", __func__);
5262
5263        switch (sec_type) {
5264        case HAL_SECURITY_TYPE_WEP40:
5265        case HAL_SECURITY_TYPE_WEP104:
5266        case HAL_SECURITY_TYPE_TKIP:
5267        case HAL_SECURITY_TYPE_AES128:
5268        case HAL_SECURITY_TYPE_GCMP128:
5269        case HAL_SECURITY_TYPE_GCMSMS4:
5270        case HAL_SECURITY_TYPE_BIP:
5271                entry_num = 1;
5272                break;
5273        case HAL_SECURITY_TYPE_WAPI:
5274        case HAL_SECURITY_TYPE_AES256:
5275        case HAL_SECURITY_TYPE_GCMP256:
5276                entry_num = 2;
5277                break;
5278        default:
5279                entry_num = 0;
5280                break;
5281        }
5282
5283        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5284                        "%s <==========\n", __func__);
5285
5286        return entry_num;
5287}
5288
5289enum halmac_ret_status
5290halmac_write_cam_88xx(struct halmac_adapter *halmac_adapter, u32 entry_index,
5291                      struct halmac_cam_entry_info *cam_entry_info)
5292{
5293        u32 i;
5294        u32 command = 0x80010000;
5295        struct halmac_api *halmac_api;
5296        void *driver_adapter = NULL;
5297        struct halmac_cam_entry_format *cam_entry_format = NULL;
5298
5299        driver_adapter = halmac_adapter->driver_adapter;
5300        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5301
5302        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5303                        "[TRACE]%s ==========>\n", __func__);
5304
5305        if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5306                return HALMAC_RET_ENTRY_INDEX_ERROR;
5307
5308        if (cam_entry_info->key_id > 3)
5309                return HALMAC_RET_FAIL;
5310
5311        cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL);
5312        if (!cam_entry_format)
5313                return HALMAC_RET_NULL_POINTER;
5314
5315        cam_entry_format->key_id = cam_entry_info->key_id;
5316        cam_entry_format->valid = cam_entry_info->valid;
5317        memcpy(cam_entry_format->mac_address, cam_entry_info->mac_address, 6);
5318        memcpy(cam_entry_format->key, cam_entry_info->key, 16);
5319
5320        switch (cam_entry_info->security_type) {
5321        case HAL_SECURITY_TYPE_NONE:
5322                cam_entry_format->type = 0;
5323                break;
5324        case HAL_SECURITY_TYPE_WEP40:
5325                cam_entry_format->type = 1;
5326                break;
5327        case HAL_SECURITY_TYPE_WEP104:
5328                cam_entry_format->type = 5;
5329                break;
5330        case HAL_SECURITY_TYPE_TKIP:
5331                cam_entry_format->type = 2;
5332                break;
5333        case HAL_SECURITY_TYPE_AES128:
5334                cam_entry_format->type = 4;
5335                break;
5336        case HAL_SECURITY_TYPE_WAPI:
5337                cam_entry_format->type = 6;
5338                break;
5339        case HAL_SECURITY_TYPE_AES256:
5340                cam_entry_format->type = 4;
5341                cam_entry_format->ext_sectype = 1;
5342                break;
5343        case HAL_SECURITY_TYPE_GCMP128:
5344                cam_entry_format->type = 7;
5345                break;
5346        case HAL_SECURITY_TYPE_GCMP256:
5347        case HAL_SECURITY_TYPE_GCMSMS4:
5348                cam_entry_format->type = 7;
5349                cam_entry_format->ext_sectype = 1;
5350                break;
5351        case HAL_SECURITY_TYPE_BIP:
5352                cam_entry_format->type = cam_entry_info->unicast == 1 ? 4 : 0;
5353                cam_entry_format->mgnt = 1;
5354                cam_entry_format->grp = cam_entry_info->unicast == 1 ? 0 : 1;
5355                break;
5356        default:
5357                kfree(cam_entry_format);
5358                return HALMAC_RET_FAIL;
5359        }
5360
5361        for (i = 0; i < 8; i++) {
5362                HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5363                                    *((u32 *)cam_entry_format + i));
5364                HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5365                                    command | ((entry_index << 3) + i));
5366                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5367                                "[TRACE]1 - CAM entry format : %X\n",
5368                                *((u32 *)cam_entry_format + i));
5369                HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5370                                "[TRACE]1 - REG_CAMCMD : %X\n",
5371                                command | ((entry_index << 3) + i));
5372        }
5373
5374        if (cam_entry_info->security_type == HAL_SECURITY_TYPE_WAPI ||
5375            cam_entry_info->security_type == HAL_SECURITY_TYPE_AES256 ||
5376            cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMP256 ||
5377            cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMSMS4) {
5378                cam_entry_format->mic = 1;
5379                memcpy(cam_entry_format->key, cam_entry_info->key_ext, 16);
5380
5381                for (i = 0; i < 8; i++) {
5382                        HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5383                                            *((u32 *)cam_entry_format + i));
5384                        HALMAC_REG_WRITE_32(
5385                                halmac_adapter, REG_CAMCMD,
5386                                command | (((entry_index + 1) << 3) + i));
5387                        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON,
5388                                        DBG_DMESG,
5389                                        "[TRACE]2 - CAM entry format : %X\n",
5390                                        *((u32 *)cam_entry_format + i));
5391                        HALMAC_RT_TRACE(
5392                                driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5393                                "[TRACE]2 - REG_CAMCMD : %X\n",
5394                                command | (((entry_index + 1) << 3) + i));
5395                }
5396        }
5397
5398        kfree(cam_entry_format);
5399
5400        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5401                        "[TRACE]%s <==========\n", __func__);
5402
5403        return HALMAC_RET_SUCCESS;
5404}
5405
5406enum halmac_ret_status
5407halmac_read_cam_entry_88xx(struct halmac_adapter *halmac_adapter,
5408                           u32 entry_index,
5409                           struct halmac_cam_entry_format *content)
5410{
5411        u32 i;
5412        u32 command = 0x80000000;
5413        struct halmac_api *halmac_api;
5414        void *driver_adapter = NULL;
5415
5416        driver_adapter = halmac_adapter->driver_adapter;
5417        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5418
5419        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5420                        "%s ==========>\n", __func__);
5421
5422        if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5423                return HALMAC_RET_ENTRY_INDEX_ERROR;
5424
5425        for (i = 0; i < 8; i++) {
5426                HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5427                                    command | ((entry_index << 3) + i));
5428                *((u32 *)content + i) =
5429                        HALMAC_REG_READ_32(halmac_adapter, REG_CAMREAD);
5430        }
5431
5432        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5433                        "%s <==========\n", __func__);
5434
5435        return HALMAC_RET_SUCCESS;
5436}
5437
5438enum halmac_ret_status
5439halmac_clear_cam_entry_88xx(struct halmac_adapter *halmac_adapter,
5440                            u32 entry_index)
5441{
5442        u32 i;
5443        u32 command = 0x80010000;
5444        void *driver_adapter = NULL;
5445        struct halmac_api *halmac_api;
5446        struct halmac_cam_entry_format *cam_entry_format;
5447
5448        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5449                return HALMAC_RET_ADAPTER_INVALID;
5450
5451        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5452                return HALMAC_RET_API_INVALID;
5453
5454        driver_adapter = halmac_adapter->driver_adapter;
5455        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5456
5457        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5458                        "[TRACE]halmac_clear_security_cam_88xx ==========>\n");
5459
5460        if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5461                return HALMAC_RET_ENTRY_INDEX_ERROR;
5462
5463        cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL);
5464        if (!cam_entry_format)
5465                return HALMAC_RET_NULL_POINTER;
5466
5467        for (i = 0; i < 8; i++) {
5468                HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5469                                    *((u32 *)cam_entry_format + i));
5470                HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5471                                    command | ((entry_index << 3) + i));
5472        }
5473
5474        kfree(cam_entry_format);
5475
5476        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5477                        "[TRACE]halmac_clear_security_cam_88xx <==========\n");
5478
5479        return HALMAC_RET_SUCCESS;
5480}
5481
5482/**
5483 * halmac_get_hw_value_88xx() -get hw config value
5484 * @halmac_adapter : the adapter of halmac
5485 * @hw_id : hw id for driver to query
5486 * @pvalue : hw value, reference table to get data type
5487 * Author : KaiYuan Chang / Ivan Lin
5488 * Return : enum halmac_ret_status
5489 * More details of status code can be found in prototype document
5490 */
5491enum halmac_ret_status
5492halmac_get_hw_value_88xx(struct halmac_adapter *halmac_adapter,
5493                         enum halmac_hw_id hw_id, void *pvalue)
5494{
5495        void *driver_adapter = NULL;
5496        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
5497
5498        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5499                return HALMAC_RET_ADAPTER_INVALID;
5500
5501        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5502                return HALMAC_RET_API_INVALID;
5503
5504        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE);
5505
5506        driver_adapter = halmac_adapter->driver_adapter;
5507
5508        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5509                        "%s ==========>\n", __func__);
5510
5511        if (!pvalue) {
5512                pr_err("%s (!pvalue)==========>\n", __func__);
5513                return HALMAC_RET_NULL_POINTER;
5514        }
5515
5516        switch (hw_id) {
5517        case HALMAC_HW_RQPN_MAPPING:
5518                ((struct halmac_rqpn_map *)pvalue)->dma_map_vo =
5519                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO];
5520                ((struct halmac_rqpn_map *)pvalue)->dma_map_vi =
5521                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI];
5522                ((struct halmac_rqpn_map *)pvalue)->dma_map_be =
5523                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE];
5524                ((struct halmac_rqpn_map *)pvalue)->dma_map_bk =
5525                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK];
5526                ((struct halmac_rqpn_map *)pvalue)->dma_map_mg =
5527                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG];
5528                ((struct halmac_rqpn_map *)pvalue)->dma_map_hi =
5529                        halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI];
5530                break;
5531        case HALMAC_HW_EFUSE_SIZE:
5532                *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size;
5533                break;
5534        case HALMAC_HW_EEPROM_SIZE:
5535                *(u32 *)pvalue = halmac_adapter->hw_config_info.eeprom_size;
5536                break;
5537        case HALMAC_HW_BT_BANK_EFUSE_SIZE:
5538                *(u32 *)pvalue = halmac_adapter->hw_config_info.bt_efuse_size;
5539                break;
5540        case HALMAC_HW_BT_BANK1_EFUSE_SIZE:
5541        case HALMAC_HW_BT_BANK2_EFUSE_SIZE:
5542                *(u32 *)pvalue = 0;
5543                break;
5544        case HALMAC_HW_TXFIFO_SIZE:
5545                *(u32 *)pvalue = halmac_adapter->hw_config_info.tx_fifo_size;
5546                break;
5547        case HALMAC_HW_RSVD_PG_BNDY:
5548                *(u16 *)pvalue =
5549                        halmac_adapter->txff_allocation.rsvd_drv_pg_bndy;
5550                break;
5551        case HALMAC_HW_CAM_ENTRY_NUM:
5552                *(u8 *)pvalue = halmac_adapter->hw_config_info.cam_entry_num;
5553                break;
5554        case HALMAC_HW_WLAN_EFUSE_AVAILABLE_SIZE: /*Remove later*/
5555                status = halmac_dump_logical_efuse_map_88xx(halmac_adapter,
5556                                                            HALMAC_EFUSE_R_DRV);
5557                if (status != HALMAC_RET_SUCCESS)
5558                        return status;
5559                *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size -
5560                                 HALMAC_PROTECTED_EFUSE_SIZE_88XX -
5561                                 halmac_adapter->efuse_end;
5562                break;
5563        case HALMAC_HW_IC_VERSION:
5564                *(u8 *)pvalue = halmac_adapter->chip_version;
5565                break;
5566        case HALMAC_HW_PAGE_SIZE:
5567                *(u32 *)pvalue = halmac_adapter->hw_config_info.page_size;
5568                break;
5569        case HALMAC_HW_TX_AGG_ALIGN_SIZE:
5570                *(u16 *)pvalue = halmac_adapter->hw_config_info.tx_align_size;
5571                break;
5572        case HALMAC_HW_RX_AGG_ALIGN_SIZE:
5573                *(u8 *)pvalue = 8;
5574                break;
5575        case HALMAC_HW_DRV_INFO_SIZE:
5576                *(u8 *)pvalue = halmac_adapter->drv_info_size;
5577                break;
5578        case HALMAC_HW_TXFF_ALLOCATION:
5579                memcpy(pvalue, &halmac_adapter->txff_allocation,
5580                       sizeof(struct halmac_txff_allocation));
5581                break;
5582        case HALMAC_HW_TX_DESC_SIZE:
5583                *(u32 *)pvalue = halmac_adapter->hw_config_info.txdesc_size;
5584                break;
5585        case HALMAC_HW_RX_DESC_SIZE:
5586                *(u32 *)pvalue = halmac_adapter->hw_config_info.rxdesc_size;
5587                break;
5588        default:
5589                return HALMAC_RET_PARA_NOT_SUPPORT;
5590        }
5591
5592        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5593                        "%s <==========\n", __func__);
5594
5595        return HALMAC_RET_SUCCESS;
5596}
5597
5598/**
5599 * halmac_set_hw_value_88xx() -set hw config value
5600 * @halmac_adapter : the adapter of halmac
5601 * @hw_id : hw id for driver to config
5602 * @pvalue : hw value, reference table to get data type
5603 * Author : KaiYuan Chang / Ivan Lin
5604 * Return : enum halmac_ret_status
5605 * More details of status code can be found in prototype document
5606 */
5607enum halmac_ret_status
5608halmac_set_hw_value_88xx(struct halmac_adapter *halmac_adapter,
5609                         enum halmac_hw_id hw_id, void *pvalue)
5610{
5611        void *driver_adapter = NULL;
5612        enum halmac_ret_status status;
5613
5614        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5615                return HALMAC_RET_ADAPTER_INVALID;
5616
5617        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5618                return HALMAC_RET_API_INVALID;
5619
5620        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE);
5621
5622        driver_adapter = halmac_adapter->driver_adapter;
5623
5624        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5625                        "%s ==========>\n", __func__);
5626
5627        if (!pvalue) {
5628                pr_err("%s (!pvalue)==========>\n", __func__);
5629                return HALMAC_RET_NULL_POINTER;
5630        }
5631
5632        switch (hw_id) {
5633        case HALMAC_HW_USB_MODE:
5634                status = halmac_set_usb_mode_88xx(
5635                        halmac_adapter, *(enum halmac_usb_mode *)pvalue);
5636                if (status != HALMAC_RET_SUCCESS)
5637                        return status;
5638                break;
5639        case HALMAC_HW_SEQ_EN:
5640                break;
5641        case HALMAC_HW_BANDWIDTH:
5642                halmac_cfg_bw_88xx(halmac_adapter, *(enum halmac_bw *)pvalue);
5643                break;
5644        case HALMAC_HW_CHANNEL:
5645                halmac_cfg_ch_88xx(halmac_adapter, *(u8 *)pvalue);
5646                break;
5647        case HALMAC_HW_PRI_CHANNEL_IDX:
5648                halmac_cfg_pri_ch_idx_88xx(halmac_adapter,
5649                                           *(enum halmac_pri_ch_idx *)pvalue);
5650                break;
5651        case HALMAC_HW_EN_BB_RF:
5652                halmac_enable_bb_rf_88xx(halmac_adapter, *(u8 *)pvalue);
5653                break;
5654        case HALMAC_HW_SDIO_TX_PAGE_THRESHOLD:
5655                halmac_config_sdio_tx_page_threshold_88xx(
5656                        halmac_adapter,
5657                        (struct halmac_tx_page_threshold_info *)pvalue);
5658                break;
5659        case HALMAC_HW_AMPDU_CONFIG:
5660                halmac_config_ampdu_88xx(halmac_adapter,
5661                                         (struct halmac_ampdu_config *)pvalue);
5662                break;
5663        default:
5664                return HALMAC_RET_PARA_NOT_SUPPORT;
5665        }
5666
5667        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5668                        "%s <==========\n", __func__);
5669
5670        return HALMAC_RET_SUCCESS;
5671}
5672
5673/**
5674 * halmac_cfg_drv_rsvd_pg_num_88xx() -config reserved page number for driver
5675 * @halmac_adapter : the adapter of halmac
5676 * @pg_num : page number
5677 * Author : KaiYuan Chang
5678 * Return : enum halmac_ret_status
5679 * More details of status code can be found in prototype document
5680 */
5681enum halmac_ret_status
5682halmac_cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *halmac_adapter,
5683                                enum halmac_drv_rsvd_pg_num pg_num)
5684{
5685        void *driver_adapter = NULL;
5686
5687        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5688                return HALMAC_RET_ADAPTER_INVALID;
5689
5690        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5691                return HALMAC_RET_API_INVALID;
5692
5693        halmac_api_record_id_88xx(halmac_adapter,
5694                                  HALMAC_API_CFG_DRV_RSVD_PG_NUM);
5695
5696        driver_adapter = halmac_adapter->driver_adapter;
5697
5698        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5699                        "%s ==========>pg_num = %d\n", __func__,
5700                        pg_num);
5701
5702        switch (pg_num) {
5703        case HALMAC_RSVD_PG_NUM16:
5704                halmac_adapter->txff_allocation.rsvd_drv_pg_num = 16;
5705                break;
5706        case HALMAC_RSVD_PG_NUM24:
5707                halmac_adapter->txff_allocation.rsvd_drv_pg_num = 24;
5708                break;
5709        case HALMAC_RSVD_PG_NUM32:
5710                halmac_adapter->txff_allocation.rsvd_drv_pg_num = 32;
5711                break;
5712        }
5713
5714        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5715                        "%s <==========\n", __func__);
5716
5717        return HALMAC_RET_SUCCESS;
5718}
5719
5720enum halmac_ret_status
5721halmac_get_chip_version_88xx(struct halmac_adapter *halmac_adapter,
5722                             struct halmac_ver *version)
5723{
5724        void *driver_adapter = NULL;
5725        struct halmac_api *halmac_api;
5726
5727        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5728                return HALMAC_RET_ADAPTER_INVALID;
5729
5730        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5731                return HALMAC_RET_API_INVALID;
5732
5733        driver_adapter = halmac_adapter->driver_adapter;
5734        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5735
5736        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5737                        "%s ==========>\n", __func__);
5738        version->major_ver = (u8)HALMAC_MAJOR_VER_88XX;
5739        version->prototype_ver = (u8)HALMAC_PROTOTYPE_VER_88XX;
5740        version->minor_ver = (u8)HALMAC_MINOR_VER_88XX;
5741        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5742                        "%s <==========\n", __func__);
5743
5744        return HALMAC_RET_SUCCESS;
5745}
5746
5747/**
5748 * halmac_chk_txdesc_88xx() -check if the tx packet format is incorrect
5749 * @halmac_adapter : the adapter of halmac
5750 * @halmac_buf : tx Packet buffer, tx desc is included
5751 * @halmac_size : tx packet size
5752 * Author : KaiYuan Chang
5753 * Return : enum halmac_ret_status
5754 * More details of status code can be found in prototype document
5755 */
5756enum halmac_ret_status
5757halmac_chk_txdesc_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf,
5758                       u32 halmac_size)
5759{
5760        void *driver_adapter = NULL;
5761        struct halmac_api *halmac_api;
5762
5763        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5764                return HALMAC_RET_ADAPTER_INVALID;
5765
5766        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5767                return HALMAC_RET_API_INVALID;
5768
5769        driver_adapter = halmac_adapter->driver_adapter;
5770        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5771
5772        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5773                        "%s ==========>\n", __func__);
5774
5775        if (GET_TX_DESC_BMC(halmac_buf))
5776                if (GET_TX_DESC_AGG_EN(halmac_buf))
5777                        pr_err("TxDesc: Agg should not be set when BMC\n");
5778
5779        if (halmac_size < (GET_TX_DESC_TXPKTSIZE(halmac_buf) +
5780                           GET_TX_DESC_OFFSET(halmac_buf)))
5781                pr_err("TxDesc: PktSize too small\n");
5782
5783        return HALMAC_RET_SUCCESS;
5784}
5785
5786/**
5787 * halmac_dl_drv_rsvd_page_88xx() - download packet to rsvd page
5788 * @halmac_adapter : the adapter of halmac
5789 * @pg_offset : page offset of driver's rsvd page
5790 * @halmac_buf : data to be downloaded, tx_desc is not included
5791 * @halmac_size : data size to be downloaded
5792 * Author : KaiYuan Chang
5793 * Return : enum halmac_ret_status
5794 * More details of status code can be found in prototype document
5795 */
5796enum halmac_ret_status
5797halmac_dl_drv_rsvd_page_88xx(struct halmac_adapter *halmac_adapter,
5798                             u8 pg_offset, u8 *halmac_buf, u32 halmac_size)
5799{
5800        void *driver_adapter = NULL;
5801        struct halmac_api *halmac_api;
5802        enum halmac_ret_status ret_status;
5803        u16 drv_pg_bndy = 0;
5804        u32 dl_pg_num = 0;
5805
5806        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5807                return HALMAC_RET_ADAPTER_INVALID;
5808
5809        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5810                return HALMAC_RET_API_INVALID;
5811
5812        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DL_DRV_RSVD_PG);
5813
5814        driver_adapter = halmac_adapter->driver_adapter;
5815        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5816
5817        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5818                        "%s ==========>\n", __func__);
5819
5820        /*check boundary and size valid*/
5821        dl_pg_num = halmac_size / halmac_adapter->hw_config_info.page_size +
5822                    ((halmac_size &
5823                      (halmac_adapter->hw_config_info.page_size - 1)) ?
5824                             1 :
5825                             0);
5826        if (pg_offset + dl_pg_num >
5827            halmac_adapter->txff_allocation.rsvd_drv_pg_num) {
5828                pr_err("[ERROR] driver download offset or size error ==========>\n");
5829                return HALMAC_RET_DRV_DL_ERR;
5830        }
5831
5832        /*update to target download boundary*/
5833        drv_pg_bndy =
5834                halmac_adapter->txff_allocation.rsvd_drv_pg_bndy + pg_offset;
5835        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
5836                            (u16)(drv_pg_bndy & BIT_MASK_BCN_HEAD_1_V1));
5837
5838        ret_status = halmac_download_rsvd_page_88xx(halmac_adapter, halmac_buf,
5839                                                    halmac_size);
5840
5841        /*restore to original bundary*/
5842        if (ret_status != HALMAC_RET_SUCCESS) {
5843                pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n",
5844                       ret_status);
5845                HALMAC_REG_WRITE_16(
5846                        halmac_adapter, REG_FIFOPAGE_CTRL_2,
5847                        (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
5848                              BIT_MASK_BCN_HEAD_1_V1));
5849                return ret_status;
5850        }
5851
5852        HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
5853                            (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
5854                                  BIT_MASK_BCN_HEAD_1_V1));
5855
5856        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5857                        "%s < ==========\n", __func__);
5858        return HALMAC_RET_SUCCESS;
5859}
5860
5861/**
5862 * halmac_cfg_csi_rate_88xx() - config CSI frame Tx rate
5863 * @halmac_adapter : the adapter of halmac
5864 * @rssi : rssi in decimal value
5865 * @current_rate : current CSI frame rate
5866 * @fixrate_en : enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate
5867 * @new_rate : API returns the final CSI frame rate
5868 * Author : chunchu
5869 * Return : enum halmac_ret_status
5870 * More details of status code can be found in prototype document
5871 */
5872enum halmac_ret_status
5873halmac_cfg_csi_rate_88xx(struct halmac_adapter *halmac_adapter, u8 rssi,
5874                         u8 current_rate, u8 fixrate_en, u8 *new_rate)
5875{
5876        void *driver_adapter = NULL;
5877        struct halmac_api *halmac_api;
5878        u32 temp_csi_setting;
5879        u16 current_rrsr;
5880        enum halmac_ret_status ret_status;
5881
5882        if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5883                return HALMAC_RET_ADAPTER_INVALID;
5884
5885        if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5886                return HALMAC_RET_API_INVALID;
5887
5888        halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CSI_RATE);
5889
5890        driver_adapter = halmac_adapter->driver_adapter;
5891        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5892        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
5893                        "<%s ==========>\n", __func__);
5894
5895        temp_csi_setting = HALMAC_REG_READ_32(halmac_adapter, REG_BBPSF_CTRL) &
5896                           ~(BIT_MASK_WMAC_CSI_RATE << BIT_SHIFT_WMAC_CSI_RATE);
5897
5898        current_rrsr = HALMAC_REG_READ_16(halmac_adapter, REG_RRSR);
5899
5900        if (rssi >= 40) {
5901                if (current_rate != HALMAC_OFDM54) {
5902                        HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR,
5903                                            current_rrsr | BIT(HALMAC_OFDM54));
5904                        HALMAC_REG_WRITE_32(
5905                                halmac_adapter, REG_BBPSF_CTRL,
5906                                temp_csi_setting |
5907                                        BIT_WMAC_CSI_RATE(HALMAC_OFDM54));
5908                }
5909                *new_rate = HALMAC_OFDM54;
5910                ret_status = HALMAC_RET_SUCCESS;
5911        } else {
5912                if (current_rate != HALMAC_OFDM24) {
5913                        HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR,
5914                                            current_rrsr &
5915                                                    ~(BIT(HALMAC_OFDM54)));
5916                        HALMAC_REG_WRITE_32(
5917                                halmac_adapter, REG_BBPSF_CTRL,
5918                                temp_csi_setting |
5919                                        BIT_WMAC_CSI_RATE(HALMAC_OFDM24));
5920                }
5921                *new_rate = HALMAC_OFDM24;
5922                ret_status = HALMAC_RET_SUCCESS;
5923        }
5924
5925        return ret_status;
5926}
5927
5928/**
5929 * halmac_sdio_cmd53_4byte_88xx() - cmd53 only for 4byte len register IO
5930 * @halmac_adapter : the adapter of halmac
5931 * @enable : 1->CMD53 only use in 4byte reg, 0 : No limitation
5932 * Author : Ivan Lin/KaiYuan Chang
5933 * Return : enum halmac_ret_status
5934 * More details of status code can be found in prototype document
5935 */
5936enum halmac_ret_status
5937halmac_sdio_cmd53_4byte_88xx(struct halmac_adapter *halmac_adapter,
5938                             enum halmac_sdio_cmd53_4byte_mode cmd53_4byte_mode)
5939{
5940        halmac_adapter->sdio_cmd53_4byte = cmd53_4byte_mode;
5941
5942        return HALMAC_RET_SUCCESS;
5943}
5944
5945/**
5946 * halmac_txfifo_is_empty_88xx() -check if txfifo is empty
5947 * @halmac_adapter : the adapter of halmac
5948 * Author : Ivan Lin
5949 * Return : enum halmac_ret_status
5950 * More details of status code can be found in prototype document
5951 */
5952enum halmac_ret_status
5953halmac_txfifo_is_empty_88xx(struct halmac_adapter *halmac_adapter, u32 chk_num)
5954{
5955        u32 counter;
5956        void *driver_adapter = NULL;
5957        struct halmac_api *halmac_api;
5958
5959        driver_adapter = halmac_adapter->driver_adapter;
5960        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5961
5962        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5963                        "%s ==========>\n", __func__);
5964
5965        counter = (chk_num <= 10) ? 10 : chk_num;
5966        do {
5967                if (HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY) != 0xFF)
5968                        return HALMAC_RET_TXFIFO_NO_EMPTY;
5969
5970                if ((HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY + 1) &
5971                     0x07) != 0x07)
5972                        return HALMAC_RET_TXFIFO_NO_EMPTY;
5973                counter--;
5974
5975        } while (counter != 0);
5976
5977        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5978                        "%s <==========\n", __func__);
5979
5980        return HALMAC_RET_SUCCESS;
5981}
5982