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