Deleted Added
full compact
ar5416_reset.c (219218) ar5416_reset.c (219393)
1/*
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
1/*
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c 219218 2011-03-03 08:38:31Z adrian $
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c 219393 2011-03-08 06:59:59Z adrian $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24
25#include "ah_eeprom_v14.h"

--- 30 unchanged lines hidden (view full) ---

56static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
57static void ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan);
58static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah,
59 struct ar5416eeprom *pEepData,
60 const struct ieee80211_channel *chan, int16_t *ratesArray,
61 uint16_t cfgCtl, uint16_t AntennaReduction,
62 uint16_t twiceMaxRegulatoryPower,
63 uint16_t powerLimit);
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24
25#include "ah_eeprom_v14.h"

--- 30 unchanged lines hidden (view full) ---

56static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
57static void ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan);
58static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah,
59 struct ar5416eeprom *pEepData,
60 const struct ieee80211_channel *chan, int16_t *ratesArray,
61 uint16_t cfgCtl, uint16_t AntennaReduction,
62 uint16_t twiceMaxRegulatoryPower,
63 uint16_t powerLimit);
64static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah,
65 struct ar5416eeprom *pEepData,
66 const struct ieee80211_channel *chan,
67 int16_t *pTxPowerIndexOffset);
68static uint16_t ar5416GetMaxEdgePower(uint16_t freq,
69 CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);
70
71static int16_t interpolate(uint16_t target, uint16_t srcLeft,
72 uint16_t srcRight, int16_t targetLeft, int16_t targetRight);
73static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan);
64static uint16_t ar5416GetMaxEdgePower(uint16_t freq,
65 CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);
66
67static int16_t interpolate(uint16_t target, uint16_t srcLeft,
68 uint16_t srcRight, int16_t targetLeft, int16_t targetRight);
69static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan);
74static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
75 const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ *pRawDataSet,
76 uint8_t * bChans, uint16_t availPiers,
77 uint16_t tPdGainOverlap, int16_t *pMinCalPower,
78 uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues,
79 uint16_t numXpdGains);
80static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList,
81 uint16_t listSize, uint16_t *indexL, uint16_t *indexR);
82static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax,
83 uint8_t *pPwrList, uint8_t *pVpdList,
84 uint16_t numIntercepts, uint8_t *pRetVpdList);
85
86/*
87 * Places the device in and out of reset and then places sane
88 * values in the registers based on EEPROM config, initialization
89 * vectors (as determined by the mode), and station configuration

--- 129 unchanged lines hidden (view full) ---

219 * with enabling the TX/RX radio chains.
220 */
221 ar5416UpdateChainMasks(ah, IEEE80211_IS_CHAN_HT(chan));
222 /*
223 * This routine swaps the analog chains - it should be done
224 * before any radio register twiddling is done.
225 */
226 ar5416InitChainMasks(ah);
70static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax,
71 uint8_t *pPwrList, uint8_t *pVpdList,
72 uint16_t numIntercepts, uint8_t *pRetVpdList);
73
74/*
75 * Places the device in and out of reset and then places sane
76 * values in the registers based on EEPROM config, initialization
77 * vectors (as determined by the mode), and station configuration

--- 129 unchanged lines hidden (view full) ---

207 * with enabling the TX/RX radio chains.
208 */
209 ar5416UpdateChainMasks(ah, IEEE80211_IS_CHAN_HT(chan));
210 /*
211 * This routine swaps the analog chains - it should be done
212 * before any radio register twiddling is done.
213 */
214 ar5416InitChainMasks(ah);
215 AH5416(ah)->ah_olcInit(ah);
227
228 /* Setup the transmit power values. */
229 if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) {
230 HALDEBUG(ah, HAL_DEBUG_ANY,
231 "%s: error init'ing transmit power\n", __func__);
232 FAIL(HAL_EIO);
233 }
234

--- 608 unchanged lines hidden (view full) ---

