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