phydm_ccx.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839
  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. #include "mp_precomp.h"
  26. #include "phydm_precomp.h"
  27. void phydm_ccx_hw_restart(void *dm_void)
  28. /*@Will Restart NHM/CLM/FAHM simultaneously*/
  29. {
  30. struct dm_struct *dm = (struct dm_struct *)dm_void;
  31. u32 reg1 = 0;
  32. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  33. reg1 = R_0x994;
  34. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  35. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  36. reg1 = R_0x1e60;
  37. #endif
  38. else
  39. reg1 = R_0x890;
  40. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  41. odm_set_bb_reg(dm, reg1, 0x7, 0x0); /*@disable NHM,CLM, FAHM*/
  42. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  43. odm_set_bb_reg(dm, R_0x994, BIT(8), 0x0);
  44. odm_set_bb_reg(dm, R_0x994, BIT(8), 0x1);
  45. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  46. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  47. odm_set_bb_reg(dm, R_0x1e60, BIT(8), 0x0);
  48. odm_set_bb_reg(dm, R_0x1e60, BIT(8), 0x1);
  49. #endif
  50. } else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
  51. odm_set_bb_reg(dm, R_0x890, BIT(8), 0x0);
  52. odm_set_bb_reg(dm, R_0x890, BIT(8), 0x1);
  53. }
  54. }
  55. #ifdef FAHM_SUPPORT
  56. u16 phydm_hw_divider(void *dm_void, u16 numerator, u16 denumerator)
  57. {
  58. struct dm_struct *dm = (struct dm_struct *)dm_void;
  59. u16 result = DEVIDER_ERROR;
  60. u32 tmp_u32 = ((numerator << 16) | denumerator);
  61. u32 reg_devider_input;
  62. u32 reg;
  63. u8 i;
  64. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  65. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  66. reg_devider_input = 0x1cbc;
  67. reg = 0x1f98;
  68. } else {
  69. reg_devider_input = 0x980;
  70. reg = 0x9f0;
  71. }
  72. odm_set_bb_reg(dm, reg_devider_input, MASKDWORD, tmp_u32);
  73. for (i = 0; i < 10; i++) {
  74. ODM_delay_ms(1);
  75. if (odm_get_bb_reg(dm, reg, BIT(24))) {
  76. /*@Chk HW rpt is ready*/
  77. result = (u16)odm_get_bb_reg(dm, reg, MASKBYTE2);
  78. break;
  79. }
  80. }
  81. return result;
  82. }
  83. void phydm_fahm_trigger(void *dm_void, u16 tgr_period)
  84. { /*@unit (4us)*/
  85. struct dm_struct *dm = (struct dm_struct *)dm_void;
  86. u32 fahm_reg1;
  87. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  88. odm_set_bb_reg(dm, R_0x1cf8, 0xffff00, tgr_period);
  89. fahm_reg1 = 0x994;
  90. } else {
  91. odm_set_bb_reg(dm, R_0x978, 0xff000000, (tgr_period & 0xff));
  92. odm_set_bb_reg(dm, R_0x97c, 0xff, (tgr_period & 0xff00) >> 8);
  93. fahm_reg1 = 0x890;
  94. }
  95. odm_set_bb_reg(dm, fahm_reg1, BIT(2), 0);
  96. odm_set_bb_reg(dm, fahm_reg1, BIT(2), 1);
  97. }
  98. void phydm_fahm_set_valid_cnt(void *dm_void, u8 numerator_sel,
  99. u8 denominator_sel)
  100. {
  101. struct dm_struct *dm = (struct dm_struct *)dm_void;
  102. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  103. u32 fahm_reg1;
  104. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  105. if (ccx_info->fahm_nume_sel == numerator_sel &&
  106. ccx_info->fahm_denom_sel == denominator_sel) {
  107. PHYDM_DBG(dm, DBG_ENV_MNTR, "no need to update\n");
  108. return;
  109. }
  110. ccx_info->fahm_nume_sel = numerator_sel;
  111. ccx_info->fahm_denom_sel = denominator_sel;
  112. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  113. fahm_reg1 = 0x994;
  114. else
  115. fahm_reg1 = 0x890;
  116. odm_set_bb_reg(dm, fahm_reg1, 0xe0, numerator_sel);
  117. odm_set_bb_reg(dm, fahm_reg1, 0x7000, denominator_sel);
  118. }
  119. void phydm_fahm_get_result(void *dm_void)
  120. {
  121. struct dm_struct *dm = (struct dm_struct *)dm_void;
  122. u16 fahm_cnt[12]; /*packet count*/
  123. u16 fahm_rpt[12]; /*percentage*/
  124. u16 denominator; /*@fahm_denominator packet count*/
  125. u32 reg_rpt, reg_rpt_2;
  126. u32 reg_tmp;
  127. boolean is_ready = false;
  128. u8 i;
  129. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  130. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  131. reg_rpt = 0x1f80;
  132. reg_rpt_2 = 0x1f98;
  133. } else {
  134. reg_rpt = 0x9d8;
  135. reg_rpt_2 = 0x9f0;
  136. }
  137. for (i = 0; i < 3; i++) {
  138. if (odm_get_bb_reg(dm, reg_rpt_2, BIT(31))) {
  139. /*@Chk HW rpt is ready*/
  140. is_ready = true;
  141. break;
  142. }
  143. ODM_delay_ms(1);
  144. }
  145. if (!is_ready)
  146. return;
  147. /*@Get FAHM Denominator*/
  148. denominator = (u16)odm_get_bb_reg(dm, reg_rpt_2, MASKLWORD);
  149. PHYDM_DBG(dm, DBG_ENV_MNTR, "Reg[0x%x] fahm_denmrtr = %d\n", reg_rpt_2,
  150. denominator);
  151. /*@Get FAHM nemerator*/
  152. for (i = 0; i < 6; i++) {
  153. reg_tmp = odm_get_bb_reg(dm, reg_rpt + (i << 2), MASKDWORD);
  154. PHYDM_DBG(dm, DBG_ENV_MNTR, "Reg[0x%x] fahm_denmrtr = %d\n",
  155. reg_rpt + (i * 4), reg_tmp);
  156. fahm_cnt[i * 2] = (u16)(reg_tmp & MASKLWORD);
  157. fahm_cnt[i * 2 + 1] = (u16)((reg_tmp & MASKHWORD) >> 16);
  158. }
  159. for (i = 0; i < 12; i++)
  160. fahm_rpt[i] = phydm_hw_divider(dm, fahm_cnt[i], denominator);
  161. PHYDM_DBG(dm, DBG_ENV_MNTR,
  162. "FAHM_RPT_cnt[10:0]=[%d, %d, %d, %d, %d(IGI), %d, %d, %d, %d, %d, %d, %d]\n",
  163. fahm_cnt[11], fahm_cnt[10], fahm_cnt[9],
  164. fahm_cnt[8], fahm_cnt[7], fahm_cnt[6],
  165. fahm_cnt[5], fahm_cnt[4], fahm_cnt[3],
  166. fahm_cnt[2], fahm_cnt[1], fahm_cnt[0]);
  167. PHYDM_DBG(dm, DBG_ENV_MNTR,
  168. "FAHM_RPT[10:0]=[%d, %d, %d, %d, %d(IGI), %d, %d, %d, %d, %d, %d, %d]\n",
  169. fahm_rpt[11], fahm_rpt[10], fahm_rpt[9], fahm_rpt[8],
  170. fahm_rpt[7], fahm_rpt[6], fahm_rpt[5], fahm_rpt[4],
  171. fahm_rpt[3], fahm_rpt[2], fahm_rpt[1], fahm_rpt[0]);
  172. }
  173. void phydm_fahm_set_th_by_igi(void *dm_void, u8 igi)
  174. {
  175. struct dm_struct *dm = (struct dm_struct *)dm_void;
  176. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  177. u32 val = 0;
  178. u8 f_th[11]; /*@FAHM Threshold*/
  179. u8 rssi_th[11]; /*@in RSSI scale*/
  180. u8 th_gap = 2 * IGI_TO_NHM_TH_MULTIPLIER; /*unit is 0.5dB for FAHM*/
  181. u8 i;
  182. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  183. if (ccx_info->env_mntr_igi == igi) {
  184. PHYDM_DBG(dm, DBG_ENV_MNTR,
  185. "No need to update FAHM_th, IGI=0x%x\n",
  186. ccx_info->env_mntr_igi);
  187. return;
  188. }
  189. ccx_info->env_mntr_igi = igi; /*@bkp IGI*/
  190. if (igi >= CCA_CAP)
  191. f_th[0] = (igi - CCA_CAP) * IGI_TO_NHM_TH_MULTIPLIER;
  192. else
  193. f_th[0] = 0;
  194. rssi_th[0] = igi - 10 - CCA_CAP;
  195. for (i = 1; i <= 10; i++) {
  196. f_th[i] = f_th[0] + th_gap * i;
  197. rssi_th[i] = rssi_th[0] + (i << 1);
  198. }
  199. PHYDM_DBG(dm, DBG_ENV_MNTR,
  200. "FAHM_RSSI_th[10:0]=[%d, %d, %d, (IGI)%d, %d, %d, %d, %d, %d, %d, %d]\n",
  201. rssi_th[10], rssi_th[9], rssi_th[8], rssi_th[7], rssi_th[6],
  202. rssi_th[5], rssi_th[4], rssi_th[3], rssi_th[2], rssi_th[1],
  203. rssi_th[0]);
  204. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  205. val = BYTE_2_DWORD(0, f_th[2], f_th[1], f_th[0]);
  206. odm_set_bb_reg(dm, R_0x1c38, 0xffffff00, val);
  207. val = BYTE_2_DWORD(0, f_th[5], f_th[4], f_th[3]);
  208. odm_set_bb_reg(dm, R_0x1c78, 0xffffff00, val);
  209. val = BYTE_2_DWORD(0, 0, f_th[7], f_th[6]);
  210. odm_set_bb_reg(dm, R_0x1c7c, 0xffff0000, val);
  211. val = BYTE_2_DWORD(0, f_th[10], f_th[9], f_th[8]);
  212. odm_set_bb_reg(dm, R_0x1cb8, 0xffffff00, val);
  213. } else {
  214. val = BYTE_2_DWORD(f_th[3], f_th[2], f_th[1], f_th[0]);
  215. odm_set_bb_reg(dm, R_0x970, MASKDWORD, val);
  216. val = BYTE_2_DWORD(f_th[7], f_th[6], f_th[5], f_th[4]);
  217. odm_set_bb_reg(dm, R_0x974, MASKDWORD, val);
  218. BYTE_2_DWORD(0, f_th[10], f_th[9], f_th[8]);
  219. odm_set_bb_reg(dm, R_0x978, 0xffffff, val);
  220. }
  221. }
  222. void phydm_fahm_init(void *dm_void)
  223. {
  224. struct dm_struct *dm = (struct dm_struct *)dm_void;
  225. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  226. u32 fahm_reg1;
  227. u8 denumerator_sel = 0;
  228. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  229. PHYDM_DBG(dm, DBG_ENV_MNTR, "IGI=0x%x\n",
  230. dm->dm_dig_table.cur_ig_value);
  231. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  232. fahm_reg1 = 0x994;
  233. else
  234. fahm_reg1 = 0x890;
  235. ccx_info->fahm_period = 65535;
  236. odm_set_bb_reg(dm, fahm_reg1, 0x6, 3); /*@FAHM HW block enable*/
  237. denumerator_sel = FAHM_INCLD_FA | FAHM_INCLD_CRC_OK | FAHM_INCLD_CRC_ER;
  238. phydm_fahm_set_valid_cnt(dm, FAHM_INCLD_FA, denumerator_sel);
  239. phydm_fahm_set_th_by_igi(dm, dm->dm_dig_table.cur_ig_value);
  240. }
  241. void phydm_fahm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
  242. u32 *_out_len)
  243. {
  244. struct dm_struct *dm = (struct dm_struct *)dm_void;
  245. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  246. char help[] = "-h";
  247. u32 var1[10] = {0};
  248. u32 used = *_used;
  249. u32 out_len = *_out_len;
  250. u32 i;
  251. for (i = 0; i < 2; i++) {
  252. if (input[i + 1])
  253. PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
  254. }
  255. if ((strcmp(input[1], help) == 0)) {
  256. PDM_SNPF(out_len, used, output + used, out_len - used,
  257. "{1: trigger, 2:get result}\n");
  258. PDM_SNPF(out_len, used, output + used, out_len - used,
  259. "{3: MNTR mode sel} {1: driver, 2. FW}\n");
  260. return;
  261. } else if (var1[0] == 1) { /* Set & trigger CLM */
  262. phydm_fahm_set_th_by_igi(dm, dm->dm_dig_table.cur_ig_value);
  263. phydm_fahm_trigger(dm, ccx_info->fahm_period);
  264. PDM_SNPF(out_len, used, output + used, out_len - used,
  265. "Monitor FAHM for %d * 4us\n", ccx_info->fahm_period);
  266. } else if (var1[0] == 2) { /* @Get CLM results */
  267. phydm_fahm_get_result(dm);
  268. PDM_SNPF(out_len, used, output + used, out_len - used,
  269. "FAHM_result=%d us\n", (ccx_info->clm_result << 2));
  270. } else {
  271. PDM_SNPF(out_len, used, output + used, out_len - used,
  272. "Error\n");
  273. }
  274. *_used = used;
  275. *_out_len = out_len;
  276. }
  277. #endif /*@#ifdef FAHM_SUPPORT*/
  278. #ifdef NHM_SUPPORT
  279. void phydm_nhm_racing_release(void *dm_void)
  280. {
  281. struct dm_struct *dm = (struct dm_struct *)dm_void;
  282. struct ccx_info *ccx = &dm->dm_ccx_info;
  283. u32 value32;
  284. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  285. PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->nhm_set_lv);
  286. ccx->nhm_ongoing = false;
  287. ccx->nhm_set_lv = NHM_RELEASE;
  288. if (!(ccx->nhm_app == NHM_BACKGROUND || ccx->nhm_app == NHM_ACS)) {
  289. phydm_pause_func(dm, F00_DIG, PHYDM_RESUME,
  290. PHYDM_PAUSE_LEVEL_1, 1, &value32);
  291. }
  292. ccx->nhm_app = NHM_BACKGROUND;
  293. }
  294. u8 phydm_nhm_racing_ctrl(void *dm_void, enum phydm_nhm_level nhm_lv)
  295. {
  296. struct dm_struct *dm = (struct dm_struct *)dm_void;
  297. struct ccx_info *ccx = &dm->dm_ccx_info;
  298. u8 set_result = PHYDM_SET_SUCCESS;
  299. /*@acquire to control NHM API*/
  300. PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_ongoing=%d, lv:(%d)->(%d)\n",
  301. ccx->nhm_ongoing, ccx->nhm_set_lv, nhm_lv);
  302. if (ccx->nhm_ongoing) {
  303. if (nhm_lv <= ccx->nhm_set_lv) {
  304. set_result = PHYDM_SET_FAIL;
  305. } else {
  306. phydm_ccx_hw_restart(dm);
  307. ccx->nhm_ongoing = false;
  308. }
  309. }
  310. if (set_result)
  311. ccx->nhm_set_lv = nhm_lv;
  312. PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm racing success=%d\n", set_result);
  313. return set_result;
  314. }
  315. void phydm_nhm_trigger(void *dm_void)
  316. {
  317. struct dm_struct *dm = (struct dm_struct *)dm_void;
  318. struct ccx_info *ccx = &dm->dm_ccx_info;
  319. u32 nhm_reg1 = 0;
  320. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  321. nhm_reg1 = R_0x994;
  322. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  323. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  324. nhm_reg1 = R_0x1e60;
  325. #endif
  326. else
  327. nhm_reg1 = R_0x890;
  328. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  329. /*Trigger NHM*/
  330. pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
  331. pdm_set_reg(dm, nhm_reg1, BIT(1), 1);
  332. ccx->nhm_trigger_time = dm->phydm_sys_up_time;
  333. ccx->nhm_rpt_stamp++;
  334. ccx->nhm_ongoing = true;
  335. }
  336. boolean
  337. phydm_nhm_check_rdy(void *dm_void)
  338. {
  339. struct dm_struct *dm = (struct dm_struct *)dm_void;
  340. boolean is_ready = false;
  341. u32 reg1 = 0, reg1_bit = 0;
  342. #if (ENV_MNTR_DBG || ENV_MNTR_DBG_1)
  343. u16 i = 0;
  344. u64 start_time, progressing_time;
  345. u32 reg_val_start = 0, reg_val = 0;
  346. u8 print_rpt = 0;
  347. #endif
  348. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  349. reg1 = 0xfb4;
  350. reg1_bit = 16;
  351. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  352. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  353. reg1 = 0x2d4c;
  354. reg1_bit = 16;
  355. #endif
  356. } else {
  357. reg1 = 0x8b4;
  358. if (dm->support_ic_type == ODM_RTL8710B) {
  359. reg1_bit = 25;
  360. } else {
  361. reg1_bit = 17;
  362. }
  363. }
  364. #if (ENV_MNTR_DBG_1)
  365. start_time = odm_get_current_time(dm);
  366. if (dm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821)) {
  367. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM_period = %d\n",
  368. odm_get_bb_reg(dm, R_0x990, MASKDWORD));
  369. /*NHM trigger bit*/
  370. reg_val_start = odm_get_bb_reg(dm, R_0x994, BIT(1));
  371. PHYDM_DBG(dm, DBG_ENV_MNTR, "reg_val_start = %d\n",
  372. reg_val_start);
  373. for (i = 0; i <= 400; i++) {
  374. if (print_rpt == 0) {
  375. reg_val = odm_get_bb_reg(dm, R_0x994, BIT(1));
  376. if (reg_val != reg_val_start) {
  377. print_rpt = 1;
  378. PHYDM_DBG(dm, DBG_ENV_MNTR,
  379. "Trig[%d] (%d) -> (%d)\n",
  380. i, reg_val_start, reg_val);
  381. }
  382. }
  383. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit))) {
  384. is_ready = true;
  385. break;
  386. }
  387. ODM_delay_ms(1);
  388. }
  389. } else {
  390. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
  391. is_ready = true;
  392. }
  393. progressing_time = odm_get_progressing_time(dm, start_time);
  394. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM rdy=%d, i=%d, NHM_polling_time=%lld\n",
  395. is_ready, i, progressing_time);
  396. #elif (ENV_MNTR_DBG)
  397. start_time = odm_get_current_time(dm);
  398. for (i = 0; i <= 400; i++) {
  399. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit))) {
  400. is_ready = true;
  401. break;
  402. }
  403. ODM_delay_ms(1);
  404. }
  405. progressing_time = odm_get_progressing_time(dm, start_time);
  406. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM rdy=%d, i=%d, NHM_polling_time=%lld\n",
  407. is_ready, i, progressing_time);
  408. #else
  409. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
  410. is_ready = true;
  411. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM rdy=%d\n", is_ready);
  412. #endif
  413. return is_ready;
  414. }
  415. void phydm_nhm_get_utility(void *dm_void)
  416. {
  417. struct dm_struct *dm = (struct dm_struct *)dm_void;
  418. struct ccx_info *ccx = &dm->dm_ccx_info;
  419. u8 nhm_rpt_non_0 = 0;
  420. if (ccx->nhm_rpt_sum >= ccx->nhm_result[0]) {
  421. nhm_rpt_non_0 = ccx->nhm_rpt_sum - ccx->nhm_result[0];
  422. ccx->nhm_ratio = (nhm_rpt_non_0 * 100) >> 8;
  423. } else {
  424. PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] nhm_rpt_sum invalid\n");
  425. ccx->nhm_ratio = 0;
  426. }
  427. PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_ratio=%d\n", ccx->nhm_ratio);
  428. }
  429. boolean
  430. phydm_nhm_get_result(void *dm_void)
  431. {
  432. struct dm_struct *dm = (struct dm_struct *)dm_void;
  433. struct ccx_info *ccx = &dm->dm_ccx_info;
  434. u32 value32;
  435. u8 i;
  436. u32 nhm_reg1 = 0;
  437. u16 nhm_rpt_sum_tmp = 0;
  438. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  439. nhm_reg1 = R_0x994;
  440. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  441. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  442. nhm_reg1 = R_0x1e60;
  443. #endif
  444. else
  445. nhm_reg1 = R_0x890;
  446. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  447. pdm_set_reg(dm, nhm_reg1, BIT(1), 0);
  448. #if (ENV_MNTR_DBG_2)
  449. PHYDM_DBG(dm, DBG_ENV_MNTR,
  450. "[DBG][3] 0xc50=0x%x, 0x994=0x%x, 0x998=0x%x\n",
  451. odm_get_bb_reg(dm, 0xc50, MASKDWORD),
  452. odm_get_bb_reg(dm, 0x994, MASKDWORD),
  453. odm_get_bb_reg(dm, 0x998, MASKDWORD));
  454. #endif
  455. if (!(phydm_nhm_check_rdy(dm))) {
  456. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM report Fail\n");
  457. phydm_nhm_racing_release(dm);
  458. return false;
  459. }
  460. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  461. value32 = odm_read_4byte(dm, 0xfa8);
  462. odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
  463. value32 = odm_read_4byte(dm, 0xfac);
  464. odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
  465. value32 = odm_read_4byte(dm, 0xfb0);
  466. odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
  467. /*@Get NHM duration*/
  468. value32 = odm_read_4byte(dm, 0xfb4);
  469. ccx->nhm_duration = (u16)(value32 & MASKLWORD);
  470. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  471. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  472. value32 = odm_read_4byte(dm, 0x2d40);
  473. odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
  474. value32 = odm_read_4byte(dm, 0x2d44);
  475. odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
  476. value32 = odm_read_4byte(dm, 0x2d48);
  477. odm_move_memory(dm, &ccx->nhm_result[8], &value32, 4);
  478. /*@Get NHM duration*/
  479. value32 = odm_read_4byte(dm, 0x2d4c);
  480. ccx->nhm_duration = (u16)(value32 & MASKLWORD);
  481. #endif
  482. } else {
  483. value32 = odm_read_4byte(dm, 0x8d8);
  484. odm_move_memory(dm, &ccx->nhm_result[0], &value32, 4);
  485. value32 = odm_read_4byte(dm, 0x8dc);
  486. odm_move_memory(dm, &ccx->nhm_result[4], &value32, 4);
  487. value32 = odm_get_bb_reg(dm, R_0x8d0, 0xffff0000);
  488. odm_move_memory(dm, &ccx->nhm_result[8], &value32, 2);
  489. value32 = odm_read_4byte(dm, 0x8d4);
  490. ccx->nhm_result[10] = (u8)((value32 & MASKBYTE2) >> 16);
  491. ccx->nhm_result[11] = (u8)((value32 & MASKBYTE3) >> 24);
  492. /*@Get NHM duration*/
  493. ccx->nhm_duration = (u16)(value32 & MASKLWORD);
  494. }
  495. /* sum all nhm_result */
  496. if (ccx->nhm_period >= 65530) {
  497. value32 = (ccx->nhm_duration * 100) >> 16;
  498. PHYDM_DBG(dm, DBG_ENV_MNTR,
  499. "NHM valid time = %d, valid: %d percent\n",
  500. ccx->nhm_duration, value32);
  501. }
  502. for (i = 0; i < NHM_RPT_NUM; i++)
  503. nhm_rpt_sum_tmp += (u16)ccx->nhm_result[i];
  504. ccx->nhm_rpt_sum = (u8)nhm_rpt_sum_tmp;
  505. PHYDM_DBG(dm, DBG_ENV_MNTR,
  506. "NHM_Rpt[%d](H->L)[%d %d %d %d %d %d %d %d %d %d %d %d]\n",
  507. ccx->nhm_rpt_stamp, ccx->nhm_result[11], ccx->nhm_result[10],
  508. ccx->nhm_result[9], ccx->nhm_result[8], ccx->nhm_result[7],
  509. ccx->nhm_result[6], ccx->nhm_result[5], ccx->nhm_result[4],
  510. ccx->nhm_result[3], ccx->nhm_result[2], ccx->nhm_result[1],
  511. ccx->nhm_result[0]);
  512. phydm_nhm_racing_release(dm);
  513. #if (ENV_MNTR_DBG_2)
  514. PHYDM_DBG(dm, DBG_ENV_MNTR,
  515. "[DBG][4] 0xc50=0x%x, 0x994=0x%x, 0x998=0x%x\n",
  516. odm_get_bb_reg(dm, 0xc50, MASKDWORD),
  517. odm_get_bb_reg(dm, 0x994, MASKDWORD),
  518. odm_get_bb_reg(dm, 0x998, MASKDWORD));
  519. #endif
  520. if (nhm_rpt_sum_tmp > 255) {
  521. PHYDM_DBG(dm, DBG_ENV_MNTR,
  522. "[Warning] Invalid NHM RPT, total=%d\n",
  523. nhm_rpt_sum_tmp);
  524. return false;
  525. }
  526. return true;
  527. }
  528. void phydm_nhm_set_th_reg(void *dm_void)
  529. {
  530. struct dm_struct *dm = (struct dm_struct *)dm_void;
  531. struct ccx_info *ccx = &dm->dm_ccx_info;
  532. u32 reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg4_bit = 0;
  533. u32 val = 0;
  534. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  535. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  536. reg1 = 0x994;
  537. reg2 = 0x998;
  538. reg3 = 0x99c;
  539. reg4 = 0x9a0;
  540. reg4_bit = MASKBYTE0;
  541. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  542. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  543. reg1 = 0x1e60;
  544. reg2 = 0x1e44;
  545. reg3 = 0x1e48;
  546. reg4 = 0x1e5c;
  547. reg4_bit = MASKBYTE2;
  548. #endif
  549. } else {
  550. reg1 = 0x890;
  551. reg2 = 0x898;
  552. reg3 = 0x89c;
  553. reg4 = 0xe28;
  554. reg4_bit = MASKBYTE0;
  555. }
  556. /*Set NHM threshold*/ /*Unit: PWdB U(8,1)*/
  557. val = BYTE_2_DWORD(ccx->nhm_th[3], ccx->nhm_th[2],
  558. ccx->nhm_th[1], ccx->nhm_th[0]);
  559. pdm_set_reg(dm, reg2, MASKDWORD, val);
  560. val = BYTE_2_DWORD(ccx->nhm_th[7], ccx->nhm_th[6],
  561. ccx->nhm_th[5], ccx->nhm_th[4]);
  562. pdm_set_reg(dm, reg3, MASKDWORD, val);
  563. pdm_set_reg(dm, reg4, reg4_bit, ccx->nhm_th[8]);
  564. val = BYTE_2_DWORD(0, 0, ccx->nhm_th[10], ccx->nhm_th[9]);
  565. pdm_set_reg(dm, reg1, 0xffff0000, val);
  566. PHYDM_DBG(dm, DBG_ENV_MNTR,
  567. "Update NHM_th[H->L]=[%d %d %d %d %d %d %d %d %d %d %d]\n",
  568. ccx->nhm_th[10], ccx->nhm_th[9], ccx->nhm_th[8],
  569. ccx->nhm_th[7], ccx->nhm_th[6], ccx->nhm_th[5],
  570. ccx->nhm_th[4], ccx->nhm_th[3], ccx->nhm_th[2],
  571. ccx->nhm_th[1], ccx->nhm_th[0]);
  572. }
  573. boolean
  574. phydm_nhm_th_update_chk(void *dm_void, enum nhm_application nhm_app, u8 *nhm_th,
  575. u32 *igi_new)
  576. {
  577. struct dm_struct *dm = (struct dm_struct *)dm_void;
  578. struct ccx_info *ccx = &dm->dm_ccx_info;
  579. boolean is_update = false;
  580. u8 igi_curr = phydm_get_igi(dm, BB_PATH_A);
  581. u8 nhm_igi_th_11k_low[NHM_TH_NUM] = {0x12, 0x15, 0x18, 0x1b, 0x1e,
  582. 0x23, 0x28, 0x2c, 0x78,
  583. 0x78, 0x78};
  584. u8 nhm_igi_th_11k_high[NHM_TH_NUM] = {0x1e, 0x23, 0x28, 0x2d, 0x32,
  585. 0x37, 0x78, 0x78, 0x78, 0x78,
  586. 0x78};
  587. u8 nhm_igi_th_xbox[NHM_TH_NUM] = {0x1a, 0x2c, 0x2e, 0x30, 0x32, 0x34,
  588. 0x36, 0x38, 0x3a, 0x3c, 0x3d};
  589. u8 i;
  590. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  591. PHYDM_DBG(dm, DBG_ENV_MNTR, "App=%d, nhm_igi=0x%x, igi_curr=0x%x\n",
  592. nhm_app, ccx->nhm_igi, igi_curr);
  593. if (igi_curr < 0x10) /* Protect for invalid IGI*/
  594. return false;
  595. switch (nhm_app) {
  596. case NHM_BACKGROUND: /*@Get IGI form driver parameter(cur_ig_value)*/
  597. case NHM_ACS:
  598. if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
  599. is_update = true;
  600. *igi_new = (u32)igi_curr;
  601. nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr - CCA_CAP);
  602. for (i = 1; i <= 10; i++)
  603. nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(2 * i);
  604. }
  605. break;
  606. case IEEE_11K_HIGH:
  607. is_update = true;
  608. *igi_new = 0x2c;
  609. for (i = 0; i < NHM_TH_NUM; i++)
  610. nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_high[i]);
  611. break;
  612. case IEEE_11K_LOW:
  613. is_update = true;
  614. *igi_new = 0x20;
  615. for (i = 0; i < NHM_TH_NUM; i++)
  616. nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_11k_low[i]);
  617. break;
  618. case INTEL_XBOX:
  619. is_update = true;
  620. *igi_new = 0x36;
  621. for (i = 0; i < NHM_TH_NUM; i++)
  622. nhm_th[i] = IGI_2_NHM_TH(nhm_igi_th_xbox[i]);
  623. break;
  624. case NHM_DBG: /*@Get IGI form register*/
  625. igi_curr = phydm_get_igi(dm, BB_PATH_A);
  626. if (ccx->nhm_igi != igi_curr || ccx->nhm_app != nhm_app) {
  627. is_update = true;
  628. *igi_new = (u32)igi_curr;
  629. nhm_th[0] = (u8)IGI_2_NHM_TH(igi_curr - CCA_CAP);
  630. for (i = 1; i <= 10; i++)
  631. nhm_th[i] = nhm_th[0] + IGI_2_NHM_TH(2 * i);
  632. }
  633. break;
  634. }
  635. if (is_update) {
  636. PHYDM_DBG(dm, DBG_ENV_MNTR, "[Update NHM_TH] igi_RSSI=%d\n",
  637. IGI_2_RSSI(*igi_new));
  638. for (i = 0; i < NHM_TH_NUM; i++) {
  639. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM_th[%d](RSSI) = %d\n",
  640. i, NTH_TH_2_RSSI(nhm_th[i]));
  641. }
  642. } else {
  643. PHYDM_DBG(dm, DBG_ENV_MNTR, "No need to update NHM_TH\n");
  644. }
  645. return is_update;
  646. }
  647. void phydm_nhm_set(void *dm_void, enum nhm_option_txon_all include_tx,
  648. enum nhm_option_cca_all include_cca,
  649. enum nhm_divider_opt_all divi_opt,
  650. enum nhm_application nhm_app, u16 period)
  651. {
  652. struct dm_struct *dm = (struct dm_struct *)dm_void;
  653. struct ccx_info *ccx = &dm->dm_ccx_info;
  654. u8 nhm_th[NHM_TH_NUM] = {0};
  655. u32 igi = 0x20;
  656. u32 reg1 = 0, reg2 = 0;
  657. u32 val_tmp = 0;
  658. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  659. PHYDM_DBG(dm, DBG_ENV_MNTR,
  660. "incld{tx, cca}={%d, %d}, divi_opt=%d, period=%d\n",
  661. include_tx, include_cca, divi_opt, period);
  662. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  663. reg1 = 0x994;
  664. reg2 = 0x990;
  665. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  666. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  667. reg1 = 0x1e60;
  668. reg2 = 0x1e40;
  669. #endif
  670. } else {
  671. reg1 = 0x890;
  672. reg2 = 0x894;
  673. }
  674. /*Set disable_ignore_cca, disable_ignore_txon, ccx_en*/
  675. if (include_tx != ccx->nhm_include_txon ||
  676. include_cca != ccx->nhm_include_cca ||
  677. divi_opt != ccx->nhm_divider_opt) {
  678. /* some old ic is not supported on NHM divider option */
  679. if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
  680. ODM_RTL8195A | ODM_RTL8192E)) {
  681. val_tmp = (u32)((include_tx << 2) |
  682. (include_cca << 1) | 1);
  683. pdm_set_reg(dm, reg1, 0x700, val_tmp);
  684. } else {
  685. val_tmp = (u32)BIT_2_BYTE(divi_opt, include_tx,
  686. include_cca, 1);
  687. pdm_set_reg(dm, reg1, 0xf00, val_tmp);
  688. }
  689. ccx->nhm_include_txon = include_tx;
  690. ccx->nhm_include_cca = include_cca;
  691. ccx->nhm_divider_opt = divi_opt;
  692. #if 0
  693. PHYDM_DBG(dm, DBG_ENV_MNTR,
  694. "val_tmp=%d, incld{tx, cca}={%d, %d}, divi_opt=%d, period=%d\n",
  695. val_tmp, include_tx, include_cca, divi_opt, period);
  696. PHYDM_DBG(dm, DBG_ENV_MNTR, "0x994=0x%x\n",
  697. odm_get_bb_reg(dm, 0x994, 0xf00));
  698. #endif
  699. }
  700. /*Set NHM period*/
  701. if (period != ccx->nhm_period) {
  702. pdm_set_reg(dm, reg2, MASKHWORD, period);
  703. PHYDM_DBG(dm, DBG_ENV_MNTR,
  704. "Update NHM period ((%d)) -> ((%d))\n",
  705. ccx->nhm_period, period);
  706. ccx->nhm_period = period;
  707. }
  708. /*Set NHM threshold*/
  709. if (phydm_nhm_th_update_chk(dm, nhm_app, &(nhm_th[0]), &igi)) {
  710. /*Pause IGI*/
  711. if (nhm_app == NHM_BACKGROUND || nhm_app == NHM_ACS) {
  712. PHYDM_DBG(dm, DBG_ENV_MNTR, "DIG Free Run\n");
  713. } else if (phydm_pause_func(dm, F00_DIG, PHYDM_PAUSE,
  714. PHYDM_PAUSE_LEVEL_1, 1, &igi)
  715. == PAUSE_FAIL) {
  716. PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG Fail\n");
  717. return;
  718. } else {
  719. PHYDM_DBG(dm, DBG_ENV_MNTR, "pause DIG=0x%x\n", igi);
  720. }
  721. ccx->nhm_app = nhm_app;
  722. ccx->nhm_igi = (u8)igi;
  723. odm_move_memory(dm, &ccx->nhm_th[0], &nhm_th, NHM_TH_NUM);
  724. /*Set NHM th*/
  725. phydm_nhm_set_th_reg(dm);
  726. }
  727. }
  728. u8 phydm_nhm_mntr_set(void *dm_void, struct nhm_para_info *nhm_para)
  729. {
  730. struct dm_struct *dm = (struct dm_struct *)dm_void;
  731. u16 nhm_time = 0; /*unit: 4us*/
  732. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  733. if (nhm_para->mntr_time == 0)
  734. return PHYDM_SET_FAIL;
  735. if (nhm_para->nhm_lv >= NHM_MAX_NUM) {
  736. PHYDM_DBG(dm, DBG_ENV_MNTR, "Wrong LV=%d\n", nhm_para->nhm_lv);
  737. return PHYDM_SET_FAIL;
  738. }
  739. if (phydm_nhm_racing_ctrl(dm, nhm_para->nhm_lv) == PHYDM_SET_FAIL)
  740. return PHYDM_SET_FAIL;
  741. if (nhm_para->mntr_time >= 262)
  742. nhm_time = NHM_PERIOD_MAX;
  743. else
  744. nhm_time = nhm_para->mntr_time * MS_TO_4US_RATIO;
  745. phydm_nhm_set(dm, nhm_para->incld_txon, nhm_para->incld_cca,
  746. nhm_para->div_opt, nhm_para->nhm_app, nhm_time);
  747. return PHYDM_SET_SUCCESS;
  748. }
  749. /*@Environment Monitor*/
  750. boolean
  751. phydm_nhm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
  752. {
  753. struct dm_struct *dm = (struct dm_struct *)dm_void;
  754. struct ccx_info *ccx = &dm->dm_ccx_info;
  755. struct nhm_para_info nhm_para = {0};
  756. boolean nhm_chk_result = false;
  757. u32 sys_return_time;
  758. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  759. if (ccx->nhm_manual_ctrl) {
  760. PHYDM_DBG(dm, DBG_ENV_MNTR, "NHM in manual ctrl\n");
  761. return nhm_chk_result;
  762. }
  763. sys_return_time = ccx->nhm_trigger_time + MAX_ENV_MNTR_TIME;
  764. if (ccx->nhm_app != NHM_BACKGROUND &&
  765. (sys_return_time > dm->phydm_sys_up_time)) {
  766. PHYDM_DBG(dm, DBG_ENV_MNTR,
  767. "nhm_app=%d, trigger_time %d, sys_time=%d\n",
  768. ccx->nhm_app, ccx->nhm_trigger_time,
  769. dm->phydm_sys_up_time);
  770. return nhm_chk_result;
  771. }
  772. /*@[NHM get result & calculate Utility----------------------------*/
  773. if (phydm_nhm_get_result(dm)) {
  774. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
  775. phydm_nhm_get_utility(dm);
  776. }
  777. /*@[NHM trigger]-------------------------------------------------*/
  778. nhm_para.incld_txon = NHM_EXCLUDE_TXON;
  779. nhm_para.incld_cca = NHM_EXCLUDE_CCA;
  780. nhm_para.div_opt = NHM_CNT_ALL;
  781. nhm_para.nhm_app = NHM_BACKGROUND;
  782. nhm_para.nhm_lv = NHM_LV_1;
  783. nhm_para.mntr_time = monitor_time;
  784. nhm_chk_result = phydm_nhm_mntr_set(dm, &nhm_para);
  785. return nhm_chk_result;
  786. }
  787. void phydm_nhm_init(void *dm_void)
  788. {
  789. struct dm_struct *dm = (struct dm_struct *)dm_void;
  790. struct ccx_info *ccx = &dm->dm_ccx_info;
  791. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  792. PHYDM_DBG(dm, DBG_ENV_MNTR, "cur_igi=0x%x\n",
  793. dm->dm_dig_table.cur_ig_value);
  794. ccx->nhm_app = NHM_BACKGROUND;
  795. ccx->nhm_igi = 0xff;
  796. /*Set NHM threshold*/
  797. ccx->nhm_ongoing = false;
  798. ccx->nhm_set_lv = NHM_RELEASE;
  799. if (phydm_nhm_th_update_chk(dm, ccx->nhm_app, &ccx->nhm_th[0],
  800. (u32 *)&ccx->nhm_igi))
  801. phydm_nhm_set_th_reg(dm);
  802. ccx->nhm_period = 0;
  803. ccx->nhm_include_cca = NHM_CCA_INIT;
  804. ccx->nhm_include_txon = NHM_TXON_INIT;
  805. ccx->nhm_divider_opt = NHM_CNT_INIT;
  806. ccx->nhm_manual_ctrl = 0;
  807. ccx->nhm_rpt_stamp = 0;
  808. }
  809. void phydm_nhm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
  810. u32 *_out_len)
  811. {
  812. struct dm_struct *dm = (struct dm_struct *)dm_void;
  813. struct ccx_info *ccx = &dm->dm_ccx_info;
  814. struct nhm_para_info nhm_para;
  815. char help[] = "-h";
  816. u32 var1[10] = {0};
  817. u32 used = *_used;
  818. u32 out_len = *_out_len;
  819. boolean nhm_rpt_success = true;
  820. u8 result_tmp = 0;
  821. u8 i;
  822. PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
  823. if ((strcmp(input[1], help) == 0)) {
  824. PDM_SNPF(out_len, used, output + used, out_len - used,
  825. "NHM Basic-Trigger 262ms: {1}\n");
  826. /* some old ic is not supported on NHM divider option */
  827. if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
  828. ODM_RTL8195A | ODM_RTL8192E)) {
  829. PDM_SNPF(out_len, used, output + used, out_len - used,
  830. "NHM Adv-Trigger: {2} {Include TXON} {Include CCA}\n{App} {LV} {0~262ms}\n");
  831. } else {
  832. PDM_SNPF(out_len, used, output + used, out_len - used,
  833. "NHM Adv-Trigger: {2} {Include TXON} {Include CCA}\n{0:Cnt_all, 1:Cnt valid} {App} {LV} {0~262ms}\n");
  834. }
  835. PDM_SNPF(out_len, used, output + used, out_len - used,
  836. "NHM Get Result: {100}\n");
  837. } else if (var1[0] == 100) { /*@Get NHM results*/
  838. PDM_SNPF(out_len, used, output + used, out_len - used,
  839. "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
  840. ccx->nhm_rpt_stamp);
  841. nhm_rpt_success = phydm_nhm_get_result(dm);
  842. if (nhm_rpt_success) {
  843. for (i = 0; i <= 11; i++) {
  844. result_tmp = ccx->nhm_result[i];
  845. PDM_SNPF(out_len, used, output + used,
  846. out_len - used,
  847. "nhm_rpt[%d] = %d (%d percent)\n",
  848. i, result_tmp,
  849. (((result_tmp * 100) + 128) >> 8));
  850. }
  851. } else {
  852. PDM_SNPF(out_len, used, output + used, out_len - used,
  853. "Get NHM_rpt Fail\n");
  854. }
  855. ccx->nhm_manual_ctrl = 0;
  856. } else { /*NMH trigger*/
  857. ccx->nhm_manual_ctrl = 1;
  858. /* some old ic is not supported on NHM divider option */
  859. if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
  860. ODM_RTL8195A | ODM_RTL8192E)) {
  861. for (i = 1; i < 6; i++) {
  862. if (input[i + 1]) {
  863. PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
  864. &var1[i]);
  865. }
  866. }
  867. } else {
  868. for (i = 1; i < 7; i++) {
  869. if (input[i + 1]) {
  870. PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL,
  871. &var1[i]);
  872. }
  873. }
  874. }
  875. if (var1[0] == 1) {
  876. nhm_para.incld_txon = NHM_EXCLUDE_TXON;
  877. nhm_para.incld_cca = NHM_EXCLUDE_CCA;
  878. nhm_para.div_opt = NHM_CNT_ALL;
  879. nhm_para.nhm_app = NHM_DBG;
  880. nhm_para.nhm_lv = NHM_LV_4;
  881. nhm_para.mntr_time = 262;
  882. } else {
  883. nhm_para.incld_txon = (enum nhm_option_txon_all)var1[1];
  884. nhm_para.incld_cca = (enum nhm_option_cca_all)var1[2];
  885. /* some old ic is not supported on NHM divider option */
  886. if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
  887. ODM_RTL8195A | ODM_RTL8192E)) {
  888. nhm_para.nhm_app = (enum nhm_application)
  889. var1[3];
  890. nhm_para.nhm_lv = (enum phydm_nhm_level)var1[4];
  891. nhm_para.mntr_time = (u16)var1[5];
  892. } else {
  893. nhm_para.div_opt = (enum nhm_divider_opt_all)
  894. var1[3];
  895. nhm_para.nhm_app = (enum nhm_application)
  896. var1[4];
  897. nhm_para.nhm_lv = (enum phydm_nhm_level)var1[5];
  898. nhm_para.mntr_time = (u16)var1[6];
  899. }
  900. }
  901. /* some old ic is not supported on NHM divider option */
  902. if (dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8723B |
  903. ODM_RTL8195A | ODM_RTL8192E)) {
  904. PDM_SNPF(out_len, used, output + used, out_len - used,
  905. "txon=%d, cca=%d, app=%d, lv=%d, time=%d ms\n",
  906. nhm_para.incld_txon, nhm_para.incld_cca,
  907. nhm_para.nhm_app, nhm_para.nhm_lv,
  908. nhm_para.mntr_time);
  909. } else {
  910. PDM_SNPF(out_len, used, output + used, out_len - used,
  911. "txon=%d, cca=%d, dev=%d, app=%d, lv=%d, time=%d ms\n",
  912. nhm_para.incld_txon, nhm_para.incld_cca,
  913. nhm_para.div_opt, nhm_para.nhm_app,
  914. nhm_para.nhm_lv, nhm_para.mntr_time);
  915. }
  916. if (phydm_nhm_mntr_set(dm, &nhm_para) == PHYDM_SET_SUCCESS)
  917. phydm_nhm_trigger(dm);
  918. PDM_SNPF(out_len, used, output + used, out_len - used,
  919. "IGI=0x%x, rpt_stamp=%d\n", ccx->nhm_igi,
  920. ccx->nhm_rpt_stamp);
  921. for (i = 0; i <= 10; i++) {
  922. PDM_SNPF(out_len, used, output + used, out_len - used,
  923. "NHM_th[%d] RSSI = %d\n", i,
  924. NTH_TH_2_RSSI(ccx->nhm_th[i]));
  925. }
  926. }
  927. *_used = used;
  928. *_out_len = out_len;
  929. }
  930. #endif /*@#ifdef NHM_SUPPORT*/
  931. #ifdef CLM_SUPPORT
  932. void phydm_clm_racing_release(void *dm_void)
  933. {
  934. struct dm_struct *dm = (struct dm_struct *)dm_void;
  935. struct ccx_info *ccx = &dm->dm_ccx_info;
  936. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  937. PHYDM_DBG(dm, DBG_ENV_MNTR, "lv:(%d)->(0)\n", ccx->clm_set_lv);
  938. ccx->clm_ongoing = false;
  939. ccx->clm_set_lv = CLM_RELEASE;
  940. ccx->clm_app = CLM_BACKGROUND;
  941. }
  942. u8 phydm_clm_racing_ctrl(void *dm_void, enum phydm_nhm_level clm_lv)
  943. {
  944. struct dm_struct *dm = (struct dm_struct *)dm_void;
  945. struct ccx_info *ccx = &dm->dm_ccx_info;
  946. u8 set_result = PHYDM_SET_SUCCESS;
  947. /*@acquire to control CLM API*/
  948. PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ongoing=%d, lv:(%d)->(%d)\n",
  949. ccx->clm_ongoing, ccx->clm_set_lv, clm_lv);
  950. if (ccx->clm_ongoing) {
  951. if (clm_lv <= ccx->clm_set_lv) {
  952. set_result = PHYDM_SET_FAIL;
  953. } else {
  954. phydm_ccx_hw_restart(dm);
  955. ccx->clm_ongoing = false;
  956. }
  957. }
  958. if (set_result)
  959. ccx->clm_set_lv = clm_lv;
  960. PHYDM_DBG(dm, DBG_ENV_MNTR, "clm racing success=%d\n", set_result);
  961. return set_result;
  962. }
  963. void phydm_clm_c2h_report_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
  964. {
  965. struct dm_struct *dm = (struct dm_struct *)dm_void;
  966. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  967. u8 clm_report = cmd_buf[0];
  968. /*@u8 clm_report_idx = cmd_buf[1];*/
  969. if (cmd_len >= 12)
  970. return;
  971. ccx_info->clm_fw_result_acc += clm_report;
  972. ccx_info->clm_fw_result_cnt++;
  973. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%d] clm_report= %d\n",
  974. ccx_info->clm_fw_result_cnt, clm_report);
  975. }
  976. void phydm_clm_h2c(void *dm_void, u16 obs_time, u8 fw_clm_en)
  977. {
  978. struct dm_struct *dm = (struct dm_struct *)dm_void;
  979. u8 h2c_val[H2C_MAX_LENGTH] = {0};
  980. u8 i = 0;
  981. u8 obs_time_idx = 0;
  982. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
  983. PHYDM_DBG(dm, DBG_ENV_MNTR, "obs_time_index=%d *4 us\n", obs_time);
  984. for (i = 1; i <= 16; i++) {
  985. if (obs_time & BIT(16 - i)) {
  986. obs_time_idx = 16 - i;
  987. break;
  988. }
  989. }
  990. #if 0
  991. obs_time = (2 ^ 16 - 1)~(2 ^ 15) => obs_time_idx = 15 (65535 ~32768)
  992. obs_time = (2 ^ 15 - 1)~(2 ^ 14) => obs_time_idx = 14
  993. ...
  994. ...
  995. ...
  996. obs_time = (2 ^ 1 - 1)~(2 ^ 0) => obs_time_idx = 0
  997. #endif
  998. h2c_val[0] = obs_time_idx | (((fw_clm_en) ? 1 : 0) << 7);
  999. h2c_val[1] = CLM_MAX_REPORT_TIME;
  1000. PHYDM_DBG(dm, DBG_ENV_MNTR, "PHYDM h2c[0x4d]=0x%x %x %x %x %x %x %x\n",
  1001. h2c_val[6], h2c_val[5], h2c_val[4], h2c_val[3], h2c_val[2],
  1002. h2c_val[1], h2c_val[0]);
  1003. odm_fill_h2c_cmd(dm, PHYDM_H2C_FW_CLM_MNTR, H2C_MAX_LENGTH, h2c_val);
  1004. }
  1005. void phydm_clm_setting(void *dm_void, u16 clm_period /*@4us sample 1 time*/)
  1006. {
  1007. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1008. struct ccx_info *ccx = &dm->dm_ccx_info;
  1009. if (ccx->clm_period != clm_period) {
  1010. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  1011. odm_set_bb_reg(dm, R_0x990, MASKLWORD, clm_period);
  1012. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1013. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  1014. odm_set_bb_reg(dm, R_0x1e40, MASKLWORD, clm_period);
  1015. #endif
  1016. else if (dm->support_ic_type & ODM_IC_11N_SERIES)
  1017. odm_set_bb_reg(dm, R_0x894, MASKLWORD, clm_period);
  1018. ccx->clm_period = clm_period;
  1019. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1020. "Update CLM period ((%d)) -> ((%d))\n",
  1021. ccx->clm_period, clm_period);
  1022. }
  1023. PHYDM_DBG(dm, DBG_ENV_MNTR, "Set CLM period=%d * 4us\n",
  1024. ccx->clm_period);
  1025. }
  1026. void phydm_clm_trigger(void *dm_void)
  1027. {
  1028. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1029. struct ccx_info *ccx = &dm->dm_ccx_info;
  1030. u32 reg1 = 0;
  1031. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  1032. reg1 = R_0x994;
  1033. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1034. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  1035. reg1 = R_0x1e60;
  1036. #endif
  1037. else
  1038. reg1 = R_0x890;
  1039. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  1040. odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
  1041. odm_set_bb_reg(dm, reg1, BIT(0), 0x1);
  1042. ccx->clm_trigger_time = dm->phydm_sys_up_time;
  1043. ccx->clm_rpt_stamp++;
  1044. ccx->clm_ongoing = true;
  1045. }
  1046. boolean
  1047. phydm_clm_check_rdy(void *dm_void)
  1048. {
  1049. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1050. boolean is_ready = false;
  1051. u32 reg1 = 0, reg1_bit = 0;
  1052. #if (ENV_MNTR_DBG)
  1053. u16 i;
  1054. u64 start_time, progressing_time;
  1055. #endif
  1056. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  1057. reg1 = ODM_REG_CLM_RESULT_11AC;
  1058. reg1_bit = 16;
  1059. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1060. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  1061. reg1 = R_0x2d88;
  1062. reg1_bit = 16;
  1063. #endif
  1064. } else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
  1065. if (dm->support_ic_type == ODM_RTL8710B) {
  1066. reg1 = R_0x8b4;
  1067. reg1_bit = 24;
  1068. } else {
  1069. reg1 = R_0x8b4;
  1070. reg1_bit = 16;
  1071. }
  1072. }
  1073. #if (ENV_MNTR_DBG)
  1074. start_time = odm_get_current_time(dm);
  1075. for (i = 0; i <= 400; i++) {
  1076. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit))) {
  1077. is_ready = true;
  1078. break;
  1079. }
  1080. ODM_delay_ms(1);
  1081. }
  1082. progressing_time = odm_get_progressing_time(dm, start_time);
  1083. PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM rdy=%d, i=%d, CLM_polling_time=%lld\n",
  1084. is_ready, i, progressing_time);
  1085. #else
  1086. if (odm_get_bb_reg(dm, reg1, BIT(reg1_bit)))
  1087. is_ready = true;
  1088. PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM rdy=%d\n", is_ready);
  1089. #endif
  1090. return is_ready;
  1091. }
  1092. void phydm_clm_get_utility(void *dm_void)
  1093. {
  1094. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1095. struct ccx_info *ccx = &dm->dm_ccx_info;
  1096. u32 clm_result_tmp;
  1097. if (ccx->clm_period == 0) {
  1098. PHYDM_DBG(dm, DBG_ENV_MNTR, "[warning] clm_period = 0\n");
  1099. ccx->clm_ratio = 0;
  1100. } else if (ccx->clm_period >= 65530) {
  1101. clm_result_tmp = (u32)(ccx->clm_result * 100);
  1102. ccx->clm_ratio = (u8)((clm_result_tmp + (1 << 15)) >> 16);
  1103. } else {
  1104. clm_result_tmp = (u32)(ccx->clm_result * 100);
  1105. ccx->clm_ratio = (u8)(clm_result_tmp / (u32)ccx->clm_period);
  1106. }
  1107. }
  1108. boolean
  1109. phydm_clm_get_result(void *dm_void)
  1110. {
  1111. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1112. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  1113. u32 reg1 = 0;
  1114. u32 val = 0;
  1115. if (dm->support_ic_type & ODM_IC_11AC_SERIES)
  1116. reg1 = R_0x994;
  1117. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1118. else if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
  1119. reg1 = R_0x1e60;
  1120. #endif
  1121. else
  1122. reg1 = R_0x890;
  1123. odm_set_bb_reg(dm, reg1, BIT(0), 0x0);
  1124. if (phydm_clm_check_rdy(dm) == false) {
  1125. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM report Fail\n");
  1126. phydm_clm_racing_release(dm);
  1127. return false;
  1128. }
  1129. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  1130. val = odm_get_bb_reg(dm, R_0xfa4, MASKLWORD);
  1131. ccx_info->clm_result = (u16)val;
  1132. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1133. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  1134. val = odm_get_bb_reg(dm, R_0x2d88, MASKLWORD);
  1135. ccx_info->clm_result = (u16)val;
  1136. #endif
  1137. } else if (dm->support_ic_type & ODM_IC_11N_SERIES) {
  1138. val = odm_get_bb_reg(dm, R_0x8d0, MASKLWORD);
  1139. ccx_info->clm_result = (u16)val;
  1140. }
  1141. PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM result = %d *4 us\n",
  1142. ccx_info->clm_result);
  1143. phydm_clm_racing_release(dm);
  1144. return true;
  1145. }
  1146. void phydm_clm_mntr_fw(void *dm_void, u16 monitor_time /*unit ms*/)
  1147. {
  1148. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1149. struct ccx_info *ccx = &dm->dm_ccx_info;
  1150. u32 val = 0;
  1151. /*@[Get CLM report]*/
  1152. if (ccx->clm_fw_result_cnt != 0) {
  1153. val = ccx->clm_fw_result_acc / ccx->clm_fw_result_cnt;
  1154. ccx->clm_ratio = (u8)val;
  1155. } else {
  1156. ccx->clm_ratio = 0;
  1157. }
  1158. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1159. "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
  1160. ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
  1161. ccx->clm_fw_result_acc = 0;
  1162. ccx->clm_fw_result_cnt = 0;
  1163. /*@[CLM trigger]*/
  1164. if (monitor_time >= 262)
  1165. ccx->clm_period = 65535;
  1166. else
  1167. ccx->clm_period = monitor_time * MS_TO_4US_RATIO;
  1168. phydm_clm_h2c(dm, monitor_time, true);
  1169. }
  1170. u8 phydm_clm_mntr_set(void *dm_void, struct clm_para_info *clm_para)
  1171. {
  1172. /*@Driver Monitor CLM*/
  1173. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1174. struct ccx_info *ccx = &dm->dm_ccx_info;
  1175. u16 clm_period = 0;
  1176. if (clm_para->mntr_time == 0)
  1177. return PHYDM_SET_FAIL;
  1178. if (clm_para->clm_lv >= CLM_MAX_NUM) {
  1179. PHYDM_DBG(dm, DBG_ENV_MNTR, "[WARNING] Wrong LV=%d\n",
  1180. clm_para->clm_lv);
  1181. return PHYDM_SET_FAIL;
  1182. }
  1183. if (phydm_clm_racing_ctrl(dm, clm_para->clm_lv) == PHYDM_SET_FAIL)
  1184. return PHYDM_SET_FAIL;
  1185. if (clm_para->mntr_time >= 262)
  1186. clm_period = CLM_PERIOD_MAX;
  1187. else
  1188. clm_period = clm_para->mntr_time * MS_TO_4US_RATIO;
  1189. ccx->clm_app = clm_para->clm_app;
  1190. phydm_clm_setting(dm, clm_period);
  1191. return PHYDM_SET_SUCCESS;
  1192. }
  1193. boolean
  1194. phydm_clm_mntr_chk(void *dm_void, u16 monitor_time /*unit ms*/)
  1195. {
  1196. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1197. struct ccx_info *ccx = &dm->dm_ccx_info;
  1198. struct clm_para_info clm_para = {0};
  1199. boolean clm_chk_result = false;
  1200. u32 sys_return_time = 0;
  1201. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
  1202. if (ccx->clm_manual_ctrl) {
  1203. PHYDM_DBG(dm, DBG_ENV_MNTR, "CLM in manual ctrl\n");
  1204. return clm_chk_result;
  1205. }
  1206. sys_return_time = ccx->clm_trigger_time + MAX_ENV_MNTR_TIME;
  1207. if (ccx->clm_app != CLM_BACKGROUND &&
  1208. sys_return_time > dm->phydm_sys_up_time) {
  1209. PHYDM_DBG(dm, DBG_ENV_MNTR, "trigger_time %d, sys_time=%d\n",
  1210. ccx->clm_trigger_time, dm->phydm_sys_up_time);
  1211. return clm_chk_result;
  1212. }
  1213. clm_para.clm_app = CLM_BACKGROUND;
  1214. clm_para.clm_lv = CLM_LV_1;
  1215. clm_para.mntr_time = monitor_time;
  1216. if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
  1217. /*@[Get CLM report]*/
  1218. if (phydm_clm_get_result(dm)) {
  1219. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
  1220. phydm_clm_get_utility(dm);
  1221. }
  1222. /*@[CLM trigger]----------------------------------------------*/
  1223. if (phydm_clm_mntr_set(dm, &clm_para) == PHYDM_SET_SUCCESS)
  1224. clm_chk_result = true;
  1225. } else {
  1226. #if 0
  1227. /*PHYDM_DBG(dm, DBG_ENV_MNTR, "enter clm_mntr_fw!!");*/
  1228. #endif
  1229. phydm_clm_mntr_fw(dm, monitor_time);
  1230. }
  1231. PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_ratio=%d\n", ccx->clm_ratio);
  1232. #if 0
  1233. /*PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_chk_result=%d\n",clm_chk_result);*/
  1234. #endif
  1235. return clm_chk_result;
  1236. }
  1237. void phydm_set_clm_mntr_mode(void *dm_void, enum clm_monitor_mode mode)
  1238. {
  1239. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1240. struct ccx_info *ccx_info = &dm->dm_ccx_info;
  1241. if (ccx_info->clm_mntr_mode != mode) {
  1242. ccx_info->clm_mntr_mode = mode;
  1243. phydm_ccx_hw_restart(dm);
  1244. if (mode == CLM_DRIVER_MNTR)
  1245. phydm_clm_h2c(dm, 0, 0);
  1246. }
  1247. }
  1248. void phydm_clm_init(void *dm_void)
  1249. {
  1250. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1251. struct ccx_info *ccx = &dm->dm_ccx_info;
  1252. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  1253. ccx->clm_ongoing = false;
  1254. ccx->clm_manual_ctrl = 0;
  1255. ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
  1256. ccx->clm_period = 0;
  1257. ccx->clm_rpt_stamp = 0;
  1258. phydm_clm_setting(dm, 65535);
  1259. }
  1260. void phydm_clm_dbg(void *dm_void, char input[][16], u32 *_used, char *output,
  1261. u32 *_out_len)
  1262. {
  1263. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1264. struct ccx_info *ccx = &dm->dm_ccx_info;
  1265. char help[] = "-h";
  1266. u32 var1[10] = {0};
  1267. u32 used = *_used;
  1268. u32 out_len = *_out_len;
  1269. struct clm_para_info clm_para = {0};
  1270. u32 i;
  1271. for (i = 0; i < 4; i++) {
  1272. if (input[i + 1])
  1273. PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]);
  1274. }
  1275. if ((strcmp(input[1], help) == 0)) {
  1276. PDM_SNPF(out_len, used, output + used, out_len - used,
  1277. "CLM Driver Basic-Trigger 262ms: {1}\n");
  1278. PDM_SNPF(out_len, used, output + used, out_len - used,
  1279. "CLM Driver Adv-Trigger: {2} {app} {LV} {0~262ms}\n");
  1280. PDM_SNPF(out_len, used, output + used, out_len - used,
  1281. "CLM FW Trigger: {3}\n");
  1282. PDM_SNPF(out_len, used, output + used, out_len - used,
  1283. "CLM Get Result: {100}\n");
  1284. } else if (var1[0] == 100) { /* @Get CLM results */
  1285. if (phydm_clm_get_result(dm))
  1286. phydm_clm_get_utility(dm);
  1287. PDM_SNPF(out_len, used, output + used, out_len - used,
  1288. "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
  1289. PDM_SNPF(out_len, used, output + used, out_len - used,
  1290. "clm_ratio:((%d percent)) = (%d us/ %d us)\n",
  1291. ccx->clm_ratio, ccx->clm_result << 2,
  1292. ccx->clm_period << 2);
  1293. ccx->clm_manual_ctrl = 0;
  1294. } else { /* Set & trigger CLM */
  1295. ccx->clm_manual_ctrl = 1;
  1296. if (var1[0] == 1) {
  1297. clm_para.clm_app = CLM_BACKGROUND;
  1298. clm_para.clm_lv = CLM_LV_4;
  1299. clm_para.mntr_time = 262;
  1300. ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
  1301. } else if (var1[0] == 2) {
  1302. clm_para.clm_app = (enum clm_application)var1[1];
  1303. clm_para.clm_lv = (enum phydm_clm_level)var1[2];
  1304. ccx->clm_mntr_mode = CLM_DRIVER_MNTR;
  1305. clm_para.mntr_time = (u16)var1[3];
  1306. } else if (var1[0] == 3) {
  1307. clm_para.clm_app = CLM_BACKGROUND;
  1308. clm_para.clm_lv = CLM_LV_4;
  1309. ccx->clm_mntr_mode = CLM_FW_MNTR;
  1310. clm_para.mntr_time = 262;
  1311. }
  1312. PDM_SNPF(out_len, used, output + used, out_len - used,
  1313. "app=%d, lv=%d, mode=%s, time=%d ms\n",
  1314. clm_para.clm_app, clm_para.clm_lv,
  1315. ((ccx->clm_mntr_mode == CLM_FW_MNTR) ? "FW" :
  1316. "driver"), clm_para.mntr_time);
  1317. if (phydm_clm_mntr_set(dm, &clm_para) == PHYDM_SET_SUCCESS)
  1318. phydm_clm_trigger(dm);
  1319. PDM_SNPF(out_len, used, output + used, out_len - used,
  1320. "clm_rpt_stamp=%d\n", ccx->clm_rpt_stamp);
  1321. }
  1322. *_used = used;
  1323. *_out_len = out_len;
  1324. }
  1325. #endif /*@#ifdef CLM_SUPPORT*/
  1326. u8 phydm_env_mntr_trigger(void *dm_void, struct nhm_para_info *nhm_para,
  1327. struct clm_para_info *clm_para,
  1328. struct env_trig_rpt *trig_rpt)
  1329. {
  1330. #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
  1331. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1332. struct ccx_info *ccx = &dm->dm_ccx_info;
  1333. boolean nhm_set_ok = false;
  1334. boolean clm_set_ok = false;
  1335. u8 trigger_result = 0;
  1336. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
  1337. #if (ENV_MNTR_DBG_2)
  1338. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  1339. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1340. "[DBG][2] 0xc50=0x%x, 0x994=0x%x, 0x998=0x%x\n",
  1341. odm_get_bb_reg(dm, 0xc50, MASKDWORD),
  1342. odm_get_bb_reg(dm, 0x994, MASKDWORD),
  1343. odm_get_bb_reg(dm, 0x998, MASKDWORD));
  1344. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1345. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  1346. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1347. "[DBG][2] 0x1d70=0x%x, 0x1e60=0x%x, 0x1e44=0x%x\n",
  1348. odm_get_bb_reg(dm, 0x1d70, MASKDWORD),
  1349. odm_get_bb_reg(dm, 0x1e60, MASKDWORD),
  1350. odm_get_bb_reg(dm, 0x1e44, MASKDWORD));
  1351. #endif
  1352. }
  1353. #endif
  1354. /*@[NHM]*/
  1355. nhm_set_ok = phydm_nhm_mntr_set(dm, nhm_para);
  1356. /*@[CLM]*/
  1357. if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
  1358. clm_set_ok = phydm_clm_mntr_set(dm, clm_para);
  1359. } else if (ccx->clm_mntr_mode == CLM_FW_MNTR) {
  1360. phydm_clm_h2c(dm, CLM_PERIOD_MAX, true);
  1361. trigger_result |= CLM_SUCCESS;
  1362. }
  1363. if (nhm_set_ok) {
  1364. phydm_nhm_trigger(dm);
  1365. trigger_result |= NHM_SUCCESS;
  1366. }
  1367. if (clm_set_ok) {
  1368. phydm_clm_trigger(dm);
  1369. trigger_result |= CLM_SUCCESS;
  1370. }
  1371. /*@monitor for the test duration*/
  1372. ccx->start_time = odm_get_current_time(dm);
  1373. trig_rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
  1374. trig_rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
  1375. PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n\n",
  1376. trig_rpt->nhm_rpt_stamp, trig_rpt->clm_rpt_stamp);
  1377. return trigger_result;
  1378. #endif
  1379. }
  1380. u8 phydm_env_mntr_result(void *dm_void, struct env_mntr_rpt *rpt)
  1381. {
  1382. #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
  1383. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1384. struct ccx_info *ccx = &dm->dm_ccx_info;
  1385. u8 env_mntr_rpt = 0;
  1386. u64 progressing_time;
  1387. u32 val_tmp = 0;
  1388. /*@monitor for the test duration*/
  1389. progressing_time = odm_get_progressing_time(dm, ccx->start_time);
  1390. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s] ======>\n", __func__);
  1391. PHYDM_DBG(dm, DBG_ENV_MNTR, "env_time=%lld\n", progressing_time);
  1392. #if (ENV_MNTR_DBG_2)
  1393. if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
  1394. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1395. "[DBG][2] 0xc50=0x%x, 0x994=0x%x, 0x998=0x%x\n",
  1396. odm_get_bb_reg(dm, 0xc50, MASKDWORD),
  1397. odm_get_bb_reg(dm, 0x994, MASKDWORD),
  1398. odm_get_bb_reg(dm, 0x998, MASKDWORD));
  1399. #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
  1400. } else if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
  1401. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1402. "[DBG][2] 0x1d70=0x%x, 0x1e60=0x%x, 0x1e44=0x%x\n",
  1403. odm_get_bb_reg(dm, 0x1d70, MASKDWORD),
  1404. odm_get_bb_reg(dm, 0x1e60, MASKDWORD),
  1405. odm_get_bb_reg(dm, 0x1e44, MASKDWORD));
  1406. #endif
  1407. }
  1408. #endif
  1409. /*@Get NHM result*/
  1410. if (phydm_nhm_get_result(dm)) {
  1411. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get NHM_rpt success\n");
  1412. phydm_nhm_get_utility(dm);
  1413. rpt->nhm_ratio = ccx->nhm_ratio;
  1414. env_mntr_rpt |= NHM_SUCCESS;
  1415. odm_move_memory(dm, &rpt->nhm_result[0],
  1416. &ccx->nhm_result[0], NHM_RPT_NUM);
  1417. } else {
  1418. rpt->nhm_ratio = ENV_MNTR_FAIL;
  1419. }
  1420. /*@Get CLM result*/
  1421. if (ccx->clm_mntr_mode == CLM_DRIVER_MNTR) {
  1422. if (phydm_clm_get_result(dm)) {
  1423. PHYDM_DBG(dm, DBG_ENV_MNTR, "Get CLM_rpt success\n");
  1424. phydm_clm_get_utility(dm);
  1425. env_mntr_rpt |= CLM_SUCCESS;
  1426. rpt->clm_ratio = ccx->clm_ratio;
  1427. } else {
  1428. rpt->clm_ratio = ENV_MNTR_FAIL;
  1429. }
  1430. } else {
  1431. if (ccx->clm_fw_result_cnt != 0) {
  1432. val_tmp = ccx->clm_fw_result_acc
  1433. / ccx->clm_fw_result_cnt;
  1434. ccx->clm_ratio = (u8)val_tmp;
  1435. } else {
  1436. ccx->clm_ratio = 0;
  1437. }
  1438. rpt->clm_ratio = ccx->clm_ratio;
  1439. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1440. "clm_fw_result_acc=%d, clm_fw_result_cnt=%d\n",
  1441. ccx->clm_fw_result_acc, ccx->clm_fw_result_cnt);
  1442. ccx->clm_fw_result_acc = 0;
  1443. ccx->clm_fw_result_cnt = 0;
  1444. env_mntr_rpt |= CLM_SUCCESS;
  1445. }
  1446. rpt->nhm_rpt_stamp = ccx->nhm_rpt_stamp;
  1447. rpt->clm_rpt_stamp = ccx->clm_rpt_stamp;
  1448. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1449. "IGI=0x%x, nhm_ratio=%d, clm_ratio=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n\n",
  1450. ccx->nhm_igi, rpt->nhm_ratio, rpt->clm_ratio,
  1451. rpt->nhm_rpt_stamp, rpt->clm_rpt_stamp);
  1452. return env_mntr_rpt;
  1453. #endif
  1454. }
  1455. /*@Environment Monitor*/
  1456. void phydm_env_mntr_watchdog(void *dm_void)
  1457. {
  1458. #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
  1459. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1460. struct ccx_info *ccx = &dm->dm_ccx_info;
  1461. boolean nhm_chk_ok = false;
  1462. boolean clm_chk_ok = false;
  1463. if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
  1464. return;
  1465. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  1466. nhm_chk_ok = phydm_nhm_mntr_chk(dm, 262); /*@monitor 262ms*/
  1467. clm_chk_ok = phydm_clm_mntr_chk(dm, 262); /*@monitor 262ms*/
  1468. #if 0
  1469. /*PHYDM_DBG(dm, DBG_ENV_MNTR, "nhm_chk_ok %d\n\n",nhm_chk_ok);*/
  1470. /*PHYDM_DBG(dm, DBG_ENV_MNTR, "clm_chk_ok %d\n\n",clm_chk_ok);*/
  1471. #endif
  1472. if (nhm_chk_ok)
  1473. phydm_nhm_trigger(dm);
  1474. if (clm_chk_ok)
  1475. phydm_clm_trigger(dm);
  1476. PHYDM_DBG(dm, DBG_ENV_MNTR,
  1477. "Summary: nhm_ratio=((%d)) clm_ratio=((%d))\n\n",
  1478. ccx->nhm_ratio, ccx->clm_ratio);
  1479. #endif
  1480. }
  1481. void phydm_env_monitor_init(void *dm_void)
  1482. {
  1483. #if (defined(NHM_SUPPORT) && defined(CLM_SUPPORT))
  1484. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1485. if (!(dm->support_ability & ODM_BB_ENV_MONITOR))
  1486. return;
  1487. PHYDM_DBG(dm, DBG_ENV_MNTR, "[%s]===>\n", __func__);
  1488. phydm_ccx_hw_restart(dm);
  1489. phydm_nhm_init(dm);
  1490. phydm_clm_init(dm);
  1491. #endif
  1492. }
  1493. void phydm_env_mntr_dbg(void *dm_void, char input[][16], u32 *_used,
  1494. char *output, u32 *_out_len)
  1495. {
  1496. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1497. char help[] = "-h";
  1498. u32 var1[10] = {0};
  1499. u32 used = *_used;
  1500. u32 out_len = *_out_len;
  1501. struct clm_para_info clm_para = {0};
  1502. struct nhm_para_info nhm_para = {0};
  1503. struct env_mntr_rpt rpt = {0};
  1504. struct env_trig_rpt trig_rpt = {0};
  1505. u8 set_result;
  1506. u8 i;
  1507. PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]);
  1508. if ((strcmp(input[1], help) == 0)) {
  1509. PDM_SNPF(out_len, used, output + used, out_len - used,
  1510. "Basic-Trigger 262ms: {1}\n");
  1511. PDM_SNPF(out_len, used, output + used, out_len - used,
  1512. "Get Result: {100}\n");
  1513. } else if (var1[0] == 100) { /* @Get CLM results */
  1514. set_result = phydm_env_mntr_result(dm, &rpt);
  1515. PDM_SNPF(out_len, used, output + used, out_len - used,
  1516. "Set Result=%d\n nhm_ratio=%d clm_ratio=%d\n nhm_rpt_stamp=%d, clm_rpt_stamp=%d,\n",
  1517. set_result, rpt.nhm_ratio, rpt.clm_ratio,
  1518. rpt.nhm_rpt_stamp, rpt.clm_rpt_stamp);
  1519. for (i = 0; i <= 11; i++) {
  1520. PDM_SNPF(out_len, used, output + used, out_len - used,
  1521. "nhm_rpt[%d] = %d (%d percent)\n", i,
  1522. rpt.nhm_result[i],
  1523. (((rpt.nhm_result[i] * 100) + 128) >> 8));
  1524. }
  1525. } else { /* Set & trigger CLM */
  1526. /*nhm para*/
  1527. nhm_para.incld_txon = NHM_EXCLUDE_TXON;
  1528. nhm_para.incld_cca = NHM_EXCLUDE_CCA;
  1529. nhm_para.div_opt = NHM_CNT_ALL;
  1530. nhm_para.nhm_app = NHM_ACS;
  1531. nhm_para.nhm_lv = NHM_LV_2;
  1532. nhm_para.mntr_time = 262;
  1533. /*@clm para*/
  1534. clm_para.clm_app = CLM_ACS;
  1535. clm_para.clm_lv = CLM_LV_2;
  1536. clm_para.mntr_time = 262;
  1537. set_result = phydm_env_mntr_trigger(dm, &nhm_para,
  1538. &clm_para, &trig_rpt);
  1539. PDM_SNPF(out_len, used, output + used, out_len - used,
  1540. "Set Result=%d, nhm_rpt_stamp=%d, clm_rpt_stamp=%d\n",
  1541. set_result, trig_rpt.nhm_rpt_stamp,
  1542. trig_rpt.clm_rpt_stamp);
  1543. }
  1544. *_used = used;
  1545. *_out_len = out_len;
  1546. }