843 &ratesArray[0],cfgCtl,
844 twiceAntennaReduction,
845 twiceMaxRegulatoryPower, powerLimit)) {
846 HALDEBUG(ah, HAL_DEBUG_ANY,
847 "%s: unable to set tx power per rate table\n", __func__);
848 return AH_FALSE;
849 }
850
216
217 /* Setup the transmit power values. */
218 if (!ah->ah_setTxPower(ah, chan, rfXpdGain)) {
219 HALDEBUG(ah, HAL_DEBUG_ANY,
220 "%s: error init'ing transmit power\n", __func__);
221 FAIL(HAL_EIO);
222 }
223

--- 608 unchanged lines hidden (view full) ---

832 &ratesArray[0],cfgCtl,
833 twiceAntennaReduction,
834 twiceMaxRegulatoryPower, powerLimit)) {
835 HALDEBUG(ah, HAL_DEBUG_ANY,
836 "%s: unable to set tx power per rate table\n", __func__);
837 return AH_FALSE;
838 }
839
851 if (!ar5416SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) {
840 if (!AH5416(ah)->ah_setPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) {
852 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
853 __func__);
854 return AH_FALSE;
855 }
856
857 maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
858
859 if (IEEE80211_IS_CHAN_2GHZ(chan)) {

--- 14 unchanged lines hidden (view full) ---

874 */
875 for (i = 0; i < N(ratesArray); i++) {
876 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
877 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
878 ratesArray[i] = AR5416_MAX_RATE_POWER;
879 }
880
881#ifdef AH_EEPROM_DUMP
841 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
842 __func__);
843 return AH_FALSE;
844 }
845
846 maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
847
848 if (IEEE80211_IS_CHAN_2GHZ(chan)) {

--- 14 unchanged lines hidden (view full) ---

863 */
864 for (i = 0; i < N(ratesArray); i++) {
865 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
866 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
867 ratesArray[i] = AR5416_MAX_RATE_POWER;
868 }
869
870#ifdef AH_EEPROM_DUMP
871 /*
872 * Dump the rate array whilst it represents the intended dBm*2
873 * values versus what's being adjusted before being programmed
874 * in. Keep this in mind if you code up this function and enable
875 * this debugging; the values won't necessarily be what's being
876 * programmed into the hardware.
877 */
882 ar5416PrintPowerPerRate(ah, ratesArray);
883#endif
884
878 ar5416PrintPowerPerRate(ah, ratesArray);
879#endif
880
881 /*
882 * Merlin and later have a power offset, so subtract
883 * pwr_table_offset * 2 from each value. The default
884 * power offset is -5 dBm - ie, a register value of 0
885 * equates to a TX power of -5 dBm.
886 */
887 if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
888 int8_t pwr_table_offset;
889
890 (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET,
891 &pwr_table_offset);
892 /* Underflow power gets clamped at raw value 0 */
893 /* Overflow power gets camped at AR5416_MAX_RATE_POWER */
894 for (i = 0; i < N(ratesArray); i++) {
895 /*
896 * + pwr_table_offset is in dBm
897 * + ratesArray is in 1/2 dBm
898 */
899 ratesArray[i] -= (pwr_table_offset * 2);
900 if (ratesArray[i] < 0)
901 ratesArray[i] = 0;
902 else if (ratesArray[i] > AR5416_MAX_RATE_POWER)
903 ratesArray[i] = AR5416_MAX_RATE_POWER;
904 }
905 }
906
907 /*
908 * Adjust rates for OLC where needed
909 *
910 * The following CCK rates need adjusting when doing 2.4ghz
911 * CCK transmission.
912 *
913 * + rate2s, rate2l, rate1l, rate11s, rate11l, rate5_5s, rate5_5l
914 * + rateExtCck, rateDupCck
915 *
916 * They're adjusted here regardless. The hardware then gets
917 * programmed as needed. 5GHz operation doesn't program in CCK
918 * rates for legacy mode but they seem to be initialised for
919 * HT40 regardless of channel type.
920 */
921 if (AR_SREV_MERLIN_20_OR_LATER(ah) &&
922 ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
923 int adj[] = {
924 rate2s, rate2l, rate1l, rate11s, rate11l,
925 rate5_5s, rate5_5l, rateExtCck, rateDupCck
926 };
927 int cck_ofdm_delta = 2;
928 int i;
929 for (i = 0; i < N(adj); i++) {
930 ratesArray[i] -= cck_ofdm_delta;
931 if (ratesArray[i] < 0)
932 ratesArray[i] = 0;
933 }
934 }
935
885 /* Write the OFDM power per rate set */
886 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
887 POW_SM(ratesArray[rate18mb], 24)
888 | POW_SM(ratesArray[rate12mb], 16)
889 | POW_SM(ratesArray[rate9mb], 8)
890 | POW_SM(ratesArray[rate6mb], 0)
891 );
892 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,

