1 /******************************************************************************
2 *
3 * Copyright(c) 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _HAL_BTC_FW_C_
16 #include "../hal_headers_le.h"
17 #include "hal_btc.h"
18 #include "halbtc_fw.h"
19 #include "halbtc_def.h"
20
21 #ifdef CONFIG_BTCOEX
22
_chk_btc_err(struct btc_t * btc,u8 type,u32 cnt)23 void _chk_btc_err(struct btc_t *btc, u8 type, u32 cnt)
24 {
25 struct btc_cx *cx = &btc->cx;
26 struct btc_dm *dm = &btc->dm;
27 struct btc_wl_info *wl = &cx->wl;
28 struct btc_bt_info *bt = &cx->bt;
29
30 switch (type) {
31 case BTC_DCNT_RPT_FREEZE:
32 if (wl->status.map.lps == BTC_LPS_RF_OFF ||
33 wl->status.map.rf_off)
34 return;
35
36 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
37 dm->cnt_dm[BTC_DCNT_RPT_FREEZE]++;
38 else
39 dm->cnt_dm[BTC_DCNT_RPT_FREEZE] = 0;
40
41 if (dm->cnt_dm[BTC_DCNT_RPT_FREEZE] >= BTC_CHK_HANG_MAX)
42 dm->error.map.wl_fw_hang = true;
43 else
44 dm->error.map.wl_fw_hang = false;
45
46 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
47 break;
48 case BTC_DCNT_CYCLE_FREEZE:
49 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
50 (dm->tdma_now.type != CXTDMA_OFF ||
51 dm->tdma_now.ext_ctrl == CXECTL_EXT))
52 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE]++;
53 else
54 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] = 0;
55
56 if (dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] >= BTC_CHK_HANG_MAX)
57 dm->error.map.cycle_hang = true;
58 else
59 dm->error.map.cycle_hang = false;
60
61 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
62 break;
63 case BTC_DCNT_W1_FREEZE:
64 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
65 dm->tdma_now.type != CXTDMA_OFF)
66 dm->cnt_dm[BTC_DCNT_W1_FREEZE]++;
67 else
68 dm->cnt_dm[BTC_DCNT_W1_FREEZE] = 0;
69
70 if (dm->cnt_dm[BTC_DCNT_W1_FREEZE] >= BTC_CHK_HANG_MAX)
71 dm->error.map.w1_hang = true;
72 else
73 dm->error.map.w1_hang = false;
74
75 dm->cnt_dm[BTC_DCNT_W1] = cnt;
76 break;
77 case BTC_DCNT_B1_FREEZE:
78 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
79 dm->tdma_now.type != CXTDMA_OFF)
80 dm->cnt_dm[BTC_DCNT_B1_FREEZE]++;
81 else
82 dm->cnt_dm[BTC_DCNT_B1_FREEZE] = 0;
83
84 if (dm->cnt_dm[BTC_DCNT_B1_FREEZE] >= BTC_CHK_HANG_MAX)
85 dm->error.map.b1_hang = true;
86 else
87 dm->error.map.b1_hang = false;
88
89 dm->cnt_dm[BTC_DCNT_B1] = cnt;
90 break;
91 case BTC_DCNT_TDMA_NONSYNC:
92 if (cnt != 0) /* if tdma not sync between drv/fw */
93 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
94 else
95 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
96
97 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
98 dm->error.map.tdma_no_sync = true;
99 else
100 dm->error.map.tdma_no_sync = false;
101 break;
102 case BTC_DCNT_SLOT_NONSYNC:
103 if (cnt != 0) /* if slot not sync between drv/fw */
104 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
105 else
106 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
107
108 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
109 dm->error.map.tdma_no_sync = true;
110 else
111 dm->error.map.tdma_no_sync = false;
112 break;
113 case BTC_DCNT_BTCNT_FREEZE:
114 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
115 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
116 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
117 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
118
119 if (cnt == 0)
120 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE]++;
121 else
122 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
123
124 if ((dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX &&
125 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] &&
126 !bt->enable.now))
127 _update_bt_scbd(btc, false);
128 break;
129 case BTC_DCNT_WL_SLOT_DRIFT:
130 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
131 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
132 else
133 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
134
135 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
136 dm->error.map.wl_slot_drift = true;
137 else
138 dm->error.map.wl_slot_drift = false;
139 break;
140 case BTC_DCNT_BT_SLOT_DRIFT:
141 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
142 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
143 else
144 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
145
146 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
147 dm->error.map.bt_slot_drift = true;
148 else
149 dm->error.map.bt_slot_drift = false;
150 break;
151 }
152 }
153
_update_bt_report(struct btc_t * btc,u8 rpt_type,u8 * pfinfo)154 static void _update_bt_report(struct btc_t *btc, u8 rpt_type, u8* pfinfo)
155 {
156 struct rtw_hal_com_t *h = btc->hal;
157 struct btc_bt_info *bt = &btc->cx.bt;
158 struct btc_bt_link_info *bt_linfo = &bt->link_info;
159 struct btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
160
161 struct fbtc_btver* pver = (struct fbtc_btver*) pfinfo;
162 struct fbtc_btscan* pscan = (struct fbtc_btscan*) pfinfo;
163 struct fbtc_btafh* pafh = (struct fbtc_btafh*) pfinfo;
164 struct fbtc_btdevinfo* pdev = (struct fbtc_btdevinfo*) pfinfo;
165
166 switch (rpt_type) {
167 case BTC_RPT_TYPE_BT_VER:
168 bt->ver_info.fw = pver->fw_ver;
169 bt->ver_info.fw_coex = (pver->coex_ver & bMASKB0);
170 bt->feature = pver->feature;
171 break;
172 case BTC_RPT_TYPE_BT_SCAN:
173 hal_mem_cpy(h, bt->scan_info, pscan->scan, BTC_SCAN_MAX1);
174 break;
175 case BTC_RPT_TYPE_BT_AFH:
176 hal_mem_cpy(h, &bt_linfo->afh_map[0], pafh->afh_l, 4);
177 hal_mem_cpy(h, &bt_linfo->afh_map[4], pafh->afh_m, 4);
178 hal_mem_cpy(h, &bt_linfo->afh_map[8], pafh->afh_h, 2);
179 break;
180 case BTC_RPT_TYPE_BT_DEVICE:
181 a2dp->device_name = pdev->dev_name;
182 a2dp->vendor_id = pdev->vendor_id;
183 a2dp->flush_time = pdev->flush_time;
184 break;
185 default:
186 break;
187 }
188 }
189
_chk_btc_report(struct btc_t * btc,struct btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)190 static u32 _chk_btc_report(struct btc_t *btc, struct btf_fwinfo *pfwinfo,
191 u8 *prptbuf, u32 index)
192 {
193 struct btc_dm *dm = &btc->dm;
194 struct rtw_hal_com_t *hal = btc->hal;
195 struct btc_rpt_cmn_info *pcinfo = NULL;
196 struct btc_wl_info *wl = &btc->cx.wl;
197 struct btc_bt_info *bt = &btc->cx.bt;
198 struct fbtc_rpt_ctrl *prpt = NULL;
199 struct fbtc_cysta *pcysta = NULL;
200 u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
201 u16 wl_slot_set = 0, polt_cnt = 0;
202 u32 rpt_len = 0, diff_t, bt_slot_real = 0;
203
204 if (!prptbuf) {
205 pfwinfo->err[BTFRE_INVALID_INPUT]++;
206 return 0;
207 }
208
209 rpt_type = prptbuf[index];
210 rpt_len = (prptbuf[index+2] << 8) + prptbuf[index+1];
211 rpt_content = &prptbuf[index+3];
212
213 switch (rpt_type) {
214 case BTC_RPT_TYPE_CTRL:
215 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
216 pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
217 pcinfo->req_len = sizeof(struct fbtc_rpt_ctrl);
218 pcinfo->req_fver = FCX_BTCRPT_VER;
219 pcinfo->rsp_fver = *rpt_content;
220 break;
221 case BTC_RPT_TYPE_TDMA:
222 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
223 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_tdma.finfo);
224 pcinfo->req_len = sizeof(struct fbtc_1tdma);
225 pcinfo->req_fver = FCX_TDMA_VER;
226 break;
227 case BTC_RPT_TYPE_SLOT:
228 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
229 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
230 pcinfo->req_len = sizeof(struct fbtc_slots);
231 pcinfo->req_fver = FCX_SLOT_VER;
232 break;
233 case BTC_RPT_TYPE_CYSTA:
234 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
235 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
236 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
237 pcinfo->req_len = sizeof(struct fbtc_cysta);
238 pcinfo->req_fver = FCX_CYSTA_VER;
239 break;
240 case BTC_RPT_TYPE_STEP:
241 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
242 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
243 pcinfo->req_len = 8 + sizeof(struct fbtc_step) * FCXDEF_STEP;
244 pcinfo->req_fver = FCX_STEP_VER;
245 break;
246 case BTC_RPT_TYPE_NULLSTA:
247 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
248 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
249 pcinfo->req_len = sizeof(struct fbtc_cynullsta);
250 pcinfo->req_fver = FCX_NULLSTA_VER;
251 break;
252 case BTC_RPT_TYPE_MREG:
253 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
254 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
255 pcinfo->req_len = sizeof(struct fbtc_mreg_val);
256 pcinfo->req_fver = FCX_MREG_VER;
257 break;
258 case BTC_RPT_TYPE_GPIO_DBG:
259 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
260 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
261 pcinfo->req_len = sizeof(struct fbtc_gpio_dbg);
262 pcinfo->req_fver = FCX_GPIODBG_VER;
263 break;
264 case BTC_RPT_TYPE_BT_VER:
265 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
266 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
267 pcinfo->req_len = sizeof(struct fbtc_btver);
268 pcinfo->req_fver = FCX_BTVER_VER;
269 break;
270 case BTC_RPT_TYPE_BT_SCAN:
271 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
272 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
273 pcinfo->req_len = sizeof(struct fbtc_btscan);
274 pcinfo->req_fver = FCX_BTSCAN_VER;
275 break;
276 case BTC_RPT_TYPE_BT_AFH:
277 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
278 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
279 pcinfo->req_len = sizeof(struct fbtc_btafh);
280 pcinfo->req_fver = FCX_BTAFH_VER;
281 break;
282 case BTC_RPT_TYPE_BT_DEVICE:
283 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
284 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
285 pcinfo->req_len = sizeof(struct fbtc_btdevinfo);
286 pcinfo->req_fver = FCX_BTDEVINFO_VER;
287 break;
288 default:
289 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
290 return 0;
291 }
292
293 pcinfo->rsp_fver = *rpt_content;
294 pcinfo->rx_len = rpt_len;
295 pcinfo->rx_cnt++;
296
297 if (rpt_len != pcinfo->req_len) {
298 if (rpt_type < BTC_RPT_TYPE_MAX)
299 pfwinfo->len_mismch |= (0x1 << rpt_type);
300 else
301 pfwinfo->len_mismch |= BIT31;
302
303 pcinfo->valid = 0;
304 return 0;
305 } else if (pcinfo->req_fver != pcinfo->rsp_fver) {
306 if (rpt_type < BTC_RPT_TYPE_MAX)
307 pfwinfo->fver_mismch |= (0x1 << rpt_type);
308 else
309 pfwinfo->fver_mismch |= BIT31;
310 pcinfo->valid = 0;
311 return 0;
312 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
313 pfwinfo->err[BTFRE_EXCEPTION]++;
314 pcinfo->valid = 0;
315 return 0;
316 }
317
318
319 hal_mem_cpy(hal, (void *)pfinfo, (void *)rpt_content, pcinfo->req_len);
320 pcinfo->valid = 1;
321
322 if (rpt_type == BTC_RPT_TYPE_TDMA) {
323 #if BTC_CX_FW_OFFLOAD /* update tdma_now if fw offload for debug */
324 _tdma_cpy(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo.tdma);
325 #else
326 _chk_btc_err(btc, BTC_DCNT_TDMA_NONSYNC,
327 _tdma_cmp(&dm->tdma_now,
328 &pfwinfo->rpt_fbtc_tdma.finfo.tdma));
329 #endif
330 }
331
332 if (rpt_type == BTC_RPT_TYPE_SLOT) {
333 #if BTC_CX_FW_OFFLOAD /* update slot_now if fw offload for debug */
334 _slots_cpy(dm->slot_now, pfwinfo->rpt_fbtc_slots.finfo.slot);
335 #else
336 _chk_btc_err(btc, BTC_DCNT_SLOT_NONSYNC,
337 _tdma_cmp(dm->slot_now,
338 pfwinfo->rpt_fbtc_slots.finfo.slot));
339 #endif
340 }
341
342 if (rpt_type == BTC_RPT_TYPE_CYSTA &&
343 pcysta->cycles >= BTC_CYSTA_CHK_PERIOD) {
344 /* Check Leak-AP */
345 if (pcysta->slot_cnt[CXST_LK] != 0 &&
346 pcysta->leak_slot.cnt_rximr != 0 && dm->tdma_now.rxflctrl) {
347 if (pcysta->slot_cnt[CXST_LK] <
348 BTC_LEAK_AP_TH * pcysta->leak_slot.cnt_rximr)
349 dm->leak_ap = 1;
350 }
351
352 /* Check diff time between real WL slot and W1 slot */
353 if (dm->tdma_now.type != CXTDMA_OFF) {
354 wl_slot_set = dm->slot_now[CXST_W1].dur;
355
356 if (pcysta->cycle_time.tavg[CXT_WL] > wl_slot_set) {
357 diff_t = pcysta->cycle_time.tavg[CXT_WL] -
358 wl_slot_set;
359 _chk_btc_err(btc, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
360 }
361 }
362
363 /* Check diff time between real BT slot and EBT/E5G slot */
364 if (dm->tdma_now.type == CXTDMA_OFF &&
365 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
366 btc->bt_req_len != 0) {
367 bt_slot_real = pcysta->cycle_time.tavg[CXT_BT];
368
369 if (btc->bt_req_len > bt_slot_real) {
370 diff_t = btc->bt_req_len - bt_slot_real;
371 _chk_btc_err(btc, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
372 }
373
374 }
375
376 _chk_btc_err(btc, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
377 _chk_btc_err(btc, BTC_DCNT_B1_FREEZE, pcysta->slot_cnt[CXST_B1]);
378 _chk_btc_err(btc, BTC_DCNT_CYCLE_FREEZE, (u32)pcysta->cycles);
379 }
380
381 if (rpt_type == BTC_RPT_TYPE_CTRL) {
382 prpt = &pfwinfo->rpt_ctrl.finfo;
383 btc->fwinfo.rpt_en_map = prpt->rpt_info.en;
384 wl->ver_info.fw_coex = prpt->wl_fw_info.cx_ver;
385 wl->ver_info.fw = prpt->wl_fw_info.fw_ver;
386 dm->wl_fw_cx_offload = !!(prpt->wl_fw_info.cx_offload);
387
388 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
389 dm->error.map.offload_mismatch = true;
390 else
391 dm->error.map.offload_mismatch = false;
392
393 if (prpt->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
394 bt->rfk_info.map.timeout = 1;
395 else
396 bt->rfk_info.map.timeout = 0;
397
398 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
399
400 _chk_btc_err(btc, BTC_DCNT_RPT_FREEZE,
401 pfwinfo->event[BTF_EVNT_RPT]);
402
403 /* To avoid I/O if WL LPS or power-off */
404 if (wl->status.map.lps != BTC_LPS_RF_OFF &&
405 !wl->status.map.rf_off) {
406 btc->chip->ops->update_bt_cnt(btc);
407 _chk_btc_err(btc, BTC_DCNT_BTCNT_FREEZE, 0);
408 rtw_hal_mac_get_bt_polt_cnt(btc->hal, HW_PHY_0,
409 &polt_cnt);
410 btc->cx.cnt_bt[BTC_BCNT_POLUT] = polt_cnt;
411 }
412 }
413
414 if (rpt_type >= BTC_RPT_TYPE_BT_VER &&
415 rpt_type <= BTC_RPT_TYPE_BT_DEVICE)
416 _update_bt_report(btc, rpt_type, pfinfo);
417
418 return (rpt_len + BTC_RPT_HDR_SIZE);
419 }
420
_parse_btc_report(struct btc_t * btc,struct btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)421 static void _parse_btc_report(struct btc_t *btc, struct btf_fwinfo *pfwinfo,
422 u8 *pbuf, u32 buf_len)
423 {
424 u32 index = 0, rpt_len = 0;
425
426 while (pbuf) {
427 if (index+2 >= RTW_PHL_BTC_FWINFO_BUF)
428 break;
429 /* At least 3 bytes: type(1) & len(2) */
430 rpt_len = (pbuf[index+2] << 8) + pbuf[index+1];
431 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
432 break;
433
434 rpt_len = _chk_btc_report(btc, pfwinfo, pbuf, index);
435 if (!rpt_len)
436 break;
437 index += rpt_len;
438 }
439 }
440
_append_tdma(struct btc_t * btc,bool force_exec)441 static void _append_tdma(struct btc_t *btc, bool force_exec)
442 {
443 struct btc_dm *dm = &btc->dm;
444 struct btf_tlv *tlv = NULL;
445 struct fbtc_1tdma *v = NULL;
446 u16 len = btc->policy_len;
447
448 if (!force_exec && !_tdma_cmp(&dm->tdma, &dm->tdma_now)) {
449 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): tdma no change!\n",
450 __func__);
451 return;
452 }
453
454 tlv = (struct btf_tlv *)&btc->policy[len];
455 tlv->type = CXPOLICY_TDMA;
456 tlv->len = sizeof(struct fbtc_1tdma);
457 v = (struct fbtc_1tdma *)&tlv->val[0];
458 v->fver = FCX_TDMA_VER;
459
460 _tdma_cpy(&v->tdma, &dm->tdma);
461
462 btc->policy_len = len + 2 + sizeof(struct fbtc_1tdma);
463
464 PHL_INFO("[BTC], %s: type:%d, rxflctrl=%d, txflctrl=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d, rxflctrl_role=0x%x\n",
465 __func__, dm->tdma.type, dm->tdma.rxflctrl, dm->tdma.txflctrl,
466 dm->tdma.wtgle_n, dm->tdma.leak_n, dm->tdma.ext_ctrl,
467 dm->tdma.rxflctrl_role);
468 }
469
_append_slot(struct btc_t * btc,bool force_exec)470 static void _append_slot(struct btc_t *btc, bool force_exec)
471 {
472 struct btc_dm *dm = &btc->dm;
473 struct btf_tlv *tlv = NULL;
474 struct fbtc_1slot *v = NULL;
475 u16 len = 0;
476 u8 i, cnt = 0;
477
478 for (i = 0; i < CXST_MAX; i++) {
479 if (!force_exec && !_slot_cmp(&dm->slot[i], &dm->slot_now[i]))
480 continue;
481
482 len = btc->policy_len;
483
484 tlv = (struct btf_tlv *)&btc->policy[len];
485 tlv->type = CXPOLICY_SLOT;
486 tlv->len = sizeof(struct fbtc_1slot);
487 v = (struct fbtc_1slot *)&tlv->val[0];
488
489 v->fver = FCX_SLOT_VER;
490 v->sid = i;
491 _slot_cpy(&v->slot, &dm->slot[i]);
492
493 PHL_INFO("[BTC], %s: slot-%d: dur=%d, table=0x%08x, type=%d\n",
494 __func__, i,dm->slot[i].dur, dm->slot[i].cxtbl,
495 dm->slot[i].cxtype);
496 cnt++;
497 btc->policy_len = len + 2 + sizeof(struct fbtc_1slot);
498 }
499
500 if (cnt > 0)
501 PHL_INFO("[BTC], %s: slot update (cnt=%d)!!\n", __func__, cnt);
502 }
503
504 /*
505 * extern functions
506 */
507
hal_btc_fw_en_rpt(struct btc_t * btc,u32 rpt_map,u32 rpt_state)508 void hal_btc_fw_en_rpt(struct btc_t *btc, u32 rpt_map, u32 rpt_state)
509 {
510 struct btc_ops *ops = btc->ops;
511 struct btf_set_report r = {0};
512 struct btf_fwinfo* fwinfo = &btc->fwinfo;
513 u32 val = 0;
514 u8 en;
515
516 if (!ops || !ops->fw_cmd)
517 return;
518
519 en = rpt_state & 0x1;
520 if (en)
521 val = fwinfo->rpt_en_map | rpt_map;
522 else
523 val = fwinfo->rpt_en_map & (~rpt_map);
524
525 if (val == fwinfo->rpt_en_map)
526 return;
527
528 fwinfo->rpt_en_map = val;
529
530 r.fver = FCX_BTCRPT_VER;
531 r.enable = val;
532 r.para = en;
533
534 ops->fw_cmd(btc, BTFC_SET, SET_REPORT_EN, (u8 *)&r, sizeof(r));
535 }
536
hal_btc_fw_set_slots(struct btc_t * btc,u8 num,struct fbtc_slot * s)537 void hal_btc_fw_set_slots(struct btc_t *btc, u8 num, struct fbtc_slot *s)
538 {
539 #if !BTC_CX_FW_OFFLOAD
540 struct rtw_hal_com_t *h = btc->hal;
541 struct btc_ops *ops = btc->ops;
542 struct btf_set_slot_table *tbl = NULL;
543 u8 *ptr = NULL;
544 u16 n = 0;
545
546 if (!ops || !ops->fw_cmd)
547 return;
548
549 n = (sizeof(struct fbtc_slot) * num) + sizeof(*tbl) - 1;
550 tbl = hal_mem_alloc(h, n);
551 if (!tbl)
552 return;
553
554 tbl->fver = FCX_SLOT_VER;
555 tbl->tbl_num = num;
556 ptr = &tbl->buf[0];
557 hal_mem_cpy(h, (void*)ptr, s, num * sizeof(struct fbtc_slot));
558
559 ops->fw_cmd(btc, BTFC_SET, SET_SLOT_TABLE, (u8*)tbl, n);
560 hal_mem_free(h, (void*)tbl, n);
561 #endif
562 }
563
564 /* set RPT_EN_MREG = 0 to stop 2s monitor timer in WL FW,
565 * before SET_MREG_TABLE, and set RPT_EN_MREG = 1 after
566 * SET_MREG_TABLE
567 */
hal_btc_fw_set_monreg(struct btc_t * btc)568 void hal_btc_fw_set_monreg(struct btc_t *btc)
569 {
570 struct rtw_hal_com_t *h = btc->hal;
571 struct btc_ops *ops = btc->ops;
572 struct btf_set_mon_reg *monreg = NULL;
573 u8 n, *ptr = NULL, ulen;
574 u16 sz = 0;
575
576 if (!ops || !ops->fw_cmd)
577 return;
578
579 n = btc->chip->mon_reg_num;
580
581 if (n > CXMREG_MAX) {
582 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], mon reg count %d > %d\n",
583 n, CXMREG_MAX);
584 return;
585 }
586
587 ulen = sizeof(struct fbtc_mreg);
588 sz = (ulen * n) + sizeof(*monreg) - 1;
589 monreg = hal_mem_alloc(h, sz);
590 if (!monreg)
591 return;
592
593 monreg->fver = FCX_MREG_VER;
594 monreg->reg_num = n;
595 ptr = &monreg->buf[0];
596 hal_mem_cpy(h, (void *)ptr, btc->chip->mon_reg, n * ulen);
597
598 ops->fw_cmd(btc, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz);
599 hal_mem_free(h, (void *)monreg, sz);
600 hal_btc_fw_en_rpt(btc, RPT_EN_MREG, 1);
601 }
602
hal_btc_fw_set_1tdma(struct btc_t * btc,u16 len,u8 * buf)603 bool hal_btc_fw_set_1tdma(struct btc_t *btc, u16 len, u8 *buf)
604 { /* for wlcli manual control */
605 struct btc_dm *dm = &btc->dm;
606
607 if (len != sizeof(struct fbtc_tdma)) {
608 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return because len != %d\n",
609 __func__, (int)sizeof(struct fbtc_tdma));
610 return false;
611 } else if (buf[0] >= CXTDMA_MAX) {
612 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return because tdma_type >= %d\n",
613 __func__, CXTDMA_MAX);
614 return false;
615 }
616
617 _tdma_cpy(&dm->tdma, buf);
618 return true;
619 }
620
hal_btc_fw_set_1slot(struct btc_t * btc,u16 len,u8 * buf)621 bool hal_btc_fw_set_1slot(struct btc_t *btc, u16 len, u8 *buf)
622 { /* for wlcli manual control */
623 struct btc_dm *dm = &btc->dm;
624
625 if (len != sizeof(struct fbtc_slot) + 1) {
626 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return because len != %d\n",
627 __func__, (int)sizeof(struct fbtc_slot) + 1);
628 return false;
629 } else if (buf[0] >= CXST_MAX) {
630 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return because slot_id >= %d\n",
631 __func__, CXST_MAX);
632 return false;
633 }
634
635 _slot_cpy(&dm->slot[buf[0]], &buf[1]);
636 return true;
637 }
638
hal_btc_fw_set_policy(struct btc_t * btc,bool force_exec,u16 policy_type,const char * action)639 bool hal_btc_fw_set_policy(struct btc_t *btc, bool force_exec, u16 policy_type,
640 const char* action)
641 {
642 struct btc_dm *dm = &btc->dm;
643 struct btc_ops *ops = btc->ops;
644
645 if (!ops || !ops->fw_cmd)
646 return false;
647
648 _act_cpy(dm->run_action, (char*)action);
649 _update_dm_step(btc, action);
650 _update_dm_step(btc, id_to_str(BTC_STR_POLICY, (u32)policy_type));
651
652 btc->policy_len = 0; /* clear length before append */
653 btc->policy_type = policy_type;
654
655 _append_tdma(btc, force_exec);
656 _append_slot(btc, force_exec);
657
658 if (btc->policy_len == 0 || btc->policy_len > BTC_POLICY_MAXLEN)
659 return false;
660
661 PHL_INFO("[BTC], %s(): action=%s -> policy type/len: 0x%04x/%d\n",
662 __func__, action, policy_type, btc->policy_len);
663
664 if (dm->tdma.rxflctrl == CXFLC_NULLP)
665 btc->hal->btc_ctrl.lps = 1;
666 else
667 btc->hal->btc_ctrl.lps = 0;
668
669 if (btc->hal->btc_ctrl.lps == 1)
670 hal_btc_notify_ps_tdma(btc, btc->hal->btc_ctrl.lps);
671
672 ops->fw_cmd(btc, BTFC_SET, SET_CX_POLICY, btc->policy, btc->policy_len);
673
674 _tdma_cpy(&dm->tdma_now, &dm->tdma);
675 _slots_cpy(dm->slot_now, dm->slot);
676
677 if (btc->hal->btc_ctrl.lps == 0)
678 hal_btc_notify_ps_tdma(btc, btc->hal->btc_ctrl.lps);
679
680 return true;
681 }
682
hal_btc_fw_set_gpio_dbg(struct btc_t * btc,u8 type,u32 val)683 void hal_btc_fw_set_gpio_dbg(struct btc_t *btc, u8 type, u32 val)
684 {
685 struct rtw_hal_com_t *h = btc->hal;
686 struct btc_ops *ops = btc->ops;
687 u8 data[7] = {0}, len = 0;
688
689 if (!ops || !ops->fw_cmd || type >= CXDGPIO_MAX)
690 return;
691
692 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s()\n", __func__);
693
694 data[0] = FCX_GPIODBG_VER;
695 data[1] = 0;
696 data[2] = type;
697
698 switch(type) {
699 case CXDGPIO_EN_MAP:
700 len = sizeof(u32) + 3;
701 hal_mem_cpy(h, &data[3], &val, sizeof(u32));
702 break;
703 case CXDGPIO_MUX_MAP:
704 len = sizeof(8) * 2 + 3;
705 data[3] = (u8)(val & bMASKB0);
706 data[4] = (u8)((val & bMASKB1) >> 8);
707 break;
708 default:
709 return;
710 }
711
712 ops->fw_cmd(btc, BTFC_SET, SET_GPIO_DBG, data, len);
713 }
714
hal_btc_fw_set_drv_info(struct btc_t * btc,u8 type)715 void hal_btc_fw_set_drv_info(struct btc_t *btc, u8 type)
716 {
717 struct rtw_hal_com_t *h = btc->hal;
718 struct btc_wl_info *wl = &btc->cx.wl;
719 struct btc_dm *dm = &btc->dm;
720 struct btc_ops *ops = btc->ops;
721 u8 buf[256] = {0};
722 u8 sz = 0, n = 0;
723
724 if (!ops || !ops->fw_cmd || type >= CXDRVINFO_MAX)
725 return;
726
727 switch (type) {
728 case CXDRVINFO_INIT:
729 n = sizeof(dm->init_info);
730 sz = n + 2;
731
732 if (sz > sizeof(buf))
733 return;
734
735 buf[0] = CXDRVINFO_INIT;
736 buf[1] = n;
737 hal_mem_cpy(h, (void *)&buf[2], &dm->init_info, n);
738 break;
739 case CXDRVINFO_ROLE:
740 n = sizeof(wl->role_info);
741 sz = n + 2;
742
743 if (sz > sizeof(buf))
744 return;
745
746 buf[0] = CXDRVINFO_ROLE;
747 buf[1] = n;
748 hal_mem_cpy(h, (void *)&buf[2], &wl->role_info, n);
749 break;
750 case CXDRVINFO_CTRL:
751 n = sizeof(btc->ctrl);
752 sz = n + 2;
753
754 if (sz > sizeof(buf))
755 return;
756
757 buf[0] = CXDRVINFO_CTRL;
758 buf[1] = n;
759 hal_mem_cpy(h, (void *)&buf[2], &btc->ctrl, n);
760 break;
761 case CXDRVINFO_RFK:
762 n = sizeof(wl->rfk_info);
763 sz = n + 2;
764
765 if (sz > sizeof(buf))
766 return;
767
768 buf[0] = CXDRVINFO_RFK;
769 buf[1] = n;
770 hal_mem_cpy(h, (void *)&buf[2], &wl->rfk_info, n);
771 break;
772 #if BTC_CX_FW_OFFLOAD
773 case CXDRVINFO_DBCC:
774 n = sizeof(wl->dbcc_info);
775 sz = n + 2;
776
777 if (sz > sizeof(buf))
778 return;
779
780 buf[0] = CXDRVINFO_DBCC;
781 buf[1] = n;
782 hal_mem_cpy(h, (void *)&buf[2], &wl->dbcc_info, n);
783 break;
784 case CXDRVINFO_SMAP:
785 n = sizeof(wl->status);
786 sz = n + 2;
787
788 if (sz > sizeof(buf))
789 return;
790
791 buf[0] = CXDRVINFO_SMAP;
792 buf[1] = n;
793 hal_mem_cpy(h, (void *)&buf[2], &wl->status, n);
794 break;
795 case CXDRVINFO_RUN:
796 n = BTC_RSN_MAXLEN;
797 sz = n + 2;
798
799 if (sz > sizeof(buf))
800 return;
801
802 buf[0] = CXDRVINFO_RUN;
803 buf[1] = n;
804 hal_mem_cpy(h, (void *)&buf[2], dm->run_reason, n);
805 break;
806 case CXDRVINFO_SCAN:
807 n = sizeof(wl->scan_info);
808 sz = n + 2;
809
810 if (sz > sizeof(buf))
811 return;
812
813 buf[0] = CXDRVINFO_SCAN;
814 buf[1] = n;
815 hal_mem_cpy(h, (void *)&buf[2], &wl->scan_info, n);
816 break;
817 #endif
818 default:
819 return;
820 }
821
822 ops->fw_cmd(btc, BTFC_SET, SET_DRV_INFO, (u8*)buf, sz);
823 }
824
hal_btc_fw_set_drv_event(struct btc_t * btc,u8 type)825 void hal_btc_fw_set_drv_event(struct btc_t *btc, u8 type)
826 {
827 struct btc_ops *ops = btc->ops;
828
829 if (!ops || !ops->fw_cmd)
830 return;
831
832 ops->fw_cmd(btc, BTFC_SET, SET_DRV_EVENT, &type, 1);
833 }
834
hal_btc_fw_set_bt(struct btc_t * btc,u8 type,u16 len,u8 * buf)835 void hal_btc_fw_set_bt(struct btc_t *btc, u8 type, u16 len, u8* buf)
836 {
837 struct btc_ops *ops = btc->ops;
838
839 if (!ops || !ops->fw_cmd ||
840 (type < SET_BT_WREG_ADDR || type > SET_BT_GOLDEN_RX_RANGE))
841 return;
842
843 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s()\n", __func__);
844
845 ops->fw_cmd(btc, BTFC_SET, type, buf, len);
846 }
847
hal_btc_fw_event(struct btc_t * btc,u8 evt_id,void * data,u32 len)848 void hal_btc_fw_event(struct btc_t *btc, u8 evt_id, void *data, u32 len)
849 {
850 struct btf_fwinfo *pfwinfo = &btc->fwinfo;
851
852 if (!len || !data)
853 return;
854
855 switch (evt_id) {
856 case BTF_EVNT_RPT:
857 _parse_btc_report(btc, pfwinfo, data, len);
858 break;
859 default:
860 break;
861 }
862 }
863
864 #endif
865