calib.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255
  1. /*
  2. * Copyright (c) 2008-2009 Atheros Communications Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "hw.h"
  17. /* We can tune this as we go by monitoring really low values */
  18. #define ATH9K_NF_TOO_LOW -60
  19. /* AR5416 may return very high value (like -31 dBm), in those cases the nf
  20. * is incorrect and we should use the static NF value. Later we can try to
  21. * find out why they are reporting these values */
  22. static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
  23. {
  24. if (nf > ATH9K_NF_TOO_LOW) {
  25. ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
  26. "noise floor value detected (%d) is "
  27. "lower than what we think is a "
  28. "reasonable value (%d)\n",
  29. nf, ATH9K_NF_TOO_LOW);
  30. return false;
  31. }
  32. return true;
  33. }
  34. static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
  35. {
  36. int16_t nfval;
  37. int16_t sort[ATH9K_NF_CAL_HIST_MAX];
  38. int i, j;
  39. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
  40. sort[i] = nfCalBuffer[i];
  41. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
  42. for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
  43. if (sort[j] > sort[j - 1]) {
  44. nfval = sort[j];
  45. sort[j] = sort[j - 1];
  46. sort[j - 1] = nfval;
  47. }
  48. }
  49. }
  50. nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
  51. return nfval;
  52. }
  53. static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
  54. int16_t *nfarray)
  55. {
  56. int i;
  57. for (i = 0; i < NUM_NF_READINGS; i++) {
  58. h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
  59. if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
  60. h[i].currIndex = 0;
  61. if (h[i].invalidNFcount > 0) {
  62. if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
  63. nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
  64. h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
  65. } else {
  66. h[i].invalidNFcount--;
  67. h[i].privNF = nfarray[i];
  68. }
  69. } else {
  70. h[i].privNF =
  71. ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
  72. }
  73. }
  74. return;
  75. }
  76. static void ath9k_hw_do_getnf(struct ath_hw *ah,
  77. int16_t nfarray[NUM_NF_READINGS])
  78. {
  79. struct ath_common *common = ath9k_hw_common(ah);
  80. int16_t nf;
  81. if (AR_SREV_9280_10_OR_LATER(ah))
  82. nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
  83. else
  84. nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
  85. if (nf & 0x100)
  86. nf = 0 - ((nf ^ 0x1ff) + 1);
  87. ath_print(common, ATH_DBG_CALIBRATE,
  88. "NF calibrated [ctl] [chain 0] is %d\n", nf);
  89. nfarray[0] = nf;
  90. if (!AR_SREV_9285(ah)) {
  91. if (AR_SREV_9280_10_OR_LATER(ah))
  92. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  93. AR9280_PHY_CH1_MINCCA_PWR);
  94. else
  95. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  96. AR_PHY_CH1_MINCCA_PWR);
  97. if (nf & 0x100)
  98. nf = 0 - ((nf ^ 0x1ff) + 1);
  99. ath_print(common, ATH_DBG_CALIBRATE,
  100. "NF calibrated [ctl] [chain 1] is %d\n", nf);
  101. nfarray[1] = nf;
  102. if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
  103. nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
  104. AR_PHY_CH2_MINCCA_PWR);
  105. if (nf & 0x100)
  106. nf = 0 - ((nf ^ 0x1ff) + 1);
  107. ath_print(common, ATH_DBG_CALIBRATE,
  108. "NF calibrated [ctl] [chain 2] is %d\n", nf);
  109. nfarray[2] = nf;
  110. }
  111. }
  112. if (AR_SREV_9280_10_OR_LATER(ah))
  113. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  114. AR9280_PHY_EXT_MINCCA_PWR);
  115. else
  116. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  117. AR_PHY_EXT_MINCCA_PWR);
  118. if (nf & 0x100)
  119. nf = 0 - ((nf ^ 0x1ff) + 1);
  120. ath_print(common, ATH_DBG_CALIBRATE,
  121. "NF calibrated [ext] [chain 0] is %d\n", nf);
  122. nfarray[3] = nf;
  123. if (!AR_SREV_9285(ah)) {
  124. if (AR_SREV_9280_10_OR_LATER(ah))
  125. nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
  126. AR9280_PHY_CH1_EXT_MINCCA_PWR);
  127. else
  128. nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
  129. AR_PHY_CH1_EXT_MINCCA_PWR);
  130. if (nf & 0x100)
  131. nf = 0 - ((nf ^ 0x1ff) + 1);
  132. ath_print(common, ATH_DBG_CALIBRATE,
  133. "NF calibrated [ext] [chain 1] is %d\n", nf);
  134. nfarray[4] = nf;
  135. if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
  136. nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
  137. AR_PHY_CH2_EXT_MINCCA_PWR);
  138. if (nf & 0x100)
  139. nf = 0 - ((nf ^ 0x1ff) + 1);
  140. ath_print(common, ATH_DBG_CALIBRATE,
  141. "NF calibrated [ext] [chain 2] is %d\n", nf);
  142. nfarray[5] = nf;
  143. }
  144. }
  145. }
  146. static bool getNoiseFloorThresh(struct ath_hw *ah,
  147. enum ieee80211_band band,
  148. int16_t *nft)
  149. {
  150. switch (band) {
  151. case IEEE80211_BAND_5GHZ:
  152. *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
  153. break;
  154. case IEEE80211_BAND_2GHZ:
  155. *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
  156. break;
  157. default:
  158. BUG_ON(1);
  159. return false;
  160. }
  161. return true;
  162. }
  163. static void ath9k_hw_setup_calibration(struct ath_hw *ah,
  164. struct ath9k_cal_list *currCal)
  165. {
  166. struct ath_common *common = ath9k_hw_common(ah);
  167. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
  168. AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
  169. currCal->calData->calCountMax);
  170. switch (currCal->calData->calType) {
  171. case IQ_MISMATCH_CAL:
  172. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
  173. ath_print(common, ATH_DBG_CALIBRATE,
  174. "starting IQ Mismatch Calibration\n");
  175. break;
  176. case ADC_GAIN_CAL:
  177. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
  178. ath_print(common, ATH_DBG_CALIBRATE,
  179. "starting ADC Gain Calibration\n");
  180. break;
  181. case ADC_DC_CAL:
  182. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
  183. ath_print(common, ATH_DBG_CALIBRATE,
  184. "starting ADC DC Calibration\n");
  185. break;
  186. case ADC_DC_INIT_CAL:
  187. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
  188. ath_print(common, ATH_DBG_CALIBRATE,
  189. "starting Init ADC DC Calibration\n");
  190. break;
  191. }
  192. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  193. AR_PHY_TIMING_CTRL4_DO_CAL);
  194. }
  195. static void ath9k_hw_reset_calibration(struct ath_hw *ah,
  196. struct ath9k_cal_list *currCal)
  197. {
  198. int i;
  199. ath9k_hw_setup_calibration(ah, currCal);
  200. currCal->calState = CAL_RUNNING;
  201. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  202. ah->meas0.sign[i] = 0;
  203. ah->meas1.sign[i] = 0;
  204. ah->meas2.sign[i] = 0;
  205. ah->meas3.sign[i] = 0;
  206. }
  207. ah->cal_samples = 0;
  208. }
  209. static bool ath9k_hw_per_calibration(struct ath_hw *ah,
  210. struct ath9k_channel *ichan,
  211. u8 rxchainmask,
  212. struct ath9k_cal_list *currCal)
  213. {
  214. bool iscaldone = false;
  215. if (currCal->calState == CAL_RUNNING) {
  216. if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
  217. AR_PHY_TIMING_CTRL4_DO_CAL)) {
  218. currCal->calData->calCollect(ah);
  219. ah->cal_samples++;
  220. if (ah->cal_samples >= currCal->calData->calNumSamples) {
  221. int i, numChains = 0;
  222. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  223. if (rxchainmask & (1 << i))
  224. numChains++;
  225. }
  226. currCal->calData->calPostProc(ah, numChains);
  227. ichan->CalValid |= currCal->calData->calType;
  228. currCal->calState = CAL_DONE;
  229. iscaldone = true;
  230. } else {
  231. ath9k_hw_setup_calibration(ah, currCal);
  232. }
  233. }
  234. } else if (!(ichan->CalValid & currCal->calData->calType)) {
  235. ath9k_hw_reset_calibration(ah, currCal);
  236. }
  237. return iscaldone;
  238. }
  239. /* Assumes you are talking about the currently configured channel */
  240. static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
  241. enum ath9k_cal_types calType)
  242. {
  243. struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
  244. switch (calType & ah->supp_cals) {
  245. case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
  246. return true;
  247. case ADC_GAIN_CAL:
  248. case ADC_DC_CAL:
  249. if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
  250. conf_is_ht20(conf)))
  251. return true;
  252. break;
  253. }
  254. return false;
  255. }
  256. static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
  257. {
  258. int i;
  259. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  260. ah->totalPowerMeasI[i] +=
  261. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  262. ah->totalPowerMeasQ[i] +=
  263. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  264. ah->totalIqCorrMeas[i] +=
  265. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  266. ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
  267. "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
  268. ah->cal_samples, i, ah->totalPowerMeasI[i],
  269. ah->totalPowerMeasQ[i],
  270. ah->totalIqCorrMeas[i]);
  271. }
  272. }
  273. static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
  274. {
  275. int i;
  276. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  277. ah->totalAdcIOddPhase[i] +=
  278. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  279. ah->totalAdcIEvenPhase[i] +=
  280. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  281. ah->totalAdcQOddPhase[i] +=
  282. REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  283. ah->totalAdcQEvenPhase[i] +=
  284. REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  285. ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
  286. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  287. "oddq=0x%08x; evenq=0x%08x;\n",
  288. ah->cal_samples, i,
  289. ah->totalAdcIOddPhase[i],
  290. ah->totalAdcIEvenPhase[i],
  291. ah->totalAdcQOddPhase[i],
  292. ah->totalAdcQEvenPhase[i]);
  293. }
  294. }
  295. static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
  296. {
  297. int i;
  298. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  299. ah->totalAdcDcOffsetIOddPhase[i] +=
  300. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  301. ah->totalAdcDcOffsetIEvenPhase[i] +=
  302. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  303. ah->totalAdcDcOffsetQOddPhase[i] +=
  304. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  305. ah->totalAdcDcOffsetQEvenPhase[i] +=
  306. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  307. ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
  308. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  309. "oddq=0x%08x; evenq=0x%08x;\n",
  310. ah->cal_samples, i,
  311. ah->totalAdcDcOffsetIOddPhase[i],
  312. ah->totalAdcDcOffsetIEvenPhase[i],
  313. ah->totalAdcDcOffsetQOddPhase[i],
  314. ah->totalAdcDcOffsetQEvenPhase[i]);
  315. }
  316. }
  317. static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
  318. {
  319. struct ath_common *common = ath9k_hw_common(ah);
  320. u32 powerMeasQ, powerMeasI, iqCorrMeas;
  321. u32 qCoffDenom, iCoffDenom;
  322. int32_t qCoff, iCoff;
  323. int iqCorrNeg, i;
  324. for (i = 0; i < numChains; i++) {
  325. powerMeasI = ah->totalPowerMeasI[i];
  326. powerMeasQ = ah->totalPowerMeasQ[i];
  327. iqCorrMeas = ah->totalIqCorrMeas[i];
  328. ath_print(common, ATH_DBG_CALIBRATE,
  329. "Starting IQ Cal and Correction for Chain %d\n",
  330. i);
  331. ath_print(common, ATH_DBG_CALIBRATE,
  332. "Orignal: Chn %diq_corr_meas = 0x%08x\n",
  333. i, ah->totalIqCorrMeas[i]);
  334. iqCorrNeg = 0;
  335. if (iqCorrMeas > 0x80000000) {
  336. iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
  337. iqCorrNeg = 1;
  338. }
  339. ath_print(common, ATH_DBG_CALIBRATE,
  340. "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
  341. ath_print(common, ATH_DBG_CALIBRATE,
  342. "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
  343. ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
  344. iqCorrNeg);
  345. iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
  346. qCoffDenom = powerMeasQ / 64;
  347. if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
  348. (qCoffDenom != 0)) {
  349. iCoff = iqCorrMeas / iCoffDenom;
  350. qCoff = powerMeasI / qCoffDenom - 64;
  351. ath_print(common, ATH_DBG_CALIBRATE,
  352. "Chn %d iCoff = 0x%08x\n", i, iCoff);
  353. ath_print(common, ATH_DBG_CALIBRATE,
  354. "Chn %d qCoff = 0x%08x\n", i, qCoff);
  355. iCoff = iCoff & 0x3f;
  356. ath_print(common, ATH_DBG_CALIBRATE,
  357. "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
  358. if (iqCorrNeg == 0x0)
  359. iCoff = 0x40 - iCoff;
  360. if (qCoff > 15)
  361. qCoff = 15;
  362. else if (qCoff <= -16)
  363. qCoff = 16;
  364. ath_print(common, ATH_DBG_CALIBRATE,
  365. "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
  366. i, iCoff, qCoff);
  367. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  368. AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
  369. iCoff);
  370. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  371. AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
  372. qCoff);
  373. ath_print(common, ATH_DBG_CALIBRATE,
  374. "IQ Cal and Correction done for Chain %d\n",
  375. i);
  376. }
  377. }
  378. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  379. AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
  380. }
  381. static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
  382. {
  383. struct ath_common *common = ath9k_hw_common(ah);
  384. u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
  385. u32 qGainMismatch, iGainMismatch, val, i;
  386. for (i = 0; i < numChains; i++) {
  387. iOddMeasOffset = ah->totalAdcIOddPhase[i];
  388. iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
  389. qOddMeasOffset = ah->totalAdcQOddPhase[i];
  390. qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
  391. ath_print(common, ATH_DBG_CALIBRATE,
  392. "Starting ADC Gain Cal for Chain %d\n", i);
  393. ath_print(common, ATH_DBG_CALIBRATE,
  394. "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
  395. iOddMeasOffset);
  396. ath_print(common, ATH_DBG_CALIBRATE,
  397. "Chn %d pwr_meas_even_i = 0x%08x\n", i,
  398. iEvenMeasOffset);
  399. ath_print(common, ATH_DBG_CALIBRATE,
  400. "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
  401. qOddMeasOffset);
  402. ath_print(common, ATH_DBG_CALIBRATE,
  403. "Chn %d pwr_meas_even_q = 0x%08x\n", i,
  404. qEvenMeasOffset);
  405. if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
  406. iGainMismatch =
  407. ((iEvenMeasOffset * 32) /
  408. iOddMeasOffset) & 0x3f;
  409. qGainMismatch =
  410. ((qOddMeasOffset * 32) /
  411. qEvenMeasOffset) & 0x3f;
  412. ath_print(common, ATH_DBG_CALIBRATE,
  413. "Chn %d gain_mismatch_i = 0x%08x\n", i,
  414. iGainMismatch);
  415. ath_print(common, ATH_DBG_CALIBRATE,
  416. "Chn %d gain_mismatch_q = 0x%08x\n", i,
  417. qGainMismatch);
  418. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  419. val &= 0xfffff000;
  420. val |= (qGainMismatch) | (iGainMismatch << 6);
  421. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  422. ath_print(common, ATH_DBG_CALIBRATE,
  423. "ADC Gain Cal done for Chain %d\n", i);
  424. }
  425. }
  426. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  427. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  428. AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
  429. }
  430. static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
  431. {
  432. struct ath_common *common = ath9k_hw_common(ah);
  433. u32 iOddMeasOffset, iEvenMeasOffset, val, i;
  434. int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
  435. const struct ath9k_percal_data *calData =
  436. ah->cal_list_curr->calData;
  437. u32 numSamples =
  438. (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
  439. for (i = 0; i < numChains; i++) {
  440. iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
  441. iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
  442. qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
  443. qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
  444. ath_print(common, ATH_DBG_CALIBRATE,
  445. "Starting ADC DC Offset Cal for Chain %d\n", i);
  446. ath_print(common, ATH_DBG_CALIBRATE,
  447. "Chn %d pwr_meas_odd_i = %d\n", i,
  448. iOddMeasOffset);
  449. ath_print(common, ATH_DBG_CALIBRATE,
  450. "Chn %d pwr_meas_even_i = %d\n", i,
  451. iEvenMeasOffset);
  452. ath_print(common, ATH_DBG_CALIBRATE,
  453. "Chn %d pwr_meas_odd_q = %d\n", i,
  454. qOddMeasOffset);
  455. ath_print(common, ATH_DBG_CALIBRATE,
  456. "Chn %d pwr_meas_even_q = %d\n", i,
  457. qEvenMeasOffset);
  458. iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
  459. numSamples) & 0x1ff;
  460. qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
  461. numSamples) & 0x1ff;
  462. ath_print(common, ATH_DBG_CALIBRATE,
  463. "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
  464. iDcMismatch);
  465. ath_print(common, ATH_DBG_CALIBRATE,
  466. "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
  467. qDcMismatch);
  468. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  469. val &= 0xc0000fff;
  470. val |= (qDcMismatch << 12) | (iDcMismatch << 21);
  471. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  472. ath_print(common, ATH_DBG_CALIBRATE,
  473. "ADC DC Offset Cal done for Chain %d\n", i);
  474. }
  475. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  476. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  477. AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
  478. }
  479. /* This is done for the currently configured channel */
  480. bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
  481. {
  482. struct ath_common *common = ath9k_hw_common(ah);
  483. struct ieee80211_conf *conf = &common->hw->conf;
  484. struct ath9k_cal_list *currCal = ah->cal_list_curr;
  485. if (!ah->curchan)
  486. return true;
  487. if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
  488. return true;
  489. if (currCal == NULL)
  490. return true;
  491. if (currCal->calState != CAL_DONE) {
  492. ath_print(common, ATH_DBG_CALIBRATE,
  493. "Calibration state incorrect, %d\n",
  494. currCal->calState);
  495. return true;
  496. }
  497. if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
  498. return true;
  499. ath_print(common, ATH_DBG_CALIBRATE,
  500. "Resetting Cal %d state for channel %u\n",
  501. currCal->calData->calType, conf->channel->center_freq);
  502. ah->curchan->CalValid &= ~currCal->calData->calType;
  503. currCal->calState = CAL_WAITING;
  504. return false;
  505. }
  506. EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
  507. void ath9k_hw_start_nfcal(struct ath_hw *ah)
  508. {
  509. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  510. AR_PHY_AGC_CONTROL_ENABLE_NF);
  511. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  512. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  513. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  514. }
  515. void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
  516. {
  517. struct ath9k_nfcal_hist *h;
  518. int i, j;
  519. int32_t val;
  520. const u32 ar5416_cca_regs[6] = {
  521. AR_PHY_CCA,
  522. AR_PHY_CH1_CCA,
  523. AR_PHY_CH2_CCA,
  524. AR_PHY_EXT_CCA,
  525. AR_PHY_CH1_EXT_CCA,
  526. AR_PHY_CH2_EXT_CCA
  527. };
  528. u8 chainmask, rx_chain_status;
  529. rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
  530. if (AR_SREV_9285(ah))
  531. chainmask = 0x9;
  532. else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
  533. if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
  534. chainmask = 0x1B;
  535. else
  536. chainmask = 0x09;
  537. } else {
  538. if (rx_chain_status & 0x4)
  539. chainmask = 0x3F;
  540. else if (rx_chain_status & 0x2)
  541. chainmask = 0x1B;
  542. else
  543. chainmask = 0x09;
  544. }
  545. h = ah->nfCalHist;
  546. for (i = 0; i < NUM_NF_READINGS; i++) {
  547. if (chainmask & (1 << i)) {
  548. val = REG_READ(ah, ar5416_cca_regs[i]);
  549. val &= 0xFFFFFE00;
  550. val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
  551. REG_WRITE(ah, ar5416_cca_regs[i], val);
  552. }
  553. }
  554. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  555. AR_PHY_AGC_CONTROL_ENABLE_NF);
  556. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  557. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  558. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  559. for (j = 0; j < 5; j++) {
  560. if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
  561. AR_PHY_AGC_CONTROL_NF) == 0)
  562. break;
  563. udelay(50);
  564. }
  565. for (i = 0; i < NUM_NF_READINGS; i++) {
  566. if (chainmask & (1 << i)) {
  567. val = REG_READ(ah, ar5416_cca_regs[i]);
  568. val &= 0xFFFFFE00;
  569. val |= (((u32) (-50) << 1) & 0x1ff);
  570. REG_WRITE(ah, ar5416_cca_regs[i], val);
  571. }
  572. }
  573. }
  574. int16_t ath9k_hw_getnf(struct ath_hw *ah,
  575. struct ath9k_channel *chan)
  576. {
  577. struct ath_common *common = ath9k_hw_common(ah);
  578. int16_t nf, nfThresh;
  579. int16_t nfarray[NUM_NF_READINGS] = { 0 };
  580. struct ath9k_nfcal_hist *h;
  581. struct ieee80211_channel *c = chan->chan;
  582. chan->channelFlags &= (~CHANNEL_CW_INT);
  583. if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
  584. ath_print(common, ATH_DBG_CALIBRATE,
  585. "NF did not complete in calibration window\n");
  586. nf = 0;
  587. chan->rawNoiseFloor = nf;
  588. return chan->rawNoiseFloor;
  589. } else {
  590. ath9k_hw_do_getnf(ah, nfarray);
  591. nf = nfarray[0];
  592. if (getNoiseFloorThresh(ah, c->band, &nfThresh)
  593. && nf > nfThresh) {
  594. ath_print(common, ATH_DBG_CALIBRATE,
  595. "noise floor failed detected; "
  596. "detected %d, threshold %d\n",
  597. nf, nfThresh);
  598. chan->channelFlags |= CHANNEL_CW_INT;
  599. }
  600. }
  601. h = ah->nfCalHist;
  602. ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
  603. chan->rawNoiseFloor = h[0].privNF;
  604. return chan->rawNoiseFloor;
  605. }
  606. void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
  607. {
  608. int i, j;
  609. s16 noise_floor;
  610. if (AR_SREV_9280(ah))
  611. noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
  612. else if (AR_SREV_9285(ah))
  613. noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
  614. else if (AR_SREV_9287(ah))
  615. noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
  616. else
  617. noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
  618. for (i = 0; i < NUM_NF_READINGS; i++) {
  619. ah->nfCalHist[i].currIndex = 0;
  620. ah->nfCalHist[i].privNF = noise_floor;
  621. ah->nfCalHist[i].invalidNFcount =
  622. AR_PHY_CCA_FILTERWINDOW_LENGTH;
  623. for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
  624. ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
  625. }
  626. }
  627. }
  628. s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
  629. {
  630. s16 nf;
  631. if (chan->rawNoiseFloor == 0)
  632. nf = -96;
  633. else
  634. nf = chan->rawNoiseFloor;
  635. if (!ath9k_hw_nf_in_range(ah, nf))
  636. nf = ATH_DEFAULT_NOISE_FLOOR;
  637. return nf;
  638. }
  639. EXPORT_SYMBOL(ath9k_hw_getchan_noise);
  640. static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah)
  641. {
  642. u32 rddata;
  643. int32_t delta, currPDADC, slope;
  644. rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
  645. currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
  646. if (ah->initPDADC == 0 || currPDADC == 0) {
  647. /*
  648. * Zero value indicates that no frames have been transmitted yet,
  649. * can't do temperature compensation until frames are transmitted.
  650. */
  651. return;
  652. } else {
  653. slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
  654. if (slope == 0) { /* to avoid divide by zero case */
  655. delta = 0;
  656. } else {
  657. delta = ((currPDADC - ah->initPDADC)*4) / slope;
  658. }
  659. REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
  660. AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
  661. REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
  662. AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
  663. }
  664. }
  665. static void ath9k_olc_temp_compensation(struct ath_hw *ah)
  666. {
  667. u32 rddata, i;
  668. int delta, currPDADC, regval;
  669. if (OLC_FOR_AR9287_10_LATER) {
  670. ath9k_olc_temp_compensation_9287(ah);
  671. } else {
  672. rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
  673. currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
  674. if (ah->initPDADC == 0 || currPDADC == 0) {
  675. return;
  676. } else {
  677. if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
  678. delta = (currPDADC - ah->initPDADC + 4) / 8;
  679. else
  680. delta = (currPDADC - ah->initPDADC + 5) / 10;
  681. if (delta != ah->PDADCdelta) {
  682. ah->PDADCdelta = delta;
  683. for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
  684. regval = ah->originalGain[i] - delta;
  685. if (regval < 0)
  686. regval = 0;
  687. REG_RMW_FIELD(ah,
  688. AR_PHY_TX_GAIN_TBL1 + i * 4,
  689. AR_PHY_TX_GAIN, regval);
  690. }
  691. }
  692. }
  693. }
  694. }
  695. static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset)
  696. {
  697. u32 regVal;
  698. unsigned int i;
  699. u32 regList [][2] = {
  700. { 0x786c, 0 },
  701. { 0x7854, 0 },
  702. { 0x7820, 0 },
  703. { 0x7824, 0 },
  704. { 0x7868, 0 },
  705. { 0x783c, 0 },
  706. { 0x7838, 0 } ,
  707. { 0x7828, 0 } ,
  708. };
  709. for (i = 0; i < ARRAY_SIZE(regList); i++)
  710. regList[i][1] = REG_READ(ah, regList[i][0]);
  711. regVal = REG_READ(ah, 0x7834);
  712. regVal &= (~(0x1));
  713. REG_WRITE(ah, 0x7834, regVal);
  714. regVal = REG_READ(ah, 0x9808);
  715. regVal |= (0x1 << 27);
  716. REG_WRITE(ah, 0x9808, regVal);
  717. /* 786c,b23,1, pwddac=1 */
  718. REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
  719. /* 7854, b5,1, pdrxtxbb=1 */
  720. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
  721. /* 7854, b7,1, pdv2i=1 */
  722. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
  723. /* 7854, b8,1, pddacinterface=1 */
  724. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
  725. /* 7824,b12,0, offcal=0 */
  726. REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
  727. /* 7838, b1,0, pwddb=0 */
  728. REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
  729. /* 7820,b11,0, enpacal=0 */
  730. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
  731. /* 7820,b25,1, pdpadrv1=0 */
  732. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
  733. /* 7820,b24,0, pdpadrv2=0 */
  734. REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
  735. /* 7820,b23,0, pdpaout=0 */
  736. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
  737. /* 783c,b14-16,7, padrvgn2tab_0=7 */
  738. REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
  739. /*
  740. * 7838,b29-31,0, padrvgn1tab_0=0
  741. * does not matter since we turn it off
  742. */
  743. REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
  744. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
  745. /* Set:
  746. * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
  747. * txon=1,paon=1,oscon=1,synthon_force=1
  748. */
  749. REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
  750. udelay(30);
  751. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
  752. /* find off_6_1; */
  753. for (i = 6; i > 0; i--) {
  754. regVal = REG_READ(ah, 0x7834);
  755. regVal |= (1 << (20 + i));
  756. REG_WRITE(ah, 0x7834, regVal);
  757. udelay(1);
  758. //regVal = REG_READ(ah, 0x7834);
  759. regVal &= (~(0x1 << (20 + i)));
  760. regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
  761. << (20 + i));
  762. REG_WRITE(ah, 0x7834, regVal);
  763. }
  764. regVal = (regVal >>20) & 0x7f;
  765. /* Update PA cal info */
  766. if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
  767. if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
  768. ah->pacal_info.max_skipcount =
  769. 2 * ah->pacal_info.max_skipcount;
  770. ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
  771. } else {
  772. ah->pacal_info.max_skipcount = 1;
  773. ah->pacal_info.skipcount = 0;
  774. ah->pacal_info.prev_offset = regVal;
  775. }
  776. regVal = REG_READ(ah, 0x7834);
  777. regVal |= 0x1;
  778. REG_WRITE(ah, 0x7834, regVal);
  779. regVal = REG_READ(ah, 0x9808);
  780. regVal &= (~(0x1 << 27));
  781. REG_WRITE(ah, 0x9808, regVal);
  782. for (i = 0; i < ARRAY_SIZE(regList); i++)
  783. REG_WRITE(ah, regList[i][0], regList[i][1]);
  784. }
  785. static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
  786. {
  787. struct ath_common *common = ath9k_hw_common(ah);
  788. u32 regVal;
  789. int i, offset, offs_6_1, offs_0;
  790. u32 ccomp_org, reg_field;
  791. u32 regList[][2] = {
  792. { 0x786c, 0 },
  793. { 0x7854, 0 },
  794. { 0x7820, 0 },
  795. { 0x7824, 0 },
  796. { 0x7868, 0 },
  797. { 0x783c, 0 },
  798. { 0x7838, 0 },
  799. };
  800. ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
  801. /* PA CAL is not needed for high power solution */
  802. if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
  803. AR5416_EEP_TXGAIN_HIGH_POWER)
  804. return;
  805. if (AR_SREV_9285_11(ah)) {
  806. REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
  807. udelay(10);
  808. }
  809. for (i = 0; i < ARRAY_SIZE(regList); i++)
  810. regList[i][1] = REG_READ(ah, regList[i][0]);
  811. regVal = REG_READ(ah, 0x7834);
  812. regVal &= (~(0x1));
  813. REG_WRITE(ah, 0x7834, regVal);
  814. regVal = REG_READ(ah, 0x9808);
  815. regVal |= (0x1 << 27);
  816. REG_WRITE(ah, 0x9808, regVal);
  817. REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
  818. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
  819. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
  820. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
  821. REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
  822. REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
  823. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
  824. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
  825. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
  826. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
  827. REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
  828. REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
  829. ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
  830. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
  831. REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
  832. udelay(30);
  833. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
  834. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
  835. for (i = 6; i > 0; i--) {
  836. regVal = REG_READ(ah, 0x7834);
  837. regVal |= (1 << (19 + i));
  838. REG_WRITE(ah, 0x7834, regVal);
  839. udelay(1);
  840. regVal = REG_READ(ah, 0x7834);
  841. regVal &= (~(0x1 << (19 + i)));
  842. reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
  843. regVal |= (reg_field << (19 + i));
  844. REG_WRITE(ah, 0x7834, regVal);
  845. }
  846. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
  847. udelay(1);
  848. reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
  849. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
  850. offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
  851. offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
  852. offset = (offs_6_1<<1) | offs_0;
  853. offset = offset - 0;
  854. offs_6_1 = offset>>1;
  855. offs_0 = offset & 1;
  856. if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
  857. if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
  858. ah->pacal_info.max_skipcount =
  859. 2 * ah->pacal_info.max_skipcount;
  860. ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
  861. } else {
  862. ah->pacal_info.max_skipcount = 1;
  863. ah->pacal_info.skipcount = 0;
  864. ah->pacal_info.prev_offset = offset;
  865. }
  866. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
  867. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
  868. regVal = REG_READ(ah, 0x7834);
  869. regVal |= 0x1;
  870. REG_WRITE(ah, 0x7834, regVal);
  871. regVal = REG_READ(ah, 0x9808);
  872. regVal &= (~(0x1 << 27));
  873. REG_WRITE(ah, 0x9808, regVal);
  874. for (i = 0; i < ARRAY_SIZE(regList); i++)
  875. REG_WRITE(ah, regList[i][0], regList[i][1]);
  876. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
  877. if (AR_SREV_9285_11(ah))
  878. REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
  879. }
  880. bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
  881. u8 rxchainmask, bool longcal)
  882. {
  883. bool iscaldone = true;
  884. struct ath9k_cal_list *currCal = ah->cal_list_curr;
  885. if (currCal &&
  886. (currCal->calState == CAL_RUNNING ||
  887. currCal->calState == CAL_WAITING)) {
  888. iscaldone = ath9k_hw_per_calibration(ah, chan,
  889. rxchainmask, currCal);
  890. if (iscaldone) {
  891. ah->cal_list_curr = currCal = currCal->calNext;
  892. if (currCal->calState == CAL_WAITING) {
  893. iscaldone = false;
  894. ath9k_hw_reset_calibration(ah, currCal);
  895. }
  896. }
  897. }
  898. /* Do NF cal only at longer intervals */
  899. if (longcal) {
  900. /* Do periodic PAOffset Cal */
  901. if (AR_SREV_9271(ah))
  902. ath9k_hw_9271_pa_cal(ah, false);
  903. else if (AR_SREV_9285_11_OR_LATER(ah)) {
  904. if (!ah->pacal_info.skipcount)
  905. ath9k_hw_9285_pa_cal(ah, false);
  906. else
  907. ah->pacal_info.skipcount--;
  908. }
  909. if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
  910. ath9k_olc_temp_compensation(ah);
  911. /* Get the value from the previous NF cal and update history buffer */
  912. ath9k_hw_getnf(ah, chan);
  913. /*
  914. * Load the NF from history buffer of the current channel.
  915. * NF is slow time-variant, so it is OK to use a historical value.
  916. */
  917. ath9k_hw_loadnf(ah, ah->curchan);
  918. ath9k_hw_start_nfcal(ah);
  919. }
  920. return iscaldone;
  921. }
  922. EXPORT_SYMBOL(ath9k_hw_calibrate);
  923. /* Carrier leakage Calibration fix */
  924. static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
  925. {
  926. struct ath_common *common = ath9k_hw_common(ah);
  927. REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
  928. if (IS_CHAN_HT20(chan)) {
  929. REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
  930. REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
  931. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  932. AR_PHY_AGC_CONTROL_FLTR_CAL);
  933. REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
  934. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
  935. if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
  936. AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
  937. ath_print(common, ATH_DBG_CALIBRATE, "offset "
  938. "calibration failed to complete in "
  939. "1ms; noisy ??\n");
  940. return false;
  941. }
  942. REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
  943. REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
  944. REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
  945. }
  946. REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
  947. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
  948. REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
  949. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
  950. if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
  951. 0, AH_WAIT_TIMEOUT)) {
  952. ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
  953. "failed to complete in 1ms; noisy ??\n");
  954. return false;
  955. }
  956. REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
  957. REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
  958. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
  959. return true;
  960. }
  961. bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
  962. {
  963. struct ath_common *common = ath9k_hw_common(ah);
  964. if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
  965. if (!ar9285_clc(ah, chan))
  966. return false;
  967. } else {
  968. if (AR_SREV_9280_10_OR_LATER(ah)) {
  969. if (!AR_SREV_9287_10_OR_LATER(ah))
  970. REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
  971. AR_PHY_ADC_CTL_OFF_PWDADC);
  972. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  973. AR_PHY_AGC_CONTROL_FLTR_CAL);
  974. }
  975. /* Calibrate the AGC */
  976. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  977. REG_READ(ah, AR_PHY_AGC_CONTROL) |
  978. AR_PHY_AGC_CONTROL_CAL);
  979. /* Poll for offset calibration complete */
  980. if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
  981. 0, AH_WAIT_TIMEOUT)) {
  982. ath_print(common, ATH_DBG_CALIBRATE,
  983. "offset calibration failed to "
  984. "complete in 1ms; noisy environment?\n");
  985. return false;
  986. }
  987. if (AR_SREV_9280_10_OR_LATER(ah)) {
  988. if (!AR_SREV_9287_10_OR_LATER(ah))
  989. REG_SET_BIT(ah, AR_PHY_ADC_CTL,
  990. AR_PHY_ADC_CTL_OFF_PWDADC);
  991. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  992. AR_PHY_AGC_CONTROL_FLTR_CAL);
  993. }
  994. }
  995. /* Do PA Calibration */
  996. if (AR_SREV_9271(ah))
  997. ath9k_hw_9271_pa_cal(ah, true);
  998. else if (AR_SREV_9285_11_OR_LATER(ah))
  999. ath9k_hw_9285_pa_cal(ah, true);
  1000. /* Do NF Calibration after DC offset and other calibrations */
  1001. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  1002. REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
  1003. ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
  1004. /* Enable IQ, ADC Gain and ADC DC offset CALs */
  1005. if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
  1006. if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
  1007. INIT_CAL(&ah->adcgain_caldata);
  1008. INSERT_CAL(ah, &ah->adcgain_caldata);
  1009. ath_print(common, ATH_DBG_CALIBRATE,
  1010. "enabling ADC Gain Calibration.\n");
  1011. }
  1012. if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
  1013. INIT_CAL(&ah->adcdc_caldata);
  1014. INSERT_CAL(ah, &ah->adcdc_caldata);
  1015. ath_print(common, ATH_DBG_CALIBRATE,
  1016. "enabling ADC DC Calibration.\n");
  1017. }
  1018. if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
  1019. INIT_CAL(&ah->iq_caldata);
  1020. INSERT_CAL(ah, &ah->iq_caldata);
  1021. ath_print(common, ATH_DBG_CALIBRATE,
  1022. "enabling IQ Calibration.\n");
  1023. }
  1024. ah->cal_list_curr = ah->cal_list;
  1025. if (ah->cal_list_curr)
  1026. ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
  1027. }
  1028. chan->CalValid = 0;
  1029. return true;
  1030. }
  1031. const struct ath9k_percal_data iq_cal_multi_sample = {
  1032. IQ_MISMATCH_CAL,
  1033. MAX_CAL_SAMPLES,
  1034. PER_MIN_LOG_COUNT,
  1035. ath9k_hw_iqcal_collect,
  1036. ath9k_hw_iqcalibrate
  1037. };
  1038. const struct ath9k_percal_data iq_cal_single_sample = {
  1039. IQ_MISMATCH_CAL,
  1040. MIN_CAL_SAMPLES,
  1041. PER_MAX_LOG_COUNT,
  1042. ath9k_hw_iqcal_collect,
  1043. ath9k_hw_iqcalibrate
  1044. };
  1045. const struct ath9k_percal_data adc_gain_cal_multi_sample = {
  1046. ADC_GAIN_CAL,
  1047. MAX_CAL_SAMPLES,
  1048. PER_MIN_LOG_COUNT,
  1049. ath9k_hw_adc_gaincal_collect,
  1050. ath9k_hw_adc_gaincal_calibrate
  1051. };
  1052. const struct ath9k_percal_data adc_gain_cal_single_sample = {
  1053. ADC_GAIN_CAL,
  1054. MIN_CAL_SAMPLES,
  1055. PER_MAX_LOG_COUNT,
  1056. ath9k_hw_adc_gaincal_collect,
  1057. ath9k_hw_adc_gaincal_calibrate
  1058. };
  1059. const struct ath9k_percal_data adc_dc_cal_multi_sample = {
  1060. ADC_DC_CAL,
  1061. MAX_CAL_SAMPLES,
  1062. PER_MIN_LOG_COUNT,
  1063. ath9k_hw_adc_dccal_collect,
  1064. ath9k_hw_adc_dccal_calibrate
  1065. };
  1066. const struct ath9k_percal_data adc_dc_cal_single_sample = {
  1067. ADC_DC_CAL,
  1068. MIN_CAL_SAMPLES,
  1069. PER_MAX_LOG_COUNT,
  1070. ath9k_hw_adc_dccal_collect,
  1071. ath9k_hw_adc_dccal_calibrate
  1072. };
  1073. const struct ath9k_percal_data adc_init_dc_cal = {
  1074. ADC_DC_INIT_CAL,
  1075. MIN_CAL_SAMPLES,
  1076. INIT_LOG_COUNT,
  1077. ath9k_hw_adc_dccal_collect,
  1078. ath9k_hw_adc_dccal_calibrate
  1079. };