diff options
Diffstat (limited to 'drivers/net/wireless/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath5k/phy.c | 185 |
1 files changed, 167 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index afd8689e5c03..fa0d47faf574 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = { | |||
1020 | { AR5K_RF_GAIN(63), { 0x000000f9 } }, | 1020 | { AR5K_RF_GAIN(63), { 0x000000f9 } }, |
1021 | }; | 1021 | }; |
1022 | 1022 | ||
1023 | /* Initial RF Gain settings for RF2425 */ | ||
1024 | static const struct ath5k_ini_rfgain rfgain_2425[] = { | ||
1025 | { AR5K_RF_GAIN(0), { 0x00000000 } }, | ||
1026 | { AR5K_RF_GAIN(1), { 0x00000040 } }, | ||
1027 | { AR5K_RF_GAIN(2), { 0x00000080 } }, | ||
1028 | { AR5K_RF_GAIN(3), { 0x00000181 } }, | ||
1029 | { AR5K_RF_GAIN(4), { 0x000001c1 } }, | ||
1030 | { AR5K_RF_GAIN(5), { 0x00000001 } }, | ||
1031 | { AR5K_RF_GAIN(6), { 0x00000041 } }, | ||
1032 | { AR5K_RF_GAIN(7), { 0x00000081 } }, | ||
1033 | { AR5K_RF_GAIN(8), { 0x00000188 } }, | ||
1034 | { AR5K_RF_GAIN(9), { 0x000001c8 } }, | ||
1035 | { AR5K_RF_GAIN(10), { 0x00000008 } }, | ||
1036 | { AR5K_RF_GAIN(11), { 0x00000048 } }, | ||
1037 | { AR5K_RF_GAIN(12), { 0x00000088 } }, | ||
1038 | { AR5K_RF_GAIN(13), { 0x00000189 } }, | ||
1039 | { AR5K_RF_GAIN(14), { 0x000001c9 } }, | ||
1040 | { AR5K_RF_GAIN(15), { 0x00000009 } }, | ||
1041 | { AR5K_RF_GAIN(16), { 0x00000049 } }, | ||
1042 | { AR5K_RF_GAIN(17), { 0x00000089 } }, | ||
1043 | { AR5K_RF_GAIN(18), { 0x000001b0 } }, | ||
1044 | { AR5K_RF_GAIN(19), { 0x000001f0 } }, | ||
1045 | { AR5K_RF_GAIN(20), { 0x00000030 } }, | ||
1046 | { AR5K_RF_GAIN(21), { 0x00000070 } }, | ||
1047 | { AR5K_RF_GAIN(22), { 0x00000171 } }, | ||
1048 | { AR5K_RF_GAIN(23), { 0x000001b1 } }, | ||
1049 | { AR5K_RF_GAIN(24), { 0x000001f1 } }, | ||
1050 | { AR5K_RF_GAIN(25), { 0x00000031 } }, | ||
1051 | { AR5K_RF_GAIN(26), { 0x00000071 } }, | ||
1052 | { AR5K_RF_GAIN(27), { 0x000001b8 } }, | ||
1053 | { AR5K_RF_GAIN(28), { 0x000001f8 } }, | ||
1054 | { AR5K_RF_GAIN(29), { 0x00000038 } }, | ||
1055 | { AR5K_RF_GAIN(30), { 0x00000078 } }, | ||
1056 | { AR5K_RF_GAIN(31), { 0x000000b8 } }, | ||
1057 | { AR5K_RF_GAIN(32), { 0x000001b9 } }, | ||
1058 | { AR5K_RF_GAIN(33), { 0x000001f9 } }, | ||
1059 | { AR5K_RF_GAIN(34), { 0x00000039 } }, | ||
1060 | { AR5K_RF_GAIN(35), { 0x00000079 } }, | ||
1061 | { AR5K_RF_GAIN(36), { 0x000000b9 } }, | ||
1062 | { AR5K_RF_GAIN(37), { 0x000000f9 } }, | ||
1063 | { AR5K_RF_GAIN(38), { 0x000000f9 } }, | ||
1064 | { AR5K_RF_GAIN(39), { 0x000000f9 } }, | ||
1065 | { AR5K_RF_GAIN(40), { 0x000000f9 } }, | ||
1066 | { AR5K_RF_GAIN(41), { 0x000000f9 } }, | ||
1067 | { AR5K_RF_GAIN(42), { 0x000000f9 } }, | ||
1068 | { AR5K_RF_GAIN(43), { 0x000000f9 } }, | ||
1069 | { AR5K_RF_GAIN(44), { 0x000000f9 } }, | ||
1070 | { AR5K_RF_GAIN(45), { 0x000000f9 } }, | ||
1071 | { AR5K_RF_GAIN(46), { 0x000000f9 } }, | ||
1072 | { AR5K_RF_GAIN(47), { 0x000000f9 } }, | ||
1073 | { AR5K_RF_GAIN(48), { 0x000000f9 } }, | ||
1074 | { AR5K_RF_GAIN(49), { 0x000000f9 } }, | ||
1075 | { AR5K_RF_GAIN(50), { 0x000000f9 } }, | ||
1076 | { AR5K_RF_GAIN(51), { 0x000000f9 } }, | ||
1077 | { AR5K_RF_GAIN(52), { 0x000000f9 } }, | ||
1078 | { AR5K_RF_GAIN(53), { 0x000000f9 } }, | ||
1079 | { AR5K_RF_GAIN(54), { 0x000000f9 } }, | ||
1080 | { AR5K_RF_GAIN(55), { 0x000000f9 } }, | ||
1081 | { AR5K_RF_GAIN(56), { 0x000000f9 } }, | ||
1082 | { AR5K_RF_GAIN(57), { 0x000000f9 } }, | ||
1083 | { AR5K_RF_GAIN(58), { 0x000000f9 } }, | ||
1084 | { AR5K_RF_GAIN(59), { 0x000000f9 } }, | ||
1085 | { AR5K_RF_GAIN(60), { 0x000000f9 } }, | ||
1086 | { AR5K_RF_GAIN(61), { 0x000000f9 } }, | ||
1087 | { AR5K_RF_GAIN(62), { 0x000000f9 } }, | ||
1088 | { AR5K_RF_GAIN(63), { 0x000000f9 } }, | ||
1089 | }; | ||
1090 | |||
1023 | static const struct ath5k_gain_opt rfgain_opt_5112 = { | 1091 | static const struct ath5k_gain_opt rfgain_opt_5112 = { |
1024 | 1, | 1092 | 1, |
1025 | 8, | 1093 | 8, |
@@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) | |||
1588 | freq = 0; /* only 2Ghz */ | 1656 | freq = 0; /* only 2Ghz */ |
1589 | break; | 1657 | break; |
1590 | case AR5K_RF2425: | 1658 | case AR5K_RF2425: |
1591 | ath5k_rfg = rfgain_2413; | 1659 | ath5k_rfg = rfgain_2425; |
1592 | size = ARRAY_SIZE(rfgain_2413); | 1660 | size = ARRAY_SIZE(rfgain_2425); |
1593 | freq = 0; /* only 2Ghz */ | 1661 | freq = 0; /* only 2Ghz */ |
1594 | break; | 1662 | break; |
1595 | default: | 1663 | default: |
@@ -1830,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1830 | data = data0 = data1 = data2 = 0; | 1898 | data = data0 = data1 = data2 = 0; |
1831 | c = channel->center_freq; | 1899 | c = channel->center_freq; |
1832 | 1900 | ||
1833 | /* | ||
1834 | * Set the channel on the RF5112 or newer | ||
1835 | */ | ||
1836 | if (c < 4800) { | 1901 | if (c < 4800) { |
1837 | if (!((c - 2224) % 5)) { | 1902 | if (!((c - 2224) % 5)) { |
1838 | data0 = ((2 * (c - 704)) - 3040) / 10; | 1903 | data0 = ((2 * (c - 704)) - 3040) / 10; |
@@ -1844,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1844 | return -EINVAL; | 1909 | return -EINVAL; |
1845 | 1910 | ||
1846 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); | 1911 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); |
1847 | } else { | 1912 | } else if ((c - (c % 5)) != 2 || c > 5435) { |
1848 | if (!(c % 20) && c >= 5120) { | 1913 | if (!(c % 20) && c >= 5120) { |
1849 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | 1914 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); |
1850 | data2 = ath5k_hw_bitswap(3, 2); | 1915 | data2 = ath5k_hw_bitswap(3, 2); |
@@ -1856,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1856 | data2 = ath5k_hw_bitswap(1, 2); | 1921 | data2 = ath5k_hw_bitswap(1, 2); |
1857 | } else | 1922 | } else |
1858 | return -EINVAL; | 1923 | return -EINVAL; |
1924 | } else { | ||
1925 | data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); | ||
1926 | data2 = ath5k_hw_bitswap(0, 2); | ||
1859 | } | 1927 | } |
1860 | 1928 | ||
1861 | data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; | 1929 | data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; |
@@ -1867,6 +1935,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1867 | } | 1935 | } |
1868 | 1936 | ||
1869 | /* | 1937 | /* |
1938 | * Set the channel on the RF2425 | ||
1939 | */ | ||
1940 | static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | ||
1941 | struct ieee80211_channel *channel) | ||
1942 | { | ||
1943 | u32 data, data0, data2; | ||
1944 | u16 c; | ||
1945 | |||
1946 | data = data0 = data2 = 0; | ||
1947 | c = channel->center_freq; | ||
1948 | |||
1949 | if (c < 4800) { | ||
1950 | data0 = ath5k_hw_bitswap((c - 2272), 8); | ||
1951 | data2 = 0; | ||
1952 | /* ? 5GHz ? */ | ||
1953 | } else if ((c - (c % 5)) != 2 || c > 5435) { | ||
1954 | if (!(c % 20) && c < 5120) | ||
1955 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | ||
1956 | else if (!(c % 10)) | ||
1957 | data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); | ||
1958 | else if (!(c % 5)) | ||
1959 | data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); | ||
1960 | else | ||
1961 | return -EINVAL; | ||
1962 | data2 = ath5k_hw_bitswap(1, 2); | ||
1963 | } else { | ||
1964 | data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); | ||
1965 | data2 = ath5k_hw_bitswap(0, 2); | ||
1966 | } | ||
1967 | |||
1968 | data = (data0 << 4) | data2 << 2 | 0x1001; | ||
1969 | |||
1970 | ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); | ||
1971 | ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); | ||
1972 | |||
1973 | return 0; | ||
1974 | } | ||
1975 | |||
1976 | /* | ||
1870 | * Set a channel on the radio chip | 1977 | * Set a channel on the radio chip |
1871 | */ | 1978 | */ |
1872 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 1979 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) |
@@ -1895,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1895 | case AR5K_RF5111: | 2002 | case AR5K_RF5111: |
1896 | ret = ath5k_hw_rf5111_channel(ah, channel); | 2003 | ret = ath5k_hw_rf5111_channel(ah, channel); |
1897 | break; | 2004 | break; |
2005 | case AR5K_RF2425: | ||
2006 | ret = ath5k_hw_rf2425_channel(ah, channel); | ||
2007 | break; | ||
1898 | default: | 2008 | default: |
1899 | ret = ath5k_hw_rf5112_channel(ah, channel); | 2009 | ret = ath5k_hw_rf5112_channel(ah, channel); |
1900 | break; | 2010 | break; |
@@ -1903,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1903 | if (ret) | 2013 | if (ret) |
1904 | return ret; | 2014 | return ret; |
1905 | 2015 | ||
2016 | /* Set JAPAN setting for channel 14 */ | ||
2017 | if (channel->center_freq == 2484) { | ||
2018 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, | ||
2019 | AR5K_PHY_CCKTXCTL_JAPAN); | ||
2020 | } else { | ||
2021 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, | ||
2022 | AR5K_PHY_CCKTXCTL_WORLD); | ||
2023 | } | ||
2024 | |||
1906 | ah->ah_current_channel.center_freq = channel->center_freq; | 2025 | ah->ah_current_channel.center_freq = channel->center_freq; |
1907 | ah->ah_current_channel.hw_value = channel->hw_value; | 2026 | ah->ah_current_channel.hw_value = channel->hw_value; |
1908 | ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; | 2027 | ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; |
@@ -1933,6 +2052,8 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1933 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ | 2052 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ |
1934 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 | 2053 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 |
1935 | * | 2054 | * |
2055 | * XXX: Since during noise floor calibration antennas are detached according to | ||
2056 | * the patent, we should stop tx queues here. | ||
1936 | */ | 2057 | */ |
1937 | int | 2058 | int |
1938 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | 2059 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) |
@@ -1942,7 +2063,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | |||
1942 | s32 noise_floor; | 2063 | s32 noise_floor; |
1943 | 2064 | ||
1944 | /* | 2065 | /* |
1945 | * Enable noise floor calibration and wait until completion | 2066 | * Enable noise floor calibration |
1946 | */ | 2067 | */ |
1947 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 2068 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
1948 | AR5K_PHY_AGCCTL_NF); | 2069 | AR5K_PHY_AGCCTL_NF); |
@@ -1952,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | |||
1952 | if (ret) { | 2073 | if (ret) { |
1953 | ATH5K_ERR(ah->ah_sc, | 2074 | ATH5K_ERR(ah->ah_sc, |
1954 | "noise floor calibration timeout (%uMHz)\n", freq); | 2075 | "noise floor calibration timeout (%uMHz)\n", freq); |
1955 | return ret; | 2076 | return -EAGAIN; |
1956 | } | 2077 | } |
1957 | 2078 | ||
1958 | /* Wait until the noise floor is calibrated and read the value */ | 2079 | /* Wait until the noise floor is calibrated and read the value */ |
@@ -1974,7 +2095,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | |||
1974 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { | 2095 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { |
1975 | ATH5K_ERR(ah->ah_sc, | 2096 | ATH5K_ERR(ah->ah_sc, |
1976 | "noise floor calibration failed (%uMHz)\n", freq); | 2097 | "noise floor calibration failed (%uMHz)\n", freq); |
1977 | return -EIO; | 2098 | return -EAGAIN; |
1978 | } | 2099 | } |
1979 | 2100 | ||
1980 | ah->ah_noise_floor = noise_floor; | 2101 | ah->ah_noise_floor = noise_floor; |
@@ -2087,38 +2208,66 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
2087 | } | 2208 | } |
2088 | 2209 | ||
2089 | /* | 2210 | /* |
2090 | * Perform a PHY calibration on RF5111/5112 | 2211 | * Perform a PHY calibration on RF5111/5112 and newer chips |
2091 | */ | 2212 | */ |
2092 | static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | 2213 | static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, |
2093 | struct ieee80211_channel *channel) | 2214 | struct ieee80211_channel *channel) |
2094 | { | 2215 | { |
2095 | u32 i_pwr, q_pwr; | 2216 | u32 i_pwr, q_pwr; |
2096 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; | 2217 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; |
2218 | int i; | ||
2097 | ATH5K_TRACE(ah->ah_sc); | 2219 | ATH5K_TRACE(ah->ah_sc); |
2098 | 2220 | ||
2099 | if (!ah->ah_calibration || | 2221 | if (!ah->ah_calibration || |
2100 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) | 2222 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) |
2101 | goto done; | 2223 | goto done; |
2102 | 2224 | ||
2103 | ah->ah_calibration = false; | 2225 | /* Calibration has finished, get the results and re-run */ |
2226 | for (i = 0; i <= 10; i++) { | ||
2227 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | ||
2228 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); | ||
2229 | q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); | ||
2230 | } | ||
2104 | 2231 | ||
2105 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | ||
2106 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); | ||
2107 | q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); | ||
2108 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; | 2232 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; |
2109 | q_coffd = q_pwr >> 6; | 2233 | q_coffd = q_pwr >> 7; |
2110 | 2234 | ||
2235 | /* No correction */ | ||
2111 | if (i_coffd == 0 || q_coffd == 0) | 2236 | if (i_coffd == 0 || q_coffd == 0) |
2112 | goto done; | 2237 | goto done; |
2113 | 2238 | ||
2114 | i_coff = ((-iq_corr) / i_coffd) & 0x3f; | 2239 | i_coff = ((-iq_corr) / i_coffd) & 0x3f; |
2115 | q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f; | ||
2116 | 2240 | ||
2117 | /* Commit new IQ value */ | 2241 | /* Boundary check */ |
2242 | if (i_coff > 31) | ||
2243 | i_coff = 31; | ||
2244 | if (i_coff < -32) | ||
2245 | i_coff = -32; | ||
2246 | |||
2247 | q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; | ||
2248 | |||
2249 | /* Boundary check */ | ||
2250 | if (q_coff > 15) | ||
2251 | q_coff = 15; | ||
2252 | if (q_coff < -16) | ||
2253 | q_coff = -16; | ||
2254 | |||
2255 | /* Commit new I/Q value */ | ||
2118 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | | 2256 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | |
2119 | ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); | 2257 | ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); |
2120 | 2258 | ||
2259 | /* Re-enable calibration -if we don't we'll commit | ||
2260 | * the same values again and again */ | ||
2261 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
2262 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
2263 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); | ||
2264 | |||
2121 | done: | 2265 | done: |
2266 | |||
2267 | /* TODO: Separate noise floor calibration from I/Q calibration | ||
2268 | * since noise floor calibration interrupts rx path while I/Q | ||
2269 | * calibration doesn't. We don't need to run noise floor calibration | ||
2270 | * as often as I/Q calibration.*/ | ||
2122 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 2271 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); |
2123 | 2272 | ||
2124 | /* Request RF gain */ | 2273 | /* Request RF gain */ |