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