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