Merge tag 'for-linus-4.14c-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / staging / rtlwifi / halmac / halmac_88xx / halmac_api_88xx.c
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  */
36 void 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  */
129 void 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  */
146 void 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  */
168 enum halmac_ret_status
169 halmac_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  */
384 enum halmac_ret_status
385 halmac_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);
603 DLFW_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
618 DLFW_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  */
638 enum halmac_ret_status
639 halmac_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
718 DL_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  */
737 enum halmac_ret_status
738 halmac_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  */
763 enum halmac_ret_status
764 halmac_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  */
848 enum halmac_ret_status
849 halmac_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  */
936 enum halmac_ret_status
937 halmac_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  */
979 enum halmac_ret_status
980 halmac_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  */
1055 enum halmac_ret_status
1056 halmac_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  */
1101 enum halmac_ret_status
1102 halmac_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  */
1182 enum halmac_ret_status
1183 halmac_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  */
1234 enum halmac_ret_status
1235 halmac_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  */
1293 enum halmac_ret_status
1294 halmac_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  */
1335 enum halmac_ret_status
1336 halmac_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
1369 enum 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
1404 enum halmac_ret_status
1405 halmac_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  */
1450 enum 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  */
1517 enum halmac_ret_status
1518 halmac_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  */
1604 enum halmac_ret_status
1605 halmac_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  */
1685 enum halmac_ret_status
1686 halmac_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  */
1769 enum halmac_ret_status
1770 halmac_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  */
1811 enum halmac_ret_status
1812 halmac_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  */
1846 enum halmac_ret_status
1847 halmac_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  */
1882 enum halmac_ret_status
1883 halmac_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  */
1986 enum halmac_ret_status
1987 halmac_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  */
2076 enum halmac_ret_status
2077 halmac_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  */
2154 enum halmac_ret_status
2155 halmac_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  */
2259 enum halmac_ret_status
2260 halmac_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
2294 enum halmac_ret_status
2295 halmac_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
2340 enum halmac_ret_status
2341 halmac_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
2368 enum halmac_ret_status
2369 halmac_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
2396 enum halmac_ret_status
2397 halmac_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
2420 enum halmac_ret_status
2421 halmac_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
2490 enum halmac_ret_status
2491 halmac_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  */
2569 enum 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  */
2599 enum 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  */
2718 enum halmac_ret_status
2719 halmac_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  */
2791 enum halmac_ret_status
2792 halmac_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
2844 enum halmac_ret_status
2845 halmac_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
2885 enum halmac_ret_status
2886 halmac_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
2915 enum halmac_ret_status
2916 halmac_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  */
2964 enum halmac_ret_status
2965 halmac_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
3055 enum halmac_ret_status
3056 halmac_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  */
3102 enum halmac_ret_status
3103 halmac_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
3139 enum halmac_ret_status
3140 halmac_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
3178 enum halmac_ret_status
3179 halmac_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  */
3208 enum halmac_ret_status
3209 halmac_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  */
3263 enum halmac_ret_status
3264 halmac_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  */
3331 u32 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  */
3371 enum halmac_ret_status
3372 halmac_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                 case HALMAC_BW_40:
3395                         temp42C |= BIT_R_TXBF0_40M;
3396                 case HALMAC_BW_20:
3397                         temp42C |= BIT_R_TXBF0_20M;
3398                         break;
3399                 default:
3400                         pr_err("%s invalid TXBF BW setting 0x%x of userid %d\n",
3401                                __func__, bw, userid);
3402                         return HALMAC_RET_INVALID_SOUNDING_SETTING;
3403                 }
3404         }
3405
3406         switch (userid) {
3407         case 0:
3408                 temp42C |=
3409                         HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3410                         ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3411                 HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL, temp42C);
3412                 break;
3413         case 1:
3414                 temp42C |=
3415                         HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3416                         ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3417                 HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2, temp42C);
3418                 break;
3419         default:
3420                 pr_err("%s invalid userid %d\n", __func__, userid);
3421                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3422         }
3423
3424         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3425                         "%s, txbf_en = %x <==========\n", __func__,
3426                         txbf_en);
3427
3428         return HALMAC_RET_SUCCESS;
3429 }
3430
3431 /**
3432  * halmac_cfg_mumimo_88xx() -config mumimo
3433  * @halmac_adapter : the adapter of halmac
3434  * @cfgmu : parameters to configure MU PPDU Tx/Rx
3435  * Author : chunchu
3436  * Return : enum halmac_ret_status
3437  * More details of status code can be found in prototype document
3438  */
3439 enum halmac_ret_status
3440 halmac_cfg_mumimo_88xx(struct halmac_adapter *halmac_adapter,
3441                        struct halmac_cfg_mumimo_para *cfgmu)
3442 {
3443         void *driver_adapter = NULL;
3444         struct halmac_api *halmac_api;
3445         u8 i, idx, id0, id1, gid, mu_tab_sel;
3446         u8 mu_tab_valid = 0;
3447         u32 gid_valid[6] = {0};
3448         u8 temp14C0 = 0;
3449
3450         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3451                 return HALMAC_RET_ADAPTER_INVALID;
3452
3453         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3454                 return HALMAC_RET_API_INVALID;
3455
3456         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MUMIMO);
3457
3458         driver_adapter = halmac_adapter->driver_adapter;
3459         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3460
3461         if (cfgmu->role == HAL_BFEE) {
3462                 /*config MU BFEE*/
3463                 temp14C0 = HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) &
3464                            ~BIT_MASK_R_MU_TABLE_VALID;
3465                 /*enable MU table 0 and 1, disable MU TX*/
3466                 HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3467                                    (temp14C0 | BIT(0) | BIT(1)) & ~(BIT(7)));
3468
3469                 /*config GID valid table and user position table*/
3470                 mu_tab_sel =
3471                         HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) &
3472                         ~(BIT(0) | BIT(1) | BIT(2));
3473                 for (i = 0; i < 2; i++) {
3474                         HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1,
3475                                            mu_tab_sel | i);
3476                         HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD,
3477                                             cfgmu->given_gid_tab[i]);
3478                         HALMAC_REG_WRITE_32(halmac_adapter,
3479                                             REG_MU_STA_USER_POS_INFO,
3480                                             cfgmu->given_user_pos[i * 2]);
3481                         HALMAC_REG_WRITE_32(halmac_adapter,
3482                                             REG_MU_STA_USER_POS_INFO + 4,
3483                                             cfgmu->given_user_pos[i * 2 + 1]);
3484                 }
3485         } else {
3486                 /*config MU BFER*/
3487                 if (!cfgmu->mu_tx_en) {
3488                         HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3489                                            HALMAC_REG_READ_8(halmac_adapter,
3490                                                              REG_MU_TX_CTL) &
3491                                                    ~(BIT(7)));
3492                         HALMAC_RT_TRACE(
3493                                 driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3494                                 "%s disable mu tx <==========\n", __func__);
3495                         return HALMAC_RET_SUCCESS;
3496                 }
3497
3498                 /*Transform BB grouping bitmap[14:0] to MAC GID_valid table*/
3499                 for (idx = 0; idx < 15; idx++) {
3500                         if (idx < 5) {
3501                                 /*group_bitmap bit0~4, MU_STA0 with MUSTA1~5*/
3502                                 id0 = 0;
3503                                 id1 = (u8)(idx + 1);
3504                         } else if (idx < 9) {
3505                                 /*group_bitmap bit5~8, MU_STA1 with MUSTA2~5*/
3506                                 id0 = 1;
3507                                 id1 = (u8)(idx - 3);
3508                         } else if (idx < 12) {
3509                                 /*group_bitmap bit9~11, MU_STA2 with MUSTA3~5*/
3510                                 id0 = 2;
3511                                 id1 = (u8)(idx - 6);
3512                         } else if (idx < 14) {
3513                                 /*group_bitmap bit12~13, MU_STA3 with MUSTA4~5*/
3514                                 id0 = 3;
3515                                 id1 = (u8)(idx - 8);
3516                         } else {
3517                                 /*group_bitmap bit14, MU_STA4 with MUSTA5*/
3518                                 id0 = 4;
3519                                 id1 = (u8)(idx - 9);
3520                         }
3521                         if (cfgmu->grouping_bitmap & BIT(idx)) {
3522                                 /*Pair 1*/
3523                                 gid = (idx << 1) + 1;
3524                                 gid_valid[id0] |= (BIT(gid));
3525                                 gid_valid[id1] |= (BIT(gid));
3526                                 /*Pair 2*/
3527                                 gid += 1;
3528                                 gid_valid[id0] |= (BIT(gid));
3529                                 gid_valid[id1] |= (BIT(gid));
3530                         } else {
3531                                 /*Pair 1*/
3532                                 gid = (idx << 1) + 1;
3533                                 gid_valid[id0] &= ~(BIT(gid));
3534                                 gid_valid[id1] &= ~(BIT(gid));
3535                                 /*Pair 2*/
3536                                 gid += 1;
3537                                 gid_valid[id0] &= ~(BIT(gid));
3538                                 gid_valid[id1] &= ~(BIT(gid));
3539                         }
3540                 }
3541
3542                 /*set MU STA GID valid TABLE*/
3543                 mu_tab_sel =
3544                         HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) &
3545                         ~(BIT(0) | BIT(1) | BIT(2));
3546                 for (idx = 0; idx < 6; idx++) {
3547                         HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1,
3548                                            idx | mu_tab_sel);
3549                         HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD,
3550                                             gid_valid[idx]);
3551                 }
3552
3553                 /*To validate the sounding successful MU STA and enable MU TX*/
3554                 for (i = 0; i < 6; i++) {
3555                         if (cfgmu->sounding_sts[i])
3556                                 mu_tab_valid |= BIT(i);
3557                 }
3558                 HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
3559                                    mu_tab_valid | BIT(7));
3560         }
3561         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3562                         "%s <==========\n", __func__);
3563         return HALMAC_RET_SUCCESS;
3564 }
3565
3566 /**
3567  * halmac_cfg_sounding_88xx() - configure general sounding
3568  * @halmac_adapter : the adapter of halmac
3569  * @role : driver's role, BFer or BFee
3570  * @datarate : set ndpa tx rate if driver is BFer, or set csi response rate
3571  *             if driver is BFee
3572  * Author : chunchu
3573  * Return : enum halmac_ret_status
3574  * More details of status code can be found in prototype document
3575  */
3576 enum halmac_ret_status
3577 halmac_cfg_sounding_88xx(struct halmac_adapter *halmac_adapter,
3578                          enum halmac_snd_role role,
3579                          enum halmac_data_rate datarate)
3580 {
3581         void *driver_adapter = NULL;
3582         struct halmac_api *halmac_api;
3583
3584         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3585                 return HALMAC_RET_ADAPTER_INVALID;
3586
3587         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3588                 return HALMAC_RET_API_INVALID;
3589
3590         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_SOUNDING);
3591
3592         driver_adapter = halmac_adapter->driver_adapter;
3593         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3594
3595         switch (role) {
3596         case HAL_BFER:
3597                 HALMAC_REG_WRITE_32(
3598                         halmac_adapter, REG_TXBF_CTRL,
3599                         HALMAC_REG_READ_32(halmac_adapter, REG_TXBF_CTRL) |
3600                                 BIT_R_ENABLE_NDPA | BIT_USE_NDPA_PARAMETER |
3601                                 BIT_R_EN_NDPA_INT | BIT_DIS_NDP_BFEN);
3602                 HALMAC_REG_WRITE_8(halmac_adapter, REG_NDPA_RATE, datarate);
3603                 HALMAC_REG_WRITE_8(
3604                         halmac_adapter, REG_NDPA_OPT_CTRL,
3605                         HALMAC_REG_READ_8(halmac_adapter, REG_NDPA_OPT_CTRL) &
3606                                 (~(BIT(0) | BIT(1))));
3607                 /*service file length 2 bytes; fix non-STA1 csi start offset */
3608                 HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 1,
3609                                    0x2 | BIT(7));
3610                 HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 2, 0x2);
3611                 break;
3612         case HAL_BFEE:
3613                 HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0xDB);
3614                 HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 3, 0x50);
3615                 /*use ndpa rx rate to decide csi rate*/
3616                 HALMAC_REG_WRITE_8(halmac_adapter, REG_BBPSF_CTRL + 3,
3617                                    HALMAC_OFDM54 | BIT(6));
3618                 HALMAC_REG_WRITE_16(
3619                         halmac_adapter, REG_RRSR,
3620                         HALMAC_REG_READ_16(halmac_adapter, REG_RRSR) |
3621                                 BIT(datarate));
3622                 /*RXFF do not accept BF Rpt Poll, avoid CSI crc error*/
3623                 HALMAC_REG_WRITE_8(
3624                         halmac_adapter, REG_RXFLTMAP1,
3625                         HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP1) &
3626                                 (~(BIT(4))));
3627                 /*FWFF do not accept BF Rpt Poll, avoid CSI crc error*/
3628                 HALMAC_REG_WRITE_8(
3629                         halmac_adapter, REG_RXFLTMAP4,
3630                         HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP4) &
3631                                 (~(BIT(4))));
3632                 break;
3633         default:
3634                 pr_err("%s invalid role\n", __func__);
3635                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3636         }
3637
3638         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3639                         "%s <==========\n", __func__);
3640
3641         return HALMAC_RET_SUCCESS;
3642 }
3643
3644 /**
3645  * halmac_del_sounding_88xx() - reset general sounding
3646  * @halmac_adapter : the adapter of halmac
3647  * @role : driver's role, BFer or BFee
3648  * Author : chunchu
3649  * Return : enum halmac_ret_status
3650  * More details of status code can be found in prototype document
3651  */
3652 enum halmac_ret_status
3653 halmac_del_sounding_88xx(struct halmac_adapter *halmac_adapter,
3654                          enum halmac_snd_role role)
3655 {
3656         void *driver_adapter = NULL;
3657         struct halmac_api *halmac_api;
3658
3659         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3660                 return HALMAC_RET_ADAPTER_INVALID;
3661
3662         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3663                 return HALMAC_RET_API_INVALID;
3664
3665         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEL_SOUNDING);
3666
3667         driver_adapter = halmac_adapter->driver_adapter;
3668         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3669
3670         switch (role) {
3671         case HAL_BFER:
3672                 HALMAC_REG_WRITE_8(halmac_adapter, REG_TXBF_CTRL + 3, 0);
3673                 break;
3674         case HAL_BFEE:
3675                 HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0);
3676                 break;
3677         default:
3678                 pr_err("%s invalid role\n", __func__);
3679                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3680         }
3681
3682         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3683                         "%s <==========\n", __func__);
3684
3685         return HALMAC_RET_SUCCESS;
3686 }
3687
3688 /**
3689  * halmac_su_bfee_entry_init_88xx() - config SU beamformee's registers
3690  * @halmac_adapter : the adapter of halmac
3691  * @userid : SU bfee userid = 0 or 1 to be added
3692  * @paid : partial AID of this bfee
3693  * Author : chunchu
3694  * Return : enum halmac_ret_status
3695  * More details of status code can be found in prototype document
3696  */
3697 enum halmac_ret_status
3698 halmac_su_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, u8 userid,
3699                                u16 paid)
3700 {
3701         u16 temp42C = 0;
3702         void *driver_adapter = NULL;
3703         struct halmac_api *halmac_api;
3704
3705         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3706                 return HALMAC_RET_ADAPTER_INVALID;
3707
3708         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3709                 return HALMAC_RET_API_INVALID;
3710
3711         halmac_api_record_id_88xx(halmac_adapter,
3712                                   HALMAC_API_SU_BFEE_ENTRY_INIT);
3713
3714         driver_adapter = halmac_adapter->driver_adapter;
3715         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3716
3717         switch (userid) {
3718         case 0:
3719                 temp42C = HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3720                           ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
3721                             BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3722                 HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL,
3723                                     temp42C | paid);
3724                 HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL,
3725                                     paid);
3726                 break;
3727         case 1:
3728                 temp42C =
3729                         HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3730                         ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
3731                           BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
3732                 HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2,
3733                                     temp42C | paid);
3734                 HALMAC_REG_WRITE_16(halmac_adapter,
3735                                     REG_ASSOCIATED_BFMEE_SEL + 2,
3736                                     paid | BIT(9));
3737                 break;
3738         default:
3739                 pr_err("%s invalid userid %d\n", __func__,
3740                        userid);
3741                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3742         }
3743
3744         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3745                         "%s <==========\n", __func__);
3746
3747         return HALMAC_RET_SUCCESS;
3748 }
3749
3750 /**
3751  * halmac_su_bfee_entry_init_88xx() - config SU beamformer's registers
3752  * @halmac_adapter : the adapter of halmac
3753  * @su_bfer_init : parameters to configure SU BFER entry
3754  * Author : chunchu
3755  * Return : enum halmac_ret_status
3756  * More details of status code can be found in prototype document
3757  */
3758 enum halmac_ret_status
3759 halmac_su_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3760                                struct halmac_su_bfer_init_para *su_bfer_init)
3761 {
3762         u16 mac_address_H;
3763         u32 mac_address_L;
3764         void *driver_adapter = NULL;
3765         struct halmac_api *halmac_api;
3766
3767         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3768                 return HALMAC_RET_ADAPTER_INVALID;
3769
3770         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3771                 return HALMAC_RET_API_INVALID;
3772
3773         halmac_api_record_id_88xx(halmac_adapter,
3774                                   HALMAC_API_SU_BFER_ENTRY_INIT);
3775
3776         driver_adapter = halmac_adapter->driver_adapter;
3777         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3778
3779         /* mac_address_L = bfer_address.address_l_h.address_low; */
3780         /* mac_address_H = bfer_address.address_l_h.address_high; */
3781
3782         mac_address_L = le32_to_cpu(
3783                 su_bfer_init->bfer_address.address_l_h.le_address_low);
3784         mac_address_H = le16_to_cpu(
3785                 su_bfer_init->bfer_address.address_l_h.le_address_high);
3786
3787         switch (su_bfer_init->userid) {
3788         case 0:
3789                 HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
3790                                     mac_address_L);
3791                 HALMAC_REG_WRITE_16(halmac_adapter,
3792                                     REG_ASSOCIATED_BFMER0_INFO + 4,
3793                                     mac_address_H);
3794                 HALMAC_REG_WRITE_16(halmac_adapter,
3795                                     REG_ASSOCIATED_BFMER0_INFO + 6,
3796                                     su_bfer_init->paid);
3797                 HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20,
3798                                     su_bfer_init->csi_para);
3799                 break;
3800         case 1:
3801                 HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO,
3802                                     mac_address_L);
3803                 HALMAC_REG_WRITE_16(halmac_adapter,
3804                                     REG_ASSOCIATED_BFMER1_INFO + 4,
3805                                     mac_address_H);
3806                 HALMAC_REG_WRITE_16(halmac_adapter,
3807                                     REG_ASSOCIATED_BFMER1_INFO + 6,
3808                                     su_bfer_init->paid);
3809                 HALMAC_REG_WRITE_16(halmac_adapter,
3810                                     REG_TX_CSI_RPT_PARAM_BW20 + 2,
3811                                     su_bfer_init->csi_para);
3812                 break;
3813         default:
3814                 pr_err("%s invalid userid %d\n", __func__,
3815                        su_bfer_init->userid);
3816                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3817         }
3818
3819         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3820                         "%s <==========\n", __func__);
3821
3822         return HALMAC_RET_SUCCESS;
3823 }
3824
3825 /**
3826  * halmac_mu_bfee_entry_init_88xx() - config MU beamformee's registers
3827  * @halmac_adapter : the adapter of halmac
3828  * @mu_bfee_init : parameters to configure MU BFEE entry
3829  * Author : chunchu
3830  * Return : enum halmac_ret_status
3831  * More details of status code can be found in prototype document
3832  */
3833 enum halmac_ret_status
3834 halmac_mu_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3835                                struct halmac_mu_bfee_init_para *mu_bfee_init)
3836 {
3837         u16 temp168X = 0, temp14C0;
3838         void *driver_adapter = NULL;
3839         struct halmac_api *halmac_api;
3840
3841         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3842                 return HALMAC_RET_ADAPTER_INVALID;
3843
3844         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3845                 return HALMAC_RET_API_INVALID;
3846
3847         halmac_api_record_id_88xx(halmac_adapter,
3848                                   HALMAC_API_MU_BFEE_ENTRY_INIT);
3849
3850         driver_adapter = halmac_adapter->driver_adapter;
3851         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3852
3853         temp168X |= mu_bfee_init->paid | BIT(9);
3854         HALMAC_REG_WRITE_16(halmac_adapter, (0x1680 + mu_bfee_init->userid * 2),
3855                             temp168X);
3856
3857         temp14C0 = HALMAC_REG_READ_16(halmac_adapter, REG_MU_TX_CTL) &
3858                    ~(BIT(8) | BIT(9) | BIT(10));
3859         HALMAC_REG_WRITE_16(halmac_adapter, REG_MU_TX_CTL,
3860                             temp14C0 | ((mu_bfee_init->userid - 2) << 8));
3861         HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD, 0);
3862         HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO,
3863                             mu_bfee_init->user_position_l);
3864         HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO + 4,
3865                             mu_bfee_init->user_position_h);
3866
3867         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3868                         "%s <==========\n", __func__);
3869
3870         return HALMAC_RET_SUCCESS;
3871 }
3872
3873 /**
3874  * halmac_mu_bfer_entry_init_88xx() - config MU beamformer's registers
3875  * @halmac_adapter : the adapter of halmac
3876  * @mu_bfer_init : parameters to configure MU BFER entry
3877  * Author : chunchu
3878  * Return : enum halmac_ret_status
3879  * More details of status code can be found in prototype document
3880  */
3881 enum halmac_ret_status
3882 halmac_mu_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter,
3883                                struct halmac_mu_bfer_init_para *mu_bfer_init)
3884 {
3885         u16 temp1680 = 0;
3886         u16 mac_address_H;
3887         u32 mac_address_L;
3888         void *driver_adapter = NULL;
3889         struct halmac_api *halmac_api;
3890
3891         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3892                 return HALMAC_RET_ADAPTER_INVALID;
3893
3894         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3895                 return HALMAC_RET_API_INVALID;
3896
3897         halmac_api_record_id_88xx(halmac_adapter,
3898                                   HALMAC_API_MU_BFER_ENTRY_INIT);
3899
3900         driver_adapter = halmac_adapter->driver_adapter;
3901         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3902
3903         mac_address_L =
3904             le32_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_low);
3905         mac_address_H =
3906             le16_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_high);
3907
3908         HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
3909                             mac_address_L);
3910         HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4,
3911                             mac_address_H);
3912         HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 6,
3913                             mu_bfer_init->paid);
3914         HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20,
3915                             mu_bfer_init->csi_para);
3916
3917         temp1680 = HALMAC_REG_READ_16(halmac_adapter, 0x1680) & 0xC000;
3918         temp1680 |= mu_bfer_init->my_aid | (mu_bfer_init->csi_length_sel << 12);
3919         HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, temp1680);
3920
3921         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3922                         "%s <==========\n", __func__);
3923
3924         return HALMAC_RET_SUCCESS;
3925 }
3926
3927 /**
3928  * halmac_su_bfee_entry_del_88xx() - reset SU beamformee's registers
3929  * @halmac_adapter : the adapter of halmac
3930  * @userid : the SU BFee userid to be deleted
3931  * Author : chunchu
3932  * Return : enum halmac_ret_status
3933  * More details of status code can be found in prototype document
3934  */
3935 enum halmac_ret_status
3936 halmac_su_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
3937 {
3938         void *driver_adapter = NULL;
3939         struct halmac_api *halmac_api;
3940
3941         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3942                 return HALMAC_RET_ADAPTER_INVALID;
3943
3944         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3945                 return HALMAC_RET_API_INVALID;
3946
3947         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFEE_ENTRY_DEL);
3948
3949         driver_adapter = halmac_adapter->driver_adapter;
3950         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
3951
3952         switch (userid) {
3953         case 0:
3954                 HALMAC_REG_WRITE_16(
3955                         halmac_adapter, REG_TXBF_CTRL,
3956                         HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) &
3957                                 ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
3958                                   BIT_R_TXBF0_40M | BIT_R_TXBF0_80M));
3959                 HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL,
3960                                     0);
3961                 break;
3962         case 1:
3963                 HALMAC_REG_WRITE_16(
3964                         halmac_adapter, REG_TXBF_CTRL + 2,
3965                         HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) &
3966                                 ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
3967                                   BIT_R_TXBF0_40M | BIT_R_TXBF0_80M));
3968                 HALMAC_REG_WRITE_16(halmac_adapter,
3969                                     REG_ASSOCIATED_BFMEE_SEL + 2, 0);
3970                 break;
3971         default:
3972                 pr_err("%s invalid userid %d\n", __func__,
3973                        userid);
3974                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
3975         }
3976
3977         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
3978                         "%s <==========\n", __func__);
3979
3980         return HALMAC_RET_SUCCESS;
3981 }
3982
3983 /**
3984  * halmac_su_bfee_entry_del_88xx() - reset SU beamformer's registers
3985  * @halmac_adapter : the adapter of halmac
3986  * @userid : the SU BFer userid to be deleted
3987  * Author : chunchu
3988  * Return : enum halmac_ret_status
3989  * More details of status code can be found in prototype document
3990  */
3991 enum halmac_ret_status
3992 halmac_su_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
3993 {
3994         void *driver_adapter = NULL;
3995         struct halmac_api *halmac_api;
3996
3997         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
3998                 return HALMAC_RET_ADAPTER_INVALID;
3999
4000         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4001                 return HALMAC_RET_API_INVALID;
4002
4003         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFER_ENTRY_DEL);
4004
4005         driver_adapter = halmac_adapter->driver_adapter;
4006         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4007
4008         switch (userid) {
4009         case 0:
4010                 HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO,
4011                                     0);
4012                 HALMAC_REG_WRITE_32(halmac_adapter,
4013                                     REG_ASSOCIATED_BFMER0_INFO + 4, 0);
4014                 break;
4015         case 1:
4016                 HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO,
4017                                     0);
4018                 HALMAC_REG_WRITE_32(halmac_adapter,
4019                                     REG_ASSOCIATED_BFMER1_INFO + 4, 0);
4020                 break;
4021         default:
4022                 pr_err("%s invalid userid %d\n", __func__,
4023                        userid);
4024                 return HALMAC_RET_INVALID_SOUNDING_SETTING;
4025         }
4026
4027         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4028                         "%s <==========\n", __func__);
4029
4030         return HALMAC_RET_SUCCESS;
4031 }
4032
4033 /**
4034  * halmac_mu_bfee_entry_del_88xx() - reset MU beamformee's registers
4035  * @halmac_adapter : the adapter of halmac
4036  * @userid : the MU STA userid to be deleted
4037  * Author : chunchu
4038  * Return : enum halmac_ret_status
4039  * More details of status code can be found in prototype document
4040  */
4041 enum halmac_ret_status
4042 halmac_mu_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid)
4043 {
4044         void *driver_adapter = NULL;
4045         struct halmac_api *halmac_api;
4046
4047         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4048                 return HALMAC_RET_ADAPTER_INVALID;
4049
4050         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4051                 return HALMAC_RET_API_INVALID;
4052
4053         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFEE_ENTRY_DEL);
4054
4055         driver_adapter = halmac_adapter->driver_adapter;
4056         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4057
4058         HALMAC_REG_WRITE_16(halmac_adapter, 0x1680 + userid * 2, 0);
4059         HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL,
4060                            HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) &
4061                                    ~(BIT(userid - 2)));
4062
4063         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4064                         "%s <==========\n", __func__);
4065
4066         return HALMAC_RET_SUCCESS;
4067 }
4068
4069 /**
4070  * halmac_mu_bfer_entry_del_88xx() -reset MU beamformer's registers
4071  * @halmac_adapter : the adapter of halmac
4072  * Author : chunchu
4073  * Return : enum halmac_ret_status
4074  * More details of status code can be found in prototype document
4075  */
4076 enum halmac_ret_status
4077 halmac_mu_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter)
4078 {
4079         void *driver_adapter = NULL;
4080         struct halmac_api *halmac_api;
4081
4082         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4083                 return HALMAC_RET_ADAPTER_INVALID;
4084
4085         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4086                 return HALMAC_RET_API_INVALID;
4087
4088         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFER_ENTRY_DEL);
4089
4090         driver_adapter = halmac_adapter->driver_adapter;
4091         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4092
4093         HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, 0);
4094         HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
4095         HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, 0);
4096         HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, 0);
4097
4098         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
4099                         "%s <==========\n", __func__);
4100
4101         return HALMAC_RET_SUCCESS;
4102 }
4103
4104 /**
4105  * halmac_add_ch_info_88xx() -add channel information
4106  * @halmac_adapter : the adapter of halmac
4107  * @ch_info : channel information
4108  * Author : KaiYuan Chang/Ivan Lin
4109  * Return : enum halmac_ret_status
4110  * More details of status code can be found in prototype document
4111  */
4112 enum halmac_ret_status
4113 halmac_add_ch_info_88xx(struct halmac_adapter *halmac_adapter,
4114                         struct halmac_ch_info *ch_info)
4115 {
4116         void *driver_adapter = NULL;
4117         struct halmac_cs_info *ch_sw_info;
4118         enum halmac_scan_cmd_construct_state state_scan;
4119
4120         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4121                 return HALMAC_RET_ADAPTER_INVALID;
4122
4123         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4124                 return HALMAC_RET_API_INVALID;
4125
4126         driver_adapter = halmac_adapter->driver_adapter;
4127         ch_sw_info = &halmac_adapter->ch_sw_info;
4128
4129         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4130                         "[TRACE]%s ==========>\n", __func__);
4131
4132         if (halmac_adapter->halmac_state.dlfw_state != HALMAC_GEN_INFO_SENT) {
4133                 pr_err("[ERR]%s: gen_info is not send to FW!!!!\n", __func__);
4134                 return HALMAC_RET_GEN_INFO_NOT_SENT;
4135         }
4136
4137         state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter);
4138         if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED &&
4139             state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4140                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_WARNING,
4141                                 "[WARN]Scan machine fail(add ch info)...\n");
4142                 return HALMAC_RET_ERROR_STATE;
4143         }
4144
4145         if (!ch_sw_info->ch_info_buf) {
4146                 ch_sw_info->ch_info_buf =
4147                         kzalloc(HALMAC_EXTRA_INFO_BUFF_SIZE_88XX, GFP_KERNEL);
4148                 if (!ch_sw_info->ch_info_buf)
4149                         return HALMAC_RET_NULL_POINTER;
4150                 ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf;
4151                 ch_sw_info->buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX;
4152                 ch_sw_info->avai_buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX;
4153                 ch_sw_info->total_size = 0;
4154                 ch_sw_info->extra_info_en = 0;
4155                 ch_sw_info->ch_num = 0;
4156         }
4157
4158         if (ch_sw_info->extra_info_en == 1) {
4159                 pr_err("[ERR]%s: construct sequence wrong!!\n", __func__);
4160                 return HALMAC_RET_CH_SW_SEQ_WRONG;
4161         }
4162
4163         if (ch_sw_info->avai_buf_size < 4) {
4164                 pr_err("[ERR]%s: no available buffer!!\n", __func__);
4165                 return HALMAC_RET_CH_SW_NO_BUF;
4166         }
4167
4168         if (halmac_transition_scan_state_88xx(
4169                     halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) !=
4170             HALMAC_RET_SUCCESS)
4171                 return HALMAC_RET_ERROR_STATE;
4172
4173         CHANNEL_INFO_SET_CHANNEL(ch_sw_info->ch_info_buf_w, ch_info->channel);
4174         CHANNEL_INFO_SET_PRI_CH_IDX(ch_sw_info->ch_info_buf_w,
4175                                     ch_info->pri_ch_idx);
4176         CHANNEL_INFO_SET_BANDWIDTH(ch_sw_info->ch_info_buf_w, ch_info->bw);
4177         CHANNEL_INFO_SET_TIMEOUT(ch_sw_info->ch_info_buf_w, ch_info->timeout);
4178         CHANNEL_INFO_SET_ACTION_ID(ch_sw_info->ch_info_buf_w,
4179                                    ch_info->action_id);
4180         CHANNEL_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w,
4181                                        ch_info->extra_info);
4182
4183         ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size - 4;
4184         ch_sw_info->total_size = ch_sw_info->total_size + 4;
4185         ch_sw_info->ch_num++;
4186         ch_sw_info->extra_info_en = ch_info->extra_info;
4187         ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w + 4;
4188
4189         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4190                         "[TRACE]%s <==========\n", __func__);
4191
4192         return HALMAC_RET_SUCCESS;
4193 }
4194
4195 /**
4196  * halmac_add_extra_ch_info_88xx() -add extra channel information
4197  * @halmac_adapter : the adapter of halmac
4198  * @ch_extra_info : extra channel information
4199  * Author : KaiYuan Chang/Ivan Lin
4200  * Return : enum halmac_ret_status
4201  * More details of status code can be found in prototype document
4202  */
4203 enum halmac_ret_status
4204 halmac_add_extra_ch_info_88xx(struct halmac_adapter *halmac_adapter,
4205                               struct halmac_ch_extra_info *ch_extra_info)
4206 {
4207         void *driver_adapter = NULL;
4208         struct halmac_cs_info *ch_sw_info;
4209
4210         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4211                 return HALMAC_RET_ADAPTER_INVALID;
4212
4213         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4214                 return HALMAC_RET_API_INVALID;
4215
4216         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ADD_EXTRA_CH_INFO);
4217
4218         driver_adapter = halmac_adapter->driver_adapter;
4219         ch_sw_info = &halmac_adapter->ch_sw_info;
4220
4221         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4222                         "%s ==========>\n", __func__);
4223
4224         if (!ch_sw_info->ch_info_buf) {
4225                 pr_err("%s: NULL==ch_sw_info->ch_info_buf!!\n", __func__);
4226                 return HALMAC_RET_CH_SW_SEQ_WRONG;
4227         }
4228
4229         if (ch_sw_info->extra_info_en == 0) {
4230                 pr_err("%s: construct sequence wrong!!\n", __func__);
4231                 return HALMAC_RET_CH_SW_SEQ_WRONG;
4232         }
4233
4234         if (ch_sw_info->avai_buf_size <
4235             (u32)(ch_extra_info->extra_info_size + 2)) {
4236                 /* +2: ch_extra_info_id, ch_extra_info, ch_extra_info_size
4237                  * are totally 2Byte
4238                  */
4239                 pr_err("%s: no available buffer!!\n", __func__);
4240                 return HALMAC_RET_CH_SW_NO_BUF;
4241         }
4242
4243         if (halmac_query_scan_curr_state_88xx(halmac_adapter) !=
4244             HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4245                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4246                                 "Scan machine fail(add extra ch info)...\n");
4247                 return HALMAC_RET_ERROR_STATE;
4248         }
4249
4250         if (halmac_transition_scan_state_88xx(
4251                     halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) !=
4252             HALMAC_RET_SUCCESS)
4253                 return HALMAC_RET_ERROR_STATE;
4254
4255         CH_EXTRA_INFO_SET_CH_EXTRA_INFO_ID(ch_sw_info->ch_info_buf_w,
4256                                            ch_extra_info->extra_action_id);
4257         CH_EXTRA_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w,
4258                                         ch_extra_info->extra_info);
4259         CH_EXTRA_INFO_SET_CH_EXTRA_INFO_SIZE(ch_sw_info->ch_info_buf_w,
4260                                              ch_extra_info->extra_info_size);
4261         memcpy(ch_sw_info->ch_info_buf_w + 2, ch_extra_info->extra_info_data,
4262                ch_extra_info->extra_info_size);
4263
4264         ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size -
4265                                     (2 + ch_extra_info->extra_info_size);
4266         ch_sw_info->total_size =
4267                 ch_sw_info->total_size + (2 + ch_extra_info->extra_info_size);
4268         ch_sw_info->extra_info_en = ch_extra_info->extra_info;
4269         ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w +
4270                                     (2 + ch_extra_info->extra_info_size);
4271
4272         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4273                         "%s <==========\n", __func__);
4274
4275         return HALMAC_RET_SUCCESS;
4276 }
4277
4278 /**
4279  * halmac_ctrl_ch_switch_88xx() -send channel switch cmd
4280  * @halmac_adapter : the adapter of halmac
4281  * @cs_option : channel switch config
4282  * Author : KaiYuan Chang/Ivan Lin
4283  * Return : enum halmac_ret_status
4284  * More details of status code can be found in prototype document
4285  */
4286 enum halmac_ret_status
4287 halmac_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter,
4288                            struct halmac_ch_switch_option *cs_option)
4289 {
4290         void *driver_adapter = NULL;
4291         struct halmac_api *halmac_api;
4292         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4293         enum halmac_scan_cmd_construct_state state_scan;
4294         enum halmac_cmd_process_status *process_status =
4295                 &halmac_adapter->halmac_state.scan_state_set.process_status;
4296
4297         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4298                 return HALMAC_RET_ADAPTER_INVALID;
4299
4300         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4301                 return HALMAC_RET_API_INVALID;
4302
4303         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4304                 return HALMAC_RET_NO_DLFW;
4305
4306         if (halmac_adapter->fw_version.h2c_version < 4)
4307                 return HALMAC_RET_FW_NO_SUPPORT;
4308
4309         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_CH_SWITCH);
4310
4311         driver_adapter = halmac_adapter->driver_adapter;
4312         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4313
4314         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4315                         "%s  cs_option->switch_en = %d==========>\n", __func__,
4316                         cs_option->switch_en);
4317
4318         if (!cs_option->switch_en)
4319                 *process_status = HALMAC_CMD_PROCESS_IDLE;
4320
4321         if (*process_status == HALMAC_CMD_PROCESS_SENDING ||
4322             *process_status == HALMAC_CMD_PROCESS_RCVD) {
4323                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4324                                 "Wait event(ctrl ch switch)...\n");
4325                 return HALMAC_RET_BUSY_STATE;
4326         }
4327
4328         state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter);
4329         if (cs_option->switch_en) {
4330                 if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) {
4331                         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C,
4332                                         DBG_DMESG,
4333                                         "%s(on)  invalid in state %x\n",
4334                                         __func__, state_scan);
4335                         return HALMAC_RET_ERROR_STATE;
4336                 }
4337         } else {
4338                 if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) {
4339                         HALMAC_RT_TRACE(
4340                                 driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4341                                 "%s(off)  invalid in state %x\n", __func__,
4342                                 state_scan);
4343                         return HALMAC_RET_ERROR_STATE;
4344                 }
4345         }
4346
4347         status = halmac_func_ctrl_ch_switch_88xx(halmac_adapter, cs_option);
4348
4349         if (status != HALMAC_RET_SUCCESS) {
4350                 pr_err("halmac_ctrl_ch_switch FAIL = %x!!\n", status);
4351                 return status;
4352         }
4353
4354         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4355                         "%s <==========\n", __func__);
4356
4357         return HALMAC_RET_SUCCESS;
4358 }
4359
4360 /**
4361  * halmac_clear_ch_info_88xx() -clear channel information
4362  * @halmac_adapter : the adapter of halmac
4363  * Author : KaiYuan Chang/Ivan Lin
4364  * Return : enum halmac_ret_status
4365  * More details of status code can be found in prototype document
4366  */
4367 enum halmac_ret_status
4368 halmac_clear_ch_info_88xx(struct halmac_adapter *halmac_adapter)
4369 {
4370         void *driver_adapter = NULL;
4371         struct halmac_api *halmac_api;
4372
4373         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4374                 return HALMAC_RET_ADAPTER_INVALID;
4375
4376         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4377                 return HALMAC_RET_API_INVALID;
4378
4379         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CLEAR_CH_INFO);
4380
4381         driver_adapter = halmac_adapter->driver_adapter;
4382         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4383
4384         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4385                         "%s ==========>\n", __func__);
4386
4387         if (halmac_query_scan_curr_state_88xx(halmac_adapter) ==
4388             HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) {
4389                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4390                                 "Scan machine fail(clear ch info)...\n");
4391                 return HALMAC_RET_ERROR_STATE;
4392         }
4393
4394         if (halmac_transition_scan_state_88xx(
4395                     halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) !=
4396             HALMAC_RET_SUCCESS)
4397                 return HALMAC_RET_ERROR_STATE;
4398
4399         kfree(halmac_adapter->ch_sw_info.ch_info_buf);
4400         halmac_adapter->ch_sw_info.ch_info_buf = NULL;
4401         halmac_adapter->ch_sw_info.ch_info_buf_w = NULL;
4402         halmac_adapter->ch_sw_info.extra_info_en = 0;
4403         halmac_adapter->ch_sw_info.buf_size = 0;
4404         halmac_adapter->ch_sw_info.avai_buf_size = 0;
4405         halmac_adapter->ch_sw_info.total_size = 0;
4406         halmac_adapter->ch_sw_info.ch_num = 0;
4407
4408         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4409                         "%s <==========\n", __func__);
4410
4411         return HALMAC_RET_SUCCESS;
4412 }
4413
4414 enum halmac_ret_status halmac_p2pps_88xx(struct halmac_adapter *halmac_adapter,
4415                                          struct halmac_p2pps *p2p_ps)
4416 {
4417         void *driver_adapter = NULL;
4418         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4419
4420         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4421                 return HALMAC_RET_ADAPTER_INVALID;
4422
4423         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4424                 return HALMAC_RET_API_INVALID;
4425
4426         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4427                 return HALMAC_RET_NO_DLFW;
4428
4429         if (halmac_adapter->fw_version.h2c_version < 6)
4430                 return HALMAC_RET_FW_NO_SUPPORT;
4431
4432         driver_adapter = halmac_adapter->driver_adapter;
4433
4434         status = halmac_func_p2pps_88xx(halmac_adapter, p2p_ps);
4435
4436         if (status != HALMAC_RET_SUCCESS) {
4437                 pr_err("[ERR]halmac_p2pps FAIL = %x!!\n", status);
4438                 return status;
4439         }
4440
4441         return HALMAC_RET_SUCCESS;
4442 }
4443
4444 enum halmac_ret_status
4445 halmac_func_p2pps_88xx(struct halmac_adapter *halmac_adapter,
4446                        struct halmac_p2pps *p2p_ps)
4447 {
4448         u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4449         u16 h2c_seq_mum = 0;
4450         void *driver_adapter = halmac_adapter->driver_adapter;
4451         struct halmac_api *halmac_api;
4452         struct halmac_h2c_header_info h2c_header_info;
4453         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4454
4455         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4456                         "[TRACE]halmac_p2pps !!\n");
4457
4458         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4459
4460         P2PPS_SET_OFFLOAD_EN(h2c_buff, p2p_ps->offload_en);
4461         P2PPS_SET_ROLE(h2c_buff, p2p_ps->role);
4462         P2PPS_SET_CTWINDOW_EN(h2c_buff, p2p_ps->ctwindow_en);
4463         P2PPS_SET_NOA_EN(h2c_buff, p2p_ps->noa_en);
4464         P2PPS_SET_NOA_SEL(h2c_buff, p2p_ps->noa_sel);
4465         P2PPS_SET_ALLSTASLEEP(h2c_buff, p2p_ps->all_sta_sleep);
4466         P2PPS_SET_DISCOVERY(h2c_buff, p2p_ps->discovery);
4467         P2PPS_SET_P2P_PORT_ID(h2c_buff, p2p_ps->p2p_port_id);
4468         P2PPS_SET_P2P_GROUP(h2c_buff, p2p_ps->p2p_group);
4469         P2PPS_SET_P2P_MACID(h2c_buff, p2p_ps->p2p_macid);
4470
4471         P2PPS_SET_CTWINDOW_LENGTH(h2c_buff, p2p_ps->ctwindow_length);
4472
4473         P2PPS_SET_NOA_DURATION_PARA(h2c_buff, p2p_ps->noa_duration_para);
4474         P2PPS_SET_NOA_INTERVAL_PARA(h2c_buff, p2p_ps->noa_interval_para);
4475         P2PPS_SET_NOA_START_TIME_PARA(h2c_buff, p2p_ps->noa_start_time_para);
4476         P2PPS_SET_NOA_COUNT_PARA(h2c_buff, p2p_ps->noa_count_para);
4477
4478         h2c_header_info.sub_cmd_id = SUB_CMD_ID_P2PPS;
4479         h2c_header_info.content_size = 24;
4480         h2c_header_info.ack = false;
4481         halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4482                                               &h2c_header_info, &h2c_seq_mum);
4483
4484         status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4485                                           HALMAC_H2C_CMD_SIZE_88XX, false);
4486
4487         if (status != HALMAC_RET_SUCCESS)
4488                 pr_err("[ERR]halmac_send_h2c_p2pps_88xx Fail = %x!!\n", status);
4489
4490         return status;
4491 }
4492
4493 /**
4494  * halmac_send_general_info_88xx() -send general information to FW
4495  * @halmac_adapter : the adapter of halmac
4496  * @general_info : general information
4497  * Author : KaiYuan Chang/Ivan Lin
4498  * Return : enum halmac_ret_status
4499  * More details of status code can be found in prototype document
4500  */
4501 enum halmac_ret_status
4502 halmac_send_general_info_88xx(struct halmac_adapter *halmac_adapter,
4503                               struct halmac_general_info *general_info)
4504 {
4505         void *driver_adapter = NULL;
4506         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4507
4508         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4509                 return HALMAC_RET_ADAPTER_INVALID;
4510
4511         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4512                 return HALMAC_RET_API_INVALID;
4513
4514         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4515                 return HALMAC_RET_NO_DLFW;
4516
4517         if (halmac_adapter->fw_version.h2c_version < 4)
4518                 return HALMAC_RET_FW_NO_SUPPORT;
4519
4520         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_GENERAL_INFO);
4521
4522         driver_adapter = halmac_adapter->driver_adapter;
4523
4524         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4525                         "%s ==========>\n", __func__);
4526
4527         if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) {
4528                 pr_err("%s Fail due to DLFW NONE!!\n", __func__);
4529                 return HALMAC_RET_DLFW_FAIL;
4530         }
4531
4532         status = halmac_func_send_general_info_88xx(halmac_adapter,
4533                                                     general_info);
4534
4535         if (status != HALMAC_RET_SUCCESS) {
4536                 pr_err("halmac_send_general_info error = %x\n", status);
4537                 return status;
4538         }
4539
4540         if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_DONE)
4541                 halmac_adapter->halmac_state.dlfw_state = HALMAC_GEN_INFO_SENT;
4542
4543         halmac_adapter->gen_info_valid = true;
4544         memcpy(&halmac_adapter->general_info, general_info,
4545                sizeof(struct halmac_general_info));
4546
4547         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4548                         "%s <==========\n", __func__);
4549
4550         return HALMAC_RET_SUCCESS;
4551 }
4552
4553 /**
4554  * halmac_start_iqk_88xx() -trigger FW IQK
4555  * @halmac_adapter : the adapter of halmac
4556  * @iqk_para : IQK parameter
4557  * Author : KaiYuan Chang/Ivan Lin
4558  * Return : enum halmac_ret_status
4559  * More details of status code can be found in prototype document
4560  */
4561 enum halmac_ret_status
4562 halmac_start_iqk_88xx(struct halmac_adapter *halmac_adapter,
4563                       struct halmac_iqk_para_ *iqk_para)
4564 {
4565         u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4566         u16 h2c_seq_num = 0;
4567         void *driver_adapter = NULL;
4568         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4569         struct halmac_h2c_header_info h2c_header_info;
4570         enum halmac_cmd_process_status *process_status =
4571                 &halmac_adapter->halmac_state.iqk_set.process_status;
4572
4573         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4574                 return HALMAC_RET_ADAPTER_INVALID;
4575
4576         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4577                 return HALMAC_RET_API_INVALID;
4578
4579         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4580                 return HALMAC_RET_NO_DLFW;
4581
4582         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_START_IQK);
4583
4584         driver_adapter = halmac_adapter->driver_adapter;
4585
4586         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4587                         "%s ==========>\n", __func__);
4588
4589         if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
4590                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4591                                 "Wait event(iqk)...\n");
4592                 return HALMAC_RET_BUSY_STATE;
4593         }
4594
4595         *process_status = HALMAC_CMD_PROCESS_SENDING;
4596
4597         IQK_SET_CLEAR(h2c_buff, iqk_para->clear);
4598         IQK_SET_SEGMENT_IQK(h2c_buff, iqk_para->segment_iqk);
4599
4600         h2c_header_info.sub_cmd_id = SUB_CMD_ID_IQK;
4601         h2c_header_info.content_size = 1;
4602         h2c_header_info.ack = true;
4603         halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4604                                               &h2c_header_info, &h2c_seq_num);
4605
4606         halmac_adapter->halmac_state.iqk_set.seq_num = h2c_seq_num;
4607
4608         status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4609                                           HALMAC_H2C_CMD_SIZE_88XX, true);
4610
4611         if (status != HALMAC_RET_SUCCESS) {
4612                 pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
4613                 return status;
4614         }
4615
4616         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4617                         "%s <==========\n", __func__);
4618
4619         return HALMAC_RET_SUCCESS;
4620 }
4621
4622 /**
4623  * halmac_ctrl_pwr_tracking_88xx() -trigger FW power tracking
4624  * @halmac_adapter : the adapter of halmac
4625  * @pwr_tracking_opt : power tracking option
4626  * Author : KaiYuan Chang/Ivan Lin
4627  * Return : enum halmac_ret_status
4628  * More details of status code can be found in prototype document
4629  */
4630 enum halmac_ret_status halmac_ctrl_pwr_tracking_88xx(
4631         struct halmac_adapter *halmac_adapter,
4632         struct halmac_pwr_tracking_option *pwr_tracking_opt)
4633 {
4634         u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
4635         u16 h2c_seq_mum = 0;
4636         void *driver_adapter = NULL;
4637         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4638         struct halmac_h2c_header_info h2c_header_info;
4639         enum halmac_cmd_process_status *process_status =
4640                 &halmac_adapter->halmac_state.power_tracking_set.process_status;
4641
4642         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4643                 return HALMAC_RET_ADAPTER_INVALID;
4644
4645         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4646                 return HALMAC_RET_API_INVALID;
4647
4648         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4649                 return HALMAC_RET_NO_DLFW;
4650
4651         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_PWR_TRACKING);
4652
4653         driver_adapter = halmac_adapter->driver_adapter;
4654
4655         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4656                         "halmac_start_iqk_88xx ==========>\n");
4657
4658         if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
4659                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
4660                                 "Wait event(pwr tracking)...\n");
4661                 return HALMAC_RET_BUSY_STATE;
4662         }
4663
4664         *process_status = HALMAC_CMD_PROCESS_SENDING;
4665
4666         POWER_TRACKING_SET_TYPE(h2c_buff, pwr_tracking_opt->type);
4667         POWER_TRACKING_SET_BBSWING_INDEX(h2c_buff,
4668                                          pwr_tracking_opt->bbswing_index);
4669         POWER_TRACKING_SET_ENABLE_A(
4670                 h2c_buff,
4671                 pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A].enable);
4672         POWER_TRACKING_SET_TX_PWR_INDEX_A(
4673                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4674                                   .tx_pwr_index);
4675         POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_A(
4676                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4677                                   .pwr_tracking_offset_value);
4678         POWER_TRACKING_SET_TSSI_VALUE_A(
4679                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A]
4680                                   .tssi_value);
4681         POWER_TRACKING_SET_ENABLE_B(
4682                 h2c_buff,
4683                 pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B].enable);
4684         POWER_TRACKING_SET_TX_PWR_INDEX_B(
4685                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4686                                   .tx_pwr_index);
4687         POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_B(
4688                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4689                                   .pwr_tracking_offset_value);
4690         POWER_TRACKING_SET_TSSI_VALUE_B(
4691                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B]
4692                                   .tssi_value);
4693         POWER_TRACKING_SET_ENABLE_C(
4694                 h2c_buff,
4695                 pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C].enable);
4696         POWER_TRACKING_SET_TX_PWR_INDEX_C(
4697                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4698                                   .tx_pwr_index);
4699         POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_C(
4700                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4701                                   .pwr_tracking_offset_value);
4702         POWER_TRACKING_SET_TSSI_VALUE_C(
4703                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C]
4704                                   .tssi_value);
4705         POWER_TRACKING_SET_ENABLE_D(
4706                 h2c_buff,
4707                 pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D].enable);
4708         POWER_TRACKING_SET_TX_PWR_INDEX_D(
4709                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4710                                   .tx_pwr_index);
4711         POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_D(
4712                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4713                                   .pwr_tracking_offset_value);
4714         POWER_TRACKING_SET_TSSI_VALUE_D(
4715                 h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D]
4716                                   .tssi_value);
4717
4718         h2c_header_info.sub_cmd_id = SUB_CMD_ID_POWER_TRACKING;
4719         h2c_header_info.content_size = 20;
4720         h2c_header_info.ack = true;
4721         halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
4722                                               &h2c_header_info, &h2c_seq_mum);
4723
4724         halmac_adapter->halmac_state.power_tracking_set.seq_num = h2c_seq_mum;
4725
4726         status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
4727                                           HALMAC_H2C_CMD_SIZE_88XX, true);
4728
4729         if (status != HALMAC_RET_SUCCESS) {
4730                 pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
4731                 return status;
4732         }
4733
4734         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4735                         "halmac_start_iqk_88xx <==========\n");
4736
4737         return HALMAC_RET_SUCCESS;
4738 }
4739
4740 /**
4741  * halmac_query_status_88xx() -query the offload feature status
4742  * @halmac_adapter : the adapter of halmac
4743  * @feature_id : feature_id
4744  * @process_status : feature_status
4745  * @data : data buffer
4746  * @size : data size
4747  *
4748  * Note :
4749  * If user wants to know the data size, use can allocate zero
4750  * size buffer first. If this size less than the data size, halmac
4751  * will return  HALMAC_RET_BUFFER_TOO_SMALL. User need to
4752  * re-allocate data buffer with correct data size.
4753  *
4754  * Author : Ivan Lin/KaiYuan Chang
4755  * Return : enum halmac_ret_status
4756  * More details of status code can be found in prototype document
4757  */
4758 enum halmac_ret_status
4759 halmac_query_status_88xx(struct halmac_adapter *halmac_adapter,
4760                          enum halmac_feature_id feature_id,
4761                          enum halmac_cmd_process_status *process_status,
4762                          u8 *data, u32 *size)
4763 {
4764         void *driver_adapter = NULL;
4765         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4766
4767         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4768                 return HALMAC_RET_ADAPTER_INVALID;
4769
4770         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4771                 return HALMAC_RET_API_INVALID;
4772
4773         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_QUERY_STATE);
4774
4775         driver_adapter = halmac_adapter->driver_adapter;
4776
4777         if (!process_status) {
4778                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4779                                 "null pointer!!\n");
4780                 return HALMAC_RET_NULL_POINTER;
4781         }
4782
4783         switch (feature_id) {
4784         case HALMAC_FEATURE_CFG_PARA:
4785                 status = halmac_query_cfg_para_status_88xx(
4786                         halmac_adapter, process_status, data, size);
4787                 break;
4788         case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
4789                 status = halmac_query_dump_physical_efuse_status_88xx(
4790                         halmac_adapter, process_status, data, size);
4791                 break;
4792         case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
4793                 status = halmac_query_dump_logical_efuse_status_88xx(
4794                         halmac_adapter, process_status, data, size);
4795                 break;
4796         case HALMAC_FEATURE_CHANNEL_SWITCH:
4797                 status = halmac_query_channel_switch_status_88xx(
4798                         halmac_adapter, process_status, data, size);
4799                 break;
4800         case HALMAC_FEATURE_UPDATE_PACKET:
4801                 status = halmac_query_update_packet_status_88xx(
4802                         halmac_adapter, process_status, data, size);
4803                 break;
4804         case HALMAC_FEATURE_IQK:
4805                 status = halmac_query_iqk_status_88xx(
4806                         halmac_adapter, process_status, data, size);
4807                 break;
4808         case HALMAC_FEATURE_POWER_TRACKING:
4809                 status = halmac_query_power_tracking_status_88xx(
4810                         halmac_adapter, process_status, data, size);
4811                 break;
4812         case HALMAC_FEATURE_PSD:
4813                 status = halmac_query_psd_status_88xx(
4814                         halmac_adapter, process_status, data, size);
4815                 break;
4816         default:
4817                 pr_err("%s invalid feature id %d\n", __func__,
4818                        feature_id);
4819                 return HALMAC_RET_INVALID_FEATURE_ID;
4820         }
4821
4822         return status;
4823 }
4824
4825 /**
4826  * halmac_reset_feature_88xx() -reset async api cmd status
4827  * @halmac_adapter : the adapter of halmac
4828  * @feature_id : feature_id
4829  * Author : Ivan Lin/KaiYuan Chang
4830  * Return : enum halmac_ret_status.
4831  * More details of status code can be found in prototype document
4832  */
4833 enum halmac_ret_status
4834 halmac_reset_feature_88xx(struct halmac_adapter *halmac_adapter,
4835                           enum halmac_feature_id feature_id)
4836 {
4837         void *driver_adapter = NULL;
4838         struct halmac_state *state = &halmac_adapter->halmac_state;
4839
4840         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4841                 return HALMAC_RET_ADAPTER_INVALID;
4842
4843         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4844                 return HALMAC_RET_API_INVALID;
4845
4846         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_RESET_FEATURE);
4847
4848         driver_adapter = halmac_adapter->driver_adapter;
4849
4850         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4851                         "%s ==========>\n", __func__);
4852
4853         switch (feature_id) {
4854         case HALMAC_FEATURE_CFG_PARA:
4855                 state->cfg_para_state_set.process_status =
4856                         HALMAC_CMD_PROCESS_IDLE;
4857                 state->cfg_para_state_set.cfg_para_cmd_construct_state =
4858                         HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE;
4859                 break;
4860         case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
4861         case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
4862                 state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4863                 state->efuse_state_set.efuse_cmd_construct_state =
4864                         HALMAC_EFUSE_CMD_CONSTRUCT_IDLE;
4865                 break;
4866         case HALMAC_FEATURE_CHANNEL_SWITCH:
4867                 state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4868                 state->scan_state_set.scan_cmd_construct_state =
4869                         HALMAC_SCAN_CMD_CONSTRUCT_IDLE;
4870                 break;
4871         case HALMAC_FEATURE_UPDATE_PACKET:
4872                 state->update_packet_set.process_status =
4873                         HALMAC_CMD_PROCESS_IDLE;
4874                 break;
4875         case HALMAC_FEATURE_ALL:
4876                 state->cfg_para_state_set.process_status =
4877                         HALMAC_CMD_PROCESS_IDLE;
4878                 state->cfg_para_state_set.cfg_para_cmd_construct_state =
4879                         HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE;
4880                 state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4881                 state->efuse_state_set.efuse_cmd_construct_state =
4882                         HALMAC_EFUSE_CMD_CONSTRUCT_IDLE;
4883                 state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE;
4884                 state->scan_state_set.scan_cmd_construct_state =
4885                         HALMAC_SCAN_CMD_CONSTRUCT_IDLE;
4886                 state->update_packet_set.process_status =
4887                         HALMAC_CMD_PROCESS_IDLE;
4888                 break;
4889         default:
4890                 pr_err("%s invalid feature id %d\n", __func__,
4891                        feature_id);
4892                 return HALMAC_RET_INVALID_FEATURE_ID;
4893         }
4894
4895         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4896                         "%s <==========\n", __func__);
4897
4898         return HALMAC_RET_SUCCESS;
4899 }
4900
4901 /**
4902  * halmac_check_fw_status_88xx() -check fw status
4903  * @halmac_adapter : the adapter of halmac
4904  * @fw_status : fw status
4905  * Author : KaiYuan Chang/Ivan Lin
4906  * Return : enum halmac_ret_status
4907  * More details of status code can be found in prototype document
4908  */
4909 enum halmac_ret_status
4910 halmac_check_fw_status_88xx(struct halmac_adapter *halmac_adapter,
4911                             bool *fw_status)
4912 {
4913         u32 value32 = 0, value32_backup = 0, i = 0;
4914         void *driver_adapter = NULL;
4915         struct halmac_api *halmac_api;
4916         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4917
4918         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4919                 return HALMAC_RET_ADAPTER_INVALID;
4920
4921         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4922                 return HALMAC_RET_API_INVALID;
4923
4924         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CHECK_FW_STATUS);
4925
4926         driver_adapter = halmac_adapter->driver_adapter;
4927         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
4928
4929         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4930                         "%s ==========>\n", __func__);
4931
4932         value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG6);
4933
4934         if (value32 != 0) {
4935                 pr_err("halmac_check_fw_status REG_FW_DBG6 !=0\n");
4936                 *fw_status = false;
4937                 return status;
4938         }
4939
4940         value32_backup = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7);
4941
4942         for (i = 0; i <= 10; i++) {
4943                 value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7);
4944                 if (value32_backup != value32)
4945                         break;
4946
4947                 if (i == 10) {
4948                         pr_err("halmac_check_fw_status Polling FW PC fail\n");
4949                         *fw_status = false;
4950                         return status;
4951                 }
4952         }
4953
4954         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4955                         "%s <==========\n", __func__);
4956
4957         return status;
4958 }
4959
4960 enum halmac_ret_status
4961 halmac_dump_fw_dmem_88xx(struct halmac_adapter *halmac_adapter, u8 *dmem,
4962                          u32 *size)
4963 {
4964         void *driver_adapter = NULL;
4965         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4966
4967         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4968                 return HALMAC_RET_ADAPTER_INVALID;
4969
4970         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
4971                 return HALMAC_RET_API_INVALID;
4972
4973         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_FW_DMEM);
4974
4975         driver_adapter = halmac_adapter->driver_adapter;
4976
4977         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4978                         "%s ==========>\n", __func__);
4979
4980         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
4981                         "%s <==========\n", __func__);
4982
4983         return status;
4984 }
4985
4986 /**
4987  * halmac_cfg_max_dl_size_88xx() - config max download FW size
4988  * @halmac_adapter : the adapter of halmac
4989  * @size : max download fw size
4990  *
4991  * Halmac uses this setting to set max packet size for
4992  * download FW.
4993  * If user has not called this API, halmac use default
4994  * setting for download FW
4995  * Note1 : size need multiple of 2
4996  * Note2 : max size is 31K
4997  *
4998  * Author : Ivan Lin/KaiYuan Chang
4999  * Return : enum halmac_ret_status
5000  * More details of status code can be found in prototype document
5001  */
5002 enum halmac_ret_status
5003 halmac_cfg_max_dl_size_88xx(struct halmac_adapter *halmac_adapter, u32 size)
5004 {
5005         void *driver_adapter = NULL;
5006
5007         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5008                 return HALMAC_RET_ADAPTER_INVALID;
5009
5010         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5011                 return HALMAC_RET_API_INVALID;
5012
5013         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MAX_DL_SIZE);
5014
5015         driver_adapter = halmac_adapter->driver_adapter;
5016
5017         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5018                         "%s ==========>\n", __func__);
5019
5020         if (size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX_88XX) {
5021                 pr_err("size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX!\n");
5022                 return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
5023         }
5024
5025         if ((size & (2 - 1)) != 0) {
5026                 pr_err("size is not power of 2!\n");
5027                 return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
5028         }
5029
5030         halmac_adapter->max_download_size = size;
5031
5032         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5033                         "Cfg max size is : %X\n", size);
5034
5035         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG,
5036                         "%s <==========\n", __func__);
5037
5038         return HALMAC_RET_SUCCESS;
5039 }
5040
5041 /**
5042  * halmac_psd_88xx() - trigger fw psd
5043  * @halmac_adapter : the adapter of halmac
5044  * @start_psd : start PSD
5045  * @end_psd : end PSD
5046  * Author : KaiYuan Chang/Ivan Lin
5047  * Return : enum halmac_ret_status
5048  * More details of status code can be found in prototype document
5049  */
5050 enum halmac_ret_status halmac_psd_88xx(struct halmac_adapter *halmac_adapter,
5051                                        u16 start_psd, u16 end_psd)
5052 {
5053         u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
5054         u16 h2c_seq_mum = 0;
5055         void *driver_adapter = NULL;
5056         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
5057         struct halmac_h2c_header_info h2c_header_info;
5058         enum halmac_cmd_process_status *process_status =
5059                 &halmac_adapter->halmac_state.psd_set.process_status;
5060
5061         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5062                 return HALMAC_RET_ADAPTER_INVALID;
5063
5064         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5065                 return HALMAC_RET_API_INVALID;
5066
5067         if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5068                 return HALMAC_RET_NO_DLFW;
5069
5070         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PSD);
5071
5072         driver_adapter = halmac_adapter->driver_adapter;
5073
5074         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5075                         "%s ==========>\n", __func__);
5076
5077         if (*process_status == HALMAC_CMD_PROCESS_SENDING) {
5078                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5079                                 "Wait event(psd)...\n");
5080                 return HALMAC_RET_BUSY_STATE;
5081         }
5082
5083         kfree(halmac_adapter->halmac_state.psd_set.data);
5084         halmac_adapter->halmac_state.psd_set.data = (u8 *)NULL;
5085
5086         halmac_adapter->halmac_state.psd_set.data_size = 0;
5087         halmac_adapter->halmac_state.psd_set.segment_size = 0;
5088
5089         *process_status = HALMAC_CMD_PROCESS_SENDING;
5090
5091         PSD_SET_START_PSD(h2c_buff, start_psd);
5092         PSD_SET_END_PSD(h2c_buff, end_psd);
5093
5094         h2c_header_info.sub_cmd_id = SUB_CMD_ID_PSD;
5095         h2c_header_info.content_size = 4;
5096         h2c_header_info.ack = true;
5097         halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff,
5098                                               &h2c_header_info, &h2c_seq_mum);
5099
5100         status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff,
5101                                           HALMAC_H2C_CMD_SIZE_88XX, true);
5102
5103         if (status != HALMAC_RET_SUCCESS) {
5104                 pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status);
5105                 return status;
5106         }
5107
5108         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5109                         "%s <==========\n", __func__);
5110
5111         return HALMAC_RET_SUCCESS;
5112 }
5113
5114 /**
5115  * halmac_cfg_la_mode_88xx() - config la mode
5116  * @halmac_adapter : the adapter of halmac
5117  * @la_mode :
5118  *      disable : no TXFF space reserved for LA debug
5119  *      partial : partial TXFF space is reserved for LA debug
5120  *      full : all TXFF space is reserved for LA debug
5121  * Author : KaiYuan Chang
5122  * Return : enum halmac_ret_status
5123  * More details of status code can be found in prototype document
5124  */
5125 enum halmac_ret_status
5126 halmac_cfg_la_mode_88xx(struct halmac_adapter *halmac_adapter,
5127                         enum halmac_la_mode la_mode)
5128 {
5129         void *driver_adapter = NULL;
5130
5131         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5132                 return HALMAC_RET_ADAPTER_INVALID;
5133
5134         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5135                 return HALMAC_RET_API_INVALID;
5136
5137         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_LA_MODE);
5138
5139         driver_adapter = halmac_adapter->driver_adapter;
5140
5141         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5142                         "%s ==========>la_mode = %d\n", __func__,
5143                         la_mode);
5144
5145         halmac_adapter->txff_allocation.la_mode = la_mode;
5146
5147         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5148                         "%s <==========\n", __func__);
5149
5150         return HALMAC_RET_SUCCESS;
5151 }
5152
5153 /**
5154  * halmac_cfg_rx_fifo_expanding_mode_88xx() - rx fifo expanding
5155  * @halmac_adapter : the adapter of halmac
5156  * @la_mode :
5157  *      disable : normal mode
5158  *      1 block : Rx FIFO + 1 FIFO block; Tx fifo - 1 FIFO block
5159  *      2 block : Rx FIFO + 2 FIFO block; Tx fifo - 2 FIFO block
5160  *      3 block : Rx FIFO + 3 FIFO block; Tx fifo - 3 FIFO block
5161  * Author : Soar
5162  * Return : enum halmac_ret_status
5163  * More details of status code can be found in prototype document
5164  */
5165 enum halmac_ret_status halmac_cfg_rx_fifo_expanding_mode_88xx(
5166         struct halmac_adapter *halmac_adapter,
5167         enum halmac_rx_fifo_expanding_mode rx_fifo_expanding_mode)
5168 {
5169         void *driver_adapter = NULL;
5170
5171         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5172                 return HALMAC_RET_ADAPTER_INVALID;
5173
5174         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5175                 return HALMAC_RET_API_INVALID;
5176
5177         halmac_api_record_id_88xx(halmac_adapter,
5178                                   HALMAC_API_CFG_RX_FIFO_EXPANDING_MODE);
5179
5180         driver_adapter = halmac_adapter->driver_adapter;
5181
5182         HALMAC_RT_TRACE(
5183                 driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5184                 "%s ==========>rx_fifo_expanding_mode = %d\n", __func__,
5185                 rx_fifo_expanding_mode);
5186
5187         halmac_adapter->txff_allocation.rx_fifo_expanding_mode =
5188                 rx_fifo_expanding_mode;
5189
5190         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5191                         "%s <==========\n", __func__);
5192
5193         return HALMAC_RET_SUCCESS;
5194 }
5195
5196 enum halmac_ret_status
5197 halmac_config_security_88xx(struct halmac_adapter *halmac_adapter,
5198                             struct halmac_security_setting *sec_setting)
5199 {
5200         struct halmac_api *halmac_api;
5201         void *driver_adapter = NULL;
5202
5203         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5204                 return HALMAC_RET_ADAPTER_INVALID;
5205
5206         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5207                 return HALMAC_RET_API_INVALID;
5208
5209         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5210         driver_adapter = halmac_adapter->driver_adapter;
5211
5212         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5213                         "%s ==========>\n", __func__);
5214
5215         HALMAC_REG_WRITE_16(halmac_adapter, REG_CR,
5216                             (u16)(HALMAC_REG_READ_16(halmac_adapter, REG_CR) |
5217                                   BIT_MAC_SEC_EN));
5218
5219         if (sec_setting->tx_encryption == 1)
5220                 HALMAC_REG_WRITE_8(
5221                         halmac_adapter, REG_SECCFG,
5222                         HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(2));
5223         else
5224                 HALMAC_REG_WRITE_8(
5225                         halmac_adapter, REG_SECCFG,
5226                         HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) &
5227                                 ~(BIT(2)));
5228
5229         if (sec_setting->rx_decryption == 1)
5230                 HALMAC_REG_WRITE_8(
5231                         halmac_adapter, REG_SECCFG,
5232                         HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(3));
5233         else
5234                 HALMAC_REG_WRITE_8(
5235                         halmac_adapter, REG_SECCFG,
5236                         HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) &
5237                                 ~(BIT(3)));
5238
5239         if (sec_setting->bip_enable == 1) {
5240                 if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8822B)
5241                         return HALMAC_RET_BIP_NO_SUPPORT;
5242         }
5243
5244         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5245                         "%s <==========\n", __func__);
5246
5247         return HALMAC_RET_SUCCESS;
5248 }
5249
5250 u8 halmac_get_used_cam_entry_num_88xx(struct halmac_adapter *halmac_adapter,
5251                                       enum hal_security_type sec_type)
5252 {
5253         u8 entry_num;
5254         void *driver_adapter = NULL;
5255
5256         driver_adapter = halmac_adapter->driver_adapter;
5257
5258         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5259                         "%s ==========>\n", __func__);
5260
5261         switch (sec_type) {
5262         case HAL_SECURITY_TYPE_WEP40:
5263         case HAL_SECURITY_TYPE_WEP104:
5264         case HAL_SECURITY_TYPE_TKIP:
5265         case HAL_SECURITY_TYPE_AES128:
5266         case HAL_SECURITY_TYPE_GCMP128:
5267         case HAL_SECURITY_TYPE_GCMSMS4:
5268         case HAL_SECURITY_TYPE_BIP:
5269                 entry_num = 1;
5270                 break;
5271         case HAL_SECURITY_TYPE_WAPI:
5272         case HAL_SECURITY_TYPE_AES256:
5273         case HAL_SECURITY_TYPE_GCMP256:
5274                 entry_num = 2;
5275                 break;
5276         default:
5277                 entry_num = 0;
5278                 break;
5279         }
5280
5281         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5282                         "%s <==========\n", __func__);
5283
5284         return entry_num;
5285 }
5286
5287 enum halmac_ret_status
5288 halmac_write_cam_88xx(struct halmac_adapter *halmac_adapter, u32 entry_index,
5289                       struct halmac_cam_entry_info *cam_entry_info)
5290 {
5291         u32 i;
5292         u32 command = 0x80010000;
5293         struct halmac_api *halmac_api;
5294         void *driver_adapter = NULL;
5295         struct halmac_cam_entry_format *cam_entry_format = NULL;
5296
5297         driver_adapter = halmac_adapter->driver_adapter;
5298         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5299
5300         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5301                         "[TRACE]%s ==========>\n", __func__);
5302
5303         if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5304                 return HALMAC_RET_ENTRY_INDEX_ERROR;
5305
5306         if (cam_entry_info->key_id > 3)
5307                 return HALMAC_RET_FAIL;
5308
5309         cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL);
5310         if (!cam_entry_format)
5311                 return HALMAC_RET_NULL_POINTER;
5312
5313         cam_entry_format->key_id = cam_entry_info->key_id;
5314         cam_entry_format->valid = cam_entry_info->valid;
5315         memcpy(cam_entry_format->mac_address, cam_entry_info->mac_address, 6);
5316         memcpy(cam_entry_format->key, cam_entry_info->key, 16);
5317
5318         switch (cam_entry_info->security_type) {
5319         case HAL_SECURITY_TYPE_NONE:
5320                 cam_entry_format->type = 0;
5321                 break;
5322         case HAL_SECURITY_TYPE_WEP40:
5323                 cam_entry_format->type = 1;
5324                 break;
5325         case HAL_SECURITY_TYPE_WEP104:
5326                 cam_entry_format->type = 5;
5327                 break;
5328         case HAL_SECURITY_TYPE_TKIP:
5329                 cam_entry_format->type = 2;
5330                 break;
5331         case HAL_SECURITY_TYPE_AES128:
5332                 cam_entry_format->type = 4;
5333                 break;
5334         case HAL_SECURITY_TYPE_WAPI:
5335                 cam_entry_format->type = 6;
5336                 break;
5337         case HAL_SECURITY_TYPE_AES256:
5338                 cam_entry_format->type = 4;
5339                 cam_entry_format->ext_sectype = 1;
5340                 break;
5341         case HAL_SECURITY_TYPE_GCMP128:
5342                 cam_entry_format->type = 7;
5343                 break;
5344         case HAL_SECURITY_TYPE_GCMP256:
5345         case HAL_SECURITY_TYPE_GCMSMS4:
5346                 cam_entry_format->type = 7;
5347                 cam_entry_format->ext_sectype = 1;
5348                 break;
5349         case HAL_SECURITY_TYPE_BIP:
5350                 cam_entry_format->type = cam_entry_info->unicast == 1 ? 4 : 0;
5351                 cam_entry_format->mgnt = 1;
5352                 cam_entry_format->grp = cam_entry_info->unicast == 1 ? 0 : 1;
5353                 break;
5354         default:
5355                 kfree(cam_entry_format);
5356                 return HALMAC_RET_FAIL;
5357         }
5358
5359         for (i = 0; i < 8; i++) {
5360                 HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5361                                     *((u32 *)cam_entry_format + i));
5362                 HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5363                                     command | ((entry_index << 3) + i));
5364                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5365                                 "[TRACE]1 - CAM entry format : %X\n",
5366                                 *((u32 *)cam_entry_format + i));
5367                 HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5368                                 "[TRACE]1 - REG_CAMCMD : %X\n",
5369                                 command | ((entry_index << 3) + i));
5370         }
5371
5372         if (cam_entry_info->security_type == HAL_SECURITY_TYPE_WAPI ||
5373             cam_entry_info->security_type == HAL_SECURITY_TYPE_AES256 ||
5374             cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMP256 ||
5375             cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMSMS4) {
5376                 cam_entry_format->mic = 1;
5377                 memcpy(cam_entry_format->key, cam_entry_info->key_ext, 16);
5378
5379                 for (i = 0; i < 8; i++) {
5380                         HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5381                                             *((u32 *)cam_entry_format + i));
5382                         HALMAC_REG_WRITE_32(
5383                                 halmac_adapter, REG_CAMCMD,
5384                                 command | (((entry_index + 1) << 3) + i));
5385                         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON,
5386                                         DBG_DMESG,
5387                                         "[TRACE]2 - CAM entry format : %X\n",
5388                                         *((u32 *)cam_entry_format + i));
5389                         HALMAC_RT_TRACE(
5390                                 driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5391                                 "[TRACE]2 - REG_CAMCMD : %X\n",
5392                                 command | (((entry_index + 1) << 3) + i));
5393                 }
5394         }
5395
5396         kfree(cam_entry_format);
5397
5398         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5399                         "[TRACE]%s <==========\n", __func__);
5400
5401         return HALMAC_RET_SUCCESS;
5402 }
5403
5404 enum halmac_ret_status
5405 halmac_read_cam_entry_88xx(struct halmac_adapter *halmac_adapter,
5406                            u32 entry_index,
5407                            struct halmac_cam_entry_format *content)
5408 {
5409         u32 i;
5410         u32 command = 0x80000000;
5411         struct halmac_api *halmac_api;
5412         void *driver_adapter = NULL;
5413
5414         driver_adapter = halmac_adapter->driver_adapter;
5415         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5416
5417         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5418                         "%s ==========>\n", __func__);
5419
5420         if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5421                 return HALMAC_RET_ENTRY_INDEX_ERROR;
5422
5423         for (i = 0; i < 8; i++) {
5424                 HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5425                                     command | ((entry_index << 3) + i));
5426                 *((u32 *)content + i) =
5427                         HALMAC_REG_READ_32(halmac_adapter, REG_CAMREAD);
5428         }
5429
5430         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5431                         "%s <==========\n", __func__);
5432
5433         return HALMAC_RET_SUCCESS;
5434 }
5435
5436 enum halmac_ret_status
5437 halmac_clear_cam_entry_88xx(struct halmac_adapter *halmac_adapter,
5438                             u32 entry_index)
5439 {
5440         u32 i;
5441         u32 command = 0x80010000;
5442         void *driver_adapter = NULL;
5443         struct halmac_api *halmac_api;
5444         struct halmac_cam_entry_format *cam_entry_format;
5445
5446         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5447                 return HALMAC_RET_ADAPTER_INVALID;
5448
5449         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5450                 return HALMAC_RET_API_INVALID;
5451
5452         driver_adapter = halmac_adapter->driver_adapter;
5453         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5454
5455         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5456                         "[TRACE]halmac_clear_security_cam_88xx ==========>\n");
5457
5458         if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num)
5459                 return HALMAC_RET_ENTRY_INDEX_ERROR;
5460
5461         cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL);
5462         if (!cam_entry_format)
5463                 return HALMAC_RET_NULL_POINTER;
5464
5465         for (i = 0; i < 8; i++) {
5466                 HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE,
5467                                     *((u32 *)cam_entry_format + i));
5468                 HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD,
5469                                     command | ((entry_index << 3) + i));
5470         }
5471
5472         kfree(cam_entry_format);
5473
5474         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5475                         "[TRACE]halmac_clear_security_cam_88xx <==========\n");
5476
5477         return HALMAC_RET_SUCCESS;
5478 }
5479
5480 /**
5481  * halmac_get_hw_value_88xx() -get hw config value
5482  * @halmac_adapter : the adapter of halmac
5483  * @hw_id : hw id for driver to query
5484  * @pvalue : hw value, reference table to get data type
5485  * Author : KaiYuan Chang / Ivan Lin
5486  * Return : enum halmac_ret_status
5487  * More details of status code can be found in prototype document
5488  */
5489 enum halmac_ret_status
5490 halmac_get_hw_value_88xx(struct halmac_adapter *halmac_adapter,
5491                          enum halmac_hw_id hw_id, void *pvalue)
5492 {
5493         void *driver_adapter = NULL;
5494         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
5495
5496         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5497                 return HALMAC_RET_ADAPTER_INVALID;
5498
5499         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5500                 return HALMAC_RET_API_INVALID;
5501
5502         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE);
5503
5504         driver_adapter = halmac_adapter->driver_adapter;
5505
5506         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5507                         "%s ==========>\n", __func__);
5508
5509         if (!pvalue) {
5510                 pr_err("%s (!pvalue)==========>\n", __func__);
5511                 return HALMAC_RET_NULL_POINTER;
5512         }
5513
5514         switch (hw_id) {
5515         case HALMAC_HW_RQPN_MAPPING:
5516                 ((struct halmac_rqpn_map *)pvalue)->dma_map_vo =
5517                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO];
5518                 ((struct halmac_rqpn_map *)pvalue)->dma_map_vi =
5519                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI];
5520                 ((struct halmac_rqpn_map *)pvalue)->dma_map_be =
5521                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE];
5522                 ((struct halmac_rqpn_map *)pvalue)->dma_map_bk =
5523                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK];
5524                 ((struct halmac_rqpn_map *)pvalue)->dma_map_mg =
5525                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG];
5526                 ((struct halmac_rqpn_map *)pvalue)->dma_map_hi =
5527                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI];
5528                 break;
5529         case HALMAC_HW_EFUSE_SIZE:
5530                 *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size;
5531                 break;
5532         case HALMAC_HW_EEPROM_SIZE:
5533                 *(u32 *)pvalue = halmac_adapter->hw_config_info.eeprom_size;
5534                 break;
5535         case HALMAC_HW_BT_BANK_EFUSE_SIZE:
5536                 *(u32 *)pvalue = halmac_adapter->hw_config_info.bt_efuse_size;
5537                 break;
5538         case HALMAC_HW_BT_BANK1_EFUSE_SIZE:
5539         case HALMAC_HW_BT_BANK2_EFUSE_SIZE:
5540                 *(u32 *)pvalue = 0;
5541                 break;
5542         case HALMAC_HW_TXFIFO_SIZE:
5543                 *(u32 *)pvalue = halmac_adapter->hw_config_info.tx_fifo_size;
5544                 break;
5545         case HALMAC_HW_RSVD_PG_BNDY:
5546                 *(u16 *)pvalue =
5547                         halmac_adapter->txff_allocation.rsvd_drv_pg_bndy;
5548                 break;
5549         case HALMAC_HW_CAM_ENTRY_NUM:
5550                 *(u8 *)pvalue = halmac_adapter->hw_config_info.cam_entry_num;
5551                 break;
5552         case HALMAC_HW_WLAN_EFUSE_AVAILABLE_SIZE: /*Remove later*/
5553                 status = halmac_dump_logical_efuse_map_88xx(halmac_adapter,
5554                                                             HALMAC_EFUSE_R_DRV);
5555                 if (status != HALMAC_RET_SUCCESS)
5556                         return status;
5557                 *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size -
5558                                  HALMAC_PROTECTED_EFUSE_SIZE_88XX -
5559                                  halmac_adapter->efuse_end;
5560                 break;
5561         case HALMAC_HW_IC_VERSION:
5562                 *(u8 *)pvalue = halmac_adapter->chip_version;
5563                 break;
5564         case HALMAC_HW_PAGE_SIZE:
5565                 *(u32 *)pvalue = halmac_adapter->hw_config_info.page_size;
5566                 break;
5567         case HALMAC_HW_TX_AGG_ALIGN_SIZE:
5568                 *(u16 *)pvalue = halmac_adapter->hw_config_info.tx_align_size;
5569                 break;
5570         case HALMAC_HW_RX_AGG_ALIGN_SIZE:
5571                 *(u8 *)pvalue = 8;
5572                 break;
5573         case HALMAC_HW_DRV_INFO_SIZE:
5574                 *(u8 *)pvalue = halmac_adapter->drv_info_size;
5575                 break;
5576         case HALMAC_HW_TXFF_ALLOCATION:
5577                 memcpy(pvalue, &halmac_adapter->txff_allocation,
5578                        sizeof(struct halmac_txff_allocation));
5579                 break;
5580         case HALMAC_HW_TX_DESC_SIZE:
5581                 *(u32 *)pvalue = halmac_adapter->hw_config_info.txdesc_size;
5582                 break;
5583         case HALMAC_HW_RX_DESC_SIZE:
5584                 *(u32 *)pvalue = halmac_adapter->hw_config_info.rxdesc_size;
5585                 break;
5586         default:
5587                 return HALMAC_RET_PARA_NOT_SUPPORT;
5588         }
5589
5590         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5591                         "%s <==========\n", __func__);
5592
5593         return HALMAC_RET_SUCCESS;
5594 }
5595
5596 /**
5597  * halmac_set_hw_value_88xx() -set hw config value
5598  * @halmac_adapter : the adapter of halmac
5599  * @hw_id : hw id for driver to config
5600  * @pvalue : hw value, reference table to get data type
5601  * Author : KaiYuan Chang / Ivan Lin
5602  * Return : enum halmac_ret_status
5603  * More details of status code can be found in prototype document
5604  */
5605 enum halmac_ret_status
5606 halmac_set_hw_value_88xx(struct halmac_adapter *halmac_adapter,
5607                          enum halmac_hw_id hw_id, void *pvalue)
5608 {
5609         void *driver_adapter = NULL;
5610         enum halmac_ret_status status;
5611
5612         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5613                 return HALMAC_RET_ADAPTER_INVALID;
5614
5615         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5616                 return HALMAC_RET_API_INVALID;
5617
5618         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE);
5619
5620         driver_adapter = halmac_adapter->driver_adapter;
5621
5622         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5623                         "%s ==========>\n", __func__);
5624
5625         if (!pvalue) {
5626                 pr_err("%s (!pvalue)==========>\n", __func__);
5627                 return HALMAC_RET_NULL_POINTER;
5628         }
5629
5630         switch (hw_id) {
5631         case HALMAC_HW_USB_MODE:
5632                 status = halmac_set_usb_mode_88xx(
5633                         halmac_adapter, *(enum halmac_usb_mode *)pvalue);
5634                 if (status != HALMAC_RET_SUCCESS)
5635                         return status;
5636                 break;
5637         case HALMAC_HW_SEQ_EN:
5638                 break;
5639         case HALMAC_HW_BANDWIDTH:
5640                 halmac_cfg_bw_88xx(halmac_adapter, *(enum halmac_bw *)pvalue);
5641                 break;
5642         case HALMAC_HW_CHANNEL:
5643                 halmac_cfg_ch_88xx(halmac_adapter, *(u8 *)pvalue);
5644                 break;
5645         case HALMAC_HW_PRI_CHANNEL_IDX:
5646                 halmac_cfg_pri_ch_idx_88xx(halmac_adapter,
5647                                            *(enum halmac_pri_ch_idx *)pvalue);
5648                 break;
5649         case HALMAC_HW_EN_BB_RF:
5650                 halmac_enable_bb_rf_88xx(halmac_adapter, *(u8 *)pvalue);
5651                 break;
5652         case HALMAC_HW_SDIO_TX_PAGE_THRESHOLD:
5653                 halmac_config_sdio_tx_page_threshold_88xx(
5654                         halmac_adapter,
5655                         (struct halmac_tx_page_threshold_info *)pvalue);
5656                 break;
5657         case HALMAC_HW_AMPDU_CONFIG:
5658                 halmac_config_ampdu_88xx(halmac_adapter,
5659                                          (struct halmac_ampdu_config *)pvalue);
5660                 break;
5661         default:
5662                 return HALMAC_RET_PARA_NOT_SUPPORT;
5663         }
5664
5665         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5666                         "%s <==========\n", __func__);
5667
5668         return HALMAC_RET_SUCCESS;
5669 }
5670
5671 /**
5672  * halmac_cfg_drv_rsvd_pg_num_88xx() -config reserved page number for driver
5673  * @halmac_adapter : the adapter of halmac
5674  * @pg_num : page number
5675  * Author : KaiYuan Chang
5676  * Return : enum halmac_ret_status
5677  * More details of status code can be found in prototype document
5678  */
5679 enum halmac_ret_status
5680 halmac_cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *halmac_adapter,
5681                                 enum halmac_drv_rsvd_pg_num pg_num)
5682 {
5683         void *driver_adapter = NULL;
5684
5685         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5686                 return HALMAC_RET_ADAPTER_INVALID;
5687
5688         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5689                 return HALMAC_RET_API_INVALID;
5690
5691         halmac_api_record_id_88xx(halmac_adapter,
5692                                   HALMAC_API_CFG_DRV_RSVD_PG_NUM);
5693
5694         driver_adapter = halmac_adapter->driver_adapter;
5695
5696         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5697                         "%s ==========>pg_num = %d\n", __func__,
5698                         pg_num);
5699
5700         switch (pg_num) {
5701         case HALMAC_RSVD_PG_NUM16:
5702                 halmac_adapter->txff_allocation.rsvd_drv_pg_num = 16;
5703                 break;
5704         case HALMAC_RSVD_PG_NUM24:
5705                 halmac_adapter->txff_allocation.rsvd_drv_pg_num = 24;
5706                 break;
5707         case HALMAC_RSVD_PG_NUM32:
5708                 halmac_adapter->txff_allocation.rsvd_drv_pg_num = 32;
5709                 break;
5710         }
5711
5712         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5713                         "%s <==========\n", __func__);
5714
5715         return HALMAC_RET_SUCCESS;
5716 }
5717
5718 enum halmac_ret_status
5719 halmac_get_chip_version_88xx(struct halmac_adapter *halmac_adapter,
5720                              struct halmac_ver *version)
5721 {
5722         void *driver_adapter = NULL;
5723         struct halmac_api *halmac_api;
5724
5725         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5726                 return HALMAC_RET_ADAPTER_INVALID;
5727
5728         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5729                 return HALMAC_RET_API_INVALID;
5730
5731         driver_adapter = halmac_adapter->driver_adapter;
5732         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5733
5734         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5735                         "%s ==========>\n", __func__);
5736         version->major_ver = (u8)HALMAC_MAJOR_VER_88XX;
5737         version->prototype_ver = (u8)HALMAC_PROTOTYPE_VER_88XX;
5738         version->minor_ver = (u8)HALMAC_MINOR_VER_88XX;
5739         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
5740                         "%s <==========\n", __func__);
5741
5742         return HALMAC_RET_SUCCESS;
5743 }
5744
5745 /**
5746  * halmac_chk_txdesc_88xx() -check if the tx packet format is incorrect
5747  * @halmac_adapter : the adapter of halmac
5748  * @halmac_buf : tx Packet buffer, tx desc is included
5749  * @halmac_size : tx packet size
5750  * Author : KaiYuan Chang
5751  * Return : enum halmac_ret_status
5752  * More details of status code can be found in prototype document
5753  */
5754 enum halmac_ret_status
5755 halmac_chk_txdesc_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf,
5756                        u32 halmac_size)
5757 {
5758         void *driver_adapter = NULL;
5759         struct halmac_api *halmac_api;
5760
5761         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5762                 return HALMAC_RET_ADAPTER_INVALID;
5763
5764         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5765                 return HALMAC_RET_API_INVALID;
5766
5767         driver_adapter = halmac_adapter->driver_adapter;
5768         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5769
5770         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5771                         "%s ==========>\n", __func__);
5772
5773         if (GET_TX_DESC_BMC(halmac_buf))
5774                 if (GET_TX_DESC_AGG_EN(halmac_buf))
5775                         pr_err("TxDesc: Agg should not be set when BMC\n");
5776
5777         if (halmac_size < (GET_TX_DESC_TXPKTSIZE(halmac_buf) +
5778                            GET_TX_DESC_OFFSET(halmac_buf)))
5779                 pr_err("TxDesc: PktSize too small\n");
5780
5781         return HALMAC_RET_SUCCESS;
5782 }
5783
5784 /**
5785  * halmac_dl_drv_rsvd_page_88xx() - download packet to rsvd page
5786  * @halmac_adapter : the adapter of halmac
5787  * @pg_offset : page offset of driver's rsvd page
5788  * @halmac_buf : data to be downloaded, tx_desc is not included
5789  * @halmac_size : data size to be downloaded
5790  * Author : KaiYuan Chang
5791  * Return : enum halmac_ret_status
5792  * More details of status code can be found in prototype document
5793  */
5794 enum halmac_ret_status
5795 halmac_dl_drv_rsvd_page_88xx(struct halmac_adapter *halmac_adapter,
5796                              u8 pg_offset, u8 *halmac_buf, u32 halmac_size)
5797 {
5798         void *driver_adapter = NULL;
5799         struct halmac_api *halmac_api;
5800         enum halmac_ret_status ret_status;
5801         u16 drv_pg_bndy = 0;
5802         u32 dl_pg_num = 0;
5803
5804         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5805                 return HALMAC_RET_ADAPTER_INVALID;
5806
5807         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5808                 return HALMAC_RET_API_INVALID;
5809
5810         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DL_DRV_RSVD_PG);
5811
5812         driver_adapter = halmac_adapter->driver_adapter;
5813         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5814
5815         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5816                         "%s ==========>\n", __func__);
5817
5818         /*check boundary and size valid*/
5819         dl_pg_num = halmac_size / halmac_adapter->hw_config_info.page_size +
5820                     ((halmac_size &
5821                       (halmac_adapter->hw_config_info.page_size - 1)) ?
5822                              1 :
5823                              0);
5824         if (pg_offset + dl_pg_num >
5825             halmac_adapter->txff_allocation.rsvd_drv_pg_num) {
5826                 pr_err("[ERROR] driver download offset or size error ==========>\n");
5827                 return HALMAC_RET_DRV_DL_ERR;
5828         }
5829
5830         /*update to target download boundary*/
5831         drv_pg_bndy =
5832                 halmac_adapter->txff_allocation.rsvd_drv_pg_bndy + pg_offset;
5833         HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
5834                             (u16)(drv_pg_bndy & BIT_MASK_BCN_HEAD_1_V1));
5835
5836         ret_status = halmac_download_rsvd_page_88xx(halmac_adapter, halmac_buf,
5837                                                     halmac_size);
5838
5839         /*restore to original bundary*/
5840         if (ret_status != HALMAC_RET_SUCCESS) {
5841                 pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n",
5842                        ret_status);
5843                 HALMAC_REG_WRITE_16(
5844                         halmac_adapter, REG_FIFOPAGE_CTRL_2,
5845                         (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
5846                               BIT_MASK_BCN_HEAD_1_V1));
5847                 return ret_status;
5848         }
5849
5850         HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2,
5851                             (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy &
5852                                   BIT_MASK_BCN_HEAD_1_V1));
5853
5854         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
5855                         "%s < ==========\n", __func__);
5856         return HALMAC_RET_SUCCESS;
5857 }
5858
5859 /**
5860  * halmac_cfg_csi_rate_88xx() - config CSI frame Tx rate
5861  * @halmac_adapter : the adapter of halmac
5862  * @rssi : rssi in decimal value
5863  * @current_rate : current CSI frame rate
5864  * @fixrate_en : enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate
5865  * @new_rate : API returns the final CSI frame rate
5866  * Author : chunchu
5867  * Return : enum halmac_ret_status
5868  * More details of status code can be found in prototype document
5869  */
5870 enum halmac_ret_status
5871 halmac_cfg_csi_rate_88xx(struct halmac_adapter *halmac_adapter, u8 rssi,
5872                          u8 current_rate, u8 fixrate_en, u8 *new_rate)
5873 {
5874         void *driver_adapter = NULL;
5875         struct halmac_api *halmac_api;
5876         u32 temp_csi_setting;
5877         u16 current_rrsr;
5878         enum halmac_ret_status ret_status;
5879
5880         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5881                 return HALMAC_RET_ADAPTER_INVALID;
5882
5883         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
5884                 return HALMAC_RET_API_INVALID;
5885
5886         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CSI_RATE);
5887
5888         driver_adapter = halmac_adapter->driver_adapter;
5889         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5890         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG,
5891                         "<%s ==========>\n", __func__);
5892
5893         temp_csi_setting = HALMAC_REG_READ_32(halmac_adapter, REG_BBPSF_CTRL) &
5894                            ~(BIT_MASK_WMAC_CSI_RATE << BIT_SHIFT_WMAC_CSI_RATE);
5895
5896         current_rrsr = HALMAC_REG_READ_16(halmac_adapter, REG_RRSR);
5897
5898         if (rssi >= 40) {
5899                 if (current_rate != HALMAC_OFDM54) {
5900                         HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR,
5901                                             current_rrsr | BIT(HALMAC_OFDM54));
5902                         HALMAC_REG_WRITE_32(
5903                                 halmac_adapter, REG_BBPSF_CTRL,
5904                                 temp_csi_setting |
5905                                         BIT_WMAC_CSI_RATE(HALMAC_OFDM54));
5906                 }
5907                 *new_rate = HALMAC_OFDM54;
5908                 ret_status = HALMAC_RET_SUCCESS;
5909         } else {
5910                 if (current_rate != HALMAC_OFDM24) {
5911                         HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR,
5912                                             current_rrsr &
5913                                                     ~(BIT(HALMAC_OFDM54)));
5914                         HALMAC_REG_WRITE_32(
5915                                 halmac_adapter, REG_BBPSF_CTRL,
5916                                 temp_csi_setting |
5917                                         BIT_WMAC_CSI_RATE(HALMAC_OFDM24));
5918                 }
5919                 *new_rate = HALMAC_OFDM24;
5920                 ret_status = HALMAC_RET_SUCCESS;
5921         }
5922
5923         return ret_status;
5924 }
5925
5926 /**
5927  * halmac_sdio_cmd53_4byte_88xx() - cmd53 only for 4byte len register IO
5928  * @halmac_adapter : the adapter of halmac
5929  * @enable : 1->CMD53 only use in 4byte reg, 0 : No limitation
5930  * Author : Ivan Lin/KaiYuan Chang
5931  * Return : enum halmac_ret_status
5932  * More details of status code can be found in prototype document
5933  */
5934 enum halmac_ret_status
5935 halmac_sdio_cmd53_4byte_88xx(struct halmac_adapter *halmac_adapter,
5936                              enum halmac_sdio_cmd53_4byte_mode cmd53_4byte_mode)
5937 {
5938         halmac_adapter->sdio_cmd53_4byte = cmd53_4byte_mode;
5939
5940         return HALMAC_RET_SUCCESS;
5941 }
5942
5943 /**
5944  * halmac_txfifo_is_empty_88xx() -check if txfifo is empty
5945  * @halmac_adapter : the adapter of halmac
5946  * Author : Ivan Lin
5947  * Return : enum halmac_ret_status
5948  * More details of status code can be found in prototype document
5949  */
5950 enum halmac_ret_status
5951 halmac_txfifo_is_empty_88xx(struct halmac_adapter *halmac_adapter, u32 chk_num)
5952 {
5953         u32 counter;
5954         void *driver_adapter = NULL;
5955         struct halmac_api *halmac_api;
5956
5957         driver_adapter = halmac_adapter->driver_adapter;
5958         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
5959
5960         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5961                         "%s ==========>\n", __func__);
5962
5963         counter = (chk_num <= 10) ? 10 : chk_num;
5964         do {
5965                 if (HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY) != 0xFF)
5966                         return HALMAC_RET_TXFIFO_NO_EMPTY;
5967
5968                 if ((HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY + 1) &
5969                      0x07) != 0x07)
5970                         return HALMAC_RET_TXFIFO_NO_EMPTY;
5971                 counter--;
5972
5973         } while (counter != 0);
5974
5975         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG,
5976                         "%s <==========\n", __func__);
5977
5978         return HALMAC_RET_SUCCESS;
5979 }