/drivers/net/wireless/ath/ath9k/eeprom.c

http://github.com/mirrors/linux · C · 681 lines · 574 code · 88 blank · 19 comment · 136 complexity · 2ef0f0c08322b2e6fd0befbbdb3de628 MD5 · raw file

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