--- 399 unchanged lines hidden (view full) ---

1292 OS_REG_WRITE(ah,
1293 AR_PHY_GAIN_2GHZ + regChainOffset,
1294 (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1295 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
1296 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
1297 }
1298}
1299
936 /* Write the OFDM power per rate set */
937 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
938 POW_SM(ratesArray[rate18mb], 24)
939 | POW_SM(ratesArray[rate12mb], 16)
940 | POW_SM(ratesArray[rate9mb], 8)
941 | POW_SM(ratesArray[rate6mb], 0)
942 );
943 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,

--- 399 unchanged lines hidden (view full) ---

1343 OS_REG_WRITE(ah,
1344 AR_PHY_GAIN_2GHZ + regChainOffset,
1345 (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1346 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
1347 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
1348 }
1349}
1350
1351/*
1352 * Get the register chain offset for the given chain.
1353 *
1354 * Take into account the register chain swapping with AR5416 v2.0.
1355 *
1356 * XXX make sure that the reg chain swapping is only done for
1357 * XXX AR5416 v2.0 or greater, and not later chips?
1358 */
1359int
1360ar5416GetRegChainOffset(struct ath_hal *ah, int i)
1361{
1362 int regChainOffset;
1300
1363
1364 if (AR_SREV_OWL_20_OR_LATER(ah) &&
1365 (AH5416(ah)->ah_rx_chainmask == 0x5 ||
1366 AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) {
1367 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
1368 * only chains 0 and 2 populated
1369 */
1370 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1371 } else {
1372 regChainOffset = i * 0x1000;
1373 }
1301
1374
1375 return regChainOffset;
1376}
1377
1302/*
1303 * Read EEPROM header info and program the device for correct operation
1304 * given the channel value.
1305 */
1306HAL_BOOL
1307ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
1308{
1309 const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;

--- 8 unchanged lines hidden (view full) ---

1318 /* NB: workaround for eeprom versions <= 14.2 */
1319 txRxAttenLocal = IEEE80211_IS_CHAN_2GHZ(chan) ? 23 : 44;
1320
1321 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
1322 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1323 if (AR_SREV_MERLIN(ah)) {
1324 if (i >= 2) break;
1325 }
1378/*
1379 * Read EEPROM header info and program the device for correct operation
1380 * given the channel value.
1381 */
1382HAL_BOOL
1383ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
1384{
1385 const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;

--- 8 unchanged lines hidden (view full) ---

1394 /* NB: workaround for eeprom versions <= 14.2 */
1395 txRxAttenLocal = IEEE80211_IS_CHAN_2GHZ(chan) ? 23 : 44;
1396
1397 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
1398 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1399 if (AR_SREV_MERLIN(ah)) {
1400 if (i >= 2) break;
1401 }
1326 if (AR_SREV_OWL_20_OR_LATER(ah) &&
1327 (AH5416(ah)->ah_rx_chainmask == 0x5 ||
1328 AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) {
1329 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
1330 * only chains 0 and 2 populated
1331 */
1332 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1333 } else {
1334 regChainOffset = i * 0x1000;
1335 }
1402 regChainOffset = ar5416GetRegChainOffset(ah, i);
1336
1337 OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]);
1338
1339 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset,
1340 (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) &
1341 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1342 SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1343 SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));

