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, ¶);
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, ¶))
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, ¶);
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, ¶) == 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