aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_eeprom.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c388
1 files changed, 381 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index ace8d2678b18..b883b174385b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -41,6 +41,20 @@
41#define LE16(x) __constant_cpu_to_le16(x) 41#define LE16(x) __constant_cpu_to_le16(x)
42#define LE32(x) __constant_cpu_to_le32(x) 42#define LE32(x) __constant_cpu_to_le32(x)
43 43
44/* Local defines to distinguish between extension and control CTL's */
45#define EXT_ADDITIVE (0x8000)
46#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
47#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
48#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
49#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
50#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
51#define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
52#define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
53#define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
54
55#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
56#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
57
44static const struct ar9300_eeprom ar9300_default = { 58static const struct ar9300_eeprom ar9300_default = {
45 .eepromVersion = 2, 59 .eepromVersion = 2,
46 .templateVersion = 2, 60 .templateVersion = 2,
@@ -609,6 +623,14 @@ static const struct ar9300_eeprom ar9300_default = {
609 } 623 }
610}; 624};
611 625
626static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
627{
628 if (fbin == AR9300_BCHAN_UNUSED)
629 return fbin;
630
631 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
632}
633
612static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) 634static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
613{ 635{
614 return 0; 636 return 0;
@@ -1417,9 +1439,9 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1417#undef POW_SM 1439#undef POW_SM
1418} 1440}
1419 1441
1420static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) 1442static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1443 u8 *targetPowerValT2)
1421{ 1444{
1422 u8 targetPowerValT2[ar9300RateSize];
1423 /* XXX: hard code for now, need to get from eeprom struct */ 1445 /* XXX: hard code for now, need to get from eeprom struct */
1424 u8 ht40PowerIncForPdadc = 0; 1446 u8 ht40PowerIncForPdadc = 0;
1425 bool is2GHz = false; 1447 bool is2GHz = false;
@@ -1553,9 +1575,6 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
1553 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); 1575 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1554 i++; 1576 i++;
1555 } 1577 }
1556
1557 /* Write target power array to registers */
1558 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
1559} 1578}
1560 1579
1561static int ar9003_hw_cal_pier_get(struct ath_hw *ah, 1580static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
@@ -1799,14 +1818,369 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1799 return 0; 1818 return 0;
1800} 1819}
1801 1820
1821static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1822 int idx,
1823 int edge,
1824 bool is2GHz)
1825{
1826 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1827 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1828
1829 if (is2GHz)
1830 return ctl_2g[idx].ctlEdges[edge].tPower;
1831 else
1832 return ctl_5g[idx].ctlEdges[edge].tPower;
1833}
1834
1835static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1836 int idx,
1837 unsigned int edge,
1838 u16 freq,
1839 bool is2GHz)
1840{
1841 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1842 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1843
1844 u8 *ctl_freqbin = is2GHz ?
1845 &eep->ctl_freqbin_2G[idx][0] :
1846 &eep->ctl_freqbin_5G[idx][0];
1847
1848 if (is2GHz) {
1849 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
1850 ctl_2g[idx].ctlEdges[edge - 1].flag)
1851 return ctl_2g[idx].ctlEdges[edge - 1].tPower;
1852 } else {
1853 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
1854 ctl_5g[idx].ctlEdges[edge - 1].flag)
1855 return ctl_5g[idx].ctlEdges[edge - 1].tPower;
1856 }
1857
1858 return AR9300_MAX_RATE_POWER;
1859}
1860
1861/*
1862 * Find the maximum conformance test limit for the given channel and CTL info
1863 */
1864static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1865 u16 freq, int idx, bool is2GHz)
1866{
1867 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1868 u8 *ctl_freqbin = is2GHz ?
1869 &eep->ctl_freqbin_2G[idx][0] :
1870 &eep->ctl_freqbin_5G[idx][0];
1871 u16 num_edges = is2GHz ?
1872 AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
1873 unsigned int edge;
1874
1875 /* Get the edge power */
1876 for (edge = 0;
1877 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1878 edge++) {
1879 /*
1880 * If there's an exact channel match or an inband flag set
1881 * on the lower channel use the given rdEdgePower
1882 */
1883 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1884 twiceMaxEdgePower =
1885 ar9003_hw_get_direct_edge_power(eep, idx,
1886 edge, is2GHz);
1887 break;
1888 } else if ((edge > 0) &&
1889 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1890 is2GHz))) {
1891 twiceMaxEdgePower =
1892 ar9003_hw_get_indirect_edge_power(eep, idx,
1893 edge, freq,
1894 is2GHz);
1895 /*
1896 * Leave loop - no more affecting edges possible in
1897 * this monotonic increasing list
1898 */
1899 break;
1900 }
1901 }
1902 return twiceMaxEdgePower;
1903}
1904
1905static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
1906 struct ath9k_channel *chan,
1907 u8 *pPwrArray, u16 cfgCtl,
1908 u8 twiceAntennaReduction,
1909 u8 twiceMaxRegulatoryPower,
1910 u16 powerLimit)
1911{
1912 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1913 struct ath_common *common = ath9k_hw_common(ah);
1914 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
1915 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1916 static const u16 tpScaleReductionTable[5] = {
1917 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1918 };
1919 int i;
1920 int16_t twiceLargestAntenna;
1921 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1922 u16 ctlModesFor11a[] = {
1923 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1924 };
1925 u16 ctlModesFor11g[] = {
1926 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1927 CTL_11G_EXT, CTL_2GHT40
1928 };
1929 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1930 struct chan_centers centers;
1931 u8 *ctlIndex;
1932 u8 ctlNum;
1933 u16 twiceMinEdgePower;
1934 bool is2ghz = IS_CHAN_2GHZ(chan);
1935
1936 ath9k_hw_get_channel_centers(ah, chan, &centers);
1937
1938 /* Compute TxPower reduction due to Antenna Gain */
1939 if (is2ghz)
1940 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1941 else
1942 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1943
1944 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1945 twiceLargestAntenna, 0);
1946
1947 /*
1948 * scaledPower is the minimum of the user input power level
1949 * and the regulatory allowed power level
1950 */
1951 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1952
1953 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1954 maxRegAllowedPower -=
1955 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1956 }
1957
1958 scaledPower = min(powerLimit, maxRegAllowedPower);
1959
1960 /*
1961 * Reduce scaled Power by number of chains active to get
1962 * to per chain tx power level
1963 */
1964 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1965 case 1:
1966 break;
1967 case 2:
1968 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1969 break;
1970 case 3:
1971 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1972 break;
1973 }
1974
1975 scaledPower = max((u16)0, scaledPower);
1976
1977 /*
1978 * Get target powers from EEPROM - our baseline for TX Power
1979 */
1980 if (is2ghz) {
1981 /* Setup for CTL modes */
1982 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1983 numCtlModes =
1984 ARRAY_SIZE(ctlModesFor11g) -
1985 SUB_NUM_CTL_MODES_AT_2G_40;
1986 pCtlMode = ctlModesFor11g;
1987 if (IS_CHAN_HT40(chan))
1988 /* All 2G CTL's */
1989 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1990 } else {
1991 /* Setup for CTL modes */
1992 /* CTL_11A, CTL_5GHT20 */
1993 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
1994 SUB_NUM_CTL_MODES_AT_5G_40;
1995 pCtlMode = ctlModesFor11a;
1996 if (IS_CHAN_HT40(chan))
1997 /* All 5G CTL's */
1998 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
1999 }
2000
2001 /*
2002 * For MIMO, need to apply regulatory caps individually across
2003 * dynamically running modes: CCK, OFDM, HT20, HT40
2004 *
2005 * The outer loop walks through each possible applicable runtime mode.
2006 * The inner loop walks through each ctlIndex entry in EEPROM.
2007 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2008 */
2009 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2010 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2011 (pCtlMode[ctlMode] == CTL_2GHT40);
2012 if (isHt40CtlMode)
2013 freq = centers.synth_center;
2014 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2015 freq = centers.ext_center;
2016 else
2017 freq = centers.ctl_center;
2018
2019 ath_print(common, ATH_DBG_REGULATORY,
2020 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2021 "EXT_ADDITIVE %d\n",
2022 ctlMode, numCtlModes, isHt40CtlMode,
2023 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2024
2025 /* walk through each CTL index stored in EEPROM */
2026 if (is2ghz) {
2027 ctlIndex = pEepData->ctlIndex_2G;
2028 ctlNum = AR9300_NUM_CTLS_2G;
2029 } else {
2030 ctlIndex = pEepData->ctlIndex_5G;
2031 ctlNum = AR9300_NUM_CTLS_5G;
2032 }
2033
2034 for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
2035 ath_print(common, ATH_DBG_REGULATORY,
2036 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2037 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2038 "chan %dn",
2039 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2040 chan->channel);
2041
2042 /*
2043 * compare test group from regulatory
2044 * channel list with test mode from pCtlMode
2045 * list
2046 */
2047 if ((((cfgCtl & ~CTL_MODE_M) |
2048 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2049 ctlIndex[i]) ||
2050 (((cfgCtl & ~CTL_MODE_M) |
2051 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2052 ((ctlIndex[i] & CTL_MODE_M) |
2053 SD_NO_CTL))) {
2054 twiceMinEdgePower =
2055 ar9003_hw_get_max_edge_power(pEepData,
2056 freq, i,
2057 is2ghz);
2058
2059 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2060 /*
2061 * Find the minimum of all CTL
2062 * edge powers that apply to
2063 * this channel
2064 */
2065 twiceMaxEdgePower =
2066 min(twiceMaxEdgePower,
2067 twiceMinEdgePower);
2068 else {
2069 /* specific */
2070 twiceMaxEdgePower =
2071 twiceMinEdgePower;
2072 break;
2073 }
2074 }
2075 }
2076
2077 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2078
2079 ath_print(common, ATH_DBG_REGULATORY,
2080 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2081 "sP %d minCtlPwr %d\n",
2082 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2083 scaledPower, minCtlPower);
2084
2085 /* Apply ctl mode to correct target power set */
2086 switch (pCtlMode[ctlMode]) {
2087 case CTL_11B:
2088 for (i = ALL_TARGET_LEGACY_1L_5L;
2089 i <= ALL_TARGET_LEGACY_11S; i++)
2090 pPwrArray[i] =
2091 (u8)min((u16)pPwrArray[i],
2092 minCtlPower);
2093 break;
2094 case CTL_11A:
2095 case CTL_11G:
2096 for (i = ALL_TARGET_LEGACY_6_24;
2097 i <= ALL_TARGET_LEGACY_54; i++)
2098 pPwrArray[i] =
2099 (u8)min((u16)pPwrArray[i],
2100 minCtlPower);
2101 break;
2102 case CTL_5GHT20:
2103 case CTL_2GHT20:
2104 for (i = ALL_TARGET_HT20_0_8_16;
2105 i <= ALL_TARGET_HT20_21; i++)
2106 pPwrArray[i] =
2107 (u8)min((u16)pPwrArray[i],
2108 minCtlPower);
2109 pPwrArray[ALL_TARGET_HT20_22] =
2110 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2111 minCtlPower);
2112 pPwrArray[ALL_TARGET_HT20_23] =
2113 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2114 minCtlPower);
2115 break;
2116 case CTL_5GHT40:
2117 case CTL_2GHT40:
2118 for (i = ALL_TARGET_HT40_0_8_16;
2119 i <= ALL_TARGET_HT40_23; i++)
2120 pPwrArray[i] =
2121 (u8)min((u16)pPwrArray[i],
2122 minCtlPower);
2123 break;
2124 default:
2125 break;
2126 }
2127 } /* end ctl mode checking */
2128}
2129
1802static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, 2130static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
1803 struct ath9k_channel *chan, u16 cfgCtl, 2131 struct ath9k_channel *chan, u16 cfgCtl,
1804 u8 twiceAntennaReduction, 2132 u8 twiceAntennaReduction,
1805 u8 twiceMaxRegulatoryPower, 2133 u8 twiceMaxRegulatoryPower,
1806 u8 powerLimit) 2134 u8 powerLimit)
1807{ 2135{
1808 ah->txpower_limit = powerLimit; 2136 struct ath_common *common = ath9k_hw_common(ah);
1809 ar9003_hw_set_target_power_eeprom(ah, chan->channel); 2137 u8 targetPowerValT2[ar9300RateSize];
2138 unsigned int i = 0;
2139
2140 ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
2141 ar9003_hw_set_power_per_rate_table(ah, chan,
2142 targetPowerValT2, cfgCtl,
2143 twiceAntennaReduction,
2144 twiceMaxRegulatoryPower,
2145 powerLimit);
2146
2147 while (i < ar9300RateSize) {
2148 ath_print(common, ATH_DBG_EEPROM,
2149 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2150 i++;
2151 ath_print(common, ATH_DBG_EEPROM,
2152 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2153 i++;
2154 ath_print(common, ATH_DBG_EEPROM,
2155 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2156 i++;
2157 ath_print(common, ATH_DBG_EEPROM,
2158 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2159 i++;
2160 }
2161
2162 /* Write target power array to registers */
2163 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
2164
2165 /*
2166 * This is the TX power we send back to driver core,
2167 * and it can use to pass to userspace to display our
2168 * currently configured TX power setting.
2169 *
2170 * Since power is rate dependent, use one of the indices
2171 * from the AR9300_Rates enum to select an entry from
2172 * targetPowerValT2[] to report. Currently returns the
2173 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2174 * as CCK power is less interesting (?).
2175 */
2176 i = ALL_TARGET_LEGACY_6_24; /* legacy */
2177 if (IS_CHAN_HT40(chan))
2178 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
2179 else if (IS_CHAN_HT20(chan))
2180 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
2181
2182 ah->txpower_limit = targetPowerValT2[i];
2183
1810 ar9003_hw_calibration_apply(ah, chan->channel); 2184 ar9003_hw_calibration_apply(ah, chan->channel);
1811} 2185}
1812 2186