OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / halmac / halmac_88xx / halmac_common_88xx.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15
16 #include "halmac_common_88xx.h"
17 #include "halmac_88xx_cfg.h"
18 #include "halmac_init_88xx.h"
19 #include "halmac_cfg_wmac_88xx.h"
20 #include "halmac_efuse_88xx.h"
21 #include "halmac_bb_rf_88xx.h"
22 #if HALMAC_USB_SUPPORT
23 #include "halmac_usb_88xx.h"
24 #endif
25 #if HALMAC_SDIO_SUPPORT
26 #include "halmac_sdio_88xx.h"
27 #endif
28 #if HALMAC_PCIE_SUPPORT
29 #include "halmac_pcie_88xx.h"
30 #endif
31 #include "halmac_mimo_88xx.h"
32
33 #if HALMAC_88XX_SUPPORT
34
35 #define CFG_PARAM_H2C_INFO_SIZE 12
36 #define ORIGINAL_H2C_CMD_SIZE   8
37
38 #define WLHDR_PROT_VER  0
39
40 #define WLHDR_TYPE_MGMT         0
41 #define WLHDR_TYPE_CTRL         1
42 #define WLHDR_TYPE_DATA         2
43
44 /* mgmt frame */
45 #define WLHDR_SUB_TYPE_ASSOC_REQ        0
46 #define WLHDR_SUB_TYPE_ASSOC_RSPNS      1
47 #define WLHDR_SUB_TYPE_REASSOC_REQ      2
48 #define WLHDR_SUB_TYPE_REASSOC_RSPNS    3
49 #define WLHDR_SUB_TYPE_PROBE_REQ        4
50 #define WLHDR_SUB_TYPE_PROBE_RSPNS      5
51 #define WLHDR_SUB_TYPE_BCN              8
52 #define WLHDR_SUB_TYPE_DISASSOC         10
53 #define WLHDR_SUB_TYPE_AUTH             11
54 #define WLHDR_SUB_TYPE_DEAUTH           12
55 #define WLHDR_SUB_TYPE_ACTION           13
56 #define WLHDR_SUB_TYPE_ACTION_NOACK     14
57
58 /* ctrl frame */
59 #define WLHDR_SUB_TYPE_BF_RPT_POLL      4
60 #define WLHDR_SUB_TYPE_NDPA             5
61
62 /* data frame */
63 #define WLHDR_SUB_TYPE_DATA             0
64 #define WLHDR_SUB_TYPE_NULL             4
65 #define WLHDR_SUB_TYPE_QOS_DATA         8
66 #define WLHDR_SUB_TYPE_QOS_NULL         12
67
68 #define LTECOEX_ACCESS_CTRL REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1
69
70 struct wlhdr_frame_ctrl {
71         u16 protocol:2;
72         u16 type:2;
73         u16 sub_type:4;
74         u16 to_ds:1;
75         u16 from_ds:1;
76         u16 more_frag:1;
77         u16 retry:1;
78         u16 pwr_mgmt:1;
79         u16 more_data:1;
80         u16 protect_frame:1;
81         u16 order:1;
82 };
83
84 static enum halmac_ret_status
85 parse_c2h_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
86
87 static enum halmac_ret_status
88 get_c2h_dbg_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
89
90 static enum halmac_ret_status
91 get_h2c_ack_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
92
93 static enum halmac_ret_status
94 get_scan_rpt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
95
96 static enum halmac_ret_status
97 get_h2c_ack_cfg_param_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
98
99 static enum halmac_ret_status
100 get_h2c_ack_update_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
101
102 static enum halmac_ret_status
103 get_h2c_ack_update_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf,
104                                 u32 size);
105
106 static enum halmac_ret_status
107 get_h2c_ack_run_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
108
109 static enum halmac_ret_status
110 get_h2c_ack_ch_switch_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
111
112 static enum halmac_ret_status
113 malloc_cfg_param_buf_88xx(struct halmac_adapter *adapter, u8 full_fifo);
114
115 static enum halmac_cmd_construct_state
116 cfg_param_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
117
118 static enum halmac_ret_status
119 proc_cfg_param_88xx(struct halmac_adapter *adapter,
120                     struct halmac_phy_parameter_info *param, u8 full_fifo);
121
122 static enum halmac_ret_status
123 send_cfg_param_h2c_88xx(struct halmac_adapter *adapter);
124
125 static enum halmac_ret_status
126 cnv_cfg_param_state_88xx(struct halmac_adapter *adapter,
127                          enum halmac_cmd_construct_state dest_state);
128
129 static enum halmac_ret_status
130 add_param_buf_88xx(struct halmac_adapter *adapter,
131                    struct halmac_phy_parameter_info *param, u8 *buf,
132                    u8 *end_cmd);
133
134 static enum halmac_ret_status
135 gen_cfg_param_h2c_88xx(struct halmac_adapter *adapter, u8 *buff);
136
137 static enum halmac_ret_status
138 send_h2c_update_packet_88xx(struct halmac_adapter *adapter,
139                             enum halmac_packet_id pkt_id, u8 *pkt, u32 size);
140
141 static enum halmac_ret_status
142 send_bt_coex_cmd_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
143                       u8 ack);
144
145 static enum halmac_ret_status
146 read_buf_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
147               enum hal_fifo_sel sel, u8 *data);
148
149 static enum halmac_cmd_construct_state
150 scan_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
151
152 static enum halmac_ret_status
153 cnv_scan_state_88xx(struct halmac_adapter *adapter,
154                     enum halmac_cmd_construct_state dest_state);
155
156 static enum halmac_ret_status
157 proc_ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
158                          struct halmac_ch_switch_option *opt);
159
160 static enum halmac_ret_status
161 proc_p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info);
162
163 static enum halmac_ret_status
164 get_cfg_param_status_88xx(struct halmac_adapter *adapter,
165                           enum halmac_cmd_process_status *proc_status);
166
167 static enum halmac_ret_status
168 get_ch_switch_status_88xx(struct halmac_adapter *adapter,
169                           enum halmac_cmd_process_status *proc_status);
170
171 static enum halmac_ret_status
172 get_update_packet_status_88xx(struct halmac_adapter *adapter,
173                               enum halmac_cmd_process_status *proc_status);
174
175 static enum halmac_ret_status
176 pwr_sub_seq_parser_88xx(struct halmac_adapter *adapter, u8 cut, u8 intf,
177                         struct halmac_wlan_pwr_cfg *cmd);
178
179 static void
180 pwr_state_88xx(struct halmac_adapter *adapter, enum halmac_mac_power *state);
181
182 static enum halmac_ret_status
183 pwr_cmd_polling_88xx(struct halmac_adapter *adapter,
184                      struct halmac_wlan_pwr_cfg *cmd);
185
186 static void
187 get_pq_mapping_88xx(struct halmac_adapter *adapter,
188                     struct halmac_rqpn_map *mapping);
189
190 static void
191 dump_reg_sdio_88xx(struct halmac_adapter *adapter);
192
193 static enum halmac_ret_status
194 wlhdr_valid_88xx(struct halmac_adapter *adapter, u8 *buf);
195
196 static u8
197 wlhdr_mgmt_valid_88xx(struct halmac_adapter *adapter,
198                       struct wlhdr_frame_ctrl *wlhdr);
199
200 static u8
201 wlhdr_ctrl_valid_88xx(struct halmac_adapter *adapter,
202                       struct wlhdr_frame_ctrl *wlhdr);
203
204 static u8
205 wlhdr_data_valid_88xx(struct halmac_adapter *adapter,
206                       struct wlhdr_frame_ctrl *wlhdr);
207
208 static void
209 dump_reg_88xx(struct halmac_adapter *adapter);
210
211 /**
212  * ofld_func_cfg_88xx() - config offload function
213  * @adapter : the adapter of halmac
214  * @info : offload function information
215  * Author : Ivan Lin
216  * Return : enum halmac_ret_status
217  * More details of status code can be found in prototype document
218  */
219 enum halmac_ret_status
220 ofld_func_cfg_88xx(struct halmac_adapter *adapter,
221                    struct halmac_ofld_func_info *info)
222 {
223         if (adapter->intf == HALMAC_INTERFACE_SDIO &&
224             info->rsvd_pg_drv_buf_max_sz > SDIO_TX_MAX_SIZE_88XX)
225                 return HALMAC_RET_FAIL;
226
227         adapter->pltfm_info.malloc_size = info->halmac_malloc_max_sz;
228         adapter->pltfm_info.rsvd_pg_size = info->rsvd_pg_drv_buf_max_sz;
229
230         return HALMAC_RET_SUCCESS;
231 }
232
233 /**
234  * dl_drv_rsvd_page_88xx() - download packet to rsvd page
235  * @adapter : the adapter of halmac
236  * @pg_offset : page offset of driver's rsvd page
237  * @halmac_buf : data to be downloaded, tx_desc is not included
238  * @halmac_size : data size to be downloaded
239  * Author : KaiYuan Chang
240  * Return : enum halmac_ret_status
241  * More details of status code can be found in prototype document
242  */
243 enum halmac_ret_status
244 dl_drv_rsvd_page_88xx(struct halmac_adapter *adapter, u8 pg_offset, u8 *buf,
245                       u32 size)
246 {
247         enum halmac_ret_status status;
248         u32 pg_size;
249         u32 pg_num = 0;
250         u16 pg_addr = 0;
251
252         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
253
254         pg_size = adapter->hw_cfg_info.page_size;
255         pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0);
256         if (pg_offset + pg_num > adapter->txff_alloc.rsvd_drv_pg_num) {
257                 PLTFM_MSG_ERR("[ERR] pkt overflow!!\n");
258                 return HALMAC_RET_DRV_DL_ERR;
259         }
260
261         pg_addr = adapter->txff_alloc.rsvd_drv_addr + pg_offset;
262
263         status = dl_rsvd_page_88xx(adapter, pg_addr, buf, size);
264
265         if (status != HALMAC_RET_SUCCESS) {
266                 PLTFM_MSG_ERR("[ERR]dl rsvd page fail!!\n");
267                 return status;
268         }
269
270         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
271
272         return HALMAC_RET_SUCCESS;
273 }
274
275 enum halmac_ret_status
276 dl_rsvd_page_88xx(struct halmac_adapter *adapter, u16 pg_addr, u8 *buf,
277                   u32 size)
278 {
279         u8 restore[2];
280         u8 value8;
281         u16 rsvd_pg_head;
282         u32 cnt;
283         enum halmac_rsvd_pg_state *state = &adapter->halmac_state.rsvd_pg_state;
284         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
285         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
286
287         if (size == 0) {
288                 PLTFM_MSG_TRACE("[TRACE]pkt size = 0\n");
289                 return HALMAC_RET_ZERO_LEN_RSVD_PACKET;
290         }
291
292         if (*state == HALMAC_RSVD_PG_STATE_BUSY)
293                 return HALMAC_RET_BUSY_STATE;
294
295         *state = HALMAC_RSVD_PG_STATE_BUSY;
296
297         pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
298         HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, (u16)(pg_addr | BIT(15)));
299
300         value8 = HALMAC_REG_R8(REG_CR + 1);
301         restore[0] = value8;
302         value8 = (u8)(value8 | BIT(0));
303         HALMAC_REG_W8(REG_CR + 1, value8);
304
305         value8 = HALMAC_REG_R8(REG_FWHW_TXQ_CTRL + 2);
306         restore[1] = value8;
307         value8 = (u8)(value8 & ~(BIT(6)));
308         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, value8);
309
310         if (PLTFM_SEND_RSVD_PAGE(buf, size) == 0) {
311                 PLTFM_MSG_ERR("[ERR]send rvsd pg(pltfm)!!\n");
312                 status = HALMAC_RET_DL_RSVD_PAGE_FAIL;
313                 goto DL_RSVD_PG_END;
314         }
315
316         cnt = 1000;
317         while (!(HALMAC_REG_R8(REG_FIFOPAGE_CTRL_2 + 1) & BIT(7))) {
318                 PLTFM_DELAY_US(10);
319                 cnt--;
320                 if (cnt == 0) {
321                         PLTFM_MSG_ERR("[ERR]bcn valid!!\n");
322                         status = HALMAC_RET_POLLING_BCN_VALID_FAIL;
323                         break;
324                 }
325         }
326 DL_RSVD_PG_END:
327         rsvd_pg_head = adapter->txff_alloc.rsvd_boundary;
328         HALMAC_REG_W16(REG_FIFOPAGE_CTRL_2, rsvd_pg_head | BIT(15));
329         HALMAC_REG_W8(REG_FWHW_TXQ_CTRL + 2, restore[1]);
330         HALMAC_REG_W8(REG_CR + 1, restore[0]);
331
332         *state = HALMAC_RSVD_PG_STATE_IDLE;
333
334         return status;
335 }
336
337 enum halmac_ret_status
338 get_hw_value_88xx(struct halmac_adapter *adapter, enum halmac_hw_id hw_id,
339                   void *value)
340 {
341         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
342
343         switch (hw_id) {
344         case HALMAC_HW_RQPN_MAPPING:
345                 get_pq_mapping_88xx(adapter, (struct halmac_rqpn_map *)value);
346                 break;
347         case HALMAC_HW_EFUSE_SIZE:
348                 *(u32 *)value = adapter->hw_cfg_info.efuse_size;
349                 break;
350         case HALMAC_HW_EEPROM_SIZE:
351                 *(u32 *)value = adapter->hw_cfg_info.eeprom_size;
352                 break;
353         case HALMAC_HW_BT_BANK_EFUSE_SIZE:
354                 *(u32 *)value = adapter->hw_cfg_info.bt_efuse_size;
355                 break;
356         case HALMAC_HW_BT_BANK1_EFUSE_SIZE:
357         case HALMAC_HW_BT_BANK2_EFUSE_SIZE:
358                 *(u32 *)value = 0;
359                 break;
360         case HALMAC_HW_TXFIFO_SIZE:
361                 *(u32 *)value = adapter->hw_cfg_info.tx_fifo_size;
362                 break;
363         case HALMAC_HW_RXFIFO_SIZE:
364                 *(u32 *)value = adapter->hw_cfg_info.rx_fifo_size;
365                 break;
366         case HALMAC_HW_RSVD_PG_BNDY:
367                 *(u16 *)value = adapter->txff_alloc.rsvd_drv_addr;
368                 break;
369         case HALMAC_HW_CAM_ENTRY_NUM:
370                 *(u8 *)value = adapter->hw_cfg_info.cam_entry_num;
371                 break;
372         case HALMAC_HW_WLAN_EFUSE_AVAILABLE_SIZE:
373                 get_efuse_available_size_88xx(adapter, (u32 *)value);
374                 break;
375         case HALMAC_HW_IC_VERSION:
376                 *(u8 *)value = adapter->chip_ver;
377                 break;
378         case HALMAC_HW_PAGE_SIZE:
379                 *(u32 *)value = adapter->hw_cfg_info.page_size;
380                 break;
381         case HALMAC_HW_TX_AGG_ALIGN_SIZE:
382                 *(u16 *)value = adapter->hw_cfg_info.tx_align_size;
383                 break;
384         case HALMAC_HW_RX_AGG_ALIGN_SIZE:
385                 *(u8 *)value = 8;
386                 break;
387         case HALMAC_HW_DRV_INFO_SIZE:
388                 *(u8 *)value = adapter->drv_info_size;
389                 break;
390         case HALMAC_HW_TXFF_ALLOCATION:
391                 PLTFM_MEMCPY(value, &adapter->txff_alloc,
392                              sizeof(struct halmac_txff_allocation));
393                 break;
394         case HALMAC_HW_RSVD_EFUSE_SIZE:
395                 *(u32 *)value = get_rsvd_efuse_size_88xx(adapter);
396                 break;
397         case HALMAC_HW_FW_HDR_SIZE:
398                 *(u32 *)value = WLAN_FW_HDR_SIZE;
399                 break;
400         case HALMAC_HW_TX_DESC_SIZE:
401                 *(u32 *)value = adapter->hw_cfg_info.txdesc_size;
402                 break;
403         case HALMAC_HW_RX_DESC_SIZE:
404                 *(u32 *)value = adapter->hw_cfg_info.rxdesc_size;
405                 break;
406         case HALMAC_HW_ORI_H2C_SIZE:
407                 *(u32 *)value = ORIGINAL_H2C_CMD_SIZE;
408                 break;
409         case HALMAC_HW_RSVD_DRV_PGNUM:
410                 *(u16 *)value = adapter->txff_alloc.rsvd_drv_pg_num;
411                 break;
412         case HALMAC_HW_TX_PAGE_SIZE:
413                 *(u16 *)value = TX_PAGE_SIZE_88XX;
414                 break;
415         case HALMAC_HW_USB_TXAGG_DESC_NUM:
416                 *(u8 *)value = adapter->hw_cfg_info.usb_txagg_num;
417                 break;
418         case HALMAC_HW_AC_OQT_SIZE:
419                 *(u8 *)value = adapter->hw_cfg_info.ac_oqt_size;
420                 break;
421         case HALMAC_HW_NON_AC_OQT_SIZE:
422                 *(u8 *)value = adapter->hw_cfg_info.non_ac_oqt_size;
423                 break;
424         case HALMAC_HW_AC_QUEUE_NUM:
425                 *(u8 *)value = adapter->hw_cfg_info.acq_num;
426                 break;
427         case HALMAC_HW_PWR_STATE:
428                 pwr_state_88xx(adapter, (enum halmac_mac_power *)value);
429                 break;
430         default:
431                 return HALMAC_RET_PARA_NOT_SUPPORT;
432         }
433
434         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
435
436         return HALMAC_RET_SUCCESS;
437 }
438
439 static void
440 get_pq_mapping_88xx(struct halmac_adapter *adapter,
441                     struct halmac_rqpn_map *mapping)
442 {
443         mapping->dma_map_vo = adapter->pq_map[HALMAC_PQ_MAP_VO];
444         mapping->dma_map_vi = adapter->pq_map[HALMAC_PQ_MAP_VI];
445         mapping->dma_map_be = adapter->pq_map[HALMAC_PQ_MAP_BE];
446         mapping->dma_map_bk = adapter->pq_map[HALMAC_PQ_MAP_BK];
447         mapping->dma_map_mg = adapter->pq_map[HALMAC_PQ_MAP_MG];
448         mapping->dma_map_hi = adapter->pq_map[HALMAC_PQ_MAP_HI];
449 }
450
451 /**
452  * set_hw_value_88xx() -set hw config value
453  * @adapter : the adapter of halmac
454  * @hw_id : hw id for driver to config
455  * @value : hw value, reference table to get data type
456  * Author : KaiYuan Chang / Ivan Lin
457  * Return : enum halmac_ret_status
458  * More details of status code can be found in prototype document
459  */
460 enum halmac_ret_status
461 set_hw_value_88xx(struct halmac_adapter *adapter, enum halmac_hw_id hw_id,
462                   void *value)
463 {
464         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
465         struct halmac_tx_page_threshold_info *th_info = NULL;
466         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
467
468         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
469
470         if (!value) {
471                 PLTFM_MSG_ERR("[ERR]null ptr-set hw value\n");
472                 return HALMAC_RET_NULL_POINTER;
473         }
474
475         switch (hw_id) {
476 #if HALMAC_USB_SUPPORT
477         case HALMAC_HW_USB_MODE:
478                 status = set_usb_mode_88xx(adapter,
479                                            *(enum halmac_usb_mode *)value);
480                 if (status != HALMAC_RET_SUCCESS)
481                         return status;
482                 break;
483 #endif
484         case HALMAC_HW_BANDWIDTH:
485                 cfg_bw_88xx(adapter, *(enum halmac_bw *)value);
486                 break;
487         case HALMAC_HW_CHANNEL:
488                 cfg_ch_88xx(adapter, *(u8 *)value);
489                 break;
490         case HALMAC_HW_PRI_CHANNEL_IDX:
491                 cfg_pri_ch_idx_88xx(adapter, *(enum halmac_pri_ch_idx *)value);
492                 break;
493         case HALMAC_HW_EN_BB_RF:
494                 enable_bb_rf_88xx(adapter, *(u8 *)value);
495                 break;
496 #if HALMAC_SDIO_SUPPORT
497         case HALMAC_HW_SDIO_TX_PAGE_THRESHOLD:
498                 if (adapter->intf == HALMAC_INTERFACE_SDIO) {
499                         th_info = (struct halmac_tx_page_threshold_info *)value;
500                         cfg_sdio_tx_page_threshold_88xx(adapter, th_info);
501                 } else {
502                         return HALMAC_RET_FAIL;
503                 }
504                 break;
505 #endif
506         case HALMAC_HW_RX_SHIFT:
507                 rx_shift_88xx(adapter, *(u8 *)value);
508                 break;
509         case HALMAC_HW_TXDESC_CHECKSUM:
510                 tx_desc_chksum_88xx(adapter, *(u8 *)value);
511                 break;
512         case HALMAC_HW_RX_CLK_GATE:
513                 rx_clk_gate_88xx(adapter, *(u8 *)value);
514                 break;
515         case HALMAC_HW_FAST_EDCA:
516                 fast_edca_cfg_88xx(adapter,
517                                    (struct halmac_fast_edca_cfg *)value);
518                 break;
519         case HALMAC_HW_RTS_FULL_BW:
520                 rts_full_bw_88xx(adapter, *(u8 *)value);
521                 break;
522         case HALMAC_HW_FREE_CNT_EN:
523                 HALMAC_REG_W8_SET(REG_MISC_CTRL, BIT_EN_FREECNT);
524                 break;
525         default:
526                 return HALMAC_RET_PARA_NOT_SUPPORT;
527         }
528
529         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
530
531         return HALMAC_RET_SUCCESS;
532 }
533
534 enum halmac_ret_status
535 set_h2c_pkt_hdr_88xx(struct halmac_adapter *adapter, u8 *hdr,
536                      struct halmac_h2c_header_info *info, u16 *seq_num)
537 {
538         u16 total_size;
539
540         PLTFM_MSG_TRACE("[TRACE]%s!!\n", __func__);
541
542         total_size = H2C_PKT_HDR_SIZE_88XX + info->content_size;
543         FW_OFFLOAD_H2C_SET_TOTAL_LEN(hdr, total_size);
544         FW_OFFLOAD_H2C_SET_SUB_CMD_ID(hdr, info->sub_cmd_id);
545
546         FW_OFFLOAD_H2C_SET_CATEGORY(hdr, 0x01);
547         FW_OFFLOAD_H2C_SET_CMD_ID(hdr, 0xFF);
548
549         PLTFM_MUTEX_LOCK(&adapter->h2c_seq_mutex);
550         FW_OFFLOAD_H2C_SET_SEQ_NUM(hdr, adapter->h2c_info.seq_num);
551         *seq_num = adapter->h2c_info.seq_num;
552         (adapter->h2c_info.seq_num)++;
553         PLTFM_MUTEX_UNLOCK(&adapter->h2c_seq_mutex);
554
555         if (info->ack == 1)
556                 FW_OFFLOAD_H2C_SET_ACK(hdr, 1);
557
558         return HALMAC_RET_SUCCESS;
559 }
560
561 enum halmac_ret_status
562 send_h2c_pkt_88xx(struct halmac_adapter *adapter, u8 *pkt)
563 {
564         u32 cnt = 100;
565         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
566
567         while (adapter->h2c_info.buf_fs <= H2C_PKT_SIZE_88XX) {
568                 get_h2c_buf_free_space_88xx(adapter);
569                 cnt--;
570                 if (cnt == 0) {
571                         PLTFM_MSG_ERR("[ERR]h2c free space!!\n");
572                         return HALMAC_RET_H2C_SPACE_FULL;
573                 }
574         }
575
576         cnt = 100;
577         do {
578                 if (PLTFM_SEND_H2C_PKT(pkt, H2C_PKT_SIZE_88XX) == 1)
579                         break;
580                 cnt--;
581                 if (cnt == 0) {
582                         PLTFM_MSG_ERR("[ERR]pltfm - sned h2c pkt!!\n");
583                         return HALMAC_RET_SEND_H2C_FAIL;
584                 }
585                 PLTFM_DELAY_US(5);
586
587         } while (1);
588
589         adapter->h2c_info.buf_fs -= H2C_PKT_SIZE_88XX;
590
591         return status;
592 }
593
594 enum halmac_ret_status
595 get_h2c_buf_free_space_88xx(struct halmac_adapter *adapter)
596 {
597         u32 hw_wptr;
598         u32 fw_rptr;
599         struct halmac_h2c_info *info = &adapter->h2c_info;
600         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
601
602         hw_wptr = HALMAC_REG_R32(REG_H2C_PKT_WRITEADDR) & 0x3FFFF;
603         fw_rptr = HALMAC_REG_R32(REG_H2C_PKT_READADDR) & 0x3FFFF;
604
605         if (hw_wptr >= fw_rptr)
606                 info->buf_fs = info->buf_size - (hw_wptr - fw_rptr);
607         else
608                 info->buf_fs = fw_rptr - hw_wptr;
609
610         return HALMAC_RET_SUCCESS;
611 }
612
613 /**
614  * get_c2h_info_88xx() - process halmac C2H packet
615  * @adapter : the adapter of halmac
616  * @buf : RX Packet pointer
617  * @size : RX Packet size
618  *
619  * Note : Don't use any IO or DELAY in this API
620  *
621  * Author : KaiYuan Chang/Ivan Lin
622  *
623  * Used to process c2h packet info from RX path. After receiving the packet,
624  * user need to call this api and pass the packet pointer.
625  *
626  * Return : enum halmac_ret_status
627  * More details of status code can be found in prototype document
628  */
629 enum halmac_ret_status
630 get_c2h_info_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
631 {
632         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
633
634         if (GET_RX_DESC_C2H(buf) == 1) {
635                 PLTFM_MSG_TRACE("[TRACE]Parse c2h pkt\n");
636
637                 status = parse_c2h_pkt_88xx(adapter, buf, size);
638                 if (status != HALMAC_RET_SUCCESS) {
639                         PLTFM_MSG_ERR("[ERR]Parse c2h pkt\n");
640                         return status;
641                 }
642         }
643
644         return HALMAC_RET_SUCCESS;
645 }
646
647 static enum halmac_ret_status
648 parse_c2h_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
649 {
650         u8 cmd_id;
651         u8 sub_cmd_id;
652         u8 *c2h_pkt = buf + adapter->hw_cfg_info.rxdesc_size;
653         u32 c2h_size = size - adapter->hw_cfg_info.rxdesc_size;
654         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
655
656         cmd_id = (u8)C2H_HDR_GET_CMD_ID(c2h_pkt);
657
658         if (cmd_id != 0xFF) {
659                 PLTFM_MSG_TRACE("[TRACE]Not 0xFF cmd!!\n");
660                 return HALMAC_RET_C2H_NOT_HANDLED;
661         }
662
663         sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_pkt);
664
665         switch (sub_cmd_id) {
666         case C2H_SUB_CMD_ID_C2H_DBG:
667                 status = get_c2h_dbg_88xx(adapter, c2h_pkt, c2h_size);
668                 break;
669         case C2H_SUB_CMD_ID_H2C_ACK_HDR:
670                 status = get_h2c_ack_88xx(adapter, c2h_pkt, c2h_size);
671                 break;
672         case C2H_SUB_CMD_ID_BT_COEX_INFO:
673                 status = HALMAC_RET_C2H_NOT_HANDLED;
674                 break;
675         case C2H_SUB_CMD_ID_SCAN_STATUS_RPT:
676                 status = get_scan_rpt_88xx(adapter, c2h_pkt, c2h_size);
677                 break;
678         case C2H_SUB_CMD_ID_PSD_DATA:
679                 status = get_psd_data_88xx(adapter, c2h_pkt, c2h_size);
680                 break;
681         case C2H_SUB_CMD_ID_EFUSE_DATA:
682                 status = get_efuse_data_88xx(adapter, c2h_pkt, c2h_size);
683                 break;
684         default:
685                 PLTFM_MSG_WARN("[WARN]Sub cmd id!!\n");
686                 status = HALMAC_RET_C2H_NOT_HANDLED;
687                 break;
688         }
689
690         return status;
691 }
692
693 static enum halmac_ret_status
694 get_c2h_dbg_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
695 {
696         u8 i;
697         u8 next_msg = 0;
698         u8 cur_msg = 0;
699         u8 msg_len = 0;
700         char *c2h_buf = (char *)NULL;
701         u8 content_len = 0;
702         u8 seq_num = 0;
703
704         content_len = (u8)C2H_HDR_GET_LEN((u8 *)buf);
705
706         if (content_len > C2H_DBG_CONTENT_MAX_LENGTH) {
707                 PLTFM_MSG_ERR("[ERR]c2h size > max len!\n");
708                 return HALMAC_RET_C2H_NOT_HANDLED;
709         }
710
711         for (i = 0; i < content_len; i++) {
712                 if (*(buf + C2H_DBG_HDR_LEN + i) == '\n') {
713                         if ((*(buf + C2H_DBG_HDR_LEN + i + 1) == '\0') ||
714                             (*(buf + C2H_DBG_HDR_LEN + i + 1) == 0xff)) {
715                                 next_msg = C2H_DBG_HDR_LEN + i + 1;
716                                 goto _ENDFOUND;
717                         }
718                 }
719         }
720
721 _ENDFOUND:
722         msg_len = next_msg - C2H_DBG_HDR_LEN;
723
724         c2h_buf = (char *)PLTFM_MALLOC(msg_len);
725         if (!c2h_buf)
726                 return HALMAC_RET_MALLOC_FAIL;
727
728         PLTFM_MEMCPY(c2h_buf, buf + C2H_DBG_HDR_LEN, msg_len);
729
730         seq_num = (u8)(*(c2h_buf));
731         *(c2h_buf + msg_len - 1) = '\0';
732         PLTFM_MSG_ALWAYS("[RTKFW, SEQ=%d]: %s\n",
733                          seq_num, (char *)(c2h_buf + 1));
734         PLTFM_FREE(c2h_buf, msg_len);
735
736         while (*(buf + next_msg) != '\0') {
737                 cur_msg = next_msg;
738
739                 msg_len = (u8)(*(buf + cur_msg + 3)) - 1;
740                 next_msg += C2H_DBG_HDR_LEN + msg_len;
741
742                 c2h_buf = (char *)PLTFM_MALLOC(msg_len);
743                 if (!c2h_buf)
744                         return HALMAC_RET_MALLOC_FAIL;
745
746                 PLTFM_MEMCPY(c2h_buf, buf + cur_msg + C2H_DBG_HDR_LEN, msg_len);
747                 *(c2h_buf + msg_len - 1) = '\0';
748                 seq_num = (u8)(*(c2h_buf));
749                 PLTFM_MSG_ALWAYS("[RTKFW, SEQ=%d]: %s\n",
750                                  seq_num, (char *)(c2h_buf + 1));
751                 PLTFM_FREE(c2h_buf, msg_len);
752         }
753
754         return HALMAC_RET_SUCCESS;
755 }
756
757 static enum halmac_ret_status
758 get_h2c_ack_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
759 {
760         u8 cmd_id;
761         u8 sub_cmd_id;
762         u8 fw_rc;
763         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
764
765         PLTFM_MSG_TRACE("[TRACE]Ack for C2H!!\n");
766
767         fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
768         if (HALMAC_H2C_RETURN_SUCCESS != (enum halmac_h2c_return_code)fw_rc)
769                 PLTFM_MSG_TRACE("[TRACE]fw rc = %d\n", fw_rc);
770
771         cmd_id = (u8)H2C_ACK_HDR_GET_H2C_CMD_ID(buf);
772
773         if (cmd_id != 0xFF) {
774                 PLTFM_MSG_ERR("[ERR]h2c ack cmd id!!\n");
775                 return HALMAC_RET_C2H_NOT_HANDLED;
776         }
777
778         sub_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_SUB_CMD_ID(buf);
779
780         switch (sub_cmd_id) {
781         case H2C_SUB_CMD_ID_DUMP_PHYSICAL_EFUSE_ACK:
782                 status = get_h2c_ack_phy_efuse_88xx(adapter, buf, size);
783                 break;
784         case H2C_SUB_CMD_ID_CFG_PARAM_ACK:
785                 status = get_h2c_ack_cfg_param_88xx(adapter, buf, size);
786                 break;
787         case H2C_SUB_CMD_ID_UPDATE_PKT_ACK:
788                 status = get_h2c_ack_update_pkt_88xx(adapter, buf, size);
789                 break;
790         case H2C_SUB_CMD_ID_UPDATE_DATAPACK_ACK:
791                 status = get_h2c_ack_update_datapkt_88xx(adapter, buf, size);
792                 break;
793         case H2C_SUB_CMD_ID_RUN_DATAPACK_ACK:
794                 status = get_h2c_ack_run_datapkt_88xx(adapter, buf, size);
795                 break;
796         case H2C_SUB_CMD_ID_CH_SWITCH_ACK:
797                 status = get_h2c_ack_ch_switch_88xx(adapter, buf, size);
798                 break;
799         case H2C_SUB_CMD_ID_IQK_ACK:
800                 status = get_h2c_ack_iqk_88xx(adapter, buf, size);
801                 break;
802         case H2C_SUB_CMD_ID_PWR_TRK_ACK:
803                 status = get_h2c_ack_pwr_trk_88xx(adapter, buf, size);
804                 break;
805         case H2C_SUB_CMD_ID_PSD_ACK:
806                 break;
807         case H2C_SUB_CMD_ID_FW_SNDING_ACK:
808                 status = get_h2c_ack_fw_snding_88xx(adapter, buf, size);
809                 break;
810         default:
811                 status = HALMAC_RET_C2H_NOT_HANDLED;
812                 break;
813         }
814
815         return status;
816 }
817
818 static enum halmac_ret_status
819 get_scan_rpt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
820 {
821         u8 fw_rc;
822         enum halmac_cmd_process_status proc_status;
823
824         fw_rc = (u8)SCAN_STATUS_RPT_GET_H2C_RETURN_CODE(buf);
825         proc_status = (HALMAC_H2C_RETURN_SUCCESS ==
826                 (enum halmac_h2c_return_code)fw_rc) ?
827                 HALMAC_CMD_PROCESS_DONE : HALMAC_CMD_PROCESS_ERROR;
828
829         PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status, NULL, 0);
830
831         adapter->halmac_state.scan_state.proc_status = proc_status;
832
833         PLTFM_MSG_TRACE("[TRACE]scan : %X\n", proc_status);
834
835         return HALMAC_RET_SUCCESS;
836 }
837
838 static enum halmac_ret_status
839 get_h2c_ack_cfg_param_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
840 {
841         u8 seq_num;
842         u8 fw_rc;
843         u32 offset_accum;
844         u32 value_accum;
845         struct halmac_cfg_param_state *state =
846                 &adapter->halmac_state.cfg_param_state;
847         enum halmac_cmd_process_status proc_status =
848                 HALMAC_CMD_PROCESS_UNDEFINE;
849
850         seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
851         PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
852                         state->seq_num, seq_num);
853         if (seq_num != state->seq_num) {
854                 PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
855                               state->seq_num, seq_num);
856                 return HALMAC_RET_SUCCESS;
857         }
858
859         if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
860                 PLTFM_MSG_ERR("[ERR]not cmd sending\n");
861                 return HALMAC_RET_SUCCESS;
862         }
863
864         fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
865         state->fw_rc = fw_rc;
866         offset_accum = CFG_PARAM_ACK_GET_OFFSET_ACCUMULATION(buf);
867         value_accum = CFG_PARAM_ACK_GET_VALUE_ACCUMULATION(buf);
868
869         if (offset_accum != adapter->cfg_param_info.offset_accum ||
870             value_accum != adapter->cfg_param_info.value_accum) {
871                 PLTFM_MSG_ERR("[ERR][C2H]offset_accu : %x, value_accu : %xn",
872                               offset_accum, value_accum);
873                 PLTFM_MSG_ERR("[ERR][Ada]offset_accu : %x, value_accu : %x\n",
874                               adapter->cfg_param_info.offset_accum,
875                               adapter->cfg_param_info.value_accum);
876                 proc_status = HALMAC_CMD_PROCESS_ERROR;
877         }
878
879         if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS &&
880             proc_status != HALMAC_CMD_PROCESS_ERROR) {
881                 proc_status = HALMAC_CMD_PROCESS_DONE;
882                 state->proc_status = proc_status;
883                 PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, proc_status, NULL, 0);
884         } else {
885                 proc_status = HALMAC_CMD_PROCESS_ERROR;
886                 state->proc_status = proc_status;
887                 PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, proc_status,
888                                 &fw_rc, 1);
889         }
890
891         return HALMAC_RET_SUCCESS;
892 }
893
894 static enum halmac_ret_status
895 get_h2c_ack_update_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
896 {
897         u8 seq_num;
898         u8 fw_rc;
899         struct halmac_update_pkt_state *state =
900                 &adapter->halmac_state.update_pkt_state;
901         enum halmac_cmd_process_status proc_status;
902
903         seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
904         PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
905                         state->seq_num, seq_num);
906         if (seq_num != state->seq_num) {
907                 PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
908                               state->seq_num, seq_num);
909                 return HALMAC_RET_SUCCESS;
910         }
911
912         if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
913                 PLTFM_MSG_ERR("[ERR]not cmd sending\n");
914                 return HALMAC_RET_SUCCESS;
915         }
916
917         fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
918         state->fw_rc = fw_rc;
919
920         if (HALMAC_H2C_RETURN_SUCCESS == (enum halmac_h2c_return_code)fw_rc) {
921                 proc_status = HALMAC_CMD_PROCESS_DONE;
922                 state->proc_status = proc_status;
923                 PLTFM_EVENT_SIG(HALMAC_FEATURE_UPDATE_PACKET, proc_status,
924                                 NULL, 0);
925         } else {
926                 proc_status = HALMAC_CMD_PROCESS_ERROR;
927                 state->proc_status = proc_status;
928                 PLTFM_EVENT_SIG(HALMAC_FEATURE_UPDATE_PACKET, proc_status,
929                                 &state->fw_rc, 1);
930         }
931
932         return HALMAC_RET_SUCCESS;
933 }
934
935 static enum halmac_ret_status
936 get_h2c_ack_update_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf,
937                                 u32 size)
938 {
939         return HALMAC_RET_NOT_SUPPORT;
940 }
941
942 static enum halmac_ret_status
943 get_h2c_ack_run_datapkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
944 {
945         return HALMAC_RET_NOT_SUPPORT;
946 }
947
948 static enum halmac_ret_status
949 get_h2c_ack_ch_switch_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
950 {
951         u8 seq_num;
952         u8 fw_rc;
953         struct halmac_scan_state *state = &adapter->halmac_state.scan_state;
954         enum halmac_cmd_process_status proc_status;
955
956         seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
957         PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
958                         state->seq_num, seq_num);
959         if (seq_num != state->seq_num) {
960                 PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
961                               state->seq_num, seq_num);
962                 return HALMAC_RET_SUCCESS;
963         }
964
965         if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
966                 PLTFM_MSG_ERR("[ERR]not cmd sending\n");
967                 return HALMAC_RET_SUCCESS;
968         }
969
970         fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
971         state->fw_rc = fw_rc;
972
973         if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
974                 proc_status = HALMAC_CMD_PROCESS_RCVD;
975                 state->proc_status = proc_status;
976                 PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status,
977                                 NULL, 0);
978         } else {
979                 proc_status = HALMAC_CMD_PROCESS_ERROR;
980                 state->proc_status = proc_status;
981                 PLTFM_EVENT_SIG(HALMAC_FEATURE_CHANNEL_SWITCH, proc_status,
982                                 &fw_rc, 1);
983         }
984
985         return HALMAC_RET_SUCCESS;
986 }
987
988 /**
989  * mac_debug_88xx_v1() - read some registers for debug
990  * @adapter
991  * Author : KaiYuan Chang/Ivan Lin
992  * Return : enum halmac_ret_status
993  */
994 enum halmac_ret_status
995 mac_debug_88xx(struct halmac_adapter *adapter)
996 {
997         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
998
999         if (adapter->intf == HALMAC_INTERFACE_SDIO)
1000                 dump_reg_sdio_88xx(adapter);
1001         else
1002                 dump_reg_88xx(adapter);
1003
1004         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1005
1006         return HALMAC_RET_SUCCESS;
1007 }
1008
1009 static void
1010 dump_reg_sdio_88xx(struct halmac_adapter *adapter)
1011 {
1012         u8 tmp8;
1013         u32 i;
1014
1015         /* Dump CCCR, it needs new platform api */
1016
1017         /*Dump SDIO Local Register, use CMD52*/
1018         for (i = 0x10250000; i < 0x102500ff; i++) {
1019                 tmp8 = PLTFM_SDIO_CMD52_R(i);
1020                 PLTFM_MSG_TRACE("[TRACE]dbg-sdio[%x]=%x\n", i, tmp8);
1021         }
1022
1023         /*Dump MAC Register*/
1024         for (i = 0x0000; i < 0x17ff; i++) {
1025                 tmp8 = PLTFM_SDIO_CMD52_R(i);
1026                 PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
1027         }
1028
1029         tmp8 = PLTFM_SDIO_CMD52_R(REG_SDIO_CRC_ERR_IDX);
1030         if (tmp8)
1031                 PLTFM_MSG_ERR("[ERR]sdio crc=%x\n", tmp8);
1032
1033         /*Check RX Fifo status*/
1034         i = REG_RXFF_PTR_V1;
1035         tmp8 = PLTFM_SDIO_CMD52_R(i);
1036         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
1037         i = REG_RXFF_WTR_V1;
1038         tmp8 = PLTFM_SDIO_CMD52_R(i);
1039         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
1040         i = REG_RXFF_PTR_V1;
1041         tmp8 = PLTFM_SDIO_CMD52_R(i);
1042         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
1043         i = REG_RXFF_WTR_V1;
1044         tmp8 = PLTFM_SDIO_CMD52_R(i);
1045         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp8);
1046 }
1047
1048 static void
1049 dump_reg_88xx(struct halmac_adapter *adapter)
1050 {
1051         u32 tmp32;
1052         u32 i;
1053         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
1054
1055         /*Dump MAC Register*/
1056         for (i = 0x0000; i < 0x17fc; i += 4) {
1057                 tmp32 = HALMAC_REG_R32(i);
1058                 PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
1059         }
1060
1061         /*Check RX Fifo status*/
1062         i = REG_RXFF_PTR_V1;
1063         tmp32 = HALMAC_REG_R32(i);
1064         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
1065         i = REG_RXFF_WTR_V1;
1066         tmp32 = HALMAC_REG_R32(i);
1067         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
1068         i = REG_RXFF_PTR_V1;
1069         tmp32 = HALMAC_REG_R32(i);
1070         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
1071         i = REG_RXFF_WTR_V1;
1072         tmp32 = HALMAC_REG_R32(i);
1073         PLTFM_MSG_TRACE("[TRACE]dbg-mac[%x]=%x\n", i, tmp32);
1074 }
1075
1076 /**
1077  * cfg_parameter_88xx() - config parameter by FW
1078  * @adapter : the adapter of halmac
1079  * @info : cmd id, content
1080  * @full_fifo : parameter information
1081  *
1082  * If msk_en = 1, the format of array is {reg_info, mask, value}.
1083  * If msk_en =_FAUSE, the format of array is {reg_info, value}
1084  * The format of reg_info is
1085  * reg_info[31]=rf_reg, 0: MAC_BB reg, 1: RF reg
1086  * reg_info[27:24]=rf_path, 0: path_A, 1: path_B
1087  * if rf_reg=0(MAC_BB reg), rf_path is meaningless.
1088  * ref_info[15:0]=offset
1089  *
1090  * Example: msk_en = 0
1091  * {0x8100000a, 0x00001122}
1092  * =>Set RF register, path_B, offset 0xA to 0x00001122
1093  * {0x00000824, 0x11224433}
1094  * =>Set MAC_BB register, offset 0x800 to 0x11224433
1095  *
1096  * Note : full fifo mode only for init flow
1097  *
1098  * Author : KaiYuan Chang/Ivan Lin
1099  * Return : enum halmac_ret_status
1100  * More details of status code can be found in prototype document
1101  */
1102 enum halmac_ret_status
1103 cfg_parameter_88xx(struct halmac_adapter *adapter,
1104                    struct halmac_phy_parameter_info *info, u8 full_fifo)
1105 {
1106         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1107         enum halmac_cmd_process_status *proc_status;
1108         enum halmac_cmd_construct_state cmd_state;
1109
1110         proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
1111
1112         if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
1113                 return HALMAC_RET_NO_DLFW;
1114
1115         if (adapter->fw_ver.h2c_version < 4)
1116                 return HALMAC_RET_FW_NO_SUPPORT;
1117
1118         if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
1119                 PLTFM_MSG_TRACE("[TRACE]Wait event(para)\n");
1120                 return HALMAC_RET_BUSY_STATE;
1121         }
1122
1123         cmd_state = cfg_param_cmd_cnstr_state_88xx(adapter);
1124         if (cmd_state != HALMAC_CMD_CNSTR_IDLE &&
1125             cmd_state != HALMAC_CMD_CNSTR_CNSTR) {
1126                 PLTFM_MSG_TRACE("[TRACE]Not idle(para)\n");
1127                 return HALMAC_RET_BUSY_STATE;
1128         }
1129
1130         *proc_status = HALMAC_CMD_PROCESS_IDLE;
1131
1132         status = proc_cfg_param_88xx(adapter, info, full_fifo);
1133
1134         if (status != HALMAC_RET_SUCCESS && status != HALMAC_RET_PARA_SENDING) {
1135                 PLTFM_MSG_ERR("[ERR]send param h2c\n");
1136                 return status;
1137         }
1138
1139         return status;
1140 }
1141
1142 static enum halmac_cmd_construct_state
1143 cfg_param_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
1144 {
1145         return adapter->halmac_state.cfg_param_state.cmd_cnstr_state;
1146 }
1147
1148 static enum halmac_ret_status
1149 proc_cfg_param_88xx(struct halmac_adapter *adapter,
1150                     struct halmac_phy_parameter_info *param, u8 full_fifo)
1151 {
1152         u8 end_cmd = 0;
1153         u32 rsvd_size;
1154         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1155         struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
1156         enum halmac_cmd_process_status *proc_status;
1157
1158         proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
1159
1160         status = malloc_cfg_param_buf_88xx(adapter, full_fifo);
1161         if (status != HALMAC_RET_SUCCESS)
1162                 return status;
1163
1164         if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
1165             HALMAC_RET_SUCCESS) {
1166                 PLTFM_FREE(info->buf, info->buf_size);
1167                 info->buf = NULL;
1168                 info->buf_wptr = NULL;
1169                 return HALMAC_RET_ERROR_STATE;
1170         }
1171
1172         add_param_buf_88xx(adapter, param, info->buf_wptr, &end_cmd);
1173         if (param->cmd_id != HALMAC_PARAMETER_CMD_END) {
1174                 info->num++;
1175                 info->buf_wptr += CFG_PARAM_H2C_INFO_SIZE;
1176                 info->avl_buf_size -= CFG_PARAM_H2C_INFO_SIZE;
1177         }
1178
1179         rsvd_size = info->avl_buf_size - adapter->hw_cfg_info.txdesc_size;
1180         if (rsvd_size > CFG_PARAM_H2C_INFO_SIZE && end_cmd == 0)
1181                 return HALMAC_RET_SUCCESS;
1182
1183         if (info->num == 0) {
1184                 PLTFM_FREE(info->buf, info->buf_size);
1185                 info->buf = NULL;
1186                 info->buf_wptr = NULL;
1187                 PLTFM_MSG_TRACE("[TRACE]param num = 0!!\n");
1188
1189                 *proc_status = HALMAC_CMD_PROCESS_DONE;
1190                 PLTFM_EVENT_SIG(HALMAC_FEATURE_CFG_PARA, *proc_status, NULL, 0);
1191
1192                 reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CFG_PARA);
1193
1194                 return HALMAC_RET_SUCCESS;
1195         }
1196
1197         status = send_cfg_param_h2c_88xx(adapter);
1198         if (status != HALMAC_RET_SUCCESS) {
1199                 if (info->buf) {
1200                         PLTFM_FREE(info->buf, info->buf_size);
1201                         info->buf = NULL;
1202                         info->buf_wptr = NULL;
1203                 }
1204                 return status;
1205         }
1206
1207         if (end_cmd == 0) {
1208                 PLTFM_MSG_TRACE("[TRACE]send h2c-buf full\n");
1209                 return HALMAC_RET_PARA_SENDING;
1210         }
1211
1212         return status;
1213 }
1214
1215 static enum halmac_ret_status
1216 send_cfg_param_h2c_88xx(struct halmac_adapter *adapter)
1217 {
1218         u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
1219         u16 pg_addr;
1220         u16 seq_num = 0;
1221         u32 info_size;
1222         struct halmac_h2c_header_info hdr_info;
1223         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1224         struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
1225         enum halmac_cmd_process_status *proc_status;
1226
1227         proc_status = &adapter->halmac_state.cfg_param_state.proc_status;
1228
1229         if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_H2C_SENT) !=
1230             HALMAC_RET_SUCCESS)
1231                 return HALMAC_RET_ERROR_STATE;
1232
1233         *proc_status = HALMAC_CMD_PROCESS_SENDING;
1234
1235         if (info->full_fifo_mode == 1)
1236                 pg_addr = 0;
1237         else
1238                 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
1239
1240         info_size = info->num * CFG_PARAM_H2C_INFO_SIZE;
1241
1242         status = dl_rsvd_page_88xx(adapter, pg_addr, info->buf, info_size);
1243         if (status != HALMAC_RET_SUCCESS) {
1244                 PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
1245                 goto CFG_PARAM_H2C_FAIL;
1246         }
1247
1248         gen_cfg_param_h2c_88xx(adapter, h2c_buf);
1249
1250         hdr_info.sub_cmd_id = SUB_CMD_ID_CFG_PARAM;
1251         hdr_info.content_size = 4;
1252         hdr_info.ack = 1;
1253         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
1254
1255         adapter->halmac_state.cfg_param_state.seq_num = seq_num;
1256
1257         status = send_h2c_pkt_88xx(adapter, h2c_buf);
1258
1259         if (status != HALMAC_RET_SUCCESS) {
1260                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
1261                 reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CFG_PARA);
1262         }
1263
1264 CFG_PARAM_H2C_FAIL:
1265         PLTFM_FREE(info->buf, info->buf_size);
1266         info->buf = NULL;
1267         info->buf_wptr = NULL;
1268
1269         if (cnv_cfg_param_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
1270             HALMAC_RET_SUCCESS)
1271                 return HALMAC_RET_ERROR_STATE;
1272
1273         return status;
1274 }
1275
1276 static enum halmac_ret_status
1277 cnv_cfg_param_state_88xx(struct halmac_adapter *adapter,
1278                          enum halmac_cmd_construct_state dest_state)
1279 {
1280         enum halmac_cmd_construct_state *state;
1281
1282         state = &adapter->halmac_state.cfg_param_state.cmd_cnstr_state;
1283
1284         if ((*state != HALMAC_CMD_CNSTR_IDLE) &&
1285             (*state != HALMAC_CMD_CNSTR_CNSTR) &&
1286             (*state != HALMAC_CMD_CNSTR_H2C_SENT))
1287                 return HALMAC_RET_ERROR_STATE;
1288
1289         if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
1290                 if (*state == HALMAC_CMD_CNSTR_CNSTR)
1291                         return HALMAC_RET_ERROR_STATE;
1292         } else if (dest_state == HALMAC_CMD_CNSTR_CNSTR) {
1293                 if (*state == HALMAC_CMD_CNSTR_H2C_SENT)
1294                         return HALMAC_RET_ERROR_STATE;
1295         } else if (dest_state == HALMAC_CMD_CNSTR_H2C_SENT) {
1296                 if ((*state == HALMAC_CMD_CNSTR_IDLE) ||
1297                     (*state == HALMAC_CMD_CNSTR_H2C_SENT))
1298                         return HALMAC_RET_ERROR_STATE;
1299         }
1300
1301         *state = dest_state;
1302
1303         return HALMAC_RET_SUCCESS;
1304 }
1305
1306 static enum halmac_ret_status
1307 add_param_buf_88xx(struct halmac_adapter *adapter,
1308                    struct halmac_phy_parameter_info *param, u8 *buf,
1309                    u8 *end_cmd)
1310 {
1311         struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
1312         union halmac_parameter_content *content = &param->content;
1313
1314         *end_cmd = 0;
1315
1316         PARAM_INFO_SET_LEN(buf, CFG_PARAM_H2C_INFO_SIZE);
1317         PARAM_INFO_SET_IO_CMD(buf, param->cmd_id);
1318
1319         switch (param->cmd_id) {
1320         case HALMAC_PARAMETER_CMD_BB_W8:
1321         case HALMAC_PARAMETER_CMD_BB_W16:
1322         case HALMAC_PARAMETER_CMD_BB_W32:
1323         case HALMAC_PARAMETER_CMD_MAC_W8:
1324         case HALMAC_PARAMETER_CMD_MAC_W16:
1325         case HALMAC_PARAMETER_CMD_MAC_W32:
1326                 PARAM_INFO_SET_IO_ADDR(buf, content->MAC_REG_W.offset);
1327                 PARAM_INFO_SET_DATA(buf, content->MAC_REG_W.value);
1328                 PARAM_INFO_SET_MASK(buf, content->MAC_REG_W.msk);
1329                 PARAM_INFO_SET_MSK_EN(buf, content->MAC_REG_W.msk_en);
1330                 info->value_accum += content->MAC_REG_W.value;
1331                 info->offset_accum += content->MAC_REG_W.offset;
1332                 break;
1333         case HALMAC_PARAMETER_CMD_RF_W:
1334                 /*In rf register, the address is only 1 byte*/
1335                 PARAM_INFO_SET_RF_ADDR(buf, content->RF_REG_W.offset);
1336                 PARAM_INFO_SET_RF_PATH(buf, content->RF_REG_W.rf_path);
1337                 PARAM_INFO_SET_DATA(buf, content->RF_REG_W.value);
1338                 PARAM_INFO_SET_MASK(buf, content->RF_REG_W.msk);
1339                 PARAM_INFO_SET_MSK_EN(buf, content->RF_REG_W.msk_en);
1340                 info->value_accum += content->RF_REG_W.value;
1341                 info->offset_accum += (content->RF_REG_W.offset +
1342                                         (content->RF_REG_W.rf_path << 8));
1343                 break;
1344         case HALMAC_PARAMETER_CMD_DELAY_US:
1345         case HALMAC_PARAMETER_CMD_DELAY_MS:
1346                 PARAM_INFO_SET_DELAY_VAL(buf, content->DELAY_TIME.delay_time);
1347                 break;
1348         case HALMAC_PARAMETER_CMD_END:
1349                 *end_cmd = 1;
1350                 break;
1351         default:
1352                 PLTFM_MSG_ERR("[ERR]cmd id!!\n");
1353                 break;
1354         }
1355
1356         return HALMAC_RET_SUCCESS;
1357 }
1358
1359 static enum halmac_ret_status
1360 gen_cfg_param_h2c_88xx(struct halmac_adapter *adapter, u8 *buff)
1361 {
1362         struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
1363         u16 h2c_info_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
1364         u16 rsvd_pg_addr = adapter->txff_alloc.rsvd_boundary;
1365
1366         CFG_PARAM_SET_NUM(buff, info->num);
1367
1368         if (info->full_fifo_mode == 1) {
1369                 CFG_PARAM_SET_INIT_CASE(buff, 0x1);
1370                 CFG_PARAM_SET_LOC(buff, 0);
1371         } else {
1372                 CFG_PARAM_SET_INIT_CASE(buff, 0x0);
1373                 CFG_PARAM_SET_LOC(buff, h2c_info_addr - rsvd_pg_addr);
1374         }
1375
1376         return HALMAC_RET_SUCCESS;
1377 }
1378
1379 static enum halmac_ret_status
1380 malloc_cfg_param_buf_88xx(struct halmac_adapter *adapter, u8 full_fifo)
1381 {
1382         struct halmac_cfg_param_info *info = &adapter->cfg_param_info;
1383         struct halmac_pltfm_cfg_info *pltfm_info = &adapter->pltfm_info;
1384
1385         if (info->buf)
1386                 return HALMAC_RET_SUCCESS;
1387
1388         if (full_fifo == 1)
1389                 info->buf_size = pltfm_info->malloc_size;
1390         else
1391                 info->buf_size = CFG_PARAM_RSVDPG_SIZE;
1392
1393         if (info->buf_size > pltfm_info->rsvd_pg_size)
1394                 info->buf_size = pltfm_info->rsvd_pg_size;
1395
1396         info->buf = smart_malloc_88xx(adapter, info->buf_size, &info->buf_size);
1397         if (info->buf) {
1398                 PLTFM_MEMSET(info->buf, 0x00, info->buf_size);
1399                 info->full_fifo_mode = full_fifo;
1400                 info->buf_wptr = info->buf;
1401                 info->num = 0;
1402                 info->avl_buf_size = info->buf_size;
1403                 info->value_accum = 0;
1404                 info->offset_accum = 0;
1405         } else {
1406                 return HALMAC_RET_MALLOC_FAIL;
1407         }
1408
1409         return HALMAC_RET_SUCCESS;
1410 }
1411
1412 /**
1413  * update_packet_88xx() - send specific packet to FW
1414  * @adapter : the adapter of halmac
1415  * @pkt_id : packet id, to know the purpose of this packet
1416  * @pkt : packet
1417  * @size : packet size
1418  *
1419  * Note : TX_DESC is not included in the pkt
1420  *
1421  * Author : KaiYuan Chang/Ivan Lin
1422  * Return : enum halmac_ret_status
1423  * More details of status code can be found in prototype document
1424  */
1425 enum halmac_ret_status
1426 update_packet_88xx(struct halmac_adapter *adapter, enum halmac_packet_id pkt_id,
1427                    u8 *pkt, u32 size)
1428 {
1429         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1430         enum halmac_cmd_process_status *proc_status =
1431                 &adapter->halmac_state.update_pkt_state.proc_status;
1432
1433         if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
1434                 return HALMAC_RET_NO_DLFW;
1435
1436         if (adapter->fw_ver.h2c_version < 4)
1437                 return HALMAC_RET_FW_NO_SUPPORT;
1438
1439         if (size > UPDATE_PKT_RSVDPG_SIZE)
1440                 return HALMAC_RET_RSVD_PG_OVERFLOW_FAIL;
1441
1442         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1443
1444         if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
1445                 PLTFM_MSG_TRACE("[TRACE]Wait event(upd)\n");
1446                 return HALMAC_RET_BUSY_STATE;
1447         }
1448
1449         *proc_status = HALMAC_CMD_PROCESS_SENDING;
1450
1451         status = send_h2c_update_packet_88xx(adapter, pkt_id, pkt, size);
1452         if (status != HALMAC_RET_SUCCESS) {
1453                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
1454                 PLTFM_MSG_ERR("[ERR]pkt id : %X!!\n", pkt_id);
1455                 return status;
1456         }
1457
1458         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1459
1460         return HALMAC_RET_SUCCESS;
1461 }
1462
1463 static enum halmac_ret_status
1464 send_h2c_update_packet_88xx(struct halmac_adapter *adapter,
1465                             enum halmac_packet_id pkt_id, u8 *pkt, u32 size)
1466 {
1467         u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
1468         u16 seq_num = 0;
1469         u16 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
1470         u16 pg_offset;
1471         struct halmac_h2c_header_info hdr_info;
1472         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1473
1474         status = dl_rsvd_page_88xx(adapter, pg_addr, pkt, size);
1475         if (status != HALMAC_RET_SUCCESS) {
1476                 PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
1477                 return status;
1478         }
1479
1480         pg_offset = pg_addr - adapter->txff_alloc.rsvd_boundary;
1481         UPDATE_PKT_SET_SIZE(h2c_buf, size + adapter->hw_cfg_info.txdesc_size);
1482         UPDATE_PKT_SET_ID(h2c_buf, pkt_id);
1483         UPDATE_PKT_SET_LOC(h2c_buf, pg_offset);
1484
1485         hdr_info.sub_cmd_id = SUB_CMD_ID_UPDATE_PKT;
1486         hdr_info.content_size = 8;
1487         hdr_info.ack = 1;
1488         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
1489         adapter->halmac_state.update_pkt_state.seq_num = seq_num;
1490
1491         status = send_h2c_pkt_88xx(adapter, h2c_buf);
1492
1493         if (status != HALMAC_RET_SUCCESS) {
1494                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
1495                 reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_UPDATE_PACKET);
1496                 return status;
1497         }
1498
1499         return status;
1500 }
1501
1502 enum halmac_ret_status
1503 bcn_ie_filter_88xx(struct halmac_adapter *adapter,
1504                    struct halmac_bcn_ie_info *info)
1505 {
1506         return HALMAC_RET_NOT_SUPPORT;
1507 }
1508
1509 enum halmac_ret_status
1510 update_datapack_88xx(struct halmac_adapter *adapter,
1511                      enum halmac_data_type data_type,
1512                      struct halmac_phy_parameter_info *info)
1513 {
1514         return HALMAC_RET_NOT_SUPPORT;
1515 }
1516
1517 enum halmac_ret_status
1518 run_datapack_88xx(struct halmac_adapter *adapter,
1519                   enum halmac_data_type data_type)
1520 {
1521         return HALMAC_RET_NOT_SUPPORT;
1522 }
1523
1524 enum halmac_ret_status
1525 send_bt_coex_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size, u8 ack)
1526 {
1527         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1528
1529         if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
1530                 return HALMAC_RET_NO_DLFW;
1531
1532         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1533
1534         status = send_bt_coex_cmd_88xx(adapter, buf, size, ack);
1535
1536         if (status != HALMAC_RET_SUCCESS) {
1537                 PLTFM_MSG_ERR("[ERR]bt coex cmd!!\n");
1538                 return status;
1539         }
1540
1541         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1542
1543         return HALMAC_RET_SUCCESS;
1544 }
1545
1546 static enum halmac_ret_status
1547 send_bt_coex_cmd_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
1548                       u8 ack)
1549 {
1550         u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
1551         u16 seq_num = 0;
1552         struct halmac_h2c_header_info hdr_info;
1553         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1554
1555         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1556
1557         PLTFM_MEMCPY(h2c_buf + 8, buf, size);
1558
1559         hdr_info.sub_cmd_id = SUB_CMD_ID_BT_COEX;
1560         hdr_info.content_size = (u16)size;
1561         hdr_info.ack = ack;
1562         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
1563
1564         status = send_h2c_pkt_88xx(adapter, h2c_buf);
1565
1566         if (status != HALMAC_RET_SUCCESS) {
1567                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
1568                 return status;
1569         }
1570
1571         return HALMAC_RET_SUCCESS;
1572 }
1573
1574 /**
1575  * dump_fifo_88xx() - dump fifo data
1576  * @adapter : the adapter of halmac
1577  * @sel : FIFO selection
1578  * @start_addr : start address of selected FIFO
1579  * @size : dump size of selected FIFO
1580  * @data : FIFO data
1581  *
1582  * Note : before dump fifo, user need to call halmac_get_fifo_size to
1583  * get fifo size. Then input this size to halmac_dump_fifo.
1584  *
1585  * Author : Ivan Lin/KaiYuan Chang
1586  * Return : enum halmac_ret_status
1587  * More details of status code can be found in prototype document
1588  */
1589 enum halmac_ret_status
1590 dump_fifo_88xx(struct halmac_adapter *adapter, enum hal_fifo_sel sel,
1591                u32 start_addr, u32 size, u8 *data)
1592 {
1593         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1594         u8 tmp8;
1595         u8 enable;
1596         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
1597
1598         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1599
1600         if (sel == HAL_FIFO_SEL_TX &&
1601             (start_addr + size) > adapter->hw_cfg_info.tx_fifo_size) {
1602                 PLTFM_MSG_ERR("[ERR]size overflow!!\n");
1603                 return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
1604         }
1605
1606         if (sel == HAL_FIFO_SEL_RX &&
1607             (start_addr + size) > adapter->hw_cfg_info.rx_fifo_size) {
1608                 PLTFM_MSG_ERR("[ERR]size overflow!!\n");
1609                 return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
1610         }
1611
1612         if ((size & (4 - 1)) != 0) {
1613                 PLTFM_MSG_ERR("[ERR]not 4byte alignment!!\n");
1614                 return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT;
1615         }
1616
1617         if (!data)
1618                 return HALMAC_RET_NULL_POINTER;
1619
1620         tmp8 = HALMAC_REG_R8(REG_RCR + 2);
1621         enable = 0;
1622         status = api->halmac_set_hw_value(adapter, HALMAC_HW_RX_CLK_GATE,
1623                                           &enable);
1624         if (status != HALMAC_RET_SUCCESS)
1625                 return status;
1626         status = read_buf_88xx(adapter, start_addr, size, sel, data);
1627
1628         HALMAC_REG_W8(REG_RCR + 2, tmp8);
1629
1630         if (status != HALMAC_RET_SUCCESS) {
1631                 PLTFM_MSG_ERR("[ERR]read buf!!\n");
1632                 return status;
1633         }
1634
1635         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1636
1637         return HALMAC_RET_SUCCESS;
1638 }
1639
1640 static enum halmac_ret_status
1641 read_buf_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
1642               enum hal_fifo_sel sel, u8 *data)
1643 {
1644         u32 start_pg;
1645         u32 value32;
1646         u32 i;
1647         u32 residue;
1648         u32 cnt = 0;
1649         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
1650
1651         if (sel == HAL_FIFO_SEL_RSVD_PAGE)
1652                 offset += (adapter->txff_alloc.rsvd_boundary <<
1653                            TX_PAGE_SIZE_SHIFT_88XX);
1654
1655         start_pg = offset >> 12;
1656         residue = offset & (4096 - 1);
1657
1658         if (sel == HAL_FIFO_SEL_TX || sel == HAL_FIFO_SEL_RSVD_PAGE)
1659                 start_pg += 0x780;
1660         else if (sel == HAL_FIFO_SEL_RX)
1661                 start_pg += 0x700;
1662         else if (sel == HAL_FIFO_SEL_REPORT)
1663                 start_pg += 0x660;
1664         else if (sel == HAL_FIFO_SEL_LLT)
1665                 start_pg += 0x650;
1666         else if (sel == HAL_FIFO_SEL_RXBUF_FW)
1667                 start_pg += 0x680;
1668         else
1669                 return HALMAC_RET_NOT_SUPPORT;
1670
1671         value32 = HALMAC_REG_R16(REG_PKTBUF_DBG_CTRL) & 0xF000;
1672
1673         do {
1674                 HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)(start_pg | value32));
1675
1676                 for (i = 0x8000 + residue; i <= 0x8FFF; i += 4) {
1677                         *(u32 *)(data + cnt) = HALMAC_REG_R32(i);
1678                         *(u32 *)(data + cnt) =
1679                                 rtk_le32_to_cpu(*(u32 *)(data + cnt));
1680                         cnt += 4;
1681                         if (size == cnt)
1682                                 goto HALMAC_BUF_READ_OK;
1683                 }
1684
1685                 residue = 0;
1686                 start_pg++;
1687         } while (1);
1688
1689 HALMAC_BUF_READ_OK:
1690         HALMAC_REG_W16(REG_PKTBUF_DBG_CTRL, (u16)value32);
1691
1692         return HALMAC_RET_SUCCESS;
1693 }
1694
1695 /**
1696  * get_fifo_size_88xx() - get fifo size
1697  * @adapter : the adapter of halmac
1698  * @sel : FIFO selection
1699  * Author : Ivan Lin/KaiYuan Chang
1700  * Return : u32
1701  * More details of status code can be found in prototype document
1702  */
1703 u32
1704 get_fifo_size_88xx(struct halmac_adapter *adapter, enum hal_fifo_sel sel)
1705 {
1706         u32 size = 0;
1707
1708         if (sel == HAL_FIFO_SEL_TX)
1709                 size = adapter->hw_cfg_info.tx_fifo_size;
1710         else if (sel == HAL_FIFO_SEL_RX)
1711                 size = adapter->hw_cfg_info.rx_fifo_size;
1712         else if (sel == HAL_FIFO_SEL_RSVD_PAGE)
1713                 size = adapter->hw_cfg_info.tx_fifo_size -
1714                        (adapter->txff_alloc.rsvd_boundary <<
1715                         TX_PAGE_SIZE_SHIFT_88XX);
1716         else if (sel == HAL_FIFO_SEL_REPORT)
1717                 size = 65536;
1718         else if (sel == HAL_FIFO_SEL_LLT)
1719                 size = 65536;
1720         else if (sel == HAL_FIFO_SEL_RXBUF_FW)
1721                 size = RX_BUF_FW_88XX;
1722
1723         return size;
1724 }
1725
1726 enum halmac_ret_status
1727 set_h2c_header_88xx(struct halmac_adapter *adapter, u8 *hdr, u16 *seq, u8 ack)
1728 {
1729         PLTFM_MSG_TRACE("[TRACE]%s!!\n", __func__);
1730
1731         H2C_CMD_HEADER_SET_CATEGORY(hdr, 0x00);
1732         H2C_CMD_HEADER_SET_TOTAL_LEN(hdr, 16);
1733
1734         PLTFM_MUTEX_LOCK(&adapter->h2c_seq_mutex);
1735         H2C_CMD_HEADER_SET_SEQ_NUM(hdr, adapter->h2c_info.seq_num);
1736         *seq = adapter->h2c_info.seq_num;
1737         (adapter->h2c_info.seq_num)++;
1738         PLTFM_MUTEX_UNLOCK(&adapter->h2c_seq_mutex);
1739
1740         if (ack == 1)
1741                 H2C_CMD_HEADER_SET_ACK(hdr, 1);
1742
1743         return HALMAC_RET_SUCCESS;
1744 }
1745
1746 /**
1747  * add_ch_info_88xx() -add channel information
1748  * @adapter : the adapter of halmac
1749  * @info : channel information
1750  * Author : KaiYuan Chang/Ivan Lin
1751  * Return : enum halmac_ret_status
1752  * More details of status code can be found in prototype document
1753  */
1754 enum halmac_ret_status
1755 add_ch_info_88xx(struct halmac_adapter *adapter, struct halmac_ch_info *info)
1756 {
1757         struct halmac_ch_sw_info *ch_sw_info = &adapter->ch_sw_info;
1758         enum halmac_cmd_construct_state state;
1759
1760         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1761
1762         if (adapter->halmac_state.dlfw_state != HALMAC_GEN_INFO_SENT) {
1763                 PLTFM_MSG_ERR("[ERR]gen info\n");
1764                 return HALMAC_RET_GEN_INFO_NOT_SENT;
1765         }
1766
1767         state = scan_cmd_cnstr_state_88xx(adapter);
1768         if (state != HALMAC_CMD_CNSTR_BUF_CLR &&
1769             state != HALMAC_CMD_CNSTR_CNSTR) {
1770                 PLTFM_MSG_WARN("[WARN]cmd state (scan)\n");
1771                 return HALMAC_RET_ERROR_STATE;
1772         }
1773
1774         if (!ch_sw_info->buf) {
1775                 ch_sw_info->buf = (u8 *)PLTFM_MALLOC(SCAN_INFO_RSVDPG_SIZE);
1776                 if (!ch_sw_info->buf)
1777                         return HALMAC_RET_NULL_POINTER;
1778                 ch_sw_info->buf_wptr = ch_sw_info->buf;
1779                 ch_sw_info->buf_size = SCAN_INFO_RSVDPG_SIZE;
1780                 ch_sw_info->avl_buf_size = SCAN_INFO_RSVDPG_SIZE;
1781                 ch_sw_info->total_size = 0;
1782                 ch_sw_info->extra_info_en = 0;
1783                 ch_sw_info->ch_num = 0;
1784         }
1785
1786         if (ch_sw_info->extra_info_en == 1) {
1787                 PLTFM_MSG_ERR("[ERR]extra info = 1!!\n");
1788                 return HALMAC_RET_CH_SW_SEQ_WRONG;
1789         }
1790
1791         if (ch_sw_info->avl_buf_size < 4) {
1792                 PLTFM_MSG_ERR("[ERR]buf full!!\n");
1793                 return HALMAC_RET_CH_SW_NO_BUF;
1794         }
1795
1796         if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
1797             HALMAC_RET_SUCCESS)
1798                 return HALMAC_RET_ERROR_STATE;
1799
1800         CH_INFO_SET_CH(ch_sw_info->buf_wptr, info->channel);
1801         CH_INFO_SET_PRI_CH_IDX(ch_sw_info->buf_wptr, info->pri_ch_idx);
1802         CH_INFO_SET_BW(ch_sw_info->buf_wptr, info->bw);
1803         CH_INFO_SET_TIMEOUT(ch_sw_info->buf_wptr, info->timeout);
1804         CH_INFO_SET_ACTION_ID(ch_sw_info->buf_wptr, info->action_id);
1805         CH_INFO_SET_EXTRA_INFO(ch_sw_info->buf_wptr, info->extra_info);
1806
1807         ch_sw_info->avl_buf_size = ch_sw_info->avl_buf_size - 4;
1808         ch_sw_info->total_size = ch_sw_info->total_size + 4;
1809         ch_sw_info->ch_num++;
1810         ch_sw_info->extra_info_en = info->extra_info;
1811         ch_sw_info->buf_wptr = ch_sw_info->buf_wptr + 4;
1812
1813         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1814
1815         return HALMAC_RET_SUCCESS;
1816 }
1817
1818 static enum halmac_cmd_construct_state
1819 scan_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
1820 {
1821         return adapter->halmac_state.scan_state.cmd_cnstr_state;
1822 }
1823
1824 static enum halmac_ret_status
1825 cnv_scan_state_88xx(struct halmac_adapter *adapter,
1826                     enum halmac_cmd_construct_state dest_state)
1827 {
1828         enum halmac_cmd_construct_state *state;
1829
1830         state = &adapter->halmac_state.scan_state.cmd_cnstr_state;
1831
1832         if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
1833                 if ((*state == HALMAC_CMD_CNSTR_BUF_CLR) ||
1834                     (*state == HALMAC_CMD_CNSTR_CNSTR))
1835                         return HALMAC_RET_ERROR_STATE;
1836         } else if (dest_state == HALMAC_CMD_CNSTR_BUF_CLR) {
1837                 if (*state == HALMAC_CMD_CNSTR_H2C_SENT)
1838                         return HALMAC_RET_ERROR_STATE;
1839         } else if (dest_state == HALMAC_CMD_CNSTR_CNSTR) {
1840                 if ((*state == HALMAC_CMD_CNSTR_IDLE) ||
1841                     (*state == HALMAC_CMD_CNSTR_H2C_SENT))
1842                         return HALMAC_RET_ERROR_STATE;
1843         } else if (dest_state == HALMAC_CMD_CNSTR_H2C_SENT) {
1844                 if ((*state != HALMAC_CMD_CNSTR_CNSTR) &&
1845                     (*state != HALMAC_CMD_CNSTR_BUF_CLR))
1846                         return HALMAC_RET_ERROR_STATE;
1847         }
1848
1849         *state = dest_state;
1850
1851         return HALMAC_RET_SUCCESS;
1852 }
1853
1854 /**
1855  * add_extra_ch_info_88xx() -add extra channel information
1856  * @adapter : the adapter of halmac
1857  * @info : extra channel information
1858  * Author : KaiYuan Chang/Ivan Lin
1859  * Return : enum halmac_ret_status
1860  * More details of status code can be found in prototype document
1861  */
1862 enum halmac_ret_status
1863 add_extra_ch_info_88xx(struct halmac_adapter *adapter,
1864                        struct halmac_ch_extra_info *info)
1865 {
1866         struct halmac_ch_sw_info *ch_sw_info = &adapter->ch_sw_info;
1867
1868         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1869
1870         if (!ch_sw_info->buf) {
1871                 PLTFM_MSG_ERR("[ERR]buf = null!!\n");
1872                 return HALMAC_RET_CH_SW_SEQ_WRONG;
1873         }
1874
1875         if (ch_sw_info->extra_info_en == 0) {
1876                 PLTFM_MSG_ERR("[ERR]extra info = 0!!\n");
1877                 return HALMAC_RET_CH_SW_SEQ_WRONG;
1878         }
1879
1880         if (ch_sw_info->avl_buf_size < (u32)(info->extra_info_size + 2)) {
1881                 PLTFM_MSG_ERR("[ERR]no available buffer!!\n");
1882                 return HALMAC_RET_CH_SW_NO_BUF;
1883         }
1884
1885         if (scan_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_CNSTR) {
1886                 PLTFM_MSG_WARN("[WARN]cmd state (ex scan)\n");
1887                 return HALMAC_RET_ERROR_STATE;
1888         }
1889
1890         if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_CNSTR) !=
1891             HALMAC_RET_SUCCESS)
1892                 return HALMAC_RET_ERROR_STATE;
1893
1894         CH_EXTRA_INFO_SET_ID(ch_sw_info->buf_wptr, info->extra_action_id);
1895         CH_EXTRA_INFO_SET_INFO(ch_sw_info->buf_wptr, info->extra_info);
1896         CH_EXTRA_INFO_SET_SIZE(ch_sw_info->buf_wptr, info->extra_info_size);
1897         PLTFM_MEMCPY(ch_sw_info->buf_wptr + 2, info->extra_info_data,
1898                      info->extra_info_size);
1899
1900         ch_sw_info->avl_buf_size -= (2 + info->extra_info_size);
1901         ch_sw_info->total_size += (2 + info->extra_info_size);
1902         ch_sw_info->extra_info_en = info->extra_info;
1903         ch_sw_info->buf_wptr += (2 + info->extra_info_size);
1904
1905         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1906
1907         return HALMAC_RET_SUCCESS;
1908 }
1909
1910 /**
1911  * ctrl_ch_switch_88xx() -send channel switch cmd
1912  * @adapter : the adapter of halmac
1913  * @opt : channel switch config
1914  * Author : KaiYuan Chang/Ivan Lin
1915  * Return : enum halmac_ret_status
1916  * More details of status code can be found in prototype document
1917  */
1918 enum halmac_ret_status
1919 ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
1920                     struct halmac_ch_switch_option *opt)
1921 {
1922         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1923         enum halmac_cmd_construct_state state;
1924         enum halmac_cmd_process_status *proc_status;
1925
1926         proc_status = &adapter->halmac_state.scan_state.proc_status;
1927
1928         if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
1929                 return HALMAC_RET_NO_DLFW;
1930
1931         if (adapter->fw_ver.h2c_version < 4)
1932                 return HALMAC_RET_FW_NO_SUPPORT;
1933
1934         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1935
1936         if (opt->switch_en == 0)
1937                 *proc_status = HALMAC_CMD_PROCESS_IDLE;
1938
1939         if ((*proc_status == HALMAC_CMD_PROCESS_SENDING) ||
1940             (*proc_status == HALMAC_CMD_PROCESS_RCVD)) {
1941                 PLTFM_MSG_TRACE("[TRACE]Wait event(scan)\n");
1942                 return HALMAC_RET_BUSY_STATE;
1943         }
1944
1945         state = scan_cmd_cnstr_state_88xx(adapter);
1946         if (opt->switch_en == 1) {
1947                 if (state != HALMAC_CMD_CNSTR_CNSTR) {
1948                         PLTFM_MSG_ERR("[ERR]state(en = 1)\n");
1949                         return HALMAC_RET_ERROR_STATE;
1950                 }
1951         } else {
1952                 if (state != HALMAC_CMD_CNSTR_BUF_CLR) {
1953                         PLTFM_MSG_ERR("[ERR]state(en = 0)\n");
1954                         return HALMAC_RET_ERROR_STATE;
1955                 }
1956         }
1957
1958         status = proc_ctrl_ch_switch_88xx(adapter, opt);
1959         if (status != HALMAC_RET_SUCCESS) {
1960                 PLTFM_MSG_ERR("[ERR]ctrl ch sw!!\n");
1961                 return status;
1962         }
1963
1964         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
1965
1966         return HALMAC_RET_SUCCESS;
1967 }
1968
1969 static enum halmac_ret_status
1970 proc_ctrl_ch_switch_88xx(struct halmac_adapter *adapter,
1971                          struct halmac_ch_switch_option *opt)
1972 {
1973         u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
1974         u16 seq_num = 0;
1975         u16 pg_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
1976         struct halmac_h2c_header_info hdr_info;
1977         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
1978         enum halmac_cmd_process_status *proc_status;
1979
1980         proc_status = &adapter->halmac_state.scan_state.proc_status;
1981
1982         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
1983
1984         if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_H2C_SENT) !=
1985             HALMAC_RET_SUCCESS)
1986                 return HALMAC_RET_ERROR_STATE;
1987
1988         *proc_status = HALMAC_CMD_PROCESS_SENDING;
1989
1990         if (opt->switch_en != 0) {
1991                 status = dl_rsvd_page_88xx(adapter, pg_addr,
1992                                            adapter->ch_sw_info.buf,
1993                                            adapter->ch_sw_info.total_size);
1994                 if (status != HALMAC_RET_SUCCESS) {
1995                         PLTFM_MSG_ERR("[ERR]dl rsvd pg!!\n");
1996                         return status;
1997                 }
1998         }
1999
2000         CH_SWITCH_SET_START(h2c_buf, opt->switch_en);
2001         CH_SWITCH_SET_CH_NUM(h2c_buf, adapter->ch_sw_info.ch_num);
2002         CH_SWITCH_SET_INFO_LOC(h2c_buf,
2003                                pg_addr - adapter->txff_alloc.rsvd_boundary);
2004         CH_SWITCH_SET_DEST_CH_EN(h2c_buf, opt->dest_ch_en);
2005         CH_SWITCH_SET_DEST_CH(h2c_buf, opt->dest_ch);
2006         CH_SWITCH_SET_PRI_CH_IDX(h2c_buf, opt->dest_pri_ch_idx);
2007         CH_SWITCH_SET_ABSOLUTE_TIME(h2c_buf, opt->absolute_time_en);
2008         CH_SWITCH_SET_TSF_LOW(h2c_buf, opt->tsf_low);
2009         CH_SWITCH_SET_PERIODIC_OPT(h2c_buf, opt->periodic_option);
2010         CH_SWITCH_SET_NORMAL_CYCLE(h2c_buf, opt->normal_cycle);
2011         CH_SWITCH_SET_NORMAL_PERIOD(h2c_buf, opt->normal_period);
2012         CH_SWITCH_SET_SLOW_PERIOD(h2c_buf, opt->phase_2_period);
2013         CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_buf, opt->normal_period_sel);
2014         CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_buf, opt->phase_2_period_sel);
2015         CH_SWITCH_SET_INFO_SIZE(h2c_buf, adapter->ch_sw_info.total_size);
2016
2017         hdr_info.sub_cmd_id = SUB_CMD_ID_CH_SWITCH;
2018         hdr_info.content_size = 20;
2019         hdr_info.ack = 1;
2020         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
2021         adapter->halmac_state.scan_state.seq_num = seq_num;
2022
2023         status = send_h2c_pkt_88xx(adapter, h2c_buf);
2024
2025         if (status != HALMAC_RET_SUCCESS) {
2026                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
2027                 reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_CHANNEL_SWITCH);
2028         }
2029         PLTFM_FREE(adapter->ch_sw_info.buf, adapter->ch_sw_info.buf_size);
2030         adapter->ch_sw_info.buf = NULL;
2031         adapter->ch_sw_info.buf_wptr = NULL;
2032         adapter->ch_sw_info.extra_info_en = 0;
2033         adapter->ch_sw_info.buf_size = 0;
2034         adapter->ch_sw_info.avl_buf_size = 0;
2035         adapter->ch_sw_info.total_size = 0;
2036         adapter->ch_sw_info.ch_num = 0;
2037
2038         if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
2039             HALMAC_RET_SUCCESS)
2040                 return HALMAC_RET_ERROR_STATE;
2041
2042         return status;
2043 }
2044
2045 /**
2046  * clear_ch_info_88xx() -clear channel information
2047  * @adapter : the adapter of halmac
2048  * Author : KaiYuan Chang/Ivan Lin
2049  * Return : enum halmac_ret_status
2050  * More details of status code can be found in prototype document
2051  */
2052 enum halmac_ret_status
2053 clear_ch_info_88xx(struct halmac_adapter *adapter)
2054 {
2055         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
2056
2057         if (scan_cmd_cnstr_state_88xx(adapter) == HALMAC_CMD_CNSTR_H2C_SENT) {
2058                 PLTFM_MSG_WARN("[WARN]state(clear)\n");
2059                 return HALMAC_RET_ERROR_STATE;
2060         }
2061
2062         if (cnv_scan_state_88xx(adapter, HALMAC_CMD_CNSTR_BUF_CLR) !=
2063             HALMAC_RET_SUCCESS)
2064                 return HALMAC_RET_ERROR_STATE;
2065
2066         PLTFM_FREE(adapter->ch_sw_info.buf, adapter->ch_sw_info.buf_size);
2067         adapter->ch_sw_info.buf = NULL;
2068         adapter->ch_sw_info.buf_wptr = NULL;
2069         adapter->ch_sw_info.extra_info_en = 0;
2070         adapter->ch_sw_info.buf_size = 0;
2071         adapter->ch_sw_info.avl_buf_size = 0;
2072         adapter->ch_sw_info.total_size = 0;
2073         adapter->ch_sw_info.ch_num = 0;
2074
2075         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
2076
2077         return HALMAC_RET_SUCCESS;
2078 }
2079
2080 /**
2081  * chk_txdesc_88xx() -check if the tx packet format is incorrect
2082  * @adapter : the adapter of halmac
2083  * @buf : tx Packet buffer, tx desc is included
2084  * @size : tx packet size
2085  * Author : KaiYuan Chang
2086  * Return : enum halmac_ret_status
2087  * More details of status code can be found in prototype document
2088  */
2089 enum halmac_ret_status
2090 chk_txdesc_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
2091 {
2092         u32 mac_clk = 0;
2093         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2094         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2095
2096         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
2097
2098         if (GET_TX_DESC_BMC(buf) == 1 && GET_TX_DESC_AGG_EN(buf) == 1)
2099                 PLTFM_MSG_ERR("[ERR]txdesc - agg + bmc\n");
2100
2101         if (size < (GET_TX_DESC_TXPKTSIZE(buf) +
2102                     adapter->hw_cfg_info.txdesc_size +
2103                     (GET_TX_DESC_PKT_OFFSET(buf) << 3))) {
2104                 PLTFM_MSG_ERR("[ERR]txdesc - total size\n");
2105                 status = HALMAC_RET_TXDESC_SET_FAIL;
2106         }
2107
2108         if (wlhdr_valid_88xx(adapter, buf) != HALMAC_RET_SUCCESS) {
2109                 PLTFM_MSG_ERR("[ERR]wlhdr\n");
2110                 status = HALMAC_RET_WLHDR_FAIL;
2111         }
2112
2113         if (GET_TX_DESC_AMSDU_PAD_EN(buf) != 0) {
2114                 PLTFM_MSG_ERR("[ERR]txdesc - amsdu_pad\n");
2115                 status = HALMAC_RET_TXDESC_SET_FAIL;
2116         }
2117
2118         switch (BIT_GET_MAC_CLK_SEL(HALMAC_REG_R32(REG_AFE_CTRL1))) {
2119         case 0x0:
2120                 mac_clk = 80;
2121                 break;
2122         case 0x1:
2123                 mac_clk = 40;
2124                 break;
2125         case 0x2:
2126                 mac_clk = 20;
2127                 break;
2128         case 0x3:
2129                 mac_clk = 10;
2130                 break;
2131         }
2132
2133         PLTFM_MSG_ALWAYS("MAC clock : 0x%XM\n", mac_clk);
2134         PLTFM_MSG_ALWAYS("mac agg en : 0x%X\n", GET_TX_DESC_AGG_EN(buf));
2135         PLTFM_MSG_ALWAYS("mac agg num : 0x%X\n", GET_TX_DESC_MAX_AGG_NUM(buf));
2136
2137         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
2138
2139         return status;
2140 }
2141
2142 static enum halmac_ret_status
2143 wlhdr_valid_88xx(struct halmac_adapter *adapter, u8 *buf)
2144 {
2145         u32 txdesc_size = adapter->hw_cfg_info.txdesc_size +
2146                                                 GET_TX_DESC_PKT_OFFSET(buf);
2147         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2148         struct wlhdr_frame_ctrl *wlhdr;
2149
2150         wlhdr = (struct wlhdr_frame_ctrl *)(buf + txdesc_size);
2151
2152         if (wlhdr->protocol != WLHDR_PROT_VER) {
2153                 PLTFM_MSG_ERR("[ERR]prot ver!!\n");
2154                 return HALMAC_RET_WLHDR_FAIL;
2155         }
2156
2157         switch (wlhdr->type) {
2158         case WLHDR_TYPE_MGMT:
2159                 if (wlhdr_mgmt_valid_88xx(adapter, wlhdr) != 1)
2160                         status = HALMAC_RET_WLHDR_FAIL;
2161                 break;
2162         case WLHDR_TYPE_CTRL:
2163                 if (wlhdr_ctrl_valid_88xx(adapter, wlhdr) != 1)
2164                         status = HALMAC_RET_WLHDR_FAIL;
2165                 break;
2166         case WLHDR_TYPE_DATA:
2167                 if (wlhdr_data_valid_88xx(adapter, wlhdr) != 1)
2168                         status = HALMAC_RET_WLHDR_FAIL;
2169                 break;
2170         default:
2171                 PLTFM_MSG_ERR("[ERR]undefined type!!\n");
2172                 status = HALMAC_RET_WLHDR_FAIL;
2173                 break;
2174         }
2175
2176         return status;
2177 }
2178
2179 static u8
2180 wlhdr_mgmt_valid_88xx(struct halmac_adapter *adapter,
2181                       struct wlhdr_frame_ctrl *wlhdr)
2182 {
2183         u8 state;
2184
2185         switch (wlhdr->sub_type) {
2186         case WLHDR_SUB_TYPE_ASSOC_REQ:
2187         case WLHDR_SUB_TYPE_ASSOC_RSPNS:
2188         case WLHDR_SUB_TYPE_REASSOC_REQ:
2189         case WLHDR_SUB_TYPE_REASSOC_RSPNS:
2190         case WLHDR_SUB_TYPE_PROBE_REQ:
2191         case WLHDR_SUB_TYPE_PROBE_RSPNS:
2192         case WLHDR_SUB_TYPE_BCN:
2193         case WLHDR_SUB_TYPE_DISASSOC:
2194         case WLHDR_SUB_TYPE_AUTH:
2195         case WLHDR_SUB_TYPE_DEAUTH:
2196         case WLHDR_SUB_TYPE_ACTION:
2197         case WLHDR_SUB_TYPE_ACTION_NOACK:
2198                 state = 1;
2199                 break;
2200         default:
2201                 PLTFM_MSG_ERR("[ERR]mgmt invalid!!\n");
2202                 state = 0;
2203                 break;
2204         }
2205
2206         return state;
2207 }
2208
2209 static u8
2210 wlhdr_ctrl_valid_88xx(struct halmac_adapter *adapter,
2211                       struct wlhdr_frame_ctrl *wlhdr)
2212 {
2213         u8 state;
2214
2215         switch (wlhdr->sub_type) {
2216         case WLHDR_SUB_TYPE_BF_RPT_POLL:
2217         case WLHDR_SUB_TYPE_NDPA:
2218                 state = 1;
2219                 break;
2220         default:
2221                 PLTFM_MSG_ERR("[ERR]ctrl invalid!!\n");
2222                 state = 0;
2223                 break;
2224         }
2225
2226         return state;
2227 }
2228
2229 static u8
2230 wlhdr_data_valid_88xx(struct halmac_adapter *adapter,
2231                       struct wlhdr_frame_ctrl *wlhdr)
2232 {
2233         u8 state;
2234
2235         switch (wlhdr->sub_type) {
2236         case WLHDR_SUB_TYPE_DATA:
2237         case WLHDR_SUB_TYPE_NULL:
2238         case WLHDR_SUB_TYPE_QOS_DATA:
2239         case WLHDR_SUB_TYPE_QOS_NULL:
2240                 state = 1;
2241                 break;
2242         default:
2243                 PLTFM_MSG_ERR("[ERR]data invalid!!\n");
2244                 state = 0;
2245                 break;
2246         }
2247
2248         return state;
2249 }
2250
2251 /**
2252  * get_version_88xx() - get HALMAC version
2253  * @ver : return version of major, prototype and minor information
2254  * Author : KaiYuan Chang / Ivan Lin
2255  * Return : enum halmac_ret_status
2256  * More details of status code can be found in prototype document
2257  */
2258 enum halmac_ret_status
2259 get_version_88xx(struct halmac_adapter *adapter, struct halmac_ver *ver)
2260 {
2261         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
2262
2263         ver->major_ver = (u8)HALMAC_MAJOR_VER;
2264         ver->prototype_ver = (u8)HALMAC_PROTOTYPE_VER;
2265         ver->minor_ver = (u8)HALMAC_MINOR_VER;
2266
2267         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
2268
2269         return HALMAC_RET_SUCCESS;
2270 }
2271
2272 enum halmac_ret_status
2273 p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info)
2274 {
2275         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2276
2277         if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
2278                 return HALMAC_RET_NO_DLFW;
2279
2280         if (adapter->fw_ver.h2c_version < 6)
2281                 return HALMAC_RET_FW_NO_SUPPORT;
2282
2283         status = proc_p2pps_88xx(adapter, info);
2284         if (status != HALMAC_RET_SUCCESS) {
2285                 PLTFM_MSG_ERR("[ERR]p2pps!!\n");
2286                 return status;
2287         }
2288
2289         return HALMAC_RET_SUCCESS;
2290 }
2291
2292 static enum halmac_ret_status
2293 proc_p2pps_88xx(struct halmac_adapter *adapter, struct halmac_p2pps *info)
2294 {
2295         u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
2296         u16 seq_num = 0;
2297         struct halmac_h2c_header_info hdr_info;
2298         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2299
2300         P2PPS_SET_OFFLOAD_EN(h2c_buf, info->offload_en);
2301         P2PPS_SET_ROLE(h2c_buf, info->role);
2302         P2PPS_SET_CTWINDOW_EN(h2c_buf, info->ctwindow_en);
2303         P2PPS_SET_NOA_EN(h2c_buf, info->noa_en);
2304         P2PPS_SET_NOA_SEL(h2c_buf, info->noa_sel);
2305         P2PPS_SET_ALLSTASLEEP(h2c_buf, info->all_sta_sleep);
2306         P2PPS_SET_DISCOVERY(h2c_buf, info->discovery);
2307         P2PPS_SET_DISABLE_CLOSERF(h2c_buf, info->disable_close_rf);
2308         P2PPS_SET_P2P_PORT_ID(h2c_buf, info->p2p_port_id);
2309         P2PPS_SET_P2P_GROUP(h2c_buf, info->p2p_group);
2310         P2PPS_SET_P2P_MACID(h2c_buf, info->p2p_macid);
2311
2312         P2PPS_SET_CTWINDOW_LENGTH(h2c_buf, info->ctwindow_length);
2313
2314         P2PPS_SET_NOA_DURATION_PARA(h2c_buf, info->noa_duration_para);
2315         P2PPS_SET_NOA_INTERVAL_PARA(h2c_buf, info->noa_interval_para);
2316         P2PPS_SET_NOA_START_TIME_PARA(h2c_buf, info->noa_start_time_para);
2317         P2PPS_SET_NOA_COUNT_PARA(h2c_buf, info->noa_count_para);
2318
2319         hdr_info.sub_cmd_id = SUB_CMD_ID_P2PPS;
2320         hdr_info.content_size = 24;
2321         hdr_info.ack = 0;
2322         set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
2323
2324         status = send_h2c_pkt_88xx(adapter, h2c_buf);
2325
2326         if (status != HALMAC_RET_SUCCESS)
2327                 PLTFM_MSG_ERR("[ERR]send h2c!!\n");
2328
2329         return status;
2330 }
2331
2332 /**
2333  * query_status_88xx() -query the offload feature status
2334  * @adapter : the adapter of halmac
2335  * @feature_id : feature_id
2336  * @proc_status : feature_status
2337  * @data : data buffer
2338  * @size : data size
2339  *
2340  * Note :
2341  * If user wants to know the data size, user can allocate zero
2342  * size buffer first. If this size less than the data size, halmac
2343  * will return  HALMAC_RET_BUFFER_TOO_SMALL. User need to
2344  * re-allocate data buffer with correct data size.
2345  *
2346  * Author : Ivan Lin/KaiYuan Chang
2347  * Return : enum halmac_ret_status
2348  * More details of status code can be found in prototype document
2349  */
2350 enum halmac_ret_status
2351 query_status_88xx(struct halmac_adapter *adapter,
2352                   enum halmac_feature_id feature_id,
2353                   enum halmac_cmd_process_status *proc_status, u8 *data,
2354                   u32 *size)
2355 {
2356         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2357
2358         if (!proc_status)
2359                 return HALMAC_RET_NULL_POINTER;
2360
2361         switch (feature_id) {
2362         case HALMAC_FEATURE_CFG_PARA:
2363                 status = get_cfg_param_status_88xx(adapter, proc_status);
2364                 break;
2365         case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
2366                 status = get_dump_phy_efuse_status_88xx(adapter, proc_status,
2367                                                         data, size);
2368                 break;
2369         case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
2370                 status = get_dump_log_efuse_status_88xx(adapter, proc_status,
2371                                                         data, size);
2372                 break;
2373         case HALMAC_FEATURE_CHANNEL_SWITCH:
2374                 status = get_ch_switch_status_88xx(adapter, proc_status);
2375                 break;
2376         case HALMAC_FEATURE_UPDATE_PACKET:
2377                 status = get_update_packet_status_88xx(adapter, proc_status);
2378                 break;
2379         case HALMAC_FEATURE_IQK:
2380                 status = get_iqk_status_88xx(adapter, proc_status);
2381                 break;
2382         case HALMAC_FEATURE_POWER_TRACKING:
2383                 status = get_pwr_trk_status_88xx(adapter, proc_status);
2384                 break;
2385         case HALMAC_FEATURE_PSD:
2386                 status = get_psd_status_88xx(adapter, proc_status, data, size);
2387                 break;
2388         case HALMAC_FEATURE_FW_SNDING:
2389                 status = get_fw_snding_status_88xx(adapter, proc_status);
2390                 break;
2391         default:
2392                 return HALMAC_RET_INVALID_FEATURE_ID;
2393         }
2394
2395         return status;
2396 }
2397
2398 static enum halmac_ret_status
2399 get_cfg_param_status_88xx(struct halmac_adapter *adapter,
2400                           enum halmac_cmd_process_status *proc_status)
2401 {
2402         *proc_status = adapter->halmac_state.cfg_param_state.proc_status;
2403
2404         return HALMAC_RET_SUCCESS;
2405 }
2406
2407 static enum halmac_ret_status
2408 get_ch_switch_status_88xx(struct halmac_adapter *adapter,
2409                           enum halmac_cmd_process_status *proc_status)
2410 {
2411         *proc_status = adapter->halmac_state.scan_state.proc_status;
2412
2413         return HALMAC_RET_SUCCESS;
2414 }
2415
2416 static enum halmac_ret_status
2417 get_update_packet_status_88xx(struct halmac_adapter *adapter,
2418                               enum halmac_cmd_process_status *proc_status)
2419 {
2420         *proc_status = adapter->halmac_state.update_pkt_state.proc_status;
2421
2422         return HALMAC_RET_SUCCESS;
2423 }
2424
2425 /**
2426  * cfg_drv_rsvd_pg_num_88xx() -config reserved page number for driver
2427  * @adapter : the adapter of halmac
2428  * @pg_num : page number
2429  * Author : KaiYuan Chang
2430  * Return : enum halmac_ret_status
2431  * More details of status code can be found in prototype document
2432  */
2433 enum halmac_ret_status
2434 cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *adapter,
2435                          enum halmac_drv_rsvd_pg_num pg_num)
2436 {
2437         if (adapter->api_registry.cfg_drv_rsvd_pg_en == 0)
2438                 return HALMAC_RET_NOT_SUPPORT;
2439
2440         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
2441         PLTFM_MSG_TRACE("[TRACE]pg_num = %d\n", pg_num);
2442
2443         switch (pg_num) {
2444         case HALMAC_RSVD_PG_NUM8:
2445                 adapter->txff_alloc.rsvd_drv_pg_num = 8;
2446                 break;
2447         case HALMAC_RSVD_PG_NUM16:
2448                 adapter->txff_alloc.rsvd_drv_pg_num = 16;
2449                 break;
2450         case HALMAC_RSVD_PG_NUM24:
2451                 adapter->txff_alloc.rsvd_drv_pg_num = 24;
2452                 break;
2453         case HALMAC_RSVD_PG_NUM32:
2454                 adapter->txff_alloc.rsvd_drv_pg_num = 32;
2455                 break;
2456         case HALMAC_RSVD_PG_NUM64:
2457                 adapter->txff_alloc.rsvd_drv_pg_num = 64;
2458                 break;
2459         case HALMAC_RSVD_PG_NUM128:
2460                 adapter->txff_alloc.rsvd_drv_pg_num = 128;
2461                 break;
2462         }
2463
2464         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
2465
2466         return HALMAC_RET_SUCCESS;
2467 }
2468
2469 /**
2470  * (debug API)h2c_lb_88xx() - send h2c loopback packet
2471  * @adapter : the adapter of halmac
2472  * Author : KaiYuan Chang/Ivan Lin
2473  * Return : enum halmac_ret_status
2474  * More details of status code can be found in prototype document
2475  */
2476 enum halmac_ret_status
2477 h2c_lb_88xx(struct halmac_adapter *adapter)
2478 {
2479         return HALMAC_RET_SUCCESS;
2480 }
2481
2482 enum halmac_ret_status
2483 pwr_seq_parser_88xx(struct halmac_adapter *adapter,
2484                     struct halmac_wlan_pwr_cfg **cmd_seq)
2485 {
2486         u8 cut;
2487         u8 intf;
2488         u32 idx = 0;
2489         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
2490         struct halmac_wlan_pwr_cfg *cmd;
2491
2492         switch (adapter->chip_ver) {
2493         case HALMAC_CHIP_VER_A_CUT:
2494                 cut = HALMAC_PWR_CUT_A_MSK;
2495                 break;
2496         case HALMAC_CHIP_VER_B_CUT:
2497                 cut = HALMAC_PWR_CUT_B_MSK;
2498                 break;
2499         case HALMAC_CHIP_VER_C_CUT:
2500                 cut = HALMAC_PWR_CUT_C_MSK;
2501                 break;
2502         case HALMAC_CHIP_VER_D_CUT:
2503                 cut = HALMAC_PWR_CUT_D_MSK;
2504                 break;
2505         case HALMAC_CHIP_VER_E_CUT:
2506                 cut = HALMAC_PWR_CUT_E_MSK;
2507                 break;
2508         case HALMAC_CHIP_VER_F_CUT:
2509                 cut = HALMAC_PWR_CUT_F_MSK;
2510                 break;
2511         case HALMAC_CHIP_VER_TEST:
2512                 cut = HALMAC_PWR_CUT_TESTCHIP_MSK;
2513                 break;
2514         default:
2515                 PLTFM_MSG_ERR("[ERR]cut version!!\n");
2516                 return HALMAC_RET_SWITCH_CASE_ERROR;
2517         }
2518
2519         switch (adapter->intf) {
2520         case HALMAC_INTERFACE_PCIE:
2521         case HALMAC_INTERFACE_AXI:
2522                 intf = HALMAC_PWR_INTF_PCI_MSK;
2523                 break;
2524         case HALMAC_INTERFACE_USB:
2525                 intf = HALMAC_PWR_INTF_USB_MSK;
2526                 break;
2527         case HALMAC_INTERFACE_SDIO:
2528                 intf = HALMAC_PWR_INTF_SDIO_MSK;
2529                 break;
2530         default:
2531                 PLTFM_MSG_ERR("[ERR]interface!!\n");
2532                 return HALMAC_RET_SWITCH_CASE_ERROR;
2533         }
2534
2535         do {
2536                 cmd = cmd_seq[idx];
2537
2538                 if (!cmd)
2539                         break;
2540
2541                 status = pwr_sub_seq_parser_88xx(adapter, cut, intf, cmd);
2542                 if (status != HALMAC_RET_SUCCESS) {
2543                         PLTFM_MSG_ERR("[ERR]pwr sub seq!!\n");
2544                         return status;
2545                 }
2546
2547                 idx++;
2548         } while (1);
2549
2550         return status;
2551 }
2552
2553 static enum halmac_ret_status
2554 pwr_sub_seq_parser_88xx(struct halmac_adapter *adapter, u8 cut, u8 intf,
2555                         struct halmac_wlan_pwr_cfg *cmd)
2556 {
2557         u8 value;
2558         u32 offset;
2559         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2560
2561         do {
2562                 if ((cmd->interface_msk & intf) && (cmd->cut_msk & cut)) {
2563                         switch (cmd->cmd) {
2564                         case HALMAC_PWR_CMD_WRITE:
2565                                 offset = cmd->offset;
2566
2567                                 if (cmd->base == HALMAC_PWR_ADDR_SDIO)
2568                                         offset |= SDIO_LOCAL_OFFSET;
2569
2570                                 value = HALMAC_REG_R8(offset);
2571                                 value = (u8)(value & (u8)(~(cmd->msk)));
2572                                 value = (u8)(value | (cmd->value & cmd->msk));
2573
2574                                 HALMAC_REG_W8(offset, value);
2575                                 break;
2576                         case HALMAC_PWR_CMD_POLLING:
2577                                 if (pwr_cmd_polling_88xx(adapter, cmd) !=
2578                                     HALMAC_RET_SUCCESS)
2579                                         return HALMAC_RET_PWRSEQ_POLLING_FAIL;
2580                                 break;
2581                         case HALMAC_PWR_CMD_DELAY:
2582                                 if (cmd->value == HALMAC_PWR_DELAY_US)
2583                                         PLTFM_DELAY_US(cmd->offset);
2584                                 else
2585                                         PLTFM_DELAY_US(1000 * cmd->offset);
2586                                 break;
2587                         case HALMAC_PWR_CMD_READ:
2588                                 break;
2589                         case HALMAC_PWR_CMD_END:
2590                                 return HALMAC_RET_SUCCESS;
2591                         default:
2592                                 return HALMAC_RET_PWRSEQ_CMD_INCORRECT;
2593                         }
2594                 }
2595                 cmd++;
2596         } while (1);
2597
2598         return HALMAC_RET_SUCCESS;
2599 }
2600
2601 static enum halmac_ret_status
2602 pwr_cmd_polling_88xx(struct halmac_adapter *adapter,
2603                      struct halmac_wlan_pwr_cfg *cmd)
2604 {
2605         u8 value;
2606         u8 flg;
2607         u8 poll_bit;
2608         u32 offset;
2609         u32 cnt;
2610         static u32 stats;
2611         enum halmac_interface intf;
2612         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2613
2614         poll_bit = 0;
2615         cnt = HALMAC_PWR_POLLING_CNT;
2616         flg = 0;
2617         intf = adapter->intf;
2618
2619         if (cmd->base == HALMAC_PWR_ADDR_SDIO)
2620                 offset = cmd->offset | SDIO_LOCAL_OFFSET;
2621         else
2622                 offset = cmd->offset;
2623
2624         do {
2625                 cnt--;
2626                 value = HALMAC_REG_R8(offset);
2627                 value = (u8)(value & cmd->msk);
2628
2629                 if (value == (cmd->value & cmd->msk)) {
2630                         poll_bit = 1;
2631                 } else {
2632                         if (cnt == 0) {
2633                                 if (intf == HALMAC_INTERFACE_PCIE && flg == 0) {
2634                                         /* PCIE + USB package */
2635                                         /* power bit polling timeout issue */
2636                                         stats++;
2637                                         PLTFM_MSG_WARN("[WARN]PCIE stats:%d\n",
2638                                                        stats);
2639                                         value = HALMAC_REG_R8(REG_SYS_PW_CTRL);
2640                                         value |= BIT(3);
2641                                         HALMAC_REG_W8(REG_SYS_PW_CTRL, value);
2642                                         value &= ~BIT(3);
2643                                         HALMAC_REG_W8(REG_SYS_PW_CTRL, value);
2644                                         poll_bit = 0;
2645                                         cnt = HALMAC_PWR_POLLING_CNT;
2646                                         flg = 1;
2647                                 } else {
2648                                         PLTFM_MSG_ERR("[ERR]polling to!!\n");
2649                                         PLTFM_MSG_ERR("[ERR]cmd offset:%X\n",
2650                                                       cmd->offset);
2651                                         PLTFM_MSG_ERR("[ERR]cmd value:%X\n",
2652                                                       cmd->value);
2653                                         PLTFM_MSG_ERR("[ERR]cmd msk:%X\n",
2654                                                       cmd->msk);
2655                                         PLTFM_MSG_ERR("[ERR]offset = %X\n",
2656                                                       offset);
2657                                         PLTFM_MSG_ERR("[ERR]value = %X\n",
2658                                                       value);
2659                                         return HALMAC_RET_PWRSEQ_POLLING_FAIL;
2660                                 }
2661                         } else {
2662                                 PLTFM_DELAY_US(50);
2663                         }
2664                 }
2665         } while (!poll_bit);
2666
2667         return HALMAC_RET_SUCCESS;
2668 }
2669
2670 enum halmac_ret_status
2671 parse_intf_phy_88xx(struct halmac_adapter *adapter,
2672                     struct halmac_intf_phy_para *param,
2673                     enum halmac_intf_phy_platform pltfm,
2674                     enum hal_intf_phy intf_phy)
2675 {
2676         u16 value;
2677         u16 cur_cut;
2678         u16 offset;
2679         u16 ip_sel;
2680         struct halmac_intf_phy_para *cur_param;
2681         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2682         u8 result = HALMAC_RET_SUCCESS;
2683
2684         switch (adapter->chip_ver) {
2685         case HALMAC_CHIP_VER_A_CUT:
2686                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_A;
2687                 break;
2688         case HALMAC_CHIP_VER_B_CUT:
2689                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_B;
2690                 break;
2691         case HALMAC_CHIP_VER_C_CUT:
2692                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_C;
2693                 break;
2694         case HALMAC_CHIP_VER_D_CUT:
2695                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_D;
2696                 break;
2697         case HALMAC_CHIP_VER_E_CUT:
2698                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_E;
2699                 break;
2700         case HALMAC_CHIP_VER_F_CUT:
2701                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_F;
2702                 break;
2703         case HALMAC_CHIP_VER_TEST:
2704                 cur_cut = (u16)HALMAC_INTF_PHY_CUT_TESTCHIP;
2705                 break;
2706         default:
2707                 return HALMAC_RET_FAIL;
2708         }
2709
2710         cur_param = param;
2711
2712         do {
2713                 if ((cur_param->cut & cur_cut) &&
2714                     (cur_param->plaform & (u16)pltfm)) {
2715                         offset =  cur_param->offset;
2716                         value = cur_param->value;
2717                         ip_sel = cur_param->ip_sel;
2718
2719                         if (offset == 0xFFFF)
2720                                 break;
2721
2722                         if (ip_sel == HALMAC_IP_SEL_MAC) {
2723                                 HALMAC_REG_W8((u32)offset, (u8)value);
2724                         } else if (intf_phy == HAL_INTF_PHY_USB2 ||
2725                                    intf_phy == HAL_INTF_PHY_USB3) {
2726 #if HALMAC_USB_SUPPORT
2727                                 result = usbphy_write_88xx(adapter, (u8)offset,
2728                                                            value, intf_phy);
2729                                 if (result != HALMAC_RET_SUCCESS)
2730                                         PLTFM_MSG_ERR("[ERR]usb phy!!\n");
2731 #endif
2732                         } else if (intf_phy == HAL_INTF_PHY_PCIE_GEN1 ||
2733                                    intf_phy == HAL_INTF_PHY_PCIE_GEN2) {
2734 #if HALMAC_PCIE_SUPPORT
2735                                 if (ip_sel == HALMAC_IP_INTF_PHY)
2736                                         result = mdio_write_88xx(adapter,
2737                                                                  (u8)offset,
2738                                                                  value,
2739                                                                  intf_phy);
2740                                 else
2741                                         result = dbi_w8_88xx(adapter, offset,
2742                                                              (u8)value);
2743                                 if (result != HALMAC_RET_SUCCESS)
2744                                         PLTFM_MSG_ERR("[ERR]mdio/dbi!!\n");
2745 #endif
2746                         } else {
2747                                 PLTFM_MSG_ERR("[ERR]intf phy sel!!\n");
2748                         }
2749                 }
2750                 cur_param++;
2751         } while (1);
2752
2753         return HALMAC_RET_SUCCESS;
2754 }
2755
2756 /**
2757  * txfifo_is_empty_88xx() -check if txfifo is empty
2758  * @adapter : the adapter of halmac
2759  * @chk_num : check number
2760  * Author : Ivan Lin
2761  * Return : enum halmac_ret_status
2762  * More details of status code can be found in prototype document
2763  */
2764 enum halmac_ret_status
2765 txfifo_is_empty_88xx(struct halmac_adapter *adapter, u32 chk_num)
2766 {
2767         u32 cnt;
2768         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2769
2770         PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
2771
2772         cnt = (chk_num <= 10) ? 10 : chk_num;
2773         do {
2774                 if (HALMAC_REG_R8(REG_TXPKT_EMPTY) != 0xFF)
2775                         return HALMAC_RET_TXFIFO_NO_EMPTY;
2776
2777                 if ((HALMAC_REG_R8(REG_TXPKT_EMPTY + 1) & 0x06) != 0x06)
2778                         return HALMAC_RET_TXFIFO_NO_EMPTY;
2779                 cnt--;
2780
2781         } while (cnt != 0);
2782
2783         PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
2784
2785         return HALMAC_RET_SUCCESS;
2786 }
2787
2788 /**
2789  * (internal use)
2790  * smart_malloc_88xx() - adapt malloc size
2791  * @adapter : the adapter of halmac
2792  * @size : expected malloc size
2793  * @pNew_size : real malloc size
2794  * Author : Ivan Lin
2795  * Return : address pointer
2796  */
2797 u8*
2798 smart_malloc_88xx(struct halmac_adapter *adapter, u32 size, u32 *new_size)
2799 {
2800         u8 retry_num;
2801         u8 *malloc_buf = NULL;
2802
2803         for (retry_num = 0; retry_num < 5; retry_num++) {
2804                 malloc_buf = (u8 *)PLTFM_MALLOC(size);
2805
2806                 if (malloc_buf) {
2807                         *new_size = size;
2808                         return malloc_buf;
2809                 }
2810
2811                 size = size >> 1;
2812
2813                 if (size == 0)
2814                         break;
2815         }
2816
2817         PLTFM_MSG_ERR("[ERR]adptive malloc!!\n");
2818
2819         return NULL;
2820 }
2821
2822 /**
2823  * (internal use)
2824  * ltecoex_reg_read_88xx() - read ltecoex register
2825  * @adapter : the adapter of halmac
2826  * @offset : offset
2827  * @pValue : value
2828  * Author : Ivan Lin
2829  * Return : enum halmac_ret_status
2830  */
2831 enum halmac_ret_status
2832 ltecoex_reg_read_88xx(struct halmac_adapter *adapter, u16 offset, u32 *value)
2833 {
2834         u32 cnt;
2835         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2836
2837         cnt = 10000;
2838         while ((HALMAC_REG_R8(LTECOEX_ACCESS_CTRL + 3) & BIT(5)) == 0) {
2839                 if (cnt == 0) {
2840                         PLTFM_MSG_ERR("[ERR]lte ready(R)\n");
2841                         return HALMAC_RET_LTECOEX_READY_FAIL;
2842                 }
2843                 cnt--;
2844                 PLTFM_DELAY_US(50);
2845         }
2846
2847         HALMAC_REG_W32(LTECOEX_ACCESS_CTRL, 0x800F0000 | offset);
2848         *value = HALMAC_REG_R32(REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1);
2849
2850         return HALMAC_RET_SUCCESS;
2851 }
2852
2853 /**
2854  * (internal use)
2855  * ltecoex_reg_write_88xx() - write ltecoex register
2856  * @adapter : the adapter of halmac
2857  * @offset : offset
2858  * @value : value
2859  * Author : Ivan Lin
2860  * Return : enum halmac_ret_status
2861  */
2862 enum halmac_ret_status
2863 ltecoex_reg_write_88xx(struct halmac_adapter *adapter, u16 offset, u32 value)
2864 {
2865         u32 cnt;
2866         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2867
2868         cnt = 10000;
2869         while ((HALMAC_REG_R8(LTECOEX_ACCESS_CTRL + 3) & BIT(5)) == 0) {
2870                 if (cnt == 0) {
2871                         PLTFM_MSG_ERR("[ERR]lte ready(W)\n");
2872                         return HALMAC_RET_LTECOEX_READY_FAIL;
2873                 }
2874                 cnt--;
2875                 PLTFM_DELAY_US(50);
2876         }
2877
2878         HALMAC_REG_W32(REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1, value);
2879         HALMAC_REG_W32(LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset);
2880
2881         return HALMAC_RET_SUCCESS;
2882 }
2883
2884 static void
2885 pwr_state_88xx(struct halmac_adapter *adapter, enum halmac_mac_power *state)
2886 {
2887         struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
2888
2889         if ((HALMAC_REG_R8(REG_SYS_FUNC_EN + 1) & BIT(3)) == 0)
2890                 *state = HALMAC_MAC_POWER_OFF;
2891         else
2892                 *state = HALMAC_MAC_POWER_ON;
2893 }
2894
2895 #endif /* HALMAC_88XX_SUPPORT */