Deleted Added
sdiff udiff text old ( 219218 ) new ( 219393 )
full compact
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 $
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);
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);
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
851 if (!ar5416SetPowerCalTable(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
882 ar5416PrintPowerPerRate(ah, ratesArray);
883#endif
884
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
1300
1301
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 }
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 }
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
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 */
1867static HAL_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];
1876 uint16_t numPiers, i, j;
1877 int16_t tMinCalPower;
1878 uint16_t numXpdGain, xpdMask;
1879 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
1880 uint32_t reg32, regOffset, 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
1900 numXpdGain = 0;
1901 /* 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 }
1912
1913 /* 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));
1918
1919 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1920
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
1938 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)) {
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));
1957 }
1958
1959 /* 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 }
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 */
1992static void
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 ---