xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8188fu/hal/phydm/phydm_ccx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 
26 #include "mp_precomp.h"
27 #include "phydm_precomp.h"
28 
phydm_ccx_hw_restart(void * dm_void)29 void phydm_ccx_hw_restart(void *dm_void)
30 			  /*@Will Restart NHM/CLM/FAHM simultaneously*/
31 {
32 	struct dm_struct *dm = (struct dm_struct *)dm_void;
33 	u32 reg1 = 0;
34 
35 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
36 		reg1 = R_0x994;
37 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
38 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
39 		reg1 = R_0x1e60;
40 	#endif
41 	else
42 		reg1 = R_0x890;
43 
44 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
45 	/*@disable NHM,CLM, FAHM*/
46 	odm_set_bb_reg(dm, reg1, 0x7, 0x0);
47 	odm_set_bb_reg(dm, reg1, BIT(8), 0x0);
48 	odm_set_bb_reg(dm, reg1, BIT(8), 0x1);
49 }
50 
51 #ifdef FAHM_SUPPORT
52 
phydm_hw_divider(void * dm_void,u16 numerator,u16 denumerator)53 u16 phydm_hw_divider(void *dm_void, u16 numerator, u16 denumerator)
54 {
55 	struct dm_struct *dm = (struct dm_struct *)dm_void;
56 	u16 result = DEVIDER_ERROR;
57 	u32 tmp_u32 = ((numerator << 16) | denumerator);
58 	u32 reg_devider_input;
59 	u32 reg;
60 	u8 i;
61 
62 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
63 
64 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
65 		reg_devider_input = 0x1cbc;
66 		reg = 0x1f98;
67 	} else {
68 		reg_devider_input = 0x980;
69 		reg = 0x9f0;
70 	}
71 
72 	odm_set_bb_reg(dm, reg_devider_input, MASKDWORD, tmp_u32);
73 
74 	for (i = 0; i < 10; i++) {
75 		ODM_delay_ms(1);
76 		if (odm_get_bb_reg(dm, reg, BIT(24))) {
77 		/*@Chk HW rpt is ready*/
78 
79 			result = (u16)odm_get_bb_reg(dm, reg, MASKBYTE2);
80 			break;
81 		}
82 	}
83 	return result;
84 }
85 
phydm_fahm_trigger(void * dm_void,u16 tgr_period)86 void phydm_fahm_trigger(void *dm_void, u16 tgr_period)
87 { /*@unit (4us)*/
88 	struct dm_struct *dm = (struct dm_struct *)dm_void;
89 	u32 fahm_reg1;
90 
91 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
92 		odm_set_bb_reg(dm, R_0x1cf8, 0xffff00, tgr_period);
93 
94 		fahm_reg1 = 0x994;
95 	} else {
96 		odm_set_bb_reg(dm, R_0x978, 0xff000000, (tgr_period & 0xff));
97 		odm_set_bb_reg(dm, R_0x97c, 0xff, (tgr_period & 0xff00) >> 8);
98 
99 		fahm_reg1 = 0x890;
100 	}
101 
102 	odm_set_bb_reg(dm, fahm_reg1, BIT(2), 0);
103 	odm_set_bb_reg(dm, fahm_reg1, BIT(2), 1);
104 }
105 
phydm_fahm_set_valid_cnt(void * dm_void,u8 numerator_sel,u8 denominator_sel)106 void phydm_fahm_set_valid_cnt(void *dm_void, u8 numerator_sel,
107 			      u8 denominator_sel)
108 {
109 	struct dm_struct *dm = (struct dm_struct *)dm_void;
110 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
111 	u32 fahm_reg1;
112 
113 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
114 
115 	if (ccx_info->fahm_nume_sel == numerator_sel &&
116 	    ccx_info->fahm_denom_sel == denominator_sel) {
117 		PHYDM_DBG(dm, DBG_ENV_MNTR, "no need to update\n");
118 		return;
119 	}
120 
121 	ccx_info->fahm_nume_sel = numerator_sel;
122 	ccx_info->fahm_denom_sel = denominator_sel;
123 
124 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
125 		fahm_reg1 = 0x994;
126 	else
127 		fahm_reg1 = 0x890;
128 
129 	odm_set_bb_reg(dm, fahm_reg1, 0xe0, numerator_sel);
130 	odm_set_bb_reg(dm, fahm_reg1, 0x7000, denominator_sel);
131 }
132 
phydm_fahm_get_result(void * dm_void)133 void phydm_fahm_get_result(void *dm_void)
134 {
135 	struct dm_struct *dm = (struct dm_struct *)dm_void;
136 	u16 fahm_cnt[12]; /*packet count*/
137 	u16 fahm_rpt[12]; /*percentage*/
138 	u16 denominator; /*@fahm_denominator packet count*/
139 	u32 reg_rpt, reg_rpt_2;
140 	u32 reg_tmp;
141 	boolean is_ready = false;
142 	u8 i;
143 
144 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
145 
146 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
147 		reg_rpt = 0x1f80;
148 		reg_rpt_2 = 0x1f98;
149 	} else {
150 		reg_rpt = 0x9d8;
151 		reg_rpt_2 = 0x9f0;
152 	}
153 
154 	for (i = 0; i < 3; i++) {
155 		if (odm_get_bb_reg(dm, reg_rpt_2, BIT(31))) {
156 		/*@Chk HW rpt is ready*/
157 			is_ready = true;
158 			break;
159 		}
160 		ODM_delay_ms(1);
161 	}
162 
163 	if (!is_ready)
164 		return;
165 
166 	/*@Get FAHM Denominator*/
167 	denominator = (u16)odm_get_bb_reg(dm, reg_rpt_2, MASKLWORD);
168 
169 	PHYDM_DBG(dm, DBG_ENV_MNTR, "Reg[0x%x] fahm_denmrtr = %d\n", reg_rpt_2,
170 		  denominator);
171 
172 	/*@Get FAHM nemerator*/
173 	for (i = 0; i < 6; i++) {
174 		reg_tmp = odm_get_bb_reg(dm, reg_rpt + (i << 2), MASKDWORD);
175 
176 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Reg[0x%x] fahm_denmrtr = %d\n",
177 			  reg_rpt + (i * 4), reg_tmp);
178 
179 		fahm_cnt[i * 2] = (u16)(reg_tmp & MASKLWORD);
180 		fahm_cnt[i * 2 + 1] = (u16)((reg_tmp & MASKHWORD) >> 16);
181 	}
182 
183 	for (i = 0; i < 12; i++)
184 		fahm_rpt[i] = phydm_hw_divider(dm, fahm_cnt[i], denominator);
185 
186 	PHYDM_DBG(dm, DBG_ENV_MNTR,
187 		  "FAHM_RPT_cnt[10:0]=[%d, %d, %d, %d, %d(IGI), %d, %d, %d, %d, %d, %d, %d]\n",
188 		  fahm_cnt[11], fahm_cnt[10], fahm_cnt[9],
189 		  fahm_cnt[8], fahm_cnt[7], fahm_cnt[6],
190 		  fahm_cnt[5], fahm_cnt[4], fahm_cnt[3],
191 		  fahm_cnt[2], fahm_cnt[1], fahm_cnt[0]);
192 
193 	PHYDM_DBG(dm, DBG_ENV_MNTR,
194 		  "FAHM_RPT[10:0]=[%d, %d, %d, %d, %d(IGI), %d, %d, %d, %d, %d, %d, %d]\n",
195 		  fahm_rpt[11], fahm_rpt[10], fahm_rpt[9], fahm_rpt[8],
196 		  fahm_rpt[7], fahm_rpt[6], fahm_rpt[5], fahm_rpt[4],
197 		  fahm_rpt[3], fahm_rpt[2], fahm_rpt[1], fahm_rpt[0]);
198 }
199 
phydm_fahm_set_th_by_igi(void * dm_void,u8 igi)200 void phydm_fahm_set_th_by_igi(void *dm_void, u8 igi)
201 {
202 	struct dm_struct *dm = (struct dm_struct *)dm_void;
203 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
204 	u32 val = 0;
205 	u8 f_th[11]; /*@FAHM Threshold*/
206 	u8 rssi_th[11]; /*@in RSSI scale*/
207 	u8 th_gap = 2 * IGI_TO_NHM_TH_MULTIPLIER; /*unit is 0.5dB for FAHM*/
208 	u8 i;
209 
210 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
211 
212 	if (ccx_info->env_mntr_igi == igi) {
213 		PHYDM_DBG(dm, DBG_ENV_MNTR,
214 			  "No need to update FAHM_th, IGI=0x%x\n",
215 			  ccx_info->env_mntr_igi);
216 		return;
217 	}
218 
219 	ccx_info->env_mntr_igi = igi; /*@bkp IGI*/
220 
221 	if (igi >= CCA_CAP)
222 		f_th[0] = (igi - CCA_CAP) * IGI_TO_NHM_TH_MULTIPLIER;
223 	else
224 		f_th[0] = 0;
225 
226 	rssi_th[0] = igi - 10 - CCA_CAP;
227 
228 	for (i = 1; i <= 10; i++) {
229 		f_th[i] = f_th[0] + th_gap * i;
230 		rssi_th[i] = rssi_th[0] + (i << 1);
231 	}
232 
233 	PHYDM_DBG(dm, DBG_ENV_MNTR,
234 		  "FAHM_RSSI_th[10:0]=[%d, %d, %d, (IGI)%d, %d, %d, %d, %d, %d, %d, %d]\n",
235 		  rssi_th[10], rssi_th[9], rssi_th[8], rssi_th[7], rssi_th[6],
236 		  rssi_th[5], rssi_th[4], rssi_th[3], rssi_th[2], rssi_th[1],
237 		  rssi_th[0]);
238 
239 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
240 		val = BYTE_2_DWORD(0, f_th[2], f_th[1], f_th[0]);
241 		odm_set_bb_reg(dm, R_0x1c38, 0xffffff00, val);
242 		val = BYTE_2_DWORD(0, f_th[5], f_th[4], f_th[3]);
243 		odm_set_bb_reg(dm, R_0x1c78, 0xffffff00, val);
244 		val = BYTE_2_DWORD(0, 0, f_th[7], f_th[6]);
245 		odm_set_bb_reg(dm, R_0x1c7c, 0xffff0000, val);
246 		val = BYTE_2_DWORD(0, f_th[10], f_th[9], f_th[8]);
247 		odm_set_bb_reg(dm, R_0x1cb8, 0xffffff00, val);
248 	} else {
249 		val = BYTE_2_DWORD(f_th[3], f_th[2], f_th[1], f_th[0]);
250 		odm_set_bb_reg(dm, R_0x970, MASKDWORD, val);
251 		val = BYTE_2_DWORD(f_th[7], f_th[6], f_th[5], f_th[4]);
252 		odm_set_bb_reg(dm, R_0x974, MASKDWORD, val);
253 		val = BYTE_2_DWORD(0, f_th[10], f_th[9], f_th[8]);
254 		odm_set_bb_reg(dm, R_0x978, 0xffffff, val);
255 	}
256 }
257 
phydm_fahm_init(void * dm_void)258 void phydm_fahm_init(void *dm_void)
259 {
260 	struct dm_struct *dm = (struct dm_struct *)dm_void;
261 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
262 	u32 fahm_reg1;
263 	u8 denumerator_sel = 0;
264 
265 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
266 	PHYDM_DBG(dm, DBG_ENV_MNTR, "IGI=0x%x\n",
267 		  dm->dm_dig_table.cur_ig_value);
268 
269 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
270 		fahm_reg1 = 0x994;
271 	else
272 		fahm_reg1 = 0x890;
273 
274 	ccx_info->fahm_period = 65535;
275 
276 	odm_set_bb_reg(dm, fahm_reg1, 0x6, 3); /*@FAHM HW block enable*/
277 
278 	denumerator_sel = FAHM_INCLD_FA | FAHM_INCLD_CRC_OK | FAHM_INCLD_CRC_ER;
279 	phydm_fahm_set_valid_cnt(dm, FAHM_INCLD_FA, denumerator_sel);
280 	phydm_fahm_set_th_by_igi(dm, dm->dm_dig_table.cur_ig_value);
281 }
282 
phydm_fahm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)283 void phydm_fahm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
284 		    u32 *_out_len)
285 {
286 	struct dm_struct *dm = (struct dm_struct *)dm_void;
287 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
288 	char help[] = "-h";
289 	u32 var1[10] = {0};
290 	u32 used = *_used;
291 	u32 out_len = *_out_len;
292 	u32 i;
293 
294 	for (i = 0; i < 2; i++) {
295 		if (input[i + 1])
296 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
297 	}
298 
299 	if ((strcmp(input[1], help) == 0)) {
300 		PDM_SNPF(out_len, used, output + used, out_len - used,
301 			 "{1: trigger, 2:get result}\n");
302 		PDM_SNPF(out_len, used, output + used, out_len - used,
303 			 "{3: MNTR mode sel} {1: driver, 2. FW}\n");
304 		return;
305 	} else if (var1[0] == 1) { /* Set & trigger CLM */
306 
307 		phydm_fahm_set_th_by_igi(dm, dm->dm_dig_table.cur_ig_value);
308 		phydm_fahm_trigger(dm, ccx_info->fahm_period);
309 		PDM_SNPF(out_len, used, output + used, out_len - used,
310 			 "Monitor FAHM for %d * 4us\n", ccx_info->fahm_period);
311 
312 	} else if (var1[0] == 2) { /* @Get CLM results */
313 
314 		phydm_fahm_get_result(dm);
315 		PDM_SNPF(out_len, used, output + used, out_len - used,
316 			 "FAHM_result=%d us\n", (ccx_info->clm_result << 2));
317 
318 	} else {
319 		PDM_SNPF(out_len, used, output + used, out_len - used,
320 			 "Error\n");
321 	}
322 
323 	*_used = used;
324 	*_out_len = out_len;
325 }
326 
327 #endif /*@#ifdef FAHM_SUPPORT*/
328 
329 #ifdef NHM_SUPPORT
330 
phydm_nhm_racing_release(void * dm_void)331 void phydm_nhm_racing_release(void *dm_void)
332 {
333 	struct dm_struct *dm = (struct dm_struct *)dm_void;
334 	struct ccx_info *ccx = &dm->dm_ccx_info;
335 	u32 value32 = 0;
336 
337 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
338 	PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->nhm_set_lv);
339 
340 	ccx->nhm_ongoing = false;
341 	ccx->nhm_set_lv = NHM_RELEASE;
342 
343 	if (!(ccx->nhm_app == NHM_BACKGROUND || ccx->nhm_app == NHM_ACS)) {
344 		phydm_pause_func(dm, F00_DIG, PHYDM_RESUME,
345 				 PHYDM_PAUSE_LEVEL_1, 1, &value32);
346 	}
347 
348 	ccx->nhm_app = NHM_BACKGROUND;
349 }
350 
phydm_nhm_racing_ctrl(void * dm_void,enum phydm_nhm_level nhm_lv)351 u8 phydm_nhm_racing_ctrl(void *dm_void, enum phydm_nhm_level nhm_lv)
352 {
353 	struct dm_struct *dm = (struct dm_struct *)dm_void;
354 	struct ccx_info *ccx = &dm->dm_ccx_info;
355 	u8 set_result = PHYDM_SET_SUCCESS;
356 	/*@acquire to control NHM API*/
357 
358 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_ongoing=%d, lv:(%d)->(%d)\n",
359 		  ccx->nhm_ongoing, ccx->nhm_set_lv, nhm_lv);
360 	if (ccx->nhm_ongoing) {
361 		if (nhm_lv <= ccx->nhm_set_lv) {
362 			set_result = PHYDM_SET_FAIL;
363 		} else {
364 			phydm_ccx_hw_restart(dm);
365 			ccx->nhm_ongoing = false;
366 		}
367 	}
368 
369 	if (set_result)
370 		ccx->nhm_set_lv = nhm_lv;
371 
372 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm racing success=%d\n", set_result);
373 	return set_result;
374 }
375 
phydm_nhm_trigger(void * dm_void)376 void phydm_nhm_trigger(void *dm_void)
377 {
378 	struct dm_struct *dm = (struct dm_struct *)dm_void;
379 	struct ccx_info *ccx = &dm->dm_ccx_info;
380 	u32 nhm_reg1 = 0;
381 
382 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
383 		nhm_reg1 = R_0x994;
384 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
385 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
386 		nhm_reg1 = R_0x1e60;
387 	#endif
388 	else
389 		nhm_reg1 = R_0x890;
390 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
391 
392 	/* @Trigger NHM*/
393 	pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
394 	pdm_set_reg(dm, nhm_reg1, BIT(1), 1);
395 	ccx->nhm_trigger_time = dm->phydm_sys_up_time;
396 	ccx->nhm_rpt_stamp++;
397 	ccx->nhm_ongoing = true;
398 }
399 
400 boolean
phydm_nhm_check_rdy(void * dm_void)401 phydm_nhm_check_rdy(void *dm_void)
402 {
403 	struct dm_struct *dm = (struct dm_struct *)dm_void;
404 	boolean is_ready = false;
405 	u32 reg1 = 0, reg1_bit = 0;
406 
407 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
408 		reg1 = R_0xfb4;
409 		reg1_bit = 16;
410 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
411 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
412 		reg1 = R_0x2d4c;
413 		reg1_bit = 16;
414 	#endif
415 	} else {
416 		reg1 = R_0x8b4;
417 		if (dm->support_ic_type & (ODM_RTL8710B | ODM_RTL8721D |
418 					ODM_RTL8710C))
419 			reg1_bit = 25;
420 		else
421 			reg1_bit = 17;
422 	}
423 	if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
424 		is_ready = true;
425 
426 	PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM rdy=%d\n", is_ready);
427 
428 	return is_ready;
429 }
430 
phydm_nhm_cal_wgt_avg(void * dm_void,u8 start_i,u8 end_i,u8 n_sum)431 u8 phydm_nhm_cal_wgt_avg(void *dm_void, u8 start_i, u8 end_i, u8 n_sum)
432 {
433 	struct dm_struct *dm = (struct dm_struct *)dm_void;
434 	struct ccx_info *ccx = &dm->dm_ccx_info;
435 	u8 i = 0;
436 	u32 noise_tmp = 0;
437 	u8 noise = 0;
438 	u32 nhm_valid = 0;
439 
440 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
441 
442 	if (n_sum == 0) {
443 		PHYDM_DBG(dm, DBG_ENV_MNTR,
444 			  "n_sum = 0, don't need to update noise\n");
445 		return 0x0;
446 	} else if (end_i > NHM_RPT_NUM - 1) {
447 		PHYDM_DBG(dm, DBG_ENV_MNTR,
448 			  "[WARNING]end_i is larger than 11!!\n");
449 		return 0x0;
450 	}
451 
452 	for (i = start_i; i <= end_i; i++) {
453 		if (i == 0)
454 			noise_tmp += ccx->nhm_result[0] *
455 				     MAX_2(ccx->nhm_th[0] - 2, 0);
456 		else if (i == (NHM_RPT_NUM - 1))
457 			noise_tmp += ccx->nhm_result[NHM_RPT_NUM - 1] *
458 				     (ccx->nhm_th[NHM_TH_NUM - 1] + 2);
459 		else
460 			noise_tmp += ccx->nhm_result[i] *
461 				     (ccx->nhm_th[i - 1] + ccx->nhm_th[i]) >> 1;
462 	}
463 
464 	/* protection for the case of minus noise(RSSI)*/
465 	noise = (u8)(NTH_TH_2_RSSI(MAX_2(PHYDM_DIV(noise_tmp, n_sum), 20)));
466 	nhm_valid = (n_sum * 100) >> 8;
467 	PHYDM_DBG(dm, DBG_ENV_MNTR,
468 		  "valid: ((%d)) percent, noise(RSSI)=((%d))\n",
469 		  nhm_valid, noise);
470 
471 	return noise;
472 }
473 
phydm_nhm_get_utility(void * dm_void)474 void phydm_nhm_get_utility(void *dm_void)
475 {
476 	struct dm_struct *dm = (struct dm_struct *)dm_void;
477 	struct ccx_info *ccx = &dm->dm_ccx_info;
478 	u8 nhm_rpt_non_0 = 0;
479 	u8 nhm_rpt_non_11 = 0;
480 
481 	if (ccx->nhm_rpt_sum >= ccx->nhm_result[0]) {
482 		nhm_rpt_non_0 = ccx->nhm_rpt_sum - ccx->nhm_result[0];
483 		nhm_rpt_non_11 = ccx->nhm_rpt_sum - ccx->nhm_result[11];
484 		ccx->nhm_ratio = (nhm_rpt_non_0 * 100) >> 8;
485 		ccx->nhm_level_valid = (nhm_rpt_non_11 * 100) >> 8;
486 		ccx->nhm_level = phydm_nhm_cal_wgt_avg(dm, 0, NHM_RPT_NUM - 2,
487 						     nhm_rpt_non_11);
488 		ccx->nhm_pwr = phydm_nhm_cal_wgt_avg(dm, 0, NHM_RPT_NUM - 1,
489 						     ccx->nhm_rpt_sum);
490 	} else {
491 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] nhm_rpt_sum invalid\n");
492 		ccx->nhm_ratio = 0;
493 	}
494 
495 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_ratio=%d, nhm_level=%d, nhm_pwr=%d\n",
496 		  ccx->nhm_ratio, ccx->nhm_level, ccx->nhm_pwr);
497 }
498 
499 boolean
phydm_nhm_get_result(void * dm_void)500 phydm_nhm_get_result(void *dm_void)
501 {
502 	struct dm_struct *dm = (struct dm_struct *)dm_void;
503 	struct ccx_info *ccx = &dm->dm_ccx_info;
504 	u32 value32 = 0;
505 	u8 i = 0;
506 	u32 nhm_reg1 = 0;
507 	u16 nhm_rpt_sum_tmp = 0;
508 
509 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
510 		nhm_reg1 = R_0x994;
511 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
512 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
513 		nhm_reg1 = R_0x1e60;
514 	#endif
515 	else
516 		nhm_reg1 = R_0x890;
517 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
518 
519 	if (!(dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8812F |
520 				     ODM_RTL8197G)))
521 		pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
522 
523 	if (!(phydm_nhm_check_rdy(dm))) {
524 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM report Fail\n");
525 		phydm_nhm_racing_release(dm);
526 		return false;
527 	}
528 
529 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
530 		value32 = odm_read_4byte(dm, R_0xfa8);
531 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
532 
533 		value32 = odm_read_4byte(dm, R_0xfac);
534 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
535 
536 		value32 = odm_read_4byte(dm, R_0xfb0);
537 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
538 
539 		/*@Get NHM duration*/
540 		value32 = odm_read_4byte(dm, R_0xfb4);
541 		ccx->nhm_duration = (u16)(value32 & MASKLWORD);
542 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
543 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
544 		value32 = odm_read_4byte(dm, R_0x2d40);
545 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
546 
547 		value32 = odm_read_4byte(dm, R_0x2d44);
548 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
549 
550 		value32 = odm_read_4byte(dm, R_0x2d48);
551 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
552 
553 		/*@Get NHM duration*/
554 		value32 = odm_read_4byte(dm, R_0x2d4c);
555 		ccx->nhm_duration = (u16)(value32 & MASKLWORD);
556 	#endif
557 	} else {
558 		value32 = odm_read_4byte(dm, R_0x8d8);
559 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
560 
561 		value32 = odm_read_4byte(dm, R_0x8dc);
562 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
563 
564 		value32 = odm_get_bb_reg(dm, R_0x8d0, 0xffff0000);
565 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 2);
566 
567 		value32 = odm_read_4byte(dm, R_0x8d4);
568 
569 		ccx->nhm_result[10] = (u8)((value32 & MASKBYTE2) >> 16);
570 		ccx->nhm_result[11] = (u8)((value32 & MASKBYTE3) >> 24);
571 
572 		/*@Get NHM duration*/
573 		ccx->nhm_duration = (u16)(value32 & MASKLWORD);
574 	}
575 
576 	/* sum all nhm_result */
577 	if (ccx->nhm_period >= 65530) {
578 		value32 = (ccx->nhm_duration * 100) >> 16;
579 		PHYDM_DBG(dm, DBG_ENV_MNTR,
580 			  "NHM valid time = %d, valid: %d percent\n",
581 			  ccx->nhm_duration, value32);
582 	}
583 
584 	for (i = 0; i < NHM_RPT_NUM; i++)
585 		nhm_rpt_sum_tmp += (u16)ccx->nhm_result[i];
586 
587 	ccx->nhm_rpt_sum = (u8)nhm_rpt_sum_tmp;
588 
589 	PHYDM_DBG(dm, DBG_ENV_MNTR,
590 		  "NHM_Rpt[%d](H->L)[%d %d %d %d %d %d %d %d %d %d %d %d]\n",
591 		  ccx->nhm_rpt_stamp, ccx->nhm_result[11], ccx->nhm_result[10],
592 		  ccx->nhm_result[9], ccx->nhm_result[8], ccx->nhm_result[7],
593 		  ccx->nhm_result[6], ccx->nhm_result[5], ccx->nhm_result[4],
594 		  ccx->nhm_result[3], ccx->nhm_result[2], ccx->nhm_result[1],
595 		  ccx->nhm_result[0]);
596 
597 	phydm_nhm_racing_release(dm);
598 
599 	if (nhm_rpt_sum_tmp > 255) {
600 		PHYDM_DBG(dm, DBG_ENV_MNTR,
601 			  "[Warning] Invalid NHM RPT, total=%d\n",
602 			  nhm_rpt_sum_tmp);
603 		return false;
604 	}
605 
606 	return true;
607 }
608 
phydm_nhm_set_th_reg(void * dm_void)609 void phydm_nhm_set_th_reg(void *dm_void)
610 {
611 	struct dm_struct *dm = (struct dm_struct *)dm_void;
612 	struct ccx_info *ccx = &dm->dm_ccx_info;
613 	u32 reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg4_bit = 0;
614 	u32 val = 0;
615 
616 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
617 
618 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
619 		reg1 = R_0x994;
620 		reg2 = R_0x998;
621 		reg3 = R_0x99c;
622 		reg4 = R_0x9a0;
623 		reg4_bit = MASKBYTE0;
624 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
625 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
626 		reg1 = R_0x1e60;
627 		reg2 = R_0x1e44;
628 		reg3 = R_0x1e48;
629 		reg4 = R_0x1e5c;
630 		reg4_bit = MASKBYTE2;
631 	#endif
632 	} else {
633 		reg1 = R_0x890;
634 		reg2 = R_0x898;
635 		reg3 = R_0x89c;
636 		reg4 = R_0xe28;
637 		reg4_bit = MASKBYTE0;
638 	}
639 
640 	/*Set NHM threshold*/ /*Unit: PWdB U(8,1)*/
641 	val = BYTE_2_DWORD(ccx->nhm_th[3], ccx->nhm_th[2],
642 			   ccx->nhm_th[1], ccx->nhm_th[0]);
643 	pdm_set_reg(dm, reg2, MASKDWORD, val);
644 	val = BYTE_2_DWORD(ccx->nhm_th[7], ccx->nhm_th[6],
645 			   ccx->nhm_th[5], ccx->nhm_th[4]);
646 	pdm_set_reg(dm, reg3, MASKDWORD, val);
647 	pdm_set_reg(dm, reg4, reg4_bit, ccx->nhm_th[8]);
648 	val = BYTE_2_DWORD(0, 0, ccx->nhm_th[10], ccx->nhm_th[9]);
649 	pdm_set_reg(dm, reg1, 0xffff0000, val);
650 
651 	PHYDM_DBG(dm, DBG_ENV_MNTR,
652 		  "Update NHM_th[H->L]=[%d %d %d %d %d %d %d %d %d %d %d]\n",
653 		  ccx->nhm_th[10], ccx->nhm_th[9], ccx->nhm_th[8],
654 		  ccx->nhm_th[7], ccx->nhm_th[6], ccx->nhm_th[5],
655 		  ccx->nhm_th[4], ccx->nhm_th[3], ccx->nhm_th[2],
656 		  ccx->nhm_th[1], ccx->nhm_th[0]);
657 }
658 
659 boolean
phydm_nhm_th_update_chk(void * dm_void,enum nhm_application nhm_app,u8 * nhm_th,u32 * igi_new,boolean en_1db_mode,u8 nhm_th0_manual)660 phydm_nhm_th_update_chk(void *dm_void, enum nhm_application nhm_app, u8 *nhm_th,
661 			u32 *igi_new, boolean en_1db_mode, u8 nhm_th0_manual)
662 {
663 	struct dm_struct *dm = (struct dm_struct *)dm_void;
664 	struct ccx_info *ccx = &dm->dm_ccx_info;
665 	boolean is_update = false;
666 	u8 igi_curr = phydm_get_igi(dm, BB_PATH_A);
667 	u8 nhm_igi_th_11k_low[NHM_TH_NUM] = {0x12, 0x15, 0x18, 0x1b, 0x1e,
668 					     0x23, 0x28, 0x2c, 0x78,
669 					     0x78, 0x78};
670 	u8 nhm_igi_th_11k_high[NHM_TH_NUM] = {0x1e, 0x23, 0x28, 0x2d, 0x32,
671 					      0x37, 0x78, 0x78, 0x78, 0x78,
672 					      0x78};
673 	u8 nhm_igi_th_xbox[NHM_TH_NUM] = {0x1a, 0x2c, 0x2e, 0x30, 0x32, 0x34,
674 					  0x36, 0x38, 0x3a, 0x3c, 0x3d};
675 	u8 i = 0;
676 	u8 th_tmp = igi_curr - CCA_CAP;
677 	u8 th_step = 2;
678 
679 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
680 	PHYDM_DBG(dm, DBG_ENV_MNTR, "App=%d, nhm_igi=0x%x, igi_curr=0x%x\n",
681 		  nhm_app, ccx->nhm_igi, igi_curr);
682 
683 	if (igi_curr < 0x10) /* Protect for invalid IGI*/
684 		return false;
685 
686 	switch (nhm_app) {
687 	case NHM_BACKGROUND: /* @Get IGI form driver parameter(cur_ig_value)*/
688 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
689 			is_update = true;
690 			*igi_new = (u32)igi_curr;
691 
692 			#ifdef NHM_DYM_PW_TH_SUPPORT
693 			if (ccx->nhm_dym_pw_th_en) {
694 				th_tmp = MAX_2(igi_curr - DYM_PWTH_CCA_CAP, 0);
695 				th_step = 3;
696 			}
697 			#endif
698 
699 			nhm_th[0] = (u8)IGI_2_NHM_TH(th_tmp);
700 
701 			for (i = 1; i <= 10; i++)
702 				nhm_th[i] = nhm_th[0] +
703 					    IGI_2_NHM_TH(th_step * i);
704 
705 		}
706 		break;
707 
708 	case NHM_ACS:
709 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
710 			is_update = true;
711 			*igi_new = (u32)igi_curr;
712 			nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr - CCA_CAP);
713 			for (i = 1; i <= 10; i++)
714 				nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(2 * i);
715 		}
716 		break;
717 
718 	case IEEE_11K_HIGH:
719 		is_update = true;
720 		*igi_new = 0x2c;
721 		for (i = 0; i < NHM_TH_NUM; i++)
722 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_high[i]);
723 		break;
724 
725 	case IEEE_11K_LOW:
726 		is_update = true;
727 		*igi_new = 0x20;
728 		for (i = 0; i < NHM_TH_NUM; i++)
729 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_low[i]);
730 		break;
731 
732 	case INTEL_XBOX:
733 		is_update = true;
734 		*igi_new = 0x36;
735 		for (i = 0; i < NHM_TH_NUM; i++)
736 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_xbox[i]);
737 		break;
738 
739 	case NHM_DBG: /*@Get IGI form register*/
740 		igi_curr = phydm_get_igi(dm, BB_PATH_A);
741 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
742 			is_update = true;
743 			*igi_new = (u32)igi_curr;
744 			if (en_1db_mode) {
745 				nhm_th[0] = (u8)IGI_2_NHM_TH(nhm_th0_manual +
746 							     10);
747 				th_step = 1;
748 			} else {
749 				nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr -
750 							     CCA_CAP);
751 			}
752 
753 			for (i = 1; i <= 10; i++)
754 				nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(th_step *
755 					    i);
756 		}
757 		break;
758 	}
759 
760 	if (is_update) {
761 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update NHM_TH] igi_RSSI=%d\n",
762 			  IGI_2_RSSI(*igi_new));
763 
764 		for (i = 0; i < NHM_TH_NUM; i++) {
765 			PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM_th[%d](RSSI) = %d\n",
766 				  i, NTH_TH_2_RSSI(nhm_th[i]));
767 		}
768 	} else {
769 		PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update NHM_TH\n");
770 	}
771 	return is_update;
772 }
773 
phydm_nhm_set(void * dm_void,enum nhm_option_txon_all include_tx,enum nhm_option_cca_all include_cca,enum nhm_divider_opt_all divi_opt,enum nhm_application nhm_app,u16 period,boolean en_1db_mode,u8 nhm_th0_manual)774 void phydm_nhm_set(void *dm_void, enum nhm_option_txon_all include_tx,
775 		   enum nhm_option_cca_all include_cca,
776 		   enum nhm_divider_opt_all divi_opt,
777 		   enum nhm_application nhm_app, u16 period,
778 		   boolean en_1db_mode, u8 nhm_th0_manual)
779 {
780 	struct dm_struct *dm = (struct dm_struct *)dm_void;
781 	struct ccx_info *ccx = &dm->dm_ccx_info;
782 	u8 nhm_th[NHM_TH_NUM] = {0};
783 	u32 igi = 0x20;
784 	u32 reg1 = 0, reg2 = 0;
785 	u32 val_tmp = 0;
786 
787 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
788 
789 	PHYDM_DBG(dm, DBG_ENV_MNTR,
790 		  "incld{tx, cca}={%d, %d}, divi_opt=%d, period=%d\n",
791 		  include_tx, include_cca, divi_opt, period);
792 
793 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
794 		reg1 = R_0x994;
795 		reg2 = R_0x990;
796 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
797 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
798 		reg1 = R_0x1e60;
799 		reg2 = R_0x1e40;
800 	#endif
801 	} else {
802 		reg1 = R_0x890;
803 		reg2 = R_0x894;
804 	}
805 
806 	/*Set disable_ignore_cca, disable_ignore_txon, ccx_en*/
807 	if (include_tx != ccx->nhm_include_txon ||
808 	    include_cca != ccx->nhm_include_cca ||
809 	    divi_opt != ccx->nhm_divider_opt) {
810 	    /* some old ic is not supported on NHM divider option */
811 		if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
812 		    ODM_RTL8195A | ODM_RTL8192E)) {
813 			val_tmp = (u32)((include_tx << 2) |
814 				  (include_cca << 1) | 1);
815 			pdm_set_reg(dm, reg1, 0x700, val_tmp);
816 		} else {
817 			val_tmp = (u32)BIT_2_BYTE(divi_opt, include_tx,
818 				  include_cca, 1);
819 			pdm_set_reg(dm, reg1, 0xf00, val_tmp);
820 		}
821 		ccx->nhm_include_txon = include_tx;
822 		ccx->nhm_include_cca = include_cca;
823 		ccx->nhm_divider_opt = divi_opt;
824 	}
825 
826 	/*Set NHM period*/
827 	if (period != ccx->nhm_period) {
828 		pdm_set_reg(dm, reg2, MASKHWORD, period);
829 		PHYDM_DBG(dm, DBG_ENV_MNTR,
830 			  "Update NHM period ((%d)) -> ((%d))\n",
831 			  ccx->nhm_period, period);
832 
833 		ccx->nhm_period = period;
834 	}
835 
836 	/*Set NHM threshold*/
837 	if (phydm_nhm_th_update_chk(dm, nhm_app, &nhm_th[0], &igi,
838 				    en_1db_mode, nhm_th0_manual)) {
839 		/*Pause IGI*/
840 		if (nhm_app == NHM_BACKGROUND || nhm_app == NHM_ACS) {
841 			PHYDM_DBG(dm, DBG_ENV_MNTR, "DIG Free Run\n");
842 		} else if (phydm_pause_func(dm, F00_DIG, PHYDM_PAUSE,
843 					    PHYDM_PAUSE_LEVEL_1, 1, &igi)
844 					    == PAUSE_FAIL) {
845 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG Fail\n");
846 			return;
847 		} else {
848 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG=0x%x\n", igi);
849 		}
850 		ccx->nhm_app = nhm_app;
851 		ccx->nhm_igi = (u8)igi;
852 		odm_move_memory(dm, &ccx->nhm_th[0], &nhm_th, NHM_TH_NUM);
853 
854 		/*Set NHM th*/
855 		phydm_nhm_set_th_reg(dm);
856 	}
857 }
858 
phydm_nhm_mntr_set(void * dm_void,struct nhm_para_info * nhm_para)859 u8 phydm_nhm_mntr_set(void *dm_void, struct nhm_para_info *nhm_para)
860 {
861 	struct dm_struct *dm = (struct dm_struct *)dm_void;
862 	u16 nhm_time = 0; /*unit: 4us*/
863 
864 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
865 
866 	if (nhm_para->mntr_time == 0)
867 		return PHYDM_SET_FAIL;
868 
869 	if (nhm_para->nhm_lv >= NHM_MAX_NUM) {
870 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n", nhm_para->nhm_lv);
871 		return PHYDM_SET_FAIL;
872 	}
873 
874 	if (phydm_nhm_racing_ctrl(dm, nhm_para->nhm_lv) == PHYDM_SET_FAIL)
875 		return PHYDM_SET_FAIL;
876 
877 	if (nhm_para->mntr_time >= 262)
878 		nhm_time = NHM_PERIOD_MAX;
879 	else
880 		nhm_time = nhm_para->mntr_time * MS_TO_4US_RATIO;
881 
882 	phydm_nhm_set(dm, nhm_para->incld_txon, nhm_para->incld_cca,
883 		      nhm_para->div_opt, nhm_para->nhm_app, nhm_time,
884 		      nhm_para->en_1db_mode, nhm_para->nhm_th0_manual);
885 
886 	return PHYDM_SET_SUCCESS;
887 }
888 
889 #ifdef NHM_DYM_PW_TH_SUPPORT
890 void
phydm_nhm_restore_pw_th(void * dm_void)891 phydm_nhm_restore_pw_th(void *dm_void)
892 {
893 	struct dm_struct *dm = (struct dm_struct *)dm_void;
894 	struct ccx_info *ccx = &dm->dm_ccx_info;
895 
896 	odm_set_bb_reg(dm, R_0x82c, 0x3f, ccx->pw_th_rf20_ori);
897 }
898 
899 void
phydm_nhm_set_pw_th(void * dm_void,u8 noise,boolean chk_succ)900 phydm_nhm_set_pw_th(void *dm_void, u8 noise, boolean chk_succ)
901 {
902 	struct dm_struct *dm = (struct dm_struct *)dm_void;
903 	struct ccx_info *ccx = &dm->dm_ccx_info;
904 	boolean not_update = false;
905 	u8 pw_th_rf20_new = 0;
906 	u8 pw_th_u_bnd = 0;
907 	s8 noise_diff = 0;
908 	u8 point_mean = 15;
909 
910 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
911 
912 	if (*dm->band_width != CHANNEL_WIDTH_20 ||
913 	    *dm->band_type == ODM_BAND_5G) {
914 		PHYDM_DBG(dm, DBG_ENV_MNTR,  "bandwidth=((%d)), band=((%d))\n",
915 			  *dm->band_width, *dm->band_type);
916 		phydm_nhm_restore_pw_th(dm);
917 		return;
918 	}
919 
920 	if (chk_succ) {
921 		noise_diff = noise - (ccx->nhm_igi - 10);
922 		pw_th_u_bnd = (u8)(noise_diff + 32 + point_mean);
923 
924 		pw_th_u_bnd = MIN_2(pw_th_u_bnd, ccx->nhm_pw_th_max);
925 
926 		PHYDM_DBG(dm, DBG_ENV_MNTR,
927 			  "noise_diff=((%d)), max=((%d)), pw_th_u_bnd=((%d))\n",
928 			  noise_diff, ccx->nhm_pw_th_max, pw_th_u_bnd);
929 
930 		if (pw_th_u_bnd > ccx->pw_th_rf20_cur) {
931 			pw_th_rf20_new = ccx->pw_th_rf20_cur + 1;
932 		} else if (pw_th_u_bnd < ccx->pw_th_rf20_cur) {
933 			if (ccx->pw_th_rf20_cur > ccx->pw_th_rf20_ori)
934 				pw_th_rf20_new = ccx->pw_th_rf20_cur - 1;
935 			else /*ccx->pw_th_rf20_cur == ccx->pw_th_ori*/
936 				not_update = true;
937 		} else {/*pw_th_u_bnd == ccx->pw_th_rf20_cur*/
938 			not_update = true;
939 		}
940 	} else {
941 		if (ccx->pw_th_rf20_cur > ccx->pw_th_rf20_ori)
942 			pw_th_rf20_new = ccx->pw_th_rf20_cur - 1;
943 		else /*ccx->pw_th_rf20_cur == ccx->pw_th_ori*/
944 			not_update = true;
945 	}
946 
947 	PHYDM_DBG(dm, DBG_ENV_MNTR, "pw_th_cur=((%d)), pw_th_new=((%d))\n",
948 		  ccx->pw_th_rf20_cur, pw_th_rf20_new);
949 
950 	if (!not_update) {
951 		odm_set_bb_reg(dm, R_0x82c, 0x3f, pw_th_rf20_new);
952 		ccx->pw_th_rf20_cur = pw_th_rf20_new;
953 	}
954 }
955 
956 void
phydm_nhm_dym_pw_th(void * dm_void)957 phydm_nhm_dym_pw_th(void *dm_void)
958 {
959 	struct dm_struct *dm = (struct dm_struct *)dm_void;
960 	struct ccx_info *ccx = &dm->dm_ccx_info;
961 	u8 i = 0;
962 	u8 n_sum = 0;
963 	u8 noise = 0;
964 	boolean chk_succ = false;
965 
966 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
967 
968 	for (i = 0; i < NHM_RPT_NUM - 3; i++) {
969 		n_sum = ccx->nhm_result[i] + ccx->nhm_result[i + 1] +
970 			ccx->nhm_result[i + 2] + ccx->nhm_result[i + 3];
971 		if (n_sum >= ccx->nhm_sl_pw_th) {
972 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Do sl[%d:%d]\n", i, i + 3);
973 			chk_succ = true;
974 			noise = phydm_nhm_cal_wgt_avg(dm, i, i + 3, n_sum);
975 			break;
976 		}
977 	}
978 
979 	if (!chk_succ)
980 		PHYDM_DBG(dm, DBG_ENV_MNTR, "SL method failed!\n");
981 
982 	phydm_nhm_set_pw_th(dm, noise, chk_succ);
983 }
984 
985 boolean
phydm_nhm_dym_pw_th_en(void * dm_void)986 phydm_nhm_dym_pw_th_en(void *dm_void)
987 {
988 	struct dm_struct *dm = (struct dm_struct *)dm_void;
989 	struct ccx_info *ccx = &dm->dm_ccx_info;
990 	struct phydm_iot_center	*iot_table = &dm->iot_table;
991 
992 	if (!(dm->support_ic_type & ODM_RTL8822C))
993 		return false;
994 
995 	if (ccx->dym_pwth_manual_ctrl)
996 		return true;
997 
998 	if (dm->iot_table.phydm_patch_id == 0x100f0401 ||
999 	    iot_table->patch_id_100f0401) {
1000 		return true;
1001 	} else if (ccx->nhm_dym_pw_th_en) {
1002 		phydm_nhm_restore_pw_th(dm);
1003 		return false;
1004 	} else {
1005 		return false;
1006 	}
1007 }
1008 #endif
1009 
1010 /*Environment Monitor*/
1011 boolean
phydm_nhm_mntr_chk(void * dm_void,u16 monitor_time)1012 phydm_nhm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
1013 {
1014 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1015 	struct ccx_info *ccx = &dm->dm_ccx_info;
1016 	struct nhm_para_info nhm_para = {0};
1017 	boolean nhm_chk_result = false;
1018 	boolean nhm_polling_result = false;
1019 	u32 sys_return_time = 0;
1020 
1021 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1022 
1023 	if (ccx->nhm_manual_ctrl) {
1024 		PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM in manual ctrl\n");
1025 		return nhm_chk_result;
1026 	}
1027 	sys_return_time = ccx->nhm_trigger_time + MAX_ENV_MNTR_TIME;
1028 	if (ccx->nhm_app != NHM_BACKGROUND &&
1029 	    (sys_return_time > dm->phydm_sys_up_time)) {
1030 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1031 			  "nhm_app=%d, trigger_time %d, sys_time=%d\n",
1032 			  ccx->nhm_app, ccx->nhm_trigger_time,
1033 			  dm->phydm_sys_up_time);
1034 
1035 		return nhm_chk_result;
1036 	}
1037 
1038 	/*[NHM get result & calculate Utility----------------------------*/
1039 	nhm_polling_result = phydm_nhm_get_result(dm);
1040 	if (nhm_polling_result) {
1041 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
1042 		phydm_nhm_get_utility(dm);
1043 	}
1044 
1045 	#ifdef NHM_DYM_PW_TH_SUPPORT
1046 	ccx->nhm_dym_pw_th_en = phydm_nhm_dym_pw_th_en(dm);
1047 	if (ccx->nhm_dym_pw_th_en) {
1048 		if (nhm_polling_result)
1049 			phydm_nhm_dym_pw_th(dm);
1050 		else
1051 			phydm_nhm_set_pw_th(dm, 0x0, false);
1052 	}
1053 	#endif
1054 
1055 	/*[NHM trigger setting]------------------------------------------*/
1056 	nhm_para.incld_txon = NHM_EXCLUDE_TXON;
1057 	nhm_para.incld_cca = NHM_EXCLUDE_CCA;
1058 	nhm_para.div_opt = NHM_CNT_ALL;
1059 	nhm_para.nhm_app = NHM_BACKGROUND;
1060 	nhm_para.nhm_lv = NHM_LV_1;
1061 	nhm_para.en_1db_mode = false;
1062 	nhm_para.mntr_time = monitor_time;
1063 
1064 	#ifdef NHM_DYM_PW_TH_SUPPORT
1065 	if (ccx->nhm_dym_pw_th_en) {
1066 		nhm_para.div_opt = NHM_VALID;
1067 		nhm_para.mntr_time = monitor_time >> ccx->nhm_period_decre;
1068 	}
1069 	#endif
1070 
1071 	nhm_chk_result = phydm_nhm_mntr_set(dm, &nhm_para);
1072 
1073 	return nhm_chk_result;
1074 }
1075 
phydm_nhm_init(void * dm_void)1076 void phydm_nhm_init(void *dm_void)
1077 {
1078 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1079 	struct ccx_info *ccx = &dm->dm_ccx_info;
1080 
1081 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1082 	PHYDM_DBG(dm, DBG_ENV_MNTR, "cur_igi=0x%x\n",
1083 		  dm->dm_dig_table.cur_ig_value);
1084 
1085 	ccx->nhm_app = NHM_BACKGROUND;
1086 	ccx->nhm_igi = 0xff;
1087 
1088 	/*Set NHM threshold*/
1089 	ccx->nhm_ongoing = false;
1090 	ccx->nhm_set_lv = NHM_RELEASE;
1091 
1092 	if (phydm_nhm_th_update_chk(dm, ccx->nhm_app, &ccx->nhm_th[0],
1093 				    (u32 *)&ccx->nhm_igi, false, 0))
1094 		phydm_nhm_set_th_reg(dm);
1095 
1096 	ccx->nhm_period = 0;
1097 
1098 	ccx->nhm_include_cca = NHM_CCA_INIT;
1099 	ccx->nhm_include_txon = NHM_TXON_INIT;
1100 	ccx->nhm_divider_opt = NHM_CNT_INIT;
1101 
1102 	ccx->nhm_manual_ctrl = 0;
1103 	ccx->nhm_rpt_stamp = 0;
1104 
1105 	#ifdef NHM_DYM_PW_TH_SUPPORT
1106 	if (dm->support_ic_type & ODM_RTL8822C) {
1107 		ccx->nhm_dym_pw_th_en = false;
1108 		ccx->pw_th_rf20_ori = (u8)odm_get_bb_reg(dm, R_0x82c, 0x3f);
1109 		ccx->pw_th_rf20_cur = ccx->pw_th_rf20_ori;
1110 		ccx->nhm_pw_th_max = 63;
1111 		ccx->nhm_sl_pw_th = 100; /*39%*/
1112 		ccx->nhm_period_decre = 1;
1113 		ccx->dym_pwth_manual_ctrl = false;
1114 	}
1115 	#endif
1116 }
1117 
phydm_nhm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1118 void phydm_nhm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
1119 		   u32 *_out_len)
1120 {
1121 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1122 	struct ccx_info *ccx = &dm->dm_ccx_info;
1123 	struct nhm_para_info nhm_para;
1124 	char help[] = "-h";
1125 	u32 var1[10] = {0};
1126 	u32 used = *_used;
1127 	u32 out_len = *_out_len;
1128 	u8 result_tmp = 0;
1129 	u8 i = 0;
1130 
1131 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
1132 
1133 	if ((strcmp(input[1], help) == 0)) {
1134 		PDM_SNPF(out_len, used, output + used, out_len - used,
1135 			 "NHM Basic-Trigger 262ms: {1}\n");
1136 
1137 		PDM_SNPF(out_len, used, output + used, out_len - used,
1138 			 "NHM Adv-Trigger: {2} {Include TXON} {Include CCA}\n{0:Cnt_all, 1:Cnt valid} {App} {LV:1~4} {0~262ms}, 1dB mode :{en} {t[0](RSSI)}\n");
1139 		#ifdef NHM_DYM_PW_TH_SUPPORT
1140 		if (dm->support_ic_type & ODM_RTL8822C) {
1141 			PDM_SNPF(out_len, used, output + used, out_len - used,
1142 				 "NHM dym_pw_th: {3} {0:off}\n");
1143 			PDM_SNPF(out_len, used, output + used, out_len - used,
1144 				 "NHM dym_pw_th: {3} {1:on} {max} {period_decre} {sl_th}\n");
1145 			PDM_SNPF(out_len, used, output + used, out_len - used,
1146 				 "NHM dym_pw_th: {3} {2:fast on}\n");
1147 		}
1148 		#endif
1149 
1150 		PDM_SNPF(out_len, used, output + used, out_len - used,
1151 			 "NHM Get Result: {100}\n");
1152 	} else if (var1[0] == 100) { /*Get NHM results*/
1153 
1154 		PDM_SNPF(out_len, used, output + used, out_len - used,
1155 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
1156 			 ccx->nhm_rpt_stamp);
1157 
1158 		if (phydm_nhm_get_result(dm)) {
1159 			for (i = 0; i <= 11; i++) {
1160 				result_tmp = ccx->nhm_result[i];
1161 				PDM_SNPF(out_len, used, output + used,
1162 					 out_len - used,
1163 					 "nhm_rpt[%d] = %d (%d percent)\n",
1164 					 i, result_tmp,
1165 					 (((result_tmp * 100) + 128) >> 8));
1166 			}
1167 			phydm_nhm_get_utility(dm);
1168 
1169 			PDM_SNPF(out_len, used, output + used, out_len - used,
1170 				 "NHM_noise: valid: %d percent, noise(RSSI) = %d\n",
1171 				 ccx->nhm_level_valid, ccx->nhm_level);
1172 			PDM_SNPF(out_len, used, output + used, out_len - used,
1173 				 "NHM_pwr: nhm_pwr (RSSI) = %d\n", ccx->nhm_pwr);
1174 		} else {
1175 			PDM_SNPF(out_len, used, output + used, out_len - used,
1176 				 "Get NHM_rpt Fail\n");
1177 		}
1178 		ccx->nhm_manual_ctrl = 0;
1179 	#ifdef NHM_DYM_PW_TH_SUPPORT
1180 	} else if (var1[0] == 3) { /*NMH dym_pw_th*/
1181 		if (dm->support_ic_type & ODM_RTL8822C) {
1182 			for (i = 1; i < 7; i++) {
1183 				if (input[i + 1]) {
1184 					PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
1185 						     &var1[i]);
1186 				}
1187 			}
1188 
1189 			if (var1[1] == 1) {
1190 				ccx->nhm_dym_pw_th_en = true;
1191 				ccx->nhm_pw_th_max = (u8)var1[2];
1192 				ccx->nhm_period_decre = (u8)var1[3];
1193 				ccx->nhm_sl_pw_th = (u8)var1[4];
1194 				ccx->dym_pwth_manual_ctrl = true;
1195 			} else if (var1[1] == 2) {
1196 				ccx->nhm_dym_pw_th_en = true;
1197 				ccx->nhm_pw_th_max = 63;
1198 				ccx->nhm_period_decre = 1;
1199 				ccx->nhm_sl_pw_th = 100;
1200 				ccx->dym_pwth_manual_ctrl = true;
1201 			} else {
1202 				ccx->nhm_dym_pw_th_en = false;
1203 				phydm_nhm_restore_pw_th(dm);
1204 				ccx->dym_pwth_manual_ctrl = false;
1205 			}
1206 		}
1207 	#endif
1208 	} else { /*NMH trigger*/
1209 		ccx->nhm_manual_ctrl = 1;
1210 
1211 		for (i = 1; i < 9; i++) {
1212 			if (input[i + 1]) {
1213 				PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
1214 					     &var1[i]);
1215 			}
1216 		}
1217 
1218 		if (var1[0] == 1) {
1219 			nhm_para.incld_txon = NHM_EXCLUDE_TXON;
1220 			nhm_para.incld_cca = NHM_EXCLUDE_CCA;
1221 			nhm_para.div_opt = NHM_CNT_ALL;
1222 			nhm_para.nhm_app = NHM_DBG;
1223 			nhm_para.nhm_lv = NHM_LV_4;
1224 			nhm_para.mntr_time = 262;
1225 			nhm_para.en_1db_mode = false;
1226 		} else {
1227 			nhm_para.incld_txon = (enum nhm_option_txon_all)var1[1];
1228 			nhm_para.incld_cca = (enum nhm_option_cca_all)var1[2];
1229 			nhm_para.div_opt = (enum nhm_divider_opt_all)var1[3];
1230 			nhm_para.nhm_app = (enum nhm_application)var1[4];
1231 			nhm_para.nhm_lv = (enum phydm_nhm_level)var1[5];
1232 			nhm_para.mntr_time = (u16)var1[6];
1233 			nhm_para.en_1db_mode = (boolean)var1[7];
1234 			nhm_para.nhm_th0_manual = (u8)var1[8];
1235 
1236 			/*some old ic is not supported on NHM divider option */
1237 			if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
1238 			    ODM_RTL8195A | ODM_RTL8192E)) {
1239 				nhm_para.div_opt = NHM_CNT_ALL;
1240 			}
1241 		}
1242 
1243 		PDM_SNPF(out_len, used, output + used, out_len - used,
1244 			 "txon=%d, cca=%d, dev=%d, app=%d, lv=%d, time=%d ms\n",
1245 			 nhm_para.incld_txon, nhm_para.incld_cca,
1246 			 nhm_para.div_opt, nhm_para.nhm_app,
1247 			 nhm_para.nhm_lv, nhm_para.mntr_time);
1248 
1249 		PDM_SNPF(out_len, used, output + used, out_len - used,
1250 			 "en_1db_mode=%d, th0(for 1db mode)=%d\n",
1251 			 nhm_para.en_1db_mode, nhm_para.nhm_th0_manual);
1252 
1253 		if (phydm_nhm_mntr_set(dm, &nhm_para) == PHYDM_SET_SUCCESS)
1254 			phydm_nhm_trigger(dm);
1255 
1256 		PDM_SNPF(out_len, used, output + used, out_len - used,
1257 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
1258 			 ccx->nhm_rpt_stamp);
1259 
1260 		for (i = 0; i <= 10; i++) {
1261 			PDM_SNPF(out_len, used, output + used, out_len - used,
1262 				 "NHM_th[%d] RSSI = %d\n", i,
1263 				 NTH_TH_2_RSSI(ccx->nhm_th[i]));
1264 		}
1265 	}
1266 
1267 	*_used = used;
1268 	*_out_len = out_len;
1269 }
1270 
1271 #endif /*@#ifdef NHM_SUPPORT*/
1272 
1273 #ifdef CLM_SUPPORT
1274 
phydm_clm_racing_release(void * dm_void)1275 void phydm_clm_racing_release(void *dm_void)
1276 {
1277 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1278 	struct ccx_info *ccx = &dm->dm_ccx_info;
1279 
1280 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1281 	PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->clm_set_lv);
1282 
1283 	ccx->clm_ongoing = false;
1284 	ccx->clm_set_lv = CLM_RELEASE;
1285 	ccx->clm_app = CLM_BACKGROUND;
1286 }
1287 
phydm_clm_racing_ctrl(void * dm_void,enum phydm_clm_level clm_lv)1288 u8 phydm_clm_racing_ctrl(void *dm_void, enum phydm_clm_level clm_lv)
1289 {
1290 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1291 	struct ccx_info *ccx = &dm->dm_ccx_info;
1292 	u8 set_result = PHYDM_SET_SUCCESS;
1293 	/*@acquire to control CLM API*/
1294 
1295 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ongoing=%d, lv:(%d)->(%d)\n",
1296 		  ccx->clm_ongoing, ccx->clm_set_lv, clm_lv);
1297 	if (ccx->clm_ongoing) {
1298 		if (clm_lv <= ccx->clm_set_lv) {
1299 			set_result = PHYDM_SET_FAIL;
1300 		} else {
1301 			phydm_ccx_hw_restart(dm);
1302 			ccx->clm_ongoing = false;
1303 		}
1304 	}
1305 
1306 	if (set_result)
1307 		ccx->clm_set_lv = clm_lv;
1308 
1309 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm racing success=%d\n", set_result);
1310 	return set_result;
1311 }
1312 
phydm_clm_c2h_report_handler(void * dm_void,u8 * cmd_buf,u8 cmd_len)1313 void phydm_clm_c2h_report_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
1314 {
1315 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1316 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1317 	u8 clm_report = cmd_buf[0];
1318 	/*@u8 clm_report_idx = cmd_buf[1];*/
1319 
1320 	if (cmd_len >= 12)
1321 		return;
1322 
1323 	ccx_info->clm_fw_result_acc += clm_report;
1324 	ccx_info->clm_fw_result_cnt++;
1325 
1326 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%d] clm_report= %d\n",
1327 		  ccx_info->clm_fw_result_cnt, clm_report);
1328 }
1329 
phydm_clm_h2c(void * dm_void,u16 obs_time,u8 fw_clm_en)1330 void phydm_clm_h2c(void *dm_void, u16 obs_time, u8 fw_clm_en)
1331 {
1332 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1333 	u8 h2c_val[H2C_MAX_LENGTH] = {0};
1334 	u8 i = 0;
1335 	u8 obs_time_idx = 0;
1336 
1337 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1338 	PHYDM_DBG(dm, DBG_ENV_MNTR, "obs_time_index=%d *4 us\n", obs_time);
1339 
1340 	for (i = 1; i <= 16; i++) {
1341 		if (obs_time & BIT(16 - i)) {
1342 			obs_time_idx = 16 - i;
1343 			break;
1344 		}
1345 	}
1346 #if 0
1347 	obs_time = (2 ^ 16 - 1)~(2 ^ 15)  => obs_time_idx = 15  (65535 ~32768)
1348 	obs_time = (2 ^ 15 - 1)~(2 ^ 14)  => obs_time_idx = 14
1349 	...
1350 	...
1351 	...
1352 	obs_time = (2 ^ 1 - 1)~(2 ^ 0)  => obs_time_idx = 0
1353 
1354 #endif
1355 
1356 	h2c_val[0] = obs_time_idx | (((fw_clm_en) ? 1 : 0) << 7);
1357 	h2c_val[1] = CLM_MAX_REPORT_TIME;
1358 
1359 	PHYDM_DBG(dm, DBG_ENV_MNTR, "PHYDM h2c[0x4d]=0x%x %x %x %x %x %x %x\n",
1360 		  h2c_val[6], h2c_val[5], h2c_val[4], h2c_val[3], h2c_val[2],
1361 		  h2c_val[1], h2c_val[0]);
1362 
1363 	odm_fill_h2c_cmd(dm, PHYDM_H2C_FW_CLM_MNTR, H2C_MAX_LENGTH, h2c_val);
1364 }
1365 
phydm_clm_setting(void * dm_void,u16 clm_period)1366 void phydm_clm_setting(void *dm_void, u16 clm_period /*@4us sample 1 time*/)
1367 {
1368 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1369 	struct ccx_info *ccx = &dm->dm_ccx_info;
1370 
1371 	if (ccx->clm_period != clm_period) {
1372 		if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1373 			odm_set_bb_reg(dm, R_0x990, MASKLWORD, clm_period);
1374 		#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1375 		else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1376 			odm_set_bb_reg(dm, R_0x1e40, MASKLWORD, clm_period);
1377 		#endif
1378 		else if (dm->support_ic_type & ODM_IC_11N_SERIES)
1379 			odm_set_bb_reg(dm, R_0x894, MASKLWORD, clm_period);
1380 
1381 		ccx->clm_period = clm_period;
1382 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1383 			  "Update CLM period ((%d)) -> ((%d))\n",
1384 			  ccx->clm_period, clm_period);
1385 	}
1386 
1387 	PHYDM_DBG(dm, DBG_ENV_MNTR, "Set CLM period=%d * 4us\n",
1388 		  ccx->clm_period);
1389 }
1390 
phydm_clm_trigger(void * dm_void)1391 void phydm_clm_trigger(void *dm_void)
1392 {
1393 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1394 	struct ccx_info *ccx = &dm->dm_ccx_info;
1395 	u32 reg1 = 0;
1396 
1397 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1398 		reg1 = R_0x994;
1399 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1400 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1401 		reg1 = R_0x1e60;
1402 	#endif
1403 	else
1404 		reg1 = R_0x890;
1405 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1406 
1407 	odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
1408 	odm_set_bb_reg(dm, reg1, BIT(0), 0x1);
1409 
1410 	ccx->clm_trigger_time = dm->phydm_sys_up_time;
1411 	ccx->clm_rpt_stamp++;
1412 	ccx->clm_ongoing = true;
1413 }
1414 
1415 boolean
phydm_clm_check_rdy(void * dm_void)1416 phydm_clm_check_rdy(void *dm_void)
1417 {
1418 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1419 	boolean is_ready = false;
1420 	u32 reg1 = 0, reg1_bit = 0;
1421 
1422 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
1423 		reg1 = R_0xfa4;
1424 		reg1_bit = 16;
1425 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1426 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
1427 		reg1 = R_0x2d88;
1428 		reg1_bit = 16;
1429 	#endif
1430 	} else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
1431 		if (dm->support_ic_type & (ODM_RTL8710B | ODM_RTL8721D |
1432 					ODM_RTL8710C)) {
1433 			reg1 = R_0x8b4;
1434 			reg1_bit = 24;
1435 		} else {
1436 			reg1 = R_0x8b4;
1437 			reg1_bit = 16;
1438 		}
1439 	}
1440 	if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
1441 		is_ready = true;
1442 
1443 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM rdy=%d\n", is_ready);
1444 
1445 	return is_ready;
1446 }
1447 
phydm_clm_get_utility(void * dm_void)1448 void phydm_clm_get_utility(void *dm_void)
1449 {
1450 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1451 	struct ccx_info *ccx = &dm->dm_ccx_info;
1452 	u32 clm_result_tmp;
1453 
1454 	if (ccx->clm_period == 0) {
1455 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] clm_period = 0\n");
1456 		ccx->clm_ratio = 0;
1457 	} else if (ccx->clm_period >= 65530) {
1458 		clm_result_tmp = (u32)(ccx->clm_result * 100);
1459 		ccx->clm_ratio = (u8)((clm_result_tmp + (1 << 15)) >> 16);
1460 	} else {
1461 		clm_result_tmp = (u32)(ccx->clm_result * 100);
1462 		ccx->clm_ratio = (u8)(clm_result_tmp / (u32)ccx->clm_period);
1463 	}
1464 }
1465 
1466 boolean
phydm_clm_get_result(void * dm_void)1467 phydm_clm_get_result(void *dm_void)
1468 {
1469 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1470 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1471 	u32 reg1 = 0;
1472 	u32 val = 0;
1473 
1474 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1475 		reg1 = R_0x994;
1476 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1477 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1478 		reg1 = R_0x1e60;
1479 	#endif
1480 	else
1481 		reg1 = R_0x890;
1482 	if (!(dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8812F |
1483 				     ODM_RTL8197G)))
1484 		odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
1485 	if (!(phydm_clm_check_rdy(dm))) {
1486 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM report Fail\n");
1487 		phydm_clm_racing_release(dm);
1488 		return false;
1489 	}
1490 
1491 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
1492 		val = odm_get_bb_reg(dm, R_0xfa4, MASKLWORD);
1493 		ccx_info->clm_result = (u16)val;
1494 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1495 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
1496 		val = odm_get_bb_reg(dm, R_0x2d88, MASKLWORD);
1497 		ccx_info->clm_result = (u16)val;
1498 	#endif
1499 	} else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
1500 		val = odm_get_bb_reg(dm, R_0x8d0, MASKLWORD);
1501 		ccx_info->clm_result = (u16)val;
1502 	}
1503 
1504 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM result = %d *4 us\n",
1505 		  ccx_info->clm_result);
1506 	phydm_clm_racing_release(dm);
1507 	return true;
1508 }
1509 
phydm_clm_mntr_fw(void * dm_void,u16 monitor_time)1510 void phydm_clm_mntr_fw(void *dm_void, u16 monitor_time /*unit ms*/)
1511 {
1512 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1513 	struct ccx_info *ccx = &dm->dm_ccx_info;
1514 	u32 val = 0;
1515 
1516 	/*@[Get CLM report]*/
1517 	if (ccx->clm_fw_result_cnt != 0) {
1518 		val = ccx->clm_fw_result_acc / ccx->clm_fw_result_cnt;
1519 		ccx->clm_ratio = (u8)val;
1520 	} else {
1521 		ccx->clm_ratio = 0;
1522 	}
1523 
1524 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1525 		  "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
1526 		  ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
1527 
1528 	ccx->clm_fw_result_acc = 0;
1529 	ccx->clm_fw_result_cnt = 0;
1530 
1531 	/*@[CLM trigger]*/
1532 	if (monitor_time >= 262)
1533 		ccx->clm_period = 65535;
1534 	else
1535 		ccx->clm_period = monitor_time * MS_TO_4US_RATIO;
1536 
1537 	phydm_clm_h2c(dm, ccx->clm_period, true);
1538 }
1539 
phydm_clm_mntr_set(void * dm_void,struct clm_para_info * clm_para)1540 u8 phydm_clm_mntr_set(void *dm_void, struct clm_para_info *clm_para)
1541 {
1542 	/*@Driver Monitor CLM*/
1543 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1544 	struct ccx_info *ccx = &dm->dm_ccx_info;
1545 	u16 clm_period = 0;
1546 
1547 	if (clm_para->mntr_time == 0)
1548 		return PHYDM_SET_FAIL;
1549 
1550 	if (clm_para->clm_lv >= CLM_MAX_NUM) {
1551 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[WARNING] Wrong LV=%d\n",
1552 			  clm_para->clm_lv);
1553 		return PHYDM_SET_FAIL;
1554 	}
1555 
1556 	if (phydm_clm_racing_ctrl(dm, clm_para->clm_lv) == PHYDM_SET_FAIL)
1557 		return PHYDM_SET_FAIL;
1558 
1559 	if (clm_para->mntr_time >= 262)
1560 		clm_period = CLM_PERIOD_MAX;
1561 	else
1562 		clm_period = clm_para->mntr_time * MS_TO_4US_RATIO;
1563 
1564 	ccx->clm_app = clm_para->clm_app;
1565 	phydm_clm_setting(dm, clm_period);
1566 
1567 	return PHYDM_SET_SUCCESS;
1568 }
1569 
1570 boolean
phydm_clm_mntr_chk(void * dm_void,u16 monitor_time)1571 phydm_clm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
1572 {
1573 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1574 	struct ccx_info *ccx = &dm->dm_ccx_info;
1575 	struct clm_para_info clm_para = {0};
1576 	boolean clm_chk_result = false;
1577 	u32 sys_return_time = 0;
1578 
1579 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1580 	if (ccx->clm_manual_ctrl) {
1581 		PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM in manual ctrl\n");
1582 		return clm_chk_result;
1583 	}
1584 
1585 	sys_return_time = ccx->clm_trigger_time + MAX_ENV_MNTR_TIME;
1586 
1587 	if (ccx->clm_app != CLM_BACKGROUND &&
1588 	    sys_return_time > dm->phydm_sys_up_time) {
1589 		PHYDM_DBG(dm, DBG_ENV_MNTR, "trigger_time %d, sys_time=%d\n",
1590 			  ccx->clm_trigger_time, dm->phydm_sys_up_time);
1591 
1592 		return clm_chk_result;
1593 	}
1594 
1595 	clm_para.clm_app = CLM_BACKGROUND;
1596 	clm_para.clm_lv = CLM_LV_1;
1597 	clm_para.mntr_time = monitor_time;
1598 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1599 		/*@[Get CLM report]*/
1600 		if (phydm_clm_get_result(dm)) {
1601 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
1602 			phydm_clm_get_utility(dm);
1603 		}
1604 
1605 		/*@[CLM trigger]----------------------------------------------*/
1606 		if (phydm_clm_mntr_set(dm, &clm_para) == PHYDM_SET_SUCCESS)
1607 			clm_chk_result = true;
1608 	} else {
1609 		phydm_clm_mntr_fw(dm, monitor_time);
1610 	}
1611 
1612 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ratio=%d\n", ccx->clm_ratio);
1613 
1614 	/*@PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_chk_result=%d\n",clm_chk_result);*/
1615 
1616 	return clm_chk_result;
1617 }
1618 
phydm_set_clm_mntr_mode(void * dm_void,enum clm_monitor_mode mode)1619 void phydm_set_clm_mntr_mode(void *dm_void, enum clm_monitor_mode mode)
1620 {
1621 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1622 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1623 
1624 	if (ccx_info->clm_mntr_mode != mode) {
1625 		ccx_info->clm_mntr_mode = mode;
1626 		phydm_ccx_hw_restart(dm);
1627 
1628 		if (mode == CLM_DRIVER_MNTR)
1629 			phydm_clm_h2c(dm, CLM_PERIOD_MAX, 0);
1630 	}
1631 }
1632 
phydm_clm_init(void * dm_void)1633 void phydm_clm_init(void *dm_void)
1634 {
1635 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1636 	struct ccx_info *ccx = &dm->dm_ccx_info;
1637 
1638 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1639 	ccx->clm_ongoing = false;
1640 	ccx->clm_manual_ctrl = 0;
1641 	ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1642 	ccx->clm_period = 0;
1643 	ccx->clm_rpt_stamp = 0;
1644 	phydm_clm_setting(dm, 65535);
1645 }
1646 
phydm_clm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1647 void phydm_clm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
1648 		   u32 *_out_len)
1649 {
1650 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1651 	struct ccx_info *ccx = &dm->dm_ccx_info;
1652 	char help[] = "-h";
1653 	u32 var1[10] = {0};
1654 	u32 used = *_used;
1655 	u32 out_len = *_out_len;
1656 	struct clm_para_info clm_para = {0};
1657 	u32 i;
1658 
1659 	for (i = 0; i < 4; i++) {
1660 		if (input[i + 1])
1661 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
1662 	}
1663 
1664 	if ((strcmp(input[1], help) == 0)) {
1665 		PDM_SNPF(out_len, used, output + used, out_len - used,
1666 			 "CLM Driver Basic-Trigger 262ms: {1}\n");
1667 		PDM_SNPF(out_len, used, output + used, out_len - used,
1668 			 "CLM Driver Adv-Trigger: {2} {app} {LV} {0~262ms}\n");
1669 		PDM_SNPF(out_len, used, output + used, out_len - used,
1670 			 "CLM FW Trigger: {3} {1:drv, 2:fw}\n");
1671 		PDM_SNPF(out_len, used, output + used, out_len - used,
1672 			 "CLM Get Result: {100}\n");
1673 	} else if (var1[0] == 100) { /* @Get CLM results */
1674 
1675 		if (phydm_clm_get_result(dm))
1676 			phydm_clm_get_utility(dm);
1677 
1678 		PDM_SNPF(out_len, used, output + used, out_len - used,
1679 			 "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
1680 
1681 		PDM_SNPF(out_len, used, output + used, out_len - used,
1682 			 "clm_ratio:((%d percent)) = (%d us/ %d us)\n",
1683 			 ccx->clm_ratio, ccx->clm_result << 2,
1684 			 ccx->clm_period << 2);
1685 
1686 		ccx->clm_manual_ctrl = 0;
1687 	} else if (var1[0] == 3) {
1688 		phydm_set_clm_mntr_mode(dm, (enum clm_monitor_mode)var1[1]);
1689 		PDM_SNPF(out_len, used, output + used, out_len - used,
1690 			 "CLM mode: %s mode\n",
1691 			 ((ccx->clm_mntr_mode == CLM_FW_MNTR) ? "FW" : "Drv"));
1692 	} else { /* Set & trigger CLM */
1693 		ccx->clm_manual_ctrl = 1;
1694 
1695 		if (var1[0] == 1) {
1696 			clm_para.clm_app = CLM_BACKGROUND;
1697 			clm_para.clm_lv = CLM_LV_4;
1698 			clm_para.mntr_time = 262;
1699 			ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1700 		} else if (var1[0] == 2) {
1701 			clm_para.clm_app = (enum clm_application)var1[1];
1702 			clm_para.clm_lv = (enum phydm_clm_level)var1[2];
1703 			ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1704 			clm_para.mntr_time = (u16)var1[3];
1705 		}
1706 
1707 		PDM_SNPF(out_len, used, output + used, out_len - used,
1708 			 "app=%d, lv=%d, mode=%s, time=%d ms\n",
1709 			 clm_para.clm_app, clm_para.clm_lv,
1710 			 ((ccx->clm_mntr_mode == CLM_FW_MNTR) ? "FW" :
1711 			 "driver"), clm_para.mntr_time);
1712 
1713 		if (phydm_clm_mntr_set(dm, &clm_para) == PHYDM_SET_SUCCESS)
1714 			phydm_clm_trigger(dm);
1715 
1716 		PDM_SNPF(out_len, used, output + used, out_len - used,
1717 			 "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
1718 	}
1719 
1720 	*_used = used;
1721 	*_out_len = out_len;
1722 }
1723 
1724 #endif /*@#ifdef CLM_SUPPORT*/
1725 
phydm_env_mntr_trigger(void * dm_void,struct nhm_para_info * nhm_para,struct clm_para_info * clm_para,struct env_trig_rpt * trig_rpt)1726 u8 phydm_env_mntr_trigger(void *dm_void, struct nhm_para_info *nhm_para,
1727 			  struct clm_para_info *clm_para,
1728 			  struct env_trig_rpt *trig_rpt)
1729 {
1730 	u8 trigger_result = 0;
1731 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1732 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1733 	struct ccx_info *ccx = &dm->dm_ccx_info;
1734 	boolean nhm_set_ok = false;
1735 	boolean clm_set_ok = false;
1736 
1737 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1738 
1739 	/*@[NHM]*/
1740 	nhm_set_ok = phydm_nhm_mntr_set(dm, nhm_para);
1741 
1742 	/*@[CLM]*/
1743 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1744 		clm_set_ok = phydm_clm_mntr_set(dm, clm_para);
1745 	} else if (ccx->clm_mntr_mode == CLM_FW_MNTR) {
1746 		phydm_clm_h2c(dm, CLM_PERIOD_MAX, true);
1747 		trigger_result |= CLM_SUCCESS;
1748 	}
1749 
1750 	if (nhm_set_ok) {
1751 		phydm_nhm_trigger(dm);
1752 		trigger_result |= NHM_SUCCESS;
1753 	}
1754 
1755 	if (clm_set_ok) {
1756 		phydm_clm_trigger(dm);
1757 		trigger_result |= CLM_SUCCESS;
1758 	}
1759 
1760 	/*@monitor for the test duration*/
1761 	ccx->start_time = odm_get_current_time(dm);
1762 
1763 	trig_rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
1764 	trig_rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
1765 
1766 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n\n",
1767 		  trig_rpt->nhm_rpt_stamp, trig_rpt->clm_rpt_stamp);
1768 #endif
1769 	return trigger_result;
1770 }
1771 
phydm_env_mntr_result(void * dm_void,struct env_mntr_rpt * rpt)1772 u8 phydm_env_mntr_result(void *dm_void, struct env_mntr_rpt *rpt)
1773 {
1774 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1775 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1776 	struct ccx_info *ccx = &dm->dm_ccx_info;
1777 	u8 env_mntr_rpt = 0;
1778 	u64 progressing_time = 0;
1779 	u32 val_tmp = 0;
1780 
1781 	/*@monitor for the test duration*/
1782 	progressing_time = odm_get_progressing_time(dm, ccx->start_time);
1783 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1784 	PHYDM_DBG(dm, DBG_ENV_MNTR, "env_time=%lld\n", progressing_time);
1785 
1786 	/*@Get NHM result*/
1787 	if (phydm_nhm_get_result(dm)) {
1788 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
1789 		phydm_nhm_get_utility(dm);
1790 		rpt->nhm_ratio = ccx->nhm_ratio;
1791 		rpt->nhm_noise_pwr = ccx->nhm_level;
1792 		rpt->nhm_pwr = ccx->nhm_pwr;
1793 		env_mntr_rpt |= NHM_SUCCESS;
1794 
1795 		odm_move_memory(dm, &rpt->nhm_result[0],
1796 				&ccx->nhm_result[0], NHM_RPT_NUM);
1797 	} else {
1798 		rpt->nhm_ratio = ENV_MNTR_FAIL;
1799 	}
1800 
1801 	/*@Get CLM result*/
1802 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1803 		if (phydm_clm_get_result(dm)) {
1804 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
1805 			phydm_clm_get_utility(dm);
1806 			env_mntr_rpt |= CLM_SUCCESS;
1807 			rpt->clm_ratio = ccx->clm_ratio;
1808 		} else {
1809 			rpt->clm_ratio = ENV_MNTR_FAIL;
1810 		}
1811 
1812 	} else {
1813 		if (ccx->clm_fw_result_cnt != 0) {
1814 			val_tmp = ccx->clm_fw_result_acc
1815 			/ ccx->clm_fw_result_cnt;
1816 			ccx->clm_ratio = (u8)val_tmp;
1817 		} else {
1818 			ccx->clm_ratio = 0;
1819 		}
1820 
1821 		rpt->clm_ratio = ccx->clm_ratio;
1822 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1823 			  "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
1824 			  ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
1825 
1826 		ccx->clm_fw_result_acc = 0;
1827 		ccx->clm_fw_result_cnt = 0;
1828 		env_mntr_rpt |= CLM_SUCCESS;
1829 	}
1830 
1831 	rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
1832 	rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
1833 
1834 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1835 		  "IGI=0x%x, nhm_ratio=%d, clm_ratio=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n\n",
1836 		  ccx->nhm_igi, rpt->nhm_ratio, rpt->clm_ratio,
1837 		  rpt->nhm_rpt_stamp, rpt->clm_rpt_stamp);
1838 
1839 	return env_mntr_rpt;
1840 #endif
1841 }
1842 
1843 /*@Environment Monitor*/
phydm_env_mntr_watchdog(void * dm_void)1844 void phydm_env_mntr_watchdog(void *dm_void)
1845 {
1846 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1847 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1848 	struct ccx_info *ccx = &dm->dm_ccx_info;
1849 	boolean nhm_chk_ok = false;
1850 	boolean clm_chk_ok = false;
1851 
1852 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
1853 		return;
1854 
1855 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1856 	nhm_chk_ok = phydm_nhm_mntr_chk(dm, 262); /*@monitor 262ms*/
1857 	clm_chk_ok = phydm_clm_mntr_chk(dm, 262); /*@monitor 262ms*/
1858 
1859 	/*@PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_chk_ok %d\n\n",nhm_chk_ok);*/
1860 	/*@PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_chk_ok %d\n\n",clm_chk_ok);*/
1861 
1862 	if (nhm_chk_ok)
1863 		phydm_nhm_trigger(dm);
1864 
1865 	if (clm_chk_ok)
1866 		phydm_clm_trigger(dm);
1867 
1868 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1869 		  "Summary: nhm_ratio=((%d)) clm_ratio=((%d))\n\n",
1870 		  ccx->nhm_ratio, ccx->clm_ratio);
1871 #endif
1872 }
1873 
phydm_env_monitor_init(void * dm_void)1874 void phydm_env_monitor_init(void *dm_void)
1875 {
1876 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1877 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1878 
1879 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
1880 		return;
1881 
1882 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1883 	phydm_ccx_hw_restart(dm);
1884 	phydm_nhm_init(dm);
1885 	phydm_clm_init(dm);
1886 #endif
1887 }
1888 
phydm_env_mntr_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1889 void phydm_env_mntr_dbg(void *dm_void, char input[][16], u32 *_used,
1890 			char *output, u32 *_out_len)
1891 {
1892 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1893 	char help[] = "-h";
1894 	u32 var1[10] = {0};
1895 	u32 used = *_used;
1896 	u32 out_len = *_out_len;
1897 	struct clm_para_info clm_para = {0};
1898 	struct nhm_para_info nhm_para = {0};
1899 	struct env_mntr_rpt rpt = {0};
1900 	struct env_trig_rpt trig_rpt = {0};
1901 	struct ccx_info *ccx = &dm->dm_ccx_info;
1902 	u8 set_result = 0;
1903 	u8 i = 0;
1904 
1905 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
1906 
1907 	if ((strcmp(input[1], help) == 0)) {
1908 		PDM_SNPF(out_len, used, output + used, out_len - used,
1909 			 "Basic-Trigger 262ms: {1}\n");
1910 		PDM_SNPF(out_len, used, output + used, out_len - used,
1911 			 "Get Result: {100}\n");
1912 	} else if (var1[0] == 100) { /* Get results */
1913 		set_result = phydm_env_mntr_result(dm, &rpt);
1914 
1915 		PDM_SNPF(out_len, used, output + used, out_len - used,
1916 			 "Set Result=%d\n nhm_ratio=%d clm_ratio=%d\n nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n",
1917 			 set_result, rpt.nhm_ratio, rpt.clm_ratio,
1918 			 rpt.nhm_rpt_stamp, rpt.clm_rpt_stamp);
1919 
1920 		for (i = 0; i <= 11; i++) {
1921 			PDM_SNPF(out_len, used, output + used, out_len - used,
1922 				 "nhm_rpt[%d] = %d (%d percent)\n", i,
1923 				 rpt.nhm_result[i],
1924 				 (((rpt.nhm_result[i] * 100) + 128) >> 8));
1925 		}
1926 		PDM_SNPF(out_len, used, output + used, out_len - used,
1927 			 "[NHM] valid: %d percent, noise(RSSI) = %d\n",
1928 			 ccx->nhm_level_valid, ccx->nhm_level);
1929 	} else { /* Set & trigger*/
1930 		/*nhm para*/
1931 		nhm_para.incld_txon = NHM_EXCLUDE_TXON;
1932 		nhm_para.incld_cca = NHM_EXCLUDE_CCA;
1933 		nhm_para.div_opt = NHM_CNT_ALL;
1934 		nhm_para.nhm_app = NHM_ACS;
1935 		nhm_para.nhm_lv = NHM_LV_2;
1936 		nhm_para.mntr_time = 262;
1937 		nhm_para.en_1db_mode = false;
1938 
1939 		/*clm para*/
1940 		clm_para.clm_app = CLM_ACS;
1941 		clm_para.clm_lv = CLM_LV_2;
1942 		clm_para.mntr_time = 262;
1943 
1944 		set_result = phydm_env_mntr_trigger(dm, &nhm_para,
1945 						    &clm_para, &trig_rpt);
1946 
1947 		PDM_SNPF(out_len, used, output + used, out_len - used,
1948 			 "Set Result=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n",
1949 			 set_result, trig_rpt.nhm_rpt_stamp,
1950 			 trig_rpt.clm_rpt_stamp);
1951 	}
1952 
1953 	*_used = used;
1954 	*_out_len = out_len;
1955 }
1956 
1957 #ifdef IFS_CLM_SUPPORT
phydm_ifs_clm_restart(void * dm_void)1958 void phydm_ifs_clm_restart(void *dm_void)
1959 			  /*Will Restart IFS CLM simultaneously*/
1960 {
1961 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1962 	u32 reg1 = 0;
1963 
1964 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1965 
1966 	/*restart IFS_CLM*/
1967 	odm_set_bb_reg(dm, R_0x1ee4, BIT(29), 0x0);
1968 	odm_set_bb_reg(dm, R_0x1ee4, BIT(29), 0x1);
1969 }
1970 
phydm_ifs_clm_racing_release(void * dm_void)1971 void phydm_ifs_clm_racing_release(void *dm_void)
1972 {
1973 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1974 	struct ccx_info *ccx = &dm->dm_ccx_info;
1975 
1976 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1977 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm lv:(%d)->(0)\n",
1978 		  ccx->ifs_clm_set_lv);
1979 
1980 	ccx->ifs_clm_ongoing = false;
1981 	ccx->ifs_clm_set_lv = IFS_CLM_RELEASE;
1982 	ccx->ifs_clm_app = IFS_CLM_BACKGROUND;
1983 }
1984 
phydm_ifs_clm_racing_ctrl(void * dm_void,enum phydm_ifs_clm_level ifs_clm_lv)1985 u8 phydm_ifs_clm_racing_ctrl(void *dm_void, enum phydm_ifs_clm_level ifs_clm_lv)
1986 {
1987 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1988 	struct ccx_info *ccx = &dm->dm_ccx_info;
1989 	u8 set_result = PHYDM_SET_SUCCESS;
1990 	/*acquire to control IFS CLM API*/
1991 
1992 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm_ongoing=%d, lv:(%d)->(%d)\n",
1993 		  ccx->ifs_clm_ongoing, ccx->ifs_clm_set_lv, ifs_clm_lv);
1994 	if (ccx->ifs_clm_ongoing) {
1995 		if (ifs_clm_lv <= ccx->ifs_clm_set_lv) {
1996 			set_result = PHYDM_SET_FAIL;
1997 		} else {
1998 			phydm_ifs_clm_restart(dm);
1999 			ccx->ifs_clm_ongoing = false;
2000 		}
2001 	}
2002 
2003 	if (set_result)
2004 		ccx->ifs_clm_set_lv = ifs_clm_lv;
2005 
2006 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm racing success=%d\n", set_result);
2007 	return set_result;
2008 }
2009 
phydm_ifs_clm_trigger(void * dm_void)2010 void phydm_ifs_clm_trigger(void *dm_void)
2011 {
2012 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2013 	struct ccx_info *ccx = &dm->dm_ccx_info;
2014 
2015 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2016 
2017 	/*Trigger IFS_CLM*/
2018 	pdm_set_reg(dm, R_0x1ee4, BIT(29), 0);
2019 	pdm_set_reg(dm, R_0x1ee4, BIT(29), 1);
2020 	ccx->ifs_clm_trigger_time = dm->phydm_sys_up_time;
2021 	ccx->ifs_clm_rpt_stamp++;
2022 	ccx->ifs_clm_ongoing = true;
2023 }
2024 
phydm_ifs_clm_get_utility(void * dm_void)2025 void phydm_ifs_clm_get_utility(void *dm_void)
2026 {
2027 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2028 	struct ccx_info *ccx = &dm->dm_ccx_info;
2029 	u32 numerator = 0;
2030 	u16 denomirator = 0;
2031 
2032 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2033 
2034 	denomirator = ccx->ifs_clm_period;
2035 	numerator = ccx->ifs_clm_tx * 100;
2036 	ccx->ifs_clm_tx_ratio = (u8)PHYDM_DIV(numerator, denomirator);
2037 	numerator = ccx->ifs_clm_edcca_excl_cca * 100;
2038 	ccx->ifs_clm_edcca_excl_cca_ratio = (u8)PHYDM_DIV(numerator,
2039 							  denomirator);
2040 	numerator = (ccx->ifs_clm_cckfa + ccx->ifs_clm_ofdmfa) * 100;
2041 	ccx->ifs_clm_fa_ratio = (u8)PHYDM_DIV(numerator, denomirator);
2042 	numerator = (ccx->ifs_clm_cckcca_excl_fa +
2043 		     ccx->ifs_clm_ofdmcca_excl_fa) * 100;
2044 	ccx->ifs_clm_cca_excl_fa_ratio = (u8)PHYDM_DIV(numerator, denomirator);
2045 
2046 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2047 		  "Tx_ratio = %d, EDCCA_exclude_CCA_ratio = %d \n",
2048 		  ccx->ifs_clm_tx_ratio, ccx->ifs_clm_edcca_excl_cca_ratio);
2049 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2050 		  "FA_ratio = %d, CCA_exclude_FA_ratio = %d \n",
2051 		  ccx->ifs_clm_fa_ratio, ccx->ifs_clm_cca_excl_fa_ratio);
2052 }
2053 
phydm_ifs_clm_get_result(void * dm_void)2054 void phydm_ifs_clm_get_result(void *dm_void)
2055 {
2056 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2057 	struct ccx_info *ccx = &dm->dm_ccx_info;
2058 	u32 value32 = 0;
2059 	u8 i = 0;
2060 
2061 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2062 
2063 	/*Enhance CLM result*/
2064 	value32 = odm_get_bb_reg(dm, R_0x2e60, MASKDWORD);
2065 	ccx->ifs_clm_tx = (u16)(value32 & MASKLWORD);
2066 	ccx->ifs_clm_edcca_excl_cca = (u16)((value32 & MASKHWORD) >> 16);
2067 	value32 = odm_get_bb_reg(dm, R_0x2e64, MASKDWORD);
2068 	ccx->ifs_clm_ofdmfa = (u16)(value32 & MASKLWORD);
2069 	ccx->ifs_clm_ofdmcca_excl_fa = (u16)((value32 & MASKHWORD) >> 16);
2070 	value32 = odm_get_bb_reg(dm, R_0x2e68, MASKDWORD);
2071 	ccx->ifs_clm_cckfa = (u16)(value32 & MASKLWORD);
2072 	ccx->ifs_clm_cckcca_excl_fa = (u16)((value32 & MASKHWORD) >> 16);
2073 	value32 = odm_get_bb_reg(dm, R_0x2e6c, MASKDWORD);
2074 	ccx->ifs_clm_total_cca = (u16)(value32 & MASKLWORD);
2075 
2076 	/* IFS result */
2077 	value32 = odm_get_bb_reg(dm, R_0x2e70, MASKDWORD);
2078 	odm_move_memory(dm, &ccx->ifs_clm_his[0], &value32, 4);
2079 	value32 = odm_get_bb_reg(dm, R_0x2e74, MASKDWORD);
2080 	ccx->ifs_clm_avg[0] = (u16)(value32 & MASKLWORD);
2081 	ccx->ifs_clm_avg[1] = (u16)((value32 & MASKHWORD) >> 16);
2082 	value32 = odm_get_bb_reg(dm, R_0x2e78, MASKDWORD);
2083 	ccx->ifs_clm_avg[2] = (u16)(value32 & MASKLWORD);
2084 	ccx->ifs_clm_avg[3] = (u16)((value32 & MASKHWORD) >> 16);
2085 	value32 = odm_get_bb_reg(dm, R_0x2e7c, MASKDWORD);
2086 	ccx->ifs_clm_avg_cca[0] = (u16)(value32 & MASKLWORD);
2087 	ccx->ifs_clm_avg_cca[1] = (u16)((value32 & MASKHWORD) >> 16);
2088 	value32 = odm_get_bb_reg(dm, R_0x2e80, MASKDWORD);
2089 	ccx->ifs_clm_avg_cca[2] = (u16)(value32 & MASKLWORD);
2090 	ccx->ifs_clm_avg_cca[3] = (u16)((value32 & MASKHWORD) >> 16);
2091 
2092 	/* Print Result */
2093 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2094 		  "ECLM_Rpt[%d]: \nTx = %d, EDCCA_exclude_CCA = %d \n",
2095 		  ccx->ifs_clm_rpt_stamp, ccx->ifs_clm_tx,
2096 		  ccx->ifs_clm_edcca_excl_cca);
2097 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2098 		  "[FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2099 		  ccx->ifs_clm_cckfa, ccx->ifs_clm_ofdmfa);
2100 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2101 		  "[CCA_exclude_FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2102 		  ccx->ifs_clm_cckcca_excl_fa, ccx->ifs_clm_ofdmcca_excl_fa);
2103 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CCATotal = %d\n", ccx->ifs_clm_total_cca);
2104 	PHYDM_DBG(dm, DBG_ENV_MNTR, "Time:[his, avg, avg_cca]\n");
2105 	for (i = 0; i < IFS_CLM_NUM; i++)
2106 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2107 			  "T%d:[%d, %d, %d]\n", i + 1,
2108 			  ccx->ifs_clm_his[i], ccx->ifs_clm_avg[i],
2109 			  ccx->ifs_clm_avg_cca[i]);
2110 
2111 	phydm_ifs_clm_racing_release(dm);
2112 
2113 	return;
2114 }
2115 
phydm_ifs_clm_set_th_reg(void * dm_void)2116 void phydm_ifs_clm_set_th_reg(void *dm_void)
2117 {
2118 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2119 	struct ccx_info *ccx = &dm->dm_ccx_info;
2120 	u8 i = 0;
2121 
2122 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2123 
2124 	/*Set IFS period TH*/
2125 	odm_set_bb_reg(dm, R_0x1ed4, BIT(31), ccx->ifs_clm_th_en[0]);
2126 	odm_set_bb_reg(dm, R_0x1ed8, BIT(31), ccx->ifs_clm_th_en[1]);
2127 	odm_set_bb_reg(dm, R_0x1edc, BIT(31), ccx->ifs_clm_th_en[2]);
2128 	odm_set_bb_reg(dm, R_0x1ee0, BIT(31), ccx->ifs_clm_th_en[3]);
2129 	odm_set_bb_reg(dm, R_0x1ed4, 0x7fff0000, ccx->ifs_clm_th_low[0]);
2130 	odm_set_bb_reg(dm, R_0x1ed8, 0x7fff0000, ccx->ifs_clm_th_low[1]);
2131 	odm_set_bb_reg(dm, R_0x1edc, 0x7fff0000, ccx->ifs_clm_th_low[2]);
2132 	odm_set_bb_reg(dm, R_0x1ee0, 0x7fff0000, ccx->ifs_clm_th_low[3]);
2133 	odm_set_bb_reg(dm, R_0x1ed4, MASKLWORD, ccx->ifs_clm_th_high[0]);
2134 	odm_set_bb_reg(dm, R_0x1ed8, MASKLWORD, ccx->ifs_clm_th_high[1]);
2135 	odm_set_bb_reg(dm, R_0x1edc, MASKLWORD, ccx->ifs_clm_th_high[2]);
2136 	odm_set_bb_reg(dm, R_0x1ee0, MASKLWORD, ccx->ifs_clm_th_high[3]);
2137 
2138 	for (i = 0; i < IFS_CLM_NUM; i++)
2139 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2140 			  "Update IFS_CLM_th%d[High Low] : [%d %d]\n", i + 1,
2141 		  	  ccx->ifs_clm_th_high[i], ccx->ifs_clm_th_low[i]);
2142 }
2143 
phydm_ifs_clm_th_update_chk(void * dm_void,enum ifs_clm_application ifs_clm_app,boolean * ifs_clm_th_en,u16 * ifs_clm_th_low,u16 * ifs_clm_th_high,s16 th_shift)2144 boolean phydm_ifs_clm_th_update_chk(void *dm_void,
2145 				    enum ifs_clm_application ifs_clm_app,
2146 				    boolean *ifs_clm_th_en, u16 *ifs_clm_th_low,
2147 				    u16 *ifs_clm_th_high, s16 th_shift)
2148 {
2149 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2150 	struct ccx_info *ccx = &dm->dm_ccx_info;
2151 	boolean is_update = false;
2152 	u16 ifs_clm_th_low_bg[IFS_CLM_NUM] = {12, 5, 2, 0};
2153 	u16 ifs_clm_th_high_bg[IFS_CLM_NUM] = {64, 12, 5, 2};
2154 	u8 i = 0;
2155 
2156 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2157 	PHYDM_DBG(dm, DBG_ENV_MNTR, "App=%d, th_shift=%d\n", ifs_clm_app,
2158 		  th_shift);
2159 
2160 	switch (ifs_clm_app) {
2161 	case IFS_CLM_BACKGROUND:
2162 		if (ccx->ifs_clm_app != ifs_clm_app || th_shift != 0) {
2163 			is_update = true;
2164 
2165 			for (i = 0; i < IFS_CLM_NUM; i++) {
2166 				ifs_clm_th_en[i] = true;
2167 				ifs_clm_th_low[i] = ifs_clm_th_low_bg[i];
2168 				ifs_clm_th_high[i] = ifs_clm_th_high_bg[i];
2169 			}
2170 		}
2171 		break;
2172 	case IFS_CLM_DBG:
2173 		if (ccx->ifs_clm_app != ifs_clm_app || th_shift != 0) {
2174 			is_update = true;
2175 
2176 			for (i = 0; i < IFS_CLM_NUM; i++) {
2177 				ifs_clm_th_en[i] = true;
2178 				ifs_clm_th_low[i] = MAX_2(ccx->ifs_clm_th_low[i] +
2179 						    th_shift, 0);
2180 				ifs_clm_th_high[i] = MAX_2(ccx->ifs_clm_th_high[i] +
2181 						     th_shift, 0);
2182 			}
2183 		}
2184 		break;
2185 	default:
2186 		break;
2187 	}
2188 
2189 	if (is_update)
2190 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update IFS_TH]\n");
2191 	else
2192 		PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update IFS_TH\n");
2193 
2194 	return is_update;
2195 }
2196 
phydm_ifs_clm_set(void * dm_void,enum ifs_clm_application ifs_clm_app,u16 period,u8 ctrl_unit,s16 th_shift)2197 void phydm_ifs_clm_set(void *dm_void, enum ifs_clm_application ifs_clm_app,
2198 		       u16 period, u8 ctrl_unit, s16 th_shift)
2199 {
2200 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2201 	struct ccx_info *ccx = &dm->dm_ccx_info;
2202 	boolean ifs_clm_th_en[IFS_CLM_NUM] =  {0};
2203 	u16 ifs_clm_th_low[IFS_CLM_NUM] =  {0};
2204 	u16 ifs_clm_th_high[IFS_CLM_NUM] =  {0};
2205 
2206 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2207 	PHYDM_DBG(dm, DBG_ENV_MNTR, "period=%d, ctrl_unit=%d\n", period,
2208 		  ctrl_unit);
2209 
2210 	/*Set Unit*/
2211 	if (ctrl_unit != ccx->ifs_clm_ctrl_unit) {
2212 		odm_set_bb_reg(dm, R_0x1ee4, 0xc0000000, ctrl_unit);
2213 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2214 			  "Update IFS_CLM unit ((%d)) -> ((%d))\n",
2215 			  ccx->ifs_clm_ctrl_unit, ctrl_unit);
2216 		ccx->ifs_clm_ctrl_unit = ctrl_unit;
2217 	}
2218 
2219 	/*Set Duration*/
2220 	if (period != ccx->ifs_clm_period) {
2221 		odm_set_bb_reg(dm, R_0x1eec, 0xc0000000, (period & 0x3));
2222 		odm_set_bb_reg(dm, R_0x1ef0, 0xfe000000, ((period >> 2) &
2223 			       0x7f));
2224 		odm_set_bb_reg(dm, R_0x1ef4, 0xc0000000, ((period >> 9) &
2225 			       0x3));
2226 		odm_set_bb_reg(dm, R_0x1ef8, 0x3e000000, ((period >> 11) &
2227 			       0x1f));
2228 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2229 			  "Update IFS_CLM period ((%d)) -> ((%d))\n",
2230 			  ccx->ifs_clm_period, period);
2231 		ccx->ifs_clm_period = period;
2232 	}
2233 
2234 	/*Set IFS CLM threshold*/
2235 	if (phydm_ifs_clm_th_update_chk(dm, ccx->ifs_clm_app, &ifs_clm_th_en[0],
2236 					&ifs_clm_th_low[0], &ifs_clm_th_high[0],
2237 					th_shift)) {
2238 
2239 		ccx->ifs_clm_app = ifs_clm_app;
2240 		odm_move_memory(dm, &ccx->ifs_clm_th_en[0], &ifs_clm_th_en,
2241 				IFS_CLM_NUM);
2242 		odm_move_memory(dm, &ccx->ifs_clm_th_low[0], &ifs_clm_th_low,
2243 				IFS_CLM_NUM);
2244 		odm_move_memory(dm, &ccx->ifs_clm_th_high[0], &ifs_clm_th_high,
2245 				IFS_CLM_NUM);
2246 
2247 		phydm_ifs_clm_set_th_reg(dm);
2248 	}
2249 }
2250 
phydm_ifs_clm_mntr_set(void * dm_void,struct ifs_clm_para_info * ifs_clm_para)2251 u8 phydm_ifs_clm_mntr_set(void *dm_void, struct ifs_clm_para_info *ifs_clm_para)
2252 {
2253 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2254 	u16 ifs_clm_time = 0; /*unit: 4/8/12/16us*/
2255 	u8 unit = 0;
2256 
2257 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2258 
2259 	if (ifs_clm_para->mntr_time == 0)
2260 		return PHYDM_SET_FAIL;
2261 
2262 	if (ifs_clm_para->ifs_clm_lv >= IFS_CLM_MAX_NUM) {
2263 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n",
2264 			  ifs_clm_para->ifs_clm_lv);
2265 		return PHYDM_SET_FAIL;
2266 	}
2267 
2268 	if (phydm_ifs_clm_racing_ctrl(dm, ifs_clm_para->ifs_clm_lv) == PHYDM_SET_FAIL)
2269 		return PHYDM_SET_FAIL;
2270 
2271 	if (ifs_clm_para->mntr_time >= 1048) {
2272 		unit = IFS_CLM_16;
2273 		ifs_clm_time = IFS_CLM_PERIOD_MAX; /*65535 * 16us = 1048ms*/
2274 	} else if (ifs_clm_para->mntr_time >= 786) {/*65535 * 12us = 786 ms*/
2275 		unit = IFS_CLM_16;
2276 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 16);
2277 	} else if (ifs_clm_para->mntr_time >= 524) {
2278 		unit = IFS_CLM_12;
2279 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 12);
2280 	} else if (ifs_clm_para->mntr_time >= 262) {
2281 		unit = IFS_CLM_8;
2282 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 8);
2283 	} else {
2284 		unit = IFS_CLM_4;
2285 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 4);
2286 	}
2287 
2288 	phydm_ifs_clm_set(dm, ifs_clm_para->ifs_clm_app, ifs_clm_time, unit,
2289 			  ifs_clm_para->th_shift);
2290 
2291 	return PHYDM_SET_SUCCESS;
2292 }
2293 
2294 boolean
phydm_ifs_clm_mntr_chk(void * dm_void,u16 monitor_time)2295 phydm_ifs_clm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
2296 {
2297 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2298 	struct ccx_info *ccx = &dm->dm_ccx_info;
2299 	struct ifs_clm_para_info ifs_clm_para = {0};
2300 	boolean ifs_clm_chk_result = false;
2301 	u32 sys_return_time = 0;
2302 
2303 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2304 
2305 	if (ccx->ifs_clm_manual_ctrl) {
2306 		PHYDM_DBG(dm, DBG_ENV_MNTR, "IFS CLM in manual ctrl\n");
2307 		return ifs_clm_chk_result;
2308 	}
2309 
2310 	sys_return_time = ccx->ifs_clm_trigger_time + MAX_ENV_MNTR_TIME;
2311 	if (ccx->ifs_clm_app != IFS_CLM_BACKGROUND &&
2312 	    (sys_return_time > dm->phydm_sys_up_time)) {
2313 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2314 			  "ifs_clm_app=%d, trigger_time %d, sys_time=%d\n",
2315 			  ccx->ifs_clm_app, ccx->ifs_clm_trigger_time,
2316 			  dm->phydm_sys_up_time);
2317 
2318 		return ifs_clm_chk_result;
2319 	}
2320 
2321 	/*[IFS CLM get result ------------------------------------]*/
2322 	phydm_ifs_clm_get_result(dm);
2323 	phydm_ifs_clm_get_utility(dm);
2324 
2325 	/*[IFS CLM trigger setting]------------------------------------------*/
2326 	ifs_clm_para.ifs_clm_app = IFS_CLM_BACKGROUND;
2327 	ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_1;
2328 	ifs_clm_para.mntr_time = monitor_time;
2329 	ifs_clm_para.th_shift = 0;
2330 
2331 	ifs_clm_chk_result = phydm_ifs_clm_mntr_set(dm, &ifs_clm_para);
2332 
2333 	return ifs_clm_chk_result;
2334 }
2335 
phydm_ifs_clm_init(void * dm_void)2336 void phydm_ifs_clm_init(void *dm_void)
2337 {
2338 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2339 	struct ccx_info *ccx = &dm->dm_ccx_info;
2340 
2341 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2342 	if (!(dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8812F |
2343 				     ODM_RTL8197G)))
2344 		return;
2345 
2346 	ccx->ifs_clm_app = IFS_CLM_BACKGROUND;
2347 
2348 	/*Set IFS threshold*/
2349 	ccx->ifs_clm_ongoing = false;
2350 	ccx->ifs_clm_set_lv = IFS_CLM_RELEASE;
2351 
2352 	if (phydm_ifs_clm_th_update_chk(dm, ccx->ifs_clm_app,
2353 					&ccx->ifs_clm_th_en[0],
2354 					&ccx->ifs_clm_th_low[0],
2355 					&ccx->ifs_clm_th_high[0], 0xffff))
2356 		phydm_ifs_clm_set_th_reg(dm);
2357 
2358 	ccx->ifs_clm_period = 0;
2359 	ccx->ifs_clm_ctrl_unit = IFS_CLM_INIT;
2360 	ccx->ifs_clm_manual_ctrl = 0;
2361 	ccx->ifs_clm_rpt_stamp = 0;
2362 }
2363 
phydm_ifs_clm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)2364 void phydm_ifs_clm_dbg(void *dm_void, char input[][16], u32 *_used,
2365 		       char *output, u32 *_out_len)
2366 {
2367 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2368 	struct ccx_info *ccx = &dm->dm_ccx_info;
2369 	struct ifs_clm_para_info ifs_clm_para;
2370 	char help[] = "-h";
2371 	u32 var1[10] = {0};
2372 	u32 used = *_used;
2373 	u32 out_len = *_out_len;
2374 	u8 result_tmp = 0;
2375 	u8 i = 0;
2376 	u16 th_shift = 0;
2377 
2378 	for (i = 0; i < 5; i++) {
2379 		if (input[i + 1])
2380 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
2381 				     &var1[i]);
2382 	}
2383 
2384 	if ((strcmp(input[1], help) == 0)) {
2385 		PDM_SNPF(out_len, used, output + used, out_len - used,
2386 			 "IFS_CLM Basic-Trigger 960ms: {1}\n");
2387 		PDM_SNPF(out_len, used, output + used, out_len - used,
2388 			 "IFS_CLM Adv-Trigger: {2} {App} {LV:1~4} {0~2096ms} {th_shift}\n");
2389 		PDM_SNPF(out_len, used, output + used, out_len - used,
2390 			 "IFS_CLM Get Result: {100}\n");
2391 	} else if (var1[0] == 100) { /*Get IFS_CLM results*/
2392 
2393 		PDM_SNPF(out_len, used, output + used, out_len - used,
2394 			 "rpt_stamp=%d\n", ccx->ifs_clm_rpt_stamp);
2395 
2396 		phydm_ifs_clm_get_result(dm);
2397 
2398 		PDM_SNPF(out_len, used, output + used, out_len - used,
2399 			  "ECLM_Rpt[%d]: \nTx = %d \nEDCCA_exclude_CCA = %d\n",
2400 			  ccx->ifs_clm_rpt_stamp, ccx->ifs_clm_tx,
2401 			  ccx->ifs_clm_edcca_excl_cca);
2402 		PDM_SNPF(out_len, used, output + used, out_len - used,
2403 			  "[FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2404 			  ccx->ifs_clm_cckfa, ccx->ifs_clm_ofdmfa);
2405 		PDM_SNPF(out_len, used, output + used, out_len - used,
2406 			  "[CCA_exclude_FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2407 			  ccx->ifs_clm_cckcca_excl_fa,
2408 			  ccx->ifs_clm_ofdmcca_excl_fa);
2409 		PDM_SNPF(out_len, used, output + used, out_len - used,
2410 			 "CCATotal = %d\n", ccx->ifs_clm_total_cca);
2411 		PDM_SNPF(out_len, used, output + used, out_len - used,
2412 			 "Time:[his, avg, avg_cca]\n");
2413 		for (i = 0; i < IFS_CLM_NUM; i++)
2414 			PDM_SNPF(out_len, used, output + used, out_len - used,
2415 				  "T%d:[%d, %d, %d]\n", i + 1,
2416 				  ccx->ifs_clm_his[i], ccx->ifs_clm_avg[i],
2417 				  ccx->ifs_clm_avg_cca[i]);
2418 
2419 		phydm_ifs_clm_get_utility(dm);
2420 
2421 		ccx->ifs_clm_manual_ctrl = 0;
2422 	} else { /*IFS_CLM trigger*/
2423 		ccx->ifs_clm_manual_ctrl = 1;
2424 
2425 		if (var1[0] == 1) {
2426 			ifs_clm_para.ifs_clm_app = IFS_CLM_DBG;
2427 			ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_4;
2428 			ifs_clm_para.mntr_time = 960;
2429 			ifs_clm_para.th_shift = 0;
2430 		} else {
2431 			ifs_clm_para.ifs_clm_app = (enum ifs_clm_application)var1[1];
2432 			ifs_clm_para.ifs_clm_lv = (enum phydm_ifs_clm_level)var1[2];
2433 			ifs_clm_para.mntr_time = (u16)var1[3];
2434 			ifs_clm_para.th_shift = (s16)var1[4];
2435 		}
2436 
2437 		PDM_SNPF(out_len, used, output + used, out_len - used,
2438 			 "app=%d, lv=%d, time=%d ms, th_shift=%s%d\n",
2439 			 ifs_clm_para.ifs_clm_app, ifs_clm_para.ifs_clm_lv,
2440 			 ifs_clm_para.mntr_time,
2441 			 (ifs_clm_para.th_shift > 0) ? "+" : "-",
2442 			 ifs_clm_para.th_shift);
2443 
2444 		if (phydm_ifs_clm_mntr_set(dm, &ifs_clm_para) == PHYDM_SET_SUCCESS)
2445 			phydm_ifs_clm_trigger(dm);
2446 
2447 		PDM_SNPF(out_len, used, output + used, out_len - used,
2448 			 "rpt_stamp=%d\n", ccx->ifs_clm_rpt_stamp);
2449 		for (i = 0; i < IFS_CLM_NUM; i++)
2450 			PDM_SNPF(out_len, used, output + used, out_len - used,
2451 				  "IFS_CLM_th%d[High Low] : [%d %d]\n", i + 1,
2452 			  	  ccx->ifs_clm_th_high[i],
2453 			  	  ccx->ifs_clm_th_low[i]);
2454 	}
2455 
2456 	*_used = used;
2457 	*_out_len = out_len;
2458 }
2459 #endif
2460 
phydm_enhance_mntr_trigger(void * dm_void,struct ifs_clm_para_info * ifs_clm_para,struct enhance_mntr_trig_rpt * trig_rpt)2461 u8 phydm_enhance_mntr_trigger(void *dm_void,
2462 			      struct ifs_clm_para_info *ifs_clm_para,
2463 			      struct enhance_mntr_trig_rpt *trig_rpt)
2464 {
2465 	u8 trigger_result = 0;
2466 #ifdef IFS_CLM_SUPPORT
2467 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2468 	struct ccx_info *ccx = &dm->dm_ccx_info;
2469 	boolean ifs_clm_set_ok = false;
2470 
2471 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
2472 
2473 	ifs_clm_set_ok = phydm_ifs_clm_mntr_set(dm, ifs_clm_para);
2474 
2475 	if (ifs_clm_set_ok) {
2476 		phydm_ifs_clm_trigger(dm);
2477 		trigger_result |= IFS_CLM_SUCCESS;
2478 	}
2479 
2480 	/*monitor for the test duration*/
2481 	ccx->start_time = odm_get_current_time(dm);
2482 
2483 	trig_rpt->ifs_clm_rpt_stamp = ccx->ifs_clm_rpt_stamp;
2484 
2485 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs_clm_rpt_stamp=%d\n\n",
2486 		  trig_rpt->ifs_clm_rpt_stamp);
2487 #endif
2488 	return trigger_result;
2489 }
2490 
phydm_enhance_mntr_result(void * dm_void,struct enhance_mntr_rpt * rpt)2491 void phydm_enhance_mntr_result(void *dm_void, struct enhance_mntr_rpt *rpt)
2492 {
2493 #ifdef IFS_CLM_SUPPORT
2494 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2495 	struct ccx_info *ccx = &dm->dm_ccx_info;
2496 	u8 enhance_mntr_mntr_rpt = 0;
2497 	u64 progressing_time = 0;
2498 	u32 val_tmp = 0;
2499 
2500 	/*monitor for the test duration*/
2501 	progressing_time = odm_get_progressing_time(dm, ccx->start_time);
2502 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
2503 	PHYDM_DBG(dm, DBG_ENV_MNTR, "enhance_mntr_time=%lld\n",
2504 		  progressing_time);
2505 
2506 	/*Get IFS_CLM result*/
2507 	phydm_ifs_clm_get_result(dm);
2508 	phydm_ifs_clm_get_utility(dm);
2509 	rpt->ifs_clm_tx_ratio = ccx->ifs_clm_tx_ratio;
2510 	rpt->ifs_clm_edcca_excl_cca_ratio = ccx->ifs_clm_edcca_excl_cca_ratio;
2511 	rpt->ifs_clm_fa_ratio = ccx->ifs_clm_fa_ratio;
2512 	rpt->ifs_clm_cca_excl_fa_ratio = ccx->ifs_clm_cca_excl_fa_ratio;
2513 	rpt->ifs_clm_rpt_stamp = ccx->ifs_clm_rpt_stamp;
2514 
2515 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs_clm_rpt_stamp = %d\n",
2516 		  ccx->ifs_clm_rpt_stamp);
2517 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2518 		  "Tx_ratio = %d, EDCCA_exclude_CCA_ratio = %d \n",
2519 		  ccx->ifs_clm_tx_ratio,
2520 		  ccx->ifs_clm_edcca_excl_cca_ratio);
2521 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2522 		  "FA_ratio = %d, CCA_exclude_FA_ratio = %d \n",
2523 		  ccx->ifs_clm_fa_ratio, ccx->ifs_clm_cca_excl_fa_ratio);
2524 #endif
2525 }
2526 
phydm_enhance_mntr_watchdog(void * dm_void)2527 void phydm_enhance_mntr_watchdog(void *dm_void)
2528 {
2529 #ifdef IFS_CLM_SUPPORT
2530 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2531 	struct ccx_info *ccx = &dm->dm_ccx_info;
2532 	boolean ifs_clm_chk_ok = false;
2533 
2534 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
2535 		return;
2536 
2537 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2538 	ifs_clm_chk_ok = phydm_ifs_clm_mntr_chk(dm, 960); /*monitor 960ms*/
2539 
2540 	if (ifs_clm_chk_ok)
2541 		phydm_ifs_clm_trigger(dm);
2542 #endif
2543 }
2544 
phydm_enhance_monitor_init(void * dm_void)2545 void phydm_enhance_monitor_init(void *dm_void)
2546 {
2547 #ifdef IFS_CLM_SUPPORT
2548 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2549 
2550 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
2551 		return;
2552 
2553 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2554 	phydm_ifs_clm_restart(dm);
2555 	phydm_ifs_clm_init(dm);
2556 #endif
2557 }
2558 
phydm_enhance_mntr_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)2559 void phydm_enhance_mntr_dbg(void *dm_void, char input[][16], u32 *_used,
2560 			    char *output, u32 *_out_len)
2561 {
2562 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2563 	char help[] = "-h";
2564 	u32 var1[10] = {0};
2565 	u32 used = *_used;
2566 	u32 out_len = *_out_len;
2567 	struct ifs_clm_para_info ifs_clm_para = {0};
2568 	struct enhance_mntr_rpt rpt = {0};
2569 	struct enhance_mntr_trig_rpt trig_rpt = {0};
2570 	struct ccx_info *ccx = &dm->dm_ccx_info;
2571 	u8 set_result = 0;
2572 	u8 i = 0;
2573 
2574 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
2575 
2576 	if ((strcmp(input[1], help) == 0)) {
2577 		PDM_SNPF(out_len, used, output + used, out_len - used,
2578 			 "Basic-Trigger 960ms: {1}\n");
2579 		PDM_SNPF(out_len, used, output + used, out_len - used,
2580 			 "Get Result: {100}\n");
2581 	} else if (var1[0] == 100) { /* Get results */
2582 		phydm_enhance_mntr_result(dm, &rpt);
2583 
2584 		PDM_SNPF(out_len, used, output + used, out_len - used,
2585 			  "Tx_ratio = %d, EDCCA_exclude_CCA_ratio = %d \n",
2586 			  rpt.ifs_clm_tx_ratio,
2587 			  rpt.ifs_clm_edcca_excl_cca_ratio);
2588 		PDM_SNPF(out_len, used, output + used, out_len - used,
2589 			  "FA_ratio = %d, CCA_exclude_FA_ratio = %d \n",
2590 			  rpt.ifs_clm_fa_ratio, rpt.ifs_clm_cca_excl_fa_ratio);
2591 	} else { /* Set & trigger*/
2592 		ifs_clm_para.ifs_clm_app = HP_TAS;
2593 		ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_2;
2594 		ifs_clm_para.mntr_time = 960;
2595 		ifs_clm_para.th_shift = 0;
2596 
2597 		set_result = phydm_enhance_mntr_trigger(dm, &ifs_clm_para,
2598 							&trig_rpt);
2599 
2600 		PDM_SNPF(out_len, used, output + used, out_len - used,
2601 			 "Set Result=%d, ifs_clm_rpt_stamp=%d\n",
2602 			 set_result, trig_rpt.ifs_clm_rpt_stamp);
2603 	}
2604 
2605 	*_used = used;
2606 	*_out_len = out_len;
2607 }
2608 
2609