1185377Ssam/* 2185377Ssam * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2008 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17186017Ssam * $FreeBSD: releng/10.3/sys/dev/ath/ath_hal/ah_eeprom_v3.c 221896 2011-05-14 15:12:02Z adrian $ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_eeprom_v3.h" 24185377Ssam 25185377Ssamstatic void 26185377SsamgetPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee, 27185377Ssam uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp) 28185377Ssam{ 29186017Ssam static const uint16_t intercepts3[] = 30185377Ssam { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; 31186017Ssam static const uint16_t intercepts3_2[] = 32185377Ssam { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; 33185377Ssam const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ? 34185377Ssam intercepts3 : intercepts3_2; 35185377Ssam int i; 36185377Ssam 37185377Ssam /* loop for the percentages in steps or 5 */ 38185377Ssam for (i = 0; i < NUM_INTERCEPTS; i++ ) 39185377Ssam *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100; 40185377Ssam} 41185377Ssam 42185377Ssam/* 43185377Ssam * Get channel value from binary representation held in eeprom 44185377Ssam */ 45185377Ssamstatic uint16_t 46185377Ssamfbin2freq(HAL_EEPROM *ee, uint16_t fbin) 47185377Ssam{ 48185377Ssam if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ 49185377Ssam return fbin; 50185377Ssam return ee->ee_version <= AR_EEPROM_VER3_2 ? 51185377Ssam (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) : 52185377Ssam 4800 + 5*fbin; 53185377Ssam} 54185377Ssam 55185377Ssamstatic uint16_t 56185377Ssamfbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin) 57185377Ssam{ 58185377Ssam if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ 59185377Ssam return fbin; 60185377Ssam return ee->ee_version <= AR_EEPROM_VER3_2 ? 61185377Ssam 2400 + fbin : 62185377Ssam 2300 + fbin; 63185377Ssam} 64185377Ssam 65185377Ssam/* 66185377Ssam * Now copy EEPROM frequency pier contents into the allocated space 67185377Ssam */ 68185377Ssamstatic HAL_BOOL 69185377SsamreadEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee) 70185377Ssam{ 71185377Ssam#define EEREAD(_off) do { \ 72185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 73185377Ssam return AH_FALSE; \ 74185377Ssam} while (0) 75185377Ssam uint16_t eeval, off; 76185377Ssam int i; 77185377Ssam 78185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0 && 79185377Ssam ee->ee_eepMap && !ee->ee_Amode) { 80185377Ssam /* 81185377Ssam * V4.0 EEPROMs with map type 1 have frequency pier 82185377Ssam * data only when 11a mode is supported. 83185377Ssam */ 84185377Ssam return AH_TRUE; 85185377Ssam } 86185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 87185377Ssam off = GROUPS_OFFSET3_3 + GROUP1_OFFSET; 88185377Ssam for (i = 0; i < ee->ee_numChannels11a; i += 2) { 89185377Ssam EEREAD(off++); 90185377Ssam ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3; 91185377Ssam ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3; 92185377Ssam } 93185377Ssam } else { 94185377Ssam off = GROUPS_OFFSET3_2 + GROUP1_OFFSET; 95185377Ssam 96185377Ssam EEREAD(off++); 97185377Ssam ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK; 98185377Ssam ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK; 99185377Ssam ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK; 100185377Ssam 101185377Ssam EEREAD(off++); 102185377Ssam ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f; 103185377Ssam ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK; 104185377Ssam ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK; 105185377Ssam 106185377Ssam EEREAD(off++); 107185377Ssam ee->ee_channels11a[4] |= (eeval >> 13) & 0x7; 108185377Ssam ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK; 109185377Ssam ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK; 110185377Ssam 111185377Ssam EEREAD(off++); 112185377Ssam ee->ee_channels11a[6] |= (eeval >> 15) & 0x1; 113185377Ssam ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK; 114185377Ssam ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK; 115185377Ssam ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK; 116185377Ssam 117185377Ssam EEREAD(off++); 118185377Ssam ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f; 119185377Ssam } 120185377Ssam 121185377Ssam for (i = 0; i < ee->ee_numChannels11a; i++) 122185377Ssam ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]); 123185377Ssam 124185377Ssam return AH_TRUE; 125185377Ssam#undef EEREAD 126185377Ssam} 127185377Ssam 128185377Ssam/* 129185377Ssam * Rev 4 Eeprom 5112 Power Extract Functions 130185377Ssam */ 131185377Ssam 132185377Ssam/* 133185377Ssam * Allocate the power information based on the number of channels 134185377Ssam * recorded by the calibration. These values are then initialized. 135185377Ssam */ 136185377Ssamstatic HAL_BOOL 137185377SsameepromAllocExpnPower5112(struct ath_hal *ah, 138185377Ssam const EEPROM_POWER_5112 *pCalDataset, 139185377Ssam EEPROM_POWER_EXPN_5112 *pPowerExpn) 140185377Ssam{ 141185377Ssam uint16_t numChannels = pCalDataset->numChannels; 142185377Ssam const uint16_t *pChanList = pCalDataset->pChannels; 143185377Ssam void *data; 144185377Ssam int i, j; 145185377Ssam 146185377Ssam /* Allocate the channel and Power Data arrays together */ 147185377Ssam data = ath_hal_malloc( 148185377Ssam roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) + 149185377Ssam sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels); 150185377Ssam if (data == AH_NULL) { 151185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 152185377Ssam "%s unable to allocate raw data struct (gen3)\n", __func__); 153185377Ssam return AH_FALSE; 154185377Ssam } 155185377Ssam pPowerExpn->pChannels = data; 156185377Ssam pPowerExpn->pDataPerChannel = (void *)(((char *)data) + 157185377Ssam roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t))); 158185377Ssam 159185377Ssam pPowerExpn->numChannels = numChannels; 160185377Ssam for (i = 0; i < numChannels; i++) { 161185377Ssam pPowerExpn->pChannels[i] = 162185377Ssam pPowerExpn->pDataPerChannel[i].channelValue = 163185377Ssam pChanList[i]; 164185377Ssam for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) { 165185377Ssam pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j; 166185377Ssam pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0; 167185377Ssam } 168185377Ssam pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4; 169185377Ssam pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3; 170185377Ssam } 171185377Ssam return AH_TRUE; 172185377Ssam} 173185377Ssam 174185377Ssam/* 175185377Ssam * Expand the dataSet from the calibration information into the 176185377Ssam * final power structure for 5112 177185377Ssam */ 178185377Ssamstatic HAL_BOOL 179185377SsameepromExpandPower5112(struct ath_hal *ah, 180185377Ssam const EEPROM_POWER_5112 *pCalDataset, 181185377Ssam EEPROM_POWER_EXPN_5112 *pPowerExpn) 182185377Ssam{ 183185377Ssam int ii, jj, kk; 184185377Ssam int16_t maxPower_t4; 185185377Ssam EXPN_DATA_PER_XPD_5112 *pExpnXPD; 186185377Ssam /* ptr to array of info held per channel */ 187185377Ssam const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh; 188185377Ssam uint16_t xgainList[2], xpdMask; 189185377Ssam 190185377Ssam pPowerExpn->xpdMask = pCalDataset->xpdMask; 191185377Ssam 192185377Ssam xgainList[0] = 0xDEAD; 193185377Ssam xgainList[1] = 0xDEAD; 194185377Ssam 195185377Ssam kk = 0; 196185377Ssam xpdMask = pPowerExpn->xpdMask; 197185377Ssam for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { 198185377Ssam if (((xpdMask >> jj) & 1) > 0) { 199185377Ssam if (kk > 1) { 200185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 201185377Ssam "%s: too many xpdGains in dataset: %u\n", 202185377Ssam __func__, kk); 203185377Ssam return AH_FALSE; 204185377Ssam } 205185377Ssam xgainList[kk++] = jj; 206185377Ssam } 207185377Ssam } 208185377Ssam 209185377Ssam pPowerExpn->numChannels = pCalDataset->numChannels; 210185377Ssam if (pPowerExpn->numChannels == 0) { 211185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__); 212185377Ssam return AH_FALSE; 213185377Ssam } 214185377Ssam 215185377Ssam for (ii = 0; ii < pPowerExpn->numChannels; ii++) { 216185377Ssam pCalCh = &pCalDataset->pDataPerChannel[ii]; 217185377Ssam pPowerExpn->pDataPerChannel[ii].channelValue = 218185377Ssam pCalCh->channelValue; 219185377Ssam pPowerExpn->pDataPerChannel[ii].maxPower_t4 = 220185377Ssam pCalCh->maxPower_t4; 221185377Ssam maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4; 222185377Ssam 223185377Ssam for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) 224185377Ssam pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0; 225185377Ssam if (xgainList[1] == 0xDEAD) { 226185377Ssam jj = xgainList[0]; 227185377Ssam pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 228185377Ssam pExpnXPD->numPcdacs = 4; 229185377Ssam pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0; 230185377Ssam pExpnXPD->pcdac[1] = (uint16_t) 231185377Ssam (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); 232185377Ssam pExpnXPD->pcdac[2] = (uint16_t) 233185377Ssam (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); 234185377Ssam pExpnXPD->pcdac[3] = (uint16_t) 235185377Ssam (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); 236185377Ssam 237185377Ssam pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; 238185377Ssam pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; 239185377Ssam pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; 240185377Ssam pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; 241185377Ssam 242185377Ssam } else { 243185377Ssam pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0; 244185377Ssam pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20; 245185377Ssam pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35; 246185377Ssam pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63; 247185377Ssam 248185377Ssam jj = xgainList[0]; 249185377Ssam pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 250185377Ssam pExpnXPD->numPcdacs = 4; 251185377Ssam pExpnXPD->pcdac[1] = (uint16_t) 252185377Ssam (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); 253185377Ssam pExpnXPD->pcdac[2] = (uint16_t) 254185377Ssam (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); 255185377Ssam pExpnXPD->pcdac[3] = (uint16_t) 256185377Ssam (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); 257185377Ssam pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; 258185377Ssam pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; 259185377Ssam pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; 260185377Ssam pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; 261185377Ssam 262185377Ssam jj = xgainList[1]; 263185377Ssam pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; 264185377Ssam pExpnXPD->numPcdacs = 3; 265185377Ssam 266185377Ssam pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3; 267185377Ssam pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3; 268185377Ssam pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3; 269185377Ssam } 270185377Ssam } 271185377Ssam return AH_TRUE; 272185377Ssam} 273185377Ssam 274185377Ssamstatic HAL_BOOL 275185377SsamreadEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) 276185377Ssam{ 277185377Ssam#define EEREAD(_off) do { \ 278185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 279185377Ssam return AH_FALSE; \ 280185377Ssam} while (0) 281185377Ssam const uint16_t dbmmask = 0xff; 282185377Ssam const uint16_t pcdac_delta_mask = 0x1f; 283185377Ssam const uint16_t pcdac_mask = 0x3f; 284185377Ssam const uint16_t freqmask = 0xff; 285185377Ssam 286185377Ssam int i, mode, numPiers; 287185377Ssam uint32_t off; 288185377Ssam uint16_t eeval; 289185377Ssam uint16_t freq[NUM_11A_EEPROM_CHANNELS]; 290185377Ssam EEPROM_POWER_5112 eePower; 291185377Ssam 292185377Ssam HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0); 293185377Ssam off = GROUPS_OFFSET3_3; 294185377Ssam for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 295185377Ssam numPiers = 0; 296185377Ssam switch (mode) { 297185377Ssam case headerInfo11A: 298185377Ssam if (!ee->ee_Amode) /* no 11a calibration data */ 299185377Ssam continue; 300185377Ssam while (numPiers < NUM_11A_EEPROM_CHANNELS) { 301185377Ssam EEREAD(off++); 302185377Ssam if ((eeval & freqmask) == 0) 303185377Ssam break; 304185377Ssam freq[numPiers++] = fbin2freq(ee, 305185377Ssam eeval & freqmask); 306185377Ssam 307185377Ssam if (((eeval >> 8) & freqmask) == 0) 308185377Ssam break; 309185377Ssam freq[numPiers++] = fbin2freq(ee, 310185377Ssam (eeval>>8) & freqmask); 311185377Ssam } 312185377Ssam break; 313185377Ssam case headerInfo11B: 314185377Ssam if (!ee->ee_Bmode) /* no 11b calibration data */ 315185377Ssam continue; 316185377Ssam for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) 317185377Ssam if (ee->ee_calPier11b[i] != CHANNEL_UNUSED) 318185377Ssam freq[numPiers++] = ee->ee_calPier11b[i]; 319185377Ssam break; 320185377Ssam case headerInfo11G: 321185377Ssam if (!ee->ee_Gmode) /* no 11g calibration data */ 322185377Ssam continue; 323185377Ssam for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) 324185377Ssam if (ee->ee_calPier11g[i] != CHANNEL_UNUSED) 325185377Ssam freq[numPiers++] = ee->ee_calPier11g[i]; 326185377Ssam break; 327185377Ssam default: 328185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 329185377Ssam __func__, mode); 330185377Ssam return AH_FALSE; 331185377Ssam } 332185377Ssam 333185377Ssam OS_MEMZERO(&eePower, sizeof(eePower)); 334185377Ssam eePower.numChannels = numPiers; 335185377Ssam 336185377Ssam for (i = 0; i < numPiers; i++) { 337185377Ssam eePower.pChannels[i] = freq[i]; 338185377Ssam eePower.pDataPerChannel[i].channelValue = freq[i]; 339185377Ssam 340185377Ssam EEREAD(off++); 341185377Ssam eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t) 342185377Ssam ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 343185377Ssam eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t) 344185377Ssam (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 345185377Ssam 346185377Ssam EEREAD(off++); 347185377Ssam eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t) 348185377Ssam ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 349185377Ssam eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t) 350185377Ssam (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 351185377Ssam 352185377Ssam EEREAD(off++); 353185377Ssam eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t) 354185377Ssam (eeval & pcdac_delta_mask); 355185377Ssam eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t) 356185377Ssam ((eeval >> 5) & pcdac_delta_mask); 357185377Ssam eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t) 358185377Ssam ((eeval >> 10) & pcdac_delta_mask); 359185377Ssam 360185377Ssam EEREAD(off++); 361185377Ssam eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t) 362185377Ssam ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 363185377Ssam eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t) 364185377Ssam (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); 365185377Ssam 366185377Ssam EEREAD(off++); 367185377Ssam eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t) 368185377Ssam ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); 369185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_3) { 370185377Ssam eePower.pDataPerChannel[i].maxPower_t4 = 371185377Ssam eePower.pDataPerChannel[i].pwr4_xg0; 372185377Ssam eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t) 373185377Ssam ((eeval >> 8) & pcdac_mask); 374185377Ssam } else { 375185377Ssam eePower.pDataPerChannel[i].maxPower_t4 = (int16_t) 376185377Ssam (((eeval >> 8) & dbmmask) - 377185377Ssam ((eeval >> 15) & 0x1)*256); 378185377Ssam eePower.pDataPerChannel[i].pcd1_xg0 = 1; 379185377Ssam } 380185377Ssam } 381185377Ssam eePower.xpdMask = ee->ee_xgain[mode]; 382185377Ssam 383185377Ssam if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { 384185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 385185377Ssam "%s: did not allocate power struct\n", __func__); 386185377Ssam return AH_FALSE; 387185377Ssam } 388185377Ssam if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { 389185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 390185377Ssam "%s: did not expand power struct\n", __func__); 391185377Ssam return AH_FALSE; 392185377Ssam } 393185377Ssam } 394185377Ssam return AH_TRUE; 395185377Ssam#undef EEREAD 396185377Ssam} 397185377Ssam 398185377Ssamstatic void 399185377SsamfreeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee) 400185377Ssam{ 401185377Ssam int mode; 402185377Ssam void *data; 403185377Ssam 404185377Ssam for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 405185377Ssam EEPROM_POWER_EXPN_5112 *pPowerExpn = 406185377Ssam &ee->ee_modePowerArray5112[mode]; 407185377Ssam data = pPowerExpn->pChannels; 408185377Ssam if (data != AH_NULL) { 409185377Ssam pPowerExpn->pChannels = AH_NULL; 410185377Ssam ath_hal_free(data); 411185377Ssam } 412185377Ssam } 413185377Ssam} 414185377Ssam 415185377Ssamstatic void 416185377Ssamar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413, 417185377Ssam uint16_t myNumRawChannels, uint16_t *pMyRawChanList) 418185377Ssam{ 419185377Ssam uint16_t i, channelValue; 420185377Ssam uint32_t xpd_mask; 421185377Ssam uint16_t numPdGainsUsed; 422185377Ssam 423185377Ssam pEEPROMDataset2413->numChannels = myNumRawChannels; 424185377Ssam 425185377Ssam xpd_mask = pEEPROMDataset2413->xpd_mask; 426185377Ssam numPdGainsUsed = 0; 427185377Ssam if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; 428185377Ssam if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; 429185377Ssam if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; 430185377Ssam if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; 431185377Ssam 432185377Ssam for (i = 0; i < myNumRawChannels; i++) { 433185377Ssam channelValue = pMyRawChanList[i]; 434185377Ssam pEEPROMDataset2413->pChannels[i] = channelValue; 435185377Ssam pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue; 436185377Ssam pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed; 437185377Ssam } 438185377Ssam} 439185377Ssam 440185377Ssamstatic HAL_BOOL 441185377Ssamar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee, 442185377Ssam EEPROM_DATA_STRUCT_2413 *pCalDataset, 443185377Ssam uint32_t start_offset, uint32_t maxPiers, uint8_t mode) 444185377Ssam{ 445185377Ssam#define EEREAD(_off) do { \ 446185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 447185377Ssam return AH_FALSE; \ 448185377Ssam} while (0) 449185377Ssam const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */ 450185377Ssam const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */ 451185377Ssam const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */ 452185377Ssam const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */ 453185377Ssam const uint16_t freqmask = 0xff; 454185377Ssam 455185377Ssam uint16_t ii, eeval; 456185377Ssam uint16_t idx, numPiers; 457185377Ssam uint16_t freq[NUM_11A_EEPROM_CHANNELS]; 458185377Ssam 459185377Ssam idx = start_offset; 460185377Ssam for (numPiers = 0; numPiers < maxPiers;) { 461185377Ssam EEREAD(idx++); 462185377Ssam if ((eeval & freqmask) == 0) 463185377Ssam break; 464185377Ssam if (mode == headerInfo11A) 465185377Ssam freq[numPiers++] = fbin2freq(ee, (eeval & freqmask)); 466185377Ssam else 467185377Ssam freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask)); 468185377Ssam 469185377Ssam if (((eeval >> 8) & freqmask) == 0) 470185377Ssam break; 471185377Ssam if (mode == headerInfo11A) 472185377Ssam freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask); 473185377Ssam else 474185377Ssam freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask); 475185377Ssam } 476185377Ssam ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]); 477185377Ssam 478185377Ssam idx = start_offset + (maxPiers / 2); 479185377Ssam for (ii = 0; ii < pCalDataset->numChannels; ii++) { 480185377Ssam EEPROM_DATA_PER_CHANNEL_2413 *currCh = 481185377Ssam &(pCalDataset->pDataPerChannel[ii]); 482185377Ssam 483185377Ssam if (currCh->numPdGains > 0) { 484185377Ssam /* 485185377Ssam * Read the first NUM_POINTS_OTHER_PDGAINS pwr 486185377Ssam * and Vpd values for pdgain_0 487185377Ssam */ 488185377Ssam EEREAD(idx++); 489185377Ssam currCh->pwr_I[0] = eeval & dbm_I_mask; 490185377Ssam currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask; 491185377Ssam currCh->pwr_delta_t2[0][0] = 492185377Ssam (eeval >> 12) & dbm_delta_mask; 493185377Ssam 494185377Ssam EEREAD(idx++); 495185377Ssam currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask; 496185377Ssam currCh->pwr_delta_t2[1][0] = 497185377Ssam (eeval >> 6) & dbm_delta_mask; 498185377Ssam currCh->Vpd_delta[1][0] = 499185377Ssam (eeval >> 10) & Vpd_delta_mask; 500185377Ssam 501185377Ssam EEREAD(idx++); 502185377Ssam currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask; 503185377Ssam currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask; 504185377Ssam } 505185377Ssam 506185377Ssam if (currCh->numPdGains > 1) { 507185377Ssam /* 508185377Ssam * Read the first NUM_POINTS_OTHER_PDGAINS pwr 509185377Ssam * and Vpd values for pdgain_1 510185377Ssam */ 511185377Ssam currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask; 512185377Ssam currCh->Vpd_I[1] = (eeval >> 15) & 0x1; 513185377Ssam 514185377Ssam EEREAD(idx++); 515185377Ssam /* upper 6 bits */ 516185377Ssam currCh->Vpd_I[1] |= (eeval & 0x3F) << 1; 517185377Ssam currCh->pwr_delta_t2[0][1] = 518185377Ssam (eeval >> 6) & dbm_delta_mask; 519185377Ssam currCh->Vpd_delta[0][1] = 520185377Ssam (eeval >> 10) & Vpd_delta_mask; 521185377Ssam 522185377Ssam EEREAD(idx++); 523185377Ssam currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask; 524185377Ssam currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask; 525185377Ssam currCh->pwr_delta_t2[2][1] = 526185377Ssam (eeval >> 10) & dbm_delta_mask; 527185377Ssam currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3; 528185377Ssam 529185377Ssam EEREAD(idx++); 530185377Ssam /* upper 4 bits */ 531185377Ssam currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2; 532185377Ssam } else if (currCh->numPdGains == 1) { 533185377Ssam /* 534185377Ssam * Read the last pwr and Vpd values for pdgain_0 535185377Ssam */ 536185377Ssam currCh->pwr_delta_t2[3][0] = 537185377Ssam (eeval >> 10) & dbm_delta_mask; 538185377Ssam currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3; 539185377Ssam 540185377Ssam EEREAD(idx++); 541185377Ssam /* upper 4 bits */ 542185377Ssam currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2; 543185377Ssam 544185377Ssam /* 4 words if numPdGains == 1 */ 545185377Ssam } 546185377Ssam 547185377Ssam if (currCh->numPdGains > 2) { 548185377Ssam /* 549185377Ssam * Read the first NUM_POINTS_OTHER_PDGAINS pwr 550185377Ssam * and Vpd values for pdgain_2 551185377Ssam */ 552185377Ssam currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask; 553185377Ssam currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask; 554185377Ssam 555185377Ssam EEREAD(idx++); 556185377Ssam currCh->pwr_delta_t2[0][2] = 557185377Ssam (eeval >> 0) & dbm_delta_mask; 558185377Ssam currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask; 559185377Ssam currCh->pwr_delta_t2[1][2] = 560185377Ssam (eeval >> 10) & dbm_delta_mask; 561185377Ssam currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3; 562185377Ssam 563185377Ssam EEREAD(idx++); 564185377Ssam /* upper 4 bits */ 565185377Ssam currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2; 566185377Ssam currCh->pwr_delta_t2[2][2] = 567185377Ssam (eeval >> 4) & dbm_delta_mask; 568185377Ssam currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask; 569185377Ssam } else if (currCh->numPdGains == 2) { 570185377Ssam /* 571185377Ssam * Read the last pwr and Vpd values for pdgain_1 572185377Ssam */ 573185377Ssam currCh->pwr_delta_t2[3][1] = 574185377Ssam (eeval >> 4) & dbm_delta_mask; 575185377Ssam currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask; 576185377Ssam 577185377Ssam /* 6 words if numPdGains == 2 */ 578185377Ssam } 579185377Ssam 580185377Ssam if (currCh->numPdGains > 3) { 581185377Ssam /* 582185377Ssam * Read the first NUM_POINTS_OTHER_PDGAINS pwr 583185377Ssam * and Vpd values for pdgain_3 584185377Ssam */ 585185377Ssam currCh->pwr_I[3] = (eeval >> 14) & 0x3; 586185377Ssam 587185377Ssam EEREAD(idx++); 588185377Ssam /* upper 3 bits */ 589185377Ssam currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2; 590185377Ssam currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask; 591185377Ssam currCh->pwr_delta_t2[0][3] = 592185377Ssam (eeval >> 10) & dbm_delta_mask; 593185377Ssam currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3; 594185377Ssam 595185377Ssam EEREAD(idx++); 596185377Ssam /* upper 4 bits */ 597185377Ssam currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2; 598185377Ssam currCh->pwr_delta_t2[1][3] = 599185377Ssam (eeval >> 4) & dbm_delta_mask; 600185377Ssam currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask; 601185377Ssam currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3; 602185377Ssam 603185377Ssam EEREAD(idx++); 604185377Ssam /* upper 2 bits */ 605185377Ssam currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2; 606185377Ssam currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask; 607185377Ssam currCh->pwr_delta_t2[3][3] = 608185377Ssam (eeval >> 8) & dbm_delta_mask; 609185377Ssam currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF; 610185377Ssam 611185377Ssam EEREAD(idx++); 612185377Ssam /* upper 2 bits */ 613185377Ssam currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4; 614185377Ssam 615185377Ssam /* 12 words if numPdGains == 4 */ 616185377Ssam } else if (currCh->numPdGains == 3) { 617185377Ssam /* read the last pwr and Vpd values for pdgain_2 */ 618185377Ssam currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3; 619185377Ssam 620185377Ssam EEREAD(idx++); 621185377Ssam /* upper 2 bits */ 622185377Ssam currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2; 623185377Ssam currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask; 624185377Ssam 625185377Ssam /* 9 words if numPdGains == 3 */ 626185377Ssam } 627185377Ssam } 628185377Ssam return AH_TRUE; 629185377Ssam#undef EEREAD 630185377Ssam} 631185377Ssam 632185377Ssamstatic void 633185377Ssamar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal) 634185377Ssam{ 635185377Ssam uint16_t i, j, kk, channelValue; 636185377Ssam uint16_t xpd_mask; 637185377Ssam uint16_t numPdGainsUsed; 638185377Ssam 639185377Ssam pRaw->numChannels = pCal->numChannels; 640185377Ssam 641185377Ssam xpd_mask = pRaw->xpd_mask; 642185377Ssam numPdGainsUsed = 0; 643185377Ssam if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; 644185377Ssam if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; 645185377Ssam if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; 646185377Ssam if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; 647185377Ssam 648185377Ssam for (i = 0; i < pCal->numChannels; i++) { 649185377Ssam channelValue = pCal->pChannels[i]; 650185377Ssam 651185377Ssam pRaw->pChannels[i] = channelValue; 652185377Ssam 653185377Ssam pRaw->pDataPerChannel[i].channelValue = channelValue; 654185377Ssam pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed; 655185377Ssam 656185377Ssam kk = 0; 657185377Ssam for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) { 658185377Ssam pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j; 659185377Ssam if ((xpd_mask >> j) & 0x1) { 660185377Ssam pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS; 661185377Ssam kk++; 662185377Ssam if (kk == 1) { 663185377Ssam /* 664185377Ssam * lowest pd_gain corresponds 665185377Ssam * to highest power and thus, 666185377Ssam * has one more point 667185377Ssam */ 668185377Ssam pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN; 669185377Ssam } 670185377Ssam } else { 671185377Ssam pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0; 672185377Ssam } 673185377Ssam } 674185377Ssam } 675185377Ssam} 676185377Ssam 677185377Ssamstatic HAL_BOOL 678185377Ssamar2413EepromToRawDataset(struct ath_hal *ah, 679185377Ssam EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw) 680185377Ssam{ 681185377Ssam uint16_t ii, jj, kk, ss; 682185377Ssam RAW_DATA_PER_PDGAIN_2413 *pRawXPD; 683185377Ssam /* ptr to array of info held per channel */ 684185377Ssam EEPROM_DATA_PER_CHANNEL_2413 *pCalCh; 685185377Ssam uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL]; 686185377Ssam uint16_t xpd_mask; 687185377Ssam uint32_t numPdGainsUsed; 688185377Ssam 689185377Ssam HALASSERT(pRaw->xpd_mask == pCal->xpd_mask); 690185377Ssam 691185377Ssam xgain_list[0] = 0xDEAD; 692185377Ssam xgain_list[1] = 0xDEAD; 693185377Ssam xgain_list[2] = 0xDEAD; 694185377Ssam xgain_list[3] = 0xDEAD; 695185377Ssam 696185377Ssam numPdGainsUsed = 0; 697185377Ssam xpd_mask = pRaw->xpd_mask; 698185377Ssam for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) { 699185377Ssam if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1) 700185377Ssam xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1; 701185377Ssam } 702185377Ssam 703185377Ssam pRaw->numChannels = pCal->numChannels; 704185377Ssam for (ii = 0; ii < pRaw->numChannels; ii++) { 705185377Ssam pCalCh = &(pCal->pDataPerChannel[ii]); 706185377Ssam pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue; 707185377Ssam 708185377Ssam /* numVpd has already been setup appropriately for the relevant pdGains */ 709185377Ssam for (jj = 0; jj < numPdGainsUsed; jj++) { 710185377Ssam /* use jj for calDataset and ss for rawDataset */ 711185377Ssam ss = xgain_list[jj]; 712185377Ssam pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]); 713185377Ssam HALASSERT(pRawXPD->numVpd >= 1); 714185377Ssam 715185377Ssam pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]); 716185377Ssam pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj]; 717185377Ssam 718185377Ssam for (kk = 1; kk < pRawXPD->numVpd; kk++) { 719185377Ssam pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]); 720185377Ssam pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]); 721185377Ssam } 722185377Ssam /* loop over Vpds */ 723185377Ssam } 724185377Ssam /* loop over pd_gains */ 725185377Ssam } 726185377Ssam /* loop over channels */ 727185377Ssam return AH_TRUE; 728185377Ssam} 729185377Ssam 730185377Ssamstatic HAL_BOOL 731185377SsamreadEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee) 732185377Ssam{ 733185377Ssam /* NB: index is 1 less than numPdgains */ 734185377Ssam static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 }; 735185377Ssam EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL; 736185377Ssam RAW_DATA_STRUCT_2413 *pRaw; 737185377Ssam int numEEPROMWordsPerChannel; 738185377Ssam uint32_t off; 739185377Ssam HAL_BOOL ret = AH_FALSE; 740185377Ssam 741185377Ssam HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0); 742185377Ssam HALASSERT(ee->ee_eepMap == 2); 743185377Ssam 744185377Ssam pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413)); 745185377Ssam if (pCal == AH_NULL) 746185377Ssam goto exit; 747185377Ssam 748185377Ssam off = ee->ee_eepMap2PowerCalStart; 749185377Ssam if (ee->ee_Amode) { 750185377Ssam OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 751185377Ssam pCal->xpd_mask = ee->ee_xgain[headerInfo11A]; 752185377Ssam if (!ar2413ReadCalDataset(ah, ee, pCal, off, 753185377Ssam NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) { 754185377Ssam goto exit; 755185377Ssam } 756185377Ssam pRaw = &ee->ee_rawDataset2413[headerInfo11A]; 757185377Ssam pRaw->xpd_mask = ee->ee_xgain[headerInfo11A]; 758185377Ssam ar2413SetupRawDataset(pRaw, pCal); 759185377Ssam if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 760185377Ssam goto exit; 761185377Ssam } 762185377Ssam /* setup offsets for mode_11a next */ 763185377Ssam numEEPROMWordsPerChannel = wordsForPdgains[ 764185377Ssam pCal->pDataPerChannel[0].numPdGains - 1]; 765185377Ssam off += pCal->numChannels * numEEPROMWordsPerChannel + 5; 766185377Ssam } 767185377Ssam if (ee->ee_Bmode) { 768185377Ssam OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 769185377Ssam pCal->xpd_mask = ee->ee_xgain[headerInfo11B]; 770185377Ssam if (!ar2413ReadCalDataset(ah, ee, pCal, off, 771185377Ssam NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) { 772185377Ssam goto exit; 773185377Ssam } 774185377Ssam pRaw = &ee->ee_rawDataset2413[headerInfo11B]; 775185377Ssam pRaw->xpd_mask = ee->ee_xgain[headerInfo11B]; 776185377Ssam ar2413SetupRawDataset(pRaw, pCal); 777185377Ssam if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 778185377Ssam goto exit; 779185377Ssam } 780185377Ssam /* setup offsets for mode_11g next */ 781185377Ssam numEEPROMWordsPerChannel = wordsForPdgains[ 782185377Ssam pCal->pDataPerChannel[0].numPdGains - 1]; 783185377Ssam off += pCal->numChannels * numEEPROMWordsPerChannel + 2; 784185377Ssam } 785185377Ssam if (ee->ee_Gmode) { 786185377Ssam OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); 787185377Ssam pCal->xpd_mask = ee->ee_xgain[headerInfo11G]; 788185377Ssam if (!ar2413ReadCalDataset(ah, ee, pCal, off, 789185377Ssam NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) { 790185377Ssam goto exit; 791185377Ssam } 792185377Ssam pRaw = &ee->ee_rawDataset2413[headerInfo11G]; 793185377Ssam pRaw->xpd_mask = ee->ee_xgain[headerInfo11G]; 794185377Ssam ar2413SetupRawDataset(pRaw, pCal); 795185377Ssam if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) { 796185377Ssam goto exit; 797185377Ssam } 798185377Ssam } 799185377Ssam ret = AH_TRUE; 800185377Ssam exit: 801185377Ssam if (pCal != AH_NULL) 802185377Ssam ath_hal_free(pCal); 803185377Ssam return ret; 804185377Ssam} 805185377Ssam 806185377Ssam/* 807185377Ssam * Now copy EEPROM Raw Power Calibration per frequency contents 808185377Ssam * into the allocated space 809185377Ssam */ 810185377Ssamstatic HAL_BOOL 811185377SsamreadEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) 812185377Ssam{ 813185377Ssam#define EEREAD(_off) do { \ 814185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 815185377Ssam return AH_FALSE; \ 816185377Ssam} while (0) 817185377Ssam uint16_t eeval, nchan; 818185377Ssam uint32_t off; 819185377Ssam int i, j, mode; 820185377Ssam 821185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) 822185377Ssam return readEepromRawPowerCalInfo5112(ah, ee); 823185377Ssam if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2) 824185377Ssam return readEepromRawPowerCalInfo2413(ah, ee); 825185377Ssam 826185377Ssam /* 827185377Ssam * Group 2: read raw power data for all frequency piers 828185377Ssam * 829185377Ssam * NOTE: Group 2 contains the raw power calibration 830185377Ssam * information for each of the channels that 831185377Ssam * we recorded above. 832185377Ssam */ 833185377Ssam for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 834185377Ssam uint16_t *pChannels = AH_NULL; 835185377Ssam DATA_PER_CHANNEL *pChannelData = AH_NULL; 836185377Ssam 837185377Ssam off = ee->ee_version >= AR_EEPROM_VER3_3 ? 838185377Ssam GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; 839185377Ssam switch (mode) { 840185377Ssam case headerInfo11A: 841185377Ssam off += GROUP2_OFFSET; 842185377Ssam nchan = ee->ee_numChannels11a; 843185377Ssam pChannelData = ee->ee_dataPerChannel11a; 844185377Ssam pChannels = ee->ee_channels11a; 845185377Ssam break; 846185377Ssam case headerInfo11B: 847185377Ssam if (!ee->ee_Bmode) 848185377Ssam continue; 849185377Ssam off += GROUP3_OFFSET; 850185377Ssam nchan = ee->ee_numChannels2_4; 851185377Ssam pChannelData = ee->ee_dataPerChannel11b; 852185377Ssam pChannels = ee->ee_channels11b; 853185377Ssam break; 854185377Ssam case headerInfo11G: 855185377Ssam if (!ee->ee_Gmode) 856185377Ssam continue; 857185377Ssam off += GROUP4_OFFSET; 858185377Ssam nchan = ee->ee_numChannels2_4; 859185377Ssam pChannelData = ee->ee_dataPerChannel11g; 860185377Ssam pChannels = ee->ee_channels11g; 861185377Ssam break; 862185377Ssam default: 863185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 864185377Ssam __func__, mode); 865185377Ssam return AH_FALSE; 866185377Ssam } 867185377Ssam for (i = 0; i < nchan; i++) { 868185377Ssam pChannelData->channelValue = pChannels[i]; 869185377Ssam 870185377Ssam EEREAD(off++); 871185377Ssam pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK); 872185377Ssam pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK); 873185377Ssam pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK); 874185377Ssam 875185377Ssam EEREAD(off++); 876185377Ssam pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3); 877185377Ssam pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK); 878185377Ssam pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK); 879185377Ssam pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK); 880185377Ssam 881185377Ssam EEREAD(off++); 882185377Ssam pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf); 883185377Ssam pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK); 884185377Ssam pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK); 885185377Ssam 886185377Ssam EEREAD(off++); 887185377Ssam pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK); 888185377Ssam pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK); 889185377Ssam pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK); 890185377Ssam 891185377Ssam EEREAD(off++); 892185377Ssam pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3); 893185377Ssam pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK); 894185377Ssam pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK); 895185377Ssam 896185377Ssam getPcdacInterceptsFromPcdacMinMax(ee, 897185377Ssam pChannelData->pcdacMin, pChannelData->pcdacMax, 898185377Ssam pChannelData->PcdacValues) ; 899185377Ssam 900185377Ssam for (j = 0; j < pChannelData->numPcdacValues; j++) { 901185377Ssam pChannelData->PwrValues[j] = (uint16_t)( 902185377Ssam PWR_STEP * pChannelData->PwrValues[j]); 903185377Ssam /* Note these values are scaled up. */ 904185377Ssam } 905185377Ssam pChannelData++; 906185377Ssam } 907185377Ssam } 908185377Ssam return AH_TRUE; 909185377Ssam#undef EEREAD 910185377Ssam} 911185377Ssam 912185377Ssam/* 913185377Ssam * Copy EEPROM Target Power Calbration per rate contents 914185377Ssam * into the allocated space 915185377Ssam */ 916185377Ssamstatic HAL_BOOL 917185377SsamreadEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee) 918185377Ssam{ 919185377Ssam#define EEREAD(_off) do { \ 920185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 921185377Ssam return AH_FALSE; \ 922185377Ssam} while (0) 923185377Ssam uint16_t eeval, enable24; 924185377Ssam uint32_t off; 925185377Ssam int i, mode, nchan; 926185377Ssam 927185377Ssam enable24 = ee->ee_Bmode || ee->ee_Gmode; 928185377Ssam for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { 929185377Ssam TRGT_POWER_INFO *pPowerInfo; 930185377Ssam uint16_t *pNumTrgtChannels; 931185377Ssam 932185377Ssam off = ee->ee_version >= AR_EEPROM_VER4_0 ? 933185377Ssam ee->ee_targetPowersStart - GROUP5_OFFSET : 934185377Ssam ee->ee_version >= AR_EEPROM_VER3_3 ? 935185377Ssam GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2; 936185377Ssam switch (mode) { 937185377Ssam case headerInfo11A: 938185377Ssam off += GROUP5_OFFSET; 939185377Ssam nchan = NUM_TEST_FREQUENCIES; 940185377Ssam pPowerInfo = ee->ee_trgtPwr_11a; 941185377Ssam pNumTrgtChannels = &ee->ee_numTargetPwr_11a; 942185377Ssam break; 943185377Ssam case headerInfo11B: 944185377Ssam if (!enable24) 945185377Ssam continue; 946185377Ssam off += GROUP6_OFFSET; 947185377Ssam nchan = 2; 948185377Ssam pPowerInfo = ee->ee_trgtPwr_11b; 949185377Ssam pNumTrgtChannels = &ee->ee_numTargetPwr_11b; 950185377Ssam break; 951185377Ssam case headerInfo11G: 952185377Ssam if (!enable24) 953185377Ssam continue; 954185377Ssam off += GROUP7_OFFSET; 955185377Ssam nchan = 3; 956185377Ssam pPowerInfo = ee->ee_trgtPwr_11g; 957185377Ssam pNumTrgtChannels = &ee->ee_numTargetPwr_11g; 958185377Ssam break; 959185377Ssam default: 960185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", 961185377Ssam __func__, mode); 962185377Ssam return AH_FALSE; 963185377Ssam } 964185377Ssam *pNumTrgtChannels = 0; 965185377Ssam for (i = 0; i < nchan; i++) { 966185377Ssam EEREAD(off++); 967185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 968185377Ssam pPowerInfo->testChannel = (eeval >> 8) & 0xff; 969185377Ssam } else { 970185377Ssam pPowerInfo->testChannel = (eeval >> 9) & 0x7f; 971185377Ssam } 972185377Ssam 973185377Ssam if (pPowerInfo->testChannel != 0) { 974185377Ssam /* get the channel value and read rest of info */ 975185377Ssam if (mode == headerInfo11A) { 976185377Ssam pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel); 977185377Ssam } else { 978185377Ssam pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel); 979185377Ssam } 980185377Ssam 981185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 982185377Ssam pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK; 983185377Ssam pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK; 984185377Ssam } else { 985185377Ssam pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK; 986185377Ssam pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK; 987185377Ssam } 988185377Ssam 989185377Ssam EEREAD(off++); 990185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 991185377Ssam pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf; 992185377Ssam pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK; 993185377Ssam pPowerInfo->twicePwr54 = eeval & POWER_MASK; 994185377Ssam } else { 995185377Ssam pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7; 996185377Ssam pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK; 997185377Ssam pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK; 998185377Ssam } 999185377Ssam (*pNumTrgtChannels)++; 1000185377Ssam } 1001185377Ssam pPowerInfo++; 1002185377Ssam } 1003185377Ssam } 1004185377Ssam return AH_TRUE; 1005185377Ssam#undef EEREAD 1006185377Ssam} 1007185377Ssam 1008185377Ssam/* 1009185377Ssam * Now copy EEPROM Coformance Testing Limits contents 1010185377Ssam * into the allocated space 1011185377Ssam */ 1012185377Ssamstatic HAL_BOOL 1013185377SsamreadEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee) 1014185377Ssam{ 1015185377Ssam#define EEREAD(_off) do { \ 1016185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 1017185377Ssam return AH_FALSE; \ 1018185377Ssam} while (0) 1019185377Ssam RD_EDGES_POWER *rep; 1020185377Ssam uint16_t eeval; 1021185377Ssam uint32_t off; 1022185377Ssam int i, j; 1023185377Ssam 1024185377Ssam rep = ee->ee_rdEdgesPower; 1025185377Ssam 1026185377Ssam off = GROUP8_OFFSET + 1027185377Ssam (ee->ee_version >= AR_EEPROM_VER4_0 ? 1028185377Ssam ee->ee_targetPowersStart - GROUP5_OFFSET : 1029185377Ssam ee->ee_version >= AR_EEPROM_VER3_3 ? 1030185377Ssam GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2); 1031185377Ssam for (i = 0; i < ee->ee_numCtls; i++) { 1032185377Ssam if (ee->ee_ctl[i] == 0) { 1033185377Ssam /* Move offset and edges */ 1034185377Ssam off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7); 1035185377Ssam rep += NUM_EDGES; 1036185377Ssam continue; 1037185377Ssam } 1038185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 1039185377Ssam for (j = 0; j < NUM_EDGES; j += 2) { 1040185377Ssam EEREAD(off++); 1041185377Ssam rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3; 1042185377Ssam rep[j+1].rdEdge = eeval & FREQ_MASK_3_3; 1043185377Ssam } 1044185377Ssam for (j = 0; j < NUM_EDGES; j += 2) { 1045185377Ssam EEREAD(off++); 1046185377Ssam rep[j].twice_rdEdgePower = 1047185377Ssam (eeval >> 8) & POWER_MASK; 1048185377Ssam rep[j].flag = (eeval >> 14) & 1; 1049185377Ssam rep[j+1].twice_rdEdgePower = eeval & POWER_MASK; 1050185377Ssam rep[j+1].flag = (eeval >> 6) & 1; 1051185377Ssam } 1052185377Ssam } else { 1053185377Ssam EEREAD(off++); 1054185377Ssam rep[0].rdEdge = (eeval >> 9) & FREQ_MASK; 1055185377Ssam rep[1].rdEdge = (eeval >> 2) & FREQ_MASK; 1056185377Ssam rep[2].rdEdge = (eeval << 5) & FREQ_MASK; 1057185377Ssam 1058185377Ssam EEREAD(off++); 1059185377Ssam rep[2].rdEdge |= (eeval >> 11) & 0x1f; 1060185377Ssam rep[3].rdEdge = (eeval >> 4) & FREQ_MASK; 1061185377Ssam rep[4].rdEdge = (eeval << 3) & FREQ_MASK; 1062185377Ssam 1063185377Ssam EEREAD(off++); 1064185377Ssam rep[4].rdEdge |= (eeval >> 13) & 0x7; 1065185377Ssam rep[5].rdEdge = (eeval >> 6) & FREQ_MASK; 1066185377Ssam rep[6].rdEdge = (eeval << 1) & FREQ_MASK; 1067185377Ssam 1068185377Ssam EEREAD(off++); 1069185377Ssam rep[6].rdEdge |= (eeval >> 15) & 0x1; 1070185377Ssam rep[7].rdEdge = (eeval >> 8) & FREQ_MASK; 1071185377Ssam 1072185377Ssam rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK; 1073185377Ssam rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK; 1074185377Ssam 1075185377Ssam EEREAD(off++); 1076185377Ssam rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf; 1077185377Ssam rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK; 1078185377Ssam rep[3].twice_rdEdgePower = eeval & POWER_MASK; 1079185377Ssam 1080185377Ssam EEREAD(off++); 1081185377Ssam rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK; 1082185377Ssam rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK; 1083185377Ssam rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK; 1084185377Ssam 1085185377Ssam EEREAD(off++); 1086185377Ssam rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3; 1087185377Ssam rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK; 1088185377Ssam } 1089185377Ssam 1090185377Ssam for (j = 0; j < NUM_EDGES; j++ ) { 1091185377Ssam if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) { 1092185377Ssam if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A || 1093185377Ssam (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) { 1094185377Ssam rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge); 1095185377Ssam } else { 1096185377Ssam rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge); 1097185377Ssam } 1098185377Ssam } 1099185377Ssam } 1100185377Ssam rep += NUM_EDGES; 1101185377Ssam } 1102185377Ssam return AH_TRUE; 1103185377Ssam#undef EEREAD 1104185377Ssam} 1105185377Ssam 1106185377Ssam/* 1107185377Ssam * Read the individual header fields for a Rev 3 EEPROM 1108185377Ssam */ 1109185377Ssamstatic HAL_BOOL 1110185377SsamreadHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee) 1111185377Ssam{ 1112185377Ssam#define EEREAD(_off) do { \ 1113185377Ssam if (!ath_hal_eepromRead(ah, _off, &eeval)) \ 1114185377Ssam return AH_FALSE; \ 1115185377Ssam} while (0) 1116185377Ssam static const uint32_t headerOffset3_0[] = { 1117185377Ssam 0x00C2, /* 0 - Mode bits, device type, max turbo power */ 1118185377Ssam 0x00C4, /* 1 - 2.4 and 5 antenna gain */ 1119185377Ssam 0x00C5, /* 2 - Begin 11A modal section */ 1120185377Ssam 0x00D0, /* 3 - Begin 11B modal section */ 1121185377Ssam 0x00DA, /* 4 - Begin 11G modal section */ 1122185377Ssam 0x00E4 /* 5 - Begin CTL section */ 1123185377Ssam }; 1124185377Ssam static const uint32_t headerOffset3_3[] = { 1125185377Ssam 0x00C2, /* 0 - Mode bits, device type, max turbo power */ 1126185377Ssam 0x00C3, /* 1 - 2.4 and 5 antenna gain */ 1127185377Ssam 0x00D4, /* 2 - Begin 11A modal section */ 1128185377Ssam 0x00F2, /* 3 - Begin 11B modal section */ 1129185377Ssam 0x010D, /* 4 - Begin 11G modal section */ 1130185377Ssam 0x0128 /* 5 - Begin CTL section */ 1131185377Ssam }; 1132185377Ssam 1133185377Ssam static const uint32_t regCapOffsetPre4_0 = 0x00CF; 1134185377Ssam static const uint32_t regCapOffsetPost4_0 = 0x00CA; 1135185377Ssam 1136185377Ssam const uint32_t *header; 1137185377Ssam uint32_t off; 1138185377Ssam uint16_t eeval; 1139185377Ssam int i; 1140185377Ssam 1141185377Ssam /* initialize cckOfdmGainDelta for < 4.2 eeprom */ 1142185377Ssam ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA; 1143185377Ssam ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT; 1144185377Ssam 1145185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 1146185377Ssam header = headerOffset3_3; 1147185377Ssam ee->ee_numCtls = NUM_CTLS_3_3; 1148185377Ssam } else { 1149185377Ssam header = headerOffset3_0; 1150185377Ssam ee->ee_numCtls = NUM_CTLS; 1151185377Ssam } 1152185377Ssam HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX); 1153185377Ssam 1154185377Ssam EEREAD(header[0]); 1155185377Ssam ee->ee_turbo5Disable = (eeval >> 15) & 0x01; 1156185377Ssam ee->ee_rfKill = (eeval >> 14) & 0x01; 1157185377Ssam ee->ee_deviceType = (eeval >> 11) & 0x07; 1158185377Ssam ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F; 1159185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) 1160185377Ssam ee->ee_turbo2Disable = (eeval >> 3) & 0x01; 1161185377Ssam else 1162185377Ssam ee->ee_turbo2Disable = 1; 1163185377Ssam ee->ee_Gmode = (eeval >> 2) & 0x01; 1164185377Ssam ee->ee_Bmode = (eeval >> 1) & 0x01; 1165185377Ssam ee->ee_Amode = (eeval & 0x01); 1166185377Ssam 1167185377Ssam off = header[1]; 1168185377Ssam EEREAD(off++); 1169185377Ssam ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF); 1170185377Ssam ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF); 1171185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) { 1172185377Ssam EEREAD(off++); 1173185377Ssam ee->ee_eepMap = (eeval>>14) & 0x3; 1174185377Ssam ee->ee_disableXr5 = (eeval>>13) & 0x1; 1175185377Ssam ee->ee_disableXr2 = (eeval>>12) & 0x1; 1176185377Ssam ee->ee_earStart = eeval & 0xfff; 1177185377Ssam 1178185377Ssam EEREAD(off++); 1179185377Ssam ee->ee_targetPowersStart = eeval & 0xfff; 1180185377Ssam ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1; 1181185377Ssam 1182185377Ssam if (ee->ee_version >= AR_EEPROM_VER5_0) { 1183185377Ssam off += 2; 1184185377Ssam EEREAD(off); 1185185377Ssam ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff; 1186185377Ssam /* Properly cal'ed 5.0 devices should be non-zero */ 1187185377Ssam } 1188185377Ssam } 1189185377Ssam 1190185377Ssam /* Read the moded sections of the EEPROM header in the order A, B, G */ 1191185377Ssam for (i = headerInfo11A; i <= headerInfo11G; i++) { 1192185377Ssam /* Set the offset via the index */ 1193185377Ssam off = header[2 + i]; 1194185377Ssam 1195185377Ssam EEREAD(off++); 1196185377Ssam ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f; 1197185377Ssam ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f; 1198185377Ssam ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f; 1199185377Ssam 1200185377Ssam EEREAD(off++); 1201185377Ssam ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f; 1202185377Ssam ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f; 1203185377Ssam ee->ee_antennaControl[2][i] = eeval & 0x3f; 1204185377Ssam 1205185377Ssam EEREAD(off++); 1206185377Ssam ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f; 1207185377Ssam ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f; 1208185377Ssam ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f; 1209185377Ssam 1210185377Ssam EEREAD(off++); 1211185377Ssam ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03; 1212185377Ssam ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f; 1213185377Ssam ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f; 1214185377Ssam ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f; 1215185377Ssam 1216185377Ssam EEREAD(off++); 1217185377Ssam ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f; 1218185377Ssam ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f; 1219185377Ssam ee->ee_antennaControl[10][i] = eeval & 0x3f; 1220185377Ssam 1221185377Ssam EEREAD(off++); 1222185377Ssam ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); 1223185377Ssam switch (i) { 1224185377Ssam case headerInfo11A: 1225185377Ssam ee->ee_ob4 = (eeval >> 5) & 0x07; 1226185377Ssam ee->ee_db4 = (eeval >> 2) & 0x07; 1227185377Ssam ee->ee_ob3 = (eeval << 1) & 0x07; 1228185377Ssam break; 1229185377Ssam case headerInfo11B: 1230185377Ssam ee->ee_obFor24 = (eeval >> 4) & 0x07; 1231185377Ssam ee->ee_dbFor24 = eeval & 0x07; 1232185377Ssam break; 1233185377Ssam case headerInfo11G: 1234185377Ssam ee->ee_obFor24g = (eeval >> 4) & 0x07; 1235185377Ssam ee->ee_dbFor24g = eeval & 0x07; 1236185377Ssam break; 1237185377Ssam } 1238185377Ssam 1239185377Ssam if (i == headerInfo11A) { 1240185377Ssam EEREAD(off++); 1241185377Ssam ee->ee_ob3 |= (eeval >> 15) & 0x01; 1242185377Ssam ee->ee_db3 = (eeval >> 12) & 0x07; 1243185377Ssam ee->ee_ob2 = (eeval >> 9) & 0x07; 1244185377Ssam ee->ee_db2 = (eeval >> 6) & 0x07; 1245185377Ssam ee->ee_ob1 = (eeval >> 3) & 0x07; 1246185377Ssam ee->ee_db1 = eeval & 0x07; 1247185377Ssam } 1248185377Ssam 1249185377Ssam EEREAD(off++); 1250185377Ssam ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff; 1251185377Ssam ee->ee_thresh62[i] = eeval & 0xff; 1252185377Ssam 1253185377Ssam EEREAD(off++); 1254185377Ssam ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff; 1255185377Ssam ee->ee_txFrameToXPAOn[i] = eeval & 0xff; 1256185377Ssam 1257185377Ssam EEREAD(off++); 1258185377Ssam ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff); 1259185377Ssam ee->ee_noiseFloorThresh[i] = eeval & 0xff; 1260185377Ssam if (ee->ee_noiseFloorThresh[i] & 0x80) { 1261185377Ssam ee->ee_noiseFloorThresh[i] = 0 - 1262185377Ssam ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1); 1263185377Ssam } 1264185377Ssam 1265185377Ssam EEREAD(off++); 1266185377Ssam ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff; 1267185377Ssam ee->ee_xgain[i] = (eeval >> 1) & 0x0f; 1268185377Ssam ee->ee_xpd[i] = eeval & 0x01; 1269185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) { 1270185377Ssam switch (i) { 1271185377Ssam case headerInfo11A: 1272185377Ssam ee->ee_fixedBias5 = (eeval >> 13) & 0x1; 1273185377Ssam break; 1274185377Ssam case headerInfo11G: 1275185377Ssam ee->ee_fixedBias2 = (eeval >> 13) & 0x1; 1276185377Ssam break; 1277185377Ssam } 1278185377Ssam } 1279185377Ssam 1280185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_3) { 1281185377Ssam EEREAD(off++); 1282185377Ssam ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F; 1283185377Ssam switch (i) { 1284185377Ssam case headerInfo11B: 1285185377Ssam ee->ee_ob2GHz[0] = eeval & 0x7; 1286185377Ssam ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; 1287185377Ssam break; 1288185377Ssam case headerInfo11G: 1289185377Ssam ee->ee_ob2GHz[1] = eeval & 0x7; 1290185377Ssam ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; 1291185377Ssam break; 1292185377Ssam case headerInfo11A: 1293185377Ssam ee->ee_xrTargetPower5 = eeval & 0x3f; 1294185377Ssam break; 1295185377Ssam } 1296185377Ssam } 1297185377Ssam if (ee->ee_version >= AR_EEPROM_VER3_4) { 1298185377Ssam ee->ee_gainI[i] = (eeval >> 13) & 0x07; 1299185377Ssam 1300185377Ssam EEREAD(off++); 1301185377Ssam ee->ee_gainI[i] |= (eeval << 3) & 0x38; 1302185377Ssam if (i == headerInfo11G) { 1303185377Ssam ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF; 1304185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_6) 1305185377Ssam ee->ee_scaledCh14FilterCckDelta = 1306185377Ssam (eeval >> 11) & 0x1f; 1307185377Ssam } 1308185377Ssam if (i == headerInfo11A && 1309185377Ssam ee->ee_version >= AR_EEPROM_VER4_0) { 1310185377Ssam ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f; 1311185377Ssam ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f; 1312185377Ssam } 1313185377Ssam } else { 1314185377Ssam ee->ee_gainI[i] = 10; 1315185377Ssam ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT; 1316185377Ssam } 1317185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) { 1318185377Ssam switch (i) { 1319185377Ssam case headerInfo11B: 1320185377Ssam EEREAD(off++); 1321185377Ssam ee->ee_calPier11b[0] = 1322185377Ssam fbin2freq_2p4(ee, eeval&0xff); 1323185377Ssam ee->ee_calPier11b[1] = 1324185377Ssam fbin2freq_2p4(ee, (eeval >> 8)&0xff); 1325185377Ssam EEREAD(off++); 1326185377Ssam ee->ee_calPier11b[2] = 1327185377Ssam fbin2freq_2p4(ee, eeval&0xff); 1328185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_1) 1329185377Ssam ee->ee_rxtxMargin[headerInfo11B] = 1330185377Ssam (eeval >> 8) & 0x3f; 1331185377Ssam break; 1332185377Ssam case headerInfo11G: 1333185377Ssam EEREAD(off++); 1334185377Ssam ee->ee_calPier11g[0] = 1335185377Ssam fbin2freq_2p4(ee, eeval & 0xff); 1336185377Ssam ee->ee_calPier11g[1] = 1337185377Ssam fbin2freq_2p4(ee, (eeval >> 8) & 0xff); 1338185377Ssam 1339185377Ssam EEREAD(off++); 1340185377Ssam ee->ee_turbo2WMaxPower2 = eeval & 0x7F; 1341185377Ssam ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f; 1342185377Ssam 1343185377Ssam EEREAD(off++); 1344185377Ssam ee->ee_calPier11g[2] = 1345185377Ssam fbin2freq_2p4(ee, eeval & 0xff); 1346185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_1) 1347185377Ssam ee->ee_rxtxMargin[headerInfo11G] = 1348185377Ssam (eeval >> 8) & 0x3f; 1349185377Ssam 1350185377Ssam EEREAD(off++); 1351185377Ssam ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F; 1352185377Ssam ee->ee_iqCalQ[1] = eeval & 0x1F; 1353185377Ssam 1354185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_2) { 1355185377Ssam EEREAD(off++); 1356185377Ssam ee->ee_cckOfdmGainDelta = 1357185377Ssam (uint8_t)(eeval & 0xFF); 1358185377Ssam if (ee->ee_version >= AR_EEPROM_VER5_0) { 1359185377Ssam ee->ee_switchSettlingTurbo[1] = 1360185377Ssam (eeval >> 8) & 0x7f; 1361185377Ssam ee->ee_txrxAttenTurbo[1] = 1362185377Ssam (eeval >> 15) & 0x1; 1363185377Ssam EEREAD(off++); 1364185377Ssam ee->ee_txrxAttenTurbo[1] |= 1365185377Ssam (eeval & 0x1F) << 1; 1366185377Ssam ee->ee_rxtxMarginTurbo[1] = 1367185377Ssam (eeval >> 5) & 0x3F; 1368185377Ssam ee->ee_adcDesiredSizeTurbo[1] = 1369185377Ssam (eeval >> 11) & 0x1F; 1370185377Ssam EEREAD(off++); 1371185377Ssam ee->ee_adcDesiredSizeTurbo[1] |= 1372185377Ssam (eeval & 0x7) << 5; 1373185377Ssam ee->ee_pgaDesiredSizeTurbo[1] = 1374185377Ssam (eeval >> 3) & 0xFF; 1375185377Ssam } 1376185377Ssam } 1377185377Ssam break; 1378185377Ssam case headerInfo11A: 1379185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_1) { 1380185377Ssam EEREAD(off++); 1381185377Ssam ee->ee_rxtxMargin[headerInfo11A] = 1382185377Ssam eeval & 0x3f; 1383185377Ssam if (ee->ee_version >= AR_EEPROM_VER5_0) { 1384185377Ssam ee->ee_switchSettlingTurbo[0] = 1385185377Ssam (eeval >> 6) & 0x7f; 1386185377Ssam ee->ee_txrxAttenTurbo[0] = 1387185377Ssam (eeval >> 13) & 0x7; 1388185377Ssam EEREAD(off++); 1389185377Ssam ee->ee_txrxAttenTurbo[0] |= 1390185377Ssam (eeval & 0x7) << 3; 1391185377Ssam ee->ee_rxtxMarginTurbo[0] = 1392185377Ssam (eeval >> 3) & 0x3F; 1393185377Ssam ee->ee_adcDesiredSizeTurbo[0] = 1394185377Ssam (eeval >> 9) & 0x7F; 1395185377Ssam EEREAD(off++); 1396185377Ssam ee->ee_adcDesiredSizeTurbo[0] |= 1397185377Ssam (eeval & 0x1) << 7; 1398185377Ssam ee->ee_pgaDesiredSizeTurbo[0] = 1399185377Ssam (eeval >> 1) & 0xFF; 1400185377Ssam } 1401185377Ssam } 1402185377Ssam break; 1403185377Ssam } 1404185377Ssam } 1405185377Ssam } 1406185377Ssam if (ee->ee_version < AR_EEPROM_VER3_3) { 1407185377Ssam /* Version 3.1+ specific parameters */ 1408185377Ssam EEREAD(0xec); 1409185377Ssam ee->ee_ob2GHz[0] = eeval & 0x7; 1410185377Ssam ee->ee_db2GHz[0] = (eeval >> 3) & 0x7; 1411185377Ssam 1412185377Ssam EEREAD(0xed); 1413185377Ssam ee->ee_ob2GHz[1] = eeval & 0x7; 1414185377Ssam ee->ee_db2GHz[1] = (eeval >> 3) & 0x7; 1415185377Ssam } 1416185377Ssam 1417185377Ssam /* Initialize corner cal (thermal tx gain adjust parameters) */ 1418185377Ssam ee->ee_cornerCal.clip = 4; 1419185377Ssam ee->ee_cornerCal.pd90 = 1; 1420185377Ssam ee->ee_cornerCal.pd84 = 1; 1421185377Ssam ee->ee_cornerCal.gSel = 0; 1422185377Ssam 1423185377Ssam /* 1424185377Ssam * Read the conformance test limit identifiers 1425185377Ssam * These are used to match regulatory domain testing needs with 1426185377Ssam * the RD-specific tests that have been calibrated in the EEPROM. 1427185377Ssam */ 1428185377Ssam off = header[5]; 1429185377Ssam for (i = 0; i < ee->ee_numCtls; i += 2) { 1430185377Ssam EEREAD(off++); 1431185377Ssam ee->ee_ctl[i] = (eeval >> 8) & 0xff; 1432185377Ssam ee->ee_ctl[i+1] = eeval & 0xff; 1433185377Ssam } 1434185377Ssam 1435185377Ssam if (ee->ee_version < AR_EEPROM_VER5_3) { 1436185377Ssam /* XXX only for 5413? */ 1437185377Ssam ee->ee_spurChans[0][1] = AR_SPUR_5413_1; 1438185377Ssam ee->ee_spurChans[1][1] = AR_SPUR_5413_2; 1439185377Ssam ee->ee_spurChans[2][1] = AR_NO_SPUR; 1440185377Ssam ee->ee_spurChans[0][0] = AR_NO_SPUR; 1441185377Ssam } else { 1442185377Ssam /* Read spur mitigation data */ 1443185377Ssam for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { 1444185377Ssam EEREAD(off); 1445185377Ssam ee->ee_spurChans[i][0] = eeval; 1446185377Ssam EEREAD(off+AR_EEPROM_MODAL_SPURS); 1447185377Ssam ee->ee_spurChans[i][1] = eeval; 1448185377Ssam off++; 1449185377Ssam } 1450185377Ssam } 1451185377Ssam 1452185377Ssam /* for recent changes to NF scale */ 1453185377Ssam if (ee->ee_version <= AR_EEPROM_VER3_2) { 1454185377Ssam ee->ee_noiseFloorThresh[headerInfo11A] = -54; 1455185377Ssam ee->ee_noiseFloorThresh[headerInfo11B] = -1; 1456185377Ssam ee->ee_noiseFloorThresh[headerInfo11G] = -1; 1457185377Ssam } 1458185377Ssam /* to override thresh62 for better 2.4 and 5 operation */ 1459185377Ssam if (ee->ee_version <= AR_EEPROM_VER3_2) { 1460185377Ssam ee->ee_thresh62[headerInfo11A] = 15; /* 11A */ 1461185377Ssam ee->ee_thresh62[headerInfo11B] = 28; /* 11B */ 1462185377Ssam ee->ee_thresh62[headerInfo11G] = 28; /* 11G */ 1463185377Ssam } 1464185377Ssam 1465185377Ssam /* Check for regulatory capabilities */ 1466185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) { 1467185377Ssam EEREAD(regCapOffsetPost4_0); 1468185377Ssam } else { 1469185377Ssam EEREAD(regCapOffsetPre4_0); 1470185377Ssam } 1471185377Ssam 1472185377Ssam ee->ee_regCap = eeval; 1473185377Ssam 1474185377Ssam if (ee->ee_Amode == 0) { 1475185377Ssam /* Check for valid Amode in upgraded h/w */ 1476185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0) { 1477185377Ssam ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0; 1478185377Ssam } else { 1479185377Ssam ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0; 1480185377Ssam } 1481185377Ssam } 1482185377Ssam 1483185377Ssam if (ee->ee_version >= AR_EEPROM_VER5_1) 1484185377Ssam EEREAD(AR_EEPROM_CAPABILITIES_OFFSET); 1485185377Ssam else 1486185377Ssam eeval = 0; 1487185377Ssam ee->ee_opCap = eeval; 1488185377Ssam 1489185377Ssam EEREAD(AR_EEPROM_REG_DOMAIN); 1490185377Ssam ee->ee_regdomain = eeval; 1491185377Ssam 1492185377Ssam return AH_TRUE; 1493185377Ssam#undef EEREAD 1494185377Ssam} 1495185377Ssam 1496185377Ssam/* 1497185377Ssam * Now verify and copy EEPROM contents into the allocated space 1498185377Ssam */ 1499185377Ssamstatic HAL_BOOL 1500185377SsamlegacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee) 1501185377Ssam{ 1502185377Ssam /* Read the header information here */ 1503185377Ssam if (!readHeaderInfo(ah, ee)) 1504185377Ssam return AH_FALSE; 1505185377Ssam#if 0 1506185377Ssam /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */ 1507185377Ssam if (IS_5112(ah) && !ee->ee_eepMap) { 1508185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1509185377Ssam "%s: 5112 devices must have EEPROM 4.0 with the " 1510185377Ssam "EEP_MAP set\n", __func__); 1511185377Ssam return AH_FALSE; 1512185377Ssam } 1513185377Ssam#endif 1514185377Ssam /* 1515185377Ssam * Group 1: frequency pier locations readback 1516185377Ssam * check that the structure has been populated 1517185377Ssam * with enough space to hold the channels 1518185377Ssam * 1519185377Ssam * NOTE: Group 1 contains the 5 GHz channel numbers 1520185377Ssam * that have dBm->pcdac calibrated information. 1521185377Ssam */ 1522185377Ssam if (!readEepromFreqPierInfo(ah, ee)) 1523185377Ssam return AH_FALSE; 1524185377Ssam 1525185377Ssam /* 1526185377Ssam * Group 2: readback data for all frequency piers 1527185377Ssam * 1528185377Ssam * NOTE: Group 2 contains the raw power calibration 1529185377Ssam * information for each of the channels that we 1530185377Ssam * recorded above. 1531185377Ssam */ 1532185377Ssam if (!readEepromRawPowerCalInfo(ah, ee)) 1533185377Ssam return AH_FALSE; 1534185377Ssam 1535185377Ssam /* 1536185377Ssam * Group 5: target power values per rate 1537185377Ssam * 1538185377Ssam * NOTE: Group 5 contains the recorded maximum power 1539185377Ssam * in dB that can be attained for the given rate. 1540185377Ssam */ 1541185377Ssam /* Read the power per rate info for test channels */ 1542185377Ssam if (!readEepromTargetPowerCalInfo(ah, ee)) 1543185377Ssam return AH_FALSE; 1544185377Ssam 1545185377Ssam /* 1546185377Ssam * Group 8: Conformance Test Limits information 1547185377Ssam * 1548185377Ssam * NOTE: Group 8 contains the values to limit the 1549185377Ssam * maximum transmit power value based on any 1550185377Ssam * band edge violations. 1551185377Ssam */ 1552185377Ssam /* Read the RD edge power limits */ 1553185377Ssam return readEepromCTLInfo(ah, ee); 1554185377Ssam} 1555185377Ssam 1556185377Ssamstatic HAL_STATUS 1557185377SsamlegacyEepromGet(struct ath_hal *ah, int param, void *val) 1558185377Ssam{ 1559185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1560185377Ssam uint8_t *macaddr; 1561185377Ssam uint16_t eeval; 1562185377Ssam uint32_t sum; 1563185377Ssam int i; 1564185377Ssam 1565185377Ssam switch (param) { 1566185377Ssam case AR_EEP_OPCAP: 1567185377Ssam *(uint16_t *) val = ee->ee_opCap; 1568185377Ssam return HAL_OK; 1569185377Ssam case AR_EEP_REGDMN_0: 1570185377Ssam *(uint16_t *) val = ee->ee_regdomain; 1571185377Ssam return HAL_OK; 1572185377Ssam case AR_EEP_RFSILENT: 1573185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval)) 1574185377Ssam return HAL_EEREAD; 1575185377Ssam *(uint16_t *) val = eeval; 1576185377Ssam return HAL_OK; 1577185377Ssam case AR_EEP_MACADDR: 1578185377Ssam sum = 0; 1579185377Ssam macaddr = val; 1580185377Ssam for (i = 0; i < 3; i++) { 1581185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) { 1582185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1583185377Ssam "%s: cannot read EEPROM location %u\n", 1584185377Ssam __func__, i); 1585185377Ssam return HAL_EEREAD; 1586185377Ssam } 1587185377Ssam sum += eeval; 1588185377Ssam macaddr[2*i] = eeval >> 8; 1589185377Ssam macaddr[2*i + 1] = eeval & 0xff; 1590185377Ssam } 1591185377Ssam if (sum == 0 || sum == 0xffff*3) { 1592185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1593185377Ssam "%s: mac address read failed: %s\n", __func__, 1594185377Ssam ath_hal_ether_sprintf(macaddr)); 1595185377Ssam return HAL_EEBADMAC; 1596185377Ssam } 1597185377Ssam return HAL_OK; 1598185377Ssam case AR_EEP_RFKILL: 1599185377Ssam HALASSERT(val == AH_NULL); 1600185377Ssam return ee->ee_rfKill ? HAL_OK : HAL_EIO; 1601185377Ssam case AR_EEP_AMODE: 1602185377Ssam HALASSERT(val == AH_NULL); 1603185377Ssam return ee->ee_Amode ? HAL_OK : HAL_EIO; 1604185377Ssam case AR_EEP_BMODE: 1605185377Ssam HALASSERT(val == AH_NULL); 1606185377Ssam return ee->ee_Bmode ? HAL_OK : HAL_EIO; 1607185377Ssam case AR_EEP_GMODE: 1608185377Ssam HALASSERT(val == AH_NULL); 1609185377Ssam return ee->ee_Gmode ? HAL_OK : HAL_EIO; 1610185377Ssam case AR_EEP_TURBO5DISABLE: 1611185377Ssam HALASSERT(val == AH_NULL); 1612185377Ssam return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO; 1613185377Ssam case AR_EEP_TURBO2DISABLE: 1614185377Ssam HALASSERT(val == AH_NULL); 1615185377Ssam return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO; 1616185377Ssam case AR_EEP_ISTALON: /* Talon detect */ 1617185377Ssam HALASSERT(val == AH_NULL); 1618185377Ssam return (ee->ee_version >= AR_EEPROM_VER5_4 && 1619185377Ssam ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ? 1620185377Ssam HAL_OK : HAL_EIO; 1621185377Ssam case AR_EEP_32KHZCRYSTAL: 1622185377Ssam HALASSERT(val == AH_NULL); 1623185377Ssam return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO; 1624185377Ssam case AR_EEP_COMPRESS: 1625185377Ssam HALASSERT(val == AH_NULL); 1626185377Ssam return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ? 1627185377Ssam HAL_OK : HAL_EIO; 1628185377Ssam case AR_EEP_FASTFRAME: 1629185377Ssam HALASSERT(val == AH_NULL); 1630185377Ssam return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ? 1631185377Ssam HAL_OK : HAL_EIO; 1632185377Ssam case AR_EEP_AES: 1633185377Ssam HALASSERT(val == AH_NULL); 1634185377Ssam return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ? 1635185377Ssam HAL_OK : HAL_EIO; 1636185377Ssam case AR_EEP_BURST: 1637185377Ssam HALASSERT(val == AH_NULL); 1638185377Ssam return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ? 1639185377Ssam HAL_OK : HAL_EIO; 1640185377Ssam case AR_EEP_MAXQCU: 1641185377Ssam if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) { 1642185377Ssam *(uint16_t *) val = 1643185377Ssam MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU); 1644185377Ssam return HAL_OK; 1645185377Ssam } else 1646185377Ssam return HAL_EIO; 1647185377Ssam case AR_EEP_KCENTRIES: 1648185377Ssam if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) { 1649185377Ssam *(uint16_t *) val = 1650185377Ssam 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES); 1651185377Ssam return HAL_OK; 1652185377Ssam } else 1653185377Ssam return HAL_EIO; 1654185377Ssam case AR_EEP_ANTGAINMAX_5: 1655185377Ssam *(int8_t *) val = ee->ee_antennaGainMax[0]; 1656185377Ssam return HAL_OK; 1657185377Ssam case AR_EEP_ANTGAINMAX_2: 1658185377Ssam *(int8_t *) val = ee->ee_antennaGainMax[1]; 1659185377Ssam return HAL_OK; 1660185377Ssam case AR_EEP_WRITEPROTECT: 1661185377Ssam HALASSERT(val == AH_NULL); 1662185377Ssam return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ? 1663185377Ssam HAL_OK : HAL_EIO; 1664185377Ssam } 1665185377Ssam return HAL_EINVAL; 1666185377Ssam} 1667185377Ssam 1668221896Sadrianstatic HAL_STATUS 1669185377SsamlegacyEepromSet(struct ath_hal *ah, int param, int v) 1670185377Ssam{ 1671185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1672185377Ssam 1673185377Ssam switch (param) { 1674185377Ssam case AR_EEP_AMODE: 1675185377Ssam ee->ee_Amode = v; 1676185377Ssam return HAL_OK; 1677185377Ssam case AR_EEP_BMODE: 1678185377Ssam ee->ee_Bmode = v; 1679185377Ssam return HAL_OK; 1680185377Ssam case AR_EEP_GMODE: 1681185377Ssam ee->ee_Gmode = v; 1682185377Ssam return HAL_OK; 1683185377Ssam case AR_EEP_TURBO5DISABLE: 1684185377Ssam ee->ee_turbo5Disable = v; 1685185377Ssam return HAL_OK; 1686185377Ssam case AR_EEP_TURBO2DISABLE: 1687185377Ssam ee->ee_turbo2Disable = v; 1688185377Ssam return HAL_OK; 1689185377Ssam case AR_EEP_COMPRESS: 1690185377Ssam if (v) 1691185377Ssam ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS; 1692185377Ssam else 1693185377Ssam ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS; 1694185377Ssam return HAL_OK; 1695185377Ssam case AR_EEP_FASTFRAME: 1696185377Ssam if (v) 1697185377Ssam ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS; 1698185377Ssam else 1699185377Ssam ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS; 1700185377Ssam return HAL_OK; 1701185377Ssam case AR_EEP_AES: 1702185377Ssam if (v) 1703185377Ssam ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS; 1704185377Ssam else 1705185377Ssam ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS; 1706185377Ssam return HAL_OK; 1707185377Ssam case AR_EEP_BURST: 1708185377Ssam if (v) 1709185377Ssam ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS; 1710185377Ssam else 1711185377Ssam ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS; 1712185377Ssam return HAL_OK; 1713185377Ssam } 1714185377Ssam return HAL_EINVAL; 1715185377Ssam} 1716185377Ssam 1717185377Ssamstatic HAL_BOOL 1718185377SsamlegacyEepromDiag(struct ath_hal *ah, int request, 1719185377Ssam const void *args, uint32_t argsize, void **result, uint32_t *resultsize) 1720185377Ssam{ 1721185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1722185377Ssam const EEPROM_POWER_EXPN_5112 *pe; 1723185377Ssam 1724185377Ssam switch (request) { 1725185377Ssam case HAL_DIAG_EEPROM: 1726185377Ssam *result = ee; 1727185377Ssam *resultsize = sizeof(*ee); 1728185377Ssam return AH_TRUE; 1729185377Ssam case HAL_DIAG_EEPROM_EXP_11A: 1730185377Ssam case HAL_DIAG_EEPROM_EXP_11B: 1731185377Ssam case HAL_DIAG_EEPROM_EXP_11G: 1732185377Ssam pe = &ee->ee_modePowerArray5112[ 1733185377Ssam request - HAL_DIAG_EEPROM_EXP_11A]; 1734185377Ssam *result = pe->pChannels; 1735185377Ssam *resultsize = (*result == AH_NULL) ? 0 : 1736185377Ssam roundup(sizeof(uint16_t) * pe->numChannels, 1737185377Ssam sizeof(uint32_t)) + 1738185377Ssam sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels; 1739185377Ssam return AH_TRUE; 1740185377Ssam } 1741185377Ssam return AH_FALSE; 1742185377Ssam} 1743185377Ssam 1744185377Ssamstatic uint16_t 1745185377SsamlegacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) 1746185377Ssam{ 1747185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1748185377Ssam 1749185377Ssam HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS); 1750185377Ssam return ee->ee_spurChans[ix][is2GHz]; 1751185377Ssam} 1752185377Ssam 1753185377Ssam/* 1754185377Ssam * Reclaim any EEPROM-related storage. 1755185377Ssam */ 1756185377Ssamstatic void 1757185377SsamlegacyEepromDetach(struct ath_hal *ah) 1758185377Ssam{ 1759185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1760185377Ssam 1761185377Ssam if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1) 1762196934Ssam freeEepromRawPowerCalInfo5112(ah, ee); 1763185377Ssam ath_hal_free(ee); 1764185377Ssam AH_PRIVATE(ah)->ah_eeprom = AH_NULL; 1765185377Ssam} 1766185377Ssam 1767185377Ssam/* 1768185380Ssam * These are not valid 2.4 channels, either we change 'em 1769185380Ssam * or we need to change the coding to accept them. 1770185377Ssam */ 1771185377Ssamstatic const uint16_t channels11b[] = { 2412, 2447, 2484 }; 1772185377Ssamstatic const uint16_t channels11g[] = { 2312, 2412, 2484 }; 1773185377Ssam 1774185377SsamHAL_STATUS 1775185377Ssamath_hal_legacyEepromAttach(struct ath_hal *ah) 1776185377Ssam{ 1777185377Ssam HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 1778185377Ssam uint32_t sum, eepMax; 1779185377Ssam uint16_t eeversion, eeprotect, eeval; 1780185377Ssam u_int i; 1781185377Ssam 1782185377Ssam HALASSERT(ee == AH_NULL); 1783185377Ssam 1784185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) { 1785185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1786185377Ssam "%s: unable to read EEPROM version\n", __func__); 1787185377Ssam return HAL_EEREAD; 1788185377Ssam } 1789185377Ssam if (eeversion < AR_EEPROM_VER3) { 1790185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version " 1791185377Ssam "%u (0x%x) found\n", __func__, eeversion, eeversion); 1792185377Ssam return HAL_EEVERSION; 1793185377Ssam } 1794185377Ssam 1795185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) { 1796185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection " 1797185377Ssam "bits; read locked?\n", __func__); 1798185377Ssam return HAL_EEREAD; 1799185377Ssam } 1800185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect); 1801185377Ssam /* XXX check proper access before continuing */ 1802185377Ssam 1803185377Ssam /* 1804185377Ssam * Read the Atheros EEPROM entries and calculate the checksum. 1805185377Ssam */ 1806185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) { 1807185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1808185377Ssam "%s: cannot read EEPROM upper size\n" , __func__); 1809185377Ssam return HAL_EEREAD; 1810185377Ssam } 1811185377Ssam if (eeval != 0) { 1812185377Ssam eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) << 1813185377Ssam AR_EEPROM_SIZE_ENDLOC_SHIFT; 1814185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) { 1815185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 1816185377Ssam "%s: cannot read EEPROM lower size\n" , __func__); 1817185377Ssam return HAL_EEREAD; 1818185377Ssam } 1819185377Ssam eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE; 1820185377Ssam } else 1821185377Ssam eepMax = AR_EEPROM_ATHEROS_MAX; 1822185377Ssam sum = 0; 1823185377Ssam for (i = 0; i < eepMax; i++) { 1824185377Ssam if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) { 1825185377Ssam return HAL_EEREAD; 1826185377Ssam } 1827185377Ssam sum ^= eeval; 1828185377Ssam } 1829185377Ssam if (sum != 0xffff) { 1830185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n", 1831185377Ssam __func__, sum); 1832185377Ssam return HAL_EEBADSUM; 1833185377Ssam } 1834185377Ssam 1835185377Ssam ee = ath_hal_malloc(sizeof(HAL_EEPROM)); 1836185377Ssam if (ee == AH_NULL) { 1837185377Ssam /* XXX message */ 1838185377Ssam return HAL_ENOMEM; 1839185377Ssam } 1840185377Ssam 1841185377Ssam ee->ee_protect = eeprotect; 1842185377Ssam ee->ee_version = eeversion; 1843185377Ssam 1844185377Ssam ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS; 1845185377Ssam ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS; 1846185377Ssam 1847185377Ssam for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++) 1848185377Ssam ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES; 1849185377Ssam 1850185377Ssam /* the channel list for 2.4 is fixed, fill this in here */ 1851185377Ssam for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) { 1852185377Ssam ee->ee_channels11b[i] = channels11b[i]; 1853185377Ssam /* XXX 5211 requires a hack though we don't support 11g */ 1854185377Ssam if (ah->ah_magic == 0x19570405) 1855185377Ssam ee->ee_channels11g[i] = channels11b[i]; 1856185377Ssam else 1857185377Ssam ee->ee_channels11g[i] = channels11g[i]; 1858185377Ssam ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES; 1859185377Ssam ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES; 1860185377Ssam } 1861185377Ssam 1862185377Ssam if (!legacyEepromReadContents(ah, ee)) { 1863185377Ssam /* XXX message */ 1864185377Ssam ath_hal_free(ee); 1865185377Ssam return HAL_EEREAD; /* XXX */ 1866185377Ssam } 1867185377Ssam 1868185377Ssam AH_PRIVATE(ah)->ah_eeprom = ee; 1869185377Ssam AH_PRIVATE(ah)->ah_eeversion = eeversion; 1870185377Ssam AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach; 1871185377Ssam AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet; 1872185377Ssam AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet; 1873185377Ssam AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan; 1874185377Ssam AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag; 1875185377Ssam return HAL_OK; 1876185377Ssam} 1877