1 /*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Copyright (c) 2002-2008 Atheros Communications, Inc.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include "opt_ah.h"
20
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_eeprom_v3.h"
24
25 static void
getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM * ee,uint16_t pcdacMin,uint16_t pcdacMax,uint16_t * vp)26 getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
27 uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
28 {
29 static const uint16_t intercepts3[] =
30 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
31 static const uint16_t intercepts3_2[] =
32 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
33 const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
34 intercepts3 : intercepts3_2;
35 int i;
36
37 /* loop for the percentages in steps or 5 */
38 for (i = 0; i < NUM_INTERCEPTS; i++ )
39 *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;
40 }
41
42 /*
43 * Get channel value from binary representation held in eeprom
44 */
45 static uint16_t
fbin2freq(HAL_EEPROM * ee,uint16_t fbin)46 fbin2freq(HAL_EEPROM *ee, uint16_t fbin)
47 {
48 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
49 return fbin;
50 return ee->ee_version <= AR_EEPROM_VER3_2 ?
51 (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) :
52 4800 + 5*fbin;
53 }
54
55 static uint16_t
fbin2freq_2p4(HAL_EEPROM * ee,uint16_t fbin)56 fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin)
57 {
58 if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
59 return fbin;
60 return ee->ee_version <= AR_EEPROM_VER3_2 ?
61 2400 + fbin :
62 2300 + fbin;
63 }
64
65 /*
66 * Now copy EEPROM frequency pier contents into the allocated space
67 */
68 static HAL_BOOL
readEepromFreqPierInfo(struct ath_hal * ah,HAL_EEPROM * ee)69 readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee)
70 {
71 #define EEREAD(_off) do { \
72 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
73 return AH_FALSE; \
74 } while (0)
75 uint16_t eeval, off;
76 int i;
77
78 if (ee->ee_version >= AR_EEPROM_VER4_0 &&
79 ee->ee_eepMap && !ee->ee_Amode) {
80 /*
81 * V4.0 EEPROMs with map type 1 have frequency pier
82 * data only when 11a mode is supported.
83 */
84 return AH_TRUE;
85 }
86 if (ee->ee_version >= AR_EEPROM_VER3_3) {
87 off = GROUPS_OFFSET3_3 + GROUP1_OFFSET;
88 for (i = 0; i < ee->ee_numChannels11a; i += 2) {
89 EEREAD(off++);
90 ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3;
91 ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3;
92 }
93 } else {
94 off = GROUPS_OFFSET3_2 + GROUP1_OFFSET;
95
96 EEREAD(off++);
97 ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK;
98 ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK;
99 ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK;
100
101 EEREAD(off++);
102 ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f;
103 ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK;
104 ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK;
105
106 EEREAD(off++);
107 ee->ee_channels11a[4] |= (eeval >> 13) & 0x7;
108 ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK;
109 ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK;
110
111 EEREAD(off++);
112 ee->ee_channels11a[6] |= (eeval >> 15) & 0x1;
113 ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK;
114 ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK;
115 ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK;
116
117 EEREAD(off++);
118 ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f;
119 }
120
121 for (i = 0; i < ee->ee_numChannels11a; i++)
122 ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]);
123
124 return AH_TRUE;
125 #undef EEREAD
126 }
127
128 /*
129 * Rev 4 Eeprom 5112 Power Extract Functions
130 */
131
132 /*
133 * Allocate the power information based on the number of channels
134 * recorded by the calibration. These values are then initialized.
135 */
136 static HAL_BOOL
eepromAllocExpnPower5112(struct ath_hal * ah,const EEPROM_POWER_5112 * pCalDataset,EEPROM_POWER_EXPN_5112 * pPowerExpn)137 eepromAllocExpnPower5112(struct ath_hal *ah,
138 const EEPROM_POWER_5112 *pCalDataset,
139 EEPROM_POWER_EXPN_5112 *pPowerExpn)
140 {
141 uint16_t numChannels = pCalDataset->numChannels;
142 const uint16_t *pChanList = pCalDataset->pChannels;
143 void *data;
144 int i, j;
145
146 /* Allocate the channel and Power Data arrays together */
147 data = ath_hal_malloc(
148 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) +
149 sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels);
150 if (data == AH_NULL) {
151 HALDEBUG(ah, HAL_DEBUG_ANY,
152 "%s unable to allocate raw data struct (gen3)\n", __func__);
153 return AH_FALSE;
154 }
155 pPowerExpn->pChannels = data;
156 pPowerExpn->pDataPerChannel = (void *)(((char *)data) +
157 roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)));
158
159 pPowerExpn->numChannels = numChannels;
160 for (i = 0; i < numChannels; i++) {
161 pPowerExpn->pChannels[i] =
162 pPowerExpn->pDataPerChannel[i].channelValue =
163 pChanList[i];
164 for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) {
165 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j;
166 pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0;
167 }
168 pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4;
169 pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3;
170 }
171 return AH_TRUE;
172 }
173
174 /*
175 * Expand the dataSet from the calibration information into the
176 * final power structure for 5112
177 */
178 static HAL_BOOL
eepromExpandPower5112(struct ath_hal * ah,const EEPROM_POWER_5112 * pCalDataset,EEPROM_POWER_EXPN_5112 * pPowerExpn)179 eepromExpandPower5112(struct ath_hal *ah,
180 const EEPROM_POWER_5112 *pCalDataset,
181 EEPROM_POWER_EXPN_5112 *pPowerExpn)
182 {
183 int ii, jj, kk;
184 int16_t maxPower_t4;
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;
189
190 pPowerExpn->xpdMask = pCalDataset->xpdMask;
191
192 xgainList[0] = 0xDEAD;
193 xgainList[1] = 0xDEAD;
194
195 kk = 0;
196 xpdMask = pPowerExpn->xpdMask;
197 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
198 if (((xpdMask >> jj) & 1) > 0) {
199 if (kk > 1) {
200 HALDEBUG(ah, HAL_DEBUG_ANY,
201 "%s: too many xpdGains in dataset: %u\n",
202 __func__, kk);
203 return AH_FALSE;
204 }
205 xgainList[kk++] = jj;
206 }
207 }
208
209 pPowerExpn->numChannels = pCalDataset->numChannels;
210 if (pPowerExpn->numChannels == 0) {
211 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__);
212 return AH_FALSE;
213 }
214
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 =
220 pCalCh->maxPower_t4;
221 maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4;
222
223 for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++)
224 pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0;
225 if (xgainList[1] == 0xDEAD) {
226 jj = xgainList[0];
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);
236
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;
241
242 } else {
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;
247
248 jj = xgainList[0];
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;
261
262 jj = xgainList[1];
263 pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
264 pExpnXPD->numPcdacs = 3;
265
266 pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3;
267 pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3;
268 pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3;
269 }
270 }
271 return AH_TRUE;
272 }
273
274 static HAL_BOOL
readEepromRawPowerCalInfo5112(struct ath_hal * ah,HAL_EEPROM * ee)275 readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
276 {
277 #define EEREAD(_off) do { \
278 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
279 return AH_FALSE; \
280 } while (0)
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;
285
286 int i, mode, numPiers;
287 uint32_t off;
288 uint16_t eeval;
289 uint16_t freq[NUM_11A_EEPROM_CHANNELS];
290 EEPROM_POWER_5112 eePower;
291
292 HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0);
293 off = GROUPS_OFFSET3_3;
294 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
295 numPiers = 0;
296 switch (mode) {
297 case headerInfo11A:
298 if (!ee->ee_Amode) /* no 11a calibration data */
299 continue;
300 while (numPiers < NUM_11A_EEPROM_CHANNELS) {
301 EEREAD(off++);
302 if ((eeval & freqmask) == 0)
303 break;
304 freq[numPiers++] = fbin2freq(ee,
305 eeval & freqmask);
306
307 if (((eeval >> 8) & freqmask) == 0)
308 break;
309 freq[numPiers++] = fbin2freq(ee,
310 (eeval>>8) & freqmask);
311 }
312 break;
313 case headerInfo11B:
314 if (!ee->ee_Bmode) /* no 11b calibration data */
315 continue;
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];
319 break;
320 case headerInfo11G:
321 if (!ee->ee_Gmode) /* no 11g calibration data */
322 continue;
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];
326 break;
327 default:
328 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
329 __func__, mode);
330 return AH_FALSE;
331 }
332
333 OS_MEMZERO(&eePower, sizeof(eePower));
334 eePower.numChannels = numPiers;
335
336 for (i = 0; i < numPiers; i++) {
337 eePower.pChannels[i] = freq[i];
338 eePower.pDataPerChannel[i].channelValue = freq[i];
339
340 EEREAD(off++);
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);
345
346 EEREAD(off++);
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);
351
352 EEREAD(off++);
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);
359
360 EEREAD(off++);
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);
365
366 EEREAD(off++);
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);
374 } else {
375 eePower.pDataPerChannel[i].maxPower_t4 = (int16_t)
376 (((eeval >> 8) & dbmmask) -
377 ((eeval >> 15) & 0x1)*256);
378 eePower.pDataPerChannel[i].pcd1_xg0 = 1;
379 }
380 }
381 eePower.xpdMask = ee->ee_xgain[mode];
382
383 if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
384 HALDEBUG(ah, HAL_DEBUG_ANY,
385 "%s: did not allocate power struct\n", __func__);
386 return AH_FALSE;
387 }
388 if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
389 HALDEBUG(ah, HAL_DEBUG_ANY,
390 "%s: did not expand power struct\n", __func__);
391 return AH_FALSE;
392 }
393 }
394 return AH_TRUE;
395 #undef EEREAD
396 }
397
398 static void
freeEepromRawPowerCalInfo5112(struct ath_hal * ah,HAL_EEPROM * ee)399 freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
400 {
401 int mode;
402 void *data;
403
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;
410 ath_hal_free(data);
411 }
412 }
413 }
414
415 static void
ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 * pEEPROMDataset2413,uint16_t myNumRawChannels,uint16_t * pMyRawChanList)416 ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413,
417 uint16_t myNumRawChannels, uint16_t *pMyRawChanList)
418 {
419 uint16_t i, channelValue;
420 uint32_t xpd_mask;
421 uint16_t numPdGainsUsed;
422
423 pEEPROMDataset2413->numChannels = myNumRawChannels;
424
425 xpd_mask = pEEPROMDataset2413->xpd_mask;
426 numPdGainsUsed = 0;
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++;
431
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;
437 }
438 }
439
440 static HAL_BOOL
ar2413ReadCalDataset(struct ath_hal * ah,HAL_EEPROM * ee,EEPROM_DATA_STRUCT_2413 * pCalDataset,uint32_t start_offset,uint32_t maxPiers,uint8_t mode)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)
444 {
445 #define EEREAD(_off) do { \
446 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
447 return AH_FALSE; \
448 } while (0)
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;
454
455 uint16_t ii, eeval;
456 uint16_t idx, numPiers;
457 uint16_t freq[NUM_11A_EEPROM_CHANNELS];
458
459 idx = start_offset;
460 for (numPiers = 0; numPiers < maxPiers;) {
461 EEREAD(idx++);
462 if ((eeval & freqmask) == 0)
463 break;
464 if (mode == headerInfo11A)
465 freq[numPiers++] = fbin2freq(ee, (eeval & freqmask));
466 else
467 freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask));
468
469 if (((eeval >> 8) & freqmask) == 0)
470 break;
471 if (mode == headerInfo11A)
472 freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask);
473 else
474 freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask);
475 }
476 ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]);
477
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]);
482
483 if (currCh->numPdGains > 0) {
484 /*
485 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
486 * and Vpd values for pdgain_0
487 */
488 EEREAD(idx++);
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;
493
494 EEREAD(idx++);
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;
500
501 EEREAD(idx++);
502 currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask;
503 currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask;
504 }
505
506 if (currCh->numPdGains > 1) {
507 /*
508 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
509 * and Vpd values for pdgain_1
510 */
511 currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask;
512 currCh->Vpd_I[1] = (eeval >> 15) & 0x1;
513
514 EEREAD(idx++);
515 /* upper 6 bits */
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;
521
522 EEREAD(idx++);
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;
528
529 EEREAD(idx++);
530 /* upper 4 bits */
531 currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2;
532 } else if (currCh->numPdGains == 1) {
533 /*
534 * Read the last pwr and Vpd values for pdgain_0
535 */
536 currCh->pwr_delta_t2[3][0] =
537 (eeval >> 10) & dbm_delta_mask;
538 currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3;
539
540 EEREAD(idx++);
541 /* upper 4 bits */
542 currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2;
543
544 /* 4 words if numPdGains == 1 */
545 }
546
547 if (currCh->numPdGains > 2) {
548 /*
549 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
550 * and Vpd values for pdgain_2
551 */
552 currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask;
553 currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask;
554
555 EEREAD(idx++);
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;
562
563 EEREAD(idx++);
564 /* upper 4 bits */
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) {
570 /*
571 * Read the last pwr and Vpd values for pdgain_1
572 */
573 currCh->pwr_delta_t2[3][1] =
574 (eeval >> 4) & dbm_delta_mask;
575 currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask;
576
577 /* 6 words if numPdGains == 2 */
578 }
579
580 if (currCh->numPdGains > 3) {
581 /*
582 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
583 * and Vpd values for pdgain_3
584 */
585 currCh->pwr_I[3] = (eeval >> 14) & 0x3;
586
587 EEREAD(idx++);
588 /* upper 3 bits */
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;
594
595 EEREAD(idx++);
596 /* upper 4 bits */
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;
602
603 EEREAD(idx++);
604 /* upper 2 bits */
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;
610
611 EEREAD(idx++);
612 /* upper 2 bits */
613 currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4;
614
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;
619
620 EEREAD(idx++);
621 /* upper 2 bits */
622 currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2;
623 currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask;
624
625 /* 9 words if numPdGains == 3 */
626 }
627 }
628 return AH_TRUE;
629 #undef EEREAD
630 }
631
632 static void
ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 * pRaw,EEPROM_DATA_STRUCT_2413 * pCal)633 ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal)
634 {
635 uint16_t i, j, kk, channelValue;
636 uint16_t xpd_mask;
637 uint16_t numPdGainsUsed;
638
639 pRaw->numChannels = pCal->numChannels;
640
641 xpd_mask = pRaw->xpd_mask;
642 numPdGainsUsed = 0;
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++;
647
648 for (i = 0; i < pCal->numChannels; i++) {
649 channelValue = pCal->pChannels[i];
650
651 pRaw->pChannels[i] = channelValue;
652
653 pRaw->pDataPerChannel[i].channelValue = channelValue;
654 pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed;
655
656 kk = 0;
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;
661 kk++;
662 if (kk == 1) {
663 /*
664 * lowest pd_gain corresponds
665 * to highest power and thus,
666 * has one more point
667 */
668 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN;
669 }
670 } else {
671 pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0;
672 }
673 }
674 }
675 }
676
677 static HAL_BOOL
ar2413EepromToRawDataset(struct ath_hal * ah,EEPROM_DATA_STRUCT_2413 * pCal,RAW_DATA_STRUCT_2413 * pRaw)678 ar2413EepromToRawDataset(struct ath_hal *ah,
679 EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw)
680 {
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];
686 uint16_t xpd_mask;
687 uint32_t numPdGainsUsed;
688
689 HALASSERT(pRaw->xpd_mask == pCal->xpd_mask);
690
691 xgain_list[0] = 0xDEAD;
692 xgain_list[1] = 0xDEAD;
693 xgain_list[2] = 0xDEAD;
694 xgain_list[3] = 0xDEAD;
695
696 numPdGainsUsed = 0;
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;
701 }
702
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;
707
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 */
711 ss = xgain_list[jj];
712 pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]);
713 HALASSERT(pRawXPD->numVpd >= 1);
714
715 pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]);
716 pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj];
717
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]);
721 }
722 /* loop over Vpds */
723 }
724 /* loop over pd_gains */
725 }
726 /* loop over channels */
727 return AH_TRUE;
728 }
729
730 static HAL_BOOL
readEepromRawPowerCalInfo2413(struct ath_hal * ah,HAL_EEPROM * ee)731 readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee)
732 {
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;
738 uint32_t off;
739 HAL_BOOL ret = AH_FALSE;
740
741 HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0);
742 HALASSERT(ee->ee_eepMap == 2);
743
744 pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413));
745 if (pCal == AH_NULL)
746 goto exit;
747
748 off = ee->ee_eepMap2PowerCalStart;
749 if (ee->ee_Amode) {
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)) {
754 goto exit;
755 }
756 pRaw = &ee->ee_rawDataset2413[headerInfo11A];
757 pRaw->xpd_mask = ee->ee_xgain[headerInfo11A];
758 ar2413SetupRawDataset(pRaw, pCal);
759 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
760 goto exit;
761 }
762 /* setup offsets for mode_11a next */
763 numEEPROMWordsPerChannel = wordsForPdgains[
764 pCal->pDataPerChannel[0].numPdGains - 1];
765 off += pCal->numChannels * numEEPROMWordsPerChannel + 5;
766 }
767 if (ee->ee_Bmode) {
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)) {
772 goto exit;
773 }
774 pRaw = &ee->ee_rawDataset2413[headerInfo11B];
775 pRaw->xpd_mask = ee->ee_xgain[headerInfo11B];
776 ar2413SetupRawDataset(pRaw, pCal);
777 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
778 goto exit;
779 }
780 /* setup offsets for mode_11g next */
781 numEEPROMWordsPerChannel = wordsForPdgains[
782 pCal->pDataPerChannel[0].numPdGains - 1];
783 off += pCal->numChannels * numEEPROMWordsPerChannel + 2;
784 }
785 if (ee->ee_Gmode) {
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)) {
790 goto exit;
791 }
792 pRaw = &ee->ee_rawDataset2413[headerInfo11G];
793 pRaw->xpd_mask = ee->ee_xgain[headerInfo11G];
794 ar2413SetupRawDataset(pRaw, pCal);
795 if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
796 goto exit;
797 }
798 }
799 ret = AH_TRUE;
800 exit:
801 if (pCal != AH_NULL)
802 ath_hal_free(pCal);
803 return ret;
804 }
805
806 /*
807 * Now copy EEPROM Raw Power Calibration per frequency contents
808 * into the allocated space
809 */
810 static HAL_BOOL
readEepromRawPowerCalInfo(struct ath_hal * ah,HAL_EEPROM * ee)811 readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
812 {
813 #define EEREAD(_off) do { \
814 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
815 return AH_FALSE; \
816 } while (0)
817 uint16_t eeval, nchan;
818 uint32_t off;
819 int i, j, mode;
820
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);
825
826 /*
827 * Group 2: read raw power data for all frequency piers
828 *
829 * NOTE: Group 2 contains the raw power calibration
830 * information for each of the channels that
831 * we recorded above.
832 */
833 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
834 uint16_t *pChannels = AH_NULL;
835 DATA_PER_CHANNEL *pChannelData = AH_NULL;
836
837 off = ee->ee_version >= AR_EEPROM_VER3_3 ?
838 GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
839 switch (mode) {
840 case headerInfo11A:
841 off += GROUP2_OFFSET;
842 nchan = ee->ee_numChannels11a;
843 pChannelData = ee->ee_dataPerChannel11a;
844 pChannels = ee->ee_channels11a;
845 break;
846 case headerInfo11B:
847 if (!ee->ee_Bmode)
848 continue;
849 off += GROUP3_OFFSET;
850 nchan = ee->ee_numChannels2_4;
851 pChannelData = ee->ee_dataPerChannel11b;
852 pChannels = ee->ee_channels11b;
853 break;
854 case headerInfo11G:
855 if (!ee->ee_Gmode)
856 continue;
857 off += GROUP4_OFFSET;
858 nchan = ee->ee_numChannels2_4;
859 pChannelData = ee->ee_dataPerChannel11g;
860 pChannels = ee->ee_channels11g;
861 break;
862 default:
863 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
864 __func__, mode);
865 return AH_FALSE;
866 }
867 for (i = 0; i < nchan; i++) {
868 pChannelData->channelValue = pChannels[i];
869
870 EEREAD(off++);
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);
874
875 EEREAD(off++);
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);
880
881 EEREAD(off++);
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);
885
886 EEREAD(off++);
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);
890
891 EEREAD(off++);
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);
895
896 getPcdacInterceptsFromPcdacMinMax(ee,
897 pChannelData->pcdacMin, pChannelData->pcdacMax,
898 pChannelData->PcdacValues) ;
899
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. */
904 }
905 pChannelData++;
906 }
907 }
908 return AH_TRUE;
909 #undef EEREAD
910 }
911
912 /*
913 * Copy EEPROM Target Power Calbration per rate contents
914 * into the allocated space
915 */
916 static HAL_BOOL
readEepromTargetPowerCalInfo(struct ath_hal * ah,HAL_EEPROM * ee)917 readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
918 {
919 #define EEREAD(_off) do { \
920 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
921 return AH_FALSE; \
922 } while (0)
923 uint16_t eeval, enable24;
924 uint32_t off;
925 int i, mode, nchan;
926
927 enable24 = ee->ee_Bmode || ee->ee_Gmode;
928 for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
929 TRGT_POWER_INFO *pPowerInfo;
930 uint16_t *pNumTrgtChannels;
931
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;
936 switch (mode) {
937 case headerInfo11A:
938 off += GROUP5_OFFSET;
939 nchan = NUM_TEST_FREQUENCIES;
940 pPowerInfo = ee->ee_trgtPwr_11a;
941 pNumTrgtChannels = &ee->ee_numTargetPwr_11a;
942 break;
943 case headerInfo11B:
944 if (!enable24)
945 continue;
946 off += GROUP6_OFFSET;
947 nchan = 2;
948 pPowerInfo = ee->ee_trgtPwr_11b;
949 pNumTrgtChannels = &ee->ee_numTargetPwr_11b;
950 break;
951 case headerInfo11G:
952 if (!enable24)
953 continue;
954 off += GROUP7_OFFSET;
955 nchan = 3;
956 pPowerInfo = ee->ee_trgtPwr_11g;
957 pNumTrgtChannels = &ee->ee_numTargetPwr_11g;
958 break;
959 default:
960 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
961 __func__, mode);
962 return AH_FALSE;
963 }
964 *pNumTrgtChannels = 0;
965 for (i = 0; i < nchan; i++) {
966 EEREAD(off++);
967 if (ee->ee_version >= AR_EEPROM_VER3_3) {
968 pPowerInfo->testChannel = (eeval >> 8) & 0xff;
969 } else {
970 pPowerInfo->testChannel = (eeval >> 9) & 0x7f;
971 }
972
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);
977 } else {
978 pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel);
979 }
980
981 if (ee->ee_version >= AR_EEPROM_VER3_3) {
982 pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK;
983 pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK;
984 } else {
985 pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK;
986 pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK;
987 }
988
989 EEREAD(off++);
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;
994 } else {
995 pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7;
996 pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK;
997 pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK;
998 }
999 (*pNumTrgtChannels)++;
1000 }
1001 pPowerInfo++;
1002 }
1003 }
1004 return AH_TRUE;
1005 #undef EEREAD
1006 }
1007
1008 /*
1009 * Now copy EEPROM Coformance Testing Limits contents
1010 * into the allocated space
1011 */
1012 static HAL_BOOL
readEepromCTLInfo(struct ath_hal * ah,HAL_EEPROM * ee)1013 readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1014 {
1015 #define EEREAD(_off) do { \
1016 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1017 return AH_FALSE; \
1018 } while (0)
1019 RD_EDGES_POWER *rep;
1020 uint16_t eeval;
1021 uint32_t off;
1022 int i, j;
1023
1024 rep = ee->ee_rdEdgesPower;
1025
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);
1035 rep += NUM_EDGES;
1036 continue;
1037 }
1038 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1039 for (j = 0; j < NUM_EDGES; j += 2) {
1040 EEREAD(off++);
1041 rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3;
1042 rep[j+1].rdEdge = eeval & FREQ_MASK_3_3;
1043 }
1044 for (j = 0; j < NUM_EDGES; j += 2) {
1045 EEREAD(off++);
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;
1051 }
1052 } else {
1053 EEREAD(off++);
1054 rep[0].rdEdge = (eeval >> 9) & FREQ_MASK;
1055 rep[1].rdEdge = (eeval >> 2) & FREQ_MASK;
1056 rep[2].rdEdge = (eeval << 5) & FREQ_MASK;
1057
1058 EEREAD(off++);
1059 rep[2].rdEdge |= (eeval >> 11) & 0x1f;
1060 rep[3].rdEdge = (eeval >> 4) & FREQ_MASK;
1061 rep[4].rdEdge = (eeval << 3) & FREQ_MASK;
1062
1063 EEREAD(off++);
1064 rep[4].rdEdge |= (eeval >> 13) & 0x7;
1065 rep[5].rdEdge = (eeval >> 6) & FREQ_MASK;
1066 rep[6].rdEdge = (eeval << 1) & FREQ_MASK;
1067
1068 EEREAD(off++);
1069 rep[6].rdEdge |= (eeval >> 15) & 0x1;
1070 rep[7].rdEdge = (eeval >> 8) & FREQ_MASK;
1071
1072 rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK;
1073 rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK;
1074
1075 EEREAD(off++);
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;
1079
1080 EEREAD(off++);
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;
1084
1085 EEREAD(off++);
1086 rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3;
1087 rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK;
1088 }
1089
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);
1095 } else {
1096 rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge);
1097 }
1098 }
1099 }
1100 rep += NUM_EDGES;
1101 }
1102 return AH_TRUE;
1103 #undef EEREAD
1104 }
1105
1106 /*
1107 * Read the individual header fields for a Rev 3 EEPROM
1108 */
1109 static HAL_BOOL
readHeaderInfo(struct ath_hal * ah,HAL_EEPROM * ee)1110 readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1111 {
1112 #define EEREAD(_off) do { \
1113 if (!ath_hal_eepromRead(ah, _off, &eeval)) \
1114 return AH_FALSE; \
1115 } while (0)
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 */
1123 };
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 */
1131 };
1132
1133 static const uint32_t regCapOffsetPre4_0 = 0x00CF;
1134 static const uint32_t regCapOffsetPost4_0 = 0x00CA;
1135
1136 const uint32_t *header;
1137 uint32_t off;
1138 uint16_t eeval;
1139 int i;
1140
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;
1144
1145 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1146 header = headerOffset3_3;
1147 ee->ee_numCtls = NUM_CTLS_3_3;
1148 } else {
1149 header = headerOffset3_0;
1150 ee->ee_numCtls = NUM_CTLS;
1151 }
1152 HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX);
1153
1154 EEREAD(header[0]);
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;
1161 else
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);
1166
1167 off = header[1];
1168 EEREAD(off++);
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) {
1172 EEREAD(off++);
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;
1177
1178 EEREAD(off++);
1179 ee->ee_targetPowersStart = eeval & 0xfff;
1180 ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1;
1181
1182 if (ee->ee_version >= AR_EEPROM_VER5_0) {
1183 off += 2;
1184 EEREAD(off);
1185 ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff;
1186 /* Properly cal'ed 5.0 devices should be non-zero */
1187 }
1188 }
1189
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];
1194
1195 EEREAD(off++);
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;
1199
1200 EEREAD(off++);
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;
1204
1205 EEREAD(off++);
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;
1209
1210 EEREAD(off++);
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;
1215
1216 EEREAD(off++);
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;
1220
1221 EEREAD(off++);
1222 ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff);
1223 switch (i) {
1224 case headerInfo11A:
1225 ee->ee_ob4 = (eeval >> 5) & 0x07;
1226 ee->ee_db4 = (eeval >> 2) & 0x07;
1227 ee->ee_ob3 = (eeval << 1) & 0x07;
1228 break;
1229 case headerInfo11B:
1230 ee->ee_obFor24 = (eeval >> 4) & 0x07;
1231 ee->ee_dbFor24 = eeval & 0x07;
1232 break;
1233 case headerInfo11G:
1234 ee->ee_obFor24g = (eeval >> 4) & 0x07;
1235 ee->ee_dbFor24g = eeval & 0x07;
1236 break;
1237 }
1238
1239 if (i == headerInfo11A) {
1240 EEREAD(off++);
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;
1247 }
1248
1249 EEREAD(off++);
1250 ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff;
1251 ee->ee_thresh62[i] = eeval & 0xff;
1252
1253 EEREAD(off++);
1254 ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff;
1255 ee->ee_txFrameToXPAOn[i] = eeval & 0xff;
1256
1257 EEREAD(off++);
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);
1263 }
1264
1265 EEREAD(off++);
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) {
1270 switch (i) {
1271 case headerInfo11A:
1272 ee->ee_fixedBias5 = (eeval >> 13) & 0x1;
1273 break;
1274 case headerInfo11G:
1275 ee->ee_fixedBias2 = (eeval >> 13) & 0x1;
1276 break;
1277 }
1278 }
1279
1280 if (ee->ee_version >= AR_EEPROM_VER3_3) {
1281 EEREAD(off++);
1282 ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F;
1283 switch (i) {
1284 case headerInfo11B:
1285 ee->ee_ob2GHz[0] = eeval & 0x7;
1286 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1287 break;
1288 case headerInfo11G:
1289 ee->ee_ob2GHz[1] = eeval & 0x7;
1290 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1291 break;
1292 case headerInfo11A:
1293 ee->ee_xrTargetPower5 = eeval & 0x3f;
1294 break;
1295 }
1296 }
1297 if (ee->ee_version >= AR_EEPROM_VER3_4) {
1298 ee->ee_gainI[i] = (eeval >> 13) & 0x07;
1299
1300 EEREAD(off++);
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;
1307 }
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;
1312 }
1313 } else {
1314 ee->ee_gainI[i] = 10;
1315 ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT;
1316 }
1317 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1318 switch (i) {
1319 case headerInfo11B:
1320 EEREAD(off++);
1321 ee->ee_calPier11b[0] =
1322 fbin2freq_2p4(ee, eeval&0xff);
1323 ee->ee_calPier11b[1] =
1324 fbin2freq_2p4(ee, (eeval >> 8)&0xff);
1325 EEREAD(off++);
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;
1331 break;
1332 case headerInfo11G:
1333 EEREAD(off++);
1334 ee->ee_calPier11g[0] =
1335 fbin2freq_2p4(ee, eeval & 0xff);
1336 ee->ee_calPier11g[1] =
1337 fbin2freq_2p4(ee, (eeval >> 8) & 0xff);
1338
1339 EEREAD(off++);
1340 ee->ee_turbo2WMaxPower2 = eeval & 0x7F;
1341 ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f;
1342
1343 EEREAD(off++);
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;
1349
1350 EEREAD(off++);
1351 ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F;
1352 ee->ee_iqCalQ[1] = eeval & 0x1F;
1353
1354 if (ee->ee_version >= AR_EEPROM_VER4_2) {
1355 EEREAD(off++);
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;
1363 EEREAD(off++);
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;
1370 EEREAD(off++);
1371 ee->ee_adcDesiredSizeTurbo[1] |=
1372 (eeval & 0x7) << 5;
1373 ee->ee_pgaDesiredSizeTurbo[1] =
1374 (eeval >> 3) & 0xFF;
1375 }
1376 }
1377 break;
1378 case headerInfo11A:
1379 if (ee->ee_version >= AR_EEPROM_VER4_1) {
1380 EEREAD(off++);
1381 ee->ee_rxtxMargin[headerInfo11A] =
1382 eeval & 0x3f;
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;
1388 EEREAD(off++);
1389 ee->ee_txrxAttenTurbo[0] |=
1390 (eeval & 0x7) << 3;
1391 ee->ee_rxtxMarginTurbo[0] =
1392 (eeval >> 3) & 0x3F;
1393 ee->ee_adcDesiredSizeTurbo[0] =
1394 (eeval >> 9) & 0x7F;
1395 EEREAD(off++);
1396 ee->ee_adcDesiredSizeTurbo[0] |=
1397 (eeval & 0x1) << 7;
1398 ee->ee_pgaDesiredSizeTurbo[0] =
1399 (eeval >> 1) & 0xFF;
1400 }
1401 }
1402 break;
1403 }
1404 }
1405 }
1406 if (ee->ee_version < AR_EEPROM_VER3_3) {
1407 /* Version 3.1+ specific parameters */
1408 EEREAD(0xec);
1409 ee->ee_ob2GHz[0] = eeval & 0x7;
1410 ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1411
1412 EEREAD(0xed);
1413 ee->ee_ob2GHz[1] = eeval & 0x7;
1414 ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1415 }
1416
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;
1422
1423 /*
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.
1427 */
1428 off = header[5];
1429 for (i = 0; i < ee->ee_numCtls; i += 2) {
1430 EEREAD(off++);
1431 ee->ee_ctl[i] = (eeval >> 8) & 0xff;
1432 ee->ee_ctl[i+1] = eeval & 0xff;
1433 }
1434
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;
1441 } else {
1442 /* Read spur mitigation data */
1443 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
1444 EEREAD(off);
1445 ee->ee_spurChans[i][0] = eeval;
1446 EEREAD(off+AR_EEPROM_MODAL_SPURS);
1447 ee->ee_spurChans[i][1] = eeval;
1448 off++;
1449 }
1450 }
1451
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;
1457 }
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 */
1463 }
1464
1465 /* Check for regulatory capabilities */
1466 if (ee->ee_version >= AR_EEPROM_VER4_0) {
1467 EEREAD(regCapOffsetPost4_0);
1468 } else {
1469 EEREAD(regCapOffsetPre4_0);
1470 }
1471
1472 ee->ee_regCap = eeval;
1473
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;
1478 } else {
1479 ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0;
1480 }
1481 }
1482
1483 if (ee->ee_version >= AR_EEPROM_VER5_1)
1484 EEREAD(AR_EEPROM_CAPABILITIES_OFFSET);
1485 else
1486 eeval = 0;
1487 ee->ee_opCap = eeval;
1488
1489 EEREAD(AR_EEPROM_REG_DOMAIN);
1490 ee->ee_regdomain = eeval;
1491
1492 return AH_TRUE;
1493 #undef EEREAD
1494 }
1495
1496 /*
1497 * Now verify and copy EEPROM contents into the allocated space
1498 */
1499 static HAL_BOOL
legacyEepromReadContents(struct ath_hal * ah,HAL_EEPROM * ee)1500 legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee)
1501 {
1502 /* Read the header information here */
1503 if (!readHeaderInfo(ah, ee))
1504 return AH_FALSE;
1505 #if 0
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__);
1511 return AH_FALSE;
1512 }
1513 #endif
1514 /*
1515 * Group 1: frequency pier locations readback
1516 * check that the structure has been populated
1517 * with enough space to hold the channels
1518 *
1519 * NOTE: Group 1 contains the 5 GHz channel numbers
1520 * that have dBm->pcdac calibrated information.
1521 */
1522 if (!readEepromFreqPierInfo(ah, ee))
1523 return AH_FALSE;
1524
1525 /*
1526 * Group 2: readback data for all frequency piers
1527 *
1528 * NOTE: Group 2 contains the raw power calibration
1529 * information for each of the channels that we
1530 * recorded above.
1531 */
1532 if (!readEepromRawPowerCalInfo(ah, ee))
1533 return AH_FALSE;
1534
1535 /*
1536 * Group 5: target power values per rate
1537 *
1538 * NOTE: Group 5 contains the recorded maximum power
1539 * in dB that can be attained for the given rate.
1540 */
1541 /* Read the power per rate info for test channels */
1542 if (!readEepromTargetPowerCalInfo(ah, ee))
1543 return AH_FALSE;
1544
1545 /*
1546 * Group 8: Conformance Test Limits information
1547 *
1548 * NOTE: Group 8 contains the values to limit the
1549 * maximum transmit power value based on any
1550 * band edge violations.
1551 */
1552 /* Read the RD edge power limits */
1553 return readEepromCTLInfo(ah, ee);
1554 }
1555
1556 static HAL_STATUS
legacyEepromGet(struct ath_hal * ah,int param,void * val)1557 legacyEepromGet(struct ath_hal *ah, int param, void *val)
1558 {
1559 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1560 uint8_t *macaddr;
1561 uint16_t eeval;
1562 uint32_t sum;
1563 int i;
1564
1565 switch (param) {
1566 case AR_EEP_OPCAP:
1567 *(uint16_t *) val = ee->ee_opCap;
1568 return HAL_OK;
1569 case AR_EEP_REGDMN_0:
1570 *(uint16_t *) val = ee->ee_regdomain;
1571 return HAL_OK;
1572 case AR_EEP_RFSILENT:
1573 if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval))
1574 return HAL_EEREAD;
1575 *(uint16_t *) val = eeval;
1576 return HAL_OK;
1577 case AR_EEP_MACADDR:
1578 sum = 0;
1579 macaddr = val;
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",
1584 __func__, i);
1585 return HAL_EEREAD;
1586 }
1587 sum += eeval;
1588 macaddr[2*i] = eeval >> 8;
1589 macaddr[2*i + 1] = eeval & 0xff;
1590 }
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;
1596 }
1597 return HAL_OK;
1598 case AR_EEP_RFKILL:
1599 HALASSERT(val == AH_NULL);
1600 return ee->ee_rfKill ? HAL_OK : HAL_EIO;
1601 case AR_EEP_AMODE:
1602 HALASSERT(val == AH_NULL);
1603 return ee->ee_Amode ? HAL_OK : HAL_EIO;
1604 case AR_EEP_BMODE:
1605 HALASSERT(val == AH_NULL);
1606 return ee->ee_Bmode ? HAL_OK : HAL_EIO;
1607 case AR_EEP_GMODE:
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) ?
1620 HAL_OK : HAL_EIO;
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 ?
1627 HAL_OK : HAL_EIO;
1628 case AR_EEP_FASTFRAME:
1629 HALASSERT(val == AH_NULL);
1630 return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ?
1631 HAL_OK : HAL_EIO;
1632 case AR_EEP_AES:
1633 HALASSERT(val == AH_NULL);
1634 return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ?
1635 HAL_OK : HAL_EIO;
1636 case AR_EEP_BURST:
1637 HALASSERT(val == AH_NULL);
1638 return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ?
1639 HAL_OK : HAL_EIO;
1640 case AR_EEP_MAXQCU:
1641 if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) {
1642 *(uint16_t *) val =
1643 MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU);
1644 return HAL_OK;
1645 } else
1646 return HAL_EIO;
1647 case AR_EEP_KCENTRIES:
1648 if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) {
1649 *(uint16_t *) val =
1650 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES);
1651 return HAL_OK;
1652 } else
1653 return HAL_EIO;
1654 case AR_EEP_ANTGAINMAX_5:
1655 *(int8_t *) val = ee->ee_antennaGainMax[0];
1656 return HAL_OK;
1657 case AR_EEP_ANTGAINMAX_2:
1658 *(int8_t *) val = ee->ee_antennaGainMax[1];
1659 return HAL_OK;
1660 case AR_EEP_WRITEPROTECT:
1661 HALASSERT(val == AH_NULL);
1662 return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ?
1663 HAL_OK : HAL_EIO;
1664 }
1665 return HAL_EINVAL;
1666 }
1667
1668 static HAL_STATUS
legacyEepromSet(struct ath_hal * ah,int param,int v)1669 legacyEepromSet(struct ath_hal *ah, int param, int v)
1670 {
1671 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1672
1673 switch (param) {
1674 case AR_EEP_AMODE:
1675 ee->ee_Amode = v;
1676 return HAL_OK;
1677 case AR_EEP_BMODE:
1678 ee->ee_Bmode = v;
1679 return HAL_OK;
1680 case AR_EEP_GMODE:
1681 ee->ee_Gmode = v;
1682 return HAL_OK;
1683 case AR_EEP_TURBO5DISABLE:
1684 ee->ee_turbo5Disable = v;
1685 return HAL_OK;
1686 case AR_EEP_TURBO2DISABLE:
1687 ee->ee_turbo2Disable = v;
1688 return HAL_OK;
1689 case AR_EEP_COMPRESS:
1690 if (v)
1691 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS;
1692 else
1693 ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS;
1694 return HAL_OK;
1695 case AR_EEP_FASTFRAME:
1696 if (v)
1697 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1698 else
1699 ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1700 return HAL_OK;
1701 case AR_EEP_AES:
1702 if (v)
1703 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS;
1704 else
1705 ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS;
1706 return HAL_OK;
1707 case AR_EEP_BURST:
1708 if (v)
1709 ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS;
1710 else
1711 ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS;
1712 return HAL_OK;
1713 }
1714 return HAL_EINVAL;
1715 }
1716
1717 static HAL_BOOL
legacyEepromDiag(struct ath_hal * ah,int request,const void * args,uint32_t argsize,void ** result,uint32_t * resultsize)1718 legacyEepromDiag(struct ath_hal *ah, int request,
1719 const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
1720 {
1721 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1722 const EEPROM_POWER_EXPN_5112 *pe;
1723
1724 switch (request) {
1725 case HAL_DIAG_EEPROM:
1726 *result = ee;
1727 *resultsize = sizeof(*ee);
1728 return AH_TRUE;
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,
1737 sizeof(uint32_t)) +
1738 sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels;
1739 return AH_TRUE;
1740 }
1741 return AH_FALSE;
1742 }
1743
1744 static uint16_t
legacyEepromGetSpurChan(struct ath_hal * ah,int ix,HAL_BOOL is2GHz)1745 legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
1746 {
1747 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1748
1749 HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS);
1750 return ee->ee_spurChans[ix][is2GHz];
1751 }
1752
1753 /*
1754 * Reclaim any EEPROM-related storage.
1755 */
1756 static void
legacyEepromDetach(struct ath_hal * ah)1757 legacyEepromDetach(struct ath_hal *ah)
1758 {
1759 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1760
1761 if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
1762 freeEepromRawPowerCalInfo5112(ah, ee);
1763 ath_hal_free(ee);
1764 AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
1765 }
1766
1767 /*
1768 * These are not valid 2.4 channels, either we change 'em
1769 * or we need to change the coding to accept them.
1770 */
1771 static const uint16_t channels11b[] = { 2412, 2447, 2484 };
1772 static const uint16_t channels11g[] = { 2312, 2412, 2484 };
1773
1774 HAL_STATUS
ath_hal_legacyEepromAttach(struct ath_hal * ah)1775 ath_hal_legacyEepromAttach(struct ath_hal *ah)
1776 {
1777 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1778 uint32_t sum, eepMax;
1779 uint16_t eeversion, eeprotect, eeval;
1780 u_int i;
1781
1782 HALASSERT(ee == AH_NULL);
1783
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__);
1787 return HAL_EEREAD;
1788 }
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;
1793 }
1794
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__);
1798 return HAL_EEREAD;
1799 }
1800 HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect);
1801 /* XXX check proper access before continuing */
1802
1803 /*
1804 * Read the Atheros EEPROM entries and calculate the checksum.
1805 */
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__);
1809 return HAL_EEREAD;
1810 }
1811 if (eeval != 0) {
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__);
1817 return HAL_EEREAD;
1818 }
1819 eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE;
1820 } else
1821 eepMax = AR_EEPROM_ATHEROS_MAX;
1822 sum = 0;
1823 for (i = 0; i < eepMax; i++) {
1824 if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) {
1825 return HAL_EEREAD;
1826 }
1827 sum ^= eeval;
1828 }
1829 if (sum != 0xffff) {
1830 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
1831 __func__, sum);
1832 return HAL_EEBADSUM;
1833 }
1834
1835 ee = ath_hal_malloc(sizeof(HAL_EEPROM));
1836 if (ee == AH_NULL) {
1837 /* XXX message */
1838 return HAL_ENOMEM;
1839 }
1840
1841 ee->ee_protect = eeprotect;
1842 ee->ee_version = eeversion;
1843
1844 ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS;
1845 ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS;
1846
1847 for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++)
1848 ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES;
1849
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];
1856 else
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;
1860 }
1861
1862 if (!legacyEepromReadContents(ah, ee)) {
1863 /* XXX message */
1864 ath_hal_free(ee);
1865 return HAL_EEREAD; /* XXX */
1866 }
1867
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;
1875 return HAL_OK;
1876 }
1877