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