1 /*- 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 5 * Copyright (c) 2002-2008 Atheros Communications, Inc. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * 19 * $FreeBSD$ 20 */ 21 #include "opt_ah.h" 22 23 #include "ah.h" 24 #include "ah_internal.h" 25 #include "ah_eeprom_v3.h" 26 27 static void 28 getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee, 29 uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp) 30 { 31 static const uint16_t intercepts3[] = 32 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; 33 static const uint16_t intercepts3_2[] = 34 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; 35 const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ? 36 intercepts3 : intercepts3_2; 37 int i; 38 39 /* loop for the percentages in steps or 5 */ 40 for (i = 0; i < NUM_INTERCEPTS; i++ ) 41 *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100; 42 } 43 44 /* 45 * Get channel value from binary representation held in eeprom 46 */ 47 static uint16_t 48 fbin2freq(HAL_EEPROM *ee, uint16_t fbin) 49 { 50 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ 51 return fbin; 52 return ee->ee_version <= AR_EEPROM_VER3_2 ? 53 (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) : 54 4800 + 5*fbin; 55 } 56 57 static uint16_t 58 fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin) 59 { 60 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ 61 return fbin; 62 return ee->ee_version <= AR_EEPROM_VER3_2 ? 63 2400 + fbin : 64 2300 + fbin; 65 } 66 67 /* 68 * Now copy EEPROM frequency pier contents into the allocated space 69 */ 70 static HAL_BOOL 71 readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee) 72 { 73 #define EEREAD(_off) do { \ 74 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 75 return AH_FALSE; \ 76 } while (0) 77 uint16_t eeval, off; 78 int i; 79 80 if (ee->ee_version >= AR_EEPROM_VER4_0 && 81 ee->ee_eepMap && !ee->ee_Amode) { 82 /* 83 * V4.0 EEPROMs with map type 1 have frequency pier 84 * data only when 11a mode is supported. 85 */ 86 return AH_TRUE; 87 } 88 if (ee->ee_version >= AR_EEPROM_VER3_3) { 89 off = GROUPS_OFFSET3_3 + GROUP1_OFFSET; 90 for (i = 0; i < ee->ee_numChannels11a; i += 2) { 91 EEREAD(off++); 92 ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3; 93 ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3; 94 } 95 } else { 96 off = GROUPS_OFFSET3_2 + GROUP1_OFFSET; 97 98 EEREAD(off++); 99 ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK; 100 ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK; 101 ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK; 102 103 EEREAD(off++); 104 ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f; 105 ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK; 106 ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK; 107 108 EEREAD(off++); 109 ee->ee_channels11a[4] |= (eeval >> 13) & 0x7; 110 ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK; 111 ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK; 112 113 EEREAD(off++); 114 ee->ee_channels11a[6] |= (eeval >> 15) & 0x1; 115 ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK; 116 ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK; 117 ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK; 118 119 EEREAD(off++); 120 ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f; 121 } 122 123 for (i = 0; i < ee->ee_numChannels11a; i++) 124 ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]); 125 126 return AH_TRUE; 127 #undef EEREAD 128 } 129 130 /* 131 * Rev 4 Eeprom 5112 Power Extract Functions 132 */ 133 134 /* 135 * Allocate the power information based on the number of channels 136 * recorded by the calibration. These values are then initialized. 137 */ 138 static HAL_BOOL 139 eepromAllocExpnPower5112(struct ath_hal *ah, 140 const EEPROM_POWER_5112 *pCalDataset, 141 EEPROM_POWER_EXPN_5112 *pPowerExpn) 142 { 143 uint16_t numChannels = pCalDataset->numChannels; 144 const uint16_t *pChanList = pCalDataset->pChannels; 145 void *data; 146 int i, j; 147 148 /* Allocate the channel and Power Data arrays together */ 149 data = ath_hal_malloc( 150 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) + 151 sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels); 152 if (data == AH_NULL) { 153 HALDEBUG(ah, HAL_DEBUG_ANY, 154 "%s unable to allocate raw data struct (gen3)\n", __func__); 155 return AH_FALSE; 156 } 157 pPowerExpn->pChannels = data; 158 pPowerExpn->pDataPerChannel = (void *)(((char *)data) + 159 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t))); 160 161 pPowerExpn->numChannels = numChannels; 162 for (i = 0; i < numChannels; i++) { 163 pPowerExpn->pChannels[i] = 164 pPowerExpn->pDataPerChannel[i].channelValue = 165 pChanList[i]; 166 for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) { 167 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j; 168 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0; 169 } 170 pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4; 171 pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3; 172 } 173 return AH_TRUE; 174 } 175 176 /* 177 * Expand the dataSet from the calibration information into the 178 * final power structure for 5112 179 */ 180 static HAL_BOOL 181 eepromExpandPower5112(struct ath_hal *ah, 182 const EEPROM_POWER_5112 *pCalDataset, 183 EEPROM_POWER_EXPN_5112 *pPowerExpn) 184 { 185 int ii, jj, kk; 186 int16_t maxPower_t4; 187 EXPN_DATA_PER_XPD_5112 *pExpnXPD; 188 /* ptr to array of info held per channel */ 189 const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh; 190 uint16_t xgainList[2], xpdMask; 191 192 pPowerExpn->xpdMask = pCalDataset->xpdMask; 193 194 xgainList[0] = 0xDEAD; 195 xgainList[1] = 0xDEAD; 196 197 kk = 0; 198 xpdMask = pPowerExpn->xpdMask; 199 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { 200 if (((xpdMask >> jj) & 1) > 0) { 201 if (kk > 1) { 202 HALDEBUG(ah, HAL_DEBUG_ANY, 203 "%s: too many xpdGains in dataset: %u\n", 204 __func__, kk); 205 return AH_FALSE; 206 } 207 xgainList[kk++] = jj; 208 } 209 } 210 211 pPowerExpn->numChannels = pCalDataset->numChannels; 212 if (pPowerExpn->numChannels == 0) { 213 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__); 214 return AH_FALSE; 215 } 216 217 for (ii = 0; ii < pPowerExpn->numChannels; ii++) { 218 pCalCh = &pCalDataset->pDataPerChannel[ii]; 219 pPowerExpn->pDataPerChannel[ii].channelValue = 220 pCalCh->channelValue; 221 pPowerExpn->pDataPerChannel[ii].maxPower_t4 = 222 pCalCh->maxPower_t4; 223 maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4; 224 225 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) 226 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0; 227 if (xgainList[1] == 0xDEAD) { 228 jj = xgainList[0]; 229 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 230 pExpnXPD->numPcdacs = 4; 231 pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0; 232 pExpnXPD->pcdac[1] = (uint16_t) 233 (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); 234 pExpnXPD->pcdac[2] = (uint16_t) 235 (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); 236 pExpnXPD->pcdac[3] = (uint16_t) 237 (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); 238 239 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; 240 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; 241 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; 242 pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; 243 244 } else { 245 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0; 246 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20; 247 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35; 248 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63; 249 250 jj = xgainList[0]; 251 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 252 pExpnXPD->numPcdacs = 4; 253 pExpnXPD->pcdac[1] = (uint16_t) 254 (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); 255 pExpnXPD->pcdac[2] = (uint16_t) 256 (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); 257 pExpnXPD->pcdac[3] = (uint16_t) 258 (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); 259 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; 260 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; 261 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; 262 pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; 263 264 jj = xgainList[1]; 265 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 266 pExpnXPD->numPcdacs = 3; 267 268 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3; 269 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3; 270 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3; 271 } 272 } 273 return AH_TRUE; 274 } 275 276 static HAL_BOOL 277 readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) 278 { 279 #define EEREAD(_off) do { \ 280 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 281 return AH_FALSE; \ 282 } while (0) 283 const uint16_t dbmmask = 0xff; 284 const uint16_t pcdac_delta_mask = 0x1f; 285 const uint16_t pcdac_mask = 0x3f; 286 const uint16_t freqmask = 0xff; 287 288 int i, mode, numPiers; 289 uint32_t off; 290 uint16_t eeval; 291 uint16_t freq[NUM_11A_EEPROM_CHANNELS]; 292 EEPROM_POWER_5112 eePower; 293 294 HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0); 295 off = GROUPS_OFFSET3_3; 296 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 297 numPiers = 0; 298 switch (mode) { 299 case headerInfo11A: 300 if (!ee->ee_Amode) /* no 11a calibration data */ 301 continue; 302 while (numPiers < NUM_11A_EEPROM_CHANNELS) { 303 EEREAD(off++); 304 if ((eeval & freqmask) == 0) 305 break; 306 freq[numPiers++] = fbin2freq(ee, 307 eeval & freqmask); 308 309 if (((eeval >> 8) & freqmask) == 0) 310 break; 311 freq[numPiers++] = fbin2freq(ee, 312 (eeval>>8) & freqmask); 313 } 314 break; 315 case headerInfo11B: 316 if (!ee->ee_Bmode) /* no 11b calibration data */ 317 continue; 318 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) 319 if (ee->ee_calPier11b[i] != CHANNEL_UNUSED) 320 freq[numPiers++] = ee->ee_calPier11b[i]; 321 break; 322 case headerInfo11G: 323 if (!ee->ee_Gmode) /* no 11g calibration data */ 324 continue; 325 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) 326 if (ee->ee_calPier11g[i] != CHANNEL_UNUSED) 327 freq[numPiers++] = ee->ee_calPier11g[i]; 328 break; 329 default: 330 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 331 __func__, mode); 332 return AH_FALSE; 333 } 334 335 OS_MEMZERO(&eePower, sizeof(eePower)); 336 eePower.numChannels = numPiers; 337 338 for (i = 0; i < numPiers; i++) { 339 eePower.pChannels[i] = freq[i]; 340 eePower.pDataPerChannel[i].channelValue = freq[i]; 341 342 EEREAD(off++); 343 eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t) 344 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 345 eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t) 346 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 347 348 EEREAD(off++); 349 eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t) 350 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 351 eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t) 352 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 353 354 EEREAD(off++); 355 eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t) 356 (eeval & pcdac_delta_mask); 357 eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t) 358 ((eeval >> 5) & pcdac_delta_mask); 359 eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t) 360 ((eeval >> 10) & pcdac_delta_mask); 361 362 EEREAD(off++); 363 eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t) 364 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 365 eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t) 366 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 367 368 EEREAD(off++); 369 eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t) 370 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 371 if (ee->ee_version >= AR_EEPROM_VER4_3) { 372 eePower.pDataPerChannel[i].maxPower_t4 = 373 eePower.pDataPerChannel[i].pwr4_xg0; 374 eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t) 375 ((eeval >> 8) & pcdac_mask); 376 } else { 377 eePower.pDataPerChannel[i].maxPower_t4 = (int16_t) 378 (((eeval >> 8) & dbmmask) - 379 ((eeval >> 15) & 0x1)*256); 380 eePower.pDataPerChannel[i].pcd1_xg0 = 1; 381 } 382 } 383 eePower.xpdMask = ee->ee_xgain[mode]; 384 385 if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { 386 HALDEBUG(ah, HAL_DEBUG_ANY, 387 "%s: did not allocate power struct\n", __func__); 388 return AH_FALSE; 389 } 390 if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { 391 HALDEBUG(ah, HAL_DEBUG_ANY, 392 "%s: did not expand power struct\n", __func__); 393 return AH_FALSE; 394 } 395 } 396 return AH_TRUE; 397 #undef EEREAD 398 } 399 400 static void 401 freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) 402 { 403 int mode; 404 void *data; 405 406 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 407 EEPROM_POWER_EXPN_5112 *pPowerExpn = 408 &ee->ee_modePowerArray5112[mode]; 409 data = pPowerExpn->pChannels; 410 if (data != AH_NULL) { 411 pPowerExpn->pChannels = AH_NULL; 412 ath_hal_free(data); 413 } 414 } 415 } 416 417 static void 418 ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413, 419 uint16_t myNumRawChannels, uint16_t *pMyRawChanList) 420 { 421 uint16_t i, channelValue; 422 uint32_t xpd_mask; 423 uint16_t numPdGainsUsed; 424 425 pEEPROMDataset2413->numChannels = myNumRawChannels; 426 427 xpd_mask = pEEPROMDataset2413->xpd_mask; 428 numPdGainsUsed = 0; 429 if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; 430 if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; 431 if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; 432 if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; 433 434 for (i = 0; i < myNumRawChannels; i++) { 435 channelValue = pMyRawChanList[i]; 436 pEEPROMDataset2413->pChannels[i] = channelValue; 437 pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue; 438 pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed; 439 } 440 } 441 442 static HAL_BOOL 443 ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee, 444 EEPROM_DATA_STRUCT_2413 *pCalDataset, 445 uint32_t start_offset, uint32_t maxPiers, uint8_t mode) 446 { 447 #define EEREAD(_off) do { \ 448 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 449 return AH_FALSE; \ 450 } while (0) 451 const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */ 452 const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */ 453 const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */ 454 const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */ 455 const uint16_t freqmask = 0xff; 456 457 uint16_t ii, eeval; 458 uint16_t idx, numPiers; 459 uint16_t freq[NUM_11A_EEPROM_CHANNELS]; 460 461 idx = start_offset; 462 for (numPiers = 0; numPiers < maxPiers;) { 463 EEREAD(idx++); 464 if ((eeval & freqmask) == 0) 465 break; 466 if (mode == headerInfo11A) 467 freq[numPiers++] = fbin2freq(ee, (eeval & freqmask)); 468 else 469 freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask)); 470 471 if (((eeval >> 8) & freqmask) == 0) 472 break; 473 if (mode == headerInfo11A) 474 freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask); 475 else 476 freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask); 477 } 478 ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]); 479 480 idx = start_offset + (maxPiers / 2); 481 for (ii = 0; ii < pCalDataset->numChannels; ii++) { 482 EEPROM_DATA_PER_CHANNEL_2413 *currCh = 483 &(pCalDataset->pDataPerChannel[ii]); 484 485 if (currCh->numPdGains > 0) { 486 /* 487 * Read the first NUM_POINTS_OTHER_PDGAINS pwr 488 * and Vpd values for pdgain_0 489 */ 490 EEREAD(idx++); 491 currCh->pwr_I[0] = eeval & dbm_I_mask; 492 currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask; 493 currCh->pwr_delta_t2[0][0] = 494 (eeval >> 12) & dbm_delta_mask; 495 496 EEREAD(idx++); 497 currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask; 498 currCh->pwr_delta_t2[1][0] = 499 (eeval >> 6) & dbm_delta_mask; 500 currCh->Vpd_delta[1][0] = 501 (eeval >> 10) & Vpd_delta_mask; 502 503 EEREAD(idx++); 504 currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask; 505 currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask; 506 } 507 508 if (currCh->numPdGains > 1) { 509 /* 510 * Read the first NUM_POINTS_OTHER_PDGAINS pwr 511 * and Vpd values for pdgain_1 512 */ 513 currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask; 514 currCh->Vpd_I[1] = (eeval >> 15) & 0x1; 515 516 EEREAD(idx++); 517 /* upper 6 bits */ 518 currCh->Vpd_I[1] |= (eeval & 0x3F) << 1; 519 currCh->pwr_delta_t2[0][1] = 520 (eeval >> 6) & dbm_delta_mask; 521 currCh->Vpd_delta[0][1] = 522 (eeval >> 10) & Vpd_delta_mask; 523 524 EEREAD(idx++); 525 currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask; 526 currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask; 527 currCh->pwr_delta_t2[2][1] = 528 (eeval >> 10) & dbm_delta_mask; 529 currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3; 530 531 EEREAD(idx++); 532 /* upper 4 bits */ 533 currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2; 534 } else if (currCh->numPdGains == 1) { 535 /* 536 * Read the last pwr and Vpd values for pdgain_0 537 */ 538 currCh->pwr_delta_t2[3][0] = 539 (eeval >> 10) & dbm_delta_mask; 540 currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3; 541 542 EEREAD(idx++); 543 /* upper 4 bits */ 544 currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2; 545 546 /* 4 words if numPdGains == 1 */ 547 } 548 549 if (currCh->numPdGains > 2) { 550 /* 551 * Read the first NUM_POINTS_OTHER_PDGAINS pwr 552 * and Vpd values for pdgain_2 553 */ 554 currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask; 555 currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask; 556 557 EEREAD(idx++); 558 currCh->pwr_delta_t2[0][2] = 559 (eeval >> 0) & dbm_delta_mask; 560 currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask; 561 currCh->pwr_delta_t2[1][2] = 562 (eeval >> 10) & dbm_delta_mask; 563 currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3; 564 565 EEREAD(idx++); 566 /* upper 4 bits */ 567 currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2; 568 currCh->pwr_delta_t2[2][2] = 569 (eeval >> 4) & dbm_delta_mask; 570 currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask; 571 } else if (currCh->numPdGains == 2) { 572 /* 573 * Read the last pwr and Vpd values for pdgain_1 574 */ 575 currCh->pwr_delta_t2[3][1] = 576 (eeval >> 4) & dbm_delta_mask; 577 currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask; 578 579 /* 6 words if numPdGains == 2 */ 580 } 581 582 if (currCh->numPdGains > 3) { 583 /* 584 * Read the first NUM_POINTS_OTHER_PDGAINS pwr 585 * and Vpd values for pdgain_3 586 */ 587 currCh->pwr_I[3] = (eeval >> 14) & 0x3; 588 589 EEREAD(idx++); 590 /* upper 3 bits */ 591 currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2; 592 currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask; 593 currCh->pwr_delta_t2[0][3] = 594 (eeval >> 10) & dbm_delta_mask; 595 currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3; 596 597 EEREAD(idx++); 598 /* upper 4 bits */ 599 currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2; 600 currCh->pwr_delta_t2[1][3] = 601 (eeval >> 4) & dbm_delta_mask; 602 currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask; 603 currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3; 604 605 EEREAD(idx++); 606 /* upper 2 bits */ 607 currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2; 608 currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask; 609 currCh->pwr_delta_t2[3][3] = 610 (eeval >> 8) & dbm_delta_mask; 611 currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF; 612 613 EEREAD(idx++); 614 /* upper 2 bits */ 615 currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4; 616 617 /* 12 words if numPdGains == 4 */ 618 } else if (currCh->numPdGains == 3) { 619 /* read the last pwr and Vpd values for pdgain_2 */ 620 currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3; 621 622 EEREAD(idx++); 623 /* upper 2 bits */ 624 currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2; 625 currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask; 626 627 /* 9 words if numPdGains == 3 */ 628 } 629 } 630 return AH_TRUE; 631 #undef EEREAD 632 } 633 634 static void 635 ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal) 636 { 637 uint16_t i, j, kk, channelValue; 638 uint16_t xpd_mask; 639 uint16_t numPdGainsUsed; 640 641 pRaw->numChannels = pCal->numChannels; 642 643 xpd_mask = pRaw->xpd_mask; 644 numPdGainsUsed = 0; 645 if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; 646 if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; 647 if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; 648 if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; 649 650 for (i = 0; i < pCal->numChannels; i++) { 651 channelValue = pCal->pChannels[i]; 652 653 pRaw->pChannels[i] = channelValue; 654 655 pRaw->pDataPerChannel[i].channelValue = channelValue; 656 pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed; 657 658 kk = 0; 659 for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) { 660 pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j; 661 if ((xpd_mask >> j) & 0x1) { 662 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS; 663 kk++; 664 if (kk == 1) { 665 /* 666 * lowest pd_gain corresponds 667 * to highest power and thus, 668 * has one more point 669 */ 670 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN; 671 } 672 } else { 673 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0; 674 } 675 } 676 } 677 } 678 679 static HAL_BOOL 680 ar2413EepromToRawDataset(struct ath_hal *ah, 681 EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw) 682 { 683 uint16_t ii, jj, kk, ss; 684 RAW_DATA_PER_PDGAIN_2413 *pRawXPD; 685 /* ptr to array of info held per channel */ 686 EEPROM_DATA_PER_CHANNEL_2413 *pCalCh; 687 uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL]; 688 uint16_t xpd_mask; 689 uint32_t numPdGainsUsed; 690 691 HALASSERT(pRaw->xpd_mask == pCal->xpd_mask); 692 693 xgain_list[0] = 0xDEAD; 694 xgain_list[1] = 0xDEAD; 695 xgain_list[2] = 0xDEAD; 696 xgain_list[3] = 0xDEAD; 697 698 numPdGainsUsed = 0; 699 xpd_mask = pRaw->xpd_mask; 700 for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) { 701 if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1) 702 xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1; 703 } 704 705 pRaw->numChannels = pCal->numChannels; 706 for (ii = 0; ii < pRaw->numChannels; ii++) { 707 pCalCh = &(pCal->pDataPerChannel[ii]); 708 pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue; 709 710 /* numVpd has already been setup appropriately for the relevant pdGains */ 711 for (jj = 0; jj < numPdGainsUsed; jj++) { 712 /* use jj for calDataset and ss for rawDataset */ 713 ss = xgain_list[jj]; 714 pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]); 715 HALASSERT(pRawXPD->numVpd >= 1); 716 717 pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]); 718 pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj]; 719 720 for (kk = 1; kk < pRawXPD->numVpd; kk++) { 721 pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]); 722 pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]); 723 } 724 /* loop over Vpds */ 725 } 726 /* loop over pd_gains */ 727 } 728 /* loop over channels */ 729 return AH_TRUE; 730 } 731 732 static HAL_BOOL 733 readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee) 734 { 735 /* NB: index is 1 less than numPdgains */ 736 static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 }; 737 EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL; 738 RAW_DATA_STRUCT_2413 *pRaw; 739 int numEEPROMWordsPerChannel; 740 uint32_t off; 741 HAL_BOOL ret = AH_FALSE; 742 743 HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0); 744 HALASSERT(ee->ee_eepMap == 2); 745 746 pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413)); 747 if (pCal == AH_NULL) 748 goto exit; 749 750 off = ee->ee_eepMap2PowerCalStart; 751 if (ee->ee_Amode) { 752 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 753 pCal->xpd_mask = ee->ee_xgain[headerInfo11A]; 754 if (!ar2413ReadCalDataset(ah, ee, pCal, off, 755 NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) { 756 goto exit; 757 } 758 pRaw = &ee->ee_rawDataset2413[headerInfo11A]; 759 pRaw->xpd_mask = ee->ee_xgain[headerInfo11A]; 760 ar2413SetupRawDataset(pRaw, pCal); 761 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 762 goto exit; 763 } 764 /* setup offsets for mode_11a next */ 765 numEEPROMWordsPerChannel = wordsForPdgains[ 766 pCal->pDataPerChannel[0].numPdGains - 1]; 767 off += pCal->numChannels * numEEPROMWordsPerChannel + 5; 768 } 769 if (ee->ee_Bmode) { 770 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 771 pCal->xpd_mask = ee->ee_xgain[headerInfo11B]; 772 if (!ar2413ReadCalDataset(ah, ee, pCal, off, 773 NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) { 774 goto exit; 775 } 776 pRaw = &ee->ee_rawDataset2413[headerInfo11B]; 777 pRaw->xpd_mask = ee->ee_xgain[headerInfo11B]; 778 ar2413SetupRawDataset(pRaw, pCal); 779 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 780 goto exit; 781 } 782 /* setup offsets for mode_11g next */ 783 numEEPROMWordsPerChannel = wordsForPdgains[ 784 pCal->pDataPerChannel[0].numPdGains - 1]; 785 off += pCal->numChannels * numEEPROMWordsPerChannel + 2; 786 } 787 if (ee->ee_Gmode) { 788 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 789 pCal->xpd_mask = ee->ee_xgain[headerInfo11G]; 790 if (!ar2413ReadCalDataset(ah, ee, pCal, off, 791 NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) { 792 goto exit; 793 } 794 pRaw = &ee->ee_rawDataset2413[headerInfo11G]; 795 pRaw->xpd_mask = ee->ee_xgain[headerInfo11G]; 796 ar2413SetupRawDataset(pRaw, pCal); 797 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 798 goto exit; 799 } 800 } 801 ret = AH_TRUE; 802 exit: 803 if (pCal != AH_NULL) 804 ath_hal_free(pCal); 805 return ret; 806 } 807 808 /* 809 * Now copy EEPROM Raw Power Calibration per frequency contents 810 * into the allocated space 811 */ 812 static HAL_BOOL 813 readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) 814 { 815 #define EEREAD(_off) do { \ 816 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 817 return AH_FALSE; \ 818 } while (0) 819 uint16_t eeval, nchan; 820 uint32_t off; 821 int i, j, mode; 822 823 if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) 824 return readEepromRawPowerCalInfo5112(ah, ee); 825 if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2) 826 return readEepromRawPowerCalInfo2413(ah, ee); 827 828 /* 829 * Group 2: read raw power data for all frequency piers 830 * 831 * NOTE: Group 2 contains the raw power calibration 832 * information for each of the channels that 833 * we recorded above. 834 */ 835 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 836 uint16_t *pChannels = AH_NULL; 837 DATA_PER_CHANNEL *pChannelData = AH_NULL; 838 839 off = ee->ee_version >= AR_EEPROM_VER3_3 ? 840 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; 841 switch (mode) { 842 case headerInfo11A: 843 off += GROUP2_OFFSET; 844 nchan = ee->ee_numChannels11a; 845 pChannelData = ee->ee_dataPerChannel11a; 846 pChannels = ee->ee_channels11a; 847 break; 848 case headerInfo11B: 849 if (!ee->ee_Bmode) 850 continue; 851 off += GROUP3_OFFSET; 852 nchan = ee->ee_numChannels2_4; 853 pChannelData = ee->ee_dataPerChannel11b; 854 pChannels = ee->ee_channels11b; 855 break; 856 case headerInfo11G: 857 if (!ee->ee_Gmode) 858 continue; 859 off += GROUP4_OFFSET; 860 nchan = ee->ee_numChannels2_4; 861 pChannelData = ee->ee_dataPerChannel11g; 862 pChannels = ee->ee_channels11g; 863 break; 864 default: 865 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 866 __func__, mode); 867 return AH_FALSE; 868 } 869 for (i = 0; i < nchan; i++) { 870 pChannelData->channelValue = pChannels[i]; 871 872 EEREAD(off++); 873 pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK); 874 pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK); 875 pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK); 876 877 EEREAD(off++); 878 pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3); 879 pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK); 880 pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK); 881 pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK); 882 883 EEREAD(off++); 884 pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf); 885 pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK); 886 pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK); 887 888 EEREAD(off++); 889 pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK); 890 pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK); 891 pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK); 892 893 EEREAD(off++); 894 pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3); 895 pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK); 896 pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK); 897 898 getPcdacInterceptsFromPcdacMinMax(ee, 899 pChannelData->pcdacMin, pChannelData->pcdacMax, 900 pChannelData->PcdacValues) ; 901 902 for (j = 0; j < pChannelData->numPcdacValues; j++) { 903 pChannelData->PwrValues[j] = (uint16_t)( 904 PWR_STEP * pChannelData->PwrValues[j]); 905 /* Note these values are scaled up. */ 906 } 907 pChannelData++; 908 } 909 } 910 return AH_TRUE; 911 #undef EEREAD 912 } 913 914 /* 915 * Copy EEPROM Target Power Calbration per rate contents 916 * into the allocated space 917 */ 918 static HAL_BOOL 919 readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) 920 { 921 #define EEREAD(_off) do { \ 922 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 923 return AH_FALSE; \ 924 } while (0) 925 uint16_t eeval, enable24; 926 uint32_t off; 927 int i, mode, nchan; 928 929 enable24 = ee->ee_Bmode || ee->ee_Gmode; 930 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 931 TRGT_POWER_INFO *pPowerInfo; 932 uint16_t *pNumTrgtChannels; 933 934 off = ee->ee_version >= AR_EEPROM_VER4_0 ? 935 ee->ee_targetPowersStart - GROUP5_OFFSET : 936 ee->ee_version >= AR_EEPROM_VER3_3 ? 937 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; 938 switch (mode) { 939 case headerInfo11A: 940 off += GROUP5_OFFSET; 941 nchan = NUM_TEST_FREQUENCIES; 942 pPowerInfo = ee->ee_trgtPwr_11a; 943 pNumTrgtChannels = &ee->ee_numTargetPwr_11a; 944 break; 945 case headerInfo11B: 946 if (!enable24) 947 continue; 948 off += GROUP6_OFFSET; 949 nchan = 2; 950 pPowerInfo = ee->ee_trgtPwr_11b; 951 pNumTrgtChannels = &ee->ee_numTargetPwr_11b; 952 break; 953 case headerInfo11G: 954 if (!enable24) 955 continue; 956 off += GROUP7_OFFSET; 957 nchan = 3; 958 pPowerInfo = ee->ee_trgtPwr_11g; 959 pNumTrgtChannels = &ee->ee_numTargetPwr_11g; 960 break; 961 default: 962 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 963 __func__, mode); 964 return AH_FALSE; 965 } 966 *pNumTrgtChannels = 0; 967 for (i = 0; i < nchan; i++) { 968 EEREAD(off++); 969 if (ee->ee_version >= AR_EEPROM_VER3_3) { 970 pPowerInfo->testChannel = (eeval >> 8) & 0xff; 971 } else { 972 pPowerInfo->testChannel = (eeval >> 9) & 0x7f; 973 } 974 975 if (pPowerInfo->testChannel != 0) { 976 /* get the channel value and read rest of info */ 977 if (mode == headerInfo11A) { 978 pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel); 979 } else { 980 pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel); 981 } 982 983 if (ee->ee_version >= AR_EEPROM_VER3_3) { 984 pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK; 985 pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK; 986 } else { 987 pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK; 988 pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK; 989 } 990 991 EEREAD(off++); 992 if (ee->ee_version >= AR_EEPROM_VER3_3) { 993 pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf; 994 pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK; 995 pPowerInfo->twicePwr54 = eeval & POWER_MASK; 996 } else { 997 pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7; 998 pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK; 999 pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK; 1000 } 1001 (*pNumTrgtChannels)++; 1002 } 1003 pPowerInfo++; 1004 } 1005 } 1006 return AH_TRUE; 1007 #undef EEREAD 1008 } 1009 1010 /* 1011 * Now copy EEPROM Coformance Testing Limits contents 1012 * into the allocated space 1013 */ 1014 static HAL_BOOL 1015 readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee) 1016 { 1017 #define EEREAD(_off) do { \ 1018 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 1019 return AH_FALSE; \ 1020 } while (0) 1021 RD_EDGES_POWER *rep; 1022 uint16_t eeval; 1023 uint32_t off; 1024 int i, j; 1025 1026 rep = ee->ee_rdEdgesPower; 1027 1028 off = GROUP8_OFFSET + 1029 (ee->ee_version >= AR_EEPROM_VER4_0 ? 1030 ee->ee_targetPowersStart - GROUP5_OFFSET : 1031 ee->ee_version >= AR_EEPROM_VER3_3 ? 1032 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2); 1033 for (i = 0; i < ee->ee_numCtls; i++) { 1034 if (ee->ee_ctl[i] == 0) { 1035 /* Move offset and edges */ 1036 off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7); 1037 rep += NUM_EDGES; 1038 continue; 1039 } 1040 if (ee->ee_version >= AR_EEPROM_VER3_3) { 1041 for (j = 0; j < NUM_EDGES; j += 2) { 1042 EEREAD(off++); 1043 rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3; 1044 rep[j+1].rdEdge = eeval & FREQ_MASK_3_3; 1045 } 1046 for (j = 0; j < NUM_EDGES; j += 2) { 1047 EEREAD(off++); 1048 rep[j].twice_rdEdgePower = 1049 (eeval >> 8) & POWER_MASK; 1050 rep[j].flag = (eeval >> 14) & 1; 1051 rep[j+1].twice_rdEdgePower = eeval & POWER_MASK; 1052 rep[j+1].flag = (eeval >> 6) & 1; 1053 } 1054 } else { 1055 EEREAD(off++); 1056 rep[0].rdEdge = (eeval >> 9) & FREQ_MASK; 1057 rep[1].rdEdge = (eeval >> 2) & FREQ_MASK; 1058 rep[2].rdEdge = (eeval << 5) & FREQ_MASK; 1059 1060 EEREAD(off++); 1061 rep[2].rdEdge |= (eeval >> 11) & 0x1f; 1062 rep[3].rdEdge = (eeval >> 4) & FREQ_MASK; 1063 rep[4].rdEdge = (eeval << 3) & FREQ_MASK; 1064 1065 EEREAD(off++); 1066 rep[4].rdEdge |= (eeval >> 13) & 0x7; 1067 rep[5].rdEdge = (eeval >> 6) & FREQ_MASK; 1068 rep[6].rdEdge = (eeval << 1) & FREQ_MASK; 1069 1070 EEREAD(off++); 1071 rep[6].rdEdge |= (eeval >> 15) & 0x1; 1072 rep[7].rdEdge = (eeval >> 8) & FREQ_MASK; 1073 1074 rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK; 1075 rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK; 1076 1077 EEREAD(off++); 1078 rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf; 1079 rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK; 1080 rep[3].twice_rdEdgePower = eeval & POWER_MASK; 1081 1082 EEREAD(off++); 1083 rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK; 1084 rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK; 1085 rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK; 1086 1087 EEREAD(off++); 1088 rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3; 1089 rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK; 1090 } 1091 1092 for (j = 0; j < NUM_EDGES; j++ ) { 1093 if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) { 1094 if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A || 1095 (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) { 1096 rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge); 1097 } else { 1098 rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge); 1099 } 1100 } 1101 } 1102 rep += NUM_EDGES; 1103 } 1104 return AH_TRUE; 1105 #undef EEREAD 1106 } 1107 1108 /* 1109 * Read the individual header fields for a Rev 3 EEPROM 1110 */ 1111 static HAL_BOOL 1112 readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee) 1113 { 1114 #define EEREAD(_off) do { \ 1115 if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 1116 return AH_FALSE; \ 1117 } while (0) 1118 static const uint32_t headerOffset3_0[] = { 1119 0x00C2, /* 0 - Mode bits, device type, max turbo power */ 1120 0x00C4, /* 1 - 2.4 and 5 antenna gain */ 1121 0x00C5, /* 2 - Begin 11A modal section */ 1122 0x00D0, /* 3 - Begin 11B modal section */ 1123 0x00DA, /* 4 - Begin 11G modal section */ 1124 0x00E4 /* 5 - Begin CTL section */ 1125 }; 1126 static const uint32_t headerOffset3_3[] = { 1127 0x00C2, /* 0 - Mode bits, device type, max turbo power */ 1128 0x00C3, /* 1 - 2.4 and 5 antenna gain */ 1129 0x00D4, /* 2 - Begin 11A modal section */ 1130 0x00F2, /* 3 - Begin 11B modal section */ 1131 0x010D, /* 4 - Begin 11G modal section */ 1132 0x0128 /* 5 - Begin CTL section */ 1133 }; 1134 1135 static const uint32_t regCapOffsetPre4_0 = 0x00CF; 1136 static const uint32_t regCapOffsetPost4_0 = 0x00CA; 1137 1138 const uint32_t *header; 1139 uint32_t off; 1140 uint16_t eeval; 1141 int i; 1142 1143 /* initialize cckOfdmGainDelta for < 4.2 eeprom */ 1144 ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA; 1145 ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT; 1146 1147 if (ee->ee_version >= AR_EEPROM_VER3_3) { 1148 header = headerOffset3_3; 1149 ee->ee_numCtls = NUM_CTLS_3_3; 1150 } else { 1151 header = headerOffset3_0; 1152 ee->ee_numCtls = NUM_CTLS; 1153 } 1154 HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX); 1155 1156 EEREAD(header[0]); 1157 ee->ee_turbo5Disable = (eeval >> 15) & 0x01; 1158 ee->ee_rfKill = (eeval >> 14) & 0x01; 1159 ee->ee_deviceType = (eeval >> 11) & 0x07; 1160 ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F; 1161 if (ee->ee_version >= AR_EEPROM_VER4_0) 1162 ee->ee_turbo2Disable = (eeval >> 3) & 0x01; 1163 else 1164 ee->ee_turbo2Disable = 1; 1165 ee->ee_Gmode = (eeval >> 2) & 0x01; 1166 ee->ee_Bmode = (eeval >> 1) & 0x01; 1167 ee->ee_Amode = (eeval & 0x01); 1168 1169 off = header[1]; 1170 EEREAD(off++); 1171 ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF); 1172 ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF); 1173 if (ee->ee_version >= AR_EEPROM_VER4_0) { 1174 EEREAD(off++); 1175 ee->ee_eepMap = (eeval>>14) & 0x3; 1176 ee->ee_disableXr5 = (eeval>>13) & 0x1; 1177 ee->ee_disableXr2 = (eeval>>12) & 0x1; 1178 ee->ee_earStart = eeval & 0xfff; 1179 1180 EEREAD(off++); 1181 ee->ee_targetPowersStart = eeval & 0xfff; 1182 ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1; 1183 1184 if (ee->ee_version >= AR_EEPROM_VER5_0) { 1185 off += 2; 1186 EEREAD(off); 1187 ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff; 1188 /* Properly cal'ed 5.0 devices should be non-zero */ 1189 } 1190 } 1191 1192 /* Read the moded sections of the EEPROM header in the order A, B, G */ 1193 for (i = headerInfo11A; i <= headerInfo11G; i++) { 1194 /* Set the offset via the index */ 1195 off = header[2 + i]; 1196 1197 EEREAD(off++); 1198 ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f; 1199 ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f; 1200 ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f; 1201 1202 EEREAD(off++); 1203 ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f; 1204 ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f; 1205 ee->ee_antennaControl[2][i] = eeval & 0x3f; 1206 1207 EEREAD(off++); 1208 ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f; 1209 ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f; 1210 ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f; 1211 1212 EEREAD(off++); 1213 ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03; 1214 ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f; 1215 ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f; 1216 ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f; 1217 1218 EEREAD(off++); 1219 ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f; 1220 ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f; 1221 ee->ee_antennaControl[10][i] = eeval & 0x3f; 1222 1223 EEREAD(off++); 1224 ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); 1225 switch (i) { 1226 case headerInfo11A: 1227 ee->ee_ob4 = (eeval >> 5) & 0x07; 1228 ee->ee_db4 = (eeval >> 2) & 0x07; 1229 ee->ee_ob3 = (eeval << 1) & 0x07; 1230 break; 1231 case headerInfo11B: 1232 ee->ee_obFor24 = (eeval >> 4) & 0x07; 1233 ee->ee_dbFor24 = eeval & 0x07; 1234 break; 1235 case headerInfo11G: 1236 ee->ee_obFor24g = (eeval >> 4) & 0x07; 1237 ee->ee_dbFor24g = eeval & 0x07; 1238 break; 1239 } 1240 1241 if (i == headerInfo11A) { 1242 EEREAD(off++); 1243 ee->ee_ob3 |= (eeval >> 15) & 0x01; 1244 ee->ee_db3 = (eeval >> 12) & 0x07; 1245 ee->ee_ob2 = (eeval >> 9) & 0x07; 1246 ee->ee_db2 = (eeval >> 6) & 0x07; 1247 ee->ee_ob1 = (eeval >> 3) & 0x07; 1248 ee->ee_db1 = eeval & 0x07; 1249 } 1250 1251 EEREAD(off++); 1252 ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff; 1253 ee->ee_thresh62[i] = eeval & 0xff; 1254 1255 EEREAD(off++); 1256 ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff; 1257 ee->ee_txFrameToXPAOn[i] = eeval & 0xff; 1258 1259 EEREAD(off++); 1260 ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); 1261 ee->ee_noiseFloorThresh[i] = eeval & 0xff; 1262 if (ee->ee_noiseFloorThresh[i] & 0x80) { 1263 ee->ee_noiseFloorThresh[i] = 0 - 1264 ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1); 1265 } 1266 1267 EEREAD(off++); 1268 ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff; 1269 ee->ee_xgain[i] = (eeval >> 1) & 0x0f; 1270 ee->ee_xpd[i] = eeval & 0x01; 1271 if (ee->ee_version >= AR_EEPROM_VER4_0) { 1272 switch (i) { 1273 case headerInfo11A: 1274 ee->ee_fixedBias5 = (eeval >> 13) & 0x1; 1275 break; 1276 case headerInfo11G: 1277 ee->ee_fixedBias2 = (eeval >> 13) & 0x1; 1278 break; 1279 } 1280 } 1281 1282 if (ee->ee_version >= AR_EEPROM_VER3_3) { 1283 EEREAD(off++); 1284 ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F; 1285 switch (i) { 1286 case headerInfo11B: 1287 ee->ee_ob2GHz[0] = eeval & 0x7; 1288 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; 1289 break; 1290 case headerInfo11G: 1291 ee->ee_ob2GHz[1] = eeval & 0x7; 1292 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; 1293 break; 1294 case headerInfo11A: 1295 ee->ee_xrTargetPower5 = eeval & 0x3f; 1296 break; 1297 } 1298 } 1299 if (ee->ee_version >= AR_EEPROM_VER3_4) { 1300 ee->ee_gainI[i] = (eeval >> 13) & 0x07; 1301 1302 EEREAD(off++); 1303 ee->ee_gainI[i] |= (eeval << 3) & 0x38; 1304 if (i == headerInfo11G) { 1305 ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF; 1306 if (ee->ee_version >= AR_EEPROM_VER4_6) 1307 ee->ee_scaledCh14FilterCckDelta = 1308 (eeval >> 11) & 0x1f; 1309 } 1310 if (i == headerInfo11A && 1311 ee->ee_version >= AR_EEPROM_VER4_0) { 1312 ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f; 1313 ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f; 1314 } 1315 } else { 1316 ee->ee_gainI[i] = 10; 1317 ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT; 1318 } 1319 if (ee->ee_version >= AR_EEPROM_VER4_0) { 1320 switch (i) { 1321 case headerInfo11B: 1322 EEREAD(off++); 1323 ee->ee_calPier11b[0] = 1324 fbin2freq_2p4(ee, eeval&0xff); 1325 ee->ee_calPier11b[1] = 1326 fbin2freq_2p4(ee, (eeval >> 8)&0xff); 1327 EEREAD(off++); 1328 ee->ee_calPier11b[2] = 1329 fbin2freq_2p4(ee, eeval&0xff); 1330 if (ee->ee_version >= AR_EEPROM_VER4_1) 1331 ee->ee_rxtxMargin[headerInfo11B] = 1332 (eeval >> 8) & 0x3f; 1333 break; 1334 case headerInfo11G: 1335 EEREAD(off++); 1336 ee->ee_calPier11g[0] = 1337 fbin2freq_2p4(ee, eeval & 0xff); 1338 ee->ee_calPier11g[1] = 1339 fbin2freq_2p4(ee, (eeval >> 8) & 0xff); 1340 1341 EEREAD(off++); 1342 ee->ee_turbo2WMaxPower2 = eeval & 0x7F; 1343 ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f; 1344 1345 EEREAD(off++); 1346 ee->ee_calPier11g[2] = 1347 fbin2freq_2p4(ee, eeval & 0xff); 1348 if (ee->ee_version >= AR_EEPROM_VER4_1) 1349 ee->ee_rxtxMargin[headerInfo11G] = 1350 (eeval >> 8) & 0x3f; 1351 1352 EEREAD(off++); 1353 ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F; 1354 ee->ee_iqCalQ[1] = eeval & 0x1F; 1355 1356 if (ee->ee_version >= AR_EEPROM_VER4_2) { 1357 EEREAD(off++); 1358 ee->ee_cckOfdmGainDelta = 1359 (uint8_t)(eeval & 0xFF); 1360 if (ee->ee_version >= AR_EEPROM_VER5_0) { 1361 ee->ee_switchSettlingTurbo[1] = 1362 (eeval >> 8) & 0x7f; 1363 ee->ee_txrxAttenTurbo[1] = 1364 (eeval >> 15) & 0x1; 1365 EEREAD(off++); 1366 ee->ee_txrxAttenTurbo[1] |= 1367 (eeval & 0x1F) << 1; 1368 ee->ee_rxtxMarginTurbo[1] = 1369 (eeval >> 5) & 0x3F; 1370 ee->ee_adcDesiredSizeTurbo[1] = 1371 (eeval >> 11) & 0x1F; 1372 EEREAD(off++); 1373 ee->ee_adcDesiredSizeTurbo[1] |= 1374 (eeval & 0x7) << 5; 1375 ee->ee_pgaDesiredSizeTurbo[1] = 1376 (eeval >> 3) & 0xFF; 1377 } 1378 } 1379 break; 1380 case headerInfo11A: 1381 if (ee->ee_version >= AR_EEPROM_VER4_1) { 1382 EEREAD(off++); 1383 ee->ee_rxtxMargin[headerInfo11A] = 1384 eeval & 0x3f; 1385 if (ee->ee_version >= AR_EEPROM_VER5_0) { 1386 ee->ee_switchSettlingTurbo[0] = 1387 (eeval >> 6) & 0x7f; 1388 ee->ee_txrxAttenTurbo[0] = 1389 (eeval >> 13) & 0x7; 1390 EEREAD(off++); 1391 ee->ee_txrxAttenTurbo[0] |= 1392 (eeval & 0x7) << 3; 1393 ee->ee_rxtxMarginTurbo[0] = 1394 (eeval >> 3) & 0x3F; 1395 ee->ee_adcDesiredSizeTurbo[0] = 1396 (eeval >> 9) & 0x7F; 1397 EEREAD(off++); 1398 ee->ee_adcDesiredSizeTurbo[0] |= 1399 (eeval & 0x1) << 7; 1400 ee->ee_pgaDesiredSizeTurbo[0] = 1401 (eeval >> 1) & 0xFF; 1402 } 1403 } 1404 break; 1405 } 1406 } 1407 } 1408 if (ee->ee_version < AR_EEPROM_VER3_3) { 1409 /* Version 3.1+ specific parameters */ 1410 EEREAD(0xec); 1411 ee->ee_ob2GHz[0] = eeval & 0x7; 1412 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; 1413 1414 EEREAD(0xed); 1415 ee->ee_ob2GHz[1] = eeval & 0x7; 1416 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; 1417 } 1418 1419 /* Initialize corner cal (thermal tx gain adjust parameters) */ 1420 ee->ee_cornerCal.clip = 4; 1421 ee->ee_cornerCal.pd90 = 1; 1422 ee->ee_cornerCal.pd84 = 1; 1423 ee->ee_cornerCal.gSel = 0; 1424 1425 /* 1426 * Read the conformance test limit identifiers 1427 * These are used to match regulatory domain testing needs with 1428 * the RD-specific tests that have been calibrated in the EEPROM. 1429 */ 1430 off = header[5]; 1431 for (i = 0; i < ee->ee_numCtls; i += 2) { 1432 EEREAD(off++); 1433 ee->ee_ctl[i] = (eeval >> 8) & 0xff; 1434 ee->ee_ctl[i+1] = eeval & 0xff; 1435 } 1436 1437 if (ee->ee_version < AR_EEPROM_VER5_3) { 1438 /* XXX only for 5413? */ 1439 ee->ee_spurChans[0][1] = AR_SPUR_5413_1; 1440 ee->ee_spurChans[1][1] = AR_SPUR_5413_2; 1441 ee->ee_spurChans[2][1] = AR_NO_SPUR; 1442 ee->ee_spurChans[0][0] = AR_NO_SPUR; 1443 } else { 1444 /* Read spur mitigation data */ 1445 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { 1446 EEREAD(off); 1447 ee->ee_spurChans[i][0] = eeval; 1448 EEREAD(off+AR_EEPROM_MODAL_SPURS); 1449 ee->ee_spurChans[i][1] = eeval; 1450 off++; 1451 } 1452 } 1453 1454 /* for recent changes to NF scale */ 1455 if (ee->ee_version <= AR_EEPROM_VER3_2) { 1456 ee->ee_noiseFloorThresh[headerInfo11A] = -54; 1457 ee->ee_noiseFloorThresh[headerInfo11B] = -1; 1458 ee->ee_noiseFloorThresh[headerInfo11G] = -1; 1459 } 1460 /* to override thresh62 for better 2.4 and 5 operation */ 1461 if (ee->ee_version <= AR_EEPROM_VER3_2) { 1462 ee->ee_thresh62[headerInfo11A] = 15; /* 11A */ 1463 ee->ee_thresh62[headerInfo11B] = 28; /* 11B */ 1464 ee->ee_thresh62[headerInfo11G] = 28; /* 11G */ 1465 } 1466 1467 /* Check for regulatory capabilities */ 1468 if (ee->ee_version >= AR_EEPROM_VER4_0) { 1469 EEREAD(regCapOffsetPost4_0); 1470 } else { 1471 EEREAD(regCapOffsetPre4_0); 1472 } 1473 1474 ee->ee_regCap = eeval; 1475 1476 if (ee->ee_Amode == 0) { 1477 /* Check for valid Amode in upgraded h/w */ 1478 if (ee->ee_version >= AR_EEPROM_VER4_0) { 1479 ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0; 1480 } else { 1481 ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0; 1482 } 1483 } 1484 1485 if (ee->ee_version >= AR_EEPROM_VER5_1) 1486 EEREAD(AR_EEPROM_CAPABILITIES_OFFSET); 1487 else 1488 eeval = 0; 1489 ee->ee_opCap = eeval; 1490 1491 EEREAD(AR_EEPROM_REG_DOMAIN); 1492 ee->ee_regdomain = eeval; 1493 1494 return AH_TRUE; 1495 #undef EEREAD 1496 } 1497 1498 /* 1499 * Now verify and copy EEPROM contents into the allocated space 1500 */ 1501 static HAL_BOOL 1502 legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee) 1503 { 1504 /* Read the header information here */ 1505 if (!readHeaderInfo(ah, ee)) 1506 return AH_FALSE; 1507 #if 0 1508 /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */ 1509 if (IS_5112(ah) && !ee->ee_eepMap) { 1510 HALDEBUG(ah, HAL_DEBUG_ANY, 1511 "%s: 5112 devices must have EEPROM 4.0 with the " 1512 "EEP_MAP set\n", __func__); 1513 return AH_FALSE; 1514 } 1515 #endif 1516 /* 1517 * Group 1: frequency pier locations readback 1518 * check that the structure has been populated 1519 * with enough space to hold the channels 1520 * 1521 * NOTE: Group 1 contains the 5 GHz channel numbers 1522 * that have dBm->pcdac calibrated information. 1523 */ 1524 if (!readEepromFreqPierInfo(ah, ee)) 1525 return AH_FALSE; 1526 1527 /* 1528 * Group 2: readback data for all frequency piers 1529 * 1530 * NOTE: Group 2 contains the raw power calibration 1531 * information for each of the channels that we 1532 * recorded above. 1533 */ 1534 if (!readEepromRawPowerCalInfo(ah, ee)) 1535 return AH_FALSE; 1536 1537 /* 1538 * Group 5: target power values per rate 1539 * 1540 * NOTE: Group 5 contains the recorded maximum power 1541 * in dB that can be attained for the given rate. 1542 */ 1543 /* Read the power per rate info for test channels */ 1544 if (!readEepromTargetPowerCalInfo(ah, ee)) 1545 return AH_FALSE; 1546 1547 /* 1548 * Group 8: Conformance Test Limits information 1549 * 1550 * NOTE: Group 8 contains the values to limit the 1551 * maximum transmit power value based on any 1552 * band edge violations. 1553 */ 1554 /* Read the RD edge power limits */ 1555 return readEepromCTLInfo(ah, ee); 1556 } 1557 1558 static HAL_STATUS 1559 legacyEepromGet(struct ath_hal *ah, int param, void *val) 1560 { 1561 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1562 uint8_t *macaddr; 1563 uint16_t eeval; 1564 uint32_t sum; 1565 int i; 1566 1567 switch (param) { 1568 case AR_EEP_OPCAP: 1569 *(uint16_t *) val = ee->ee_opCap; 1570 return HAL_OK; 1571 case AR_EEP_REGDMN_0: 1572 *(uint16_t *) val = ee->ee_regdomain; 1573 return HAL_OK; 1574 case AR_EEP_RFSILENT: 1575 if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval)) 1576 return HAL_EEREAD; 1577 *(uint16_t *) val = eeval; 1578 return HAL_OK; 1579 case AR_EEP_MACADDR: 1580 sum = 0; 1581 macaddr = val; 1582 for (i = 0; i < 3; i++) { 1583 if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) { 1584 HALDEBUG(ah, HAL_DEBUG_ANY, 1585 "%s: cannot read EEPROM location %u\n", 1586 __func__, i); 1587 return HAL_EEREAD; 1588 } 1589 sum += eeval; 1590 macaddr[2*i] = eeval >> 8; 1591 macaddr[2*i + 1] = eeval & 0xff; 1592 } 1593 if (sum == 0 || sum == 0xffff*3) { 1594 HALDEBUG(ah, HAL_DEBUG_ANY, 1595 "%s: mac address read failed: %s\n", __func__, 1596 ath_hal_ether_sprintf(macaddr)); 1597 return HAL_EEBADMAC; 1598 } 1599 return HAL_OK; 1600 case AR_EEP_RFKILL: 1601 HALASSERT(val == AH_NULL); 1602 return ee->ee_rfKill ? HAL_OK : HAL_EIO; 1603 case AR_EEP_AMODE: 1604 HALASSERT(val == AH_NULL); 1605 return ee->ee_Amode ? HAL_OK : HAL_EIO; 1606 case AR_EEP_BMODE: 1607 HALASSERT(val == AH_NULL); 1608 return ee->ee_Bmode ? HAL_OK : HAL_EIO; 1609 case AR_EEP_GMODE: 1610 HALASSERT(val == AH_NULL); 1611 return ee->ee_Gmode ? HAL_OK : HAL_EIO; 1612 case AR_EEP_TURBO5DISABLE: 1613 HALASSERT(val == AH_NULL); 1614 return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO; 1615 case AR_EEP_TURBO2DISABLE: 1616 HALASSERT(val == AH_NULL); 1617 return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO; 1618 case AR_EEP_ISTALON: /* Talon detect */ 1619 HALASSERT(val == AH_NULL); 1620 return (ee->ee_version >= AR_EEPROM_VER5_4 && 1621 ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ? 1622 HAL_OK : HAL_EIO; 1623 case AR_EEP_32KHZCRYSTAL: 1624 HALASSERT(val == AH_NULL); 1625 return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO; 1626 case AR_EEP_COMPRESS: 1627 HALASSERT(val == AH_NULL); 1628 return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ? 1629 HAL_OK : HAL_EIO; 1630 case AR_EEP_FASTFRAME: 1631 HALASSERT(val == AH_NULL); 1632 return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ? 1633 HAL_OK : HAL_EIO; 1634 case AR_EEP_AES: 1635 HALASSERT(val == AH_NULL); 1636 return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ? 1637 HAL_OK : HAL_EIO; 1638 case AR_EEP_BURST: 1639 HALASSERT(val == AH_NULL); 1640 return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ? 1641 HAL_OK : HAL_EIO; 1642 case AR_EEP_MAXQCU: 1643 if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) { 1644 *(uint16_t *) val = 1645 MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU); 1646 return HAL_OK; 1647 } else 1648 return HAL_EIO; 1649 case AR_EEP_KCENTRIES: 1650 if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) { 1651 *(uint16_t *) val = 1652 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES); 1653 return HAL_OK; 1654 } else 1655 return HAL_EIO; 1656 case AR_EEP_ANTGAINMAX_5: 1657 *(int8_t *) val = ee->ee_antennaGainMax[0]; 1658 return HAL_OK; 1659 case AR_EEP_ANTGAINMAX_2: 1660 *(int8_t *) val = ee->ee_antennaGainMax[1]; 1661 return HAL_OK; 1662 case AR_EEP_WRITEPROTECT: 1663 HALASSERT(val == AH_NULL); 1664 return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ? 1665 HAL_OK : HAL_EIO; 1666 } 1667 return HAL_EINVAL; 1668 } 1669 1670 static HAL_STATUS 1671 legacyEepromSet(struct ath_hal *ah, int param, int v) 1672 { 1673 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1674 1675 switch (param) { 1676 case AR_EEP_AMODE: 1677 ee->ee_Amode = v; 1678 return HAL_OK; 1679 case AR_EEP_BMODE: 1680 ee->ee_Bmode = v; 1681 return HAL_OK; 1682 case AR_EEP_GMODE: 1683 ee->ee_Gmode = v; 1684 return HAL_OK; 1685 case AR_EEP_TURBO5DISABLE: 1686 ee->ee_turbo5Disable = v; 1687 return HAL_OK; 1688 case AR_EEP_TURBO2DISABLE: 1689 ee->ee_turbo2Disable = v; 1690 return HAL_OK; 1691 case AR_EEP_COMPRESS: 1692 if (v) 1693 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS; 1694 else 1695 ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS; 1696 return HAL_OK; 1697 case AR_EEP_FASTFRAME: 1698 if (v) 1699 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS; 1700 else 1701 ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS; 1702 return HAL_OK; 1703 case AR_EEP_AES: 1704 if (v) 1705 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS; 1706 else 1707 ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS; 1708 return HAL_OK; 1709 case AR_EEP_BURST: 1710 if (v) 1711 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS; 1712 else 1713 ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS; 1714 return HAL_OK; 1715 } 1716 return HAL_EINVAL; 1717 } 1718 1719 static HAL_BOOL 1720 legacyEepromDiag(struct ath_hal *ah, int request, 1721 const void *args, uint32_t argsize, void **result, uint32_t *resultsize) 1722 { 1723 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1724 const EEPROM_POWER_EXPN_5112 *pe; 1725 1726 switch (request) { 1727 case HAL_DIAG_EEPROM: 1728 *result = ee; 1729 *resultsize = sizeof(*ee); 1730 return AH_TRUE; 1731 case HAL_DIAG_EEPROM_EXP_11A: 1732 case HAL_DIAG_EEPROM_EXP_11B: 1733 case HAL_DIAG_EEPROM_EXP_11G: 1734 pe = &ee->ee_modePowerArray5112[ 1735 request - HAL_DIAG_EEPROM_EXP_11A]; 1736 *result = pe->pChannels; 1737 *resultsize = (*result == AH_NULL) ? 0 : 1738 roundup(sizeof(uint16_t) * pe->numChannels, 1739 sizeof(uint32_t)) + 1740 sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels; 1741 return AH_TRUE; 1742 } 1743 return AH_FALSE; 1744 } 1745 1746 static uint16_t 1747 legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) 1748 { 1749 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1750 1751 HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS); 1752 return ee->ee_spurChans[ix][is2GHz]; 1753 } 1754 1755 /* 1756 * Reclaim any EEPROM-related storage. 1757 */ 1758 static void 1759 legacyEepromDetach(struct ath_hal *ah) 1760 { 1761 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1762 1763 if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) 1764 freeEepromRawPowerCalInfo5112(ah, ee); 1765 ath_hal_free(ee); 1766 AH_PRIVATE(ah)->ah_eeprom = AH_NULL; 1767 } 1768 1769 /* 1770 * These are not valid 2.4 channels, either we change 'em 1771 * or we need to change the coding to accept them. 1772 */ 1773 static const uint16_t channels11b[] = { 2412, 2447, 2484 }; 1774 static const uint16_t channels11g[] = { 2312, 2412, 2484 }; 1775 1776 HAL_STATUS 1777 ath_hal_legacyEepromAttach(struct ath_hal *ah) 1778 { 1779 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1780 uint32_t sum, eepMax; 1781 uint16_t eeversion, eeprotect, eeval; 1782 u_int i; 1783 1784 HALASSERT(ee == AH_NULL); 1785 1786 if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) { 1787 HALDEBUG(ah, HAL_DEBUG_ANY, 1788 "%s: unable to read EEPROM version\n", __func__); 1789 return HAL_EEREAD; 1790 } 1791 if (eeversion < AR_EEPROM_VER3) { 1792 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version " 1793 "%u (0x%x) found\n", __func__, eeversion, eeversion); 1794 return HAL_EEVERSION; 1795 } 1796 1797 if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) { 1798 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection " 1799 "bits; read locked?\n", __func__); 1800 return HAL_EEREAD; 1801 } 1802 HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect); 1803 /* XXX check proper access before continuing */ 1804 1805 /* 1806 * Read the Atheros EEPROM entries and calculate the checksum. 1807 */ 1808 if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) { 1809 HALDEBUG(ah, HAL_DEBUG_ANY, 1810 "%s: cannot read EEPROM upper size\n" , __func__); 1811 return HAL_EEREAD; 1812 } 1813 if (eeval != 0) { 1814 eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) << 1815 AR_EEPROM_SIZE_ENDLOC_SHIFT; 1816 if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) { 1817 HALDEBUG(ah, HAL_DEBUG_ANY, 1818 "%s: cannot read EEPROM lower size\n" , __func__); 1819 return HAL_EEREAD; 1820 } 1821 eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE; 1822 } else 1823 eepMax = AR_EEPROM_ATHEROS_MAX; 1824 sum = 0; 1825 for (i = 0; i < eepMax; i++) { 1826 if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) { 1827 return HAL_EEREAD; 1828 } 1829 sum ^= eeval; 1830 } 1831 if (sum != 0xffff) { 1832 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", 1833 __func__, sum); 1834 return HAL_EEBADSUM; 1835 } 1836 1837 ee = ath_hal_malloc(sizeof(HAL_EEPROM)); 1838 if (ee == AH_NULL) { 1839 /* XXX message */ 1840 return HAL_ENOMEM; 1841 } 1842 1843 ee->ee_protect = eeprotect; 1844 ee->ee_version = eeversion; 1845 1846 ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS; 1847 ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS; 1848 1849 for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++) 1850 ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES; 1851 1852 /* the channel list for 2.4 is fixed, fill this in here */ 1853 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) { 1854 ee->ee_channels11b[i] = channels11b[i]; 1855 /* XXX 5211 requires a hack though we don't support 11g */ 1856 if (ah->ah_magic == 0x19570405) 1857 ee->ee_channels11g[i] = channels11b[i]; 1858 else 1859 ee->ee_channels11g[i] = channels11g[i]; 1860 ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES; 1861 ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES; 1862 } 1863 1864 if (!legacyEepromReadContents(ah, ee)) { 1865 /* XXX message */ 1866 ath_hal_free(ee); 1867 return HAL_EEREAD; /* XXX */ 1868 } 1869 1870 AH_PRIVATE(ah)->ah_eeprom = ee; 1871 AH_PRIVATE(ah)->ah_eeversion = eeversion; 1872 AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach; 1873 AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet; 1874 AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet; 1875 AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan; 1876 AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag; 1877 return HAL_OK; 1878 } 1879