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