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