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: ah_eeprom_v3.c,v 1.2 2008/12/11 05:30:29 alc Exp $
22 #include "ah_internal.h"
23 #include "ah_eeprom_v3.h"
26 getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM
*ee
,
27 uint16_t pcdacMin
, uint16_t pcdacMax
, uint16_t *vp
)
29 static const uint16_t intercepts3
[] =
30 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
31 static const uint16_t intercepts3_2
[] =
32 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
33 const uint16_t *ip
= ee
->ee_version
< AR_EEPROM_VER3_2
?
34 intercepts3
: intercepts3_2
;
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
46 fbin2freq(HAL_EEPROM
*ee
, uint16_t fbin
)
48 if (fbin
== CHANNEL_UNUSED
) /* reserved value, don't convert */
50 return ee
->ee_version
<= AR_EEPROM_VER3_2
?
51 (fbin
> 62 ? 5100 + 10*62 + 5*(fbin
-62) : 5100 + 10*fbin
) :
56 fbin2freq_2p4(HAL_EEPROM
*ee
, uint16_t fbin
)
58 if (fbin
== CHANNEL_UNUSED
) /* reserved value, don't convert */
60 return ee
->ee_version
<= AR_EEPROM_VER3_2
?
66 * Now copy EEPROM frequency pier contents into the allocated space
69 readEepromFreqPierInfo(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
71 #define EEREAD(_off) do { \
72 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
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.
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) {
90 ee
->ee_channels11a
[i
] = (eeval
>> 8) & FREQ_MASK_3_3
;
91 ee
->ee_channels11a
[i
+1] = eeval
& FREQ_MASK_3_3
;
94 off
= GROUPS_OFFSET3_2
+ GROUP1_OFFSET
;
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
;
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
;
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
;
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
;
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
]);
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.
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
;
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__
);
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
=
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;
175 * Expand the dataSet from the calibration information into the
176 * final power structure for 5112
179 eepromExpandPower5112(struct ath_hal
*ah
,
180 const EEPROM_POWER_5112
*pCalDataset
,
181 EEPROM_POWER_EXPN_5112
*pPowerExpn
)
185 EXPN_DATA_PER_XPD_5112
*pExpnXPD
;
186 /* ptr to array of info held per channel */
187 const EEPROM_DATA_PER_CHANNEL_5112
*pCalCh
;
188 uint16_t xgainList
[2], xpdMask
;
190 pPowerExpn
->xpdMask
= pCalDataset
->xpdMask
;
192 xgainList
[0] = 0xDEAD;
193 xgainList
[1] = 0xDEAD;
196 xpdMask
= pPowerExpn
->xpdMask
;
197 for (jj
= 0; jj
< NUM_XPD_PER_CHANNEL
; jj
++) {
198 if (((xpdMask
>> jj
) & 1) > 0) {
200 HALDEBUG(ah
, HAL_DEBUG_ANY
,
201 "%s: too many xpdGains in dataset: %u\n",
205 xgainList
[kk
++] = jj
;
209 pPowerExpn
->numChannels
= pCalDataset
->numChannels
;
210 if (pPowerExpn
->numChannels
== 0) {
211 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: no channels\n", __func__
);
215 for (ii
= 0; ii
< pPowerExpn
->numChannels
; ii
++) {
216 pCalCh
= &pCalDataset
->pDataPerChannel
[ii
];
217 pPowerExpn
->pDataPerChannel
[ii
].channelValue
=
218 pCalCh
->channelValue
;
219 pPowerExpn
->pDataPerChannel
[ii
].maxPower_t4
=
221 maxPower_t4
= pPowerExpn
->pDataPerChannel
[ii
].maxPower_t4
;
223 for (jj
= 0; jj
< NUM_XPD_PER_CHANNEL
; jj
++)
224 pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[jj
].numPcdacs
= 0;
225 if (xgainList
[1] == 0xDEAD) {
227 pExpnXPD
= &pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[jj
];
228 pExpnXPD
->numPcdacs
= 4;
229 pExpnXPD
->pcdac
[0] = pCalCh
->pcd1_xg0
;
230 pExpnXPD
->pcdac
[1] = (uint16_t)
231 (pExpnXPD
->pcdac
[0] + pCalCh
->pcd2_delta_xg0
);
232 pExpnXPD
->pcdac
[2] = (uint16_t)
233 (pExpnXPD
->pcdac
[1] + pCalCh
->pcd3_delta_xg0
);
234 pExpnXPD
->pcdac
[3] = (uint16_t)
235 (pExpnXPD
->pcdac
[2] + pCalCh
->pcd4_delta_xg0
);
237 pExpnXPD
->pwr_t4
[0] = pCalCh
->pwr1_xg0
;
238 pExpnXPD
->pwr_t4
[1] = pCalCh
->pwr2_xg0
;
239 pExpnXPD
->pwr_t4
[2] = pCalCh
->pwr3_xg0
;
240 pExpnXPD
->pwr_t4
[3] = pCalCh
->pwr4_xg0
;
243 pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[xgainList
[0]].pcdac
[0] = pCalCh
->pcd1_xg0
;
244 pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[xgainList
[1]].pcdac
[0] = 20;
245 pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[xgainList
[1]].pcdac
[1] = 35;
246 pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[xgainList
[1]].pcdac
[2] = 63;
249 pExpnXPD
= &pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[jj
];
250 pExpnXPD
->numPcdacs
= 4;
251 pExpnXPD
->pcdac
[1] = (uint16_t)
252 (pExpnXPD
->pcdac
[0] + pCalCh
->pcd2_delta_xg0
);
253 pExpnXPD
->pcdac
[2] = (uint16_t)
254 (pExpnXPD
->pcdac
[1] + pCalCh
->pcd3_delta_xg0
);
255 pExpnXPD
->pcdac
[3] = (uint16_t)
256 (pExpnXPD
->pcdac
[2] + pCalCh
->pcd4_delta_xg0
);
257 pExpnXPD
->pwr_t4
[0] = pCalCh
->pwr1_xg0
;
258 pExpnXPD
->pwr_t4
[1] = pCalCh
->pwr2_xg0
;
259 pExpnXPD
->pwr_t4
[2] = pCalCh
->pwr3_xg0
;
260 pExpnXPD
->pwr_t4
[3] = pCalCh
->pwr4_xg0
;
263 pExpnXPD
= &pPowerExpn
->pDataPerChannel
[ii
].pDataPerXPD
[jj
];
264 pExpnXPD
->numPcdacs
= 3;
266 pExpnXPD
->pwr_t4
[0] = pCalCh
->pwr1_xg3
;
267 pExpnXPD
->pwr_t4
[1] = pCalCh
->pwr2_xg3
;
268 pExpnXPD
->pwr_t4
[2] = pCalCh
->pwr3_xg3
;
275 readEepromRawPowerCalInfo5112(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
277 #define EEREAD(_off) do { \
278 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
281 const uint16_t dbmmask
= 0xff;
282 const uint16_t pcdac_delta_mask
= 0x1f;
283 const uint16_t pcdac_mask
= 0x3f;
284 const uint16_t freqmask
= 0xff;
286 int i
, mode
, numPiers
;
289 uint16_t freq
[NUM_11A_EEPROM_CHANNELS
];
290 EEPROM_POWER_5112 eePower
;
292 HALASSERT(ee
->ee_version
>= AR_EEPROM_VER4_0
);
293 off
= GROUPS_OFFSET3_3
;
294 for (mode
= headerInfo11A
; mode
<= headerInfo11G
; mode
++) {
298 if (!ee
->ee_Amode
) /* no 11a calibration data */
300 while (numPiers
< NUM_11A_EEPROM_CHANNELS
) {
302 if ((eeval
& freqmask
) == 0)
304 freq
[numPiers
++] = fbin2freq(ee
,
307 if (((eeval
>> 8) & freqmask
) == 0)
309 freq
[numPiers
++] = fbin2freq(ee
,
310 (eeval
>>8) & freqmask
);
314 if (!ee
->ee_Bmode
) /* no 11b calibration data */
316 for (i
= 0; i
< NUM_2_4_EEPROM_CHANNELS
; i
++)
317 if (ee
->ee_calPier11b
[i
] != CHANNEL_UNUSED
)
318 freq
[numPiers
++] = ee
->ee_calPier11b
[i
];
321 if (!ee
->ee_Gmode
) /* no 11g calibration data */
323 for (i
= 0; i
< NUM_2_4_EEPROM_CHANNELS
; i
++)
324 if (ee
->ee_calPier11g
[i
] != CHANNEL_UNUSED
)
325 freq
[numPiers
++] = ee
->ee_calPier11g
[i
];
328 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid mode 0x%x\n",
333 OS_MEMZERO(&eePower
, sizeof(eePower
));
334 eePower
.numChannels
= numPiers
;
336 for (i
= 0; i
< numPiers
; i
++) {
337 eePower
.pChannels
[i
] = freq
[i
];
338 eePower
.pDataPerChannel
[i
].channelValue
= freq
[i
];
341 eePower
.pDataPerChannel
[i
].pwr1_xg0
= (int16_t)
342 ((eeval
& dbmmask
) - ((eeval
>> 7) & 0x1)*256);
343 eePower
.pDataPerChannel
[i
].pwr2_xg0
= (int16_t)
344 (((eeval
>> 8) & dbmmask
) - ((eeval
>> 15) & 0x1)*256);
347 eePower
.pDataPerChannel
[i
].pwr3_xg0
= (int16_t)
348 ((eeval
& dbmmask
) - ((eeval
>> 7) & 0x1)*256);
349 eePower
.pDataPerChannel
[i
].pwr4_xg0
= (int16_t)
350 (((eeval
>> 8) & dbmmask
) - ((eeval
>> 15) & 0x1)*256);
353 eePower
.pDataPerChannel
[i
].pcd2_delta_xg0
= (uint16_t)
354 (eeval
& pcdac_delta_mask
);
355 eePower
.pDataPerChannel
[i
].pcd3_delta_xg0
= (uint16_t)
356 ((eeval
>> 5) & pcdac_delta_mask
);
357 eePower
.pDataPerChannel
[i
].pcd4_delta_xg0
= (uint16_t)
358 ((eeval
>> 10) & pcdac_delta_mask
);
361 eePower
.pDataPerChannel
[i
].pwr1_xg3
= (int16_t)
362 ((eeval
& dbmmask
) - ((eeval
>> 7) & 0x1)*256);
363 eePower
.pDataPerChannel
[i
].pwr2_xg3
= (int16_t)
364 (((eeval
>> 8) & dbmmask
) - ((eeval
>> 15) & 0x1)*256);
367 eePower
.pDataPerChannel
[i
].pwr3_xg3
= (int16_t)
368 ((eeval
& dbmmask
) - ((eeval
>> 7) & 0x1)*256);
369 if (ee
->ee_version
>= AR_EEPROM_VER4_3
) {
370 eePower
.pDataPerChannel
[i
].maxPower_t4
=
371 eePower
.pDataPerChannel
[i
].pwr4_xg0
;
372 eePower
.pDataPerChannel
[i
].pcd1_xg0
= (uint16_t)
373 ((eeval
>> 8) & pcdac_mask
);
375 eePower
.pDataPerChannel
[i
].maxPower_t4
= (int16_t)
376 (((eeval
>> 8) & dbmmask
) -
377 ((eeval
>> 15) & 0x1)*256);
378 eePower
.pDataPerChannel
[i
].pcd1_xg0
= 1;
381 eePower
.xpdMask
= ee
->ee_xgain
[mode
];
383 if (!eepromAllocExpnPower5112(ah
, &eePower
, &ee
->ee_modePowerArray5112
[mode
])) {
384 HALDEBUG(ah
, HAL_DEBUG_ANY
,
385 "%s: did not allocate power struct\n", __func__
);
388 if (!eepromExpandPower5112(ah
, &eePower
, &ee
->ee_modePowerArray5112
[mode
])) {
389 HALDEBUG(ah
, HAL_DEBUG_ANY
,
390 "%s: did not expand power struct\n", __func__
);
399 freeEepromRawPowerCalInfo5112(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
404 for (mode
= headerInfo11A
; mode
<= headerInfo11G
; mode
++) {
405 EEPROM_POWER_EXPN_5112
*pPowerExpn
=
406 &ee
->ee_modePowerArray5112
[mode
];
407 data
= pPowerExpn
->pChannels
;
408 if (data
!= AH_NULL
) {
409 pPowerExpn
->pChannels
= AH_NULL
;
416 ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413
*pEEPROMDataset2413
,
417 uint16_t myNumRawChannels
, uint16_t *pMyRawChanList
)
419 uint16_t i
, channelValue
;
421 uint16_t numPdGainsUsed
;
423 pEEPROMDataset2413
->numChannels
= myNumRawChannels
;
425 xpd_mask
= pEEPROMDataset2413
->xpd_mask
;
427 if ((xpd_mask
>> 0) & 0x1) numPdGainsUsed
++;
428 if ((xpd_mask
>> 1) & 0x1) numPdGainsUsed
++;
429 if ((xpd_mask
>> 2) & 0x1) numPdGainsUsed
++;
430 if ((xpd_mask
>> 3) & 0x1) numPdGainsUsed
++;
432 for (i
= 0; i
< myNumRawChannels
; i
++) {
433 channelValue
= pMyRawChanList
[i
];
434 pEEPROMDataset2413
->pChannels
[i
] = channelValue
;
435 pEEPROMDataset2413
->pDataPerChannel
[i
].channelValue
= channelValue
;
436 pEEPROMDataset2413
->pDataPerChannel
[i
].numPdGains
= numPdGainsUsed
;
441 ar2413ReadCalDataset(struct ath_hal
*ah
, HAL_EEPROM
*ee
,
442 EEPROM_DATA_STRUCT_2413
*pCalDataset
,
443 uint32_t start_offset
, uint32_t maxPiers
, uint8_t mode
)
445 #define EEREAD(_off) do { \
446 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
449 const uint16_t dbm_I_mask
= 0x1F; /* 5-bits. 1dB step. */
450 const uint16_t dbm_delta_mask
= 0xF; /* 4-bits. 0.5dB step. */
451 const uint16_t Vpd_I_mask
= 0x7F; /* 7-bits. 0-128 */
452 const uint16_t Vpd_delta_mask
= 0x3F; /* 6-bits. 0-63 */
453 const uint16_t freqmask
= 0xff;
456 uint16_t idx
, numPiers
;
457 uint16_t freq
[NUM_11A_EEPROM_CHANNELS
];
460 for (numPiers
= 0; numPiers
< maxPiers
;) {
462 if ((eeval
& freqmask
) == 0)
464 if (mode
== headerInfo11A
)
465 freq
[numPiers
++] = fbin2freq(ee
, (eeval
& freqmask
));
467 freq
[numPiers
++] = fbin2freq_2p4(ee
, (eeval
& freqmask
));
469 if (((eeval
>> 8) & freqmask
) == 0)
471 if (mode
== headerInfo11A
)
472 freq
[numPiers
++] = fbin2freq(ee
, (eeval
>> 8) & freqmask
);
474 freq
[numPiers
++] = fbin2freq_2p4(ee
, (eeval
>> 8) & freqmask
);
476 ar2413SetupEEPROMDataset(pCalDataset
, numPiers
, &freq
[0]);
478 idx
= start_offset
+ (maxPiers
/ 2);
479 for (ii
= 0; ii
< pCalDataset
->numChannels
; ii
++) {
480 EEPROM_DATA_PER_CHANNEL_2413
*currCh
=
481 &(pCalDataset
->pDataPerChannel
[ii
]);
483 if (currCh
->numPdGains
> 0) {
485 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
486 * and Vpd values for pdgain_0
489 currCh
->pwr_I
[0] = eeval
& dbm_I_mask
;
490 currCh
->Vpd_I
[0] = (eeval
>> 5) & Vpd_I_mask
;
491 currCh
->pwr_delta_t2
[0][0] =
492 (eeval
>> 12) & dbm_delta_mask
;
495 currCh
->Vpd_delta
[0][0] = eeval
& Vpd_delta_mask
;
496 currCh
->pwr_delta_t2
[1][0] =
497 (eeval
>> 6) & dbm_delta_mask
;
498 currCh
->Vpd_delta
[1][0] =
499 (eeval
>> 10) & Vpd_delta_mask
;
502 currCh
->pwr_delta_t2
[2][0] = eeval
& dbm_delta_mask
;
503 currCh
->Vpd_delta
[2][0] = (eeval
>> 4) & Vpd_delta_mask
;
506 if (currCh
->numPdGains
> 1) {
508 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
509 * and Vpd values for pdgain_1
511 currCh
->pwr_I
[1] = (eeval
>> 10) & dbm_I_mask
;
512 currCh
->Vpd_I
[1] = (eeval
>> 15) & 0x1;
516 currCh
->Vpd_I
[1] |= (eeval
& 0x3F) << 1;
517 currCh
->pwr_delta_t2
[0][1] =
518 (eeval
>> 6) & dbm_delta_mask
;
519 currCh
->Vpd_delta
[0][1] =
520 (eeval
>> 10) & Vpd_delta_mask
;
523 currCh
->pwr_delta_t2
[1][1] = eeval
& dbm_delta_mask
;
524 currCh
->Vpd_delta
[1][1] = (eeval
>> 4) & Vpd_delta_mask
;
525 currCh
->pwr_delta_t2
[2][1] =
526 (eeval
>> 10) & dbm_delta_mask
;
527 currCh
->Vpd_delta
[2][1] = (eeval
>> 14) & 0x3;
531 currCh
->Vpd_delta
[2][1] |= (eeval
& 0xF) << 2;
532 } else if (currCh
->numPdGains
== 1) {
534 * Read the last pwr and Vpd values for pdgain_0
536 currCh
->pwr_delta_t2
[3][0] =
537 (eeval
>> 10) & dbm_delta_mask
;
538 currCh
->Vpd_delta
[3][0] = (eeval
>> 14) & 0x3;
542 currCh
->Vpd_delta
[3][0] |= (eeval
& 0xF) << 2;
544 /* 4 words if numPdGains == 1 */
547 if (currCh
->numPdGains
> 2) {
549 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
550 * and Vpd values for pdgain_2
552 currCh
->pwr_I
[2] = (eeval
>> 4) & dbm_I_mask
;
553 currCh
->Vpd_I
[2] = (eeval
>> 9) & Vpd_I_mask
;
556 currCh
->pwr_delta_t2
[0][2] =
557 (eeval
>> 0) & dbm_delta_mask
;
558 currCh
->Vpd_delta
[0][2] = (eeval
>> 4) & Vpd_delta_mask
;
559 currCh
->pwr_delta_t2
[1][2] =
560 (eeval
>> 10) & dbm_delta_mask
;
561 currCh
->Vpd_delta
[1][2] = (eeval
>> 14) & 0x3;
565 currCh
->Vpd_delta
[1][2] |= (eeval
& 0xF) << 2;
566 currCh
->pwr_delta_t2
[2][2] =
567 (eeval
>> 4) & dbm_delta_mask
;
568 currCh
->Vpd_delta
[2][2] = (eeval
>> 8) & Vpd_delta_mask
;
569 } else if (currCh
->numPdGains
== 2) {
571 * Read the last pwr and Vpd values for pdgain_1
573 currCh
->pwr_delta_t2
[3][1] =
574 (eeval
>> 4) & dbm_delta_mask
;
575 currCh
->Vpd_delta
[3][1] = (eeval
>> 8) & Vpd_delta_mask
;
577 /* 6 words if numPdGains == 2 */
580 if (currCh
->numPdGains
> 3) {
582 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
583 * and Vpd values for pdgain_3
585 currCh
->pwr_I
[3] = (eeval
>> 14) & 0x3;
589 currCh
->pwr_I
[3] |= ((eeval
>> 0) & 0x7) << 2;
590 currCh
->Vpd_I
[3] = (eeval
>> 3) & Vpd_I_mask
;
591 currCh
->pwr_delta_t2
[0][3] =
592 (eeval
>> 10) & dbm_delta_mask
;
593 currCh
->Vpd_delta
[0][3] = (eeval
>> 14) & 0x3;
597 currCh
->Vpd_delta
[0][3] |= (eeval
& 0xF) << 2;
598 currCh
->pwr_delta_t2
[1][3] =
599 (eeval
>> 4) & dbm_delta_mask
;
600 currCh
->Vpd_delta
[1][3] = (eeval
>> 8) & Vpd_delta_mask
;
601 currCh
->pwr_delta_t2
[2][3] = (eeval
>> 14) & 0x3;
605 currCh
->pwr_delta_t2
[2][3] |= ((eeval
>> 0) & 0x3) << 2;
606 currCh
->Vpd_delta
[2][3] = (eeval
>> 2) & Vpd_delta_mask
;
607 currCh
->pwr_delta_t2
[3][3] =
608 (eeval
>> 8) & dbm_delta_mask
;
609 currCh
->Vpd_delta
[3][3] = (eeval
>> 12) & 0xF;
613 currCh
->Vpd_delta
[3][3] |= ((eeval
>> 0) & 0x3) << 4;
615 /* 12 words if numPdGains == 4 */
616 } else if (currCh
->numPdGains
== 3) {
617 /* read the last pwr and Vpd values for pdgain_2 */
618 currCh
->pwr_delta_t2
[3][2] = (eeval
>> 14) & 0x3;
622 currCh
->pwr_delta_t2
[3][2] |= ((eeval
>> 0) & 0x3) << 2;
623 currCh
->Vpd_delta
[3][2] = (eeval
>> 2) & Vpd_delta_mask
;
625 /* 9 words if numPdGains == 3 */
633 ar2413SetupRawDataset(RAW_DATA_STRUCT_2413
*pRaw
, EEPROM_DATA_STRUCT_2413
*pCal
)
635 uint16_t i
, j
, kk
, channelValue
;
637 uint16_t numPdGainsUsed
;
639 pRaw
->numChannels
= pCal
->numChannels
;
641 xpd_mask
= pRaw
->xpd_mask
;
643 if ((xpd_mask
>> 0) & 0x1) numPdGainsUsed
++;
644 if ((xpd_mask
>> 1) & 0x1) numPdGainsUsed
++;
645 if ((xpd_mask
>> 2) & 0x1) numPdGainsUsed
++;
646 if ((xpd_mask
>> 3) & 0x1) numPdGainsUsed
++;
648 for (i
= 0; i
< pCal
->numChannels
; i
++) {
649 channelValue
= pCal
->pChannels
[i
];
651 pRaw
->pChannels
[i
] = channelValue
;
653 pRaw
->pDataPerChannel
[i
].channelValue
= channelValue
;
654 pRaw
->pDataPerChannel
[i
].numPdGains
= numPdGainsUsed
;
657 for (j
= 0; j
< MAX_NUM_PDGAINS_PER_CHANNEL
; j
++) {
658 pRaw
->pDataPerChannel
[i
].pDataPerPDGain
[j
].pd_gain
= j
;
659 if ((xpd_mask
>> j
) & 0x1) {
660 pRaw
->pDataPerChannel
[i
].pDataPerPDGain
[j
].numVpd
= NUM_POINTS_OTHER_PDGAINS
;
664 * lowest pd_gain corresponds
665 * to highest power and thus,
668 pRaw
->pDataPerChannel
[i
].pDataPerPDGain
[j
].numVpd
= NUM_POINTS_LAST_PDGAIN
;
671 pRaw
->pDataPerChannel
[i
].pDataPerPDGain
[j
].numVpd
= 0;
678 ar2413EepromToRawDataset(struct ath_hal
*ah
,
679 EEPROM_DATA_STRUCT_2413
*pCal
, RAW_DATA_STRUCT_2413
*pRaw
)
681 uint16_t ii
, jj
, kk
, ss
;
682 RAW_DATA_PER_PDGAIN_2413
*pRawXPD
;
683 /* ptr to array of info held per channel */
684 EEPROM_DATA_PER_CHANNEL_2413
*pCalCh
;
685 uint16_t xgain_list
[MAX_NUM_PDGAINS_PER_CHANNEL
];
687 uint32_t numPdGainsUsed
;
689 HALASSERT(pRaw
->xpd_mask
== pCal
->xpd_mask
);
691 xgain_list
[0] = 0xDEAD;
692 xgain_list
[1] = 0xDEAD;
693 xgain_list
[2] = 0xDEAD;
694 xgain_list
[3] = 0xDEAD;
697 xpd_mask
= pRaw
->xpd_mask
;
698 for (jj
= 0; jj
< MAX_NUM_PDGAINS_PER_CHANNEL
; jj
++) {
699 if ((xpd_mask
>> (MAX_NUM_PDGAINS_PER_CHANNEL
-jj
-1)) & 1)
700 xgain_list
[numPdGainsUsed
++] = MAX_NUM_PDGAINS_PER_CHANNEL
-jj
-1;
703 pRaw
->numChannels
= pCal
->numChannels
;
704 for (ii
= 0; ii
< pRaw
->numChannels
; ii
++) {
705 pCalCh
= &(pCal
->pDataPerChannel
[ii
]);
706 pRaw
->pDataPerChannel
[ii
].channelValue
= pCalCh
->channelValue
;
708 /* numVpd has already been setup appropriately for the relevant pdGains */
709 for (jj
= 0; jj
< numPdGainsUsed
; jj
++) {
710 /* use jj for calDataset and ss for rawDataset */
712 pRawXPD
= &(pRaw
->pDataPerChannel
[ii
].pDataPerPDGain
[ss
]);
713 HALASSERT(pRawXPD
->numVpd
>= 1);
715 pRawXPD
->pwr_t4
[0] = (uint16_t)(4*pCalCh
->pwr_I
[jj
]);
716 pRawXPD
->Vpd
[0] = pCalCh
->Vpd_I
[jj
];
718 for (kk
= 1; kk
< pRawXPD
->numVpd
; kk
++) {
719 pRawXPD
->pwr_t4
[kk
] = (int16_t)(pRawXPD
->pwr_t4
[kk
-1] + 2*pCalCh
->pwr_delta_t2
[kk
-1][jj
]);
720 pRawXPD
->Vpd
[kk
] = (uint16_t)(pRawXPD
->Vpd
[kk
-1] + pCalCh
->Vpd_delta
[kk
-1][jj
]);
724 /* loop over pd_gains */
726 /* loop over channels */
731 readEepromRawPowerCalInfo2413(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
733 /* NB: index is 1 less than numPdgains */
734 static const uint16_t wordsForPdgains
[] = { 4, 6, 9, 12 };
735 EEPROM_DATA_STRUCT_2413
*pCal
= AH_NULL
;
736 RAW_DATA_STRUCT_2413
*pRaw
;
737 int numEEPROMWordsPerChannel
;
739 HAL_BOOL ret
= AH_FALSE
;
741 HALASSERT(ee
->ee_version
>= AR_EEPROM_VER5_0
);
742 HALASSERT(ee
->ee_eepMap
== 2);
744 pCal
= ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413
));
748 off
= ee
->ee_eepMap2PowerCalStart
;
750 OS_MEMZERO(pCal
, sizeof(EEPROM_DATA_STRUCT_2413
));
751 pCal
->xpd_mask
= ee
->ee_xgain
[headerInfo11A
];
752 if (!ar2413ReadCalDataset(ah
, ee
, pCal
, off
,
753 NUM_11A_EEPROM_CHANNELS_2413
, headerInfo11A
)) {
756 pRaw
= &ee
->ee_rawDataset2413
[headerInfo11A
];
757 pRaw
->xpd_mask
= ee
->ee_xgain
[headerInfo11A
];
758 ar2413SetupRawDataset(pRaw
, pCal
);
759 if (!ar2413EepromToRawDataset(ah
, pCal
, pRaw
)) {
762 /* setup offsets for mode_11a next */
763 numEEPROMWordsPerChannel
= wordsForPdgains
[
764 pCal
->pDataPerChannel
[0].numPdGains
- 1];
765 off
+= pCal
->numChannels
* numEEPROMWordsPerChannel
+ 5;
768 OS_MEMZERO(pCal
, sizeof(EEPROM_DATA_STRUCT_2413
));
769 pCal
->xpd_mask
= ee
->ee_xgain
[headerInfo11B
];
770 if (!ar2413ReadCalDataset(ah
, ee
, pCal
, off
,
771 NUM_2_4_EEPROM_CHANNELS_2413
, headerInfo11B
)) {
774 pRaw
= &ee
->ee_rawDataset2413
[headerInfo11B
];
775 pRaw
->xpd_mask
= ee
->ee_xgain
[headerInfo11B
];
776 ar2413SetupRawDataset(pRaw
, pCal
);
777 if (!ar2413EepromToRawDataset(ah
, pCal
, pRaw
)) {
780 /* setup offsets for mode_11g next */
781 numEEPROMWordsPerChannel
= wordsForPdgains
[
782 pCal
->pDataPerChannel
[0].numPdGains
- 1];
783 off
+= pCal
->numChannels
* numEEPROMWordsPerChannel
+ 2;
786 OS_MEMZERO(pCal
, sizeof(EEPROM_DATA_STRUCT_2413
));
787 pCal
->xpd_mask
= ee
->ee_xgain
[headerInfo11G
];
788 if (!ar2413ReadCalDataset(ah
, ee
, pCal
, off
,
789 NUM_2_4_EEPROM_CHANNELS_2413
, headerInfo11G
)) {
792 pRaw
= &ee
->ee_rawDataset2413
[headerInfo11G
];
793 pRaw
->xpd_mask
= ee
->ee_xgain
[headerInfo11G
];
794 ar2413SetupRawDataset(pRaw
, pCal
);
795 if (!ar2413EepromToRawDataset(ah
, pCal
, pRaw
)) {
807 * Now copy EEPROM Raw Power Calibration per frequency contents
808 * into the allocated space
811 readEepromRawPowerCalInfo(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
813 #define EEREAD(_off) do { \
814 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
817 uint16_t eeval
, nchan
;
821 if (ee
->ee_version
>= AR_EEPROM_VER4_0
&& ee
->ee_eepMap
== 1)
822 return readEepromRawPowerCalInfo5112(ah
, ee
);
823 if (ee
->ee_version
>= AR_EEPROM_VER5_0
&& ee
->ee_eepMap
== 2)
824 return readEepromRawPowerCalInfo2413(ah
, ee
);
827 * Group 2: read raw power data for all frequency piers
829 * NOTE: Group 2 contains the raw power calibration
830 * information for each of the channels that
833 for (mode
= headerInfo11A
; mode
<= headerInfo11G
; mode
++) {
834 uint16_t *pChannels
= AH_NULL
;
835 DATA_PER_CHANNEL
*pChannelData
= AH_NULL
;
837 off
= ee
->ee_version
>= AR_EEPROM_VER3_3
?
838 GROUPS_OFFSET3_3
: GROUPS_OFFSET3_2
;
841 off
+= GROUP2_OFFSET
;
842 nchan
= ee
->ee_numChannels11a
;
843 pChannelData
= ee
->ee_dataPerChannel11a
;
844 pChannels
= ee
->ee_channels11a
;
849 off
+= GROUP3_OFFSET
;
850 nchan
= ee
->ee_numChannels2_4
;
851 pChannelData
= ee
->ee_dataPerChannel11b
;
852 pChannels
= ee
->ee_channels11b
;
857 off
+= GROUP4_OFFSET
;
858 nchan
= ee
->ee_numChannels2_4
;
859 pChannelData
= ee
->ee_dataPerChannel11g
;
860 pChannels
= ee
->ee_channels11g
;
863 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid mode 0x%x\n",
867 for (i
= 0; i
< nchan
; i
++) {
868 pChannelData
->channelValue
= pChannels
[i
];
871 pChannelData
->pcdacMax
= (uint16_t)((eeval
>> 10) & PCDAC_MASK
);
872 pChannelData
->pcdacMin
= (uint16_t)((eeval
>> 4) & PCDAC_MASK
);
873 pChannelData
->PwrValues
[0] = (uint16_t)((eeval
<< 2) & POWER_MASK
);
876 pChannelData
->PwrValues
[0] |= (uint16_t)((eeval
>> 14) & 0x3);
877 pChannelData
->PwrValues
[1] = (uint16_t)((eeval
>> 8) & POWER_MASK
);
878 pChannelData
->PwrValues
[2] = (uint16_t)((eeval
>> 2) & POWER_MASK
);
879 pChannelData
->PwrValues
[3] = (uint16_t)((eeval
<< 4) & POWER_MASK
);
882 pChannelData
->PwrValues
[3] |= (uint16_t)((eeval
>> 12) & 0xf);
883 pChannelData
->PwrValues
[4] = (uint16_t)((eeval
>> 6) & POWER_MASK
);
884 pChannelData
->PwrValues
[5] = (uint16_t)(eeval
& POWER_MASK
);
887 pChannelData
->PwrValues
[6] = (uint16_t)((eeval
>> 10) & POWER_MASK
);
888 pChannelData
->PwrValues
[7] = (uint16_t)((eeval
>> 4) & POWER_MASK
);
889 pChannelData
->PwrValues
[8] = (uint16_t)((eeval
<< 2) & POWER_MASK
);
892 pChannelData
->PwrValues
[8] |= (uint16_t)((eeval
>> 14) & 0x3);
893 pChannelData
->PwrValues
[9] = (uint16_t)((eeval
>> 8) & POWER_MASK
);
894 pChannelData
->PwrValues
[10] = (uint16_t)((eeval
>> 2) & POWER_MASK
);
896 getPcdacInterceptsFromPcdacMinMax(ee
,
897 pChannelData
->pcdacMin
, pChannelData
->pcdacMax
,
898 pChannelData
->PcdacValues
) ;
900 for (j
= 0; j
< pChannelData
->numPcdacValues
; j
++) {
901 pChannelData
->PwrValues
[j
] = (uint16_t)(
902 PWR_STEP
* pChannelData
->PwrValues
[j
]);
903 /* Note these values are scaled up. */
913 * Copy EEPROM Target Power Calbration per rate contents
914 * into the allocated space
917 readEepromTargetPowerCalInfo(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
919 #define EEREAD(_off) do { \
920 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
923 uint16_t eeval
, enable24
;
927 enable24
= ee
->ee_Bmode
|| ee
->ee_Gmode
;
928 for (mode
= headerInfo11A
; mode
<= headerInfo11G
; mode
++) {
929 TRGT_POWER_INFO
*pPowerInfo
;
930 uint16_t *pNumTrgtChannels
;
932 off
= ee
->ee_version
>= AR_EEPROM_VER4_0
?
933 ee
->ee_targetPowersStart
- GROUP5_OFFSET
:
934 ee
->ee_version
>= AR_EEPROM_VER3_3
?
935 GROUPS_OFFSET3_3
: GROUPS_OFFSET3_2
;
938 off
+= GROUP5_OFFSET
;
939 nchan
= NUM_TEST_FREQUENCIES
;
940 pPowerInfo
= ee
->ee_trgtPwr_11a
;
941 pNumTrgtChannels
= &ee
->ee_numTargetPwr_11a
;
946 off
+= GROUP6_OFFSET
;
948 pPowerInfo
= ee
->ee_trgtPwr_11b
;
949 pNumTrgtChannels
= &ee
->ee_numTargetPwr_11b
;
954 off
+= GROUP7_OFFSET
;
956 pPowerInfo
= ee
->ee_trgtPwr_11g
;
957 pNumTrgtChannels
= &ee
->ee_numTargetPwr_11g
;
960 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid mode 0x%x\n",
964 *pNumTrgtChannels
= 0;
965 for (i
= 0; i
< nchan
; i
++) {
967 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
968 pPowerInfo
->testChannel
= (eeval
>> 8) & 0xff;
970 pPowerInfo
->testChannel
= (eeval
>> 9) & 0x7f;
973 if (pPowerInfo
->testChannel
!= 0) {
974 /* get the channel value and read rest of info */
975 if (mode
== headerInfo11A
) {
976 pPowerInfo
->testChannel
= fbin2freq(ee
, pPowerInfo
->testChannel
);
978 pPowerInfo
->testChannel
= fbin2freq_2p4(ee
, pPowerInfo
->testChannel
);
981 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
982 pPowerInfo
->twicePwr6_24
= (eeval
>> 2) & POWER_MASK
;
983 pPowerInfo
->twicePwr36
= (eeval
<< 4) & POWER_MASK
;
985 pPowerInfo
->twicePwr6_24
= (eeval
>> 3) & POWER_MASK
;
986 pPowerInfo
->twicePwr36
= (eeval
<< 3) & POWER_MASK
;
990 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
991 pPowerInfo
->twicePwr36
|= (eeval
>> 12) & 0xf;
992 pPowerInfo
->twicePwr48
= (eeval
>> 6) & POWER_MASK
;
993 pPowerInfo
->twicePwr54
= eeval
& POWER_MASK
;
995 pPowerInfo
->twicePwr36
|= (eeval
>> 13) & 0x7;
996 pPowerInfo
->twicePwr48
= (eeval
>> 7) & POWER_MASK
;
997 pPowerInfo
->twicePwr54
= (eeval
>> 1) & POWER_MASK
;
999 (*pNumTrgtChannels
)++;
1009 * Now copy EEPROM Coformance Testing Limits contents
1010 * into the allocated space
1013 readEepromCTLInfo(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
1015 #define EEREAD(_off) do { \
1016 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1019 RD_EDGES_POWER
*rep
;
1024 rep
= ee
->ee_rdEdgesPower
;
1026 off
= GROUP8_OFFSET
+
1027 (ee
->ee_version
>= AR_EEPROM_VER4_0
?
1028 ee
->ee_targetPowersStart
- GROUP5_OFFSET
:
1029 ee
->ee_version
>= AR_EEPROM_VER3_3
?
1030 GROUPS_OFFSET3_3
: GROUPS_OFFSET3_2
);
1031 for (i
= 0; i
< ee
->ee_numCtls
; i
++) {
1032 if (ee
->ee_ctl
[i
] == 0) {
1033 /* Move offset and edges */
1034 off
+= (ee
->ee_version
>= AR_EEPROM_VER3_3
? 8 : 7);
1038 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
1039 for (j
= 0; j
< NUM_EDGES
; j
+= 2) {
1041 rep
[j
].rdEdge
= (eeval
>> 8) & FREQ_MASK_3_3
;
1042 rep
[j
+1].rdEdge
= eeval
& FREQ_MASK_3_3
;
1044 for (j
= 0; j
< NUM_EDGES
; j
+= 2) {
1046 rep
[j
].twice_rdEdgePower
=
1047 (eeval
>> 8) & POWER_MASK
;
1048 rep
[j
].flag
= (eeval
>> 14) & 1;
1049 rep
[j
+1].twice_rdEdgePower
= eeval
& POWER_MASK
;
1050 rep
[j
+1].flag
= (eeval
>> 6) & 1;
1054 rep
[0].rdEdge
= (eeval
>> 9) & FREQ_MASK
;
1055 rep
[1].rdEdge
= (eeval
>> 2) & FREQ_MASK
;
1056 rep
[2].rdEdge
= (eeval
<< 5) & FREQ_MASK
;
1059 rep
[2].rdEdge
|= (eeval
>> 11) & 0x1f;
1060 rep
[3].rdEdge
= (eeval
>> 4) & FREQ_MASK
;
1061 rep
[4].rdEdge
= (eeval
<< 3) & FREQ_MASK
;
1064 rep
[4].rdEdge
|= (eeval
>> 13) & 0x7;
1065 rep
[5].rdEdge
= (eeval
>> 6) & FREQ_MASK
;
1066 rep
[6].rdEdge
= (eeval
<< 1) & FREQ_MASK
;
1069 rep
[6].rdEdge
|= (eeval
>> 15) & 0x1;
1070 rep
[7].rdEdge
= (eeval
>> 8) & FREQ_MASK
;
1072 rep
[0].twice_rdEdgePower
= (eeval
>> 2) & POWER_MASK
;
1073 rep
[1].twice_rdEdgePower
= (eeval
<< 4) & POWER_MASK
;
1076 rep
[1].twice_rdEdgePower
|= (eeval
>> 12) & 0xf;
1077 rep
[2].twice_rdEdgePower
= (eeval
>> 6) & POWER_MASK
;
1078 rep
[3].twice_rdEdgePower
= eeval
& POWER_MASK
;
1081 rep
[4].twice_rdEdgePower
= (eeval
>> 10) & POWER_MASK
;
1082 rep
[5].twice_rdEdgePower
= (eeval
>> 4) & POWER_MASK
;
1083 rep
[6].twice_rdEdgePower
= (eeval
<< 2) & POWER_MASK
;
1086 rep
[6].twice_rdEdgePower
|= (eeval
>> 14) & 0x3;
1087 rep
[7].twice_rdEdgePower
= (eeval
>> 8) & POWER_MASK
;
1090 for (j
= 0; j
< NUM_EDGES
; j
++ ) {
1091 if (rep
[j
].rdEdge
!= 0 || rep
[j
].twice_rdEdgePower
!= 0) {
1092 if ((ee
->ee_ctl
[i
] & CTL_MODE_M
) == CTL_11A
||
1093 (ee
->ee_ctl
[i
] & CTL_MODE_M
) == CTL_TURBO
) {
1094 rep
[j
].rdEdge
= fbin2freq(ee
, rep
[j
].rdEdge
);
1096 rep
[j
].rdEdge
= fbin2freq_2p4(ee
, rep
[j
].rdEdge
);
1107 * Read the individual header fields for a Rev 3 EEPROM
1110 readHeaderInfo(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
1112 #define EEREAD(_off) do { \
1113 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1116 static const uint32_t headerOffset3_0
[] = {
1117 0x00C2, /* 0 - Mode bits, device type, max turbo power */
1118 0x00C4, /* 1 - 2.4 and 5 antenna gain */
1119 0x00C5, /* 2 - Begin 11A modal section */
1120 0x00D0, /* 3 - Begin 11B modal section */
1121 0x00DA, /* 4 - Begin 11G modal section */
1122 0x00E4 /* 5 - Begin CTL section */
1124 static const uint32_t headerOffset3_3
[] = {
1125 0x00C2, /* 0 - Mode bits, device type, max turbo power */
1126 0x00C3, /* 1 - 2.4 and 5 antenna gain */
1127 0x00D4, /* 2 - Begin 11A modal section */
1128 0x00F2, /* 3 - Begin 11B modal section */
1129 0x010D, /* 4 - Begin 11G modal section */
1130 0x0128 /* 5 - Begin CTL section */
1133 static const uint32_t regCapOffsetPre4_0
= 0x00CF;
1134 static const uint32_t regCapOffsetPost4_0
= 0x00CA;
1136 const uint32_t *header
;
1141 /* initialize cckOfdmGainDelta for < 4.2 eeprom */
1142 ee
->ee_cckOfdmGainDelta
= CCK_OFDM_GAIN_DELTA
;
1143 ee
->ee_scaledCh14FilterCckDelta
= TENX_CH14_FILTER_CCK_DELTA_INIT
;
1145 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
1146 header
= headerOffset3_3
;
1147 ee
->ee_numCtls
= NUM_CTLS_3_3
;
1149 header
= headerOffset3_0
;
1150 ee
->ee_numCtls
= NUM_CTLS
;
1152 HALASSERT(ee
->ee_numCtls
<= NUM_CTLS_MAX
);
1155 ee
->ee_turbo5Disable
= (eeval
>> 15) & 0x01;
1156 ee
->ee_rfKill
= (eeval
>> 14) & 0x01;
1157 ee
->ee_deviceType
= (eeval
>> 11) & 0x07;
1158 ee
->ee_turbo2WMaxPower5
= (eeval
>> 4) & 0x7F;
1159 if (ee
->ee_version
>= AR_EEPROM_VER4_0
)
1160 ee
->ee_turbo2Disable
= (eeval
>> 3) & 0x01;
1162 ee
->ee_turbo2Disable
= 1;
1163 ee
->ee_Gmode
= (eeval
>> 2) & 0x01;
1164 ee
->ee_Bmode
= (eeval
>> 1) & 0x01;
1165 ee
->ee_Amode
= (eeval
& 0x01);
1169 ee
->ee_antennaGainMax
[0] = (int8_t)((eeval
>> 8) & 0xFF);
1170 ee
->ee_antennaGainMax
[1] = (int8_t)(eeval
& 0xFF);
1171 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1173 ee
->ee_eepMap
= (eeval
>>14) & 0x3;
1174 ee
->ee_disableXr5
= (eeval
>>13) & 0x1;
1175 ee
->ee_disableXr2
= (eeval
>>12) & 0x1;
1176 ee
->ee_earStart
= eeval
& 0xfff;
1179 ee
->ee_targetPowersStart
= eeval
& 0xfff;
1180 ee
->ee_exist32kHzCrystal
= (eeval
>>14) & 0x1;
1182 if (ee
->ee_version
>= AR_EEPROM_VER5_0
) {
1185 ee
->ee_eepMap2PowerCalStart
= (eeval
>> 4) & 0xfff;
1186 /* Properly cal'ed 5.0 devices should be non-zero */
1190 /* Read the moded sections of the EEPROM header in the order A, B, G */
1191 for (i
= headerInfo11A
; i
<= headerInfo11G
; i
++) {
1192 /* Set the offset via the index */
1193 off
= header
[2 + i
];
1196 ee
->ee_switchSettling
[i
] = (eeval
>> 8) & 0x7f;
1197 ee
->ee_txrxAtten
[i
] = (eeval
>> 2) & 0x3f;
1198 ee
->ee_antennaControl
[0][i
] = (eeval
<< 4) & 0x3f;
1201 ee
->ee_antennaControl
[0][i
] |= (eeval
>> 12) & 0x0f;
1202 ee
->ee_antennaControl
[1][i
] = (eeval
>> 6) & 0x3f;
1203 ee
->ee_antennaControl
[2][i
] = eeval
& 0x3f;
1206 ee
->ee_antennaControl
[3][i
] = (eeval
>> 10) & 0x3f;
1207 ee
->ee_antennaControl
[4][i
] = (eeval
>> 4) & 0x3f;
1208 ee
->ee_antennaControl
[5][i
] = (eeval
<< 2) & 0x3f;
1211 ee
->ee_antennaControl
[5][i
] |= (eeval
>> 14) & 0x03;
1212 ee
->ee_antennaControl
[6][i
] = (eeval
>> 8) & 0x3f;
1213 ee
->ee_antennaControl
[7][i
] = (eeval
>> 2) & 0x3f;
1214 ee
->ee_antennaControl
[8][i
] = (eeval
<< 4) & 0x3f;
1217 ee
->ee_antennaControl
[8][i
] |= (eeval
>> 12) & 0x0f;
1218 ee
->ee_antennaControl
[9][i
] = (eeval
>> 6) & 0x3f;
1219 ee
->ee_antennaControl
[10][i
] = eeval
& 0x3f;
1222 ee
->ee_adcDesiredSize
[i
] = (int8_t)((eeval
>> 8) & 0xff);
1225 ee
->ee_ob4
= (eeval
>> 5) & 0x07;
1226 ee
->ee_db4
= (eeval
>> 2) & 0x07;
1227 ee
->ee_ob3
= (eeval
<< 1) & 0x07;
1230 ee
->ee_obFor24
= (eeval
>> 4) & 0x07;
1231 ee
->ee_dbFor24
= eeval
& 0x07;
1234 ee
->ee_obFor24g
= (eeval
>> 4) & 0x07;
1235 ee
->ee_dbFor24g
= eeval
& 0x07;
1239 if (i
== headerInfo11A
) {
1241 ee
->ee_ob3
|= (eeval
>> 15) & 0x01;
1242 ee
->ee_db3
= (eeval
>> 12) & 0x07;
1243 ee
->ee_ob2
= (eeval
>> 9) & 0x07;
1244 ee
->ee_db2
= (eeval
>> 6) & 0x07;
1245 ee
->ee_ob1
= (eeval
>> 3) & 0x07;
1246 ee
->ee_db1
= eeval
& 0x07;
1250 ee
->ee_txEndToXLNAOn
[i
] = (eeval
>> 8) & 0xff;
1251 ee
->ee_thresh62
[i
] = eeval
& 0xff;
1254 ee
->ee_txEndToXPAOff
[i
] = (eeval
>> 8) & 0xff;
1255 ee
->ee_txFrameToXPAOn
[i
] = eeval
& 0xff;
1258 ee
->ee_pgaDesiredSize
[i
] = (int8_t)((eeval
>> 8) & 0xff);
1259 ee
->ee_noiseFloorThresh
[i
] = eeval
& 0xff;
1260 if (ee
->ee_noiseFloorThresh
[i
] & 0x80) {
1261 ee
->ee_noiseFloorThresh
[i
] = 0 -
1262 ((ee
->ee_noiseFloorThresh
[i
] ^ 0xff) + 1);
1266 ee
->ee_xlnaGain
[i
] = (eeval
>> 5) & 0xff;
1267 ee
->ee_xgain
[i
] = (eeval
>> 1) & 0x0f;
1268 ee
->ee_xpd
[i
] = eeval
& 0x01;
1269 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1272 ee
->ee_fixedBias5
= (eeval
>> 13) & 0x1;
1275 ee
->ee_fixedBias2
= (eeval
>> 13) & 0x1;
1280 if (ee
->ee_version
>= AR_EEPROM_VER3_3
) {
1282 ee
->ee_falseDetectBackoff
[i
] = (eeval
>> 6) & 0x7F;
1285 ee
->ee_ob2GHz
[0] = eeval
& 0x7;
1286 ee
->ee_db2GHz
[0] = (eeval
>> 3) & 0x7;
1289 ee
->ee_ob2GHz
[1] = eeval
& 0x7;
1290 ee
->ee_db2GHz
[1] = (eeval
>> 3) & 0x7;
1293 ee
->ee_xrTargetPower5
= eeval
& 0x3f;
1297 if (ee
->ee_version
>= AR_EEPROM_VER3_4
) {
1298 ee
->ee_gainI
[i
] = (eeval
>> 13) & 0x07;
1301 ee
->ee_gainI
[i
] |= (eeval
<< 3) & 0x38;
1302 if (i
== headerInfo11G
) {
1303 ee
->ee_cckOfdmPwrDelta
= (eeval
>> 3) & 0xFF;
1304 if (ee
->ee_version
>= AR_EEPROM_VER4_6
)
1305 ee
->ee_scaledCh14FilterCckDelta
=
1306 (eeval
>> 11) & 0x1f;
1308 if (i
== headerInfo11A
&&
1309 ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1310 ee
->ee_iqCalI
[0] = (eeval
>> 8 ) & 0x3f;
1311 ee
->ee_iqCalQ
[0] = (eeval
>> 3 ) & 0x1f;
1314 ee
->ee_gainI
[i
] = 10;
1315 ee
->ee_cckOfdmPwrDelta
= TENX_OFDM_CCK_DELTA_INIT
;
1317 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1321 ee
->ee_calPier11b
[0] =
1322 fbin2freq_2p4(ee
, eeval
&0xff);
1323 ee
->ee_calPier11b
[1] =
1324 fbin2freq_2p4(ee
, (eeval
>> 8)&0xff);
1326 ee
->ee_calPier11b
[2] =
1327 fbin2freq_2p4(ee
, eeval
&0xff);
1328 if (ee
->ee_version
>= AR_EEPROM_VER4_1
)
1329 ee
->ee_rxtxMargin
[headerInfo11B
] =
1330 (eeval
>> 8) & 0x3f;
1334 ee
->ee_calPier11g
[0] =
1335 fbin2freq_2p4(ee
, eeval
& 0xff);
1336 ee
->ee_calPier11g
[1] =
1337 fbin2freq_2p4(ee
, (eeval
>> 8) & 0xff);
1340 ee
->ee_turbo2WMaxPower2
= eeval
& 0x7F;
1341 ee
->ee_xrTargetPower2
= (eeval
>> 7) & 0x3f;
1344 ee
->ee_calPier11g
[2] =
1345 fbin2freq_2p4(ee
, eeval
& 0xff);
1346 if (ee
->ee_version
>= AR_EEPROM_VER4_1
)
1347 ee
->ee_rxtxMargin
[headerInfo11G
] =
1348 (eeval
>> 8) & 0x3f;
1351 ee
->ee_iqCalI
[1] = (eeval
>> 5) & 0x3F;
1352 ee
->ee_iqCalQ
[1] = eeval
& 0x1F;
1354 if (ee
->ee_version
>= AR_EEPROM_VER4_2
) {
1356 ee
->ee_cckOfdmGainDelta
=
1357 (uint8_t)(eeval
& 0xFF);
1358 if (ee
->ee_version
>= AR_EEPROM_VER5_0
) {
1359 ee
->ee_switchSettlingTurbo
[1] =
1360 (eeval
>> 8) & 0x7f;
1361 ee
->ee_txrxAttenTurbo
[1] =
1362 (eeval
>> 15) & 0x1;
1364 ee
->ee_txrxAttenTurbo
[1] |=
1365 (eeval
& 0x1F) << 1;
1366 ee
->ee_rxtxMarginTurbo
[1] =
1367 (eeval
>> 5) & 0x3F;
1368 ee
->ee_adcDesiredSizeTurbo
[1] =
1369 (eeval
>> 11) & 0x1F;
1371 ee
->ee_adcDesiredSizeTurbo
[1] |=
1373 ee
->ee_pgaDesiredSizeTurbo
[1] =
1374 (eeval
>> 3) & 0xFF;
1379 if (ee
->ee_version
>= AR_EEPROM_VER4_1
) {
1381 ee
->ee_rxtxMargin
[headerInfo11A
] =
1383 if (ee
->ee_version
>= AR_EEPROM_VER5_0
) {
1384 ee
->ee_switchSettlingTurbo
[0] =
1385 (eeval
>> 6) & 0x7f;
1386 ee
->ee_txrxAttenTurbo
[0] =
1387 (eeval
>> 13) & 0x7;
1389 ee
->ee_txrxAttenTurbo
[0] |=
1391 ee
->ee_rxtxMarginTurbo
[0] =
1392 (eeval
>> 3) & 0x3F;
1393 ee
->ee_adcDesiredSizeTurbo
[0] =
1394 (eeval
>> 9) & 0x7F;
1396 ee
->ee_adcDesiredSizeTurbo
[0] |=
1398 ee
->ee_pgaDesiredSizeTurbo
[0] =
1399 (eeval
>> 1) & 0xFF;
1406 if (ee
->ee_version
< AR_EEPROM_VER3_3
) {
1407 /* Version 3.1+ specific parameters */
1409 ee
->ee_ob2GHz
[0] = eeval
& 0x7;
1410 ee
->ee_db2GHz
[0] = (eeval
>> 3) & 0x7;
1413 ee
->ee_ob2GHz
[1] = eeval
& 0x7;
1414 ee
->ee_db2GHz
[1] = (eeval
>> 3) & 0x7;
1417 /* Initialize corner cal (thermal tx gain adjust parameters) */
1418 ee
->ee_cornerCal
.clip
= 4;
1419 ee
->ee_cornerCal
.pd90
= 1;
1420 ee
->ee_cornerCal
.pd84
= 1;
1421 ee
->ee_cornerCal
.gSel
= 0;
1424 * Read the conformance test limit identifiers
1425 * These are used to match regulatory domain testing needs with
1426 * the RD-specific tests that have been calibrated in the EEPROM.
1429 for (i
= 0; i
< ee
->ee_numCtls
; i
+= 2) {
1431 ee
->ee_ctl
[i
] = (eeval
>> 8) & 0xff;
1432 ee
->ee_ctl
[i
+1] = eeval
& 0xff;
1435 if (ee
->ee_version
< AR_EEPROM_VER5_3
) {
1436 /* XXX only for 5413? */
1437 ee
->ee_spurChans
[0][1] = AR_SPUR_5413_1
;
1438 ee
->ee_spurChans
[1][1] = AR_SPUR_5413_2
;
1439 ee
->ee_spurChans
[2][1] = AR_NO_SPUR
;
1440 ee
->ee_spurChans
[0][0] = AR_NO_SPUR
;
1442 /* Read spur mitigation data */
1443 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
1445 ee
->ee_spurChans
[i
][0] = eeval
;
1446 EEREAD(off
+AR_EEPROM_MODAL_SPURS
);
1447 ee
->ee_spurChans
[i
][1] = eeval
;
1452 /* for recent changes to NF scale */
1453 if (ee
->ee_version
<= AR_EEPROM_VER3_2
) {
1454 ee
->ee_noiseFloorThresh
[headerInfo11A
] = -54;
1455 ee
->ee_noiseFloorThresh
[headerInfo11B
] = -1;
1456 ee
->ee_noiseFloorThresh
[headerInfo11G
] = -1;
1458 /* to override thresh62 for better 2.4 and 5 operation */
1459 if (ee
->ee_version
<= AR_EEPROM_VER3_2
) {
1460 ee
->ee_thresh62
[headerInfo11A
] = 15; /* 11A */
1461 ee
->ee_thresh62
[headerInfo11B
] = 28; /* 11B */
1462 ee
->ee_thresh62
[headerInfo11G
] = 28; /* 11G */
1465 /* Check for regulatory capabilities */
1466 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1467 EEREAD(regCapOffsetPost4_0
);
1469 EEREAD(regCapOffsetPre4_0
);
1472 ee
->ee_regCap
= eeval
;
1474 if (ee
->ee_Amode
== 0) {
1475 /* Check for valid Amode in upgraded h/w */
1476 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
1477 ee
->ee_Amode
= (ee
->ee_regCap
& AR_EEPROM_EEREGCAP_EN_KK_NEW_11A
)?1:0;
1479 ee
->ee_Amode
= (ee
->ee_regCap
& AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0
)?1:0;
1483 if (ee
->ee_version
>= AR_EEPROM_VER5_1
)
1484 EEREAD(AR_EEPROM_CAPABILITIES_OFFSET
);
1487 ee
->ee_opCap
= eeval
;
1489 EEREAD(AR_EEPROM_REG_DOMAIN
);
1490 ee
->ee_regdomain
= eeval
;
1497 * Now verify and copy EEPROM contents into the allocated space
1500 legacyEepromReadContents(struct ath_hal
*ah
, HAL_EEPROM
*ee
)
1502 /* Read the header information here */
1503 if (!readHeaderInfo(ah
, ee
))
1506 /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */
1507 if (IS_5112(ah
) && !ee
->ee_eepMap
) {
1508 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1509 "%s: 5112 devices must have EEPROM 4.0 with the "
1510 "EEP_MAP set\n", __func__
);
1515 * Group 1: frequency pier locations readback
1516 * check that the structure has been populated
1517 * with enough space to hold the channels
1519 * NOTE: Group 1 contains the 5 GHz channel numbers
1520 * that have dBm->pcdac calibrated information.
1522 if (!readEepromFreqPierInfo(ah
, ee
))
1526 * Group 2: readback data for all frequency piers
1528 * NOTE: Group 2 contains the raw power calibration
1529 * information for each of the channels that we
1532 if (!readEepromRawPowerCalInfo(ah
, ee
))
1536 * Group 5: target power values per rate
1538 * NOTE: Group 5 contains the recorded maximum power
1539 * in dB that can be attained for the given rate.
1541 /* Read the power per rate info for test channels */
1542 if (!readEepromTargetPowerCalInfo(ah
, ee
))
1546 * Group 8: Conformance Test Limits information
1548 * NOTE: Group 8 contains the values to limit the
1549 * maximum transmit power value based on any
1550 * band edge violations.
1552 /* Read the RD edge power limits */
1553 return readEepromCTLInfo(ah
, ee
);
1557 legacyEepromGet(struct ath_hal
*ah
, int param
, void *val
)
1559 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1567 *(uint16_t *) val
= ee
->ee_opCap
;
1569 case AR_EEP_REGDMN_0
:
1570 *(uint16_t *) val
= ee
->ee_regdomain
;
1572 case AR_EEP_RFSILENT
:
1573 if (!ath_hal_eepromRead(ah
, AR_EEPROM_RFSILENT
, &eeval
))
1575 *(uint16_t *) val
= eeval
;
1577 case AR_EEP_MACADDR
:
1580 for (i
= 0; i
< 3; i
++) {
1581 if (!ath_hal_eepromRead(ah
, AR_EEPROM_MAC(2-i
), &eeval
)) {
1582 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1583 "%s: cannot read EEPROM location %u\n",
1588 macaddr
[2*i
] = eeval
>> 8;
1589 macaddr
[2*i
+ 1] = eeval
& 0xff;
1591 if (sum
== 0 || sum
== 0xffff*3) {
1592 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1593 "%s: mac address read failed: %s\n", __func__
,
1594 ath_hal_ether_sprintf(macaddr
));
1595 return HAL_EEBADMAC
;
1599 HALASSERT(val
== AH_NULL
);
1600 return ee
->ee_rfKill
? HAL_OK
: HAL_EIO
;
1602 HALASSERT(val
== AH_NULL
);
1603 return ee
->ee_Amode
? HAL_OK
: HAL_EIO
;
1605 HALASSERT(val
== AH_NULL
);
1606 return ee
->ee_Bmode
? HAL_OK
: HAL_EIO
;
1608 HALASSERT(val
== AH_NULL
);
1609 return ee
->ee_Gmode
? HAL_OK
: HAL_EIO
;
1610 case AR_EEP_TURBO5DISABLE
:
1611 HALASSERT(val
== AH_NULL
);
1612 return ee
->ee_turbo5Disable
? HAL_OK
: HAL_EIO
;
1613 case AR_EEP_TURBO2DISABLE
:
1614 HALASSERT(val
== AH_NULL
);
1615 return ee
->ee_turbo2Disable
? HAL_OK
: HAL_EIO
;
1616 case AR_EEP_ISTALON
: /* Talon detect */
1617 HALASSERT(val
== AH_NULL
);
1618 return (ee
->ee_version
>= AR_EEPROM_VER5_4
&&
1619 ath_hal_eepromRead(ah
, 0x0b, &eeval
) && eeval
== 1) ?
1621 case AR_EEP_32KHZCRYSTAL
:
1622 HALASSERT(val
== AH_NULL
);
1623 return ee
->ee_exist32kHzCrystal
? HAL_OK
: HAL_EIO
;
1624 case AR_EEP_COMPRESS
:
1625 HALASSERT(val
== AH_NULL
);
1626 return (ee
->ee_opCap
& AR_EEPROM_EEPCAP_COMPRESS_DIS
) == 0 ?
1628 case AR_EEP_FASTFRAME
:
1629 HALASSERT(val
== AH_NULL
);
1630 return (ee
->ee_opCap
& AR_EEPROM_EEPCAP_FASTFRAME_DIS
) == 0 ?
1633 HALASSERT(val
== AH_NULL
);
1634 return (ee
->ee_opCap
& AR_EEPROM_EEPCAP_AES_DIS
) == 0 ?
1637 HALASSERT(val
== AH_NULL
);
1638 return (ee
->ee_opCap
& AR_EEPROM_EEPCAP_BURST_DIS
) == 0 ?
1641 if (ee
->ee_opCap
& AR_EEPROM_EEPCAP_MAXQCU
) {
1643 MS(ee
->ee_opCap
, AR_EEPROM_EEPCAP_MAXQCU
);
1647 case AR_EEP_KCENTRIES
:
1648 if (ee
->ee_opCap
& AR_EEPROM_EEPCAP_KC_ENTRIES
) {
1650 1 << MS(ee
->ee_opCap
, AR_EEPROM_EEPCAP_KC_ENTRIES
);
1654 case AR_EEP_ANTGAINMAX_5
:
1655 *(int8_t *) val
= ee
->ee_antennaGainMax
[0];
1657 case AR_EEP_ANTGAINMAX_2
:
1658 *(int8_t *) val
= ee
->ee_antennaGainMax
[1];
1660 case AR_EEP_WRITEPROTECT
:
1661 HALASSERT(val
== AH_NULL
);
1662 return (ee
->ee_protect
& AR_EEPROM_PROTECT_WP_128_191
) ?
1669 legacyEepromSet(struct ath_hal
*ah
, int param
, int v
)
1671 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1683 case AR_EEP_TURBO5DISABLE
:
1684 ee
->ee_turbo5Disable
= v
;
1686 case AR_EEP_TURBO2DISABLE
:
1687 ee
->ee_turbo2Disable
= v
;
1689 case AR_EEP_COMPRESS
:
1691 ee
->ee_opCap
&= ~AR_EEPROM_EEPCAP_COMPRESS_DIS
;
1693 ee
->ee_opCap
|= AR_EEPROM_EEPCAP_COMPRESS_DIS
;
1695 case AR_EEP_FASTFRAME
:
1697 ee
->ee_opCap
&= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS
;
1699 ee
->ee_opCap
|= AR_EEPROM_EEPCAP_FASTFRAME_DIS
;
1703 ee
->ee_opCap
&= ~AR_EEPROM_EEPCAP_AES_DIS
;
1705 ee
->ee_opCap
|= AR_EEPROM_EEPCAP_AES_DIS
;
1709 ee
->ee_opCap
&= ~AR_EEPROM_EEPCAP_BURST_DIS
;
1711 ee
->ee_opCap
|= AR_EEPROM_EEPCAP_BURST_DIS
;
1718 legacyEepromDiag(struct ath_hal
*ah
, int request
,
1719 const void *args
, uint32_t argsize
, void **result
, uint32_t *resultsize
)
1721 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1722 const EEPROM_POWER_EXPN_5112
*pe
;
1725 case HAL_DIAG_EEPROM
:
1727 *resultsize
= sizeof(*ee
);
1729 case HAL_DIAG_EEPROM_EXP_11A
:
1730 case HAL_DIAG_EEPROM_EXP_11B
:
1731 case HAL_DIAG_EEPROM_EXP_11G
:
1732 pe
= &ee
->ee_modePowerArray5112
[
1733 request
- HAL_DIAG_EEPROM_EXP_11A
];
1734 *result
= pe
->pChannels
;
1735 *resultsize
= (*result
== AH_NULL
) ? 0 :
1736 roundup(sizeof(uint16_t) * pe
->numChannels
,
1738 sizeof(EXPN_DATA_PER_CHANNEL_5112
) * pe
->numChannels
;
1745 legacyEepromGetSpurChan(struct ath_hal
*ah
, int ix
, HAL_BOOL is2GHz
)
1747 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1749 HALASSERT(0 <= ix
&& ix
< AR_EEPROM_MODAL_SPURS
);
1750 return ee
->ee_spurChans
[ix
][is2GHz
];
1754 * Reclaim any EEPROM-related storage.
1757 legacyEepromDetach(struct ath_hal
*ah
)
1759 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1761 if (ee
->ee_version
>= AR_EEPROM_VER4_0
&& ee
->ee_eepMap
== 1)
1762 return freeEepromRawPowerCalInfo5112(ah
, ee
);
1764 AH_PRIVATE(ah
)->ah_eeprom
= AH_NULL
;
1768 * These are not valid 2.4 channels, either we change 'em
1769 * or we need to change the coding to accept them.
1771 static const uint16_t channels11b
[] = { 2412, 2447, 2484 };
1772 static const uint16_t channels11g
[] = { 2312, 2412, 2484 };
1775 ath_hal_legacyEepromAttach(struct ath_hal
*ah
)
1777 HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1778 uint32_t sum
, eepMax
;
1779 uint16_t eeversion
, eeprotect
, eeval
;
1782 HALASSERT(ee
== AH_NULL
);
1784 if (!ath_hal_eepromRead(ah
, AR_EEPROM_VERSION
, &eeversion
)) {
1785 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1786 "%s: unable to read EEPROM version\n", __func__
);
1789 if (eeversion
< AR_EEPROM_VER3
) {
1790 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unsupported EEPROM version "
1791 "%u (0x%x) found\n", __func__
, eeversion
, eeversion
);
1792 return HAL_EEVERSION
;
1795 if (!ath_hal_eepromRead(ah
, AR_EEPROM_PROTECT
, &eeprotect
)) {
1796 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: cannot read EEPROM protection "
1797 "bits; read locked?\n", __func__
);
1800 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "EEPROM protect 0x%x\n", eeprotect
);
1801 /* XXX check proper access before continuing */
1804 * Read the Atheros EEPROM entries and calculate the checksum.
1806 if (!ath_hal_eepromRead(ah
, AR_EEPROM_SIZE_UPPER
, &eeval
)) {
1807 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1808 "%s: cannot read EEPROM upper size\n" , __func__
);
1812 eepMax
= (eeval
& AR_EEPROM_SIZE_UPPER_MASK
) <<
1813 AR_EEPROM_SIZE_ENDLOC_SHIFT
;
1814 if (!ath_hal_eepromRead(ah
, AR_EEPROM_SIZE_LOWER
, &eeval
)) {
1815 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1816 "%s: cannot read EEPROM lower size\n" , __func__
);
1819 eepMax
= (eepMax
| eeval
) - AR_EEPROM_ATHEROS_BASE
;
1821 eepMax
= AR_EEPROM_ATHEROS_MAX
;
1823 for (i
= 0; i
< eepMax
; i
++) {
1824 if (!ath_hal_eepromRead(ah
, AR_EEPROM_ATHEROS(i
), &eeval
)) {
1829 if (sum
!= 0xffff) {
1830 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad EEPROM checksum 0x%x\n",
1832 return HAL_EEBADSUM
;
1835 ee
= ath_hal_malloc(sizeof(HAL_EEPROM
));
1836 if (ee
== AH_NULL
) {
1841 ee
->ee_protect
= eeprotect
;
1842 ee
->ee_version
= eeversion
;
1844 ee
->ee_numChannels11a
= NUM_11A_EEPROM_CHANNELS
;
1845 ee
->ee_numChannels2_4
= NUM_2_4_EEPROM_CHANNELS
;
1847 for (i
= 0; i
< NUM_11A_EEPROM_CHANNELS
; i
++)
1848 ee
->ee_dataPerChannel11a
[i
].numPcdacValues
= NUM_PCDAC_VALUES
;
1850 /* the channel list for 2.4 is fixed, fill this in here */
1851 for (i
= 0; i
< NUM_2_4_EEPROM_CHANNELS
; i
++) {
1852 ee
->ee_channels11b
[i
] = channels11b
[i
];
1853 /* XXX 5211 requires a hack though we don't support 11g */
1854 if (ah
->ah_magic
== 0x19570405)
1855 ee
->ee_channels11g
[i
] = channels11b
[i
];
1857 ee
->ee_channels11g
[i
] = channels11g
[i
];
1858 ee
->ee_dataPerChannel11b
[i
].numPcdacValues
= NUM_PCDAC_VALUES
;
1859 ee
->ee_dataPerChannel11g
[i
].numPcdacValues
= NUM_PCDAC_VALUES
;
1862 if (!legacyEepromReadContents(ah
, ee
)) {
1865 return HAL_EEREAD
; /* XXX */
1868 AH_PRIVATE(ah
)->ah_eeprom
= ee
;
1869 AH_PRIVATE(ah
)->ah_eeversion
= eeversion
;
1870 AH_PRIVATE(ah
)->ah_eepromDetach
= legacyEepromDetach
;
1871 AH_PRIVATE(ah
)->ah_eepromGet
= legacyEepromGet
;
1872 AH_PRIVATE(ah
)->ah_eepromSet
= legacyEepromSet
;
1873 AH_PRIVATE(ah
)->ah_getSpurChan
= legacyEepromGetSpurChan
;
1874 AH_PRIVATE(ah
)->ah_eepromDiag
= legacyEepromDiag
;