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 #include <linux/ath9k_platform.h> 19 20 void 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 28 void 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 37 int16_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 52 bool 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 80 void 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 112 static 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 122 static 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 130 static 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 138 static 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 146 bool 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 else 159 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 168 int 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 220 bool 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 237 bool 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 252 void 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 else 271 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 279 void 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 334 void 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 } else 360 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 389 u16 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 416 u16 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 active 423 * 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 else 439 power_limit = 0; 440 441 return min_t(u16, power_limit, MAX_RATE_POWER); 442 } 443 444 void 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 464 void 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 else 501 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_2GHZ 588 (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 else 602 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 else 614 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 else 658 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 671 int ath9k_hw_eeprom_init(struct ath_hw *ah) 672 { 673 int status; 674 675 if (AR_SREV_9300_20_OR_LATER(ah)) 676 ah->eep_ops = &eep_ar9300_ops; 677 else if (AR_SREV_9287(ah)) { 678 ah->eep_ops = &eep_ar9287_ops; 679 } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { 680 ah->eep_ops = &eep_4k_ops; 681 } else { 682 ah->eep_ops = &eep_def_ops; 683 } 684 685 if (!ah->eep_ops->fill_eeprom(ah)) 686 return -EIO; 687 688 status = ah->eep_ops->check_eeprom(ah); 689 690 return status; 691 } 692