eeprom.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /*
  2. * Copyright (c) 2008-2011 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. void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
  18. {
  19. REG_WRITE(ah, reg, val);
  20. if (ah->config.analog_shiftreg)
  21. udelay(100);
  22. }
  23. void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
  24. u32 shift, u32 val)
  25. {
  26. REG_RMW(ah, reg, ((val << shift) & mask), mask);
  27. if (ah->config.analog_shiftreg)
  28. udelay(100);
  29. }
  30. int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
  31. int16_t targetLeft, int16_t targetRight)
  32. {
  33. int16_t rv;
  34. if (srcRight == srcLeft) {
  35. rv = targetLeft;
  36. } else {
  37. rv = (int16_t) (((target - srcLeft) * targetRight +
  38. (srcRight - target) * targetLeft) /
  39. (srcRight - srcLeft));
  40. }
  41. return rv;
  42. }
  43. bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
  44. u16 *indexL, u16 *indexR)
  45. {
  46. u16 i;
  47. if (target <= pList[0]) {
  48. *indexL = *indexR = 0;
  49. return true;
  50. }
  51. if (target >= pList[listSize - 1]) {
  52. *indexL = *indexR = (u16) (listSize - 1);
  53. return true;
  54. }
  55. for (i = 0; i < listSize - 1; i++) {
  56. if (pList[i] == target) {
  57. *indexL = *indexR = i;
  58. return true;
  59. }
  60. if (target < pList[i + 1]) {
  61. *indexL = i;
  62. *indexR = (u16) (i + 1);
  63. return false;
  64. }
  65. }
  66. return false;
  67. }
  68. void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
  69. int eep_start_loc, int size)
  70. {
  71. int i = 0, j, addr;
  72. u32 addrdata[8];
  73. u32 data[8];
  74. for (addr = 0; addr < size; addr++) {
  75. addrdata[i] = AR5416_EEPROM_OFFSET +
  76. ((addr + eep_start_loc) << AR5416_EEPROM_S);
  77. i++;
  78. if (i == 8) {
  79. REG_READ_MULTI(ah, addrdata, data, i);
  80. for (j = 0; j < i; j++) {
  81. *eep_data = data[j];
  82. eep_data++;
  83. }
  84. i = 0;
  85. }
  86. }
  87. if (i != 0) {
  88. REG_READ_MULTI(ah, addrdata, data, i);
  89. for (j = 0; j < i; j++) {
  90. *eep_data = data[j];
  91. eep_data++;
  92. }
  93. }
  94. }
  95. static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
  96. off_t offset, u16 *data)
  97. {
  98. if (offset >= blob_size)
  99. return false;
  100. *data = blob[offset];
  101. return true;
  102. }
  103. static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
  104. off_t offset, u16 *data)
  105. {
  106. return ath9k_hw_nvram_read_array((u16 *) eeprom_blob->data,
  107. eeprom_blob->size / sizeof(u16),
  108. offset, data);
  109. }
  110. static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
  111. u16 *data)
  112. {
  113. return ath9k_hw_nvram_read_array(ah->nvmem_blob,
  114. ah->nvmem_blob_len / sizeof(u16),
  115. offset, data);
  116. }
  117. bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
  118. {
  119. struct ath_common *common = ath9k_hw_common(ah);
  120. bool ret;
  121. if (ah->nvmem_blob)
  122. ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
  123. else if (ah->eeprom_blob)
  124. ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
  125. else
  126. ret = common->bus_ops->eeprom_read(common, off, data);
  127. if (!ret)
  128. ath_dbg(common, EEPROM,
  129. "unable to read eeprom region at offset %u\n", off);
  130. return ret;
  131. }
  132. int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
  133. {
  134. u16 magic;
  135. u16 *eepdata;
  136. int i;
  137. bool needs_byteswap = false;
  138. struct ath_common *common = ath9k_hw_common(ah);
  139. if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
  140. ath_err(common, "Reading Magic # failed\n");
  141. return -EIO;
  142. }
  143. if (swab16(magic) == AR5416_EEPROM_MAGIC) {
  144. needs_byteswap = true;
  145. ath_dbg(common, EEPROM,
  146. "EEPROM needs byte-swapping to correct endianness.\n");
  147. } else if (magic != AR5416_EEPROM_MAGIC) {
  148. if (ath9k_hw_use_flash(ah)) {
  149. ath_dbg(common, EEPROM,
  150. "Ignoring invalid EEPROM magic (0x%04x).\n",
  151. magic);
  152. } else {
  153. ath_err(common,
  154. "Invalid EEPROM magic (0x%04x).\n", magic);
  155. return -EINVAL;
  156. }
  157. }
  158. if (needs_byteswap) {
  159. if (ah->ah_flags & AH_NO_EEP_SWAP) {
  160. ath_info(common,
  161. "Ignoring endianness difference in EEPROM magic bytes.\n");
  162. } else {
  163. eepdata = (u16 *)(&ah->eeprom);
  164. for (i = 0; i < size; i++)
  165. eepdata[i] = swab16(eepdata[i]);
  166. }
  167. }
  168. if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) {
  169. *swap_needed = true;
  170. ath_dbg(common, EEPROM,
  171. "Big Endian EEPROM detected according to EEPMISC register.\n");
  172. } else {
  173. *swap_needed = false;
  174. }
  175. return 0;
  176. }
  177. bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
  178. {
  179. u32 i, sum = 0;
  180. u16 *eepdata = (u16 *)(&ah->eeprom);
  181. struct ath_common *common = ath9k_hw_common(ah);
  182. for (i = 0; i < size; i++)
  183. sum ^= eepdata[i];
  184. if (sum != 0xffff) {
  185. ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
  186. return false;
  187. }
  188. return true;
  189. }
  190. bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
  191. {
  192. struct ath_common *common = ath9k_hw_common(ah);
  193. if (ah->eep_ops->get_eeprom_ver(ah) != version ||
  194. ah->eep_ops->get_eeprom_rev(ah) < minrev) {
  195. ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
  196. ah->eep_ops->get_eeprom_ver(ah),
  197. ah->eep_ops->get_eeprom_rev(ah));
  198. return false;
  199. }
  200. return true;
  201. }
  202. void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
  203. u8 *pVpdList, u16 numIntercepts,
  204. u8 *pRetVpdList)
  205. {
  206. u16 i, k;
  207. u8 currPwr = pwrMin;
  208. u16 idxL = 0, idxR = 0;
  209. for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
  210. ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
  211. numIntercepts, &(idxL),
  212. &(idxR));
  213. if (idxR < 1)
  214. idxR = 1;
  215. if (idxL == numIntercepts - 1)
  216. idxL = (u16) (numIntercepts - 2);
  217. if (pPwrList[idxL] == pPwrList[idxR])
  218. k = pVpdList[idxL];
  219. else
  220. k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
  221. (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
  222. (pPwrList[idxR] - pPwrList[idxL]));
  223. pRetVpdList[i] = (u8) k;
  224. currPwr += 2;
  225. }
  226. }
  227. void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
  228. struct ath9k_channel *chan,
  229. struct cal_target_power_leg *powInfo,
  230. u16 numChannels,
  231. struct cal_target_power_leg *pNewPower,
  232. u16 numRates, bool isExtTarget)
  233. {
  234. struct chan_centers centers;
  235. u16 clo, chi;
  236. int i;
  237. int matchIndex = -1, lowIndex = -1;
  238. u16 freq;
  239. ath9k_hw_get_channel_centers(ah, chan, &centers);
  240. freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
  241. if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
  242. IS_CHAN_2GHZ(chan))) {
  243. matchIndex = 0;
  244. } else {
  245. for (i = 0; (i < numChannels) &&
  246. (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
  247. if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
  248. IS_CHAN_2GHZ(chan))) {
  249. matchIndex = i;
  250. break;
  251. } else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
  252. IS_CHAN_2GHZ(chan)) && i > 0 &&
  253. freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
  254. IS_CHAN_2GHZ(chan))) {
  255. lowIndex = i - 1;
  256. break;
  257. }
  258. }
  259. if ((matchIndex == -1) && (lowIndex == -1))
  260. matchIndex = i - 1;
  261. }
  262. if (matchIndex != -1) {
  263. *pNewPower = powInfo[matchIndex];
  264. } else {
  265. clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
  266. IS_CHAN_2GHZ(chan));
  267. chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
  268. IS_CHAN_2GHZ(chan));
  269. for (i = 0; i < numRates; i++) {
  270. pNewPower->tPow2x[i] =
  271. (u8)ath9k_hw_interpolate(freq, clo, chi,
  272. powInfo[lowIndex].tPow2x[i],
  273. powInfo[lowIndex + 1].tPow2x[i]);
  274. }
  275. }
  276. }
  277. void ath9k_hw_get_target_powers(struct ath_hw *ah,
  278. struct ath9k_channel *chan,
  279. struct cal_target_power_ht *powInfo,
  280. u16 numChannels,
  281. struct cal_target_power_ht *pNewPower,
  282. u16 numRates, bool isHt40Target)
  283. {
  284. struct chan_centers centers;
  285. u16 clo, chi;
  286. int i;
  287. int matchIndex = -1, lowIndex = -1;
  288. u16 freq;
  289. ath9k_hw_get_channel_centers(ah, chan, &centers);
  290. freq = isHt40Target ? centers.synth_center : centers.ctl_center;
  291. if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
  292. matchIndex = 0;
  293. } else {
  294. for (i = 0; (i < numChannels) &&
  295. (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
  296. if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
  297. IS_CHAN_2GHZ(chan))) {
  298. matchIndex = i;
  299. break;
  300. } else
  301. if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
  302. IS_CHAN_2GHZ(chan)) && i > 0 &&
  303. freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
  304. IS_CHAN_2GHZ(chan))) {
  305. lowIndex = i - 1;
  306. break;
  307. }
  308. }
  309. if ((matchIndex == -1) && (lowIndex == -1))
  310. matchIndex = i - 1;
  311. }
  312. if (matchIndex != -1) {
  313. *pNewPower = powInfo[matchIndex];
  314. } else {
  315. clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
  316. IS_CHAN_2GHZ(chan));
  317. chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
  318. IS_CHAN_2GHZ(chan));
  319. for (i = 0; i < numRates; i++) {
  320. pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
  321. clo, chi,
  322. powInfo[lowIndex].tPow2x[i],
  323. powInfo[lowIndex + 1].tPow2x[i]);
  324. }
  325. }
  326. }
  327. u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
  328. bool is2GHz, int num_band_edges)
  329. {
  330. u16 twiceMaxEdgePower = MAX_RATE_POWER;
  331. int i;
  332. for (i = 0; (i < num_band_edges) &&
  333. (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
  334. if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
  335. twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
  336. break;
  337. } else if ((i > 0) &&
  338. (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
  339. is2GHz))) {
  340. if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
  341. is2GHz) < freq &&
  342. CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
  343. twiceMaxEdgePower =
  344. CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
  345. }
  346. break;
  347. }
  348. }
  349. return twiceMaxEdgePower;
  350. }
  351. u16 ath9k_hw_get_scaled_power(struct ath_hw *ah, u16 power_limit,
  352. u8 antenna_reduction)
  353. {
  354. u16 reduction = antenna_reduction;
  355. /*
  356. * Reduce scaled Power by number of chains active
  357. * to get the per chain tx power level.
  358. */
  359. switch (ar5416_get_ntxchains(ah->txchainmask)) {
  360. case 1:
  361. break;
  362. case 2:
  363. reduction += POWER_CORRECTION_FOR_TWO_CHAIN;
  364. break;
  365. case 3:
  366. reduction += POWER_CORRECTION_FOR_THREE_CHAIN;
  367. break;
  368. }
  369. if (power_limit > reduction)
  370. power_limit -= reduction;
  371. else
  372. power_limit = 0;
  373. return min_t(u16, power_limit, MAX_RATE_POWER);
  374. }
  375. void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
  376. {
  377. struct ath_common *common = ath9k_hw_common(ah);
  378. struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
  379. switch (ar5416_get_ntxchains(ah->txchainmask)) {
  380. case 1:
  381. break;
  382. case 2:
  383. regulatory->max_power_level += POWER_CORRECTION_FOR_TWO_CHAIN;
  384. break;
  385. case 3:
  386. regulatory->max_power_level += POWER_CORRECTION_FOR_THREE_CHAIN;
  387. break;
  388. default:
  389. ath_dbg(common, EEPROM, "Invalid chainmask configuration\n");
  390. break;
  391. }
  392. }
  393. void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
  394. struct ath9k_channel *chan,
  395. void *pRawDataSet,
  396. u8 *bChans, u16 availPiers,
  397. u16 tPdGainOverlap,
  398. u16 *pPdGainBoundaries, u8 *pPDADCValues,
  399. u16 numXpdGains)
  400. {
  401. int i, j, k;
  402. int16_t ss;
  403. u16 idxL = 0, idxR = 0, numPiers;
  404. static u8 vpdTableL[AR5416_NUM_PD_GAINS]
  405. [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
  406. static u8 vpdTableR[AR5416_NUM_PD_GAINS]
  407. [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
  408. static u8 vpdTableI[AR5416_NUM_PD_GAINS]
  409. [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
  410. u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
  411. u8 minPwrT4[AR5416_NUM_PD_GAINS];
  412. u8 maxPwrT4[AR5416_NUM_PD_GAINS];
  413. int16_t vpdStep;
  414. int16_t tmpVal;
  415. u16 sizeCurrVpdTable, maxIndex, tgtIndex;
  416. bool match;
  417. int16_t minDelta = 0;
  418. struct chan_centers centers;
  419. int pdgain_boundary_default;
  420. struct cal_data_per_freq *data_def = pRawDataSet;
  421. struct cal_data_per_freq_4k *data_4k = pRawDataSet;
  422. struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
  423. bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
  424. int intercepts;
  425. if (AR_SREV_9287(ah))
  426. intercepts = AR9287_PD_GAIN_ICEPTS;
  427. else
  428. intercepts = AR5416_PD_GAIN_ICEPTS;
  429. memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
  430. ath9k_hw_get_channel_centers(ah, chan, &centers);
  431. for (numPiers = 0; numPiers < availPiers; numPiers++) {
  432. if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
  433. break;
  434. }
  435. match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
  436. IS_CHAN_2GHZ(chan)),
  437. bChans, numPiers, &idxL, &idxR);
  438. if (match) {
  439. if (AR_SREV_9287(ah)) {
  440. for (i = 0; i < numXpdGains; i++) {
  441. minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
  442. maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1];
  443. ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
  444. data_9287[idxL].pwrPdg[i],
  445. data_9287[idxL].vpdPdg[i],
  446. intercepts,
  447. vpdTableI[i]);
  448. }
  449. } else if (eeprom_4k) {
  450. for (i = 0; i < numXpdGains; i++) {
  451. minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
  452. maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1];
  453. ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
  454. data_4k[idxL].pwrPdg[i],
  455. data_4k[idxL].vpdPdg[i],
  456. intercepts,
  457. vpdTableI[i]);
  458. }
  459. } else {
  460. for (i = 0; i < numXpdGains; i++) {
  461. minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
  462. maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1];
  463. ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
  464. data_def[idxL].pwrPdg[i],
  465. data_def[idxL].vpdPdg[i],
  466. intercepts,
  467. vpdTableI[i]);
  468. }
  469. }
  470. } else {
  471. for (i = 0; i < numXpdGains; i++) {
  472. if (AR_SREV_9287(ah)) {
  473. pVpdL = data_9287[idxL].vpdPdg[i];
  474. pPwrL = data_9287[idxL].pwrPdg[i];
  475. pVpdR = data_9287[idxR].vpdPdg[i];
  476. pPwrR = data_9287[idxR].pwrPdg[i];
  477. } else if (eeprom_4k) {
  478. pVpdL = data_4k[idxL].vpdPdg[i];
  479. pPwrL = data_4k[idxL].pwrPdg[i];
  480. pVpdR = data_4k[idxR].vpdPdg[i];
  481. pPwrR = data_4k[idxR].pwrPdg[i];
  482. } else {
  483. pVpdL = data_def[idxL].vpdPdg[i];
  484. pPwrL = data_def[idxL].pwrPdg[i];
  485. pVpdR = data_def[idxR].vpdPdg[i];
  486. pPwrR = data_def[idxR].pwrPdg[i];
  487. }
  488. minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
  489. maxPwrT4[i] =
  490. min(pPwrL[intercepts - 1],
  491. pPwrR[intercepts - 1]);
  492. ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
  493. pPwrL, pVpdL,
  494. intercepts,
  495. vpdTableL[i]);
  496. ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
  497. pPwrR, pVpdR,
  498. intercepts,
  499. vpdTableR[i]);
  500. for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
  501. vpdTableI[i][j] =
  502. (u8)(ath9k_hw_interpolate((u16)
  503. FREQ2FBIN(centers.
  504. synth_center,
  505. IS_CHAN_2GHZ
  506. (chan)),
  507. bChans[idxL], bChans[idxR],
  508. vpdTableL[i][j], vpdTableR[i][j]));
  509. }
  510. }
  511. }
  512. k = 0;
  513. for (i = 0; i < numXpdGains; i++) {
  514. if (i == (numXpdGains - 1))
  515. pPdGainBoundaries[i] =
  516. (u16)(maxPwrT4[i] / 2);
  517. else
  518. pPdGainBoundaries[i] =
  519. (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
  520. pPdGainBoundaries[i] =
  521. min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
  522. minDelta = 0;
  523. if (i == 0) {
  524. if (AR_SREV_9280_20_OR_LATER(ah))
  525. ss = (int16_t)(0 - (minPwrT4[i] / 2));
  526. else
  527. ss = 0;
  528. } else {
  529. ss = (int16_t)((pPdGainBoundaries[i - 1] -
  530. (minPwrT4[i] / 2)) -
  531. tPdGainOverlap + 1 + minDelta);
  532. }
  533. vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
  534. vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
  535. while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
  536. tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
  537. pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
  538. ss++;
  539. }
  540. sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
  541. tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
  542. (minPwrT4[i] / 2));
  543. maxIndex = (tgtIndex < sizeCurrVpdTable) ?
  544. tgtIndex : sizeCurrVpdTable;
  545. while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
  546. pPDADCValues[k++] = vpdTableI[i][ss++];
  547. }
  548. vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
  549. vpdTableI[i][sizeCurrVpdTable - 2]);
  550. vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
  551. if (tgtIndex >= maxIndex) {
  552. while ((ss <= tgtIndex) &&
  553. (k < (AR5416_NUM_PDADC_VALUES - 1))) {
  554. tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
  555. (ss - maxIndex + 1) * vpdStep));
  556. pPDADCValues[k++] = (u8)((tmpVal > 255) ?
  557. 255 : tmpVal);
  558. ss++;
  559. }
  560. }
  561. }
  562. if (eeprom_4k)
  563. pdgain_boundary_default = 58;
  564. else
  565. pdgain_boundary_default = pPdGainBoundaries[i - 1];
  566. while (i < AR5416_PD_GAINS_IN_MASK) {
  567. pPdGainBoundaries[i] = pdgain_boundary_default;
  568. i++;
  569. }
  570. while (k < AR5416_NUM_PDADC_VALUES) {
  571. pPDADCValues[k] = pPDADCValues[k - 1];
  572. k++;
  573. }
  574. }
  575. int ath9k_hw_eeprom_init(struct ath_hw *ah)
  576. {
  577. if (AR_SREV_9300_20_OR_LATER(ah))
  578. ah->eep_ops = &eep_ar9300_ops;
  579. else if (AR_SREV_9287(ah)) {
  580. ah->eep_ops = &eep_ar9287_ops;
  581. } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
  582. ah->eep_ops = &eep_4k_ops;
  583. } else {
  584. ah->eep_ops = &eep_def_ops;
  585. }
  586. if (!ah->eep_ops->fill_eeprom(ah))
  587. return -EIO;
  588. return ah->eep_ops->check_eeprom(ah);
  589. }