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