calib.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. /*
  2. * Copyright (c) 2008 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 "core.h"
  17. #include "hw.h"
  18. #include "reg.h"
  19. #include "phy.h"
  20. static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
  21. /* We can tune this as we go by monitoring really low values */
  22. #define ATH9K_NF_TOO_LOW -60
  23. /* AR5416 may return very high value (like -31 dBm), in those cases the nf
  24. * is incorrect and we should use the static NF value. Later we can try to
  25. * find out why they are reporting these values */
  26. static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
  27. {
  28. if (nf > ATH9K_NF_TOO_LOW) {
  29. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  30. "%s: noise floor value detected (%d) is "
  31. "lower than what we think is a "
  32. "reasonable value (%d)\n",
  33. __func__, nf, ATH9K_NF_TOO_LOW);
  34. return false;
  35. }
  36. return true;
  37. }
  38. static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
  39. {
  40. int16_t nfval;
  41. int16_t sort[ATH9K_NF_CAL_HIST_MAX];
  42. int i, j;
  43. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
  44. sort[i] = nfCalBuffer[i];
  45. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
  46. for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
  47. if (sort[j] > sort[j - 1]) {
  48. nfval = sort[j];
  49. sort[j] = sort[j - 1];
  50. sort[j - 1] = nfval;
  51. }
  52. }
  53. }
  54. nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
  55. return nfval;
  56. }
  57. static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
  58. int16_t *nfarray)
  59. {
  60. int i;
  61. for (i = 0; i < NUM_NF_READINGS; i++) {
  62. h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
  63. if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
  64. h[i].currIndex = 0;
  65. if (h[i].invalidNFcount > 0) {
  66. if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
  67. nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
  68. h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
  69. } else {
  70. h[i].invalidNFcount--;
  71. h[i].privNF = nfarray[i];
  72. }
  73. } else {
  74. h[i].privNF =
  75. ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
  76. }
  77. }
  78. return;
  79. }
  80. static void ath9k_hw_do_getnf(struct ath_hal *ah,
  81. int16_t nfarray[NUM_NF_READINGS])
  82. {
  83. int16_t nf;
  84. if (AR_SREV_9280_10_OR_LATER(ah))
  85. nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
  86. else
  87. nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
  88. if (nf & 0x100)
  89. nf = 0 - ((nf ^ 0x1ff) + 1);
  90. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  91. "NF calibrated [ctl] [chain 0] is %d\n", nf);
  92. nfarray[0] = nf;
  93. if (AR_SREV_9280_10_OR_LATER(ah))
  94. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  95. AR9280_PHY_CH1_MINCCA_PWR);
  96. else
  97. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  98. AR_PHY_CH1_MINCCA_PWR);
  99. if (nf & 0x100)
  100. nf = 0 - ((nf ^ 0x1ff) + 1);
  101. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  102. "NF calibrated [ctl] [chain 1] is %d\n", nf);
  103. nfarray[1] = nf;
  104. if (!AR_SREV_9280(ah)) {
  105. nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
  106. AR_PHY_CH2_MINCCA_PWR);
  107. if (nf & 0x100)
  108. nf = 0 - ((nf ^ 0x1ff) + 1);
  109. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  110. "NF calibrated [ctl] [chain 2] is %d\n", nf);
  111. nfarray[2] = nf;
  112. }
  113. if (AR_SREV_9280_10_OR_LATER(ah))
  114. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  115. AR9280_PHY_EXT_MINCCA_PWR);
  116. else
  117. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  118. AR_PHY_EXT_MINCCA_PWR);
  119. if (nf & 0x100)
  120. nf = 0 - ((nf ^ 0x1ff) + 1);
  121. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  122. "NF calibrated [ext] [chain 0] is %d\n", nf);
  123. nfarray[3] = nf;
  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. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  133. "NF calibrated [ext] [chain 1] is %d\n", nf);
  134. nfarray[4] = nf;
  135. if (!AR_SREV_9280(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. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  141. "NF calibrated [ext] [chain 2] is %d\n", nf);
  142. nfarray[5] = nf;
  143. }
  144. }
  145. static bool getNoiseFloorThresh(struct ath_hal *ah,
  146. const struct ath9k_channel *chan,
  147. int16_t *nft)
  148. {
  149. switch (chan->chanmode) {
  150. case CHANNEL_A:
  151. case CHANNEL_A_HT20:
  152. case CHANNEL_A_HT40PLUS:
  153. case CHANNEL_A_HT40MINUS:
  154. *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
  155. break;
  156. case CHANNEL_B:
  157. case CHANNEL_G:
  158. case CHANNEL_G_HT20:
  159. case CHANNEL_G_HT40PLUS:
  160. case CHANNEL_G_HT40MINUS:
  161. *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
  162. break;
  163. default:
  164. DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
  165. "%s: invalid channel flags 0x%x\n", __func__,
  166. chan->channelFlags);
  167. return false;
  168. }
  169. return true;
  170. }
  171. static void ath9k_hw_setup_calibration(struct ath_hal *ah,
  172. struct hal_cal_list *currCal)
  173. {
  174. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
  175. AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
  176. currCal->calData->calCountMax);
  177. switch (currCal->calData->calType) {
  178. case IQ_MISMATCH_CAL:
  179. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
  180. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  181. "%s: starting IQ Mismatch Calibration\n",
  182. __func__);
  183. break;
  184. case ADC_GAIN_CAL:
  185. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
  186. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  187. "%s: starting ADC Gain Calibration\n", __func__);
  188. break;
  189. case ADC_DC_CAL:
  190. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
  191. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  192. "%s: starting ADC DC Calibration\n", __func__);
  193. break;
  194. case ADC_DC_INIT_CAL:
  195. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
  196. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  197. "%s: starting Init ADC DC Calibration\n",
  198. __func__);
  199. break;
  200. }
  201. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  202. AR_PHY_TIMING_CTRL4_DO_CAL);
  203. }
  204. static void ath9k_hw_reset_calibration(struct ath_hal *ah,
  205. struct hal_cal_list *currCal)
  206. {
  207. struct ath_hal_5416 *ahp = AH5416(ah);
  208. int i;
  209. ath9k_hw_setup_calibration(ah, currCal);
  210. currCal->calState = CAL_RUNNING;
  211. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  212. ahp->ah_Meas0.sign[i] = 0;
  213. ahp->ah_Meas1.sign[i] = 0;
  214. ahp->ah_Meas2.sign[i] = 0;
  215. ahp->ah_Meas3.sign[i] = 0;
  216. }
  217. ahp->ah_CalSamples = 0;
  218. }
  219. static void ath9k_hw_per_calibration(struct ath_hal *ah,
  220. struct ath9k_channel *ichan,
  221. u8 rxchainmask,
  222. struct hal_cal_list *currCal,
  223. bool *isCalDone)
  224. {
  225. struct ath_hal_5416 *ahp = AH5416(ah);
  226. *isCalDone = false;
  227. if (currCal->calState == CAL_RUNNING) {
  228. if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
  229. AR_PHY_TIMING_CTRL4_DO_CAL)) {
  230. currCal->calData->calCollect(ah);
  231. ahp->ah_CalSamples++;
  232. if (ahp->ah_CalSamples >= currCal->calData->calNumSamples) {
  233. int i, numChains = 0;
  234. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  235. if (rxchainmask & (1 << i))
  236. numChains++;
  237. }
  238. currCal->calData->calPostProc(ah, numChains);
  239. ichan->CalValid |= currCal->calData->calType;
  240. currCal->calState = CAL_DONE;
  241. *isCalDone = true;
  242. } else {
  243. ath9k_hw_setup_calibration(ah, currCal);
  244. }
  245. }
  246. } else if (!(ichan->CalValid & currCal->calData->calType)) {
  247. ath9k_hw_reset_calibration(ah, currCal);
  248. }
  249. }
  250. static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
  251. struct ath9k_channel *chan,
  252. enum hal_cal_types calType)
  253. {
  254. struct ath_hal_5416 *ahp = AH5416(ah);
  255. bool retval = false;
  256. switch (calType & ahp->ah_suppCals) {
  257. case IQ_MISMATCH_CAL:
  258. if (!IS_CHAN_B(chan))
  259. retval = true;
  260. break;
  261. case ADC_GAIN_CAL:
  262. case ADC_DC_CAL:
  263. if (!IS_CHAN_B(chan)
  264. && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
  265. retval = true;
  266. break;
  267. }
  268. return retval;
  269. }
  270. static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
  271. {
  272. struct ath_hal_5416 *ahp = AH5416(ah);
  273. int i;
  274. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  275. ahp->ah_totalPowerMeasI[i] +=
  276. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  277. ahp->ah_totalPowerMeasQ[i] +=
  278. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  279. ahp->ah_totalIqCorrMeas[i] +=
  280. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  281. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  282. "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
  283. ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
  284. ahp->ah_totalPowerMeasQ[i],
  285. ahp->ah_totalIqCorrMeas[i]);
  286. }
  287. }
  288. static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
  289. {
  290. struct ath_hal_5416 *ahp = AH5416(ah);
  291. int i;
  292. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  293. ahp->ah_totalAdcIOddPhase[i] +=
  294. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  295. ahp->ah_totalAdcIEvenPhase[i] +=
  296. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  297. ahp->ah_totalAdcQOddPhase[i] +=
  298. REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  299. ahp->ah_totalAdcQEvenPhase[i] +=
  300. REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  301. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  302. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  303. "oddq=0x%08x; evenq=0x%08x;\n",
  304. ahp->ah_CalSamples, i,
  305. ahp->ah_totalAdcIOddPhase[i],
  306. ahp->ah_totalAdcIEvenPhase[i],
  307. ahp->ah_totalAdcQOddPhase[i],
  308. ahp->ah_totalAdcQEvenPhase[i]);
  309. }
  310. }
  311. static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
  312. {
  313. struct ath_hal_5416 *ahp = AH5416(ah);
  314. int i;
  315. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  316. ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
  317. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  318. ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
  319. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  320. ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
  321. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  322. ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
  323. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  324. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  325. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  326. "oddq=0x%08x; evenq=0x%08x;\n",
  327. ahp->ah_CalSamples, i,
  328. ahp->ah_totalAdcDcOffsetIOddPhase[i],
  329. ahp->ah_totalAdcDcOffsetIEvenPhase[i],
  330. ahp->ah_totalAdcDcOffsetQOddPhase[i],
  331. ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
  332. }
  333. }
  334. static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
  335. {
  336. struct ath_hal_5416 *ahp = AH5416(ah);
  337. u32 powerMeasQ, powerMeasI, iqCorrMeas;
  338. u32 qCoffDenom, iCoffDenom;
  339. int32_t qCoff, iCoff;
  340. int iqCorrNeg, i;
  341. for (i = 0; i < numChains; i++) {
  342. powerMeasI = ahp->ah_totalPowerMeasI[i];
  343. powerMeasQ = ahp->ah_totalPowerMeasQ[i];
  344. iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
  345. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  346. "Starting IQ Cal and Correction for Chain %d\n",
  347. i);
  348. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  349. "Orignal: Chn %diq_corr_meas = 0x%08x\n",
  350. i, ahp->ah_totalIqCorrMeas[i]);
  351. iqCorrNeg = 0;
  352. if (iqCorrMeas > 0x80000000) {
  353. iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
  354. iqCorrNeg = 1;
  355. }
  356. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  357. "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
  358. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  359. "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
  360. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
  361. iqCorrNeg);
  362. iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
  363. qCoffDenom = powerMeasQ / 64;
  364. if (powerMeasQ != 0) {
  365. iCoff = iqCorrMeas / iCoffDenom;
  366. qCoff = powerMeasI / qCoffDenom - 64;
  367. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  368. "Chn %d iCoff = 0x%08x\n", i, iCoff);
  369. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  370. "Chn %d qCoff = 0x%08x\n", i, qCoff);
  371. iCoff = iCoff & 0x3f;
  372. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  373. "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
  374. if (iqCorrNeg == 0x0)
  375. iCoff = 0x40 - iCoff;
  376. if (qCoff > 15)
  377. qCoff = 15;
  378. else if (qCoff <= -16)
  379. qCoff = 16;
  380. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  381. "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
  382. i, iCoff, qCoff);
  383. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  384. AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
  385. iCoff);
  386. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  387. AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
  388. qCoff);
  389. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  390. "IQ Cal and Correction done for Chain %d\n",
  391. i);
  392. }
  393. }
  394. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  395. AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
  396. }
  397. static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
  398. {
  399. struct ath_hal_5416 *ahp = AH5416(ah);
  400. u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
  401. u32 qGainMismatch, iGainMismatch, val, i;
  402. for (i = 0; i < numChains; i++) {
  403. iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
  404. iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
  405. qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
  406. qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
  407. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  408. "Starting ADC Gain Cal for Chain %d\n", i);
  409. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  410. "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
  411. iOddMeasOffset);
  412. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  413. "Chn %d pwr_meas_even_i = 0x%08x\n", i,
  414. iEvenMeasOffset);
  415. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  416. "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
  417. qOddMeasOffset);
  418. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  419. "Chn %d pwr_meas_even_q = 0x%08x\n", i,
  420. qEvenMeasOffset);
  421. if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
  422. iGainMismatch =
  423. ((iEvenMeasOffset * 32) /
  424. iOddMeasOffset) & 0x3f;
  425. qGainMismatch =
  426. ((qOddMeasOffset * 32) /
  427. qEvenMeasOffset) & 0x3f;
  428. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  429. "Chn %d gain_mismatch_i = 0x%08x\n", i,
  430. iGainMismatch);
  431. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  432. "Chn %d gain_mismatch_q = 0x%08x\n", i,
  433. qGainMismatch);
  434. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  435. val &= 0xfffff000;
  436. val |= (qGainMismatch) | (iGainMismatch << 6);
  437. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  438. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  439. "ADC Gain Cal done for Chain %d\n", i);
  440. }
  441. }
  442. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  443. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  444. AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
  445. }
  446. static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
  447. {
  448. struct ath_hal_5416 *ahp = AH5416(ah);
  449. u32 iOddMeasOffset, iEvenMeasOffset, val, i;
  450. int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
  451. const struct hal_percal_data *calData =
  452. ahp->ah_cal_list_curr->calData;
  453. u32 numSamples =
  454. (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
  455. for (i = 0; i < numChains; i++) {
  456. iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
  457. iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
  458. qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
  459. qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
  460. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  461. "Starting ADC DC Offset Cal for Chain %d\n", i);
  462. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  463. "Chn %d pwr_meas_odd_i = %d\n", i,
  464. iOddMeasOffset);
  465. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  466. "Chn %d pwr_meas_even_i = %d\n", i,
  467. iEvenMeasOffset);
  468. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  469. "Chn %d pwr_meas_odd_q = %d\n", i,
  470. qOddMeasOffset);
  471. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  472. "Chn %d pwr_meas_even_q = %d\n", i,
  473. qEvenMeasOffset);
  474. iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
  475. numSamples) & 0x1ff;
  476. qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
  477. numSamples) & 0x1ff;
  478. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  479. "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
  480. iDcMismatch);
  481. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  482. "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
  483. qDcMismatch);
  484. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  485. val &= 0xc0000fff;
  486. val |= (qDcMismatch << 12) | (iDcMismatch << 21);
  487. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  488. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  489. "ADC DC Offset Cal done for Chain %d\n", i);
  490. }
  491. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  492. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  493. AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
  494. }
  495. void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
  496. bool *isCalDone)
  497. {
  498. struct ath_hal_5416 *ahp = AH5416(ah);
  499. struct ath9k_channel *ichan =
  500. ath9k_regd_check_channel(ah, chan);
  501. struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
  502. *isCalDone = true;
  503. if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
  504. return;
  505. if (currCal == NULL)
  506. return;
  507. if (ichan == NULL) {
  508. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  509. "%s: invalid channel %u/0x%x; no mapping\n",
  510. __func__, chan->channel, chan->channelFlags);
  511. return;
  512. }
  513. if (currCal->calState != CAL_DONE) {
  514. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  515. "%s: Calibration state incorrect, %d\n",
  516. __func__, currCal->calState);
  517. return;
  518. }
  519. if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
  520. return;
  521. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  522. "%s: Resetting Cal %d state for channel %u/0x%x\n",
  523. __func__, currCal->calData->calType, chan->channel,
  524. chan->channelFlags);
  525. ichan->CalValid &= ~currCal->calData->calType;
  526. currCal->calState = CAL_WAITING;
  527. *isCalDone = false;
  528. }
  529. void ath9k_hw_start_nfcal(struct ath_hal *ah)
  530. {
  531. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  532. AR_PHY_AGC_CONTROL_ENABLE_NF);
  533. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  534. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  535. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  536. }
  537. void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
  538. {
  539. struct ath9k_nfcal_hist *h;
  540. int i, j;
  541. int32_t val;
  542. const u32 ar5416_cca_regs[6] = {
  543. AR_PHY_CCA,
  544. AR_PHY_CH1_CCA,
  545. AR_PHY_CH2_CCA,
  546. AR_PHY_EXT_CCA,
  547. AR_PHY_CH1_EXT_CCA,
  548. AR_PHY_CH2_EXT_CCA
  549. };
  550. u8 chainmask;
  551. if (AR_SREV_9280(ah))
  552. chainmask = 0x1B;
  553. else
  554. chainmask = 0x3F;
  555. #ifdef ATH_NF_PER_CHAN
  556. h = chan->nfCalHist;
  557. #else
  558. h = ah->nfCalHist;
  559. #endif
  560. for (i = 0; i < NUM_NF_READINGS; i++) {
  561. if (chainmask & (1 << i)) {
  562. val = REG_READ(ah, ar5416_cca_regs[i]);
  563. val &= 0xFFFFFE00;
  564. val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
  565. REG_WRITE(ah, ar5416_cca_regs[i], val);
  566. }
  567. }
  568. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  569. AR_PHY_AGC_CONTROL_ENABLE_NF);
  570. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  571. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  572. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  573. for (j = 0; j < 1000; j++) {
  574. if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
  575. AR_PHY_AGC_CONTROL_NF) == 0)
  576. break;
  577. udelay(10);
  578. }
  579. for (i = 0; i < NUM_NF_READINGS; i++) {
  580. if (chainmask & (1 << i)) {
  581. val = REG_READ(ah, ar5416_cca_regs[i]);
  582. val &= 0xFFFFFE00;
  583. val |= (((u32) (-50) << 1) & 0x1ff);
  584. REG_WRITE(ah, ar5416_cca_regs[i], val);
  585. }
  586. }
  587. }
  588. int16_t ath9k_hw_getnf(struct ath_hal *ah,
  589. struct ath9k_channel *chan)
  590. {
  591. int16_t nf, nfThresh;
  592. int16_t nfarray[NUM_NF_READINGS] = { 0 };
  593. struct ath9k_nfcal_hist *h;
  594. u8 chainmask;
  595. if (AR_SREV_9280(ah))
  596. chainmask = 0x1B;
  597. else
  598. chainmask = 0x3F;
  599. chan->channelFlags &= (~CHANNEL_CW_INT);
  600. if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
  601. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  602. "%s: NF did not complete in calibration window\n",
  603. __func__);
  604. nf = 0;
  605. chan->rawNoiseFloor = nf;
  606. return chan->rawNoiseFloor;
  607. } else {
  608. ath9k_hw_do_getnf(ah, nfarray);
  609. nf = nfarray[0];
  610. if (getNoiseFloorThresh(ah, chan, &nfThresh)
  611. && nf > nfThresh) {
  612. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  613. "%s: noise floor failed detected; "
  614. "detected %d, threshold %d\n", __func__,
  615. nf, nfThresh);
  616. chan->channelFlags |= CHANNEL_CW_INT;
  617. }
  618. }
  619. #ifdef ATH_NF_PER_CHAN
  620. h = chan->nfCalHist;
  621. #else
  622. h = ah->nfCalHist;
  623. #endif
  624. ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
  625. chan->rawNoiseFloor = h[0].privNF;
  626. return chan->rawNoiseFloor;
  627. }
  628. void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
  629. {
  630. int i, j;
  631. for (i = 0; i < NUM_NF_READINGS; i++) {
  632. ah->nfCalHist[i].currIndex = 0;
  633. ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
  634. ah->nfCalHist[i].invalidNFcount =
  635. AR_PHY_CCA_FILTERWINDOW_LENGTH;
  636. for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
  637. ah->nfCalHist[i].nfCalBuffer[j] =
  638. AR_PHY_CCA_MAX_GOOD_VALUE;
  639. }
  640. }
  641. return;
  642. }
  643. s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
  644. {
  645. struct ath9k_channel *ichan;
  646. s16 nf;
  647. ichan = ath9k_regd_check_channel(ah, chan);
  648. if (ichan == NULL) {
  649. DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
  650. "%s: invalid channel %u/0x%x; no mapping\n",
  651. __func__, chan->channel, chan->channelFlags);
  652. return ATH_DEFAULT_NOISE_FLOOR;
  653. }
  654. if (ichan->rawNoiseFloor == 0) {
  655. enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
  656. nf = NOISE_FLOOR[mode];
  657. } else
  658. nf = ichan->rawNoiseFloor;
  659. if (!ath9k_hw_nf_in_range(ah, nf))
  660. nf = ATH_DEFAULT_NOISE_FLOOR;
  661. return nf;
  662. }
  663. bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
  664. u8 rxchainmask, bool longcal,
  665. bool *isCalDone)
  666. {
  667. struct ath_hal_5416 *ahp = AH5416(ah);
  668. struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
  669. struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
  670. *isCalDone = true;
  671. if (ichan == NULL) {
  672. DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
  673. "%s: invalid channel %u/0x%x; no mapping\n",
  674. __func__, chan->channel, chan->channelFlags);
  675. return false;
  676. }
  677. if (currCal &&
  678. (currCal->calState == CAL_RUNNING ||
  679. currCal->calState == CAL_WAITING)) {
  680. ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
  681. isCalDone);
  682. if (*isCalDone) {
  683. ahp->ah_cal_list_curr = currCal = currCal->calNext;
  684. if (currCal->calState == CAL_WAITING) {
  685. *isCalDone = false;
  686. ath9k_hw_reset_calibration(ah, currCal);
  687. }
  688. }
  689. }
  690. if (longcal) {
  691. ath9k_hw_getnf(ah, ichan);
  692. ath9k_hw_loadnf(ah, ah->ah_curchan);
  693. ath9k_hw_start_nfcal(ah);
  694. if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
  695. chan->channelFlags |= CHANNEL_CW_INT;
  696. ichan->channelFlags &= ~CHANNEL_CW_INT;
  697. }
  698. }
  699. return true;
  700. }
  701. bool ath9k_hw_init_cal(struct ath_hal *ah,
  702. struct ath9k_channel *chan)
  703. {
  704. struct ath_hal_5416 *ahp = AH5416(ah);
  705. struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
  706. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  707. REG_READ(ah, AR_PHY_AGC_CONTROL) |
  708. AR_PHY_AGC_CONTROL_CAL);
  709. if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
  710. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  711. "%s: offset calibration failed to complete in 1ms; "
  712. "noisy environment?\n", __func__);
  713. return false;
  714. }
  715. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  716. REG_READ(ah, AR_PHY_AGC_CONTROL) |
  717. AR_PHY_AGC_CONTROL_NF);
  718. ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
  719. if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
  720. if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
  721. INIT_CAL(&ahp->ah_adcGainCalData);
  722. INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
  723. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  724. "%s: enabling ADC Gain Calibration.\n",
  725. __func__);
  726. }
  727. if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
  728. INIT_CAL(&ahp->ah_adcDcCalData);
  729. INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
  730. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  731. "%s: enabling ADC DC Calibration.\n",
  732. __func__);
  733. }
  734. if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
  735. INIT_CAL(&ahp->ah_iqCalData);
  736. INSERT_CAL(ahp, &ahp->ah_iqCalData);
  737. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  738. "%s: enabling IQ Calibration.\n",
  739. __func__);
  740. }
  741. ahp->ah_cal_list_curr = ahp->ah_cal_list;
  742. if (ahp->ah_cal_list_curr)
  743. ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
  744. }
  745. ichan->CalValid = 0;
  746. return true;
  747. }
  748. const struct hal_percal_data iq_cal_multi_sample = {
  749. IQ_MISMATCH_CAL,
  750. MAX_CAL_SAMPLES,
  751. PER_MIN_LOG_COUNT,
  752. ath9k_hw_iqcal_collect,
  753. ath9k_hw_iqcalibrate
  754. };
  755. const struct hal_percal_data iq_cal_single_sample = {
  756. IQ_MISMATCH_CAL,
  757. MIN_CAL_SAMPLES,
  758. PER_MAX_LOG_COUNT,
  759. ath9k_hw_iqcal_collect,
  760. ath9k_hw_iqcalibrate
  761. };
  762. const struct hal_percal_data adc_gain_cal_multi_sample = {
  763. ADC_GAIN_CAL,
  764. MAX_CAL_SAMPLES,
  765. PER_MIN_LOG_COUNT,
  766. ath9k_hw_adc_gaincal_collect,
  767. ath9k_hw_adc_gaincal_calibrate
  768. };
  769. const struct hal_percal_data adc_gain_cal_single_sample = {
  770. ADC_GAIN_CAL,
  771. MIN_CAL_SAMPLES,
  772. PER_MAX_LOG_COUNT,
  773. ath9k_hw_adc_gaincal_collect,
  774. ath9k_hw_adc_gaincal_calibrate
  775. };
  776. const struct hal_percal_data adc_dc_cal_multi_sample = {
  777. ADC_DC_CAL,
  778. MAX_CAL_SAMPLES,
  779. PER_MIN_LOG_COUNT,
  780. ath9k_hw_adc_dccal_collect,
  781. ath9k_hw_adc_dccal_calibrate
  782. };
  783. const struct hal_percal_data adc_dc_cal_single_sample = {
  784. ADC_DC_CAL,
  785. MIN_CAL_SAMPLES,
  786. PER_MAX_LOG_COUNT,
  787. ath9k_hw_adc_dccal_collect,
  788. ath9k_hw_adc_dccal_calibrate
  789. };
  790. const struct hal_percal_data adc_init_dc_cal = {
  791. ADC_DC_INIT_CAL,
  792. MIN_CAL_SAMPLES,
  793. INIT_LOG_COUNT,
  794. ath9k_hw_adc_dccal_collect,
  795. ath9k_hw_adc_dccal_calibrate
  796. };