Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_hal/ah_eeprom_v3.c
39537 views
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1878