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