1*6e778a7eSPedro F. Giffuni /*-
2*6e778a7eSPedro F. Giffuni * SPDX-License-Identifier: ISC
3*6e778a7eSPedro F. Giffuni *
414779705SSam Leffler * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
514779705SSam Leffler * Copyright (c) 2002-2008 Atheros Communications, Inc.
614779705SSam Leffler *
714779705SSam Leffler * Permission to use, copy, modify, and/or distribute this software for any
814779705SSam Leffler * purpose with or without fee is hereby granted, provided that the above
914779705SSam Leffler * copyright notice and this permission notice appear in all copies.
1014779705SSam Leffler *
1114779705SSam Leffler * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1214779705SSam Leffler * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1314779705SSam Leffler * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1414779705SSam Leffler * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1514779705SSam Leffler * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1614779705SSam Leffler * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1714779705SSam Leffler * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1814779705SSam Leffler */
1914779705SSam Leffler #include "opt_ah.h"
2014779705SSam Leffler
2114779705SSam Leffler #include "ah.h"
2214779705SSam Leffler #include "ah_internal.h"
2314779705SSam Leffler #include "ah_eeprom_v3.h"
2414779705SSam Leffler
2514779705SSam Leffler static void
getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM * ee,uint16_t pcdacMin,uint16_t pcdacMax,uint16_t * vp)2614779705SSam Leffler getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
2714779705SSam Leffler uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
2814779705SSam Leffler {
29128ae978SSam Leffler static const uint16_t intercepts3[] =
3014779705SSam Leffler { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
31128ae978SSam Leffler static const uint16_t intercepts3_2[] =
3214779705SSam Leffler { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
3314779705SSam Leffler const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
3414779705SSam Leffler intercepts3 : intercepts3_2;
3514779705SSam Leffler int i;
3614779705SSam Leffler
3714779705SSam Leffler /* loop for the percentages in steps or 5 */
3814779705SSam Leffler for (i = 0; i < NUM_INTERCEPTS; i++ )
3914779705SSam Leffler *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;
4014779705SSam Leffler }
4114779705SSam Leffler
4214779705SSam Leffler /*
4314779705SSam Leffler * Get channel value from binary representation held in eeprom
4414779705SSam Leffler */
4514779705SSam Leffler static uint16_t
fbin2freq(HAL_EEPROM * ee,uint16_t fbin)4614779705SSam Leffler fbin2freq(HAL_EEPROM *ee, uint16_t fbin)
4714779705SSam Leffler {
4814779705SSam Leffler if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
4914779705SSam Leffler return fbin;
5014779705SSam Leffler return ee->ee_version <= AR_EEPROM_VER3_2 ?
5114779705SSam Leffler (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) :
5214779705SSam Leffler 4800 + 5*fbin;
5314779705SSam Leffler }
5414779705SSam Leffler
5514779705SSam Leffler static uint16_t
fbin2freq_2p4(HAL_EEPROM * ee,uint16_t fbin)5614779705SSam Leffler fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin)
5714779705SSam Leffler {
5814779705SSam Leffler if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */
5914779705SSam Leffler return fbin;
6014779705SSam Leffler return ee->ee_version <= AR_EEPROM_VER3_2 ?
6114779705SSam Leffler 2400 + fbin :
6214779705SSam Leffler 2300 + fbin;
6314779705SSam Leffler }
6414779705SSam Leffler
6514779705SSam Leffler /*
6614779705SSam Leffler * Now copy EEPROM frequency pier contents into the allocated space
6714779705SSam Leffler */
6814779705SSam Leffler static HAL_BOOL
readEepromFreqPierInfo(struct ath_hal * ah,HAL_EEPROM * ee)6914779705SSam Leffler readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee)
7014779705SSam Leffler {
7114779705SSam Leffler #define EEREAD(_off) do { \
7214779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
7314779705SSam Leffler return AH_FALSE; \
7414779705SSam Leffler } while (0)
7514779705SSam Leffler uint16_t eeval, off;
7614779705SSam Leffler int i;
7714779705SSam Leffler
7814779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0 &&
7914779705SSam Leffler ee->ee_eepMap && !ee->ee_Amode) {
8014779705SSam Leffler /*
8114779705SSam Leffler * V4.0 EEPROMs with map type 1 have frequency pier
8214779705SSam Leffler * data only when 11a mode is supported.
8314779705SSam Leffler */
8414779705SSam Leffler return AH_TRUE;
8514779705SSam Leffler }
8614779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
8714779705SSam Leffler off = GROUPS_OFFSET3_3 + GROUP1_OFFSET;
8814779705SSam Leffler for (i = 0; i < ee->ee_numChannels11a; i += 2) {
8914779705SSam Leffler EEREAD(off++);
9014779705SSam Leffler ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3;
9114779705SSam Leffler ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3;
9214779705SSam Leffler }
9314779705SSam Leffler } else {
9414779705SSam Leffler off = GROUPS_OFFSET3_2 + GROUP1_OFFSET;
9514779705SSam Leffler
9614779705SSam Leffler EEREAD(off++);
9714779705SSam Leffler ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK;
9814779705SSam Leffler ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK;
9914779705SSam Leffler ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK;
10014779705SSam Leffler
10114779705SSam Leffler EEREAD(off++);
10214779705SSam Leffler ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f;
10314779705SSam Leffler ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK;
10414779705SSam Leffler ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK;
10514779705SSam Leffler
10614779705SSam Leffler EEREAD(off++);
10714779705SSam Leffler ee->ee_channels11a[4] |= (eeval >> 13) & 0x7;
10814779705SSam Leffler ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK;
10914779705SSam Leffler ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK;
11014779705SSam Leffler
11114779705SSam Leffler EEREAD(off++);
11214779705SSam Leffler ee->ee_channels11a[6] |= (eeval >> 15) & 0x1;
11314779705SSam Leffler ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK;
11414779705SSam Leffler ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK;
11514779705SSam Leffler ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK;
11614779705SSam Leffler
11714779705SSam Leffler EEREAD(off++);
11814779705SSam Leffler ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f;
11914779705SSam Leffler }
12014779705SSam Leffler
12114779705SSam Leffler for (i = 0; i < ee->ee_numChannels11a; i++)
12214779705SSam Leffler ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]);
12314779705SSam Leffler
12414779705SSam Leffler return AH_TRUE;
12514779705SSam Leffler #undef EEREAD
12614779705SSam Leffler }
12714779705SSam Leffler
12814779705SSam Leffler /*
12914779705SSam Leffler * Rev 4 Eeprom 5112 Power Extract Functions
13014779705SSam Leffler */
13114779705SSam Leffler
13214779705SSam Leffler /*
13314779705SSam Leffler * Allocate the power information based on the number of channels
13414779705SSam Leffler * recorded by the calibration. These values are then initialized.
13514779705SSam Leffler */
13614779705SSam Leffler static HAL_BOOL
eepromAllocExpnPower5112(struct ath_hal * ah,const EEPROM_POWER_5112 * pCalDataset,EEPROM_POWER_EXPN_5112 * pPowerExpn)13714779705SSam Leffler eepromAllocExpnPower5112(struct ath_hal *ah,
13814779705SSam Leffler const EEPROM_POWER_5112 *pCalDataset,
13914779705SSam Leffler EEPROM_POWER_EXPN_5112 *pPowerExpn)
14014779705SSam Leffler {
14114779705SSam Leffler uint16_t numChannels = pCalDataset->numChannels;
14214779705SSam Leffler const uint16_t *pChanList = pCalDataset->pChannels;
14314779705SSam Leffler void *data;
14414779705SSam Leffler int i, j;
14514779705SSam Leffler
14614779705SSam Leffler /* Allocate the channel and Power Data arrays together */
14714779705SSam Leffler data = ath_hal_malloc(
14814779705SSam Leffler roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) +
14914779705SSam Leffler sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels);
15014779705SSam Leffler if (data == AH_NULL) {
15114779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
15214779705SSam Leffler "%s unable to allocate raw data struct (gen3)\n", __func__);
15314779705SSam Leffler return AH_FALSE;
15414779705SSam Leffler }
15514779705SSam Leffler pPowerExpn->pChannels = data;
15614779705SSam Leffler pPowerExpn->pDataPerChannel = (void *)(((char *)data) +
15714779705SSam Leffler roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)));
15814779705SSam Leffler
15914779705SSam Leffler pPowerExpn->numChannels = numChannels;
16014779705SSam Leffler for (i = 0; i < numChannels; i++) {
16114779705SSam Leffler pPowerExpn->pChannels[i] =
16214779705SSam Leffler pPowerExpn->pDataPerChannel[i].channelValue =
16314779705SSam Leffler pChanList[i];
16414779705SSam Leffler for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) {
16514779705SSam Leffler pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j;
16614779705SSam Leffler pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0;
16714779705SSam Leffler }
16814779705SSam Leffler pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4;
16914779705SSam Leffler pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3;
17014779705SSam Leffler }
17114779705SSam Leffler return AH_TRUE;
17214779705SSam Leffler }
17314779705SSam Leffler
17414779705SSam Leffler /*
17514779705SSam Leffler * Expand the dataSet from the calibration information into the
17614779705SSam Leffler * final power structure for 5112
17714779705SSam Leffler */
17814779705SSam Leffler static HAL_BOOL
eepromExpandPower5112(struct ath_hal * ah,const EEPROM_POWER_5112 * pCalDataset,EEPROM_POWER_EXPN_5112 * pPowerExpn)17914779705SSam Leffler eepromExpandPower5112(struct ath_hal *ah,
18014779705SSam Leffler const EEPROM_POWER_5112 *pCalDataset,
18114779705SSam Leffler EEPROM_POWER_EXPN_5112 *pPowerExpn)
18214779705SSam Leffler {
18314779705SSam Leffler int ii, jj, kk;
18414779705SSam Leffler int16_t maxPower_t4;
18514779705SSam Leffler EXPN_DATA_PER_XPD_5112 *pExpnXPD;
18614779705SSam Leffler /* ptr to array of info held per channel */
18714779705SSam Leffler const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh;
18814779705SSam Leffler uint16_t xgainList[2], xpdMask;
18914779705SSam Leffler
19014779705SSam Leffler pPowerExpn->xpdMask = pCalDataset->xpdMask;
19114779705SSam Leffler
19214779705SSam Leffler xgainList[0] = 0xDEAD;
19314779705SSam Leffler xgainList[1] = 0xDEAD;
19414779705SSam Leffler
19514779705SSam Leffler kk = 0;
19614779705SSam Leffler xpdMask = pPowerExpn->xpdMask;
19714779705SSam Leffler for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
19814779705SSam Leffler if (((xpdMask >> jj) & 1) > 0) {
19914779705SSam Leffler if (kk > 1) {
20014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
20114779705SSam Leffler "%s: too many xpdGains in dataset: %u\n",
20214779705SSam Leffler __func__, kk);
20314779705SSam Leffler return AH_FALSE;
20414779705SSam Leffler }
20514779705SSam Leffler xgainList[kk++] = jj;
20614779705SSam Leffler }
20714779705SSam Leffler }
20814779705SSam Leffler
20914779705SSam Leffler pPowerExpn->numChannels = pCalDataset->numChannels;
21014779705SSam Leffler if (pPowerExpn->numChannels == 0) {
21114779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__);
21214779705SSam Leffler return AH_FALSE;
21314779705SSam Leffler }
21414779705SSam Leffler
21514779705SSam Leffler for (ii = 0; ii < pPowerExpn->numChannels; ii++) {
21614779705SSam Leffler pCalCh = &pCalDataset->pDataPerChannel[ii];
21714779705SSam Leffler pPowerExpn->pDataPerChannel[ii].channelValue =
21814779705SSam Leffler pCalCh->channelValue;
21914779705SSam Leffler pPowerExpn->pDataPerChannel[ii].maxPower_t4 =
22014779705SSam Leffler pCalCh->maxPower_t4;
22114779705SSam Leffler maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4;
22214779705SSam Leffler
22314779705SSam Leffler for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++)
22414779705SSam Leffler pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0;
22514779705SSam Leffler if (xgainList[1] == 0xDEAD) {
22614779705SSam Leffler jj = xgainList[0];
22714779705SSam Leffler pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
22814779705SSam Leffler pExpnXPD->numPcdacs = 4;
22914779705SSam Leffler pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0;
23014779705SSam Leffler pExpnXPD->pcdac[1] = (uint16_t)
23114779705SSam Leffler (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
23214779705SSam Leffler pExpnXPD->pcdac[2] = (uint16_t)
23314779705SSam Leffler (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
23414779705SSam Leffler pExpnXPD->pcdac[3] = (uint16_t)
23514779705SSam Leffler (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
23614779705SSam Leffler
23714779705SSam Leffler pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
23814779705SSam Leffler pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
23914779705SSam Leffler pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
24014779705SSam Leffler pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
24114779705SSam Leffler
24214779705SSam Leffler } else {
24314779705SSam Leffler pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0;
24414779705SSam Leffler pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20;
24514779705SSam Leffler pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35;
24614779705SSam Leffler pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63;
24714779705SSam Leffler
24814779705SSam Leffler jj = xgainList[0];
24914779705SSam Leffler pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
25014779705SSam Leffler pExpnXPD->numPcdacs = 4;
25114779705SSam Leffler pExpnXPD->pcdac[1] = (uint16_t)
25214779705SSam Leffler (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
25314779705SSam Leffler pExpnXPD->pcdac[2] = (uint16_t)
25414779705SSam Leffler (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
25514779705SSam Leffler pExpnXPD->pcdac[3] = (uint16_t)
25614779705SSam Leffler (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
25714779705SSam Leffler pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
25814779705SSam Leffler pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
25914779705SSam Leffler pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
26014779705SSam Leffler pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
26114779705SSam Leffler
26214779705SSam Leffler jj = xgainList[1];
26314779705SSam Leffler pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
26414779705SSam Leffler pExpnXPD->numPcdacs = 3;
26514779705SSam Leffler
26614779705SSam Leffler pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3;
26714779705SSam Leffler pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3;
26814779705SSam Leffler pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3;
26914779705SSam Leffler }
27014779705SSam Leffler }
27114779705SSam Leffler return AH_TRUE;
27214779705SSam Leffler }
27314779705SSam Leffler
27414779705SSam Leffler static HAL_BOOL
readEepromRawPowerCalInfo5112(struct ath_hal * ah,HAL_EEPROM * ee)27514779705SSam Leffler readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
27614779705SSam Leffler {
27714779705SSam Leffler #define EEREAD(_off) do { \
27814779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
27914779705SSam Leffler return AH_FALSE; \
28014779705SSam Leffler } while (0)
28114779705SSam Leffler const uint16_t dbmmask = 0xff;
28214779705SSam Leffler const uint16_t pcdac_delta_mask = 0x1f;
28314779705SSam Leffler const uint16_t pcdac_mask = 0x3f;
28414779705SSam Leffler const uint16_t freqmask = 0xff;
28514779705SSam Leffler
28614779705SSam Leffler int i, mode, numPiers;
28714779705SSam Leffler uint32_t off;
28814779705SSam Leffler uint16_t eeval;
28914779705SSam Leffler uint16_t freq[NUM_11A_EEPROM_CHANNELS];
29014779705SSam Leffler EEPROM_POWER_5112 eePower;
29114779705SSam Leffler
29214779705SSam Leffler HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0);
29314779705SSam Leffler off = GROUPS_OFFSET3_3;
29414779705SSam Leffler for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
29514779705SSam Leffler numPiers = 0;
29614779705SSam Leffler switch (mode) {
29714779705SSam Leffler case headerInfo11A:
29814779705SSam Leffler if (!ee->ee_Amode) /* no 11a calibration data */
29914779705SSam Leffler continue;
30014779705SSam Leffler while (numPiers < NUM_11A_EEPROM_CHANNELS) {
30114779705SSam Leffler EEREAD(off++);
30214779705SSam Leffler if ((eeval & freqmask) == 0)
30314779705SSam Leffler break;
30414779705SSam Leffler freq[numPiers++] = fbin2freq(ee,
30514779705SSam Leffler eeval & freqmask);
30614779705SSam Leffler
30714779705SSam Leffler if (((eeval >> 8) & freqmask) == 0)
30814779705SSam Leffler break;
30914779705SSam Leffler freq[numPiers++] = fbin2freq(ee,
31014779705SSam Leffler (eeval>>8) & freqmask);
31114779705SSam Leffler }
31214779705SSam Leffler break;
31314779705SSam Leffler case headerInfo11B:
31414779705SSam Leffler if (!ee->ee_Bmode) /* no 11b calibration data */
31514779705SSam Leffler continue;
31614779705SSam Leffler for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
31714779705SSam Leffler if (ee->ee_calPier11b[i] != CHANNEL_UNUSED)
31814779705SSam Leffler freq[numPiers++] = ee->ee_calPier11b[i];
31914779705SSam Leffler break;
32014779705SSam Leffler case headerInfo11G:
32114779705SSam Leffler if (!ee->ee_Gmode) /* no 11g calibration data */
32214779705SSam Leffler continue;
32314779705SSam Leffler for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
32414779705SSam Leffler if (ee->ee_calPier11g[i] != CHANNEL_UNUSED)
32514779705SSam Leffler freq[numPiers++] = ee->ee_calPier11g[i];
32614779705SSam Leffler break;
32714779705SSam Leffler default:
32814779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
32914779705SSam Leffler __func__, mode);
33014779705SSam Leffler return AH_FALSE;
33114779705SSam Leffler }
33214779705SSam Leffler
33314779705SSam Leffler OS_MEMZERO(&eePower, sizeof(eePower));
33414779705SSam Leffler eePower.numChannels = numPiers;
33514779705SSam Leffler
33614779705SSam Leffler for (i = 0; i < numPiers; i++) {
33714779705SSam Leffler eePower.pChannels[i] = freq[i];
33814779705SSam Leffler eePower.pDataPerChannel[i].channelValue = freq[i];
33914779705SSam Leffler
34014779705SSam Leffler EEREAD(off++);
34114779705SSam Leffler eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t)
34214779705SSam Leffler ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
34314779705SSam Leffler eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t)
34414779705SSam Leffler (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
34514779705SSam Leffler
34614779705SSam Leffler EEREAD(off++);
34714779705SSam Leffler eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t)
34814779705SSam Leffler ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
34914779705SSam Leffler eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t)
35014779705SSam Leffler (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
35114779705SSam Leffler
35214779705SSam Leffler EEREAD(off++);
35314779705SSam Leffler eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t)
35414779705SSam Leffler (eeval & pcdac_delta_mask);
35514779705SSam Leffler eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t)
35614779705SSam Leffler ((eeval >> 5) & pcdac_delta_mask);
35714779705SSam Leffler eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t)
35814779705SSam Leffler ((eeval >> 10) & pcdac_delta_mask);
35914779705SSam Leffler
36014779705SSam Leffler EEREAD(off++);
36114779705SSam Leffler eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t)
36214779705SSam Leffler ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
36314779705SSam Leffler eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t)
36414779705SSam Leffler (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
36514779705SSam Leffler
36614779705SSam Leffler EEREAD(off++);
36714779705SSam Leffler eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t)
36814779705SSam Leffler ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
36914779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_3) {
37014779705SSam Leffler eePower.pDataPerChannel[i].maxPower_t4 =
37114779705SSam Leffler eePower.pDataPerChannel[i].pwr4_xg0;
37214779705SSam Leffler eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t)
37314779705SSam Leffler ((eeval >> 8) & pcdac_mask);
37414779705SSam Leffler } else {
37514779705SSam Leffler eePower.pDataPerChannel[i].maxPower_t4 = (int16_t)
37614779705SSam Leffler (((eeval >> 8) & dbmmask) -
37714779705SSam Leffler ((eeval >> 15) & 0x1)*256);
37814779705SSam Leffler eePower.pDataPerChannel[i].pcd1_xg0 = 1;
37914779705SSam Leffler }
38014779705SSam Leffler }
38114779705SSam Leffler eePower.xpdMask = ee->ee_xgain[mode];
38214779705SSam Leffler
38314779705SSam Leffler if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
38414779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
38514779705SSam Leffler "%s: did not allocate power struct\n", __func__);
38614779705SSam Leffler return AH_FALSE;
38714779705SSam Leffler }
38814779705SSam Leffler if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
38914779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
39014779705SSam Leffler "%s: did not expand power struct\n", __func__);
39114779705SSam Leffler return AH_FALSE;
39214779705SSam Leffler }
39314779705SSam Leffler }
39414779705SSam Leffler return AH_TRUE;
39514779705SSam Leffler #undef EEREAD
39614779705SSam Leffler }
39714779705SSam Leffler
39814779705SSam Leffler static void
freeEepromRawPowerCalInfo5112(struct ath_hal * ah,HAL_EEPROM * ee)39914779705SSam Leffler freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
40014779705SSam Leffler {
40114779705SSam Leffler int mode;
40214779705SSam Leffler void *data;
40314779705SSam Leffler
40414779705SSam Leffler for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
40514779705SSam Leffler EEPROM_POWER_EXPN_5112 *pPowerExpn =
40614779705SSam Leffler &ee->ee_modePowerArray5112[mode];
40714779705SSam Leffler data = pPowerExpn->pChannels;
40814779705SSam Leffler if (data != AH_NULL) {
40914779705SSam Leffler pPowerExpn->pChannels = AH_NULL;
41014779705SSam Leffler ath_hal_free(data);
41114779705SSam Leffler }
41214779705SSam Leffler }
41314779705SSam Leffler }
41414779705SSam Leffler
41514779705SSam Leffler static void
ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 * pEEPROMDataset2413,uint16_t myNumRawChannels,uint16_t * pMyRawChanList)41614779705SSam Leffler ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413,
41714779705SSam Leffler uint16_t myNumRawChannels, uint16_t *pMyRawChanList)
41814779705SSam Leffler {
41914779705SSam Leffler uint16_t i, channelValue;
42014779705SSam Leffler uint32_t xpd_mask;
42114779705SSam Leffler uint16_t numPdGainsUsed;
42214779705SSam Leffler
42314779705SSam Leffler pEEPROMDataset2413->numChannels = myNumRawChannels;
42414779705SSam Leffler
42514779705SSam Leffler xpd_mask = pEEPROMDataset2413->xpd_mask;
42614779705SSam Leffler numPdGainsUsed = 0;
42714779705SSam Leffler if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
42814779705SSam Leffler if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
42914779705SSam Leffler if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
43014779705SSam Leffler if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
43114779705SSam Leffler
43214779705SSam Leffler for (i = 0; i < myNumRawChannels; i++) {
43314779705SSam Leffler channelValue = pMyRawChanList[i];
43414779705SSam Leffler pEEPROMDataset2413->pChannels[i] = channelValue;
43514779705SSam Leffler pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue;
43614779705SSam Leffler pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed;
43714779705SSam Leffler }
43814779705SSam Leffler }
43914779705SSam Leffler
44014779705SSam Leffler static HAL_BOOL
ar2413ReadCalDataset(struct ath_hal * ah,HAL_EEPROM * ee,EEPROM_DATA_STRUCT_2413 * pCalDataset,uint32_t start_offset,uint32_t maxPiers,uint8_t mode)44114779705SSam Leffler ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee,
44214779705SSam Leffler EEPROM_DATA_STRUCT_2413 *pCalDataset,
44314779705SSam Leffler uint32_t start_offset, uint32_t maxPiers, uint8_t mode)
44414779705SSam Leffler {
44514779705SSam Leffler #define EEREAD(_off) do { \
44614779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
44714779705SSam Leffler return AH_FALSE; \
44814779705SSam Leffler } while (0)
44914779705SSam Leffler const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */
45014779705SSam Leffler const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */
45114779705SSam Leffler const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */
45214779705SSam Leffler const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */
45314779705SSam Leffler const uint16_t freqmask = 0xff;
45414779705SSam Leffler
45514779705SSam Leffler uint16_t ii, eeval;
45614779705SSam Leffler uint16_t idx, numPiers;
45714779705SSam Leffler uint16_t freq[NUM_11A_EEPROM_CHANNELS];
45814779705SSam Leffler
45914779705SSam Leffler idx = start_offset;
46014779705SSam Leffler for (numPiers = 0; numPiers < maxPiers;) {
46114779705SSam Leffler EEREAD(idx++);
46214779705SSam Leffler if ((eeval & freqmask) == 0)
46314779705SSam Leffler break;
46414779705SSam Leffler if (mode == headerInfo11A)
46514779705SSam Leffler freq[numPiers++] = fbin2freq(ee, (eeval & freqmask));
46614779705SSam Leffler else
46714779705SSam Leffler freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask));
46814779705SSam Leffler
46914779705SSam Leffler if (((eeval >> 8) & freqmask) == 0)
47014779705SSam Leffler break;
47114779705SSam Leffler if (mode == headerInfo11A)
47214779705SSam Leffler freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask);
47314779705SSam Leffler else
47414779705SSam Leffler freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask);
47514779705SSam Leffler }
47614779705SSam Leffler ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]);
47714779705SSam Leffler
47814779705SSam Leffler idx = start_offset + (maxPiers / 2);
47914779705SSam Leffler for (ii = 0; ii < pCalDataset->numChannels; ii++) {
48014779705SSam Leffler EEPROM_DATA_PER_CHANNEL_2413 *currCh =
48114779705SSam Leffler &(pCalDataset->pDataPerChannel[ii]);
48214779705SSam Leffler
48314779705SSam Leffler if (currCh->numPdGains > 0) {
48414779705SSam Leffler /*
48514779705SSam Leffler * Read the first NUM_POINTS_OTHER_PDGAINS pwr
48614779705SSam Leffler * and Vpd values for pdgain_0
48714779705SSam Leffler */
48814779705SSam Leffler EEREAD(idx++);
48914779705SSam Leffler currCh->pwr_I[0] = eeval & dbm_I_mask;
49014779705SSam Leffler currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask;
49114779705SSam Leffler currCh->pwr_delta_t2[0][0] =
49214779705SSam Leffler (eeval >> 12) & dbm_delta_mask;
49314779705SSam Leffler
49414779705SSam Leffler EEREAD(idx++);
49514779705SSam Leffler currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask;
49614779705SSam Leffler currCh->pwr_delta_t2[1][0] =
49714779705SSam Leffler (eeval >> 6) & dbm_delta_mask;
49814779705SSam Leffler currCh->Vpd_delta[1][0] =
49914779705SSam Leffler (eeval >> 10) & Vpd_delta_mask;
50014779705SSam Leffler
50114779705SSam Leffler EEREAD(idx++);
50214779705SSam Leffler currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask;
50314779705SSam Leffler currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask;
50414779705SSam Leffler }
50514779705SSam Leffler
50614779705SSam Leffler if (currCh->numPdGains > 1) {
50714779705SSam Leffler /*
50814779705SSam Leffler * Read the first NUM_POINTS_OTHER_PDGAINS pwr
50914779705SSam Leffler * and Vpd values for pdgain_1
51014779705SSam Leffler */
51114779705SSam Leffler currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask;
51214779705SSam Leffler currCh->Vpd_I[1] = (eeval >> 15) & 0x1;
51314779705SSam Leffler
51414779705SSam Leffler EEREAD(idx++);
51514779705SSam Leffler /* upper 6 bits */
51614779705SSam Leffler currCh->Vpd_I[1] |= (eeval & 0x3F) << 1;
51714779705SSam Leffler currCh->pwr_delta_t2[0][1] =
51814779705SSam Leffler (eeval >> 6) & dbm_delta_mask;
51914779705SSam Leffler currCh->Vpd_delta[0][1] =
52014779705SSam Leffler (eeval >> 10) & Vpd_delta_mask;
52114779705SSam Leffler
52214779705SSam Leffler EEREAD(idx++);
52314779705SSam Leffler currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask;
52414779705SSam Leffler currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask;
52514779705SSam Leffler currCh->pwr_delta_t2[2][1] =
52614779705SSam Leffler (eeval >> 10) & dbm_delta_mask;
52714779705SSam Leffler currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3;
52814779705SSam Leffler
52914779705SSam Leffler EEREAD(idx++);
53014779705SSam Leffler /* upper 4 bits */
53114779705SSam Leffler currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2;
53214779705SSam Leffler } else if (currCh->numPdGains == 1) {
53314779705SSam Leffler /*
53414779705SSam Leffler * Read the last pwr and Vpd values for pdgain_0
53514779705SSam Leffler */
53614779705SSam Leffler currCh->pwr_delta_t2[3][0] =
53714779705SSam Leffler (eeval >> 10) & dbm_delta_mask;
53814779705SSam Leffler currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3;
53914779705SSam Leffler
54014779705SSam Leffler EEREAD(idx++);
54114779705SSam Leffler /* upper 4 bits */
54214779705SSam Leffler currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2;
54314779705SSam Leffler
54414779705SSam Leffler /* 4 words if numPdGains == 1 */
54514779705SSam Leffler }
54614779705SSam Leffler
54714779705SSam Leffler if (currCh->numPdGains > 2) {
54814779705SSam Leffler /*
54914779705SSam Leffler * Read the first NUM_POINTS_OTHER_PDGAINS pwr
55014779705SSam Leffler * and Vpd values for pdgain_2
55114779705SSam Leffler */
55214779705SSam Leffler currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask;
55314779705SSam Leffler currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask;
55414779705SSam Leffler
55514779705SSam Leffler EEREAD(idx++);
55614779705SSam Leffler currCh->pwr_delta_t2[0][2] =
55714779705SSam Leffler (eeval >> 0) & dbm_delta_mask;
55814779705SSam Leffler currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask;
55914779705SSam Leffler currCh->pwr_delta_t2[1][2] =
56014779705SSam Leffler (eeval >> 10) & dbm_delta_mask;
56114779705SSam Leffler currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3;
56214779705SSam Leffler
56314779705SSam Leffler EEREAD(idx++);
56414779705SSam Leffler /* upper 4 bits */
56514779705SSam Leffler currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2;
56614779705SSam Leffler currCh->pwr_delta_t2[2][2] =
56714779705SSam Leffler (eeval >> 4) & dbm_delta_mask;
56814779705SSam Leffler currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask;
56914779705SSam Leffler } else if (currCh->numPdGains == 2) {
57014779705SSam Leffler /*
57114779705SSam Leffler * Read the last pwr and Vpd values for pdgain_1
57214779705SSam Leffler */
57314779705SSam Leffler currCh->pwr_delta_t2[3][1] =
57414779705SSam Leffler (eeval >> 4) & dbm_delta_mask;
57514779705SSam Leffler currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask;
57614779705SSam Leffler
57714779705SSam Leffler /* 6 words if numPdGains == 2 */
57814779705SSam Leffler }
57914779705SSam Leffler
58014779705SSam Leffler if (currCh->numPdGains > 3) {
58114779705SSam Leffler /*
58214779705SSam Leffler * Read the first NUM_POINTS_OTHER_PDGAINS pwr
58314779705SSam Leffler * and Vpd values for pdgain_3
58414779705SSam Leffler */
58514779705SSam Leffler currCh->pwr_I[3] = (eeval >> 14) & 0x3;
58614779705SSam Leffler
58714779705SSam Leffler EEREAD(idx++);
58814779705SSam Leffler /* upper 3 bits */
58914779705SSam Leffler currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2;
59014779705SSam Leffler currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask;
59114779705SSam Leffler currCh->pwr_delta_t2[0][3] =
59214779705SSam Leffler (eeval >> 10) & dbm_delta_mask;
59314779705SSam Leffler currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3;
59414779705SSam Leffler
59514779705SSam Leffler EEREAD(idx++);
59614779705SSam Leffler /* upper 4 bits */
59714779705SSam Leffler currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2;
59814779705SSam Leffler currCh->pwr_delta_t2[1][3] =
59914779705SSam Leffler (eeval >> 4) & dbm_delta_mask;
60014779705SSam Leffler currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask;
60114779705SSam Leffler currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3;
60214779705SSam Leffler
60314779705SSam Leffler EEREAD(idx++);
60414779705SSam Leffler /* upper 2 bits */
60514779705SSam Leffler currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2;
60614779705SSam Leffler currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask;
60714779705SSam Leffler currCh->pwr_delta_t2[3][3] =
60814779705SSam Leffler (eeval >> 8) & dbm_delta_mask;
60914779705SSam Leffler currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF;
61014779705SSam Leffler
61114779705SSam Leffler EEREAD(idx++);
61214779705SSam Leffler /* upper 2 bits */
61314779705SSam Leffler currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4;
61414779705SSam Leffler
61514779705SSam Leffler /* 12 words if numPdGains == 4 */
61614779705SSam Leffler } else if (currCh->numPdGains == 3) {
61714779705SSam Leffler /* read the last pwr and Vpd values for pdgain_2 */
61814779705SSam Leffler currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3;
61914779705SSam Leffler
62014779705SSam Leffler EEREAD(idx++);
62114779705SSam Leffler /* upper 2 bits */
62214779705SSam Leffler currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2;
62314779705SSam Leffler currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask;
62414779705SSam Leffler
62514779705SSam Leffler /* 9 words if numPdGains == 3 */
62614779705SSam Leffler }
62714779705SSam Leffler }
62814779705SSam Leffler return AH_TRUE;
62914779705SSam Leffler #undef EEREAD
63014779705SSam Leffler }
63114779705SSam Leffler
63214779705SSam Leffler static void
ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 * pRaw,EEPROM_DATA_STRUCT_2413 * pCal)63314779705SSam Leffler ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal)
63414779705SSam Leffler {
63514779705SSam Leffler uint16_t i, j, kk, channelValue;
63614779705SSam Leffler uint16_t xpd_mask;
63714779705SSam Leffler uint16_t numPdGainsUsed;
63814779705SSam Leffler
63914779705SSam Leffler pRaw->numChannels = pCal->numChannels;
64014779705SSam Leffler
64114779705SSam Leffler xpd_mask = pRaw->xpd_mask;
64214779705SSam Leffler numPdGainsUsed = 0;
64314779705SSam Leffler if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
64414779705SSam Leffler if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
64514779705SSam Leffler if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
64614779705SSam Leffler if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
64714779705SSam Leffler
64814779705SSam Leffler for (i = 0; i < pCal->numChannels; i++) {
64914779705SSam Leffler channelValue = pCal->pChannels[i];
65014779705SSam Leffler
65114779705SSam Leffler pRaw->pChannels[i] = channelValue;
65214779705SSam Leffler
65314779705SSam Leffler pRaw->pDataPerChannel[i].channelValue = channelValue;
65414779705SSam Leffler pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed;
65514779705SSam Leffler
65614779705SSam Leffler kk = 0;
65714779705SSam Leffler for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) {
65814779705SSam Leffler pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j;
65914779705SSam Leffler if ((xpd_mask >> j) & 0x1) {
66014779705SSam Leffler pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS;
66114779705SSam Leffler kk++;
66214779705SSam Leffler if (kk == 1) {
66314779705SSam Leffler /*
66414779705SSam Leffler * lowest pd_gain corresponds
66514779705SSam Leffler * to highest power and thus,
66614779705SSam Leffler * has one more point
66714779705SSam Leffler */
66814779705SSam Leffler pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN;
66914779705SSam Leffler }
67014779705SSam Leffler } else {
67114779705SSam Leffler pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0;
67214779705SSam Leffler }
67314779705SSam Leffler }
67414779705SSam Leffler }
67514779705SSam Leffler }
67614779705SSam Leffler
67714779705SSam Leffler static HAL_BOOL
ar2413EepromToRawDataset(struct ath_hal * ah,EEPROM_DATA_STRUCT_2413 * pCal,RAW_DATA_STRUCT_2413 * pRaw)67814779705SSam Leffler ar2413EepromToRawDataset(struct ath_hal *ah,
67914779705SSam Leffler EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw)
68014779705SSam Leffler {
68114779705SSam Leffler uint16_t ii, jj, kk, ss;
68214779705SSam Leffler RAW_DATA_PER_PDGAIN_2413 *pRawXPD;
68314779705SSam Leffler /* ptr to array of info held per channel */
68414779705SSam Leffler EEPROM_DATA_PER_CHANNEL_2413 *pCalCh;
68514779705SSam Leffler uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL];
68614779705SSam Leffler uint16_t xpd_mask;
68714779705SSam Leffler uint32_t numPdGainsUsed;
68814779705SSam Leffler
68914779705SSam Leffler HALASSERT(pRaw->xpd_mask == pCal->xpd_mask);
69014779705SSam Leffler
69114779705SSam Leffler xgain_list[0] = 0xDEAD;
69214779705SSam Leffler xgain_list[1] = 0xDEAD;
69314779705SSam Leffler xgain_list[2] = 0xDEAD;
69414779705SSam Leffler xgain_list[3] = 0xDEAD;
69514779705SSam Leffler
69614779705SSam Leffler numPdGainsUsed = 0;
69714779705SSam Leffler xpd_mask = pRaw->xpd_mask;
69814779705SSam Leffler for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) {
69914779705SSam Leffler if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1)
70014779705SSam Leffler xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1;
70114779705SSam Leffler }
70214779705SSam Leffler
70314779705SSam Leffler pRaw->numChannels = pCal->numChannels;
70414779705SSam Leffler for (ii = 0; ii < pRaw->numChannels; ii++) {
70514779705SSam Leffler pCalCh = &(pCal->pDataPerChannel[ii]);
70614779705SSam Leffler pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue;
70714779705SSam Leffler
70814779705SSam Leffler /* numVpd has already been setup appropriately for the relevant pdGains */
70914779705SSam Leffler for (jj = 0; jj < numPdGainsUsed; jj++) {
71014779705SSam Leffler /* use jj for calDataset and ss for rawDataset */
71114779705SSam Leffler ss = xgain_list[jj];
71214779705SSam Leffler pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]);
71314779705SSam Leffler HALASSERT(pRawXPD->numVpd >= 1);
71414779705SSam Leffler
71514779705SSam Leffler pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]);
71614779705SSam Leffler pRawXPD->Vpd[0] = pCalCh->Vpd_I[jj];
71714779705SSam Leffler
71814779705SSam Leffler for (kk = 1; kk < pRawXPD->numVpd; kk++) {
71914779705SSam Leffler pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]);
72014779705SSam Leffler pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]);
72114779705SSam Leffler }
72214779705SSam Leffler /* loop over Vpds */
72314779705SSam Leffler }
72414779705SSam Leffler /* loop over pd_gains */
72514779705SSam Leffler }
72614779705SSam Leffler /* loop over channels */
72714779705SSam Leffler return AH_TRUE;
72814779705SSam Leffler }
72914779705SSam Leffler
73014779705SSam Leffler static HAL_BOOL
readEepromRawPowerCalInfo2413(struct ath_hal * ah,HAL_EEPROM * ee)73114779705SSam Leffler readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee)
73214779705SSam Leffler {
73314779705SSam Leffler /* NB: index is 1 less than numPdgains */
73414779705SSam Leffler static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 };
73514779705SSam Leffler EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL;
73614779705SSam Leffler RAW_DATA_STRUCT_2413 *pRaw;
73714779705SSam Leffler int numEEPROMWordsPerChannel;
73814779705SSam Leffler uint32_t off;
73914779705SSam Leffler HAL_BOOL ret = AH_FALSE;
74014779705SSam Leffler
74114779705SSam Leffler HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0);
74214779705SSam Leffler HALASSERT(ee->ee_eepMap == 2);
74314779705SSam Leffler
74414779705SSam Leffler pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413));
74514779705SSam Leffler if (pCal == AH_NULL)
74614779705SSam Leffler goto exit;
74714779705SSam Leffler
74814779705SSam Leffler off = ee->ee_eepMap2PowerCalStart;
74914779705SSam Leffler if (ee->ee_Amode) {
75014779705SSam Leffler OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
75114779705SSam Leffler pCal->xpd_mask = ee->ee_xgain[headerInfo11A];
75214779705SSam Leffler if (!ar2413ReadCalDataset(ah, ee, pCal, off,
75314779705SSam Leffler NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) {
75414779705SSam Leffler goto exit;
75514779705SSam Leffler }
75614779705SSam Leffler pRaw = &ee->ee_rawDataset2413[headerInfo11A];
75714779705SSam Leffler pRaw->xpd_mask = ee->ee_xgain[headerInfo11A];
75814779705SSam Leffler ar2413SetupRawDataset(pRaw, pCal);
75914779705SSam Leffler if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
76014779705SSam Leffler goto exit;
76114779705SSam Leffler }
76214779705SSam Leffler /* setup offsets for mode_11a next */
76314779705SSam Leffler numEEPROMWordsPerChannel = wordsForPdgains[
76414779705SSam Leffler pCal->pDataPerChannel[0].numPdGains - 1];
76514779705SSam Leffler off += pCal->numChannels * numEEPROMWordsPerChannel + 5;
76614779705SSam Leffler }
76714779705SSam Leffler if (ee->ee_Bmode) {
76814779705SSam Leffler OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
76914779705SSam Leffler pCal->xpd_mask = ee->ee_xgain[headerInfo11B];
77014779705SSam Leffler if (!ar2413ReadCalDataset(ah, ee, pCal, off,
77114779705SSam Leffler NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) {
77214779705SSam Leffler goto exit;
77314779705SSam Leffler }
77414779705SSam Leffler pRaw = &ee->ee_rawDataset2413[headerInfo11B];
77514779705SSam Leffler pRaw->xpd_mask = ee->ee_xgain[headerInfo11B];
77614779705SSam Leffler ar2413SetupRawDataset(pRaw, pCal);
77714779705SSam Leffler if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
77814779705SSam Leffler goto exit;
77914779705SSam Leffler }
78014779705SSam Leffler /* setup offsets for mode_11g next */
78114779705SSam Leffler numEEPROMWordsPerChannel = wordsForPdgains[
78214779705SSam Leffler pCal->pDataPerChannel[0].numPdGains - 1];
78314779705SSam Leffler off += pCal->numChannels * numEEPROMWordsPerChannel + 2;
78414779705SSam Leffler }
78514779705SSam Leffler if (ee->ee_Gmode) {
78614779705SSam Leffler OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
78714779705SSam Leffler pCal->xpd_mask = ee->ee_xgain[headerInfo11G];
78814779705SSam Leffler if (!ar2413ReadCalDataset(ah, ee, pCal, off,
78914779705SSam Leffler NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) {
79014779705SSam Leffler goto exit;
79114779705SSam Leffler }
79214779705SSam Leffler pRaw = &ee->ee_rawDataset2413[headerInfo11G];
79314779705SSam Leffler pRaw->xpd_mask = ee->ee_xgain[headerInfo11G];
79414779705SSam Leffler ar2413SetupRawDataset(pRaw, pCal);
79514779705SSam Leffler if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
79614779705SSam Leffler goto exit;
79714779705SSam Leffler }
79814779705SSam Leffler }
79914779705SSam Leffler ret = AH_TRUE;
80014779705SSam Leffler exit:
80114779705SSam Leffler if (pCal != AH_NULL)
80214779705SSam Leffler ath_hal_free(pCal);
80314779705SSam Leffler return ret;
80414779705SSam Leffler }
80514779705SSam Leffler
80614779705SSam Leffler /*
80714779705SSam Leffler * Now copy EEPROM Raw Power Calibration per frequency contents
80814779705SSam Leffler * into the allocated space
80914779705SSam Leffler */
81014779705SSam Leffler static HAL_BOOL
readEepromRawPowerCalInfo(struct ath_hal * ah,HAL_EEPROM * ee)81114779705SSam Leffler readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
81214779705SSam Leffler {
81314779705SSam Leffler #define EEREAD(_off) do { \
81414779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
81514779705SSam Leffler return AH_FALSE; \
81614779705SSam Leffler } while (0)
81714779705SSam Leffler uint16_t eeval, nchan;
81814779705SSam Leffler uint32_t off;
81914779705SSam Leffler int i, j, mode;
82014779705SSam Leffler
82114779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
82214779705SSam Leffler return readEepromRawPowerCalInfo5112(ah, ee);
82314779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2)
82414779705SSam Leffler return readEepromRawPowerCalInfo2413(ah, ee);
82514779705SSam Leffler
82614779705SSam Leffler /*
82714779705SSam Leffler * Group 2: read raw power data for all frequency piers
82814779705SSam Leffler *
82914779705SSam Leffler * NOTE: Group 2 contains the raw power calibration
83014779705SSam Leffler * information for each of the channels that
83114779705SSam Leffler * we recorded above.
83214779705SSam Leffler */
83314779705SSam Leffler for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
83414779705SSam Leffler uint16_t *pChannels = AH_NULL;
83514779705SSam Leffler DATA_PER_CHANNEL *pChannelData = AH_NULL;
83614779705SSam Leffler
83714779705SSam Leffler off = ee->ee_version >= AR_EEPROM_VER3_3 ?
83814779705SSam Leffler GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
83914779705SSam Leffler switch (mode) {
84014779705SSam Leffler case headerInfo11A:
84114779705SSam Leffler off += GROUP2_OFFSET;
84214779705SSam Leffler nchan = ee->ee_numChannels11a;
84314779705SSam Leffler pChannelData = ee->ee_dataPerChannel11a;
84414779705SSam Leffler pChannels = ee->ee_channels11a;
84514779705SSam Leffler break;
84614779705SSam Leffler case headerInfo11B:
84714779705SSam Leffler if (!ee->ee_Bmode)
84814779705SSam Leffler continue;
84914779705SSam Leffler off += GROUP3_OFFSET;
85014779705SSam Leffler nchan = ee->ee_numChannels2_4;
85114779705SSam Leffler pChannelData = ee->ee_dataPerChannel11b;
85214779705SSam Leffler pChannels = ee->ee_channels11b;
85314779705SSam Leffler break;
85414779705SSam Leffler case headerInfo11G:
85514779705SSam Leffler if (!ee->ee_Gmode)
85614779705SSam Leffler continue;
85714779705SSam Leffler off += GROUP4_OFFSET;
85814779705SSam Leffler nchan = ee->ee_numChannels2_4;
85914779705SSam Leffler pChannelData = ee->ee_dataPerChannel11g;
86014779705SSam Leffler pChannels = ee->ee_channels11g;
86114779705SSam Leffler break;
86214779705SSam Leffler default:
86314779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
86414779705SSam Leffler __func__, mode);
86514779705SSam Leffler return AH_FALSE;
86614779705SSam Leffler }
86714779705SSam Leffler for (i = 0; i < nchan; i++) {
86814779705SSam Leffler pChannelData->channelValue = pChannels[i];
86914779705SSam Leffler
87014779705SSam Leffler EEREAD(off++);
87114779705SSam Leffler pChannelData->pcdacMax = (uint16_t)((eeval >> 10) & PCDAC_MASK);
87214779705SSam Leffler pChannelData->pcdacMin = (uint16_t)((eeval >> 4) & PCDAC_MASK);
87314779705SSam Leffler pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK);
87414779705SSam Leffler
87514779705SSam Leffler EEREAD(off++);
87614779705SSam Leffler pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3);
87714779705SSam Leffler pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK);
87814779705SSam Leffler pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK);
87914779705SSam Leffler pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK);
88014779705SSam Leffler
88114779705SSam Leffler EEREAD(off++);
88214779705SSam Leffler pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf);
88314779705SSam Leffler pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK);
88414779705SSam Leffler pChannelData->PwrValues[5] = (uint16_t)(eeval & POWER_MASK);
88514779705SSam Leffler
88614779705SSam Leffler EEREAD(off++);
88714779705SSam Leffler pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK);
88814779705SSam Leffler pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK);
88914779705SSam Leffler pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK);
89014779705SSam Leffler
89114779705SSam Leffler EEREAD(off++);
89214779705SSam Leffler pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3);
89314779705SSam Leffler pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK);
89414779705SSam Leffler pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK);
89514779705SSam Leffler
89614779705SSam Leffler getPcdacInterceptsFromPcdacMinMax(ee,
89714779705SSam Leffler pChannelData->pcdacMin, pChannelData->pcdacMax,
89814779705SSam Leffler pChannelData->PcdacValues) ;
89914779705SSam Leffler
90014779705SSam Leffler for (j = 0; j < pChannelData->numPcdacValues; j++) {
90114779705SSam Leffler pChannelData->PwrValues[j] = (uint16_t)(
90214779705SSam Leffler PWR_STEP * pChannelData->PwrValues[j]);
90314779705SSam Leffler /* Note these values are scaled up. */
90414779705SSam Leffler }
90514779705SSam Leffler pChannelData++;
90614779705SSam Leffler }
90714779705SSam Leffler }
90814779705SSam Leffler return AH_TRUE;
90914779705SSam Leffler #undef EEREAD
91014779705SSam Leffler }
91114779705SSam Leffler
91214779705SSam Leffler /*
91314779705SSam Leffler * Copy EEPROM Target Power Calbration per rate contents
91414779705SSam Leffler * into the allocated space
91514779705SSam Leffler */
91614779705SSam Leffler static HAL_BOOL
readEepromTargetPowerCalInfo(struct ath_hal * ah,HAL_EEPROM * ee)91714779705SSam Leffler readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
91814779705SSam Leffler {
91914779705SSam Leffler #define EEREAD(_off) do { \
92014779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
92114779705SSam Leffler return AH_FALSE; \
92214779705SSam Leffler } while (0)
92314779705SSam Leffler uint16_t eeval, enable24;
92414779705SSam Leffler uint32_t off;
92514779705SSam Leffler int i, mode, nchan;
92614779705SSam Leffler
92714779705SSam Leffler enable24 = ee->ee_Bmode || ee->ee_Gmode;
92814779705SSam Leffler for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
92914779705SSam Leffler TRGT_POWER_INFO *pPowerInfo;
93014779705SSam Leffler uint16_t *pNumTrgtChannels;
93114779705SSam Leffler
93214779705SSam Leffler off = ee->ee_version >= AR_EEPROM_VER4_0 ?
93314779705SSam Leffler ee->ee_targetPowersStart - GROUP5_OFFSET :
93414779705SSam Leffler ee->ee_version >= AR_EEPROM_VER3_3 ?
93514779705SSam Leffler GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
93614779705SSam Leffler switch (mode) {
93714779705SSam Leffler case headerInfo11A:
93814779705SSam Leffler off += GROUP5_OFFSET;
93914779705SSam Leffler nchan = NUM_TEST_FREQUENCIES;
94014779705SSam Leffler pPowerInfo = ee->ee_trgtPwr_11a;
94114779705SSam Leffler pNumTrgtChannels = &ee->ee_numTargetPwr_11a;
94214779705SSam Leffler break;
94314779705SSam Leffler case headerInfo11B:
94414779705SSam Leffler if (!enable24)
94514779705SSam Leffler continue;
94614779705SSam Leffler off += GROUP6_OFFSET;
94714779705SSam Leffler nchan = 2;
94814779705SSam Leffler pPowerInfo = ee->ee_trgtPwr_11b;
94914779705SSam Leffler pNumTrgtChannels = &ee->ee_numTargetPwr_11b;
95014779705SSam Leffler break;
95114779705SSam Leffler case headerInfo11G:
95214779705SSam Leffler if (!enable24)
95314779705SSam Leffler continue;
95414779705SSam Leffler off += GROUP7_OFFSET;
95514779705SSam Leffler nchan = 3;
95614779705SSam Leffler pPowerInfo = ee->ee_trgtPwr_11g;
95714779705SSam Leffler pNumTrgtChannels = &ee->ee_numTargetPwr_11g;
95814779705SSam Leffler break;
95914779705SSam Leffler default:
96014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
96114779705SSam Leffler __func__, mode);
96214779705SSam Leffler return AH_FALSE;
96314779705SSam Leffler }
96414779705SSam Leffler *pNumTrgtChannels = 0;
96514779705SSam Leffler for (i = 0; i < nchan; i++) {
96614779705SSam Leffler EEREAD(off++);
96714779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
96814779705SSam Leffler pPowerInfo->testChannel = (eeval >> 8) & 0xff;
96914779705SSam Leffler } else {
97014779705SSam Leffler pPowerInfo->testChannel = (eeval >> 9) & 0x7f;
97114779705SSam Leffler }
97214779705SSam Leffler
97314779705SSam Leffler if (pPowerInfo->testChannel != 0) {
97414779705SSam Leffler /* get the channel value and read rest of info */
97514779705SSam Leffler if (mode == headerInfo11A) {
97614779705SSam Leffler pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel);
97714779705SSam Leffler } else {
97814779705SSam Leffler pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel);
97914779705SSam Leffler }
98014779705SSam Leffler
98114779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
98214779705SSam Leffler pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK;
98314779705SSam Leffler pPowerInfo->twicePwr36 = (eeval << 4) & POWER_MASK;
98414779705SSam Leffler } else {
98514779705SSam Leffler pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK;
98614779705SSam Leffler pPowerInfo->twicePwr36 = (eeval << 3) & POWER_MASK;
98714779705SSam Leffler }
98814779705SSam Leffler
98914779705SSam Leffler EEREAD(off++);
99014779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
99114779705SSam Leffler pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf;
99214779705SSam Leffler pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK;
99314779705SSam Leffler pPowerInfo->twicePwr54 = eeval & POWER_MASK;
99414779705SSam Leffler } else {
99514779705SSam Leffler pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7;
99614779705SSam Leffler pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK;
99714779705SSam Leffler pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK;
99814779705SSam Leffler }
99914779705SSam Leffler (*pNumTrgtChannels)++;
100014779705SSam Leffler }
100114779705SSam Leffler pPowerInfo++;
100214779705SSam Leffler }
100314779705SSam Leffler }
100414779705SSam Leffler return AH_TRUE;
100514779705SSam Leffler #undef EEREAD
100614779705SSam Leffler }
100714779705SSam Leffler
100814779705SSam Leffler /*
100914779705SSam Leffler * Now copy EEPROM Coformance Testing Limits contents
101014779705SSam Leffler * into the allocated space
101114779705SSam Leffler */
101214779705SSam Leffler static HAL_BOOL
readEepromCTLInfo(struct ath_hal * ah,HAL_EEPROM * ee)101314779705SSam Leffler readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee)
101414779705SSam Leffler {
101514779705SSam Leffler #define EEREAD(_off) do { \
101614779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
101714779705SSam Leffler return AH_FALSE; \
101814779705SSam Leffler } while (0)
101914779705SSam Leffler RD_EDGES_POWER *rep;
102014779705SSam Leffler uint16_t eeval;
102114779705SSam Leffler uint32_t off;
102214779705SSam Leffler int i, j;
102314779705SSam Leffler
102414779705SSam Leffler rep = ee->ee_rdEdgesPower;
102514779705SSam Leffler
102614779705SSam Leffler off = GROUP8_OFFSET +
102714779705SSam Leffler (ee->ee_version >= AR_EEPROM_VER4_0 ?
102814779705SSam Leffler ee->ee_targetPowersStart - GROUP5_OFFSET :
102914779705SSam Leffler ee->ee_version >= AR_EEPROM_VER3_3 ?
103014779705SSam Leffler GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2);
103114779705SSam Leffler for (i = 0; i < ee->ee_numCtls; i++) {
103214779705SSam Leffler if (ee->ee_ctl[i] == 0) {
103314779705SSam Leffler /* Move offset and edges */
103414779705SSam Leffler off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7);
103514779705SSam Leffler rep += NUM_EDGES;
103614779705SSam Leffler continue;
103714779705SSam Leffler }
103814779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
103914779705SSam Leffler for (j = 0; j < NUM_EDGES; j += 2) {
104014779705SSam Leffler EEREAD(off++);
104114779705SSam Leffler rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3;
104214779705SSam Leffler rep[j+1].rdEdge = eeval & FREQ_MASK_3_3;
104314779705SSam Leffler }
104414779705SSam Leffler for (j = 0; j < NUM_EDGES; j += 2) {
104514779705SSam Leffler EEREAD(off++);
104614779705SSam Leffler rep[j].twice_rdEdgePower =
104714779705SSam Leffler (eeval >> 8) & POWER_MASK;
104814779705SSam Leffler rep[j].flag = (eeval >> 14) & 1;
104914779705SSam Leffler rep[j+1].twice_rdEdgePower = eeval & POWER_MASK;
105014779705SSam Leffler rep[j+1].flag = (eeval >> 6) & 1;
105114779705SSam Leffler }
105214779705SSam Leffler } else {
105314779705SSam Leffler EEREAD(off++);
105414779705SSam Leffler rep[0].rdEdge = (eeval >> 9) & FREQ_MASK;
105514779705SSam Leffler rep[1].rdEdge = (eeval >> 2) & FREQ_MASK;
105614779705SSam Leffler rep[2].rdEdge = (eeval << 5) & FREQ_MASK;
105714779705SSam Leffler
105814779705SSam Leffler EEREAD(off++);
105914779705SSam Leffler rep[2].rdEdge |= (eeval >> 11) & 0x1f;
106014779705SSam Leffler rep[3].rdEdge = (eeval >> 4) & FREQ_MASK;
106114779705SSam Leffler rep[4].rdEdge = (eeval << 3) & FREQ_MASK;
106214779705SSam Leffler
106314779705SSam Leffler EEREAD(off++);
106414779705SSam Leffler rep[4].rdEdge |= (eeval >> 13) & 0x7;
106514779705SSam Leffler rep[5].rdEdge = (eeval >> 6) & FREQ_MASK;
106614779705SSam Leffler rep[6].rdEdge = (eeval << 1) & FREQ_MASK;
106714779705SSam Leffler
106814779705SSam Leffler EEREAD(off++);
106914779705SSam Leffler rep[6].rdEdge |= (eeval >> 15) & 0x1;
107014779705SSam Leffler rep[7].rdEdge = (eeval >> 8) & FREQ_MASK;
107114779705SSam Leffler
107214779705SSam Leffler rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK;
107314779705SSam Leffler rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK;
107414779705SSam Leffler
107514779705SSam Leffler EEREAD(off++);
107614779705SSam Leffler rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf;
107714779705SSam Leffler rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK;
107814779705SSam Leffler rep[3].twice_rdEdgePower = eeval & POWER_MASK;
107914779705SSam Leffler
108014779705SSam Leffler EEREAD(off++);
108114779705SSam Leffler rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK;
108214779705SSam Leffler rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK;
108314779705SSam Leffler rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK;
108414779705SSam Leffler
108514779705SSam Leffler EEREAD(off++);
108614779705SSam Leffler rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3;
108714779705SSam Leffler rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK;
108814779705SSam Leffler }
108914779705SSam Leffler
109014779705SSam Leffler for (j = 0; j < NUM_EDGES; j++ ) {
109114779705SSam Leffler if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) {
109214779705SSam Leffler if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A ||
109314779705SSam Leffler (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) {
109414779705SSam Leffler rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge);
109514779705SSam Leffler } else {
109614779705SSam Leffler rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge);
109714779705SSam Leffler }
109814779705SSam Leffler }
109914779705SSam Leffler }
110014779705SSam Leffler rep += NUM_EDGES;
110114779705SSam Leffler }
110214779705SSam Leffler return AH_TRUE;
110314779705SSam Leffler #undef EEREAD
110414779705SSam Leffler }
110514779705SSam Leffler
110614779705SSam Leffler /*
110714779705SSam Leffler * Read the individual header fields for a Rev 3 EEPROM
110814779705SSam Leffler */
110914779705SSam Leffler static HAL_BOOL
readHeaderInfo(struct ath_hal * ah,HAL_EEPROM * ee)111014779705SSam Leffler readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee)
111114779705SSam Leffler {
111214779705SSam Leffler #define EEREAD(_off) do { \
111314779705SSam Leffler if (!ath_hal_eepromRead(ah, _off, &eeval)) \
111414779705SSam Leffler return AH_FALSE; \
111514779705SSam Leffler } while (0)
111614779705SSam Leffler static const uint32_t headerOffset3_0[] = {
111714779705SSam Leffler 0x00C2, /* 0 - Mode bits, device type, max turbo power */
111814779705SSam Leffler 0x00C4, /* 1 - 2.4 and 5 antenna gain */
111914779705SSam Leffler 0x00C5, /* 2 - Begin 11A modal section */
112014779705SSam Leffler 0x00D0, /* 3 - Begin 11B modal section */
112114779705SSam Leffler 0x00DA, /* 4 - Begin 11G modal section */
112214779705SSam Leffler 0x00E4 /* 5 - Begin CTL section */
112314779705SSam Leffler };
112414779705SSam Leffler static const uint32_t headerOffset3_3[] = {
112514779705SSam Leffler 0x00C2, /* 0 - Mode bits, device type, max turbo power */
112614779705SSam Leffler 0x00C3, /* 1 - 2.4 and 5 antenna gain */
112714779705SSam Leffler 0x00D4, /* 2 - Begin 11A modal section */
112814779705SSam Leffler 0x00F2, /* 3 - Begin 11B modal section */
112914779705SSam Leffler 0x010D, /* 4 - Begin 11G modal section */
113014779705SSam Leffler 0x0128 /* 5 - Begin CTL section */
113114779705SSam Leffler };
113214779705SSam Leffler
113314779705SSam Leffler static const uint32_t regCapOffsetPre4_0 = 0x00CF;
113414779705SSam Leffler static const uint32_t regCapOffsetPost4_0 = 0x00CA;
113514779705SSam Leffler
113614779705SSam Leffler const uint32_t *header;
113714779705SSam Leffler uint32_t off;
113814779705SSam Leffler uint16_t eeval;
113914779705SSam Leffler int i;
114014779705SSam Leffler
114114779705SSam Leffler /* initialize cckOfdmGainDelta for < 4.2 eeprom */
114214779705SSam Leffler ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA;
114314779705SSam Leffler ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT;
114414779705SSam Leffler
114514779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
114614779705SSam Leffler header = headerOffset3_3;
114714779705SSam Leffler ee->ee_numCtls = NUM_CTLS_3_3;
114814779705SSam Leffler } else {
114914779705SSam Leffler header = headerOffset3_0;
115014779705SSam Leffler ee->ee_numCtls = NUM_CTLS;
115114779705SSam Leffler }
115214779705SSam Leffler HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX);
115314779705SSam Leffler
115414779705SSam Leffler EEREAD(header[0]);
115514779705SSam Leffler ee->ee_turbo5Disable = (eeval >> 15) & 0x01;
115614779705SSam Leffler ee->ee_rfKill = (eeval >> 14) & 0x01;
115714779705SSam Leffler ee->ee_deviceType = (eeval >> 11) & 0x07;
115814779705SSam Leffler ee->ee_turbo2WMaxPower5 = (eeval >> 4) & 0x7F;
115914779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0)
116014779705SSam Leffler ee->ee_turbo2Disable = (eeval >> 3) & 0x01;
116114779705SSam Leffler else
116214779705SSam Leffler ee->ee_turbo2Disable = 1;
116314779705SSam Leffler ee->ee_Gmode = (eeval >> 2) & 0x01;
116414779705SSam Leffler ee->ee_Bmode = (eeval >> 1) & 0x01;
116514779705SSam Leffler ee->ee_Amode = (eeval & 0x01);
116614779705SSam Leffler
116714779705SSam Leffler off = header[1];
116814779705SSam Leffler EEREAD(off++);
116914779705SSam Leffler ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF);
117014779705SSam Leffler ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF);
117114779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0) {
117214779705SSam Leffler EEREAD(off++);
117314779705SSam Leffler ee->ee_eepMap = (eeval>>14) & 0x3;
117414779705SSam Leffler ee->ee_disableXr5 = (eeval>>13) & 0x1;
117514779705SSam Leffler ee->ee_disableXr2 = (eeval>>12) & 0x1;
117614779705SSam Leffler ee->ee_earStart = eeval & 0xfff;
117714779705SSam Leffler
117814779705SSam Leffler EEREAD(off++);
117914779705SSam Leffler ee->ee_targetPowersStart = eeval & 0xfff;
118014779705SSam Leffler ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1;
118114779705SSam Leffler
118214779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER5_0) {
118314779705SSam Leffler off += 2;
118414779705SSam Leffler EEREAD(off);
118514779705SSam Leffler ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff;
118614779705SSam Leffler /* Properly cal'ed 5.0 devices should be non-zero */
118714779705SSam Leffler }
118814779705SSam Leffler }
118914779705SSam Leffler
119014779705SSam Leffler /* Read the moded sections of the EEPROM header in the order A, B, G */
119114779705SSam Leffler for (i = headerInfo11A; i <= headerInfo11G; i++) {
119214779705SSam Leffler /* Set the offset via the index */
119314779705SSam Leffler off = header[2 + i];
119414779705SSam Leffler
119514779705SSam Leffler EEREAD(off++);
119614779705SSam Leffler ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f;
119714779705SSam Leffler ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f;
119814779705SSam Leffler ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f;
119914779705SSam Leffler
120014779705SSam Leffler EEREAD(off++);
120114779705SSam Leffler ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f;
120214779705SSam Leffler ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f;
120314779705SSam Leffler ee->ee_antennaControl[2][i] = eeval & 0x3f;
120414779705SSam Leffler
120514779705SSam Leffler EEREAD(off++);
120614779705SSam Leffler ee->ee_antennaControl[3][i] = (eeval >> 10) & 0x3f;
120714779705SSam Leffler ee->ee_antennaControl[4][i] = (eeval >> 4) & 0x3f;
120814779705SSam Leffler ee->ee_antennaControl[5][i] = (eeval << 2) & 0x3f;
120914779705SSam Leffler
121014779705SSam Leffler EEREAD(off++);
121114779705SSam Leffler ee->ee_antennaControl[5][i] |= (eeval >> 14) & 0x03;
121214779705SSam Leffler ee->ee_antennaControl[6][i] = (eeval >> 8) & 0x3f;
121314779705SSam Leffler ee->ee_antennaControl[7][i] = (eeval >> 2) & 0x3f;
121414779705SSam Leffler ee->ee_antennaControl[8][i] = (eeval << 4) & 0x3f;
121514779705SSam Leffler
121614779705SSam Leffler EEREAD(off++);
121714779705SSam Leffler ee->ee_antennaControl[8][i] |= (eeval >> 12) & 0x0f;
121814779705SSam Leffler ee->ee_antennaControl[9][i] = (eeval >> 6) & 0x3f;
121914779705SSam Leffler ee->ee_antennaControl[10][i] = eeval & 0x3f;
122014779705SSam Leffler
122114779705SSam Leffler EEREAD(off++);
122214779705SSam Leffler ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff);
122314779705SSam Leffler switch (i) {
122414779705SSam Leffler case headerInfo11A:
122514779705SSam Leffler ee->ee_ob4 = (eeval >> 5) & 0x07;
122614779705SSam Leffler ee->ee_db4 = (eeval >> 2) & 0x07;
122714779705SSam Leffler ee->ee_ob3 = (eeval << 1) & 0x07;
122814779705SSam Leffler break;
122914779705SSam Leffler case headerInfo11B:
123014779705SSam Leffler ee->ee_obFor24 = (eeval >> 4) & 0x07;
123114779705SSam Leffler ee->ee_dbFor24 = eeval & 0x07;
123214779705SSam Leffler break;
123314779705SSam Leffler case headerInfo11G:
123414779705SSam Leffler ee->ee_obFor24g = (eeval >> 4) & 0x07;
123514779705SSam Leffler ee->ee_dbFor24g = eeval & 0x07;
123614779705SSam Leffler break;
123714779705SSam Leffler }
123814779705SSam Leffler
123914779705SSam Leffler if (i == headerInfo11A) {
124014779705SSam Leffler EEREAD(off++);
124114779705SSam Leffler ee->ee_ob3 |= (eeval >> 15) & 0x01;
124214779705SSam Leffler ee->ee_db3 = (eeval >> 12) & 0x07;
124314779705SSam Leffler ee->ee_ob2 = (eeval >> 9) & 0x07;
124414779705SSam Leffler ee->ee_db2 = (eeval >> 6) & 0x07;
124514779705SSam Leffler ee->ee_ob1 = (eeval >> 3) & 0x07;
124614779705SSam Leffler ee->ee_db1 = eeval & 0x07;
124714779705SSam Leffler }
124814779705SSam Leffler
124914779705SSam Leffler EEREAD(off++);
125014779705SSam Leffler ee->ee_txEndToXLNAOn[i] = (eeval >> 8) & 0xff;
125114779705SSam Leffler ee->ee_thresh62[i] = eeval & 0xff;
125214779705SSam Leffler
125314779705SSam Leffler EEREAD(off++);
125414779705SSam Leffler ee->ee_txEndToXPAOff[i] = (eeval >> 8) & 0xff;
125514779705SSam Leffler ee->ee_txFrameToXPAOn[i] = eeval & 0xff;
125614779705SSam Leffler
125714779705SSam Leffler EEREAD(off++);
125814779705SSam Leffler ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8) & 0xff);
125914779705SSam Leffler ee->ee_noiseFloorThresh[i] = eeval & 0xff;
126014779705SSam Leffler if (ee->ee_noiseFloorThresh[i] & 0x80) {
126114779705SSam Leffler ee->ee_noiseFloorThresh[i] = 0 -
126214779705SSam Leffler ((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1);
126314779705SSam Leffler }
126414779705SSam Leffler
126514779705SSam Leffler EEREAD(off++);
126614779705SSam Leffler ee->ee_xlnaGain[i] = (eeval >> 5) & 0xff;
126714779705SSam Leffler ee->ee_xgain[i] = (eeval >> 1) & 0x0f;
126814779705SSam Leffler ee->ee_xpd[i] = eeval & 0x01;
126914779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0) {
127014779705SSam Leffler switch (i) {
127114779705SSam Leffler case headerInfo11A:
127214779705SSam Leffler ee->ee_fixedBias5 = (eeval >> 13) & 0x1;
127314779705SSam Leffler break;
127414779705SSam Leffler case headerInfo11G:
127514779705SSam Leffler ee->ee_fixedBias2 = (eeval >> 13) & 0x1;
127614779705SSam Leffler break;
127714779705SSam Leffler }
127814779705SSam Leffler }
127914779705SSam Leffler
128014779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_3) {
128114779705SSam Leffler EEREAD(off++);
128214779705SSam Leffler ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F;
128314779705SSam Leffler switch (i) {
128414779705SSam Leffler case headerInfo11B:
128514779705SSam Leffler ee->ee_ob2GHz[0] = eeval & 0x7;
128614779705SSam Leffler ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
128714779705SSam Leffler break;
128814779705SSam Leffler case headerInfo11G:
128914779705SSam Leffler ee->ee_ob2GHz[1] = eeval & 0x7;
129014779705SSam Leffler ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
129114779705SSam Leffler break;
129214779705SSam Leffler case headerInfo11A:
129314779705SSam Leffler ee->ee_xrTargetPower5 = eeval & 0x3f;
129414779705SSam Leffler break;
129514779705SSam Leffler }
129614779705SSam Leffler }
129714779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER3_4) {
129814779705SSam Leffler ee->ee_gainI[i] = (eeval >> 13) & 0x07;
129914779705SSam Leffler
130014779705SSam Leffler EEREAD(off++);
130114779705SSam Leffler ee->ee_gainI[i] |= (eeval << 3) & 0x38;
130214779705SSam Leffler if (i == headerInfo11G) {
130314779705SSam Leffler ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF;
130414779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_6)
130514779705SSam Leffler ee->ee_scaledCh14FilterCckDelta =
130614779705SSam Leffler (eeval >> 11) & 0x1f;
130714779705SSam Leffler }
130814779705SSam Leffler if (i == headerInfo11A &&
130914779705SSam Leffler ee->ee_version >= AR_EEPROM_VER4_0) {
131014779705SSam Leffler ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f;
131114779705SSam Leffler ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f;
131214779705SSam Leffler }
131314779705SSam Leffler } else {
131414779705SSam Leffler ee->ee_gainI[i] = 10;
131514779705SSam Leffler ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT;
131614779705SSam Leffler }
131714779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0) {
131814779705SSam Leffler switch (i) {
131914779705SSam Leffler case headerInfo11B:
132014779705SSam Leffler EEREAD(off++);
132114779705SSam Leffler ee->ee_calPier11b[0] =
132214779705SSam Leffler fbin2freq_2p4(ee, eeval&0xff);
132314779705SSam Leffler ee->ee_calPier11b[1] =
132414779705SSam Leffler fbin2freq_2p4(ee, (eeval >> 8)&0xff);
132514779705SSam Leffler EEREAD(off++);
132614779705SSam Leffler ee->ee_calPier11b[2] =
132714779705SSam Leffler fbin2freq_2p4(ee, eeval&0xff);
132814779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_1)
132914779705SSam Leffler ee->ee_rxtxMargin[headerInfo11B] =
133014779705SSam Leffler (eeval >> 8) & 0x3f;
133114779705SSam Leffler break;
133214779705SSam Leffler case headerInfo11G:
133314779705SSam Leffler EEREAD(off++);
133414779705SSam Leffler ee->ee_calPier11g[0] =
133514779705SSam Leffler fbin2freq_2p4(ee, eeval & 0xff);
133614779705SSam Leffler ee->ee_calPier11g[1] =
133714779705SSam Leffler fbin2freq_2p4(ee, (eeval >> 8) & 0xff);
133814779705SSam Leffler
133914779705SSam Leffler EEREAD(off++);
134014779705SSam Leffler ee->ee_turbo2WMaxPower2 = eeval & 0x7F;
134114779705SSam Leffler ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f;
134214779705SSam Leffler
134314779705SSam Leffler EEREAD(off++);
134414779705SSam Leffler ee->ee_calPier11g[2] =
134514779705SSam Leffler fbin2freq_2p4(ee, eeval & 0xff);
134614779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_1)
134714779705SSam Leffler ee->ee_rxtxMargin[headerInfo11G] =
134814779705SSam Leffler (eeval >> 8) & 0x3f;
134914779705SSam Leffler
135014779705SSam Leffler EEREAD(off++);
135114779705SSam Leffler ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F;
135214779705SSam Leffler ee->ee_iqCalQ[1] = eeval & 0x1F;
135314779705SSam Leffler
135414779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_2) {
135514779705SSam Leffler EEREAD(off++);
135614779705SSam Leffler ee->ee_cckOfdmGainDelta =
135714779705SSam Leffler (uint8_t)(eeval & 0xFF);
135814779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER5_0) {
135914779705SSam Leffler ee->ee_switchSettlingTurbo[1] =
136014779705SSam Leffler (eeval >> 8) & 0x7f;
136114779705SSam Leffler ee->ee_txrxAttenTurbo[1] =
136214779705SSam Leffler (eeval >> 15) & 0x1;
136314779705SSam Leffler EEREAD(off++);
136414779705SSam Leffler ee->ee_txrxAttenTurbo[1] |=
136514779705SSam Leffler (eeval & 0x1F) << 1;
136614779705SSam Leffler ee->ee_rxtxMarginTurbo[1] =
136714779705SSam Leffler (eeval >> 5) & 0x3F;
136814779705SSam Leffler ee->ee_adcDesiredSizeTurbo[1] =
136914779705SSam Leffler (eeval >> 11) & 0x1F;
137014779705SSam Leffler EEREAD(off++);
137114779705SSam Leffler ee->ee_adcDesiredSizeTurbo[1] |=
137214779705SSam Leffler (eeval & 0x7) << 5;
137314779705SSam Leffler ee->ee_pgaDesiredSizeTurbo[1] =
137414779705SSam Leffler (eeval >> 3) & 0xFF;
137514779705SSam Leffler }
137614779705SSam Leffler }
137714779705SSam Leffler break;
137814779705SSam Leffler case headerInfo11A:
137914779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_1) {
138014779705SSam Leffler EEREAD(off++);
138114779705SSam Leffler ee->ee_rxtxMargin[headerInfo11A] =
138214779705SSam Leffler eeval & 0x3f;
138314779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER5_0) {
138414779705SSam Leffler ee->ee_switchSettlingTurbo[0] =
138514779705SSam Leffler (eeval >> 6) & 0x7f;
138614779705SSam Leffler ee->ee_txrxAttenTurbo[0] =
138714779705SSam Leffler (eeval >> 13) & 0x7;
138814779705SSam Leffler EEREAD(off++);
138914779705SSam Leffler ee->ee_txrxAttenTurbo[0] |=
139014779705SSam Leffler (eeval & 0x7) << 3;
139114779705SSam Leffler ee->ee_rxtxMarginTurbo[0] =
139214779705SSam Leffler (eeval >> 3) & 0x3F;
139314779705SSam Leffler ee->ee_adcDesiredSizeTurbo[0] =
139414779705SSam Leffler (eeval >> 9) & 0x7F;
139514779705SSam Leffler EEREAD(off++);
139614779705SSam Leffler ee->ee_adcDesiredSizeTurbo[0] |=
139714779705SSam Leffler (eeval & 0x1) << 7;
139814779705SSam Leffler ee->ee_pgaDesiredSizeTurbo[0] =
139914779705SSam Leffler (eeval >> 1) & 0xFF;
140014779705SSam Leffler }
140114779705SSam Leffler }
140214779705SSam Leffler break;
140314779705SSam Leffler }
140414779705SSam Leffler }
140514779705SSam Leffler }
140614779705SSam Leffler if (ee->ee_version < AR_EEPROM_VER3_3) {
140714779705SSam Leffler /* Version 3.1+ specific parameters */
140814779705SSam Leffler EEREAD(0xec);
140914779705SSam Leffler ee->ee_ob2GHz[0] = eeval & 0x7;
141014779705SSam Leffler ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
141114779705SSam Leffler
141214779705SSam Leffler EEREAD(0xed);
141314779705SSam Leffler ee->ee_ob2GHz[1] = eeval & 0x7;
141414779705SSam Leffler ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
141514779705SSam Leffler }
141614779705SSam Leffler
141714779705SSam Leffler /* Initialize corner cal (thermal tx gain adjust parameters) */
141814779705SSam Leffler ee->ee_cornerCal.clip = 4;
141914779705SSam Leffler ee->ee_cornerCal.pd90 = 1;
142014779705SSam Leffler ee->ee_cornerCal.pd84 = 1;
142114779705SSam Leffler ee->ee_cornerCal.gSel = 0;
142214779705SSam Leffler
142314779705SSam Leffler /*
142414779705SSam Leffler * Read the conformance test limit identifiers
142514779705SSam Leffler * These are used to match regulatory domain testing needs with
142614779705SSam Leffler * the RD-specific tests that have been calibrated in the EEPROM.
142714779705SSam Leffler */
142814779705SSam Leffler off = header[5];
142914779705SSam Leffler for (i = 0; i < ee->ee_numCtls; i += 2) {
143014779705SSam Leffler EEREAD(off++);
143114779705SSam Leffler ee->ee_ctl[i] = (eeval >> 8) & 0xff;
143214779705SSam Leffler ee->ee_ctl[i+1] = eeval & 0xff;
143314779705SSam Leffler }
143414779705SSam Leffler
143514779705SSam Leffler if (ee->ee_version < AR_EEPROM_VER5_3) {
143614779705SSam Leffler /* XXX only for 5413? */
143714779705SSam Leffler ee->ee_spurChans[0][1] = AR_SPUR_5413_1;
143814779705SSam Leffler ee->ee_spurChans[1][1] = AR_SPUR_5413_2;
143914779705SSam Leffler ee->ee_spurChans[2][1] = AR_NO_SPUR;
144014779705SSam Leffler ee->ee_spurChans[0][0] = AR_NO_SPUR;
144114779705SSam Leffler } else {
144214779705SSam Leffler /* Read spur mitigation data */
144314779705SSam Leffler for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
144414779705SSam Leffler EEREAD(off);
144514779705SSam Leffler ee->ee_spurChans[i][0] = eeval;
144614779705SSam Leffler EEREAD(off+AR_EEPROM_MODAL_SPURS);
144714779705SSam Leffler ee->ee_spurChans[i][1] = eeval;
144814779705SSam Leffler off++;
144914779705SSam Leffler }
145014779705SSam Leffler }
145114779705SSam Leffler
145214779705SSam Leffler /* for recent changes to NF scale */
145314779705SSam Leffler if (ee->ee_version <= AR_EEPROM_VER3_2) {
145414779705SSam Leffler ee->ee_noiseFloorThresh[headerInfo11A] = -54;
145514779705SSam Leffler ee->ee_noiseFloorThresh[headerInfo11B] = -1;
145614779705SSam Leffler ee->ee_noiseFloorThresh[headerInfo11G] = -1;
145714779705SSam Leffler }
145814779705SSam Leffler /* to override thresh62 for better 2.4 and 5 operation */
145914779705SSam Leffler if (ee->ee_version <= AR_EEPROM_VER3_2) {
146014779705SSam Leffler ee->ee_thresh62[headerInfo11A] = 15; /* 11A */
146114779705SSam Leffler ee->ee_thresh62[headerInfo11B] = 28; /* 11B */
146214779705SSam Leffler ee->ee_thresh62[headerInfo11G] = 28; /* 11G */
146314779705SSam Leffler }
146414779705SSam Leffler
146514779705SSam Leffler /* Check for regulatory capabilities */
146614779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0) {
146714779705SSam Leffler EEREAD(regCapOffsetPost4_0);
146814779705SSam Leffler } else {
146914779705SSam Leffler EEREAD(regCapOffsetPre4_0);
147014779705SSam Leffler }
147114779705SSam Leffler
147214779705SSam Leffler ee->ee_regCap = eeval;
147314779705SSam Leffler
147414779705SSam Leffler if (ee->ee_Amode == 0) {
147514779705SSam Leffler /* Check for valid Amode in upgraded h/w */
147614779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0) {
147714779705SSam Leffler ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0;
147814779705SSam Leffler } else {
147914779705SSam Leffler ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0;
148014779705SSam Leffler }
148114779705SSam Leffler }
148214779705SSam Leffler
148314779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER5_1)
148414779705SSam Leffler EEREAD(AR_EEPROM_CAPABILITIES_OFFSET);
148514779705SSam Leffler else
148614779705SSam Leffler eeval = 0;
148714779705SSam Leffler ee->ee_opCap = eeval;
148814779705SSam Leffler
148914779705SSam Leffler EEREAD(AR_EEPROM_REG_DOMAIN);
149014779705SSam Leffler ee->ee_regdomain = eeval;
149114779705SSam Leffler
149214779705SSam Leffler return AH_TRUE;
149314779705SSam Leffler #undef EEREAD
149414779705SSam Leffler }
149514779705SSam Leffler
149614779705SSam Leffler /*
149714779705SSam Leffler * Now verify and copy EEPROM contents into the allocated space
149814779705SSam Leffler */
149914779705SSam Leffler static HAL_BOOL
legacyEepromReadContents(struct ath_hal * ah,HAL_EEPROM * ee)150014779705SSam Leffler legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee)
150114779705SSam Leffler {
150214779705SSam Leffler /* Read the header information here */
150314779705SSam Leffler if (!readHeaderInfo(ah, ee))
150414779705SSam Leffler return AH_FALSE;
150514779705SSam Leffler #if 0
150614779705SSam Leffler /* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */
150714779705SSam Leffler if (IS_5112(ah) && !ee->ee_eepMap) {
150814779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
150914779705SSam Leffler "%s: 5112 devices must have EEPROM 4.0 with the "
151014779705SSam Leffler "EEP_MAP set\n", __func__);
151114779705SSam Leffler return AH_FALSE;
151214779705SSam Leffler }
151314779705SSam Leffler #endif
151414779705SSam Leffler /*
151514779705SSam Leffler * Group 1: frequency pier locations readback
151614779705SSam Leffler * check that the structure has been populated
151714779705SSam Leffler * with enough space to hold the channels
151814779705SSam Leffler *
151914779705SSam Leffler * NOTE: Group 1 contains the 5 GHz channel numbers
152014779705SSam Leffler * that have dBm->pcdac calibrated information.
152114779705SSam Leffler */
152214779705SSam Leffler if (!readEepromFreqPierInfo(ah, ee))
152314779705SSam Leffler return AH_FALSE;
152414779705SSam Leffler
152514779705SSam Leffler /*
152614779705SSam Leffler * Group 2: readback data for all frequency piers
152714779705SSam Leffler *
152814779705SSam Leffler * NOTE: Group 2 contains the raw power calibration
152914779705SSam Leffler * information for each of the channels that we
153014779705SSam Leffler * recorded above.
153114779705SSam Leffler */
153214779705SSam Leffler if (!readEepromRawPowerCalInfo(ah, ee))
153314779705SSam Leffler return AH_FALSE;
153414779705SSam Leffler
153514779705SSam Leffler /*
153614779705SSam Leffler * Group 5: target power values per rate
153714779705SSam Leffler *
153814779705SSam Leffler * NOTE: Group 5 contains the recorded maximum power
153914779705SSam Leffler * in dB that can be attained for the given rate.
154014779705SSam Leffler */
154114779705SSam Leffler /* Read the power per rate info for test channels */
154214779705SSam Leffler if (!readEepromTargetPowerCalInfo(ah, ee))
154314779705SSam Leffler return AH_FALSE;
154414779705SSam Leffler
154514779705SSam Leffler /*
154614779705SSam Leffler * Group 8: Conformance Test Limits information
154714779705SSam Leffler *
154814779705SSam Leffler * NOTE: Group 8 contains the values to limit the
154914779705SSam Leffler * maximum transmit power value based on any
155014779705SSam Leffler * band edge violations.
155114779705SSam Leffler */
155214779705SSam Leffler /* Read the RD edge power limits */
155314779705SSam Leffler return readEepromCTLInfo(ah, ee);
155414779705SSam Leffler }
155514779705SSam Leffler
155614779705SSam Leffler static HAL_STATUS
legacyEepromGet(struct ath_hal * ah,int param,void * val)155714779705SSam Leffler legacyEepromGet(struct ath_hal *ah, int param, void *val)
155814779705SSam Leffler {
155914779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
156014779705SSam Leffler uint8_t *macaddr;
156114779705SSam Leffler uint16_t eeval;
156214779705SSam Leffler uint32_t sum;
156314779705SSam Leffler int i;
156414779705SSam Leffler
156514779705SSam Leffler switch (param) {
156614779705SSam Leffler case AR_EEP_OPCAP:
156714779705SSam Leffler *(uint16_t *) val = ee->ee_opCap;
156814779705SSam Leffler return HAL_OK;
156914779705SSam Leffler case AR_EEP_REGDMN_0:
157014779705SSam Leffler *(uint16_t *) val = ee->ee_regdomain;
157114779705SSam Leffler return HAL_OK;
157214779705SSam Leffler case AR_EEP_RFSILENT:
157314779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval))
157414779705SSam Leffler return HAL_EEREAD;
157514779705SSam Leffler *(uint16_t *) val = eeval;
157614779705SSam Leffler return HAL_OK;
157714779705SSam Leffler case AR_EEP_MACADDR:
157814779705SSam Leffler sum = 0;
157914779705SSam Leffler macaddr = val;
158014779705SSam Leffler for (i = 0; i < 3; i++) {
158114779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) {
158214779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
158314779705SSam Leffler "%s: cannot read EEPROM location %u\n",
158414779705SSam Leffler __func__, i);
158514779705SSam Leffler return HAL_EEREAD;
158614779705SSam Leffler }
158714779705SSam Leffler sum += eeval;
158814779705SSam Leffler macaddr[2*i] = eeval >> 8;
158914779705SSam Leffler macaddr[2*i + 1] = eeval & 0xff;
159014779705SSam Leffler }
159114779705SSam Leffler if (sum == 0 || sum == 0xffff*3) {
159214779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
159314779705SSam Leffler "%s: mac address read failed: %s\n", __func__,
159414779705SSam Leffler ath_hal_ether_sprintf(macaddr));
159514779705SSam Leffler return HAL_EEBADMAC;
159614779705SSam Leffler }
159714779705SSam Leffler return HAL_OK;
159814779705SSam Leffler case AR_EEP_RFKILL:
159914779705SSam Leffler HALASSERT(val == AH_NULL);
160014779705SSam Leffler return ee->ee_rfKill ? HAL_OK : HAL_EIO;
160114779705SSam Leffler case AR_EEP_AMODE:
160214779705SSam Leffler HALASSERT(val == AH_NULL);
160314779705SSam Leffler return ee->ee_Amode ? HAL_OK : HAL_EIO;
160414779705SSam Leffler case AR_EEP_BMODE:
160514779705SSam Leffler HALASSERT(val == AH_NULL);
160614779705SSam Leffler return ee->ee_Bmode ? HAL_OK : HAL_EIO;
160714779705SSam Leffler case AR_EEP_GMODE:
160814779705SSam Leffler HALASSERT(val == AH_NULL);
160914779705SSam Leffler return ee->ee_Gmode ? HAL_OK : HAL_EIO;
161014779705SSam Leffler case AR_EEP_TURBO5DISABLE:
161114779705SSam Leffler HALASSERT(val == AH_NULL);
161214779705SSam Leffler return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO;
161314779705SSam Leffler case AR_EEP_TURBO2DISABLE:
161414779705SSam Leffler HALASSERT(val == AH_NULL);
161514779705SSam Leffler return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO;
161614779705SSam Leffler case AR_EEP_ISTALON: /* Talon detect */
161714779705SSam Leffler HALASSERT(val == AH_NULL);
161814779705SSam Leffler return (ee->ee_version >= AR_EEPROM_VER5_4 &&
161914779705SSam Leffler ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ?
162014779705SSam Leffler HAL_OK : HAL_EIO;
162114779705SSam Leffler case AR_EEP_32KHZCRYSTAL:
162214779705SSam Leffler HALASSERT(val == AH_NULL);
162314779705SSam Leffler return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO;
162414779705SSam Leffler case AR_EEP_COMPRESS:
162514779705SSam Leffler HALASSERT(val == AH_NULL);
162614779705SSam Leffler return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ?
162714779705SSam Leffler HAL_OK : HAL_EIO;
162814779705SSam Leffler case AR_EEP_FASTFRAME:
162914779705SSam Leffler HALASSERT(val == AH_NULL);
163014779705SSam Leffler return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ?
163114779705SSam Leffler HAL_OK : HAL_EIO;
163214779705SSam Leffler case AR_EEP_AES:
163314779705SSam Leffler HALASSERT(val == AH_NULL);
163414779705SSam Leffler return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ?
163514779705SSam Leffler HAL_OK : HAL_EIO;
163614779705SSam Leffler case AR_EEP_BURST:
163714779705SSam Leffler HALASSERT(val == AH_NULL);
163814779705SSam Leffler return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ?
163914779705SSam Leffler HAL_OK : HAL_EIO;
164014779705SSam Leffler case AR_EEP_MAXQCU:
164114779705SSam Leffler if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) {
164214779705SSam Leffler *(uint16_t *) val =
164314779705SSam Leffler MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU);
164414779705SSam Leffler return HAL_OK;
164514779705SSam Leffler } else
164614779705SSam Leffler return HAL_EIO;
164714779705SSam Leffler case AR_EEP_KCENTRIES:
164814779705SSam Leffler if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) {
164914779705SSam Leffler *(uint16_t *) val =
165014779705SSam Leffler 1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES);
165114779705SSam Leffler return HAL_OK;
165214779705SSam Leffler } else
165314779705SSam Leffler return HAL_EIO;
165414779705SSam Leffler case AR_EEP_ANTGAINMAX_5:
165514779705SSam Leffler *(int8_t *) val = ee->ee_antennaGainMax[0];
165614779705SSam Leffler return HAL_OK;
165714779705SSam Leffler case AR_EEP_ANTGAINMAX_2:
165814779705SSam Leffler *(int8_t *) val = ee->ee_antennaGainMax[1];
165914779705SSam Leffler return HAL_OK;
166014779705SSam Leffler case AR_EEP_WRITEPROTECT:
166114779705SSam Leffler HALASSERT(val == AH_NULL);
166214779705SSam Leffler return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ?
166314779705SSam Leffler HAL_OK : HAL_EIO;
166414779705SSam Leffler }
166514779705SSam Leffler return HAL_EINVAL;
166614779705SSam Leffler }
166714779705SSam Leffler
166892ffeb63SAdrian Chadd static HAL_STATUS
legacyEepromSet(struct ath_hal * ah,int param,int v)166914779705SSam Leffler legacyEepromSet(struct ath_hal *ah, int param, int v)
167014779705SSam Leffler {
167114779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
167214779705SSam Leffler
167314779705SSam Leffler switch (param) {
167414779705SSam Leffler case AR_EEP_AMODE:
167514779705SSam Leffler ee->ee_Amode = v;
167614779705SSam Leffler return HAL_OK;
167714779705SSam Leffler case AR_EEP_BMODE:
167814779705SSam Leffler ee->ee_Bmode = v;
167914779705SSam Leffler return HAL_OK;
168014779705SSam Leffler case AR_EEP_GMODE:
168114779705SSam Leffler ee->ee_Gmode = v;
168214779705SSam Leffler return HAL_OK;
168314779705SSam Leffler case AR_EEP_TURBO5DISABLE:
168414779705SSam Leffler ee->ee_turbo5Disable = v;
168514779705SSam Leffler return HAL_OK;
168614779705SSam Leffler case AR_EEP_TURBO2DISABLE:
168714779705SSam Leffler ee->ee_turbo2Disable = v;
168814779705SSam Leffler return HAL_OK;
168914779705SSam Leffler case AR_EEP_COMPRESS:
169014779705SSam Leffler if (v)
169114779705SSam Leffler ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS;
169214779705SSam Leffler else
169314779705SSam Leffler ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS;
169414779705SSam Leffler return HAL_OK;
169514779705SSam Leffler case AR_EEP_FASTFRAME:
169614779705SSam Leffler if (v)
169714779705SSam Leffler ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS;
169814779705SSam Leffler else
169914779705SSam Leffler ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS;
170014779705SSam Leffler return HAL_OK;
170114779705SSam Leffler case AR_EEP_AES:
170214779705SSam Leffler if (v)
170314779705SSam Leffler ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS;
170414779705SSam Leffler else
170514779705SSam Leffler ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS;
170614779705SSam Leffler return HAL_OK;
170714779705SSam Leffler case AR_EEP_BURST:
170814779705SSam Leffler if (v)
170914779705SSam Leffler ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS;
171014779705SSam Leffler else
171114779705SSam Leffler ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS;
171214779705SSam Leffler return HAL_OK;
171314779705SSam Leffler }
171414779705SSam Leffler return HAL_EINVAL;
171514779705SSam Leffler }
171614779705SSam Leffler
171714779705SSam Leffler static HAL_BOOL
legacyEepromDiag(struct ath_hal * ah,int request,const void * args,uint32_t argsize,void ** result,uint32_t * resultsize)171814779705SSam Leffler legacyEepromDiag(struct ath_hal *ah, int request,
171914779705SSam Leffler const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
172014779705SSam Leffler {
172114779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
172214779705SSam Leffler const EEPROM_POWER_EXPN_5112 *pe;
172314779705SSam Leffler
172414779705SSam Leffler switch (request) {
172514779705SSam Leffler case HAL_DIAG_EEPROM:
172614779705SSam Leffler *result = ee;
172714779705SSam Leffler *resultsize = sizeof(*ee);
172814779705SSam Leffler return AH_TRUE;
172914779705SSam Leffler case HAL_DIAG_EEPROM_EXP_11A:
173014779705SSam Leffler case HAL_DIAG_EEPROM_EXP_11B:
173114779705SSam Leffler case HAL_DIAG_EEPROM_EXP_11G:
173214779705SSam Leffler pe = &ee->ee_modePowerArray5112[
173314779705SSam Leffler request - HAL_DIAG_EEPROM_EXP_11A];
173414779705SSam Leffler *result = pe->pChannels;
173514779705SSam Leffler *resultsize = (*result == AH_NULL) ? 0 :
173614779705SSam Leffler roundup(sizeof(uint16_t) * pe->numChannels,
173714779705SSam Leffler sizeof(uint32_t)) +
173814779705SSam Leffler sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels;
173914779705SSam Leffler return AH_TRUE;
174014779705SSam Leffler }
174114779705SSam Leffler return AH_FALSE;
174214779705SSam Leffler }
174314779705SSam Leffler
174414779705SSam Leffler static uint16_t
legacyEepromGetSpurChan(struct ath_hal * ah,int ix,HAL_BOOL is2GHz)174514779705SSam Leffler legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
174614779705SSam Leffler {
174714779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
174814779705SSam Leffler
174914779705SSam Leffler HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS);
175014779705SSam Leffler return ee->ee_spurChans[ix][is2GHz];
175114779705SSam Leffler }
175214779705SSam Leffler
175314779705SSam Leffler /*
175414779705SSam Leffler * Reclaim any EEPROM-related storage.
175514779705SSam Leffler */
175614779705SSam Leffler static void
legacyEepromDetach(struct ath_hal * ah)175714779705SSam Leffler legacyEepromDetach(struct ath_hal *ah)
175814779705SSam Leffler {
175914779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
176014779705SSam Leffler
176114779705SSam Leffler if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
1762d5c613bdSSam Leffler freeEepromRawPowerCalInfo5112(ah, ee);
176314779705SSam Leffler ath_hal_free(ee);
176414779705SSam Leffler AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
176514779705SSam Leffler }
176614779705SSam Leffler
176714779705SSam Leffler /*
176814779705SSam Leffler * These are not valid 2.4 channels, either we change 'em
176914779705SSam Leffler * or we need to change the coding to accept them.
177014779705SSam Leffler */
177114779705SSam Leffler static const uint16_t channels11b[] = { 2412, 2447, 2484 };
177214779705SSam Leffler static const uint16_t channels11g[] = { 2312, 2412, 2484 };
177314779705SSam Leffler
177414779705SSam Leffler HAL_STATUS
ath_hal_legacyEepromAttach(struct ath_hal * ah)177514779705SSam Leffler ath_hal_legacyEepromAttach(struct ath_hal *ah)
177614779705SSam Leffler {
177714779705SSam Leffler HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
177814779705SSam Leffler uint32_t sum, eepMax;
177914779705SSam Leffler uint16_t eeversion, eeprotect, eeval;
178014779705SSam Leffler u_int i;
178114779705SSam Leffler
178214779705SSam Leffler HALASSERT(ee == AH_NULL);
178314779705SSam Leffler
178414779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) {
178514779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
178614779705SSam Leffler "%s: unable to read EEPROM version\n", __func__);
178714779705SSam Leffler return HAL_EEREAD;
178814779705SSam Leffler }
178914779705SSam Leffler if (eeversion < AR_EEPROM_VER3) {
179014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version "
179114779705SSam Leffler "%u (0x%x) found\n", __func__, eeversion, eeversion);
179214779705SSam Leffler return HAL_EEVERSION;
179314779705SSam Leffler }
179414779705SSam Leffler
179514779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) {
179614779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection "
179714779705SSam Leffler "bits; read locked?\n", __func__);
179814779705SSam Leffler return HAL_EEREAD;
179914779705SSam Leffler }
180014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect);
180114779705SSam Leffler /* XXX check proper access before continuing */
180214779705SSam Leffler
180314779705SSam Leffler /*
180414779705SSam Leffler * Read the Atheros EEPROM entries and calculate the checksum.
180514779705SSam Leffler */
180614779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) {
180714779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
180814779705SSam Leffler "%s: cannot read EEPROM upper size\n" , __func__);
180914779705SSam Leffler return HAL_EEREAD;
181014779705SSam Leffler }
181114779705SSam Leffler if (eeval != 0) {
181214779705SSam Leffler eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) <<
181314779705SSam Leffler AR_EEPROM_SIZE_ENDLOC_SHIFT;
181414779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) {
181514779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY,
181614779705SSam Leffler "%s: cannot read EEPROM lower size\n" , __func__);
181714779705SSam Leffler return HAL_EEREAD;
181814779705SSam Leffler }
181914779705SSam Leffler eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE;
182014779705SSam Leffler } else
182114779705SSam Leffler eepMax = AR_EEPROM_ATHEROS_MAX;
182214779705SSam Leffler sum = 0;
182314779705SSam Leffler for (i = 0; i < eepMax; i++) {
182414779705SSam Leffler if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) {
182514779705SSam Leffler return HAL_EEREAD;
182614779705SSam Leffler }
182714779705SSam Leffler sum ^= eeval;
182814779705SSam Leffler }
182914779705SSam Leffler if (sum != 0xffff) {
183014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
183114779705SSam Leffler __func__, sum);
183214779705SSam Leffler return HAL_EEBADSUM;
183314779705SSam Leffler }
183414779705SSam Leffler
183514779705SSam Leffler ee = ath_hal_malloc(sizeof(HAL_EEPROM));
183614779705SSam Leffler if (ee == AH_NULL) {
183714779705SSam Leffler /* XXX message */
183814779705SSam Leffler return HAL_ENOMEM;
183914779705SSam Leffler }
184014779705SSam Leffler
184114779705SSam Leffler ee->ee_protect = eeprotect;
184214779705SSam Leffler ee->ee_version = eeversion;
184314779705SSam Leffler
184414779705SSam Leffler ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS;
184514779705SSam Leffler ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS;
184614779705SSam Leffler
184714779705SSam Leffler for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++)
184814779705SSam Leffler ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES;
184914779705SSam Leffler
185014779705SSam Leffler /* the channel list for 2.4 is fixed, fill this in here */
185114779705SSam Leffler for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) {
185214779705SSam Leffler ee->ee_channels11b[i] = channels11b[i];
185314779705SSam Leffler /* XXX 5211 requires a hack though we don't support 11g */
185414779705SSam Leffler if (ah->ah_magic == 0x19570405)
185514779705SSam Leffler ee->ee_channels11g[i] = channels11b[i];
185614779705SSam Leffler else
185714779705SSam Leffler ee->ee_channels11g[i] = channels11g[i];
185814779705SSam Leffler ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES;
185914779705SSam Leffler ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES;
186014779705SSam Leffler }
186114779705SSam Leffler
186214779705SSam Leffler if (!legacyEepromReadContents(ah, ee)) {
186314779705SSam Leffler /* XXX message */
186414779705SSam Leffler ath_hal_free(ee);
186514779705SSam Leffler return HAL_EEREAD; /* XXX */
186614779705SSam Leffler }
186714779705SSam Leffler
186814779705SSam Leffler AH_PRIVATE(ah)->ah_eeprom = ee;
186914779705SSam Leffler AH_PRIVATE(ah)->ah_eeversion = eeversion;
187014779705SSam Leffler AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach;
187114779705SSam Leffler AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet;
187214779705SSam Leffler AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet;
187314779705SSam Leffler AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan;
187414779705SSam Leffler AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag;
187514779705SSam Leffler return HAL_OK;
187614779705SSam Leffler }
1877