xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/hal_g6/btc/halbtc_fw.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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