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 --- |