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