2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
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.
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.
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v3.c 196970 2009-09-08 13:19:05Z phk $
23 #include "ah_internal.h"
24 #include "ah_eeprom_v3.h"
27 getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
28 uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
30 static const uint16_t intercepts3[] =
31 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
32 static const uint16_t intercepts3_2[] =
33 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
34 const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
35 intercepts3 : intercepts3_2;
38 /* loop for the percentages in steps or 5 */
39 for (i = 0; i < NUM_INTERCEPTS; i++ )
40 *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;
44 * Get channel value from binary representation held in eeprom
47 fbin2freq(HAL_EEPROM *ee, uint16_t fbin)
49 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
51 return ee->ee_version <= AR_EEPROM_VER3_2 ?
52 (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) :
57 fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin)
59 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
61 return ee->ee_version <= AR_EEPROM_VER3_2 ?
67 * Now copy EEPROM frequency pier contents into the allocated space
70 readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee)
72 #define EEREAD(_off) do { \
73 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
79 if (ee->ee_version >= AR_EEPROM_VER4_0 &&
80 ee->ee_eepMap && !ee->ee_Amode) {
82 * V4.0 EEPROMs with map type 1 have frequency pier
83 * data only when 11a mode is supported.
87 if (ee->ee_version >= AR_EEPROM_VER3_3) {
88 off = GROUPS_OFFSET3_3 + GROUP1_OFFSET;
89 for (i = 0; i < ee->ee_numChannels11a; i += 2) {
91 ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3;
92 ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3;
95 off = GROUPS_OFFSET3_2 + GROUP1_OFFSET;
98 ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK;
99 ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK;
100 ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK;
103 ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f;
104 ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK;
105 ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK;
108 ee->ee_channels11a[4] |= (eeval >> 13) & 0x7;
109 ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK;
110 ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK;
113 ee->ee_channels11a[6] |= (eeval >> 15) & 0x1;
114 ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK;
115 ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK;
116 ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK;
119 ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f;
122 for (i = 0; i < ee->ee_numChannels11a; i++)
123 ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]);
130 * Rev 4 Eeprom 5112 Power Extract Functions
134 * Allocate the power information based on the number of channels
135 * recorded by the calibration. These values are then initialized.
138 eepromAllocExpnPower5112(struct ath_hal *ah,
139 const EEPROM_POWER_5112 *pCalDataset,
140 EEPROM_POWER_EXPN_5112 *pPowerExpn)
142 uint16_t numChannels = pCalDataset->numChannels;
143 const uint16_t *pChanList = pCalDataset->pChannels;
147 /* Allocate the channel and Power Data arrays together */
148 data = ath_hal_malloc(
149 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) +
150 sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels);
151 if (data == AH_NULL) {
152 HALDEBUG(ah, HAL_DEBUG_ANY,
153 "%s unable to allocate raw data struct (gen3)\n", __func__);
156 pPowerExpn->pChannels = data;
157 pPowerExpn->pDataPerChannel = (void *)(((char *)data) +
158 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)));
160 pPowerExpn->numChannels = numChannels;
161 for (i = 0; i < numChannels; i++) {
162 pPowerExpn->pChannels[i] =
163 pPowerExpn->pDataPerChannel[i].channelValue =
165 for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) {
166 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j;
167 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0;
169 pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4;
170 pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3;
176 * Expand the dataSet from the calibration information into the
177 * final power structure for 5112
180 eepromExpandPower5112(struct ath_hal *ah,
181 const EEPROM_POWER_5112 *pCalDataset,
182 EEPROM_POWER_EXPN_5112 *pPowerExpn)
186 EXPN_DATA_PER_XPD_5112 *pExpnXPD;
187 /* ptr to array of info held per channel */
188 const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh;
189 uint16_t xgainList[2], xpdMask;
191 pPowerExpn->xpdMask = pCalDataset->xpdMask;
193 xgainList[0] = 0xDEAD;
194 xgainList[1] = 0xDEAD;
197 xpdMask = pPowerExpn->xpdMask;
198 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
199 if (((xpdMask >> jj) & 1) > 0) {
201 HALDEBUG(ah, HAL_DEBUG_ANY,
202 "%s: too many xpdGains in dataset: %u\n",
206 xgainList[kk++] = jj;
210 pPowerExpn->numChannels = pCalDataset->numChannels;
211 if (pPowerExpn->numChannels == 0) {
212 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__);
216 for (ii = 0; ii < pPowerExpn->numChannels; ii++) {
217 pCalCh = &pCalDataset->pDataPerChannel[ii];
218 pPowerExpn->pDataPerChannel[ii].channelValue =
219 pCalCh->channelValue;
220 pPowerExpn->pDataPerChannel[ii].maxPower_t4 =
222 maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4;
224 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++)
225 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0;
226 if (xgainList[1] == 0xDEAD) {
228 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
229 pExpnXPD->numPcdacs = 4;
230 pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0;
231 pExpnXPD->pcdac[1] = (uint16_t)
232 (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
233 pExpnXPD->pcdac[2] = (uint16_t)
234 (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
235 pExpnXPD->pcdac[3] = (uint16_t)
236 (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
238 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
239 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
240 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
241 pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
244 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0;
245 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20;
246 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35;
247 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63;
250 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
251 pExpnXPD->numPcdacs = 4;
252 pExpnXPD->pcdac[1] = (uint16_t)
253 (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
254 pExpnXPD->pcdac[2] = (uint16_t)
255 (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
256 pExpnXPD->pcdac[3] = (uint16_t)
257 (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
258 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
259 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
260 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
261 pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
264 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
265 pExpnXPD->numPcdacs = 3;
267 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3;
268 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3;
269 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3;
276 readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
278 #define EEREAD(_off) do { \
279 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
282 const uint16_t dbmmask = 0xff;
283 const uint16_t pcdac_delta_mask = 0x1f;
284 const uint16_t pcdac_mask = 0x3f;
285 const uint16_t freqmask = 0xff;
287 int i, mode, numPiers;
290 uint16_t freq[NUM_11A_EEPROM_CHANNELS];
291 EEPROM_POWER_5112 eePower;
293 HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0);
294 off = GROUPS_OFFSET3_3;
295 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
299 if (!ee->ee_Amode) /* no 11a calibration data */
301 while (numPiers < NUM_11A_EEPROM_CHANNELS) {
303 if ((eeval & freqmask) == 0)
305 freq[numPiers++] = fbin2freq(ee,
308 if (((eeval >> 8) & freqmask) == 0)
310 freq[numPiers++] = fbin2freq(ee,
311 (eeval>>8) & freqmask);
315 if (!ee->ee_Bmode) /* no 11b calibration data */
317 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
318 if (ee->ee_calPier11b[i] != CHANNEL_UNUSED)
319 freq[numPiers++] = ee->ee_calPier11b[i];
322 if (!ee->ee_Gmode) /* no 11g calibration data */
324 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
325 if (ee->ee_calPier11g[i] != CHANNEL_UNUSED)
326 freq[numPiers++] = ee->ee_calPier11g[i];
329 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
334 OS_MEMZERO(&eePower, sizeof(eePower));
335 eePower.numChannels = numPiers;
337 for (i = 0; i < numPiers; i++) {
338 eePower.pChannels[i] = freq[i];
339 eePower.pDataPerChannel[i].channelValue = freq[i];
342 eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t)
343 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
344 eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t)
345 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
348 eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t)
349 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
350 eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t)
351 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
354 eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t)
355 (eeval & pcdac_delta_mask);
356 eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t)
357 ((eeval >> 5) & pcdac_delta_mask);
358 eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t)
359 ((eeval >> 10) & pcdac_delta_mask);
362 eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t)
363 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
364 eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t)
365 (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
368 eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t)
369 ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
370 if (ee->ee_version >= AR_EEPROM_VER4_3) {
371 eePower.pDataPerChannel[i].maxPower_t4 =
372 eePower.pDataPerChannel[i].pwr4_xg0;
373 eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t)
374 ((eeval >> 8) & pcdac_mask);
376 eePower.pDataPerChannel[i].maxPower_t4 = (int16_t)
377 (((eeval >> 8) & dbmmask) -
378 ((eeval >> 15) & 0x1)*256);
379 eePower.pDataPerChannel[i].pcd1_xg0 = 1;
382 eePower.xpdMask = ee->ee_xgain[mode];
384 if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
385 HALDEBUG(ah, HAL_DEBUG_ANY,
386 "%s: did not allocate power struct\n", __func__);
389 if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
390 HALDEBUG(ah, HAL_DEBUG_ANY,
391 "%s: did not expand power struct\n", __func__);
400 freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
405 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
406 EEPROM_POWER_EXPN_5112 *pPowerExpn =
407 &ee->ee_modePowerArray5112[mode];
408 data = pPowerExpn->pChannels;
409 if (data != AH_NULL) {
410 pPowerExpn->pChannels = AH_NULL;
417 ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413,
418 uint16_t myNumRawChannels, uint16_t *pMyRawChanList)
420 uint16_t i, channelValue;
422 uint16_t numPdGainsUsed;
424 pEEPROMDataset2413->numChannels = myNumRawChannels;
426 xpd_mask = pEEPROMDataset2413->xpd_mask;
428 if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
429 if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
430 if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
431 if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
433 for (i = 0; i < myNumRawChannels; i++) {
434 channelValue = pMyRawChanList[i];
435 pEEPROMDataset2413->pChannels[i] = channelValue;
436 pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue;
437 pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed;
442 ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee,
443 EEPROM_DATA_STRUCT_2413 *pCalDataset,
444 uint32_t start_offset, uint32_t maxPiers, uint8_t mode)
446 #define EEREAD(_off) do { \
447 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
450 const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */
451 const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */
452 const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */
453 const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */
454 const uint16_t freqmask = 0xff;
457 uint16_t idx, numPiers;
458 uint16_t freq[NUM_11A_EEPROM_CHANNELS];
461 for (numPiers = 0; numPiers < maxPiers;) {
463 if ((eeval & freqmask) == 0)
465 if (mode == headerInfo11A)
466 freq[numPiers++] = fbin2freq(ee, (eeval & freqmask));
468 freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask));
470 if (((eeval >> 8) & freqmask) == 0)
472 if (mode == headerInfo11A)
473 freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask);
475 freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask);
477 ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]);
479 idx = start_offset + (maxPiers / 2);
480 for (ii = 0; ii < pCalDataset->numChannels; ii++) {
481 EEPROM_DATA_PER_CHANNEL_2413 *currCh =
482 &(pCalDataset->pDataPerChannel[ii]);
484 if (currCh->numPdGains > 0) {
486 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
487 * and Vpd values for pdgain_0
490 currCh->pwr_I[0] = eeval & dbm_I_mask;
491 currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask;
492 currCh->pwr_delta_t2[0][0] =
493 (eeval >> 12) & dbm_delta_mask;
496 currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask;
497 currCh->pwr_delta_t2[1][0] =
498 (eeval >> 6) & dbm_delta_mask;
499 currCh->Vpd_delta[1][0] =
500 (eeval >> 10) & Vpd_delta_mask;
503 currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask;
504 currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask;
507 if (currCh->numPdGains > 1) {
509 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
510 * and Vpd values for pdgain_1
512 currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask;
513 currCh->Vpd_I[1] = (eeval >> 15) & 0x1;
517 currCh->Vpd_I[1] |= (eeval & 0x3F) << 1;
518 currCh->pwr_delta_t2[0][1] =
519 (eeval >> 6) & dbm_delta_mask;
520 currCh->Vpd_delta[0][1] =
521 (eeval >> 10) & Vpd_delta_mask;
524 currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask;
525 currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask;
526 currCh->pwr_delta_t2[2][1] =
527 (eeval >> 10) & dbm_delta_mask;
528 currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3;
532 currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2;
533 } else if (currCh->numPdGains == 1) {
535 * Read the last pwr and Vpd values for pdgain_0
537 currCh->pwr_delta_t2[3][0] =
538 (eeval >> 10) & dbm_delta_mask;
539 currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3;
543 currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2;
545 /* 4 words if numPdGains == 1 */
548 if (currCh->numPdGains > 2) {
550 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
551 * and Vpd values for pdgain_2
553 currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask;
554 currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask;
557 currCh->pwr_delta_t2[0][2] =
558 (eeval >> 0) & dbm_delta_mask;
559 currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask;
560 currCh->pwr_delta_t2[1][2] =
561 (eeval >> 10) & dbm_delta_mask;
562 currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3;
566 currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2;
567 currCh->pwr_delta_t2[2][2] =
568 (eeval >> 4) & dbm_delta_mask;
569 currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask;
570 } else if (currCh->numPdGains == 2) {
572 * Read the last pwr and Vpd values for pdgain_1
574 currCh->pwr_delta_t2[3][1] =
575 (eeval >> 4) & dbm_delta_mask;
576 currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask;
578 /* 6 words if numPdGains == 2 */
581 if (currCh->numPdGains > 3) {
583 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
584 * and Vpd values for pdgain_3
586 currCh->pwr_I[3] = (eeval >> 14) & 0x3;
590 currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2;
591 currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask;
592 currCh->pwr_delta_t2[0][3] =
593 (eeval >> 10) & dbm_delta_mask;
594 currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3;
598 currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2;
599 currCh->pwr_delta_t2[1][3] =
600 (eeval >> 4) & dbm_delta_mask;
601 currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask;
602 currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3;
606 currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2;
607 currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask;
608 currCh->pwr_delta_t2[3][3] =
609 (eeval >> 8) & dbm_delta_mask;
610 currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF;
614 currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4;
616 /* 12 words if numPdGains == 4 */
617 } else if (currCh->numPdGains == 3) {
618 /* read the last pwr and Vpd values for pdgain_2 */
619 currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3;
623 currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2;
624 currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask;
626 /* 9 words if numPdGains == 3 */
634 ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal)
636 uint16_t i, j, kk, channelValue;
638 uint16_t numPdGainsUsed;
640 pRaw->numChannels = pCal->numChannels;
642 xpd_mask = pRaw->xpd_mask;
644 if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
645 if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
646 if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
647 if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
649 for (i = 0; i < pCal->numChannels; i++) {
650 channelValue = pCal->pChannels[i];
652 pRaw->pChannels[i] = channelValue;
654 pRaw->pDataPerChannel[i].channelValue = channelValue;
655 pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed;
658 for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) {
659 pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j;
660 if ((xpd_mask >> j) & 0x1) {
661 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS;
665 * lowest pd_gain corresponds
666 * to highest power and thus,
669 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN;
672 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0;
679 ar2413EepromToRawDataset(struct ath_hal *ah,
680 EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw)
682 uint16_t ii, jj, kk, ss;
683 RAW_DATA_PER_PDGAIN_2413 *pRawXPD;
684 /* ptr to array of info held per channel */
685 EEPROM_DATA_PER_CHANNEL_2413 *pCalCh;
686 uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL];
688 uint32_t numPdGainsUsed;
690 HALASSERT(pRaw->xpd_mask == pCal->xpd_mask);
692 xgain_list[0] = 0xDEAD;
693 xgain_list[1] = 0xDEAD;
694 xgain_list[2] = 0xDEAD;
695 xgain_list[3] = 0xDEAD;
698 xpd_mask = pRaw->xpd_mask;
699 for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) {
700 if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1)
701 xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1;
704 pRaw->numChannels = pCal->numChannels;
705 for (ii = 0; ii < pRaw->numChannels; ii++) {
706 pCalCh = &(pCal->pDataPerChannel[ii]);
707 pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue;
709 /* numVpd has already been setup appropriately for the relevant pdGains */
710 for (jj = 0; jj < numPdGainsUsed; jj++) {
711 /* use jj for calDataset and ss for rawDataset */
713 pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]);
714 HALASSERT(pRawXPD->numVpd >= 1);
716 pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]);
717 pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj];
719 for (kk = 1; kk < pRawXPD->numVpd; kk++) {
720 pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]);
721 pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]);
725 /* loop over pd_gains */
727 /* loop over channels */
732 readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee)
734 /* NB: index is 1 less than numPdgains */
735 static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 };
736 EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL;
737 RAW_DATA_STRUCT_2413 *pRaw;
738 int numEEPROMWordsPerChannel;
740 HAL_BOOL ret = AH_FALSE;
742 HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0);
743 HALASSERT(ee->ee_eepMap == 2);
745 pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413));
749 off = ee->ee_eepMap2PowerCalStart;
751 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
752 pCal->xpd_mask = ee->ee_xgain[headerInfo11A];
753 if (!ar2413ReadCalDataset(ah, ee, pCal, off,
754 NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) {
757 pRaw = &ee->ee_rawDataset2413[headerInfo11A];
758 pRaw->xpd_mask = ee->ee_xgain[headerInfo11A];
759 ar2413SetupRawDataset(pRaw, pCal);
760 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
763 /* setup offsets for mode_11a next */
764 numEEPROMWordsPerChannel = wordsForPdgains[
765 pCal->pDataPerChannel[0].numPdGains - 1];
766 off += pCal->numChannels * numEEPROMWordsPerChannel + 5;
769 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
770 pCal->xpd_mask = ee->ee_xgain[headerInfo11B];
771 if (!ar2413ReadCalDataset(ah, ee, pCal, off,
772 NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) {
775 pRaw = &ee->ee_rawDataset2413[headerInfo11B];
776 pRaw->xpd_mask = ee->ee_xgain[headerInfo11B];
777 ar2413SetupRawDataset(pRaw, pCal);
778 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
781 /* setup offsets for mode_11g next */
782 numEEPROMWordsPerChannel = wordsForPdgains[
783 pCal->pDataPerChannel[0].numPdGains - 1];
784 off += pCal->numChannels * numEEPROMWordsPerChannel + 2;
787 OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
788 pCal->xpd_mask = ee->ee_xgain[headerInfo11G];
789 if (!ar2413ReadCalDataset(ah, ee, pCal, off,
790 NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) {
793 pRaw = &ee->ee_rawDataset2413[headerInfo11G];
794 pRaw->xpd_mask = ee->ee_xgain[headerInfo11G];
795 ar2413SetupRawDataset(pRaw, pCal);
796 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
808 * Now copy EEPROM Raw Power Calibration per frequency contents
809 * into the allocated space
812 readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
814 #define EEREAD(_off) do { \
815 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
818 uint16_t eeval, nchan;
822 if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
823 return readEepromRawPowerCalInfo5112(ah, ee);
824 if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2)
825 return readEepromRawPowerCalInfo2413(ah, ee);
828 * Group 2: read raw power data for all frequency piers
830 * NOTE: Group 2 contains the raw power calibration
831 * information for each of the channels that
834 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
835 uint16_t *pChannels = AH_NULL;
836 DATA_PER_CHANNEL *pChannelData = AH_NULL;
838 off = ee->ee_version >= AR_EEPROM_VER3_3 ?
839 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
842 off += GROUP2_OFFSET;
843 nchan = ee->ee_numChannels11a;
844 pChannelData = ee->ee_dataPerChannel11a;
845 pChannels = ee->ee_channels11a;
850 off += GROUP3_OFFSET;
851 nchan = ee->ee_numChannels2_4;
852 pChannelData = ee->ee_dataPerChannel11b;
853 pChannels = ee->ee_channels11b;
858 off += GROUP4_OFFSET;
859 nchan = ee->ee_numChannels2_4;
860 pChannelData = ee->ee_dataPerChannel11g;
861 pChannels = ee->ee_channels11g;
864 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
868 for (i = 0; i < nchan; i++) {
869 pChannelData->channelValue = pChannels[i];
872 pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK);
873 pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK);
874 pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK);
877 pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3);
878 pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK);
879 pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK);
880 pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK);
883 pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf);
884 pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK);
885 pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK);
888 pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK);
889 pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK);
890 pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK);
893 pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3);
894 pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK);
895 pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK);
897 getPcdacInterceptsFromPcdacMinMax(ee,
898 pChannelData->pcdacMin, pChannelData->pcdacMax,
899 pChannelData->PcdacValues) ;
901 for (j = 0; j < pChannelData->numPcdacValues; j++) {
902 pChannelData->PwrValues[j] = (uint16_t)(
903 PWR_STEP * pChannelData->PwrValues[j]);
904 /* Note these values are scaled up. */
914 * Copy EEPROM Target Power Calbration per rate contents
915 * into the allocated space
918 readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
920 #define EEREAD(_off) do { \
921 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
924 uint16_t eeval, enable24;
928 enable24 = ee->ee_Bmode || ee->ee_Gmode;
929 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
930 TRGT_POWER_INFO *pPowerInfo;
931 uint16_t *pNumTrgtChannels;
933 off = ee->ee_version >= AR_EEPROM_VER4_0 ?
934 ee->ee_targetPowersStart - GROUP5_OFFSET :
935 ee->ee_version >= AR_EEPROM_VER3_3 ?
936 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
939 off += GROUP5_OFFSET;
940 nchan = NUM_TEST_FREQUENCIES;
941 pPowerInfo = ee->ee_trgtPwr_11a;
942 pNumTrgtChannels = &ee->ee_numTargetPwr_11a;
947 off += GROUP6_OFFSET;
949 pPowerInfo = ee->ee_trgtPwr_11b;
950 pNumTrgtChannels = &ee->ee_numTargetPwr_11b;
955 off += GROUP7_OFFSET;
957 pPowerInfo = ee->ee_trgtPwr_11g;
958 pNumTrgtChannels = &ee->ee_numTargetPwr_11g;
961 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
965 *pNumTrgtChannels = 0;
966 for (i = 0; i < nchan; i++) {
968 if (ee->ee_version >= AR_EEPROM_VER3_3) {
969 pPowerInfo->testChannel = (eeval >> 8) & 0xff;
971 pPowerInfo->testChannel = (eeval >> 9) & 0x7f;
974 if (pPowerInfo->testChannel != 0) {
975 /* get the channel value and read rest of info */
976 if (mode == headerInfo11A) {
977 pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel);
979 pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel);
982 if (ee->ee_version >= AR_EEPROM_VER3_3) {
983 pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK;
984 pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK;
986 pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK;
987 pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK;
991 if (ee->ee_version >= AR_EEPROM_VER3_3) {
992 pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf;
993 pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK;
994 pPowerInfo->twicePwr54 = eeval & POWER_MASK;
996 pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7;
997 pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK;
998 pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK;
1000 (*pNumTrgtChannels)++;
1010 * Now copy EEPROM Coformance Testing Limits contents
1011 * into the allocated space
1014 readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1016 #define EEREAD(_off) do { \
1017 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1020 RD_EDGES_POWER *rep;
1025 rep = ee->ee_rdEdgesPower;
1027 off = GROUP8_OFFSET +
1028 (ee->ee_version >= AR_EEPROM_VER4_0 ?
1029 ee->ee_targetPowersStart - GROUP5_OFFSET :
1030 ee->ee_version >= AR_EEPROM_VER3_3 ?
1031 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2);
1032 for (i = 0; i < ee->ee_numCtls; i++) {
1033 if (ee->ee_ctl[i] == 0) {
1034 /* Move offset and edges */
1035 off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7);
1039 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1040 for (j = 0; j < NUM_EDGES; j += 2) {
1042 rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3;
1043 rep[j+1].rdEdge = eeval & FREQ_MASK_3_3;
1045 for (j = 0; j < NUM_EDGES; j += 2) {
1047 rep[j].twice_rdEdgePower =
1048 (eeval >> 8) & POWER_MASK;
1049 rep[j].flag = (eeval >> 14) & 1;
1050 rep[j+1].twice_rdEdgePower = eeval & POWER_MASK;
1051 rep[j+1].flag = (eeval >> 6) & 1;
1055 rep[0].rdEdge = (eeval >> 9) & FREQ_MASK;
1056 rep[1].rdEdge = (eeval >> 2) & FREQ_MASK;
1057 rep[2].rdEdge = (eeval << 5) & FREQ_MASK;
1060 rep[2].rdEdge |= (eeval >> 11) & 0x1f;
1061 rep[3].rdEdge = (eeval >> 4) & FREQ_MASK;
1062 rep[4].rdEdge = (eeval << 3) & FREQ_MASK;
1065 rep[4].rdEdge |= (eeval >> 13) & 0x7;
1066 rep[5].rdEdge = (eeval >> 6) & FREQ_MASK;
1067 rep[6].rdEdge = (eeval << 1) & FREQ_MASK;
1070 rep[6].rdEdge |= (eeval >> 15) & 0x1;
1071 rep[7].rdEdge = (eeval >> 8) & FREQ_MASK;
1073 rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK;
1074 rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK;
1077 rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf;
1078 rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK;
1079 rep[3].twice_rdEdgePower = eeval & POWER_MASK;
1082 rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK;
1083 rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK;
1084 rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK;
1087 rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3;
1088 rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK;
1091 for (j = 0; j < NUM_EDGES; j++ ) {
1092 if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) {
1093 if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A ||
1094 (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) {
1095 rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge);
1097 rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge);
1108 * Read the individual header fields for a Rev 3 EEPROM
1111 readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1113 #define EEREAD(_off) do { \
1114 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1117 static const uint32_t headerOffset3_0[] = {
1118 0x00C2, /* 0 - Mode bits, device type, max turbo power */
1119 0x00C4, /* 1 - 2.4 and 5 antenna gain */
1120 0x00C5, /* 2 - Begin 11A modal section */
1121 0x00D0, /* 3 - Begin 11B modal section */
1122 0x00DA, /* 4 - Begin 11G modal section */
1123 0x00E4 /* 5 - Begin CTL section */
1125 static const uint32_t headerOffset3_3[] = {
1126 0x00C2, /* 0 - Mode bits, device type, max turbo power */
1127 0x00C3, /* 1 - 2.4 and 5 antenna gain */
1128 0x00D4, /* 2 - Begin 11A modal section */
1129 0x00F2, /* 3 - Begin 11B modal section */
1130 0x010D, /* 4 - Begin 11G modal section */
1131 0x0128 /* 5 - Begin CTL section */
1134 static const uint32_t regCapOffsetPre4_0 = 0x00CF;
1135 static const uint32_t regCapOffsetPost4_0 = 0x00CA;
1137 const uint32_t *header;
1142 /* initialize cckOfdmGainDelta for < 4.2 eeprom */
1143 ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA;
1144 ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT;
1146 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1147 header = headerOffset3_3;
1148 ee->ee_numCtls = NUM_CTLS_3_3;
1150 header = headerOffset3_0;
1151 ee->ee_numCtls = NUM_CTLS;
1153 HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX);
1156 ee->ee_turbo5Disable = (eeval >> 15) & 0x01;
1157 ee->ee_rfKill = (eeval >> 14) & 0x01;
1158 ee->ee_deviceType = (eeval >> 11) & 0x07;
1159 ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F;
1160 if (ee->ee_version >= AR_EEPROM_VER4_0)
1161 ee->ee_turbo2Disable = (eeval >> 3) & 0x01;
1163 ee->ee_turbo2Disable = 1;
1164 ee->ee_Gmode = (eeval >> 2) & 0x01;
1165 ee->ee_Bmode = (eeval >> 1) & 0x01;
1166 ee->ee_Amode = (eeval & 0x01);
1170 ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF);
1171 ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF);
1172 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1174 ee->ee_eepMap = (eeval>>14) & 0x3;
1175 ee->ee_disableXr5 = (eeval>>13) & 0x1;
1176 ee->ee_disableXr2 = (eeval>>12) & 0x1;
1177 ee->ee_earStart = eeval & 0xfff;
1180 ee->ee_targetPowersStart = eeval & 0xfff;
1181 ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1;
1183 if (ee->ee_version >= AR_EEPROM_VER5_0) {
1186 ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff;
1187 /* Properly cal'ed 5.0 devices should be non-zero */
1191 /* Read the moded sections of the EEPROM header in the order A, B, G */
1192 for (i = headerInfo11A; i <= headerInfo11G; i++) {
1193 /* Set the offset via the index */
1194 off = header[2 + i];
1197 ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f;
1198 ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f;
1199 ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f;
1202 ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f;
1203 ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f;
1204 ee->ee_antennaControl[2][i] = eeval & 0x3f;
1207 ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f;
1208 ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f;
1209 ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f;
1212 ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03;
1213 ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f;
1214 ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f;
1215 ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f;
1218 ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f;
1219 ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f;
1220 ee->ee_antennaControl[10][i] = eeval & 0x3f;
1223 ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff);
1226 ee->ee_ob4 = (eeval >> 5) & 0x07;
1227 ee->ee_db4 = (eeval >> 2) & 0x07;
1228 ee->ee_ob3 = (eeval << 1) & 0x07;
1231 ee->ee_obFor24 = (eeval >> 4) & 0x07;
1232 ee->ee_dbFor24 = eeval & 0x07;
1235 ee->ee_obFor24g = (eeval >> 4) & 0x07;
1236 ee->ee_dbFor24g = eeval & 0x07;
1240 if (i == headerInfo11A) {
1242 ee->ee_ob3 |= (eeval >> 15) & 0x01;
1243 ee->ee_db3 = (eeval >> 12) & 0x07;
1244 ee->ee_ob2 = (eeval >> 9) & 0x07;
1245 ee->ee_db2 = (eeval >> 6) & 0x07;
1246 ee->ee_ob1 = (eeval >> 3) & 0x07;
1247 ee->ee_db1 = eeval & 0x07;
1251 ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff;
1252 ee->ee_thresh62[i] = eeval & 0xff;
1255 ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff;
1256 ee->ee_txFrameToXPAOn[i] = eeval & 0xff;
1259 ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff);
1260 ee->ee_noiseFloorThresh[i] = eeval & 0xff;
1261 if (ee->ee_noiseFloorThresh[i] & 0x80) {
1262 ee->ee_noiseFloorThresh[i] = 0 -
1263 ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1);
1267 ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff;
1268 ee->ee_xgain[i] = (eeval >> 1) & 0x0f;
1269 ee->ee_xpd[i] = eeval & 0x01;
1270 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1273 ee->ee_fixedBias5 = (eeval >> 13) & 0x1;
1276 ee->ee_fixedBias2 = (eeval >> 13) & 0x1;
1281 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1283 ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F;
1286 ee->ee_ob2GHz[0] = eeval & 0x7;
1287 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1290 ee->ee_ob2GHz[1] = eeval & 0x7;
1291 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1294 ee->ee_xrTargetPower5 = eeval & 0x3f;
1298 if (ee->ee_version >= AR_EEPROM_VER3_4) {
1299 ee->ee_gainI[i] = (eeval >> 13) & 0x07;
1302 ee->ee_gainI[i] |= (eeval << 3) & 0x38;
1303 if (i == headerInfo11G) {
1304 ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF;
1305 if (ee->ee_version >= AR_EEPROM_VER4_6)
1306 ee->ee_scaledCh14FilterCckDelta =
1307 (eeval >> 11) & 0x1f;
1309 if (i == headerInfo11A &&
1310 ee->ee_version >= AR_EEPROM_VER4_0) {
1311 ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f;
1312 ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f;
1315 ee->ee_gainI[i] = 10;
1316 ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT;
1318 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1322 ee->ee_calPier11b[0] =
1323 fbin2freq_2p4(ee, eeval&0xff);
1324 ee->ee_calPier11b[1] =
1325 fbin2freq_2p4(ee, (eeval >> 8)&0xff);
1327 ee->ee_calPier11b[2] =
1328 fbin2freq_2p4(ee, eeval&0xff);
1329 if (ee->ee_version >= AR_EEPROM_VER4_1)
1330 ee->ee_rxtxMargin[headerInfo11B] =
1331 (eeval >> 8) & 0x3f;
1335 ee->ee_calPier11g[0] =
1336 fbin2freq_2p4(ee, eeval & 0xff);
1337 ee->ee_calPier11g[1] =
1338 fbin2freq_2p4(ee, (eeval >> 8) & 0xff);
1341 ee->ee_turbo2WMaxPower2 = eeval & 0x7F;
1342 ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f;
1345 ee->ee_calPier11g[2] =
1346 fbin2freq_2p4(ee, eeval & 0xff);
1347 if (ee->ee_version >= AR_EEPROM_VER4_1)
1348 ee->ee_rxtxMargin[headerInfo11G] =
1349 (eeval >> 8) & 0x3f;
1352 ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F;
1353 ee->ee_iqCalQ[1] = eeval & 0x1F;
1355 if (ee->ee_version >= AR_EEPROM_VER4_2) {
1357 ee->ee_cckOfdmGainDelta =
1358 (uint8_t)(eeval & 0xFF);
1359 if (ee->ee_version >= AR_EEPROM_VER5_0) {
1360 ee->ee_switchSettlingTurbo[1] =
1361 (eeval >> 8) & 0x7f;
1362 ee->ee_txrxAttenTurbo[1] =
1363 (eeval >> 15) & 0x1;
1365 ee->ee_txrxAttenTurbo[1] |=
1366 (eeval & 0x1F) << 1;
1367 ee->ee_rxtxMarginTurbo[1] =
1368 (eeval >> 5) & 0x3F;
1369 ee->ee_adcDesiredSizeTurbo[1] =
1370 (eeval >> 11) & 0x1F;
1372 ee->ee_adcDesiredSizeTurbo[1] |=
1374 ee->ee_pgaDesiredSizeTurbo[1] =
1375 (eeval >> 3) & 0xFF;
1380 if (ee->ee_version >= AR_EEPROM_VER4_1) {
1382 ee->ee_rxtxMargin[headerInfo11A] =
1384 if (ee->ee_version >= AR_EEPROM_VER5_0) {
1385 ee->ee_switchSettlingTurbo[0] =
1386 (eeval >> 6) & 0x7f;
1387 ee->ee_txrxAttenTurbo[0] =
1388 (eeval >> 13) & 0x7;
1390 ee->ee_txrxAttenTurbo[0] |=
1392 ee->ee_rxtxMarginTurbo[0] =
1393 (eeval >> 3) & 0x3F;
1394 ee->ee_adcDesiredSizeTurbo[0] =
1395 (eeval >> 9) & 0x7F;
1397 ee->ee_adcDesiredSizeTurbo[0] |=
1399 ee->ee_pgaDesiredSizeTurbo[0] =
1400 (eeval >> 1) & 0xFF;
1407 if (ee->ee_version < AR_EEPROM_VER3_3) {
1408 /* Version 3.1+ specific parameters */
1410 ee->ee_ob2GHz[0] = eeval & 0x7;
1411 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1414 ee->ee_ob2GHz[1] = eeval & 0x7;
1415 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1418 /* Initialize corner cal (thermal tx gain adjust parameters) */
1419 ee->ee_cornerCal.clip = 4;
1420 ee->ee_cornerCal.pd90 = 1;
1421 ee->ee_cornerCal.pd84 = 1;
1422 ee->ee_cornerCal.gSel = 0;
1425 * Read the conformance test limit identifiers
1426 * These are used to match regulatory domain testing needs with
1427 * the RD-specific tests that have been calibrated in the EEPROM.
1430 for (i = 0; i < ee->ee_numCtls; i += 2) {
1432 ee->ee_ctl[i] = (eeval >> 8) & 0xff;
1433 ee->ee_ctl[i+1] = eeval & 0xff;
1436 if (ee->ee_version < AR_EEPROM_VER5_3) {
1437 /* XXX only for 5413? */
1438 ee->ee_spurChans[0][1] = AR_SPUR_5413_1;
1439 ee->ee_spurChans[1][1] = AR_SPUR_5413_2;
1440 ee->ee_spurChans[2][1] = AR_NO_SPUR;
1441 ee->ee_spurChans[0][0] = AR_NO_SPUR;
1443 /* Read spur mitigation data */
1444 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
1446 ee->ee_spurChans[i][0] = eeval;
1447 EEREAD(off+AR_EEPROM_MODAL_SPURS);
1448 ee->ee_spurChans[i][1] = eeval;
1453 /* for recent changes to NF scale */
1454 if (ee->ee_version <= AR_EEPROM_VER3_2) {
1455 ee->ee_noiseFloorThresh[headerInfo11A] = -54;
1456 ee->ee_noiseFloorThresh[headerInfo11B] = -1;
1457 ee->ee_noiseFloorThresh[headerInfo11G] = -1;
1459 /* to override thresh62 for better 2.4 and 5 operation */
1460 if (ee->ee_version <= AR_EEPROM_VER3_2) {
1461 ee->ee_thresh62[headerInfo11A] = 15; /* 11A */
1462 ee->ee_thresh62[headerInfo11B] = 28; /* 11B */
1463 ee->ee_thresh62[headerInfo11G] = 28; /* 11G */
1466 /* Check for regulatory capabilities */
1467 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1468 EEREAD(regCapOffsetPost4_0);
1470 EEREAD(regCapOffsetPre4_0);
1473 ee->ee_regCap = eeval;
1475 if (ee->ee_Amode == 0) {
1476 /* Check for valid Amode in upgraded h/w */
1477 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1478 ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0;
1480 ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0;
1484 if (ee->ee_version >= AR_EEPROM_VER5_1)
1485 EEREAD(AR_EEPROM_CAPABILITIES_OFFSET);
1488 ee->ee_opCap = eeval;
1490 EEREAD(AR_EEPROM_REG_DOMAIN);
1491 ee->ee_regdomain = eeval;
1498 * Now verify and copy EEPROM contents into the allocated space
1501 legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee)
1503 /* Read the header information here */
1504 if (!readHeaderInfo(ah, ee))
1507 /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */
1508 if (IS_5112(ah) && !ee->ee_eepMap) {
1509 HALDEBUG(ah, HAL_DEBUG_ANY,
1510 "%s: 5112 devices must have EEPROM 4.0 with the "
1511 "EEP_MAP set\n", __func__);
1516 * Group 1: frequency pier locations readback
1517 * check that the structure has been populated
1518 * with enough space to hold the channels
1520 * NOTE: Group 1 contains the 5 GHz channel numbers
1521 * that have dBm->pcdac calibrated information.
1523 if (!readEepromFreqPierInfo(ah, ee))
1527 * Group 2: readback data for all frequency piers
1529 * NOTE: Group 2 contains the raw power calibration
1530 * information for each of the channels that we
1533 if (!readEepromRawPowerCalInfo(ah, ee))
1537 * Group 5: target power values per rate
1539 * NOTE: Group 5 contains the recorded maximum power
1540 * in dB that can be attained for the given rate.
1542 /* Read the power per rate info for test channels */
1543 if (!readEepromTargetPowerCalInfo(ah, ee))
1547 * Group 8: Conformance Test Limits information
1549 * NOTE: Group 8 contains the values to limit the
1550 * maximum transmit power value based on any
1551 * band edge violations.
1553 /* Read the RD edge power limits */
1554 return readEepromCTLInfo(ah, ee);
1558 legacyEepromGet(struct ath_hal *ah, int param, void *val)
1560 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1568 *(uint16_t *) val = ee->ee_opCap;
1570 case AR_EEP_REGDMN_0:
1571 *(uint16_t *) val = ee->ee_regdomain;
1573 case AR_EEP_RFSILENT:
1574 if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval))
1576 *(uint16_t *) val = eeval;
1578 case AR_EEP_MACADDR:
1581 for (i = 0; i < 3; i++) {
1582 if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) {
1583 HALDEBUG(ah, HAL_DEBUG_ANY,
1584 "%s: cannot read EEPROM location %u\n",
1589 macaddr[2*i] = eeval >> 8;
1590 macaddr[2*i + 1] = eeval & 0xff;
1592 if (sum == 0 || sum == 0xffff*3) {
1593 HALDEBUG(ah, HAL_DEBUG_ANY,
1594 "%s: mac address read failed: %s\n", __func__,
1595 ath_hal_ether_sprintf(macaddr));
1596 return HAL_EEBADMAC;
1600 HALASSERT(val == AH_NULL);
1601 return ee->ee_rfKill ? HAL_OK : HAL_EIO;
1603 HALASSERT(val == AH_NULL);
1604 return ee->ee_Amode ? HAL_OK : HAL_EIO;
1606 HALASSERT(val == AH_NULL);
1607 return ee->ee_Bmode ? HAL_OK : HAL_EIO;
1609 HALASSERT(val == AH_NULL);
1610 return ee->ee_Gmode ? HAL_OK : HAL_EIO;
1611 case AR_EEP_TURBO5DISABLE:
1612 HALASSERT(val == AH_NULL);
1613 return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO;
1614 case AR_EEP_TURBO2DISABLE:
1615 HALASSERT(val == AH_NULL);
1616 return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO;
1617 case AR_EEP_ISTALON: /* Talon detect */
1618 HALASSERT(val == AH_NULL);
1619 return (ee->ee_version >= AR_EEPROM_VER5_4 &&
1620 ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ?
1622 case AR_EEP_32KHZCRYSTAL:
1623 HALASSERT(val == AH_NULL);
1624 return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO;
1625 case AR_EEP_COMPRESS:
1626 HALASSERT(val == AH_NULL);
1627 return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ?
1629 case AR_EEP_FASTFRAME:
1630 HALASSERT(val == AH_NULL);
1631 return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ?
1634 HALASSERT(val == AH_NULL);
1635 return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ?
1638 HALASSERT(val == AH_NULL);
1639 return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ?
1642 if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) {
1644 MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU);
1648 case AR_EEP_KCENTRIES:
1649 if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) {
1651 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES);
1655 case AR_EEP_ANTGAINMAX_5:
1656 *(int8_t *) val = ee->ee_antennaGainMax[0];
1658 case AR_EEP_ANTGAINMAX_2:
1659 *(int8_t *) val = ee->ee_antennaGainMax[1];
1661 case AR_EEP_WRITEPROTECT:
1662 HALASSERT(val == AH_NULL);
1663 return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ?
1670 legacyEepromSet(struct ath_hal *ah, int param, int v)
1672 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1684 case AR_EEP_TURBO5DISABLE:
1685 ee->ee_turbo5Disable = v;
1687 case AR_EEP_TURBO2DISABLE:
1688 ee->ee_turbo2Disable = v;
1690 case AR_EEP_COMPRESS:
1692 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS;
1694 ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS;
1696 case AR_EEP_FASTFRAME:
1698 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1700 ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1704 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS;
1706 ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS;
1710 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS;
1712 ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS;
1719 legacyEepromDiag(struct ath_hal *ah, int request,
1720 const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
1722 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1723 const EEPROM_POWER_EXPN_5112 *pe;
1726 case HAL_DIAG_EEPROM:
1728 *resultsize = sizeof(*ee);
1730 case HAL_DIAG_EEPROM_EXP_11A:
1731 case HAL_DIAG_EEPROM_EXP_11B:
1732 case HAL_DIAG_EEPROM_EXP_11G:
1733 pe = &ee->ee_modePowerArray5112[
1734 request - HAL_DIAG_EEPROM_EXP_11A];
1735 *result = pe->pChannels;
1736 *resultsize = (*result == AH_NULL) ? 0 :
1737 roundup(sizeof(uint16_t) * pe->numChannels,
1739 sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels;
1746 legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
1748 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1750 HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS);
1751 return ee->ee_spurChans[ix][is2GHz];
1755 * Reclaim any EEPROM-related storage.
1758 legacyEepromDetach(struct ath_hal *ah)
1760 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1762 if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
1763 freeEepromRawPowerCalInfo5112(ah, ee);
1765 AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
1769 * These are not valid 2.4 channels, either we change 'em
1770 * or we need to change the coding to accept them.
1772 static const uint16_t channels11b[] = { 2412, 2447, 2484 };
1773 static const uint16_t channels11g[] = { 2312, 2412, 2484 };
1776 ath_hal_legacyEepromAttach(struct ath_hal *ah)
1778 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1779 uint32_t sum, eepMax;
1780 uint16_t eeversion, eeprotect, eeval;
1783 HALASSERT(ee == AH_NULL);
1785 if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) {
1786 HALDEBUG(ah, HAL_DEBUG_ANY,
1787 "%s: unable to read EEPROM version\n", __func__);
1790 if (eeversion < AR_EEPROM_VER3) {
1791 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version "
1792 "%u (0x%x) found\n", __func__, eeversion, eeversion);
1793 return HAL_EEVERSION;
1796 if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) {
1797 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection "
1798 "bits; read locked?\n", __func__);
1801 HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect);
1802 /* XXX check proper access before continuing */
1805 * Read the Atheros EEPROM entries and calculate the checksum.
1807 if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) {
1808 HALDEBUG(ah, HAL_DEBUG_ANY,
1809 "%s: cannot read EEPROM upper size\n" , __func__);
1813 eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) <<
1814 AR_EEPROM_SIZE_ENDLOC_SHIFT;
1815 if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) {
1816 HALDEBUG(ah, HAL_DEBUG_ANY,
1817 "%s: cannot read EEPROM lower size\n" , __func__);
1820 eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE;
1822 eepMax = AR_EEPROM_ATHEROS_MAX;
1824 for (i = 0; i < eepMax; i++) {
1825 if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) {
1830 if (sum != 0xffff) {
1831 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
1833 return HAL_EEBADSUM;
1836 ee = ath_hal_malloc(sizeof(HAL_EEPROM));
1837 if (ee == AH_NULL) {
1842 ee->ee_protect = eeprotect;
1843 ee->ee_version = eeversion;
1845 ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS;
1846 ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS;
1848 for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++)
1849 ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES;
1851 /* the channel list for 2.4 is fixed, fill this in here */
1852 for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) {
1853 ee->ee_channels11b[i] = channels11b[i];
1854 /* XXX 5211 requires a hack though we don't support 11g */
1855 if (ah->ah_magic == 0x19570405)
1856 ee->ee_channels11g[i] = channels11b[i];
1858 ee->ee_channels11g[i] = channels11g[i];
1859 ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES;
1860 ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES;
1863 if (!legacyEepromReadContents(ah, ee)) {
1866 return HAL_EEREAD; /* XXX */
1869 AH_PRIVATE(ah)->ah_eeprom = ee;
1870 AH_PRIVATE(ah)->ah_eeversion = eeversion;
1871 AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach;
1872 AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet;
1873 AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet;
1874 AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan;
1875 AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag;