xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8723ds/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_env_mntr_get_802_11_k_rsni(void * dm_void,s8 rcpi,s8 anpi)29 u8 phydm_env_mntr_get_802_11_k_rsni(void *dm_void, s8 rcpi, s8 anpi)
30 {
31 	u8 rsni = 0;
32 	u8 signal = 0;
33 	u8 sig_to_rsni[13] = {0, 8, 15, 20, 24, 27, 30, 32, 35, 37, 39, 41, 43};
34 
35 	/*rcpi = signal + noise + interference = rssi*/
36 	/*anpi = noise + interferecne = nhm*/
37 	/*signal = rcpi - anpi*/
38 
39 	/*rsni = 2*(10*log10((rcpi_lin/anpi_lin)-1)+10), unit = 0.5dB*/
40 	/*rcpi_lin/anpi_lin=10^((rcpi_dB-anpi_db)/10)*/
41 	/*rsni is approximated as 2*((rcpi_db-anpi_db)+10) when signal >= 13*/
42 
43 	if (rcpi <= anpi)
44 		signal = 0;
45 	else if (rcpi - anpi >= 117)
46 		signal = 117;
47 	else
48 		signal = rcpi - anpi;
49 
50 	if (signal < 13)
51 		rsni = sig_to_rsni[signal];
52 	else
53 		rsni = 2 * (signal + 10);
54 
55 	return rsni;
56 }
57 
phydm_ccx_hw_restart(void * dm_void)58 void phydm_ccx_hw_restart(void *dm_void)
59 			  /*@Will Restart NHM/CLM/FAHM simultaneously*/
60 {
61 	struct dm_struct *dm = (struct dm_struct *)dm_void;
62 	u32 reg1 = 0;
63 
64 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
65 		reg1 = R_0x994;
66 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
67 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
68 		reg1 = R_0x1e60;
69 	#endif
70 	else
71 		reg1 = R_0x890;
72 
73 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
74 	/*@disable NHM,CLM, FAHM*/
75 	odm_set_bb_reg(dm, reg1, 0x7, 0x0);
76 	odm_set_bb_reg(dm, reg1, BIT(8), 0x0);
77 	odm_set_bb_reg(dm, reg1, BIT(8), 0x1);
78 }
79 
phydm_ccx_get_rpt_ratio(void * dm_void,u16 rpt,u16 denom)80 u8 phydm_ccx_get_rpt_ratio(void *dm_void, u16 rpt, u16 denom)
81 {
82 	u32 numer = 0;
83 
84 	numer = rpt * 100 + (denom >> 1);
85 
86 	return (u8)PHYDM_DIV(numer, denom);
87 }
88 
89 #ifdef NHM_SUPPORT
90 
phydm_nhm_racing_release(void * dm_void)91 void phydm_nhm_racing_release(void *dm_void)
92 {
93 	struct dm_struct *dm = (struct dm_struct *)dm_void;
94 	struct ccx_info *ccx = &dm->dm_ccx_info;
95 	u32 value32 = 0;
96 
97 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
98 	PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->nhm_set_lv);
99 
100 	ccx->nhm_ongoing = false;
101 	ccx->nhm_set_lv = NHM_RELEASE;
102 
103 	if (!(ccx->nhm_app == NHM_BACKGROUND || ccx->nhm_app == NHM_ACS)) {
104 		phydm_pause_func(dm, F00_DIG, PHYDM_RESUME,
105 				 PHYDM_PAUSE_LEVEL_1, 1, &value32);
106 	}
107 
108 	ccx->nhm_app = NHM_BACKGROUND;
109 }
110 
phydm_nhm_racing_ctrl(void * dm_void,enum phydm_nhm_level nhm_lv)111 u8 phydm_nhm_racing_ctrl(void *dm_void, enum phydm_nhm_level nhm_lv)
112 {
113 	struct dm_struct *dm = (struct dm_struct *)dm_void;
114 	struct ccx_info *ccx = &dm->dm_ccx_info;
115 	u8 set_result = PHYDM_SET_SUCCESS;
116 	/*@acquire to control NHM API*/
117 
118 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_ongoing=%d, lv:(%d)->(%d)\n",
119 		  ccx->nhm_ongoing, ccx->nhm_set_lv, nhm_lv);
120 	if (ccx->nhm_ongoing) {
121 		if (nhm_lv <= ccx->nhm_set_lv) {
122 			set_result = PHYDM_SET_FAIL;
123 		} else {
124 			phydm_ccx_hw_restart(dm);
125 			ccx->nhm_ongoing = false;
126 		}
127 	}
128 
129 	if (set_result)
130 		ccx->nhm_set_lv = nhm_lv;
131 
132 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm racing success=%d\n", set_result);
133 	return set_result;
134 }
135 
phydm_nhm_trigger(void * dm_void)136 void phydm_nhm_trigger(void *dm_void)
137 {
138 	struct dm_struct *dm = (struct dm_struct *)dm_void;
139 	struct ccx_info *ccx = &dm->dm_ccx_info;
140 	u32 nhm_reg1 = 0;
141 
142 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
143 		nhm_reg1 = R_0x994;
144 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
145 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
146 		nhm_reg1 = R_0x1e60;
147 	#endif
148 	else
149 		nhm_reg1 = R_0x890;
150 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
151 
152 	/* @Trigger NHM*/
153 	pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
154 	pdm_set_reg(dm, nhm_reg1, BIT(1), 1);
155 	ccx->nhm_trigger_time = dm->phydm_sys_up_time;
156 	ccx->nhm_rpt_stamp++;
157 	ccx->nhm_ongoing = true;
158 }
159 
160 boolean
phydm_nhm_check_rdy(void * dm_void)161 phydm_nhm_check_rdy(void *dm_void)
162 {
163 	struct dm_struct *dm = (struct dm_struct *)dm_void;
164 	boolean is_ready = false;
165 	u32 reg1 = 0, reg1_bit = 0;
166 
167 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
168 		reg1 = R_0xfb4;
169 		reg1_bit = 16;
170 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
171 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
172 		reg1 = R_0x2d4c;
173 		reg1_bit = 16;
174 	#endif
175 	} else {
176 		reg1 = R_0x8b4;
177 		if (dm->support_ic_type & (ODM_RTL8710B | ODM_RTL8721D |
178 					ODM_RTL8710C))
179 			reg1_bit = 25;
180 		else
181 			reg1_bit = 17;
182 	}
183 	if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
184 		is_ready = true;
185 
186 	PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM rdy=%d\n", is_ready);
187 
188 	return is_ready;
189 }
190 
phydm_nhm_cal_wgt(void * dm_void)191 void phydm_nhm_cal_wgt(void *dm_void)
192 {
193 	struct dm_struct *dm = (struct dm_struct *)dm_void;
194 	struct ccx_info *ccx = &dm->dm_ccx_info;
195 	u8 i = 0;
196 
197 	for (i = 0; i < NHM_RPT_NUM; i++) {
198 		if (i == 0)
199 			ccx->nhm_wgt[0] = (u8)(MAX_2(ccx->nhm_th[0] - 2, 0));
200 		else if (i == (NHM_RPT_NUM - 1))
201 			ccx->nhm_wgt[NHM_RPT_NUM - 1] = (u8)(ccx->nhm_th[NHM_TH_NUM - 1] + 2);
202 		else
203 			ccx->nhm_wgt[i] = (u8)((ccx->nhm_th[i - 1] + ccx->nhm_th[i]) >> 1);
204 	}
205 }
206 
phydm_nhm_cal_wgt_avg(void * dm_void,u8 start_i,u8 end_i,u8 n_sum)207 u8 phydm_nhm_cal_wgt_avg(void *dm_void, u8 start_i, u8 end_i, u8 n_sum)
208 {
209 	struct dm_struct *dm = (struct dm_struct *)dm_void;
210 	struct ccx_info *ccx = &dm->dm_ccx_info;
211 	u8 i = 0;
212 	u32 noise_tmp = 0;
213 	u8 noise = 0;
214 	u32 nhm_valid = 0;
215 
216 	if (n_sum == 0) {
217 		PHYDM_DBG(dm, DBG_ENV_MNTR,
218 			  "n_sum = 0, don't need to update noise\n");
219 		return 0x0;
220 	} else if (end_i > NHM_RPT_NUM - 1) {
221 		PHYDM_DBG(dm, DBG_ENV_MNTR,
222 			  "[WARNING]end_i is larger than 11!!\n");
223 		return 0x0;
224 	}
225 
226 	for (i = start_i; i <= end_i; i++)
227 		noise_tmp += ccx->nhm_result[i] * ccx->nhm_wgt[i];
228 
229 	/* protection for the case of minus noise(RSSI)*/
230 	noise = (u8)(NTH_TH_2_RSSI(MAX_2(PHYDM_DIV(noise_tmp, n_sum), 20)));
231 	nhm_valid = (n_sum * 100) >> 8;
232 	PHYDM_DBG(dm, DBG_ENV_MNTR,
233 		  "cal wgt_avg : valid: ((%d)) percent, noise(RSSI)=((%d))\n",
234 		  nhm_valid, noise);
235 
236 	return noise;
237 }
238 
phydm_nhm_cal_nhm_env(void * dm_void)239 u8 phydm_nhm_cal_nhm_env(void *dm_void)
240 {
241 	struct dm_struct *dm = (struct dm_struct *)dm_void;
242 	struct ccx_info *ccx = &dm->dm_ccx_info;
243 	u8 first_idx = 0;
244 	u8 nhm_env = 0;
245 	u8 i = 0;
246 
247 	nhm_env = ccx->nhm_rpt_sum;
248 
249 	/*search first cluster*/
250 	for (i = 0; i < NHM_RPT_NUM; i++) {
251 		if (ccx->nhm_result[i]) {
252 			first_idx = i;
253 			break;
254 		}
255 	}
256 
257 	/*exclude first cluster under -80dBm*/
258 	for (i = 0; i < 4; i++) {
259 		if (((first_idx + i) < NHM_RPT_NUM) &&
260 		    (ccx->nhm_wgt[first_idx + i] <= NHM_IC_NOISE_TH))
261 			nhm_env -= ccx->nhm_result[first_idx + i];
262 	}
263 
264 	/*exclude nhm_rpt[0] above -80dBm*/
265 	if (ccx->nhm_wgt[0] > NHM_IC_NOISE_TH)
266 		nhm_env -= ccx->nhm_result[0];
267 
268 	PHYDM_DBG(dm, DBG_ENV_MNTR, "cal nhm_env: first_idx=%d, nhm_env=%d\n",
269 		  first_idx, nhm_env);
270 
271 	return nhm_env;
272 }
273 
phydm_nhm_get_utility(void * dm_void)274 void phydm_nhm_get_utility(void *dm_void)
275 {
276 	struct dm_struct *dm = (struct dm_struct *)dm_void;
277 	struct ccx_info *ccx = &dm->dm_ccx_info;
278 	u8 nhm_rpt_non_0 = 0;
279 	u8 nhm_rpt_non_11 = 0;
280 	u8 nhm_env = 0;
281 
282 	if (ccx->nhm_rpt_sum >= ccx->nhm_result[0]) {
283 		phydm_nhm_cal_wgt(dm);
284 
285 		nhm_rpt_non_0 = ccx->nhm_rpt_sum - ccx->nhm_result[0];
286 		nhm_rpt_non_11 = ccx->nhm_rpt_sum - ccx->nhm_result[11];
287 		/*exclude nhm_r[0] above -80dBm or first cluster under -80dBm*/
288 		nhm_env = phydm_nhm_cal_nhm_env(dm);
289 		ccx->nhm_ratio = phydm_ccx_get_rpt_ratio(dm, nhm_rpt_non_0,
290 				 NHM_RPT_MAX);
291 		ccx->nhm_env_ratio = phydm_ccx_get_rpt_ratio(dm, nhm_env,
292 				     NHM_RPT_MAX);
293 		ccx->nhm_level_valid = phydm_ccx_get_rpt_ratio(dm,
294 				       nhm_rpt_non_11, NHM_RPT_MAX);
295 		ccx->nhm_level = phydm_nhm_cal_wgt_avg(dm, 0, NHM_RPT_NUM - 2,
296 						     nhm_rpt_non_11);
297 		ccx->nhm_pwr = phydm_nhm_cal_wgt_avg(dm, 0, NHM_RPT_NUM - 1,
298 						     ccx->nhm_rpt_sum);
299 	} else {
300 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] nhm_rpt_sum invalid\n");
301 		ccx->nhm_ratio = 0;
302 		ccx->nhm_env_ratio = 0;
303 	}
304 
305 	PHYDM_DBG(dm, DBG_ENV_MNTR,
306 		  "nhm_ratio=%d, nhm_env_ratio=%d, nhm_level=%d, nhm_pwr=%d\n",
307 		  ccx->nhm_ratio, ccx->nhm_env_ratio, ccx->nhm_level,
308 		  ccx->nhm_pwr);
309 }
310 
311 boolean
phydm_nhm_get_result(void * dm_void)312 phydm_nhm_get_result(void *dm_void)
313 {
314 	struct dm_struct *dm = (struct dm_struct *)dm_void;
315 	struct ccx_info *ccx = &dm->dm_ccx_info;
316 	u32 value32 = 0;
317 	u8 i = 0;
318 	u32 nhm_reg1 = 0;
319 	u16 nhm_rpt_sum_tmp = 0;
320 	u16 nhm_duration = 0;
321 
322 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
323 		nhm_reg1 = R_0x994;
324 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
325 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
326 		nhm_reg1 = R_0x1e60;
327 	#endif
328 	else
329 		nhm_reg1 = R_0x890;
330 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
331 
332 	if (!(dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8812F |
333 				     ODM_RTL8197G | ODM_RTL8723F)))
334 		pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
335 
336 	if (!(phydm_nhm_check_rdy(dm))) {
337 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM report Fail\n");
338 		phydm_nhm_racing_release(dm);
339 		return false;
340 	}
341 
342 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
343 		value32 = odm_read_4byte(dm, R_0xfa8);
344 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
345 
346 		value32 = odm_read_4byte(dm, R_0xfac);
347 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
348 
349 		value32 = odm_read_4byte(dm, R_0xfb0);
350 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
351 
352 		/*@Get NHM duration*/
353 		value32 = odm_read_4byte(dm, R_0xfb4);
354 		nhm_duration = (u16)(value32 & MASKLWORD);
355 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
356 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
357 		value32 = odm_read_4byte(dm, R_0x2d40);
358 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
359 
360 		value32 = odm_read_4byte(dm, R_0x2d44);
361 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
362 
363 		value32 = odm_read_4byte(dm, R_0x2d48);
364 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
365 
366 		/*@Get NHM duration*/
367 		value32 = odm_read_4byte(dm, R_0x2d4c);
368 		nhm_duration = (u16)(value32 & MASKLWORD);
369 	#endif
370 	} else {
371 		value32 = odm_read_4byte(dm, R_0x8d8);
372 		odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
373 
374 		value32 = odm_read_4byte(dm, R_0x8dc);
375 		odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
376 
377 		value32 = odm_get_bb_reg(dm, R_0x8d0, 0xffff0000);
378 		odm_move_memory(dm, &ccx->nhm_result[8], &value32, 2);
379 
380 		value32 = odm_read_4byte(dm, R_0x8d4);
381 
382 		ccx->nhm_result[10] = (u8)((value32 & MASKBYTE2) >> 16);
383 		ccx->nhm_result[11] = (u8)((value32 & MASKBYTE3) >> 24);
384 
385 		/*@Get NHM duration*/
386 		nhm_duration = (u16)(value32 & MASKLWORD);
387 	}
388 
389 	/* sum all nhm_result */
390 	if (ccx->nhm_period >= 65530)
391 		PHYDM_DBG(dm, DBG_ENV_MNTR,
392 			  "NHM valid time = %d, valid: %d percent\n",
393 			  nhm_duration, (nhm_duration * 100) >> 16);
394 
395 	for (i = 0; i < NHM_RPT_NUM; i++)
396 		nhm_rpt_sum_tmp = (u16)(nhm_rpt_sum_tmp + ccx->nhm_result[i]);
397 
398 	ccx->nhm_rpt_sum = (u8)nhm_rpt_sum_tmp;
399 
400 	PHYDM_DBG(dm, DBG_ENV_MNTR,
401 		  "NHM_Rpt[%d](H->L)[%d %d %d %d %d %d %d %d %d %d %d %d]\n",
402 		  ccx->nhm_rpt_stamp, ccx->nhm_result[11], ccx->nhm_result[10],
403 		  ccx->nhm_result[9], ccx->nhm_result[8], ccx->nhm_result[7],
404 		  ccx->nhm_result[6], ccx->nhm_result[5], ccx->nhm_result[4],
405 		  ccx->nhm_result[3], ccx->nhm_result[2], ccx->nhm_result[1],
406 		  ccx->nhm_result[0]);
407 
408 	phydm_nhm_racing_release(dm);
409 
410 	if (nhm_rpt_sum_tmp > 255) {
411 		PHYDM_DBG(dm, DBG_ENV_MNTR,
412 			  "[Warning] Invalid NHM RPT, total=%d\n",
413 			  nhm_rpt_sum_tmp);
414 		return false;
415 	}
416 
417 	return true;
418 }
419 
phydm_nhm_set_th_reg(void * dm_void)420 void phydm_nhm_set_th_reg(void *dm_void)
421 {
422 	struct dm_struct *dm = (struct dm_struct *)dm_void;
423 	struct ccx_info *ccx = &dm->dm_ccx_info;
424 	u32 reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg4_bit = 0;
425 	u32 val = 0;
426 
427 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
428 
429 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
430 		reg1 = R_0x994;
431 		reg2 = R_0x998;
432 		reg3 = R_0x99c;
433 		reg4 = R_0x9a0;
434 		reg4_bit = MASKBYTE0;
435 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
436 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
437 		reg1 = R_0x1e60;
438 		reg2 = R_0x1e44;
439 		reg3 = R_0x1e48;
440 		reg4 = R_0x1e5c;
441 		reg4_bit = MASKBYTE2;
442 	#endif
443 	} else {
444 		reg1 = R_0x890;
445 		reg2 = R_0x898;
446 		reg3 = R_0x89c;
447 		reg4 = R_0xe28;
448 		reg4_bit = MASKBYTE0;
449 	}
450 
451 	/*Set NHM threshold*/ /*Unit: PWdB U(8,1)*/
452 	val = BYTE_2_DWORD(ccx->nhm_th[3], ccx->nhm_th[2],
453 			   ccx->nhm_th[1], ccx->nhm_th[0]);
454 	pdm_set_reg(dm, reg2, MASKDWORD, val);
455 	val = BYTE_2_DWORD(ccx->nhm_th[7], ccx->nhm_th[6],
456 			   ccx->nhm_th[5], ccx->nhm_th[4]);
457 	pdm_set_reg(dm, reg3, MASKDWORD, val);
458 	pdm_set_reg(dm, reg4, reg4_bit, ccx->nhm_th[8]);
459 	val = BYTE_2_DWORD(0, 0, ccx->nhm_th[10], ccx->nhm_th[9]);
460 	pdm_set_reg(dm, reg1, 0xffff0000, val);
461 
462 	PHYDM_DBG(dm, DBG_ENV_MNTR,
463 		  "Update NHM_th[H->L]=[%d %d %d %d %d %d %d %d %d %d %d]\n",
464 		  ccx->nhm_th[10], ccx->nhm_th[9], ccx->nhm_th[8],
465 		  ccx->nhm_th[7], ccx->nhm_th[6], ccx->nhm_th[5],
466 		  ccx->nhm_th[4], ccx->nhm_th[3], ccx->nhm_th[2],
467 		  ccx->nhm_th[1], ccx->nhm_th[0]);
468 }
469 
470 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)471 phydm_nhm_th_update_chk(void *dm_void, enum nhm_application nhm_app, u8 *nhm_th,
472 			u32 *igi_new, boolean en_1db_mode, u8 nhm_th0_manual)
473 {
474 	struct dm_struct *dm = (struct dm_struct *)dm_void;
475 	struct ccx_info *ccx = &dm->dm_ccx_info;
476 	boolean is_update = false;
477 	u8 igi_curr = phydm_get_igi(dm, BB_PATH_A);
478 	u8 nhm_igi_th_11k_low[NHM_TH_NUM] = {0x12, 0x15, 0x18, 0x1b, 0x1e,
479 					     0x23, 0x28, 0x2c, 0x78,
480 					     0x78, 0x78};
481 	u8 nhm_igi_th_11k_high[NHM_TH_NUM] = {0x1e, 0x23, 0x28, 0x2d, 0x32,
482 					      0x37, 0x78, 0x78, 0x78, 0x78,
483 					      0x78};
484 	u8 nhm_igi_th_xbox[NHM_TH_NUM] = {0x1a, 0x2c, 0x2e, 0x30, 0x32, 0x34,
485 					  0x36, 0x38, 0x3a, 0x3c, 0x3d};
486 	u8 i = 0;
487 	u8 th_tmp = igi_curr - CCA_CAP;
488 	u8 th_step = 2;
489 
490 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
491 	PHYDM_DBG(dm, DBG_ENV_MNTR, "App=%d, nhm_igi=0x%x, igi_curr=0x%x\n",
492 		  nhm_app, ccx->nhm_igi, igi_curr);
493 
494 	if (igi_curr < 0x10) /* Protect for invalid IGI*/
495 		return false;
496 
497 	switch (nhm_app) {
498 	case NHM_BACKGROUND: /* @Get IGI form driver parameter(cur_ig_value)*/
499 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
500 			is_update = true;
501 			*igi_new = (u32)igi_curr;
502 
503 			#ifdef NHM_DYM_PW_TH_SUPPORT
504 			if (ccx->nhm_dym_pw_th_en) {
505 				th_tmp = MAX_2(igi_curr - DYM_PWTH_CCA_CAP, 0);
506 				th_step = 3;
507 			}
508 			#endif
509 
510 			nhm_th[0] = (u8)IGI_2_NHM_TH(th_tmp);
511 
512 			for (i = 1; i <= 10; i++)
513 				nhm_th[i] = nhm_th[0] +
514 					    IGI_2_NHM_TH(th_step * i);
515 
516 		}
517 		break;
518 
519 	case NHM_ACS:
520 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
521 			is_update = true;
522 			*igi_new = (u32)igi_curr;
523 			nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr - CCA_CAP);
524 			for (i = 1; i <= 10; i++)
525 				nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(2 * i);
526 		}
527 		break;
528 
529 	case IEEE_11K_HIGH:
530 		is_update = true;
531 		*igi_new = 0x2c;
532 		for (i = 0; i < NHM_TH_NUM; i++)
533 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_high[i]);
534 		break;
535 
536 	case IEEE_11K_LOW:
537 		is_update = true;
538 		*igi_new = 0x20;
539 		for (i = 0; i < NHM_TH_NUM; i++)
540 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_low[i]);
541 		break;
542 
543 	case INTEL_XBOX:
544 		is_update = true;
545 		*igi_new = 0x36;
546 		for (i = 0; i < NHM_TH_NUM; i++)
547 			nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_xbox[i]);
548 		break;
549 
550 	case NHM_DBG: /*@Get IGI form register*/
551 		igi_curr = phydm_get_igi(dm, BB_PATH_A);
552 		if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
553 			is_update = true;
554 			*igi_new = (u32)igi_curr;
555 			if (en_1db_mode) {
556 				nhm_th[0] = (u8)IGI_2_NHM_TH(nhm_th0_manual +
557 							     10);
558 				th_step = 1;
559 			} else {
560 				nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr -
561 							     CCA_CAP);
562 			}
563 
564 			for (i = 1; i <= 10; i++)
565 				nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(th_step *
566 					    i);
567 		}
568 		break;
569 	}
570 
571 	if (is_update) {
572 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update NHM_TH] igi_RSSI=%d\n",
573 			  IGI_2_RSSI(*igi_new));
574 
575 		for (i = 0; i < NHM_TH_NUM; i++) {
576 			PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM_th[%d](RSSI) = %d\n",
577 				  i, NTH_TH_2_RSSI(nhm_th[i]));
578 		}
579 	} else {
580 		PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update NHM_TH\n");
581 	}
582 	return is_update;
583 }
584 
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)585 void phydm_nhm_set(void *dm_void, enum nhm_option_txon_all include_tx,
586 		   enum nhm_option_cca_all include_cca,
587 		   enum nhm_divider_opt_all divi_opt,
588 		   enum nhm_application nhm_app, u16 period,
589 		   boolean en_1db_mode, u8 nhm_th0_manual)
590 {
591 	struct dm_struct *dm = (struct dm_struct *)dm_void;
592 	struct ccx_info *ccx = &dm->dm_ccx_info;
593 	u8 nhm_th[NHM_TH_NUM] = {0};
594 	u32 igi = 0x20;
595 	u32 reg1 = 0, reg2 = 0;
596 	u32 val_tmp = 0;
597 
598 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
599 
600 	PHYDM_DBG(dm, DBG_ENV_MNTR,
601 		  "incld{tx, cca}={%d, %d}, divi_opt=%d, period=%d\n",
602 		  include_tx, include_cca, divi_opt, period);
603 
604 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
605 		reg1 = R_0x994;
606 		reg2 = R_0x990;
607 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
608 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
609 		reg1 = R_0x1e60;
610 		reg2 = R_0x1e40;
611 	#endif
612 	} else {
613 		reg1 = R_0x890;
614 		reg2 = R_0x894;
615 	}
616 
617 	/*Set disable_ignore_cca, disable_ignore_txon, ccx_en*/
618 	if (include_tx != ccx->nhm_include_txon ||
619 	    include_cca != ccx->nhm_include_cca ||
620 	    divi_opt != ccx->nhm_divider_opt) {
621 	    /* some old ic is not supported on NHM divider option */
622 		if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
623 		    ODM_RTL8195A | ODM_RTL8192E)) {
624 			val_tmp = (u32)((include_tx << 2) |
625 				  (include_cca << 1) | 1);
626 			pdm_set_reg(dm, reg1, 0x700, val_tmp);
627 		} else {
628 			val_tmp = (u32)BIT_2_BYTE(divi_opt, include_tx,
629 				  include_cca, 1);
630 			pdm_set_reg(dm, reg1, 0xf00, val_tmp);
631 		}
632 		ccx->nhm_include_txon = include_tx;
633 		ccx->nhm_include_cca = include_cca;
634 		ccx->nhm_divider_opt = divi_opt;
635 	}
636 
637 	/*Set NHM period*/
638 	if (period != ccx->nhm_period) {
639 		pdm_set_reg(dm, reg2, MASKHWORD, period);
640 		PHYDM_DBG(dm, DBG_ENV_MNTR,
641 			  "Update NHM period ((%d)) -> ((%d))\n",
642 			  ccx->nhm_period, period);
643 
644 		ccx->nhm_period = period;
645 	}
646 
647 	/*Set NHM threshold*/
648 	if (phydm_nhm_th_update_chk(dm, nhm_app, &nhm_th[0], &igi,
649 				    en_1db_mode, nhm_th0_manual)) {
650 		/*Pause IGI*/
651 		if (nhm_app == NHM_BACKGROUND || nhm_app == NHM_ACS) {
652 			PHYDM_DBG(dm, DBG_ENV_MNTR, "DIG Free Run\n");
653 		} else if (phydm_pause_func(dm, F00_DIG, PHYDM_PAUSE,
654 					    PHYDM_PAUSE_LEVEL_1, 1, &igi)
655 					    == PAUSE_FAIL) {
656 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG Fail\n");
657 			return;
658 		} else {
659 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG=0x%x\n", igi);
660 		}
661 		ccx->nhm_app = nhm_app;
662 		ccx->nhm_igi = (u8)igi;
663 		odm_move_memory(dm, &ccx->nhm_th[0], &nhm_th, NHM_TH_NUM);
664 
665 		/*Set NHM th*/
666 		phydm_nhm_set_th_reg(dm);
667 	}
668 }
669 
670 boolean
phydm_nhm_mntr_set(void * dm_void,struct nhm_para_info * nhm_para)671 phydm_nhm_mntr_set(void *dm_void, struct nhm_para_info *nhm_para)
672 {
673 	struct dm_struct *dm = (struct dm_struct *)dm_void;
674 	u16 nhm_time = 0; /*unit: 4us*/
675 
676 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
677 
678 	if (nhm_para->mntr_time == 0)
679 		return false;
680 
681 	if (nhm_para->nhm_lv >= NHM_MAX_NUM) {
682 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n", nhm_para->nhm_lv);
683 		return false;
684 	}
685 
686 	if (phydm_nhm_racing_ctrl(dm, nhm_para->nhm_lv) == PHYDM_SET_FAIL)
687 		return false;
688 
689 	if (nhm_para->mntr_time >= 262)
690 		nhm_time = NHM_PERIOD_MAX;
691 	else
692 		nhm_time = nhm_para->mntr_time * MS_TO_4US_RATIO;
693 
694 	phydm_nhm_set(dm, nhm_para->incld_txon, nhm_para->incld_cca,
695 		      nhm_para->div_opt, nhm_para->nhm_app, nhm_time,
696 		      nhm_para->en_1db_mode, nhm_para->nhm_th0_manual);
697 
698 	return true;
699 }
700 
701 #ifdef NHM_DYM_PW_TH_SUPPORT
702 void
phydm_nhm_restore_pw_th(void * dm_void)703 phydm_nhm_restore_pw_th(void *dm_void)
704 {
705 	struct dm_struct *dm = (struct dm_struct *)dm_void;
706 	struct ccx_info *ccx = &dm->dm_ccx_info;
707 
708 	odm_set_bb_reg(dm, R_0x82c, 0x3f, ccx->pw_th_rf20_ori);
709 }
710 
711 void
phydm_nhm_set_pw_th(void * dm_void,u8 noise,boolean chk_succ)712 phydm_nhm_set_pw_th(void *dm_void, u8 noise, boolean chk_succ)
713 {
714 	struct dm_struct *dm = (struct dm_struct *)dm_void;
715 	struct ccx_info *ccx = &dm->dm_ccx_info;
716 	boolean not_update = false;
717 	u8 pw_th_rf20_new = 0;
718 	u8 pw_th_u_bnd = 0;
719 	s8 noise_diff = 0;
720 	u8 point_mean = 15;
721 
722 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
723 
724 	if (*dm->band_width != CHANNEL_WIDTH_20 ||
725 	    *dm->band_type == ODM_BAND_5G) {
726 		PHYDM_DBG(dm, DBG_ENV_MNTR,  "bandwidth=((%d)), band=((%d))\n",
727 			  *dm->band_width, *dm->band_type);
728 		phydm_nhm_restore_pw_th(dm);
729 		return;
730 	}
731 
732 	if (chk_succ) {
733 		noise_diff = noise - (ccx->nhm_igi - 10);
734 		pw_th_u_bnd = (u8)(noise_diff + 32 + point_mean);
735 
736 		pw_th_u_bnd = MIN_2(pw_th_u_bnd, ccx->nhm_pw_th_max);
737 
738 		PHYDM_DBG(dm, DBG_ENV_MNTR,
739 			  "noise_diff=((%d)), max=((%d)), pw_th_u_bnd=((%d))\n",
740 			  noise_diff, ccx->nhm_pw_th_max, pw_th_u_bnd);
741 
742 		if (pw_th_u_bnd > ccx->pw_th_rf20_cur) {
743 			pw_th_rf20_new = ccx->pw_th_rf20_cur + 1;
744 		} else if (pw_th_u_bnd < ccx->pw_th_rf20_cur) {
745 			if (ccx->pw_th_rf20_cur > ccx->pw_th_rf20_ori)
746 				pw_th_rf20_new = ccx->pw_th_rf20_cur - 1;
747 			else /*ccx->pw_th_rf20_cur == ccx->pw_th_ori*/
748 				not_update = true;
749 		} else {/*pw_th_u_bnd == ccx->pw_th_rf20_cur*/
750 			not_update = true;
751 		}
752 	} else {
753 		if (ccx->pw_th_rf20_cur > ccx->pw_th_rf20_ori)
754 			pw_th_rf20_new = ccx->pw_th_rf20_cur - 1;
755 		else /*ccx->pw_th_rf20_cur == ccx->pw_th_ori*/
756 			not_update = true;
757 	}
758 
759 	PHYDM_DBG(dm, DBG_ENV_MNTR, "pw_th_cur=((%d)), pw_th_new=((%d))\n",
760 		  ccx->pw_th_rf20_cur, pw_th_rf20_new);
761 
762 	if (!not_update) {
763 		odm_set_bb_reg(dm, R_0x82c, 0x3f, pw_th_rf20_new);
764 		ccx->pw_th_rf20_cur = pw_th_rf20_new;
765 	}
766 }
767 
768 void
phydm_nhm_dym_pw_th(void * dm_void)769 phydm_nhm_dym_pw_th(void *dm_void)
770 {
771 	struct dm_struct *dm = (struct dm_struct *)dm_void;
772 	struct ccx_info *ccx = &dm->dm_ccx_info;
773 	u8 i = 0;
774 	u8 n_sum = 0;
775 	u8 noise = 0;
776 	boolean chk_succ = false;
777 
778 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
779 
780 	for (i = 0; i < NHM_RPT_NUM - 3; i++) {
781 		n_sum = ccx->nhm_result[i] + ccx->nhm_result[i + 1] +
782 			ccx->nhm_result[i + 2] + ccx->nhm_result[i + 3];
783 		if (n_sum >= ccx->nhm_sl_pw_th) {
784 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Do sl[%d:%d]\n", i, i + 3);
785 			chk_succ = true;
786 			noise = phydm_nhm_cal_wgt_avg(dm, i, i + 3, n_sum);
787 			break;
788 		}
789 	}
790 
791 	if (!chk_succ)
792 		PHYDM_DBG(dm, DBG_ENV_MNTR, "SL method failed!\n");
793 
794 	phydm_nhm_set_pw_th(dm, noise, chk_succ);
795 }
796 
797 boolean
phydm_nhm_dym_pw_th_en(void * dm_void)798 phydm_nhm_dym_pw_th_en(void *dm_void)
799 {
800 	struct dm_struct *dm = (struct dm_struct *)dm_void;
801 	struct ccx_info *ccx = &dm->dm_ccx_info;
802 	struct phydm_iot_center	*iot_table = &dm->iot_table;
803 
804 	if (!(dm->support_ic_type & ODM_RTL8822C))
805 		return false;
806 
807 	if (ccx->dym_pwth_manual_ctrl)
808 		return true;
809 
810 	if (dm->iot_table.phydm_patch_id == 0x100f0401 ||
811 	    iot_table->patch_id_100f0401) {
812 		return true;
813 	} else if (ccx->nhm_dym_pw_th_en) {
814 		phydm_nhm_restore_pw_th(dm);
815 		return false;
816 	} else {
817 		return false;
818 	}
819 }
820 #endif
821 
822 /*Environment Monitor*/
823 boolean
phydm_nhm_mntr_racing_chk(void * dm_void)824 phydm_nhm_mntr_racing_chk(void *dm_void)
825 {
826 	struct dm_struct *dm = (struct dm_struct *)dm_void;
827 	struct ccx_info *ccx = &dm->dm_ccx_info;
828 	u32 sys_return_time = 0;
829 
830 	if (ccx->nhm_manual_ctrl) {
831 		PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM in manual ctrl\n");
832 		return true;
833 	}
834 
835 	sys_return_time = ccx->nhm_trigger_time + MAX_ENV_MNTR_TIME;
836 
837 	if (ccx->nhm_app != NHM_BACKGROUND &&
838 	    (sys_return_time > dm->phydm_sys_up_time)) {
839 		PHYDM_DBG(dm, DBG_ENV_MNTR,
840 			  "nhm_app=%d, trigger_time %d, sys_time=%d\n",
841 			  ccx->nhm_app, ccx->nhm_trigger_time,
842 			  dm->phydm_sys_up_time);
843 
844 		return true;
845 	}
846 
847 	return false;
848 }
849 
850 boolean
phydm_nhm_mntr_chk(void * dm_void,u16 monitor_time)851 phydm_nhm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
852 {
853 	struct dm_struct *dm = (struct dm_struct *)dm_void;
854 	struct ccx_info *ccx = &dm->dm_ccx_info;
855 	struct nhm_para_info nhm_para = {0};
856 	boolean nhm_chk_result = false;
857 
858 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
859 
860 	if (phydm_nhm_mntr_racing_chk(dm))
861 		return nhm_chk_result;
862 
863 	/*[NHM trigger setting]------------------------------------------*/
864 	nhm_para.incld_txon = NHM_EXCLUDE_TXON;
865 	nhm_para.incld_cca = NHM_EXCLUDE_CCA;
866 	nhm_para.div_opt = NHM_CNT_ALL;
867 	nhm_para.nhm_app = NHM_BACKGROUND;
868 	nhm_para.nhm_lv = NHM_LV_1;
869 	nhm_para.en_1db_mode = false;
870 	nhm_para.mntr_time = monitor_time;
871 
872 	#ifdef NHM_DYM_PW_TH_SUPPORT
873 	if (ccx->nhm_dym_pw_th_en) {
874 		nhm_para.div_opt = NHM_VALID;
875 		nhm_para.mntr_time = monitor_time >> ccx->nhm_period_decre;
876 	}
877 	#endif
878 
879 	nhm_chk_result = phydm_nhm_mntr_set(dm, &nhm_para);
880 
881 	return nhm_chk_result;
882 }
883 
884 boolean
phydm_nhm_mntr_result(void * dm_void)885 phydm_nhm_mntr_result(void *dm_void)
886 {
887 	struct dm_struct *dm = (struct dm_struct *)dm_void;
888 	struct ccx_info *ccx = &dm->dm_ccx_info;
889 	boolean nhm_chk_result = false;
890 
891 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
892 
893 	if (phydm_nhm_mntr_racing_chk(dm))
894 		return nhm_chk_result;
895 
896 	/*[NHM get result & calculate Utility]---------------------------*/
897 	if (phydm_nhm_get_result(dm)) {
898 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
899 		phydm_nhm_get_utility(dm);
900 		nhm_chk_result = true;
901 	}
902 
903 	#ifdef NHM_DYM_PW_TH_SUPPORT
904 	ccx->nhm_dym_pw_th_en = phydm_nhm_dym_pw_th_en(dm);
905 	if (ccx->nhm_dym_pw_th_en) {
906 		if (nhm_chk_result)
907 			phydm_nhm_dym_pw_th(dm);
908 		else
909 			phydm_nhm_set_pw_th(dm, 0x0, false);
910 	}
911 	#endif
912 
913 	return nhm_chk_result;
914 }
915 
phydm_nhm_init(void * dm_void)916 void phydm_nhm_init(void *dm_void)
917 {
918 	struct dm_struct *dm = (struct dm_struct *)dm_void;
919 	struct ccx_info *ccx = &dm->dm_ccx_info;
920 
921 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
922 	PHYDM_DBG(dm, DBG_ENV_MNTR, "cur_igi=0x%x\n",
923 		  dm->dm_dig_table.cur_ig_value);
924 
925 	ccx->nhm_app = NHM_BACKGROUND;
926 	ccx->nhm_igi = 0xff;
927 
928 	/*Set NHM threshold*/
929 	ccx->nhm_ongoing = false;
930 	ccx->nhm_set_lv = NHM_RELEASE;
931 
932 	if (phydm_nhm_th_update_chk(dm, ccx->nhm_app, &ccx->nhm_th[0],
933 				    (u32 *)&ccx->nhm_igi, false, 0))
934 		phydm_nhm_set_th_reg(dm);
935 
936 	ccx->nhm_period = 0;
937 
938 	ccx->nhm_include_cca = NHM_CCA_INIT;
939 	ccx->nhm_include_txon = NHM_TXON_INIT;
940 	ccx->nhm_divider_opt = NHM_CNT_INIT;
941 
942 	ccx->nhm_manual_ctrl = 0;
943 	ccx->nhm_rpt_stamp = 0;
944 
945 	#ifdef NHM_DYM_PW_TH_SUPPORT
946 	if (dm->support_ic_type & ODM_RTL8822C) {
947 		ccx->nhm_dym_pw_th_en = false;
948 		ccx->pw_th_rf20_ori = (u8)odm_get_bb_reg(dm, R_0x82c, 0x3f);
949 		ccx->pw_th_rf20_cur = ccx->pw_th_rf20_ori;
950 		ccx->nhm_pw_th_max = 63;
951 		ccx->nhm_sl_pw_th = 100; /*39%*/
952 		ccx->nhm_period_decre = 1;
953 		ccx->dym_pwth_manual_ctrl = false;
954 	}
955 	#endif
956 }
957 
phydm_nhm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)958 void phydm_nhm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
959 		   u32 *_out_len)
960 {
961 	struct dm_struct *dm = (struct dm_struct *)dm_void;
962 	struct ccx_info *ccx = &dm->dm_ccx_info;
963 	struct nhm_para_info nhm_para = {0};
964 	char help[] = "-h";
965 	u32 var1[10] = {0};
966 	u32 used = *_used;
967 	u32 out_len = *_out_len;
968 	u8 result_tmp = 0;
969 	u8 i = 0;
970 
971 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
972 
973 	if ((strcmp(input[1], help) == 0)) {
974 		PDM_SNPF(out_len, used, output + used, out_len - used,
975 			 "NHM Basic-Trigger 262ms: {1}\n");
976 
977 		PDM_SNPF(out_len, used, output + used, out_len - used,
978 			 "NHM Adv-Trigger: {2} {Include TXON} {Include CCA}\n{0:Cnt_all, 1:Cnt valid} {App:5 for dbg} {LV:1~4} {0~262ms}, 1dB mode :{en} {t[0](RSSI)}\n");
979 		#ifdef NHM_DYM_PW_TH_SUPPORT
980 		if (dm->support_ic_type & ODM_RTL8822C) {
981 			PDM_SNPF(out_len, used, output + used, out_len - used,
982 				 "NHM dym_pw_th: {3} {0:off}\n");
983 			PDM_SNPF(out_len, used, output + used, out_len - used,
984 				 "NHM dym_pw_th: {3} {1:on} {max} {period_decre} {sl_th}\n");
985 			PDM_SNPF(out_len, used, output + used, out_len - used,
986 				 "NHM dym_pw_th: {3} {2:fast on}\n");
987 		}
988 		#endif
989 
990 		PDM_SNPF(out_len, used, output + used, out_len - used,
991 			 "NHM Get Result: {100}\n");
992 	} else if (var1[0] == 100) { /*Get NHM results*/
993 
994 		PDM_SNPF(out_len, used, output + used, out_len - used,
995 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
996 			 ccx->nhm_rpt_stamp);
997 
998 		if (phydm_nhm_get_result(dm)) {
999 			for (i = 0; i < NHM_RPT_NUM; i++) {
1000 				result_tmp = ccx->nhm_result[i];
1001 				PDM_SNPF(out_len, used, output + used,
1002 					 out_len - used,
1003 					 "nhm_rpt[%d] = %d (%d percent)\n",
1004 					 i, result_tmp,
1005 					 (((result_tmp * 100) + 128) >> 8));
1006 			}
1007 			phydm_nhm_get_utility(dm);
1008 
1009 			PDM_SNPF(out_len, used, output + used, out_len - used,
1010 				 "NHM_noise: valid: %d percent, noise(RSSI) = %d\n",
1011 				 ccx->nhm_level_valid, ccx->nhm_level);
1012 			PDM_SNPF(out_len, used, output + used, out_len - used,
1013 				 "NHM_pwr: nhm_pwr (RSSI) = %d\n", ccx->nhm_pwr);
1014 			PDM_SNPF(out_len, used, output + used, out_len - used,
1015 				 "ratio: nhm_ratio=%d, nhm_env_ratio=%d\n",
1016 				 ccx->nhm_ratio, ccx->nhm_env_ratio);
1017 		} else {
1018 			PDM_SNPF(out_len, used, output + used, out_len - used,
1019 				 "Get NHM_rpt Fail\n");
1020 		}
1021 		ccx->nhm_manual_ctrl = 0;
1022 	#ifdef NHM_DYM_PW_TH_SUPPORT
1023 	} else if (var1[0] == 3) { /*NMH dym_pw_th*/
1024 		if (dm->support_ic_type & ODM_RTL8822C) {
1025 			for (i = 1; i < 7; i++) {
1026 				PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
1027 					     &var1[i]);
1028 			}
1029 
1030 			if (var1[1] == 1) {
1031 				ccx->nhm_dym_pw_th_en = true;
1032 				ccx->nhm_pw_th_max = (u8)var1[2];
1033 				ccx->nhm_period_decre = (u8)var1[3];
1034 				ccx->nhm_sl_pw_th = (u8)var1[4];
1035 				ccx->dym_pwth_manual_ctrl = true;
1036 			} else if (var1[1] == 2) {
1037 				ccx->nhm_dym_pw_th_en = true;
1038 				ccx->nhm_pw_th_max = 63;
1039 				ccx->nhm_period_decre = 1;
1040 				ccx->nhm_sl_pw_th = 100;
1041 				ccx->dym_pwth_manual_ctrl = true;
1042 			} else {
1043 				ccx->nhm_dym_pw_th_en = false;
1044 				phydm_nhm_restore_pw_th(dm);
1045 				ccx->dym_pwth_manual_ctrl = false;
1046 			}
1047 		}
1048 	#endif
1049 	} else { /*NMH trigger*/
1050 		ccx->nhm_manual_ctrl = 1;
1051 
1052 		for (i = 1; i < 9; i++) {
1053 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
1054 				     &var1[i]);
1055 		}
1056 
1057 		if (var1[0] == 1) {
1058 			nhm_para.incld_txon = NHM_EXCLUDE_TXON;
1059 			nhm_para.incld_cca = NHM_EXCLUDE_CCA;
1060 			nhm_para.div_opt = NHM_CNT_ALL;
1061 			nhm_para.nhm_app = NHM_DBG;
1062 			nhm_para.nhm_lv = NHM_LV_4;
1063 			nhm_para.mntr_time = 262;
1064 			nhm_para.en_1db_mode = false;
1065 			nhm_para.nhm_th0_manual = 0;
1066 		} else {
1067 			nhm_para.incld_txon = (enum nhm_option_txon_all)var1[1];
1068 			nhm_para.incld_cca = (enum nhm_option_cca_all)var1[2];
1069 			nhm_para.div_opt = (enum nhm_divider_opt_all)var1[3];
1070 			nhm_para.nhm_app = (enum nhm_application)var1[4];
1071 			nhm_para.nhm_lv = (enum phydm_nhm_level)var1[5];
1072 			nhm_para.mntr_time = (u16)var1[6];
1073 			nhm_para.en_1db_mode = (boolean)var1[7];
1074 			nhm_para.nhm_th0_manual = (u8)var1[8];
1075 
1076 			/*some old ic is not supported on NHM divider option */
1077 			if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
1078 			    ODM_RTL8195A | ODM_RTL8192E)) {
1079 				nhm_para.div_opt = NHM_CNT_ALL;
1080 			}
1081 		}
1082 
1083 		PDM_SNPF(out_len, used, output + used, out_len - used,
1084 			 "txon=%d, cca=%d, dev=%d, app=%d, lv=%d, time=%d ms\n",
1085 			 nhm_para.incld_txon, nhm_para.incld_cca,
1086 			 nhm_para.div_opt, nhm_para.nhm_app,
1087 			 nhm_para.nhm_lv, nhm_para.mntr_time);
1088 
1089 		PDM_SNPF(out_len, used, output + used, out_len - used,
1090 			 "en_1db_mode=%d, th0(for 1db mode)=%d\n",
1091 			 nhm_para.en_1db_mode, nhm_para.nhm_th0_manual);
1092 
1093 		if (phydm_nhm_mntr_set(dm, &nhm_para))
1094 			phydm_nhm_trigger(dm);
1095 
1096 		PDM_SNPF(out_len, used, output + used, out_len - used,
1097 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
1098 			 ccx->nhm_rpt_stamp);
1099 
1100 		for (i = 0; i < NHM_TH_NUM; i++) {
1101 			PDM_SNPF(out_len, used, output + used, out_len - used,
1102 				 "NHM_th[%d] RSSI = %d\n", i,
1103 				 NTH_TH_2_RSSI(ccx->nhm_th[i]));
1104 		}
1105 	}
1106 
1107 	*_used = used;
1108 	*_out_len = out_len;
1109 }
1110 
1111 #endif /*@#ifdef NHM_SUPPORT*/
1112 
1113 #ifdef CLM_SUPPORT
1114 
phydm_clm_racing_release(void * dm_void)1115 void phydm_clm_racing_release(void *dm_void)
1116 {
1117 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1118 	struct ccx_info *ccx = &dm->dm_ccx_info;
1119 
1120 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1121 	PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->clm_set_lv);
1122 
1123 	ccx->clm_ongoing = false;
1124 	ccx->clm_set_lv = CLM_RELEASE;
1125 	ccx->clm_app = CLM_BACKGROUND;
1126 }
1127 
phydm_clm_racing_ctrl(void * dm_void,enum phydm_clm_level clm_lv)1128 u8 phydm_clm_racing_ctrl(void *dm_void, enum phydm_clm_level clm_lv)
1129 {
1130 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1131 	struct ccx_info *ccx = &dm->dm_ccx_info;
1132 	u8 set_result = PHYDM_SET_SUCCESS;
1133 	/*@acquire to control CLM API*/
1134 
1135 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ongoing=%d, lv:(%d)->(%d)\n",
1136 		  ccx->clm_ongoing, ccx->clm_set_lv, clm_lv);
1137 	if (ccx->clm_ongoing) {
1138 		if (clm_lv <= ccx->clm_set_lv) {
1139 			set_result = PHYDM_SET_FAIL;
1140 		} else {
1141 			phydm_ccx_hw_restart(dm);
1142 			ccx->clm_ongoing = false;
1143 		}
1144 	}
1145 
1146 	if (set_result)
1147 		ccx->clm_set_lv = clm_lv;
1148 
1149 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm racing success=%d\n", set_result);
1150 	return set_result;
1151 }
1152 
phydm_clm_c2h_report_handler(void * dm_void,u8 * cmd_buf,u8 cmd_len)1153 void phydm_clm_c2h_report_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
1154 {
1155 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1156 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1157 	u8 clm_report = cmd_buf[0];
1158 	/*@u8 clm_report_idx = cmd_buf[1];*/
1159 
1160 	if (cmd_len >= 12)
1161 		return;
1162 
1163 	ccx_info->clm_fw_result_acc += clm_report;
1164 	ccx_info->clm_fw_result_cnt++;
1165 
1166 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%d] clm_report= %d\n",
1167 		  ccx_info->clm_fw_result_cnt, clm_report);
1168 }
1169 
phydm_clm_h2c(void * dm_void,u16 obs_time,u8 fw_clm_en)1170 void phydm_clm_h2c(void *dm_void, u16 obs_time, u8 fw_clm_en)
1171 {
1172 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1173 	u8 h2c_val[H2C_MAX_LENGTH] = {0};
1174 	u8 i = 0;
1175 	u8 obs_time_idx = 0;
1176 
1177 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1178 	PHYDM_DBG(dm, DBG_ENV_MNTR, "obs_time_index=%d *4 us\n", obs_time);
1179 
1180 	for (i = 1; i <= 16; i++) {
1181 		if (obs_time & BIT(16 - i)) {
1182 			obs_time_idx = 16 - i;
1183 			break;
1184 		}
1185 	}
1186 #if 0
1187 	obs_time = (2 ^ 16 - 1)~(2 ^ 15)  => obs_time_idx = 15  (65535 ~32768)
1188 	obs_time = (2 ^ 15 - 1)~(2 ^ 14)  => obs_time_idx = 14
1189 	...
1190 	...
1191 	...
1192 	obs_time = (2 ^ 1 - 1)~(2 ^ 0)  => obs_time_idx = 0
1193 
1194 #endif
1195 
1196 	h2c_val[0] = obs_time_idx | (((fw_clm_en) ? 1 : 0) << 7);
1197 	h2c_val[1] = CLM_MAX_REPORT_TIME;
1198 
1199 	PHYDM_DBG(dm, DBG_ENV_MNTR, "PHYDM h2c[0x4d]=0x%x %x %x %x %x %x %x\n",
1200 		  h2c_val[6], h2c_val[5], h2c_val[4], h2c_val[3], h2c_val[2],
1201 		  h2c_val[1], h2c_val[0]);
1202 
1203 	odm_fill_h2c_cmd(dm, PHYDM_H2C_FW_CLM_MNTR, H2C_MAX_LENGTH, h2c_val);
1204 }
1205 
phydm_clm_setting(void * dm_void,u16 clm_period)1206 void phydm_clm_setting(void *dm_void, u16 clm_period /*@4us sample 1 time*/)
1207 {
1208 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1209 	struct ccx_info *ccx = &dm->dm_ccx_info;
1210 
1211 	if (ccx->clm_period != clm_period) {
1212 		if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1213 			odm_set_bb_reg(dm, R_0x990, MASKLWORD, clm_period);
1214 		#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1215 		else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1216 			odm_set_bb_reg(dm, R_0x1e40, MASKLWORD, clm_period);
1217 		#endif
1218 		else if (dm->support_ic_type & ODM_IC_11N_SERIES)
1219 			odm_set_bb_reg(dm, R_0x894, MASKLWORD, clm_period);
1220 
1221 		ccx->clm_period = clm_period;
1222 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1223 			  "Update CLM period ((%d)) -> ((%d))\n",
1224 			  ccx->clm_period, clm_period);
1225 	}
1226 
1227 	PHYDM_DBG(dm, DBG_ENV_MNTR, "Set CLM period=%d * 4us\n",
1228 		  ccx->clm_period);
1229 }
1230 
phydm_clm_trigger(void * dm_void)1231 void phydm_clm_trigger(void *dm_void)
1232 {
1233 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1234 	struct ccx_info *ccx = &dm->dm_ccx_info;
1235 	u32 reg1 = 0;
1236 
1237 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1238 		reg1 = R_0x994;
1239 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1240 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1241 		reg1 = R_0x1e60;
1242 	#endif
1243 	else
1244 		reg1 = R_0x890;
1245 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1246 
1247 	odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
1248 	odm_set_bb_reg(dm, reg1, BIT(0), 0x1);
1249 
1250 	ccx->clm_trigger_time = dm->phydm_sys_up_time;
1251 	ccx->clm_rpt_stamp++;
1252 	ccx->clm_ongoing = true;
1253 }
1254 
1255 boolean
phydm_clm_check_rdy(void * dm_void)1256 phydm_clm_check_rdy(void *dm_void)
1257 {
1258 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1259 	boolean is_ready = false;
1260 	u32 reg1 = 0, reg1_bit = 0;
1261 
1262 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
1263 		reg1 = R_0xfa4;
1264 		reg1_bit = 16;
1265 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1266 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
1267 		reg1 = R_0x2d88;
1268 		reg1_bit = 16;
1269 	#endif
1270 	} else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
1271 		if (dm->support_ic_type & (ODM_RTL8710B | ODM_RTL8721D |
1272 					ODM_RTL8710C)) {
1273 			reg1 = R_0x8b4;
1274 			reg1_bit = 24;
1275 		} else {
1276 			reg1 = R_0x8b4;
1277 			reg1_bit = 16;
1278 		}
1279 	}
1280 	if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
1281 		is_ready = true;
1282 
1283 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM rdy=%d\n", is_ready);
1284 
1285 	return is_ready;
1286 }
1287 
phydm_clm_get_utility(void * dm_void)1288 void phydm_clm_get_utility(void *dm_void)
1289 {
1290 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1291 	struct ccx_info *ccx = &dm->dm_ccx_info;
1292 
1293 	if (ccx->clm_period == 0) {
1294 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] clm_period = 0\n");
1295 		ccx->clm_ratio = 0;
1296 	} else {
1297 		ccx->clm_ratio = phydm_ccx_get_rpt_ratio(dm, ccx->clm_result,
1298 							 ccx->clm_period);
1299 	}
1300 }
1301 
1302 boolean
phydm_clm_get_result(void * dm_void)1303 phydm_clm_get_result(void *dm_void)
1304 {
1305 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1306 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1307 	u32 reg1 = 0;
1308 	u32 val = 0;
1309 
1310 	if (dm->support_ic_type & ODM_IC_11AC_SERIES)
1311 		reg1 = R_0x994;
1312 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1313 	else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
1314 		reg1 = R_0x1e60;
1315 	#endif
1316 	else
1317 		reg1 = R_0x890;
1318 	if (!(dm->support_ic_type & (ODM_RTL8822C | ODM_RTL8812F |
1319 				     ODM_RTL8197G | ODM_RTL8723F)))
1320 		odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
1321 	if (!(phydm_clm_check_rdy(dm))) {
1322 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM report Fail\n");
1323 		phydm_clm_racing_release(dm);
1324 		return false;
1325 	}
1326 
1327 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
1328 		val = odm_get_bb_reg(dm, R_0xfa4, MASKLWORD);
1329 		ccx_info->clm_result = (u16)val;
1330 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1331 	} else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
1332 		val = odm_get_bb_reg(dm, R_0x2d88, MASKLWORD);
1333 		ccx_info->clm_result = (u16)val;
1334 	#endif
1335 	} else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
1336 		val = odm_get_bb_reg(dm, R_0x8d0, MASKLWORD);
1337 		ccx_info->clm_result = (u16)val;
1338 	}
1339 
1340 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM result = %d *4 us\n",
1341 		  ccx_info->clm_result);
1342 	phydm_clm_racing_release(dm);
1343 	return true;
1344 }
1345 
1346 boolean
phydm_clm_mntr_set(void * dm_void,struct clm_para_info * clm_para)1347 phydm_clm_mntr_set(void *dm_void, struct clm_para_info *clm_para)
1348 {
1349 	/*@Driver Monitor CLM*/
1350 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1351 	struct ccx_info *ccx = &dm->dm_ccx_info;
1352 	u16 clm_period = 0;
1353 
1354 	if (clm_para->mntr_time == 0)
1355 		return false;
1356 
1357 	if (clm_para->clm_lv >= CLM_MAX_NUM) {
1358 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[WARNING] Wrong LV=%d\n",
1359 			  clm_para->clm_lv);
1360 		return false;
1361 	}
1362 
1363 	if (phydm_clm_racing_ctrl(dm, clm_para->clm_lv) == PHYDM_SET_FAIL)
1364 		return false;
1365 
1366 	if (clm_para->mntr_time >= 262)
1367 		clm_period = CLM_PERIOD_MAX;
1368 	else
1369 		clm_period = clm_para->mntr_time * MS_TO_4US_RATIO;
1370 
1371 	ccx->clm_app = clm_para->clm_app;
1372 	phydm_clm_setting(dm, clm_period);
1373 
1374 	return true;
1375 }
1376 
1377 boolean
phydm_clm_mntr_racing_chk(void * dm_void)1378 phydm_clm_mntr_racing_chk(void *dm_void)
1379 {
1380 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1381 	struct ccx_info *ccx = &dm->dm_ccx_info;
1382 	u32 sys_return_time = 0;
1383 
1384 	if (ccx->clm_manual_ctrl) {
1385 		PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM in manual ctrl\n");
1386 		return true;
1387 	}
1388 
1389 	sys_return_time = ccx->clm_trigger_time + MAX_ENV_MNTR_TIME;
1390 
1391 	if (ccx->clm_app != CLM_BACKGROUND &&
1392 	    (sys_return_time > dm->phydm_sys_up_time)) {
1393 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1394 			  "clm_app=%d, trigger_time %d, sys_time=%d\n",
1395 			  ccx->clm_app, ccx->clm_trigger_time,
1396 			  dm->phydm_sys_up_time);
1397 
1398 		return true;
1399 	}
1400 
1401 	return false;
1402 }
1403 
1404 boolean
phydm_clm_mntr_chk(void * dm_void,u16 monitor_time)1405 phydm_clm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
1406 {
1407 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1408 	struct ccx_info *ccx = &dm->dm_ccx_info;
1409 	struct clm_para_info clm_para = {0};
1410 	boolean clm_chk_result = false;
1411 
1412 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1413 
1414 	if (phydm_clm_mntr_racing_chk(dm))
1415 		return clm_chk_result;
1416 
1417 	clm_para.clm_app = CLM_BACKGROUND;
1418 	clm_para.clm_lv = CLM_LV_1;
1419 	clm_para.mntr_time = monitor_time;
1420 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1421 		if (phydm_clm_mntr_set(dm, &clm_para))
1422 			clm_chk_result = true;
1423 	} else {
1424 		if (monitor_time >= 262)
1425 			ccx->clm_period = 65535;
1426 		else
1427 			ccx->clm_period = monitor_time * MS_TO_4US_RATIO;
1428 
1429 		phydm_clm_h2c(dm, ccx->clm_period, true);
1430 	}
1431 
1432 	return clm_chk_result;
1433 }
1434 
1435 boolean
phydm_clm_mntr_result(void * dm_void)1436 phydm_clm_mntr_result(void *dm_void)
1437 {
1438 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1439 	struct ccx_info *ccx = &dm->dm_ccx_info;
1440 	boolean clm_chk_result = false;
1441 	u32 val = 0;
1442 
1443 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1444 
1445 	if (phydm_clm_mntr_racing_chk(dm))
1446 		return clm_chk_result;
1447 
1448 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1449 		if (phydm_clm_get_result(dm)) {
1450 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
1451 			phydm_clm_get_utility(dm);
1452 			clm_chk_result = true;
1453 		}
1454 	} else {
1455 		if (ccx->clm_fw_result_cnt != 0) {
1456 			val = ccx->clm_fw_result_acc / ccx->clm_fw_result_cnt;
1457 			ccx->clm_ratio = (u8)val;
1458 			clm_chk_result = true;
1459 		} else {
1460 			ccx->clm_ratio = 0;
1461 		}
1462 
1463 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1464 			  "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
1465 			  ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
1466 
1467 		ccx->clm_fw_result_acc = 0;
1468 		ccx->clm_fw_result_cnt = 0;
1469 	}
1470 
1471 	PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ratio=%d\n", ccx->clm_ratio);
1472 
1473 	return clm_chk_result;
1474 }
1475 
phydm_set_clm_mntr_mode(void * dm_void,enum clm_monitor_mode mode)1476 void phydm_set_clm_mntr_mode(void *dm_void, enum clm_monitor_mode mode)
1477 {
1478 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1479 	struct ccx_info *ccx_info = &dm->dm_ccx_info;
1480 
1481 	if (ccx_info->clm_mntr_mode != mode) {
1482 		ccx_info->clm_mntr_mode = mode;
1483 		phydm_ccx_hw_restart(dm);
1484 
1485 		if (mode == CLM_DRIVER_MNTR)
1486 			phydm_clm_h2c(dm, CLM_PERIOD_MAX, 0);
1487 	}
1488 }
1489 
phydm_clm_init(void * dm_void)1490 void phydm_clm_init(void *dm_void)
1491 {
1492 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1493 	struct ccx_info *ccx = &dm->dm_ccx_info;
1494 
1495 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1496 	ccx->clm_ongoing = false;
1497 	ccx->clm_manual_ctrl = 0;
1498 	ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1499 	ccx->clm_period = 0;
1500 	ccx->clm_rpt_stamp = 0;
1501 	phydm_clm_setting(dm, 65535);
1502 }
1503 
phydm_clm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1504 void phydm_clm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
1505 		   u32 *_out_len)
1506 {
1507 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1508 	struct ccx_info *ccx = &dm->dm_ccx_info;
1509 	char help[] = "-h";
1510 	u32 var1[10] = {0};
1511 	u32 used = *_used;
1512 	u32 out_len = *_out_len;
1513 	struct clm_para_info clm_para = {0};
1514 	u32 i;
1515 
1516 	for (i = 0; i < 4; i++) {
1517 		PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
1518 	}
1519 
1520 	if ((strcmp(input[1], help) == 0)) {
1521 		PDM_SNPF(out_len, used, output + used, out_len - used,
1522 			 "CLM Driver Basic-Trigger 262ms: {1}\n");
1523 		PDM_SNPF(out_len, used, output + used, out_len - used,
1524 			 "CLM Driver Adv-Trigger: {2} {app} {LV} {0~262ms}\n");
1525 		PDM_SNPF(out_len, used, output + used, out_len - used,
1526 			 "CLM FW Trigger: {3} {1:drv, 2:fw}\n");
1527 		PDM_SNPF(out_len, used, output + used, out_len - used,
1528 			 "CLM Get Result: {100}\n");
1529 	} else if (var1[0] == 100) { /* @Get CLM results */
1530 
1531 		if (phydm_clm_get_result(dm))
1532 			phydm_clm_get_utility(dm);
1533 
1534 		PDM_SNPF(out_len, used, output + used, out_len - used,
1535 			 "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
1536 
1537 		PDM_SNPF(out_len, used, output + used, out_len - used,
1538 			 "clm_ratio:((%d percent)) = (%d us/ %d us)\n",
1539 			 ccx->clm_ratio, ccx->clm_result << 2,
1540 			 ccx->clm_period << 2);
1541 
1542 		ccx->clm_manual_ctrl = 0;
1543 	} else if (var1[0] == 3) {
1544 		phydm_set_clm_mntr_mode(dm, (enum clm_monitor_mode)var1[1]);
1545 		PDM_SNPF(out_len, used, output + used, out_len - used,
1546 			 "CLM mode: %s mode\n",
1547 			 ((ccx->clm_mntr_mode == CLM_FW_MNTR) ? "FW" : "Drv"));
1548 	} else { /* Set & trigger CLM */
1549 		ccx->clm_manual_ctrl = 1;
1550 
1551 		if (var1[0] == 1) {
1552 			clm_para.clm_app = CLM_BACKGROUND;
1553 			clm_para.clm_lv = CLM_LV_4;
1554 			clm_para.mntr_time = 262;
1555 			ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1556 		} else if (var1[0] == 2) {
1557 			clm_para.clm_app = (enum clm_application)var1[1];
1558 			clm_para.clm_lv = (enum phydm_clm_level)var1[2];
1559 			ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
1560 			clm_para.mntr_time = (u16)var1[3];
1561 		}
1562 
1563 		PDM_SNPF(out_len, used, output + used, out_len - used,
1564 			 "app=%d, lv=%d, mode=%s, time=%d ms\n",
1565 			 clm_para.clm_app, clm_para.clm_lv,
1566 			 ((ccx->clm_mntr_mode == CLM_FW_MNTR) ? "FW" :
1567 			 "driver"), clm_para.mntr_time);
1568 
1569 		if (phydm_clm_mntr_set(dm, &clm_para))
1570 			phydm_clm_trigger(dm);
1571 
1572 		PDM_SNPF(out_len, used, output + used, out_len - used,
1573 			 "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
1574 	}
1575 
1576 	*_used = used;
1577 	*_out_len = out_len;
1578 }
1579 
1580 #endif /*@#ifdef CLM_SUPPORT*/
1581 
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)1582 u8 phydm_env_mntr_trigger(void *dm_void, struct nhm_para_info *nhm_para,
1583 			  struct clm_para_info *clm_para,
1584 			  struct env_trig_rpt *trig_rpt)
1585 {
1586 	u8 trigger_result = 0;
1587 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1588 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1589 	struct ccx_info *ccx = &dm->dm_ccx_info;
1590 	boolean nhm_set_ok = false;
1591 	boolean clm_set_ok = false;
1592 
1593 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1594 
1595 	/*@[NHM]*/
1596 	nhm_set_ok = phydm_nhm_mntr_set(dm, nhm_para);
1597 
1598 	/*@[CLM]*/
1599 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1600 		clm_set_ok = phydm_clm_mntr_set(dm, clm_para);
1601 	} else if (ccx->clm_mntr_mode == CLM_FW_MNTR) {
1602 		phydm_clm_h2c(dm, CLM_PERIOD_MAX, true);
1603 		trigger_result |= CLM_SUCCESS;
1604 	}
1605 
1606 	if (nhm_set_ok) {
1607 		phydm_nhm_trigger(dm);
1608 		trigger_result |= NHM_SUCCESS;
1609 	}
1610 
1611 	if (clm_set_ok) {
1612 		phydm_clm_trigger(dm);
1613 		trigger_result |= CLM_SUCCESS;
1614 	}
1615 
1616 	/*@monitor for the test duration*/
1617 	ccx->start_time = odm_get_current_time(dm);
1618 
1619 	trig_rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
1620 	trig_rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
1621 
1622 	PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n\n",
1623 		  trig_rpt->nhm_rpt_stamp, trig_rpt->clm_rpt_stamp);
1624 #endif
1625 	return trigger_result;
1626 }
1627 
phydm_env_mntr_result(void * dm_void,struct env_mntr_rpt * rpt)1628 u8 phydm_env_mntr_result(void *dm_void, struct env_mntr_rpt *rpt)
1629 {
1630 	u8 env_mntr_rpt = 0;
1631 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
1632 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1633 	struct ccx_info *ccx = &dm->dm_ccx_info;
1634 	u64 progressing_time = 0;
1635 	u32 val_tmp = 0;
1636 
1637 	/*@monitor for the test duration*/
1638 	progressing_time = odm_get_progressing_time(dm, ccx->start_time);
1639 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
1640 	PHYDM_DBG(dm, DBG_ENV_MNTR, "env_time=%lld\n", progressing_time);
1641 
1642 	/*@Get NHM result*/
1643 	if (phydm_nhm_get_result(dm)) {
1644 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
1645 		phydm_nhm_get_utility(dm);
1646 		rpt->nhm_ratio = ccx->nhm_ratio;
1647 		rpt->nhm_env_ratio = ccx->nhm_env_ratio;
1648 		rpt->nhm_noise_pwr = ccx->nhm_level;
1649 		rpt->nhm_pwr = ccx->nhm_pwr;
1650 		env_mntr_rpt |= NHM_SUCCESS;
1651 
1652 		odm_move_memory(dm, &rpt->nhm_result[0],
1653 				&ccx->nhm_result[0], NHM_RPT_NUM);
1654 	} else {
1655 		rpt->nhm_ratio = ENV_MNTR_FAIL;
1656 		rpt->nhm_env_ratio = ENV_MNTR_FAIL;
1657 	}
1658 
1659 	/*@Get CLM result*/
1660 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
1661 		if (phydm_clm_get_result(dm)) {
1662 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
1663 			phydm_clm_get_utility(dm);
1664 			env_mntr_rpt |= CLM_SUCCESS;
1665 			rpt->clm_ratio = ccx->clm_ratio;
1666 		} else {
1667 			rpt->clm_ratio = ENV_MNTR_FAIL;
1668 		}
1669 
1670 	} else {
1671 		if (ccx->clm_fw_result_cnt != 0) {
1672 			val_tmp = ccx->clm_fw_result_acc
1673 			/ ccx->clm_fw_result_cnt;
1674 			ccx->clm_ratio = (u8)val_tmp;
1675 		} else {
1676 			ccx->clm_ratio = 0;
1677 		}
1678 
1679 		rpt->clm_ratio = ccx->clm_ratio;
1680 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1681 			  "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
1682 			  ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
1683 
1684 		ccx->clm_fw_result_acc = 0;
1685 		ccx->clm_fw_result_cnt = 0;
1686 		env_mntr_rpt |= CLM_SUCCESS;
1687 	}
1688 
1689 	rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
1690 	rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
1691 
1692 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1693 		  "IGI=0x%x, nhm_ratio=%d, nhm_env_ratio=%d, clm_ratio=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n\n",
1694 		  ccx->nhm_igi, rpt->nhm_ratio, rpt->nhm_env_ratio,
1695 		  rpt->clm_ratio, rpt->nhm_rpt_stamp, rpt->clm_rpt_stamp);
1696 #endif
1697 	return env_mntr_rpt;
1698 }
1699 
phydm_env_mntr_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1700 void phydm_env_mntr_dbg(void *dm_void, char input[][16], u32 *_used,
1701 			char *output, u32 *_out_len)
1702 {
1703 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1704 	char help[] = "-h";
1705 	u32 var1[10] = {0};
1706 	u32 used = *_used;
1707 	u32 out_len = *_out_len;
1708 	struct clm_para_info clm_para = {0};
1709 	struct nhm_para_info nhm_para = {0};
1710 	struct env_mntr_rpt rpt = {0};
1711 	struct env_trig_rpt trig_rpt = {0};
1712 	struct ccx_info *ccx = &dm->dm_ccx_info;
1713 	u8 set_result = 0;
1714 	u8 i = 0;
1715 
1716 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
1717 
1718 	if ((strcmp(input[1], help) == 0)) {
1719 		PDM_SNPF(out_len, used, output + used, out_len - used,
1720 			 "Basic-Trigger 262ms: {1}\n");
1721 		PDM_SNPF(out_len, used, output + used, out_len - used,
1722 			 "Get Result: {100}\n");
1723 	} else if (var1[0] == 100) { /* Get results */
1724 		set_result = phydm_env_mntr_result(dm, &rpt);
1725 
1726 		PDM_SNPF(out_len, used, output + used, out_len - used,
1727 			 "Set Result=%d\n nhm_ratio=%d nhm_env_ratio=%d clm_ratio=%d\n nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n",
1728 			 set_result, rpt.nhm_ratio, rpt.nhm_env_ratio,
1729 			 rpt.clm_ratio, rpt.nhm_rpt_stamp, rpt.clm_rpt_stamp);
1730 
1731 		for (i = 0; i <= 11; i++) {
1732 			PDM_SNPF(out_len, used, output + used, out_len - used,
1733 				 "nhm_rpt[%d] = %d (%d percent)\n", i,
1734 				 rpt.nhm_result[i],
1735 				 (((rpt.nhm_result[i] * 100) + 128) >> 8));
1736 		}
1737 		PDM_SNPF(out_len, used, output + used, out_len - used,
1738 			 "[NHM] valid: %d percent, noise(RSSI) = %d\n",
1739 			 ccx->nhm_level_valid, ccx->nhm_level);
1740 	} else { /* Set & trigger*/
1741 		/*nhm para*/
1742 		nhm_para.incld_txon = NHM_EXCLUDE_TXON;
1743 		nhm_para.incld_cca = NHM_EXCLUDE_CCA;
1744 		nhm_para.div_opt = NHM_CNT_ALL;
1745 		nhm_para.nhm_app = NHM_ACS;
1746 		nhm_para.nhm_lv = NHM_LV_2;
1747 		nhm_para.mntr_time = 262;
1748 		nhm_para.en_1db_mode = false;
1749 
1750 		/*clm para*/
1751 		clm_para.clm_app = CLM_ACS;
1752 		clm_para.clm_lv = CLM_LV_2;
1753 		clm_para.mntr_time = 262;
1754 
1755 		set_result = phydm_env_mntr_trigger(dm, &nhm_para,
1756 						    &clm_para, &trig_rpt);
1757 
1758 		PDM_SNPF(out_len, used, output + used, out_len - used,
1759 			 "Set Result=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n",
1760 			 set_result, trig_rpt.nhm_rpt_stamp,
1761 			 trig_rpt.clm_rpt_stamp);
1762 	}
1763 
1764 	*_used = used;
1765 	*_out_len = out_len;
1766 }
1767 
1768 #ifdef FAHM_SUPPORT
1769 
phydm_fahm_racing_release(void * dm_void)1770 void phydm_fahm_racing_release(void *dm_void)
1771 {
1772 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1773 	struct ccx_info *ccx = &dm->dm_ccx_info;
1774 	u32 value32 = 0;
1775 
1776 	PHYDM_DBG(dm, DBG_ENV_MNTR, "fahm_racing_release : lv:(%d)->(0)\n",
1777 		  ccx->fahm_set_lv);
1778 
1779 	ccx->fahm_ongoing = false;
1780 	ccx->fahm_set_lv = FAHM_RELEASE;
1781 
1782 	if (!(ccx->fahm_app == FAHM_BACKGROUND || ccx->fahm_app == FAHM_ACS))
1783 		phydm_pause_func(dm, F00_DIG, PHYDM_RESUME,
1784 				 PHYDM_PAUSE_LEVEL_1, 1, &value32);
1785 
1786 	ccx->fahm_app = FAHM_BACKGROUND;
1787 }
1788 
phydm_fahm_racing_ctrl(void * dm_void,enum phydm_fahm_level lv)1789 u8 phydm_fahm_racing_ctrl(void *dm_void, enum phydm_fahm_level lv)
1790 {
1791 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1792 	struct ccx_info *ccx = &dm->dm_ccx_info;
1793 	u8 set_result = PHYDM_SET_SUCCESS;
1794 	/*acquire to control FAHM API*/
1795 
1796 	PHYDM_DBG(dm, DBG_ENV_MNTR, "fahm_ongoing=%d, lv:(%d)->(%d)\n",
1797 		  ccx->fahm_ongoing, ccx->fahm_set_lv, lv);
1798 	if (ccx->fahm_ongoing) {
1799 		if (lv <= ccx->fahm_set_lv) {
1800 			set_result = PHYDM_SET_FAIL;
1801 		} else {
1802 			phydm_ccx_hw_restart(dm);
1803 			ccx->fahm_ongoing = false;
1804 		}
1805 	}
1806 
1807 	if (set_result)
1808 		ccx->fahm_set_lv = lv;
1809 
1810 	PHYDM_DBG(dm, DBG_ENV_MNTR, "fahm racing success=%d\n", set_result);
1811 	return set_result;
1812 }
1813 
phydm_fahm_trigger(void * dm_void)1814 void phydm_fahm_trigger(void *dm_void)
1815 { /*@unit (4us)*/
1816 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1817 	struct ccx_info *ccx = &dm->dm_ccx_info;
1818 	u32 reg = 0;
1819 
1820 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1821 
1822 	switch (dm->ic_ip_series) {
1823 	case PHYDM_IC_JGR3:
1824 		reg = R_0x1e60;
1825 		break;
1826 	case PHYDM_IC_AC:
1827 		reg = R_0x994;
1828 		break;
1829 	case PHYDM_IC_N:
1830 		reg = R_0x890;
1831 		break;
1832 	default:
1833 		break;
1834 	}
1835 
1836 	odm_set_bb_reg(dm, reg, BIT(2), 0);
1837 	odm_set_bb_reg(dm, reg, BIT(2), 1);
1838 
1839 	ccx->fahm_trigger_time = dm->phydm_sys_up_time;
1840 	ccx->fahm_rpt_stamp++;
1841 	ccx->fahm_ongoing = true;
1842 }
1843 
1844 boolean
phydm_fahm_check_rdy(void * dm_void)1845 phydm_fahm_check_rdy(void *dm_void)
1846 {
1847 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1848 	boolean is_ready = false;
1849 	u32 reg = 0, reg_bit = 0;
1850 
1851 	switch (dm->ic_ip_series) {
1852 	case PHYDM_IC_JGR3:
1853 		reg = R_0x2d84;
1854 		reg_bit = 31;
1855 		break;
1856 	case PHYDM_IC_AC:
1857 		reg = R_0x1f98;
1858 		reg_bit = 31;
1859 		break;
1860 	case PHYDM_IC_N:
1861 		reg = R_0x9f0;
1862 		reg_bit = 31;
1863 		break;
1864 	default:
1865 		break;
1866 	}
1867 
1868 	if (odm_get_bb_reg(dm, reg, BIT(reg_bit)))
1869 		is_ready = true;
1870 
1871 	PHYDM_DBG(dm, DBG_ENV_MNTR, "FAHM rdy=%d\n", is_ready);
1872 
1873 	return is_ready;
1874 }
1875 
phydm_fahm_cal_wgt_avg(void * dm_void,u8 start_i,u8 end_i,u16 r_sum,u16 period)1876 u8 phydm_fahm_cal_wgt_avg(void *dm_void, u8 start_i, u8 end_i, u16 r_sum,
1877 			  u16 period)
1878 {
1879 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1880 	struct ccx_info *ccx = &dm->dm_ccx_info;
1881 	u8 i = 0;
1882 	u32 pwr_tmp = 0;
1883 	u8 pwr = 0;
1884 	u32 fahm_valid = 0;
1885 
1886 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
1887 
1888 	if (r_sum == 0) {
1889 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1890 			  "rpt_sum = 0, don't need to update\n");
1891 		return 0x0;
1892 	} else if (end_i > FAHM_RPT_NUM - 1) {
1893 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1894 			  "[WARNING]end_i is larger than 11!!\n");
1895 		return 0x0;
1896 	}
1897 
1898 	for (i = start_i; i <= end_i; i++) {
1899 		if (i == 0)
1900 			pwr_tmp += ccx->fahm_result[0] *
1901 				   MAX_2(ccx->fahm_th[0] - 2, 0);
1902 		else if (i == (FAHM_RPT_NUM - 1))
1903 			pwr_tmp += ccx->fahm_result[FAHM_RPT_NUM - 1] *
1904 				   (ccx->fahm_th[FAHM_TH_NUM - 1] + 2);
1905 		else
1906 			pwr_tmp += ccx->fahm_result[i] *
1907 				   (ccx->fahm_th[i - 1] + ccx->fahm_th[i]) >> 1;
1908 	}
1909 
1910 	/* protection for the case of minus pwr(RSSI)*/
1911 	pwr = (u8)(NTH_TH_2_RSSI(MAX_2(PHYDM_DIV(pwr_tmp, r_sum), 20)));
1912 	fahm_valid = PHYDM_DIV(r_sum * 100, period);
1913 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1914 		  "valid: ((%d)) percent, pwr(RSSI)=((%d))\n",
1915 		  fahm_valid, pwr);
1916 
1917 	return pwr;
1918 }
1919 
phydm_fahm_get_utility(void * dm_void)1920 void phydm_fahm_get_utility(void *dm_void)
1921 {
1922 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1923 	struct ccx_info *ccx = &dm->dm_ccx_info;
1924 
1925 	if (ccx->fahm_result_sum >= ccx->fahm_result[0]) {
1926 		ccx->fahm_pwr = phydm_fahm_cal_wgt_avg(dm, 0, FAHM_RPT_NUM - 1,
1927 						       ccx->fahm_result_sum,
1928 						       ccx->fahm_period);
1929 		ccx->fahm_ratio = phydm_ccx_get_rpt_ratio(dm,
1930 				  ccx->fahm_result_sum, ccx->fahm_period);
1931 		ccx->fahm_denom_ratio = phydm_ccx_get_rpt_ratio(dm,
1932 					ccx->fahm_denom_result,
1933 					ccx->fahm_period);
1934 	} else {
1935 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1936 			  "[warning] fahm_result_sum invalid\n");
1937 		ccx->fahm_pwr = 0;
1938 		ccx->fahm_ratio = 0;
1939 		ccx->fahm_denom_ratio = 0;
1940 	}
1941 
1942 	PHYDM_DBG(dm, DBG_ENV_MNTR,
1943 		  "fahm_pwr=%d, fahm_ratio=%d, fahm_denom_ratio=%d\n",
1944 		  ccx->fahm_pwr, ccx->fahm_ratio, ccx->fahm_denom_ratio);
1945 }
1946 
1947 boolean
phydm_fahm_get_result(void * dm_void)1948 phydm_fahm_get_result(void *dm_void)
1949 {
1950 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1951 	struct ccx_info *ccx = &dm->dm_ccx_info;
1952 	u32 value32 = 0;
1953 	u32 reg1 = 0;
1954 	u32 reg2 = 0;
1955 	u8 i = 0;
1956 	u32 fahm_rpt_sum_tmp = 0;
1957 
1958 	switch (dm->ic_ip_series) {
1959 	case PHYDM_IC_JGR3:
1960 		reg1 = R_0x2d6c;
1961 		reg2 = R_0x2d84;
1962 		break;
1963 	case PHYDM_IC_AC:
1964 		reg1 = R_0x1f80;
1965 		reg2 = R_0x1f98;
1966 		break;
1967 	case PHYDM_IC_N:
1968 		reg1 = R_0x9d8;
1969 		reg2 = R_0x9f0;
1970 		break;
1971 	default:
1972 		break;
1973 	}
1974 
1975 	if (!(phydm_fahm_check_rdy(dm))) {
1976 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get FAHM report Fail\n");
1977 		phydm_fahm_racing_release(dm);
1978 		return false;
1979 	}
1980 
1981 	/*Get FAHM numerator and sum all fahm_result*/
1982 	for (i = 0; i < 6; i++) {
1983 		value32 = odm_get_bb_reg(dm, reg1 + (i << 2), MASKDWORD);
1984 		ccx->fahm_result[i * 2] = (u16)(value32 & MASKLWORD);
1985 		ccx->fahm_result[i * 2 + 1] = (u16)((value32 & MASKHWORD) >> 16);
1986 		fahm_rpt_sum_tmp = (u32)(fahm_rpt_sum_tmp +
1987 					 ccx->fahm_result[i * 2] +
1988 					 ccx->fahm_result[i * 2 + 1]);
1989 	}
1990 	ccx->fahm_result_sum = (u16)fahm_rpt_sum_tmp;
1991 
1992 	/*Get FAHM Denominator*/
1993 	ccx->fahm_denom_result = (u16)odm_get_bb_reg(dm, reg2, MASKLWORD);
1994 
1995 	if (!(ccx->fahm_inclu_cck))
1996 		PHYDM_DBG(dm, DBG_ENV_MNTR,
1997 			  "===>The following fahm report does not count CCK pkt\n");
1998 
1999 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2000 		  "fahm_result_sum=%d, fahm_denom_result = %d\n",
2001 		  ccx->fahm_result_sum, ccx->fahm_denom_result);
2002 
2003 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2004 		  "FAHM_Rpt[%d](H->L)[%d %d %d %d %d %d %d %d %d %d %d %d]\n",
2005 		  ccx->fahm_rpt_stamp, ccx->fahm_result[11],
2006 		  ccx->fahm_result[10], ccx->fahm_result[9],
2007 		  ccx->fahm_result[8], ccx->fahm_result[7], ccx->fahm_result[6],
2008 		  ccx->fahm_result[5], ccx->fahm_result[4], ccx->fahm_result[3],
2009 		  ccx->fahm_result[2], ccx->fahm_result[1],
2010 		  ccx->fahm_result[0]);
2011 
2012 	phydm_fahm_racing_release(dm);
2013 
2014 	if (fahm_rpt_sum_tmp > 0xffff) {
2015 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2016 			  "[Warning] Invalid FAHM RPT, total=%d\n",
2017 			  fahm_rpt_sum_tmp);
2018 		return false;
2019 	}
2020 
2021 	return true;
2022 }
2023 
phydm_fahm_set_th_reg(void * dm_void)2024 void phydm_fahm_set_th_reg(void *dm_void)
2025 {
2026 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2027 	struct ccx_info *ccx = &dm->dm_ccx_info;
2028 	u32 val = 0;
2029 
2030 	/*Set FAHM threshold*/ /*Unit: PWdB U(8,1)*/
2031 	switch (dm->ic_ip_series) {
2032 	case PHYDM_IC_JGR3:
2033 		val = BYTE_2_DWORD(ccx->fahm_th[3], ccx->fahm_th[2],
2034 				   ccx->fahm_th[1], ccx->fahm_th[0]);
2035 		odm_set_bb_reg(dm, R_0x1e50, MASKDWORD, val);
2036 		val = BYTE_2_DWORD(ccx->fahm_th[7], ccx->fahm_th[6],
2037 				   ccx->fahm_th[5], ccx->fahm_th[4]);
2038 		odm_set_bb_reg(dm, R_0x1e54, MASKDWORD, val);
2039 		val = BYTE_2_DWORD(0, ccx->fahm_th[10], ccx->fahm_th[9],
2040 				   ccx->fahm_th[8]);
2041 		odm_set_bb_reg(dm, R_0x1e58, 0xffffff, val);
2042 		break;
2043 	case PHYDM_IC_AC:
2044 		val = BYTE_2_DWORD(0, ccx->fahm_th[2], ccx->fahm_th[1],
2045 				   ccx->fahm_th[0]);
2046 		odm_set_bb_reg(dm, R_0x1c38, 0xffffff00, val);
2047 		val = BYTE_2_DWORD(0, ccx->fahm_th[5], ccx->fahm_th[4],
2048 				   ccx->fahm_th[3]);
2049 		odm_set_bb_reg(dm, R_0x1c78, 0xffffff00, val);
2050 		val = BYTE_2_DWORD(0, 0, ccx->fahm_th[7], ccx->fahm_th[6]);
2051 		odm_set_bb_reg(dm, R_0x1c7c, 0xffff0000, val);
2052 		val = BYTE_2_DWORD(0, ccx->fahm_th[10], ccx->fahm_th[9],
2053 				   ccx->fahm_th[8]);
2054 		odm_set_bb_reg(dm, R_0x1cb8, 0xffffff00, val);
2055 		break;
2056 	case PHYDM_IC_N:
2057 		val = BYTE_2_DWORD(ccx->fahm_th[3], ccx->fahm_th[2],
2058 				   ccx->fahm_th[1], ccx->fahm_th[0]);
2059 		odm_set_bb_reg(dm, R_0x970, MASKDWORD, val);
2060 		val = BYTE_2_DWORD(ccx->fahm_th[7], ccx->fahm_th[6],
2061 				   ccx->fahm_th[5], ccx->fahm_th[4]);
2062 		odm_set_bb_reg(dm, R_0x974, MASKDWORD, val);
2063 		val = BYTE_2_DWORD(0, ccx->fahm_th[10], ccx->fahm_th[9],
2064 				   ccx->fahm_th[8]);
2065 		odm_set_bb_reg(dm, R_0x978, 0xffffff, val);
2066 		break;
2067 	default:
2068 		break;
2069 	}
2070 
2071 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2072 		  "Update FAHM_th[H->L]=[%d %d %d %d %d %d %d %d %d %d %d]\n",
2073 		  ccx->fahm_th[10], ccx->fahm_th[9], ccx->fahm_th[8],
2074 		  ccx->fahm_th[7], ccx->fahm_th[6], ccx->fahm_th[5],
2075 		  ccx->fahm_th[4], ccx->fahm_th[3], ccx->fahm_th[2],
2076 		  ccx->fahm_th[1], ccx->fahm_th[0]);
2077 }
2078 
2079 boolean
phydm_fahm_th_update_chk(void * dm_void,enum fahm_application fahm_app,u8 * fahm_th,u32 * igi_new,boolean en_1db_mode,u8 fahm_th0_manual)2080 phydm_fahm_th_update_chk(void *dm_void, enum fahm_application fahm_app,
2081 			 u8 *fahm_th, u32 *igi_new, boolean en_1db_mode,
2082 			 u8 fahm_th0_manual)
2083 {
2084 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2085 	struct ccx_info *ccx = &dm->dm_ccx_info;
2086 	boolean is_update = false;
2087 	u8 igi_curr = phydm_get_igi(dm, BB_PATH_A);
2088 	u8 i = 0;
2089 	u8 th_tmp = igi_curr - CCA_CAP;
2090 	u8 th_step = 2;
2091 
2092 	PHYDM_DBG(dm, DBG_ENV_MNTR, "fahm_th_update_chk : App=%d, fahm_igi=0x%x, igi_curr=0x%x\n",
2093 		  fahm_app, ccx->fahm_igi, igi_curr);
2094 
2095 	if (igi_curr < 0x10) /* Protect for invalid IGI*/
2096 		return false;
2097 
2098 	switch (fahm_app) {
2099 	case FAHM_BACKGROUND: /*Get IGI from driver parameter(cur_ig_value)*/
2100 		if (ccx->fahm_igi != igi_curr || ccx->fahm_app != fahm_app) {
2101 			is_update = true;
2102 			*igi_new = (u32)igi_curr;
2103 
2104 			fahm_th[0] = (u8)IGI_2_NHM_TH(th_tmp);
2105 
2106 			for (i = 1; i <= 10; i++)
2107 				fahm_th[i] = fahm_th[0] +
2108 					    IGI_2_NHM_TH(th_step * i);
2109 
2110 		}
2111 		break;
2112 	case FAHM_ACS:
2113 		if (ccx->fahm_igi != igi_curr || ccx->fahm_app != fahm_app) {
2114 			is_update = true;
2115 			*igi_new = (u32)igi_curr;
2116 			fahm_th[0] = (u8)IGI_2_NHM_TH(igi_curr - CCA_CAP);
2117 			for (i = 1; i <= 10; i++)
2118 				fahm_th[i] = fahm_th[0] + IGI_2_NHM_TH(2 * i);
2119 		}
2120 		break;
2121 	case FAHM_DBG: /*Get IGI from register*/
2122 		igi_curr = phydm_get_igi(dm, BB_PATH_A);
2123 		if (ccx->fahm_igi != igi_curr || ccx->fahm_app != fahm_app) {
2124 			is_update = true;
2125 			*igi_new = (u32)igi_curr;
2126 			if (en_1db_mode) {
2127 				fahm_th[0] = (u8)IGI_2_NHM_TH(fahm_th0_manual +
2128 							      10);
2129 				th_step = 1;
2130 			} else {
2131 				fahm_th[0] = (u8)IGI_2_NHM_TH(igi_curr -
2132 							      CCA_CAP);
2133 			}
2134 
2135 			for (i = 1; i <= 10; i++)
2136 				fahm_th[i] = fahm_th[0] +
2137 					     IGI_2_NHM_TH(th_step * i);
2138 		}
2139 		break;
2140 	}
2141 
2142 	if (is_update) {
2143 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update FAHM_TH] igi_RSSI=%d\n",
2144 			  IGI_2_RSSI(*igi_new));
2145 
2146 		for (i = 0; i < FAHM_TH_NUM; i++)
2147 			PHYDM_DBG(dm, DBG_ENV_MNTR, "FAHM_th[%d](RSSI) = %d\n",
2148 				  i, NTH_TH_2_RSSI(fahm_th[i]));
2149 	} else {
2150 		PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update FAHM_TH\n");
2151 	}
2152 	return is_update;
2153 }
2154 
phydm_fahm_set(void * dm_void,u8 numer_opt,u8 denom_opt,enum fahm_application app,u16 period,boolean en_1db_mode,u8 th0_manual)2155 void phydm_fahm_set(void *dm_void, u8 numer_opt, u8 denom_opt,
2156 		    enum fahm_application app, u16 period, boolean en_1db_mode,
2157 		    u8 th0_manual)
2158 {
2159 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2160 	struct ccx_info *ccx = &dm->dm_ccx_info;
2161 	u8 fahm_th[FAHM_TH_NUM] = {0};
2162 	u32 igi = 0x20;
2163 	u32 reg1 = 0, reg2 = 0, reg3 = 0;
2164 	u32 val_tmp = 0;
2165 
2166 	PHYDM_DBG(dm, DBG_ENV_MNTR, "numer_opt=%d, denom_opt=%d, period=%d\n",
2167 		  numer_opt, denom_opt, period);
2168 
2169 	switch (dm->ic_ip_series) {
2170 	case PHYDM_IC_JGR3:
2171 		reg1 = R_0x1e60;
2172 		reg2 = R_0x1e58;
2173 		reg3 = R_0x1e5c;
2174 		break;
2175 	case PHYDM_IC_AC:
2176 		reg1 = R_0x994;
2177 		reg2 = R_0x1cf8;
2178 		break;
2179 	case PHYDM_IC_N:
2180 		reg1 = R_0x890;
2181 		reg2 = R_0x978;
2182 		reg3 = R_0x97c;
2183 		break;
2184 	default:
2185 		 break;
2186 	}
2187 
2188 	/*Set enable fa, ignore crc32 ok, ignore crc32 err*/
2189 	if (numer_opt != ccx->fahm_numer_opt ||
2190 	    denom_opt != ccx->fahm_denom_opt) {
2191 		odm_set_bb_reg(dm, reg1, 0xe0, numer_opt);
2192 		odm_set_bb_reg(dm, reg1, 0x7000, denom_opt);
2193 		ccx->fahm_numer_opt = numer_opt;
2194 		ccx->fahm_denom_opt = denom_opt;
2195 
2196 		/*[PHYDM-400]*/
2197 		/*Counting B mode pkt for new B mode IP or fahm_opt is non-FA*/
2198 		if ((dm->support_ic_type & ODM_RTL8723F) ||
2199 		    (((numer_opt | denom_opt) & FAHM_INCLU_FA) == 0))
2200 			ccx->fahm_inclu_cck = true;
2201 		else
2202 			ccx->fahm_inclu_cck = false;
2203 
2204 		odm_set_bb_reg(dm, reg1, BIT(4), ccx->fahm_inclu_cck);
2205 		PHYDM_DBG(dm, DBG_ENV_MNTR, "fahm_inclu_cck=%d\n",
2206 			  ccx->fahm_inclu_cck);
2207 	}
2208 
2209 	/*Set FAHM period*/
2210 	if (period != ccx->fahm_period) {
2211 		switch (dm->ic_ip_series) {
2212 		case PHYDM_IC_AC:
2213 			odm_set_bb_reg(dm, reg2, 0xffff00, period);
2214 			break;
2215 		case PHYDM_IC_JGR3:
2216 		case PHYDM_IC_N:
2217 			odm_set_bb_reg(dm, reg2, 0xff000000, (period & 0xff));
2218 			odm_set_bb_reg(dm, reg3, 0xff, (period & 0xff00) >> 8);
2219 			break;
2220 		default:
2221 			break;
2222 		}
2223 
2224 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2225 			  "Update FAHM period ((%d)) -> ((%d))\n",
2226 			  ccx->fahm_period, period);
2227 
2228 		ccx->fahm_period = period;
2229 	}
2230 
2231 	/*Set FAHM threshold*/
2232 	if (phydm_fahm_th_update_chk(dm, app, &fahm_th[0], &igi, en_1db_mode,
2233 				     th0_manual)) {
2234 		/*Pause IGI*/
2235 		if (app == FAHM_BACKGROUND || app == FAHM_ACS) {
2236 			PHYDM_DBG(dm, DBG_ENV_MNTR, "DIG Free Run\n");
2237 		} else if (phydm_pause_func(dm, F00_DIG, PHYDM_PAUSE,
2238 					    PHYDM_PAUSE_LEVEL_1, 1, &igi)
2239 					    == PAUSE_FAIL) {
2240 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG Fail\n");
2241 			return;
2242 		} else {
2243 			PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG=0x%x\n", igi);
2244 		}
2245 		ccx->fahm_app = app;
2246 		ccx->fahm_igi = (u8)igi;
2247 		odm_move_memory(dm, &ccx->fahm_th[0], &fahm_th, FAHM_TH_NUM);
2248 
2249 		/*Set FAHM th*/
2250 		phydm_fahm_set_th_reg(dm);
2251 	}
2252 }
2253 
2254 boolean
phydm_fahm_mntr_set(void * dm_void,struct fahm_para_info * para)2255 phydm_fahm_mntr_set(void *dm_void, struct fahm_para_info *para)
2256 {
2257 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2258 	u16 fahm_time = 0; /*unit: 4us*/
2259 
2260 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2261 
2262 	if (para->mntr_time == 0)
2263 		return false;
2264 
2265 	if (para->lv >= FAHM_MAX_NUM) {
2266 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n", para->lv);
2267 		return false;
2268 	}
2269 
2270 	if (phydm_fahm_racing_ctrl(dm, para->lv) == PHYDM_SET_FAIL)
2271 		return false;
2272 
2273 	if (para->mntr_time >= 262)
2274 		fahm_time = FAHM_PERIOD_MAX;
2275 	else
2276 		fahm_time = para->mntr_time * MS_TO_4US_RATIO;
2277 
2278 	phydm_fahm_set(dm, para->numer_opt, para->denom_opt, para->app,
2279 		       fahm_time, para->en_1db_mode, para->th0_manual);
2280 
2281 	return true;
2282 }
2283 
2284 boolean
phydm_fahm_mntr_racing_chk(void * dm_void)2285 phydm_fahm_mntr_racing_chk(void *dm_void)
2286 {
2287 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2288 	struct ccx_info *ccx = &dm->dm_ccx_info;
2289 	u32 sys_return_time = 0;
2290 
2291 	if (ccx->fahm_manual_ctrl) {
2292 		PHYDM_DBG(dm, DBG_ENV_MNTR, "FAHM in manual ctrl\n");
2293 		return true;
2294 	}
2295 
2296 	sys_return_time = ccx->fahm_trigger_time + MAX_ENV_MNTR_TIME;
2297 
2298 	if (ccx->fahm_app != FAHM_BACKGROUND &&
2299 	    (sys_return_time > dm->phydm_sys_up_time)) {
2300 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2301 			  "fahm_app=%d, trigger_time %d, sys_time=%d\n",
2302 			  ccx->fahm_app, ccx->fahm_trigger_time,
2303 			  dm->phydm_sys_up_time);
2304 
2305 		return true;
2306 	}
2307 
2308 	return false;
2309 }
2310 
2311 boolean
phydm_fahm_mntr_chk(void * dm_void,u16 monitor_time)2312 phydm_fahm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
2313 {
2314 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2315 	struct ccx_info *ccx = &dm->dm_ccx_info;
2316 	struct fahm_para_info para = {0};
2317 	boolean fahm_chk_result = false;
2318 
2319 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2320 
2321 	if (phydm_fahm_mntr_racing_chk(dm))
2322 		return fahm_chk_result;
2323 
2324 	/*[FAHM trigger setting]------------------------------------------*/
2325 	para.numer_opt = FAHM_INCLU_FA;
2326 	para.denom_opt = FAHM_INCLU_CRC_ERR;
2327 	para.app = FAHM_BACKGROUND;
2328 	para.lv = FAHM_LV_1;
2329 	para.en_1db_mode = false;
2330 	para.mntr_time = monitor_time;
2331 
2332 	fahm_chk_result = phydm_fahm_mntr_set(dm, &para);
2333 
2334 	return fahm_chk_result;
2335 }
2336 
2337 boolean
phydm_fahm_mntr_result(void * dm_void)2338 phydm_fahm_mntr_result(void *dm_void)
2339 {
2340 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2341 	struct ccx_info *ccx = &dm->dm_ccx_info;
2342 	boolean fahm_chk_result = false;
2343 
2344 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2345 
2346 	if (phydm_fahm_mntr_racing_chk(dm))
2347 		return fahm_chk_result;
2348 
2349 	/*[FAHM get result & calculate Utility]---------------------------*/
2350 	if (phydm_fahm_get_result(dm)) {
2351 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get FAHM_rpt success\n");
2352 		phydm_fahm_get_utility(dm);
2353 		fahm_chk_result = true;
2354 	}
2355 
2356 	return fahm_chk_result;
2357 }
2358 
phydm_fahm_init(void * dm_void)2359 void phydm_fahm_init(void *dm_void)
2360 {
2361 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2362 	struct ccx_info *ccx = &dm->dm_ccx_info;
2363 	u32 reg = 0;
2364 
2365 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM))
2366 		return;
2367 
2368 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2369 
2370 	ccx->fahm_app = FAHM_BACKGROUND;
2371 	ccx->fahm_igi = 0xff;
2372 
2373 	/*Set FAHM threshold*/
2374 	ccx->fahm_ongoing = false;
2375 	ccx->fahm_set_lv = FAHM_RELEASE;
2376 
2377 	if (phydm_fahm_th_update_chk(dm, ccx->fahm_app, &ccx->fahm_th[0],
2378 				    (u32 *)&ccx->fahm_igi, false, 0))
2379 		phydm_fahm_set_th_reg(dm);
2380 
2381 	ccx->fahm_period = 0;
2382 	ccx->fahm_numer_opt = 0;
2383 	ccx->fahm_denom_opt = 0;
2384 	ccx->fahm_manual_ctrl = 0;
2385 	ccx->fahm_rpt_stamp = 0;
2386 	ccx->fahm_inclu_cck = false;
2387 
2388 	switch (dm->ic_ip_series) {
2389 	case PHYDM_IC_JGR3:
2390 		reg = R_0x1e60;
2391 		break;
2392 	case PHYDM_IC_AC:
2393 		reg = R_0x994;
2394 		break;
2395 	case PHYDM_IC_N:
2396 		reg = R_0x890;
2397 		break;
2398 	default:
2399 		break;
2400 	}
2401 
2402 	/*Counting OFDM pkt*/
2403 	odm_set_bb_reg(dm, reg, BIT(3), 1);
2404 }
2405 
phydm_fahm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)2406 void phydm_fahm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
2407 		    u32 *_out_len)
2408 {
2409 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2410 	struct ccx_info *ccx = &dm->dm_ccx_info;
2411 	struct fahm_para_info para = {0};
2412 	char help[] = "-h";
2413 	u32 var1[10] = {0};
2414 	u32 used = *_used;
2415 	u32 out_len = *_out_len;
2416 	u16 result_tmp = 0;
2417 	u8 i = 0;
2418 
2419 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM))
2420 		return;
2421 
2422 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
2423 
2424 	if ((strcmp(input[1], help) == 0)) {
2425 		PDM_SNPF(out_len, used, output + used, out_len - used,
2426 			 "FAHM Basic-Trigger 262ms: {1}\n");
2427 		PDM_SNPF(out_len, used, output + used, out_len - used,
2428 			 "FAHM Adv-Trigger: {2} {numer_opt} {denom_opt}\n {App:1 for dbg} {LV:1~4} {0~262ms}, 1dB mode :{en} {t[0](RSSI)}\n");
2429 		PDM_SNPF(out_len, used, output + used, out_len - used,
2430 			 "FAHM Get Result: {100}\n");
2431 		PDM_SNPF(out_len, used, output + used, out_len - used,
2432 			 "numer_opt/denom_opt: {BIT 0/1/2} = {FA/CRC32_OK/CRC32_ERR}\n");
2433 	} else if (var1[0] == 100) { /*Get FAHM results*/
2434 		PDM_SNPF(out_len, used, output + used, out_len - used,
2435 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->fahm_igi,
2436 			 ccx->fahm_rpt_stamp);
2437 
2438 		if (phydm_fahm_get_result(dm)) {
2439 			if (!(ccx->fahm_inclu_cck))
2440 				PDM_SNPF(out_len, used, output + used,
2441 					 out_len - used,
2442 					 "===>The following fahm report does not count CCK pkt\n");
2443 
2444 			for (i = 0; i < FAHM_RPT_NUM; i++) {
2445 				result_tmp = ccx->fahm_result[i];
2446 				PDM_SNPF(out_len, used, output + used,
2447 					 out_len - used,
2448 					 "fahm_rpt[%d] = %d (%d percent)\n",
2449 					 i, result_tmp,
2450 					 (((result_tmp * 100) + 32768) >> 16));
2451 			}
2452 			phydm_fahm_get_utility(dm);
2453 
2454 			PDM_SNPF(out_len, used, output + used, out_len - used,
2455 				 "fahm_pwr=%d, fahm_ratio=%d, fahm_denom_ratio=%d\n",
2456 				 ccx->fahm_pwr, ccx->fahm_ratio,
2457 				 ccx->fahm_denom_ratio);
2458 		} else {
2459 			PDM_SNPF(out_len, used, output + used, out_len - used,
2460 				 "Get FAHM_rpt Fail\n");
2461 		}
2462 		ccx->fahm_manual_ctrl = 0;
2463 	} else { /*FAMH trigger*/
2464 		ccx->fahm_manual_ctrl = 1;
2465 
2466 		for (i = 1; i < 9; i++)
2467 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
2468 
2469 		if (var1[0] == 1) {
2470 			para.numer_opt = FAHM_INCLU_FA;
2471 			para.denom_opt = FAHM_INCLU_CRC_ERR;
2472 			para.app = FAHM_DBG;
2473 			para.lv = FAHM_LV_4;
2474 			para.mntr_time = 262;
2475 			para.en_1db_mode = false;
2476 			para.th0_manual = 0;
2477 		} else {
2478 			para.numer_opt = (u8)var1[1];
2479 			para.denom_opt = (u8)var1[2];
2480 			para.app = (enum fahm_application)var1[3];
2481 			para.lv = (enum phydm_fahm_level)var1[4];
2482 			para.mntr_time = (u16)var1[5];
2483 			para.en_1db_mode = (boolean)var1[6];
2484 			para.th0_manual = (u8)var1[7];
2485 		}
2486 
2487 		PDM_SNPF(out_len, used, output + used, out_len - used,
2488 			 "numer_opt=%d, denom_opt=%d, app=%d, lv=%d, time=%d ms\n",
2489 			 para.numer_opt, para.denom_opt,para.app, para.lv,
2490 			 para.mntr_time);
2491 
2492 		PDM_SNPF(out_len, used, output + used, out_len - used,
2493 			 "en_1db_mode=%d, th0(for 1db mode)=%d\n",
2494 			 para.en_1db_mode, para.th0_manual);
2495 
2496 		if (phydm_fahm_mntr_set(dm, &para))
2497 			phydm_fahm_trigger(dm);
2498 
2499 		PDM_SNPF(out_len, used, output + used, out_len - used,
2500 			 "IGI=0x%x, rpt_stamp=%d\n", ccx->fahm_igi,
2501 			 ccx->fahm_rpt_stamp);
2502 
2503 		for (i = 0; i < FAHM_TH_NUM; i++)
2504 			PDM_SNPF(out_len, used, output + used, out_len - used,
2505 				 "FAHM_th[%d] RSSI = %d\n", i,
2506 				 NTH_TH_2_RSSI(ccx->fahm_th[i]));
2507 	}
2508 
2509 	*_used = used;
2510 	*_out_len = out_len;
2511 }
2512 
2513 #endif /*#ifdef FAHM_SUPPORT*/
2514 
2515 #ifdef IFS_CLM_SUPPORT
phydm_ifs_clm_restart(void * dm_void)2516 void phydm_ifs_clm_restart(void *dm_void)
2517 {
2518 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2519 
2520 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2521 
2522 	/*restart IFS_CLM*/
2523 	odm_set_bb_reg(dm, R_0x1ee4, BIT(29), 0x0);
2524 	odm_set_bb_reg(dm, R_0x1ee4, BIT(29), 0x1);
2525 }
2526 
phydm_ifs_clm_racing_release(void * dm_void)2527 void phydm_ifs_clm_racing_release(void *dm_void)
2528 {
2529 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2530 	struct ccx_info *ccx = &dm->dm_ccx_info;
2531 
2532 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2533 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm lv:(%d)->(0)\n",
2534 		  ccx->ifs_clm_set_lv);
2535 
2536 	ccx->ifs_clm_ongoing = false;
2537 	ccx->ifs_clm_set_lv = IFS_CLM_RELEASE;
2538 	ccx->ifs_clm_app = IFS_CLM_BACKGROUND;
2539 }
2540 
phydm_ifs_clm_racing_ctrl(void * dm_void,enum phydm_ifs_clm_level ifs_clm_lv)2541 u8 phydm_ifs_clm_racing_ctrl(void *dm_void, enum phydm_ifs_clm_level ifs_clm_lv)
2542 {
2543 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2544 	struct ccx_info *ccx = &dm->dm_ccx_info;
2545 	u8 set_result = PHYDM_SET_SUCCESS;
2546 	/*acquire to control IFS CLM API*/
2547 
2548 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm_ongoing=%d, lv:(%d)->(%d)\n",
2549 		  ccx->ifs_clm_ongoing, ccx->ifs_clm_set_lv, ifs_clm_lv);
2550 	if (ccx->ifs_clm_ongoing) {
2551 		if (ifs_clm_lv <= ccx->ifs_clm_set_lv) {
2552 			set_result = PHYDM_SET_FAIL;
2553 		} else {
2554 			phydm_ifs_clm_restart(dm);
2555 			ccx->ifs_clm_ongoing = false;
2556 		}
2557 	}
2558 
2559 	if (set_result)
2560 		ccx->ifs_clm_set_lv = ifs_clm_lv;
2561 
2562 	PHYDM_DBG(dm, DBG_ENV_MNTR, "ifs clm racing success=%d\n", set_result);
2563 	return set_result;
2564 }
2565 
phydm_ifs_clm_trigger(void * dm_void)2566 void phydm_ifs_clm_trigger(void *dm_void)
2567 {
2568 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2569 	struct ccx_info *ccx = &dm->dm_ccx_info;
2570 
2571 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2572 
2573 	/*Trigger IFS_CLM*/
2574 	pdm_set_reg(dm, R_0x1ee4, BIT(29), 0);
2575 	pdm_set_reg(dm, R_0x1ee4, BIT(29), 1);
2576 	ccx->ifs_clm_trigger_time = dm->phydm_sys_up_time;
2577 	ccx->ifs_clm_rpt_stamp++;
2578 	ccx->ifs_clm_ongoing = true;
2579 }
2580 
phydm_ifs_clm_get_utility(void * dm_void)2581 void phydm_ifs_clm_get_utility(void *dm_void)
2582 {
2583 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2584 	struct ccx_info *ccx = &dm->dm_ccx_info;
2585 	u16 denom = 0;
2586 
2587 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2588 
2589 	denom = ccx->ifs_clm_period;
2590 	ccx->ifs_clm_tx_ratio = phydm_ccx_get_rpt_ratio(dm, ccx->ifs_clm_tx,
2591 				denom);
2592 	ccx->ifs_clm_edcca_excl_cca_ratio = phydm_ccx_get_rpt_ratio(dm,
2593 					    ccx->ifs_clm_edcca_excl_cca,
2594 					    denom);
2595 	ccx->ifs_clm_cck_fa_ratio = phydm_ccx_get_rpt_ratio(dm,
2596 				    ccx->ifs_clm_cckfa, denom);
2597 	ccx->ifs_clm_ofdm_fa_ratio = phydm_ccx_get_rpt_ratio(dm,
2598 				     ccx->ifs_clm_ofdmfa, denom);
2599 	ccx->ifs_clm_cck_cca_excl_fa_ratio = phydm_ccx_get_rpt_ratio(dm,
2600 					     ccx->ifs_clm_cckcca_excl_fa,
2601 					     denom);
2602 	ccx->ifs_clm_ofdm_cca_excl_fa_ratio = phydm_ccx_get_rpt_ratio(dm,
2603 					      ccx->ifs_clm_ofdmcca_excl_fa,
2604 					      denom);
2605 
2606 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2607 		  "Tx_ratio = %d, EDCCA_exclude_CCA_ratio = %d \n",
2608 		  ccx->ifs_clm_tx_ratio, ccx->ifs_clm_edcca_excl_cca_ratio);
2609 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2610 		  "CCK : FA_ratio = %d, CCA_exclude_FA_ratio = %d \n",
2611 		  ccx->ifs_clm_cck_fa_ratio,
2612 		  ccx->ifs_clm_cck_cca_excl_fa_ratio);
2613 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2614 		  "OFDM : FA_ratio = %d, CCA_exclude_FA_ratio = %d \n",
2615 		  ccx->ifs_clm_ofdm_fa_ratio,
2616 		  ccx->ifs_clm_ofdm_cca_excl_fa_ratio);
2617 }
2618 
phydm_ifs_clm_get_result(void * dm_void)2619 void phydm_ifs_clm_get_result(void *dm_void)
2620 {
2621 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2622 	struct ccx_info *ccx = &dm->dm_ccx_info;
2623 	u32 value32 = 0;
2624 	u8 i = 0;
2625 
2626 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2627 
2628 	/*Enhance CLM result*/
2629 	value32 = odm_get_bb_reg(dm, R_0x2e60, MASKDWORD);
2630 	ccx->ifs_clm_tx = (u16)(value32 & MASKLWORD);
2631 	ccx->ifs_clm_edcca_excl_cca = (u16)((value32 & MASKHWORD) >> 16);
2632 	value32 = odm_get_bb_reg(dm, R_0x2e64, MASKDWORD);
2633 	ccx->ifs_clm_ofdmfa = (u16)(value32 & MASKLWORD);
2634 	ccx->ifs_clm_ofdmcca_excl_fa = (u16)((value32 & MASKHWORD) >> 16);
2635 	value32 = odm_get_bb_reg(dm, R_0x2e68, MASKDWORD);
2636 	ccx->ifs_clm_cckfa = (u16)(value32 & MASKLWORD);
2637 	ccx->ifs_clm_cckcca_excl_fa = (u16)((value32 & MASKHWORD) >> 16);
2638 	value32 = odm_get_bb_reg(dm, R_0x2e6c, MASKDWORD);
2639 	ccx->ifs_clm_total_cca = (u16)(value32 & MASKLWORD);
2640 
2641 	/* IFS result */
2642 	value32 = odm_get_bb_reg(dm, R_0x2e70, MASKDWORD);
2643 	odm_move_memory(dm, &ccx->ifs_clm_his[0], &value32, 4);
2644 	value32 = odm_get_bb_reg(dm, R_0x2e74, MASKDWORD);
2645 	ccx->ifs_clm_avg[0] = (u16)(value32 & MASKLWORD);
2646 	ccx->ifs_clm_avg[1] = (u16)((value32 & MASKHWORD) >> 16);
2647 	value32 = odm_get_bb_reg(dm, R_0x2e78, MASKDWORD);
2648 	ccx->ifs_clm_avg[2] = (u16)(value32 & MASKLWORD);
2649 	ccx->ifs_clm_avg[3] = (u16)((value32 & MASKHWORD) >> 16);
2650 	value32 = odm_get_bb_reg(dm, R_0x2e7c, MASKDWORD);
2651 	ccx->ifs_clm_avg_cca[0] = (u16)(value32 & MASKLWORD);
2652 	ccx->ifs_clm_avg_cca[1] = (u16)((value32 & MASKHWORD) >> 16);
2653 	value32 = odm_get_bb_reg(dm, R_0x2e80, MASKDWORD);
2654 	ccx->ifs_clm_avg_cca[2] = (u16)(value32 & MASKLWORD);
2655 	ccx->ifs_clm_avg_cca[3] = (u16)((value32 & MASKHWORD) >> 16);
2656 
2657 	/* Print Result */
2658 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2659 		  "ECLM_Rpt[%d]: \nTx = %d, EDCCA_exclude_CCA = %d \n",
2660 		  ccx->ifs_clm_rpt_stamp, ccx->ifs_clm_tx,
2661 		  ccx->ifs_clm_edcca_excl_cca);
2662 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2663 		  "[FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2664 		  ccx->ifs_clm_cckfa, ccx->ifs_clm_ofdmfa);
2665 	PHYDM_DBG(dm, DBG_ENV_MNTR,
2666 		  "[CCA_exclude_FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2667 		  ccx->ifs_clm_cckcca_excl_fa, ccx->ifs_clm_ofdmcca_excl_fa);
2668 	PHYDM_DBG(dm, DBG_ENV_MNTR, "CCATotal = %d\n", ccx->ifs_clm_total_cca);
2669 	PHYDM_DBG(dm, DBG_ENV_MNTR, "Time:[his, avg, avg_cca]\n");
2670 	for (i = 0; i < IFS_CLM_NUM; i++)
2671 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2672 			  "T%d:[%d, %d, %d]\n", i + 1,
2673 			  ccx->ifs_clm_his[i], ccx->ifs_clm_avg[i],
2674 			  ccx->ifs_clm_avg_cca[i]);
2675 
2676 	phydm_ifs_clm_racing_release(dm);
2677 
2678 	return;
2679 }
2680 
phydm_ifs_clm_set_th_reg(void * dm_void)2681 void phydm_ifs_clm_set_th_reg(void *dm_void)
2682 {
2683 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2684 	struct ccx_info *ccx = &dm->dm_ccx_info;
2685 	u8 i = 0;
2686 
2687 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2688 
2689 	/*Set IFS period TH*/
2690 	odm_set_bb_reg(dm, R_0x1ed4, BIT(31), ccx->ifs_clm_th_en[0]);
2691 	odm_set_bb_reg(dm, R_0x1ed8, BIT(31), ccx->ifs_clm_th_en[1]);
2692 	odm_set_bb_reg(dm, R_0x1edc, BIT(31), ccx->ifs_clm_th_en[2]);
2693 	odm_set_bb_reg(dm, R_0x1ee0, BIT(31), ccx->ifs_clm_th_en[3]);
2694 	odm_set_bb_reg(dm, R_0x1ed4, 0x7fff0000, ccx->ifs_clm_th_low[0]);
2695 	odm_set_bb_reg(dm, R_0x1ed8, 0x7fff0000, ccx->ifs_clm_th_low[1]);
2696 	odm_set_bb_reg(dm, R_0x1edc, 0x7fff0000, ccx->ifs_clm_th_low[2]);
2697 	odm_set_bb_reg(dm, R_0x1ee0, 0x7fff0000, ccx->ifs_clm_th_low[3]);
2698 	odm_set_bb_reg(dm, R_0x1ed4, MASKLWORD, ccx->ifs_clm_th_high[0]);
2699 	odm_set_bb_reg(dm, R_0x1ed8, MASKLWORD, ccx->ifs_clm_th_high[1]);
2700 	odm_set_bb_reg(dm, R_0x1edc, MASKLWORD, ccx->ifs_clm_th_high[2]);
2701 	odm_set_bb_reg(dm, R_0x1ee0, MASKLWORD, ccx->ifs_clm_th_high[3]);
2702 
2703 	for (i = 0; i < IFS_CLM_NUM; i++)
2704 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2705 			  "Update IFS_CLM_th%d[High Low] : [%d %d]\n", i + 1,
2706 		  	  ccx->ifs_clm_th_high[i], ccx->ifs_clm_th_low[i]);
2707 }
2708 
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)2709 boolean phydm_ifs_clm_th_update_chk(void *dm_void,
2710 				    enum ifs_clm_application ifs_clm_app,
2711 				    boolean *ifs_clm_th_en, u16 *ifs_clm_th_low,
2712 				    u16 *ifs_clm_th_high, s16 th_shift)
2713 {
2714 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2715 	struct ccx_info *ccx = &dm->dm_ccx_info;
2716 	boolean is_update = false;
2717 	u16 ifs_clm_th_low_bg[IFS_CLM_NUM] = {12, 5, 2, 0};
2718 	u16 ifs_clm_th_high_bg[IFS_CLM_NUM] = {64, 12, 5, 2};
2719 	u8 i = 0;
2720 
2721 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2722 	PHYDM_DBG(dm, DBG_ENV_MNTR, "App=%d, th_shift=%d\n", ifs_clm_app,
2723 		  th_shift);
2724 
2725 	switch (ifs_clm_app) {
2726 	case IFS_CLM_BACKGROUND:
2727 	case IFS_CLM_ACS:
2728 	case IFS_CLM_HP_TAS:
2729 		if (ccx->ifs_clm_app != ifs_clm_app || th_shift != 0) {
2730 			is_update = true;
2731 
2732 			for (i = 0; i < IFS_CLM_NUM; i++) {
2733 				ifs_clm_th_en[i] = true;
2734 				ifs_clm_th_low[i] = ifs_clm_th_low_bg[i];
2735 				ifs_clm_th_high[i] = ifs_clm_th_high_bg[i];
2736 			}
2737 		}
2738 		break;
2739 	case IFS_CLM_DBG:
2740 		if (ccx->ifs_clm_app != ifs_clm_app || th_shift != 0) {
2741 			is_update = true;
2742 
2743 			for (i = 0; i < IFS_CLM_NUM; i++) {
2744 				ifs_clm_th_en[i] = true;
2745 				ifs_clm_th_low[i] = MAX_2(ccx->ifs_clm_th_low[i] +
2746 						    th_shift, 0);
2747 				ifs_clm_th_high[i] = MAX_2(ccx->ifs_clm_th_high[i] +
2748 						     th_shift, 0);
2749 			}
2750 		}
2751 		break;
2752 	default:
2753 		break;
2754 	}
2755 
2756 	if (is_update)
2757 		PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update IFS_TH]\n");
2758 	else
2759 		PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update IFS_TH\n");
2760 
2761 	return is_update;
2762 }
2763 
phydm_ifs_clm_set(void * dm_void,enum ifs_clm_application ifs_clm_app,u16 period,u8 ctrl_unit,s16 th_shift)2764 void phydm_ifs_clm_set(void *dm_void, enum ifs_clm_application ifs_clm_app,
2765 		       u16 period, u8 ctrl_unit, s16 th_shift)
2766 {
2767 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2768 	struct ccx_info *ccx = &dm->dm_ccx_info;
2769 	boolean ifs_clm_th_en[IFS_CLM_NUM] =  {0};
2770 	u16 ifs_clm_th_low[IFS_CLM_NUM] =  {0};
2771 	u16 ifs_clm_th_high[IFS_CLM_NUM] =  {0};
2772 
2773 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2774 	PHYDM_DBG(dm, DBG_ENV_MNTR, "period=%d, ctrl_unit=%d\n", period,
2775 		  ctrl_unit);
2776 
2777 	/*Set Unit*/
2778 	if (ctrl_unit != ccx->ifs_clm_ctrl_unit) {
2779 		odm_set_bb_reg(dm, R_0x1ee4, 0xc0000000, ctrl_unit);
2780 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2781 			  "Update IFS_CLM unit ((%d)) -> ((%d))\n",
2782 			  ccx->ifs_clm_ctrl_unit, ctrl_unit);
2783 		ccx->ifs_clm_ctrl_unit = ctrl_unit;
2784 	}
2785 
2786 	/*Set Duration*/
2787 	if (period != ccx->ifs_clm_period) {
2788 		odm_set_bb_reg(dm, R_0x1eec, 0xc0000000, (period & 0x3));
2789 		odm_set_bb_reg(dm, R_0x1ef0, 0xfe000000, ((period >> 2) &
2790 			       0x7f));
2791 		odm_set_bb_reg(dm, R_0x1ef4, 0xc0000000, ((period >> 9) &
2792 			       0x3));
2793 		odm_set_bb_reg(dm, R_0x1ef8, 0x3e000000, ((period >> 11) &
2794 			       0x1f));
2795 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2796 			  "Update IFS_CLM period ((%d)) -> ((%d))\n",
2797 			  ccx->ifs_clm_period, period);
2798 		ccx->ifs_clm_period = period;
2799 	}
2800 
2801 	/*Set IFS CLM threshold*/
2802 	if (phydm_ifs_clm_th_update_chk(dm, ifs_clm_app, &ifs_clm_th_en[0],
2803 					&ifs_clm_th_low[0], &ifs_clm_th_high[0],
2804 					th_shift)) {
2805 
2806 		ccx->ifs_clm_app = ifs_clm_app;
2807 		odm_move_memory(dm, &ccx->ifs_clm_th_en[0], &ifs_clm_th_en,
2808 				IFS_CLM_NUM);
2809 		odm_move_memory(dm, &ccx->ifs_clm_th_low[0], &ifs_clm_th_low,
2810 				IFS_CLM_NUM);
2811 		odm_move_memory(dm, &ccx->ifs_clm_th_high[0], &ifs_clm_th_high,
2812 				IFS_CLM_NUM);
2813 
2814 		phydm_ifs_clm_set_th_reg(dm);
2815 	}
2816 }
2817 
2818 boolean
phydm_ifs_clm_mntr_set(void * dm_void,struct ifs_clm_para_info * ifs_clm_para)2819 phydm_ifs_clm_mntr_set(void *dm_void, struct ifs_clm_para_info *ifs_clm_para)
2820 {
2821 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2822 	u16 ifs_clm_time = 0; /*unit: 4/8/12/16us*/
2823 	u8 unit = 0;
2824 
2825 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2826 
2827 	if (ifs_clm_para->mntr_time == 0)
2828 		return false;
2829 
2830 	if (ifs_clm_para->ifs_clm_lv >= IFS_CLM_MAX_NUM) {
2831 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n",
2832 			  ifs_clm_para->ifs_clm_lv);
2833 		return false;
2834 	}
2835 
2836 	if (phydm_ifs_clm_racing_ctrl(dm, ifs_clm_para->ifs_clm_lv) == PHYDM_SET_FAIL)
2837 		return false;
2838 
2839 	if (ifs_clm_para->mntr_time >= 1048) {
2840 		unit = IFS_CLM_16;
2841 		ifs_clm_time = IFS_CLM_PERIOD_MAX; /*65535 * 16us = 1048ms*/
2842 	} else if (ifs_clm_para->mntr_time >= 786) {/*65535 * 12us = 786 ms*/
2843 		unit = IFS_CLM_16;
2844 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 16);
2845 	} else if (ifs_clm_para->mntr_time >= 524) {
2846 		unit = IFS_CLM_12;
2847 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 12);
2848 	} else if (ifs_clm_para->mntr_time >= 262) {
2849 		unit = IFS_CLM_8;
2850 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 8);
2851 	} else {
2852 		unit = IFS_CLM_4;
2853 		ifs_clm_time = PHYDM_DIV(ifs_clm_para->mntr_time * MS_TO_US, 4);
2854 	}
2855 
2856 	phydm_ifs_clm_set(dm, ifs_clm_para->ifs_clm_app, ifs_clm_time, unit,
2857 			  ifs_clm_para->th_shift);
2858 
2859 	return true;
2860 }
2861 
2862 boolean
phydm_ifs_clm_mntr_racing_chk(void * dm_void)2863 phydm_ifs_clm_mntr_racing_chk(void *dm_void)
2864 {
2865 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2866 	struct ccx_info *ccx = &dm->dm_ccx_info;
2867 	u32 sys_return_time = 0;
2868 
2869 	if (ccx->ifs_clm_manual_ctrl) {
2870 		PHYDM_DBG(dm, DBG_ENV_MNTR, "IFS_CLM in manual ctrl\n");
2871 		return true;
2872 	}
2873 
2874 	sys_return_time = ccx->ifs_clm_trigger_time + MAX_ENV_MNTR_TIME;
2875 
2876 	if (ccx->ifs_clm_app != IFS_CLM_BACKGROUND &&
2877 	    (sys_return_time > dm->phydm_sys_up_time)) {
2878 		PHYDM_DBG(dm, DBG_ENV_MNTR,
2879 			  "ifs_clm_app=%d, trigger_time %d, sys_time=%d\n",
2880 			  ccx->ifs_clm_app, ccx->ifs_clm_trigger_time,
2881 			  dm->phydm_sys_up_time);
2882 
2883 		return true;
2884 	}
2885 
2886 	return false;
2887 }
2888 
2889 boolean
phydm_ifs_clm_mntr_chk(void * dm_void,u16 monitor_time)2890 phydm_ifs_clm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
2891 {
2892 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2893 	struct ccx_info *ccx = &dm->dm_ccx_info;
2894 	struct ifs_clm_para_info ifs_clm_para = {0};
2895 	boolean ifs_clm_chk_result = false;
2896 
2897 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2898 
2899 	if (phydm_ifs_clm_mntr_racing_chk(dm))
2900 		return ifs_clm_chk_result;
2901 
2902 	/*[IFS CLM trigger setting]------------------------------------------*/
2903 	ifs_clm_para.ifs_clm_app = IFS_CLM_BACKGROUND;
2904 	ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_1;
2905 	ifs_clm_para.mntr_time = monitor_time;
2906 	ifs_clm_para.th_shift = 0;
2907 
2908 	ifs_clm_chk_result = phydm_ifs_clm_mntr_set(dm, &ifs_clm_para);
2909 
2910 	return ifs_clm_chk_result;
2911 }
2912 
2913 boolean
phydm_ifs_clm_mntr_result(void * dm_void)2914 phydm_ifs_clm_mntr_result(void *dm_void)
2915 {
2916 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2917 	struct ccx_info *ccx = &dm->dm_ccx_info;
2918 	boolean ifs_clm_chk_result = false;
2919 
2920 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2921 
2922 	if (phydm_ifs_clm_mntr_racing_chk(dm))
2923 		return ifs_clm_chk_result;
2924 
2925 	/*[IFS CLM get result] ------------------------------------]*/
2926 	phydm_ifs_clm_get_result(dm);
2927 	phydm_ifs_clm_get_utility(dm);
2928 	ifs_clm_chk_result = true;
2929 
2930 	return ifs_clm_chk_result;
2931 }
2932 
phydm_ifs_clm_init(void * dm_void)2933 void phydm_ifs_clm_init(void *dm_void)
2934 {
2935 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2936 	struct ccx_info *ccx = &dm->dm_ccx_info;
2937 
2938 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
2939 
2940 	ccx->ifs_clm_app = IFS_CLM_BACKGROUND;
2941 
2942 	/*Set IFS threshold*/
2943 	ccx->ifs_clm_ongoing = false;
2944 	ccx->ifs_clm_set_lv = IFS_CLM_RELEASE;
2945 
2946 	if (phydm_ifs_clm_th_update_chk(dm, ccx->ifs_clm_app,
2947 					&ccx->ifs_clm_th_en[0],
2948 					&ccx->ifs_clm_th_low[0],
2949 					&ccx->ifs_clm_th_high[0], 0xffff))
2950 		phydm_ifs_clm_set_th_reg(dm);
2951 
2952 	ccx->ifs_clm_period = 0;
2953 	ccx->ifs_clm_ctrl_unit = IFS_CLM_INIT;
2954 	ccx->ifs_clm_manual_ctrl = 0;
2955 	ccx->ifs_clm_rpt_stamp = 0;
2956 }
2957 
phydm_ifs_clm_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)2958 void phydm_ifs_clm_dbg(void *dm_void, char input[][16], u32 *_used,
2959 		       char *output, u32 *_out_len)
2960 {
2961 	struct dm_struct *dm = (struct dm_struct *)dm_void;
2962 	struct ccx_info *ccx = &dm->dm_ccx_info;
2963 	struct ifs_clm_para_info ifs_clm_para;
2964 	char help[] = "-h";
2965 	u32 var1[10] = {0};
2966 	u32 used = *_used;
2967 	u32 out_len = *_out_len;
2968 	u8 result_tmp = 0;
2969 	u8 i = 0;
2970 	u16 th_shift = 0;
2971 
2972 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM))
2973 		return;
2974 
2975 	for (i = 0; i < 5; i++) {
2976 		if (input[i + 1])
2977 			PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
2978 				     &var1[i]);
2979 	}
2980 
2981 	if ((strcmp(input[1], help) == 0)) {
2982 		PDM_SNPF(out_len, used, output + used, out_len - used,
2983 			 "IFS_CLM Basic-Trigger 960ms: {1}\n");
2984 		PDM_SNPF(out_len, used, output + used, out_len - used,
2985 			 "IFS_CLM Adv-Trigger: {2} {App:3 for dbg} {LV:1~4} {0~2096ms} {th_shift}\n");
2986 		PDM_SNPF(out_len, used, output + used, out_len - used,
2987 			 "IFS_CLM Get Result: {100}\n");
2988 	} else if (var1[0] == 100) { /*Get IFS_CLM results*/
2989 		phydm_ifs_clm_get_result(dm);
2990 
2991 		PDM_SNPF(out_len, used, output + used, out_len - used,
2992 			  "ECLM_Rpt[%d]: \nTx = %d \nEDCCA_exclude_CCA = %d\n",
2993 			  ccx->ifs_clm_rpt_stamp, ccx->ifs_clm_tx,
2994 			  ccx->ifs_clm_edcca_excl_cca);
2995 		PDM_SNPF(out_len, used, output + used, out_len - used,
2996 			  "[FA_cnt] {CCK, OFDM} = {%d, %d}\n",
2997 			  ccx->ifs_clm_cckfa, ccx->ifs_clm_ofdmfa);
2998 		PDM_SNPF(out_len, used, output + used, out_len - used,
2999 			  "[CCA_exclude_FA_cnt] {CCK, OFDM} = {%d, %d}\n",
3000 			  ccx->ifs_clm_cckcca_excl_fa,
3001 			  ccx->ifs_clm_ofdmcca_excl_fa);
3002 		PDM_SNPF(out_len, used, output + used, out_len - used,
3003 			 "CCATotal = %d\n", ccx->ifs_clm_total_cca);
3004 		PDM_SNPF(out_len, used, output + used, out_len - used,
3005 			 "Time:[his, avg, avg_cca]\n");
3006 		for (i = 0; i < IFS_CLM_NUM; i++)
3007 			PDM_SNPF(out_len, used, output + used, out_len - used,
3008 				  "T%d:[%d, %d, %d]\n", i + 1,
3009 				  ccx->ifs_clm_his[i], ccx->ifs_clm_avg[i],
3010 				  ccx->ifs_clm_avg_cca[i]);
3011 
3012 		phydm_ifs_clm_get_utility(dm);
3013 
3014 		ccx->ifs_clm_manual_ctrl = 0;
3015 	} else { /*IFS_CLM trigger*/
3016 		ccx->ifs_clm_manual_ctrl = 1;
3017 
3018 		if (var1[0] == 1) {
3019 			ifs_clm_para.ifs_clm_app = IFS_CLM_DBG;
3020 			ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_4;
3021 			ifs_clm_para.mntr_time = 960;
3022 			ifs_clm_para.th_shift = 0;
3023 		} else {
3024 			ifs_clm_para.ifs_clm_app = (enum ifs_clm_application)var1[1];
3025 			ifs_clm_para.ifs_clm_lv = (enum phydm_ifs_clm_level)var1[2];
3026 			ifs_clm_para.mntr_time = (u16)var1[3];
3027 			ifs_clm_para.th_shift = (s16)var1[4];
3028 		}
3029 
3030 		PDM_SNPF(out_len, used, output + used, out_len - used,
3031 			 "app=%d, lv=%d, time=%d ms, th_shift=%s%d\n",
3032 			 ifs_clm_para.ifs_clm_app, ifs_clm_para.ifs_clm_lv,
3033 			 ifs_clm_para.mntr_time,
3034 			 (ifs_clm_para.th_shift > 0) ? "+" : "-",
3035 			 ifs_clm_para.th_shift);
3036 
3037 		if (phydm_ifs_clm_mntr_set(dm, &ifs_clm_para) == PHYDM_SET_SUCCESS)
3038 			phydm_ifs_clm_trigger(dm);
3039 
3040 		PDM_SNPF(out_len, used, output + used, out_len - used,
3041 			 "rpt_stamp=%d\n", ccx->ifs_clm_rpt_stamp);
3042 		for (i = 0; i < IFS_CLM_NUM; i++)
3043 			PDM_SNPF(out_len, used, output + used, out_len - used,
3044 				  "IFS_CLM_th%d[High Low] : [%d %d]\n", i + 1,
3045 			  	  ccx->ifs_clm_th_high[i],
3046 			  	  ccx->ifs_clm_th_low[i]);
3047 	}
3048 
3049 	*_used = used;
3050 	*_out_len = out_len;
3051 }
3052 #endif
3053 
phydm_enhance_mntr_trigger(void * dm_void,struct nhm_para_info * nhm_para,struct clm_para_info * clm_para,struct fahm_para_info * fahm_para,struct ifs_clm_para_info * ifs_clm_para,struct enhance_mntr_trig_rpt * trig_rpt)3054 u8 phydm_enhance_mntr_trigger(void *dm_void, struct nhm_para_info *nhm_para,
3055 			     struct clm_para_info *clm_para,
3056 			     struct fahm_para_info *fahm_para,
3057 			     struct ifs_clm_para_info *ifs_clm_para,
3058 			     struct enhance_mntr_trig_rpt *trig_rpt)
3059 {
3060 	u8 trigger_result = 0;
3061 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT) && defined(FAHM_SUPPORT) && defined(IFS_CLM_SUPPORT))
3062 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3063 	struct ccx_info *ccx = &dm->dm_ccx_info;
3064 	boolean nhm_set_ok = false;
3065 	boolean clm_set_ok = false;
3066 	boolean fahm_set_ok = false;
3067 	boolean ifs_clm_set_ok = false;
3068 
3069 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM) ||
3070 	    !(dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM))
3071 		return trigger_result;
3072 
3073 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
3074 
3075 	nhm_set_ok = phydm_nhm_mntr_set(dm, nhm_para);
3076 
3077 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
3078 		clm_set_ok = phydm_clm_mntr_set(dm, clm_para);
3079 	} else if (ccx->clm_mntr_mode == CLM_FW_MNTR) {
3080 		phydm_clm_h2c(dm, CLM_PERIOD_MAX, true);
3081 		trigger_result |= CLM_SUCCESS;
3082 	}
3083 
3084 	fahm_set_ok = phydm_fahm_mntr_set(dm, fahm_para);
3085 
3086 	ifs_clm_set_ok = phydm_ifs_clm_mntr_set(dm, ifs_clm_para);
3087 
3088 	if (nhm_set_ok) {
3089 		phydm_nhm_trigger(dm);
3090 		trigger_result |= NHM_SUCCESS;
3091 	}
3092 
3093 	if (clm_set_ok) {
3094 		phydm_clm_trigger(dm);
3095 		trigger_result |= CLM_SUCCESS;
3096 	}
3097 
3098 	if (fahm_set_ok) {
3099 		phydm_fahm_trigger(dm);
3100 		trigger_result |= FAHM_SUCCESS;
3101 	}
3102 
3103 	if (ifs_clm_set_ok) {
3104 		phydm_ifs_clm_trigger(dm);
3105 		trigger_result |= IFS_CLM_SUCCESS;
3106 	}
3107 
3108 	/*monitor for the test duration*/
3109 	ccx->start_time = odm_get_current_time(dm);
3110 
3111 	trig_rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
3112 	trig_rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
3113 	trig_rpt->fahm_rpt_stamp = ccx->fahm_rpt_stamp;
3114 	trig_rpt->ifs_clm_rpt_stamp = ccx->ifs_clm_rpt_stamp;
3115 
3116 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3117 		  "rpt_stamp{NHM, CLM, FAHM, IFS_CLM}={%d, %d, %d, %d}\n\n",
3118 		  trig_rpt->nhm_rpt_stamp, trig_rpt->clm_rpt_stamp,
3119 		  trig_rpt->fahm_rpt_stamp, trig_rpt->ifs_clm_rpt_stamp);
3120 
3121 #endif
3122 	return trigger_result;
3123 }
3124 
phydm_enhance_mntr_result(void * dm_void,struct enhance_mntr_rpt * rpt)3125 u8 phydm_enhance_mntr_result(void *dm_void, struct enhance_mntr_rpt *rpt)
3126 {
3127 	u8 enhance_mntr_rpt = 0;
3128 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT) && defined(FAHM_SUPPORT) && defined(IFS_CLM_SUPPORT))
3129 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3130 	struct ccx_info *ccx = &dm->dm_ccx_info;
3131 	u64 progressing_time = 0;
3132 	u32 val_tmp = 0;
3133 
3134 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM) ||
3135 	    !(dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM))
3136 		return enhance_mntr_rpt;
3137 
3138 	/*monitor for the test duration*/
3139 	progressing_time = odm_get_progressing_time(dm, ccx->start_time);
3140 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
3141 	PHYDM_DBG(dm, DBG_ENV_MNTR, "enhance_mntr_time=%lld\n",
3142 		  progressing_time);
3143 
3144 	/*Get NHM result*/
3145 	if (phydm_nhm_get_result(dm)) {
3146 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
3147 		phydm_nhm_get_utility(dm);
3148 		rpt->nhm_ratio = ccx->nhm_ratio;
3149 		rpt->nhm_env_ratio = ccx->nhm_env_ratio;
3150 		rpt->nhm_noise_pwr = ccx->nhm_level;
3151 		rpt->nhm_pwr = ccx->nhm_pwr;
3152 		enhance_mntr_rpt |= NHM_SUCCESS;
3153 
3154 		odm_move_memory(dm, &rpt->nhm_result[0],
3155 				&ccx->nhm_result[0], NHM_RPT_NUM);
3156 	} else {
3157 		rpt->nhm_ratio = ENV_MNTR_FAIL;
3158 		rpt->nhm_env_ratio = ENV_MNTR_FAIL;
3159 	}
3160 
3161 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3162 		  "[NHM]rpt_stamp=%d, IGI=0x%x, ratio=%d, env_ratio=%d, noise_pwr=%d, pwr=%d\n",
3163 		  rpt->nhm_rpt_stamp, ccx->nhm_igi, rpt->nhm_ratio,
3164 		  rpt->nhm_env_ratio, rpt->nhm_noise_pwr, rpt->nhm_pwr);
3165 
3166 	/*Get CLM result*/
3167 	if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
3168 		if (phydm_clm_get_result(dm)) {
3169 			PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
3170 			phydm_clm_get_utility(dm);
3171 			enhance_mntr_rpt |= CLM_SUCCESS;
3172 			rpt->clm_ratio = ccx->clm_ratio;
3173 		} else {
3174 			rpt->clm_ratio = ENV_MNTR_FAIL;
3175 		}
3176 	} else {
3177 		if (ccx->clm_fw_result_cnt != 0) {
3178 			val_tmp = ccx->clm_fw_result_acc
3179 			/ ccx->clm_fw_result_cnt;
3180 			ccx->clm_ratio = (u8)val_tmp;
3181 		} else {
3182 			ccx->clm_ratio = 0;
3183 		}
3184 		rpt->clm_ratio = ccx->clm_ratio;
3185 		PHYDM_DBG(dm, DBG_ENV_MNTR,
3186 			  "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
3187 			  ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
3188 
3189 		ccx->clm_fw_result_acc = 0;
3190 		ccx->clm_fw_result_cnt = 0;
3191 		enhance_mntr_rpt |= CLM_SUCCESS;
3192 	}
3193 
3194 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[CLM]rpt_stamp=%d, ratio=%d\n",
3195 		  rpt->clm_rpt_stamp, rpt->clm_ratio);
3196 
3197 	/*Get FAHM result*/
3198 	if (phydm_fahm_get_result(dm)) {
3199 		PHYDM_DBG(dm, DBG_ENV_MNTR, "Get FAHM_rpt success\n");
3200 		phydm_fahm_get_utility(dm);
3201 		rpt->fahm_pwr = ccx->fahm_pwr;
3202 		rpt->fahm_ratio = ccx->fahm_ratio;
3203 		rpt->fahm_denom_ratio = ccx->fahm_denom_ratio;
3204 		rpt->fahm_inclu_cck = ccx->fahm_inclu_cck;
3205 		enhance_mntr_rpt |= FAHM_SUCCESS;
3206 
3207 		odm_move_memory(dm, &rpt->fahm_result[0],
3208 				&ccx->fahm_result[0], FAHM_RPT_NUM * 2);
3209 	} else {
3210 		rpt->fahm_pwr = 0;
3211 		rpt->fahm_ratio = 0;
3212 		rpt->fahm_denom_ratio = 0;
3213 	}
3214 
3215 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3216 		  "[FAHM]stamp=%d, IGI=0x%x, fahm_inclu_cck=%d, fahm_pwr=%d, fahm_ratio=%d, fahm_denom_ratio=%d\n",
3217 		  rpt->fahm_rpt_stamp, ccx->fahm_igi, rpt->fahm_inclu_cck,
3218 		  rpt->fahm_pwr, rpt->fahm_ratio, rpt->fahm_denom_ratio);
3219 
3220 	/*Get IFS_CLM result*/
3221 	phydm_ifs_clm_get_result(dm);
3222 	phydm_ifs_clm_get_utility(dm);
3223 	rpt->ifs_clm_tx_ratio = ccx->ifs_clm_tx_ratio;
3224 	rpt->ifs_clm_edcca_excl_cca_ratio = ccx->ifs_clm_edcca_excl_cca_ratio;
3225 	rpt->ifs_clm_cck_fa_ratio = ccx->ifs_clm_cck_fa_ratio;
3226 	rpt->ifs_clm_cck_cca_excl_fa_ratio = ccx->ifs_clm_cck_cca_excl_fa_ratio;
3227 	rpt->ifs_clm_ofdm_fa_ratio = ccx->ifs_clm_ofdm_fa_ratio;
3228 	rpt->ifs_clm_ofdm_cca_excl_fa_ratio = ccx->ifs_clm_ofdm_cca_excl_fa_ratio;
3229 	rpt->ifs_clm_rpt_stamp = ccx->ifs_clm_rpt_stamp;
3230 	enhance_mntr_rpt |= IFS_CLM_SUCCESS;
3231 
3232 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3233 		  "[IFS_CLM]rpt_stamp = %d, Tx_ratio = %d, EDCCA_exclude_CCA_ratio = %d\n",
3234 		  ccx->ifs_clm_rpt_stamp, ccx->ifs_clm_tx_ratio,
3235 		  ccx->ifs_clm_edcca_excl_cca_ratio);
3236 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3237 		  "CCK : FA_ratio = %d, CCA_exclude_FA_ratio = %d\n",
3238 		  ccx->ifs_clm_cck_fa_ratio, ccx->ifs_clm_cck_cca_excl_fa_ratio);
3239 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3240 		  "OFDM : FA_ratio = %d, CCA_exclude_FA_ratio = %d\n",
3241 		  ccx->ifs_clm_ofdm_fa_ratio,
3242 		  ccx->ifs_clm_ofdm_cca_excl_fa_ratio);
3243 
3244 	rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
3245 	rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
3246 	rpt->fahm_rpt_stamp = ccx->fahm_rpt_stamp;
3247 	rpt->ifs_clm_rpt_stamp = ccx->ifs_clm_rpt_stamp;
3248 #endif
3249 	return enhance_mntr_rpt;
3250 }
3251 
phydm_enhance_mntr_dbg(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)3252 void phydm_enhance_mntr_dbg(void *dm_void, char input[][16], u32 *_used,
3253 			    char *output, u32 *_out_len)
3254 {
3255 #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT) && defined(FAHM_SUPPORT) && defined(IFS_CLM_SUPPORT))
3256 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3257 	char help[] = "-h";
3258 	u32 var1[10] = {0};
3259 	u32 used = *_used;
3260 	u32 out_len = *_out_len;
3261 	struct nhm_para_info nhm_para = {0};
3262 	struct clm_para_info clm_para = {0};
3263 	struct fahm_para_info fahm_para = {0};
3264 	struct ifs_clm_para_info ifs_clm_para = {0};
3265 	struct enhance_mntr_rpt rpt = {0};
3266 	struct enhance_mntr_trig_rpt trig_rpt = {0};
3267 	struct ccx_info *ccx = &dm->dm_ccx_info;
3268 	u8 set_result = 0;
3269 	u8 i = 0;
3270 
3271 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM) ||
3272 	    !(dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM))
3273 		return;
3274 
3275 	PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
3276 
3277 	if ((strcmp(input[1], help) == 0)) {
3278 		PDM_SNPF(out_len, used, output + used, out_len - used,
3279 			 "Basic-Trigger 960ms for ifs_clm, 262ms for others: {1}\n");
3280 		PDM_SNPF(out_len, used, output + used, out_len - used,
3281 			 "Get Result: {100}\n");
3282 	} else if (var1[0] == 100) { /* Get results */
3283 		set_result = phydm_enhance_mntr_result(dm, &rpt);
3284 
3285 		PDM_SNPF(out_len, used, output + used, out_len - used,
3286 			 "Set Result=%d, rpt_stamp{NHM, CLM, FAHM, IFS_CLM}={%d, %d, %d, %d}\n",
3287 			 set_result, rpt.nhm_rpt_stamp, rpt.clm_rpt_stamp,
3288 			 rpt.fahm_rpt_stamp, rpt.ifs_clm_rpt_stamp);
3289 		PDM_SNPF(out_len, used, output + used, out_len - used,
3290 			 "clm_ratio=%d\n", rpt.clm_ratio);
3291 
3292 		for (i = 0; i < NHM_RPT_NUM; i++) {
3293 			PDM_SNPF(out_len, used, output + used, out_len - used,
3294 				 "nhm_rpt[%d] = %d (%d percent)\n", i,
3295 				 rpt.nhm_result[i],
3296 				 (((rpt.nhm_result[i] * 100) + 128) >> 8));
3297 		}
3298 
3299 		PDM_SNPF(out_len, used, output + used, out_len - used,
3300 			 "nhm_IGI=0x%x, nhm_ratio=%d, nhm_env_ratio=%d, nhm_noise_pwr=%d, nhm_pwr=%d\n",
3301 			 ccx->nhm_igi, rpt.nhm_ratio, rpt.nhm_env_ratio,
3302 			 rpt.nhm_noise_pwr, rpt.nhm_pwr);
3303 
3304 		if (!(rpt.fahm_inclu_cck))
3305 			PDM_SNPF(out_len, used, output + used,
3306 				 out_len - used,
3307 				 "===>The following fahm report does not count CCK pkt\n");
3308 
3309 		for (i = 0; i < FAHM_RPT_NUM; i++) {
3310 			PDM_SNPF(out_len, used, output + used, out_len - used,
3311 				 "fahm_rpt[%d] = %d (%d percent)\n", i,
3312 				 rpt.fahm_result[i],
3313 				 (((rpt.fahm_result[i] * 100) + 32768) >> 16));
3314 		}
3315 
3316 		PDM_SNPF(out_len, used, output + used, out_len - used,
3317 			 "fahm_IGI=0x%x, fahm_pwr=%d, fahm_ratio=%d, fahm_denom_ratio=%d\n",
3318 			 ccx->fahm_igi, rpt.fahm_pwr, rpt.fahm_ratio,
3319 			 rpt.fahm_denom_ratio);
3320 		PDM_SNPF(out_len, used, output + used, out_len - used,
3321 			 "ifs_clm_Tx_ratio = %d, ifs_clm_EDCCA_exclude_CCA_ratio = %d \n",
3322 			 rpt.ifs_clm_tx_ratio,
3323 			 rpt.ifs_clm_edcca_excl_cca_ratio);
3324 		PDM_SNPF(out_len, used, output + used, out_len - used,
3325 			 "ifs_clm_cck_fa_ratio = %d, ifs_clm_cck_cca_exclude_FA_ratio = %d \n",
3326 			 rpt.ifs_clm_cck_fa_ratio,
3327 			 rpt.ifs_clm_cck_cca_excl_fa_ratio);
3328 		PDM_SNPF(out_len, used, output + used, out_len - used,
3329 			 "ifs_clm_ofdm_fa_ratio = %d, ifs_clm_ofdm_cca_exclude_FA_ratio = %d \n",
3330 			 rpt.ifs_clm_ofdm_fa_ratio,
3331 			 rpt.ifs_clm_ofdm_cca_excl_fa_ratio);
3332 	} else { /* Set & trigger*/
3333 		/*nhm para*/
3334 		nhm_para.incld_txon = NHM_EXCLUDE_TXON;
3335 		nhm_para.incld_cca = NHM_EXCLUDE_CCA;
3336 		nhm_para.div_opt = NHM_CNT_ALL;
3337 		nhm_para.nhm_app = NHM_ACS;
3338 		nhm_para.nhm_lv = NHM_LV_2;
3339 		nhm_para.mntr_time = 262;
3340 		nhm_para.en_1db_mode = false;
3341 
3342 		/*clm para*/
3343 		clm_para.clm_app = CLM_ACS;
3344 		clm_para.clm_lv = CLM_LV_2;
3345 		clm_para.mntr_time = 262;
3346 
3347 		/*fahm para*/
3348 		fahm_para.numer_opt = FAHM_INCLU_FA;
3349 		fahm_para.denom_opt = FAHM_INCLU_CRC_ERR;
3350 		fahm_para.app = FAHM_ACS;
3351 		fahm_para.lv = FAHM_LV_2;
3352 		fahm_para.mntr_time = 262;
3353 		fahm_para.en_1db_mode = false;
3354 
3355 		ifs_clm_para.ifs_clm_app = IFS_CLM_ACS;
3356 		ifs_clm_para.ifs_clm_lv = IFS_CLM_LV_2;
3357 		ifs_clm_para.mntr_time = 960;
3358 		ifs_clm_para.th_shift = 0;
3359 
3360 		set_result = phydm_enhance_mntr_trigger(dm, &nhm_para,
3361 							&clm_para, &fahm_para,
3362 							&ifs_clm_para,
3363 							&trig_rpt);
3364 
3365 		PDM_SNPF(out_len, used, output + used, out_len - used,
3366 			 "Set Result=%d, rpt_stamp{NHM, CLM, FAHM, IFS_CLM}={%d, %d ,%d, %d}\n",
3367 			 set_result, trig_rpt.nhm_rpt_stamp,
3368 			 trig_rpt.clm_rpt_stamp, trig_rpt.fahm_rpt_stamp,
3369 			 trig_rpt.ifs_clm_rpt_stamp);
3370 	}
3371 	*_used = used;
3372 	*_out_len = out_len;
3373 #endif
3374 }
3375 
3376 /*Environment Monitor*/
phydm_env_mntr_result_watchdog(void * dm_void)3377 void phydm_env_mntr_result_watchdog(void *dm_void)
3378 {
3379 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3380 	struct ccx_info *ccx = &dm->dm_ccx_info;
3381 
3382 	ccx->ccx_watchdog_result = 0;
3383 
3384 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
3385 		return;
3386 
3387 	#if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
3388 	if (phydm_nhm_mntr_result(dm))
3389 		ccx->ccx_watchdog_result |= NHM_SUCCESS;
3390 
3391 	if (phydm_clm_mntr_result(dm))
3392 		ccx->ccx_watchdog_result |= CLM_SUCCESS;
3393 
3394 	PHYDM_DBG(dm, DBG_ENV_MNTR,
3395 		  "Summary: nhm_ratio=((%d)) clm_ratio=((%d))\n\n",
3396 		  ccx->nhm_ratio, ccx->clm_ratio);
3397 	#endif
3398 
3399 	#ifdef FAHM_SUPPORT
3400 	if (dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM) {
3401 		if (phydm_fahm_mntr_result(dm))
3402 			ccx->ccx_watchdog_result |= FAHM_SUCCESS;
3403 	}
3404 	#endif
3405 
3406 	#ifdef IFS_CLM_SUPPORT
3407 	if (dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM) {
3408 		if (phydm_ifs_clm_mntr_result(dm))
3409 			ccx->ccx_watchdog_result |= IFS_CLM_SUCCESS;
3410 	}
3411 	#endif
3412 }
3413 
phydm_env_mntr_set_watchdog(void * dm_void)3414 void phydm_env_mntr_set_watchdog(void *dm_void)
3415 {
3416 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3417 	struct ccx_info *ccx = &dm->dm_ccx_info;
3418 
3419 	if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
3420 		return;
3421 
3422 	PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
3423 
3424 	#if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
3425 	if (phydm_nhm_mntr_chk(dm, 262))
3426 		phydm_nhm_trigger(dm);
3427 
3428 	if (phydm_clm_mntr_chk(dm, 262))
3429 		phydm_clm_trigger(dm);
3430 	#endif
3431 
3432 	#ifdef FAHM_SUPPORT
3433 	if (dm->support_ic_type & PHYDM_IC_SUPPORT_FAHM) {
3434 		if (phydm_fahm_mntr_chk(dm, 262))
3435 			phydm_fahm_trigger(dm);
3436 	}
3437 	#endif
3438 
3439 	#ifdef IFS_CLM_SUPPORT
3440 	if (dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM) {
3441 		if (phydm_ifs_clm_mntr_chk(dm, 960))
3442 			phydm_ifs_clm_trigger(dm);
3443 	}
3444 	#endif
3445 }
3446 
phydm_env_monitor_init(void * dm_void)3447 void phydm_env_monitor_init(void *dm_void)
3448 {
3449 	struct dm_struct *dm = (struct dm_struct *)dm_void;
3450 	#if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
3451 	phydm_ccx_hw_restart(dm);
3452 	phydm_nhm_init(dm);
3453 	phydm_clm_init(dm);
3454 	#endif
3455 
3456 	#ifdef FAHM_SUPPORT
3457 	phydm_fahm_init(dm);
3458 	#endif
3459 
3460 	#ifdef IFS_CLM_SUPPORT
3461 	if (!(dm->support_ic_type & PHYDM_IC_SUPPORT_IFS_CLM))
3462 		return;
3463 
3464 	phydm_ifs_clm_restart(dm);
3465 	phydm_ifs_clm_init(dm);
3466 	#endif
3467 }
3468 
3469