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