calib.c 35 KB

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