--- 508 unchanged lines hidden (view full) ---

1852
1853 for (i = 0; i < numRates; i++) {
1854 pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
1855 powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
1856 }
1857 }
1858}
1859
1403
1404 OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]);
1405
1406 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset,
1407 (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) &
1408 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1409 SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1410 SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));

--- 508 unchanged lines hidden (view full) ---

1919
1920 for (i = 0; i < numRates; i++) {
1921 pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
1922 powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
1923 }
1924 }
1925}
1926
1927/*
1928 * Set the gain boundaries for the given radio chain.
1929 *
1930 * The gain boundaries tell the hardware at what point in the
1931 * PDADC array to "switch over" from one PD gain setting
1932 * to another. There's also a gain overlap between two
1933 * PDADC array gain curves where there's valid PD values
1934 * for 2 gain settings.
1935 *
1936 * The hardware uses the gain overlap and gain boundaries
1937 * to determine which gain curve to use for the given
1938 * target TX power.
1939 */
1940void
1941ar5416SetGainBoundariesClosedLoop(struct ath_hal *ah, int regChainOffset,
1942 uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[])
1943{
1944 OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
1945 SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
1946 SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
1947 SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
1948 SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
1949 SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
1950}
1951
1952/*
1953 * Get the gain values and the number of gain levels given
1954 * in xpdMask.
1955 *
1956 * The EEPROM xpdMask determines which power detector gain
1957 * levels were used during calibration. Each of these mask
1958 * bits maps to a fixed gain level in hardware.
1959 */
1960uint16_t
1961ar5416GetXpdGainValues(struct ath_hal *ah, uint16_t xpdMask,
1962 uint16_t xpdGainValues[])
1963{
1964 int i;
1965 uint16_t numXpdGain = 0;
1966
1967 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
1968 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
1969 if (numXpdGain >= AR5416_NUM_PD_GAINS) {
1970 HALASSERT(0);
1971 break;
1972 }
1973 xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
1974 numXpdGain++;
1975 }
1976 }
1977 return numXpdGain;
1978}
1979
1980/*
1981 * Write the detector gain and biases.
1982 *
1983 * There are four power detector gain levels. The xpdMask in the EEPROM
1984 * determines which power detector gain levels have TX power calibration
1985 * data associated with them. This function writes the number of
1986 * PD gain levels and their values into the hardware.
1987 *
1988 * This is valid for all TX chains - the calibration data itself however
1989 * will likely differ per-chain.
1990 */
1991void
1992ar5416WriteDetectorGainBiases(struct ath_hal *ah, uint16_t numXpdGain,
1993 uint16_t xpdGainValues[])
1994{
1995 OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) &
1996 ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 |
1997 AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) |
1998 SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) |
1999 SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) |
2000 SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) |
2001 SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3));
2002}
2003
2004/*
2005 * Write the PDADC array to the given chain offset.
2006 *
2007 * The 32 PDADC registers are written without any care about
2008 * their contents - so if various chips treat values as "special",
2009 * this routine will not care.
2010 */
2011void
2012ar5416WritePdadcValues(struct ath_hal *ah, int regChainOffset,
2013 uint8_t pdadcValues[])
2014{
2015 int regOffset;
2016 int j;
2017 int reg32;
2018
2019 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
2020
2021 for (j = 0; j < 32; j++) {
2022 reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) |
2023 ((pdadcValues[4*j + 1] & 0xFF) << 8) |
2024 ((pdadcValues[4*j + 2] & 0xFF) << 16) |
2025 ((pdadcValues[4*j + 3] & 0xFF) << 24) ;
2026 OS_REG_WRITE(ah, regOffset, reg32);
2027#ifdef PDADC_DUMP
2028 ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d |"
2029 " PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d"
2030 " Value %3d |\n",
2031 i,
2032 4*j, pdadcValues[4*j],
2033 4*j+1, pdadcValues[4*j + 1],
2034 4*j+2, pdadcValues[4*j + 2],
2035 4*j+3, pdadcValues[4*j + 3]);
2036#endif
2037 regOffset += 4;
2038 }
2039}
2040
1860/**************************************************************
1861 * ar5416SetPowerCalTable
1862 *
1863 * Pull the PDADC piers from cal data and interpolate them across the given
1864 * points as well as from the nearest pier(s) to get a power detector
1865 * linear voltage to power level table.
1866 */
2041/**************************************************************
2042 * ar5416SetPowerCalTable
2043 *
2044 * Pull the PDADC piers from cal data and interpolate them across the given
2045 * points as well as from the nearest pier(s) to get a power detector
2046 * linear voltage to power level table.
2047 */
1867static HAL_BOOL
2048HAL_BOOL
1868ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData,
1869 const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset)
1870{
1871 CAL_DATA_PER_FREQ *pRawDataset;
1872 uint8_t *pCalBChans = AH_NULL;
1873 uint16_t pdGainOverlap_t2;
1874 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
1875 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
2049ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData,
2050 const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset)
2051{
2052 CAL_DATA_PER_FREQ *pRawDataset;
2053 uint8_t *pCalBChans = AH_NULL;
2054 uint16_t pdGainOverlap_t2;
2055 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
2056 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
1876 uint16_t numPiers, i, j;
2057 uint16_t numPiers, i;
1877 int16_t tMinCalPower;
1878 uint16_t numXpdGain, xpdMask;
1879 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
2058 int16_t tMinCalPower;
2059 uint16_t numXpdGain, xpdMask;
2060 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
1880 uint32_t reg32, regOffset, regChainOffset;
2061 uint32_t regChainOffset;
1881
1882 OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues));
1883
1884 xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain;
1885
1886 if (IS_EEP_MINOR_V2(ah)) {
1887 pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap;
1888 } else {
1889 pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
1890 }
1891
1892 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
1893 pCalBChans = pEepData->calFreqPier2G;
1894 numPiers = AR5416_NUM_2G_CAL_PIERS;
1895 } else {
1896 pCalBChans = pEepData->calFreqPier5G;
1897 numPiers = AR5416_NUM_5G_CAL_PIERS;
1898 }
1899
2062
2063 OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues));
2064
2065 xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain;
2066
2067 if (IS_EEP_MINOR_V2(ah)) {
2068 pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap;
2069 } else {
2070 pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
2071 }
2072
2073 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2074 pCalBChans = pEepData->calFreqPier2G;
2075 numPiers = AR5416_NUM_2G_CAL_PIERS;
2076 } else {
2077 pCalBChans = pEepData->calFreqPier5G;
2078 numPiers = AR5416_NUM_5G_CAL_PIERS;
2079 }
2080
1900 numXpdGain = 0;
1901 /* Calculate the value of xpdgains from the xpdGain Mask */
2081 /* Calculate the value of xpdgains from the xpdGain Mask */
1902 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
1903 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
1904 if (numXpdGain >= AR5416_NUM_PD_GAINS) {
1905 HALASSERT(0);
1906 break;
1907 }
1908 xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
1909 numXpdGain++;
1910 }
1911 }
2082 numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues);
1912
1913 /* Write the detector gain biases and their number */
2083
2084 /* Write the detector gain biases and their number */
1914 OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) &
1915 ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) |
1916 SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) |
1917 SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3));
2085 ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues);
1918
1919 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2086
2087 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2088 regChainOffset = ar5416GetRegChainOffset(ah, i);
1920
2089
1921 if (AR_SREV_OWL_20_OR_LATER(ah) &&
1922 ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) {
1923 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
1924 * only chains 0 and 2 populated
1925 */
1926 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1927 } else {
1928 regChainOffset = i * 0x1000;
1929 }
1930
1931 if (pEepData->baseEepHeader.txMask & (1 << i)) {
1932 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
1933 pRawDataset = pEepData->calPierData2G[i];
1934 } else {
1935 pRawDataset = pEepData->calPierData5G[i];
1936 }
1937
2090 if (pEepData->baseEepHeader.txMask & (1 << i)) {
2091 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2092 pRawDataset = pEepData->calPierData2G[i];
2093 } else {
2094 pRawDataset = pEepData->calPierData5G[i];
2095 }
2096
1938 ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset,
2097 /* Fetch the gain boundaries and the PDADC values */
2098 ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset,
1939 pCalBChans, numPiers,
1940 pdGainOverlap_t2,
1941 &tMinCalPower, gainBoundaries,
1942 pdadcValues, numXpdGain);
1943
1944 if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
2099 pCalBChans, numPiers,
2100 pdGainOverlap_t2,
2101 &tMinCalPower, gainBoundaries,
2102 pdadcValues, numXpdGain);
2103
2104 if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
1945 /*
1946 * Note the pdadc table may not start at 0 dBm power, could be
1947 * negative or greater than 0. Need to offset the power
1948 * values by the amount of minPower for griffin
1949 */
1950
1951 OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
1952 SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
1953 SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
1954 SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
1955 SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
1956 SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
2105 ar5416SetGainBoundariesClosedLoop(ah, regChainOffset,
2106 pdGainOverlap_t2, gainBoundaries);
1957 }
1958
1959 /* Write the power values into the baseband power table */
2107 }
2108
2109 /* Write the power values into the baseband power table */
1960 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
1961
1962 for (j = 0; j < 32; j++) {
1963 reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) |
1964 ((pdadcValues[4*j + 1] & 0xFF) << 8) |
1965 ((pdadcValues[4*j + 2] & 0xFF) << 16) |
1966 ((pdadcValues[4*j + 3] & 0xFF) << 24) ;
1967 OS_REG_WRITE(ah, regOffset, reg32);
1968
1969#ifdef PDADC_DUMP
1970 ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
1971 i,
1972 4*j, pdadcValues[4*j],
1973 4*j+1, pdadcValues[4*j + 1],
1974 4*j+2, pdadcValues[4*j + 2],
1975 4*j+3, pdadcValues[4*j + 3]);
1976#endif
1977 regOffset += 4;
1978 }
2110 ar5416WritePdadcValues(ah, regChainOffset, pdadcValues);
1979 }
1980 }
1981 *pTxPowerIndexOffset = 0;
1982
1983 return AH_TRUE;
1984}
1985
1986/**************************************************************
1987 * ar5416GetGainBoundariesAndPdadcs
1988 *
1989 * Uses the data points read from EEPROM to reconstruct the pdadc power table
1990 * Called by ar5416SetPowerCalTable only.
1991 */
2111 }
2112 }
2113 *pTxPowerIndexOffset = 0;
2114
2115 return AH_TRUE;
2116}
2117
2118/**************************************************************
2119 * ar5416GetGainBoundariesAndPdadcs
2120 *
2121 * Uses the data points read from EEPROM to reconstruct the pdadc power table
2122 * Called by ar5416SetPowerCalTable only.
2123 */
1992static void
2124void
1993ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
1994 const struct ieee80211_channel *chan,
1995 CAL_DATA_PER_FREQ *pRawDataSet,
1996 uint8_t * bChans, uint16_t availPiers,
1997 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries,
1998 uint8_t * pPDADCValues, uint16_t numXpdGains)
1999{
2000

--- 383 unchanged lines hidden ---
2125ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
2126 const struct ieee80211_channel *chan,
2127 CAL_DATA_PER_FREQ *pRawDataSet,
2128 uint8_t * bChans, uint16_t availPiers,
2129 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries,
2130 uint8_t * pPDADCValues, uint16_t numXpdGains)
2131{
2132

--- 383 unchanged lines hidden ---