18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* We use the hw_value as an index into our private channel structure */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "common.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define CHAN2G(_freq, _idx) { \ 228c2ecf20Sopenharmony_ci .band = NL80211_BAND_2GHZ, \ 238c2ecf20Sopenharmony_ci .center_freq = (_freq), \ 248c2ecf20Sopenharmony_ci .hw_value = (_idx), \ 258c2ecf20Sopenharmony_ci .max_power = 20, \ 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define CHAN5G(_freq, _idx) { \ 298c2ecf20Sopenharmony_ci .band = NL80211_BAND_5GHZ, \ 308c2ecf20Sopenharmony_ci .center_freq = (_freq), \ 318c2ecf20Sopenharmony_ci .hw_value = (_idx), \ 328c2ecf20Sopenharmony_ci .max_power = 20, \ 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* Some 2 GHz radios are actually tunable on 2312-2732 368c2ecf20Sopenharmony_ci * on 5 MHz steps, we support the channels which we know 378c2ecf20Sopenharmony_ci * we have calibration data for all cards though to make 388c2ecf20Sopenharmony_ci * this static */ 398c2ecf20Sopenharmony_cistatic const struct ieee80211_channel ath9k_2ghz_chantable[] = { 408c2ecf20Sopenharmony_ci CHAN2G(2412, 0), /* Channel 1 */ 418c2ecf20Sopenharmony_ci CHAN2G(2417, 1), /* Channel 2 */ 428c2ecf20Sopenharmony_ci CHAN2G(2422, 2), /* Channel 3 */ 438c2ecf20Sopenharmony_ci CHAN2G(2427, 3), /* Channel 4 */ 448c2ecf20Sopenharmony_ci CHAN2G(2432, 4), /* Channel 5 */ 458c2ecf20Sopenharmony_ci CHAN2G(2437, 5), /* Channel 6 */ 468c2ecf20Sopenharmony_ci CHAN2G(2442, 6), /* Channel 7 */ 478c2ecf20Sopenharmony_ci CHAN2G(2447, 7), /* Channel 8 */ 488c2ecf20Sopenharmony_ci CHAN2G(2452, 8), /* Channel 9 */ 498c2ecf20Sopenharmony_ci CHAN2G(2457, 9), /* Channel 10 */ 508c2ecf20Sopenharmony_ci CHAN2G(2462, 10), /* Channel 11 */ 518c2ecf20Sopenharmony_ci CHAN2G(2467, 11), /* Channel 12 */ 528c2ecf20Sopenharmony_ci CHAN2G(2472, 12), /* Channel 13 */ 538c2ecf20Sopenharmony_ci CHAN2G(2484, 13), /* Channel 14 */ 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Some 5 GHz radios are actually tunable on XXXX-YYYY 578c2ecf20Sopenharmony_ci * on 5 MHz steps, we support the channels which we know 588c2ecf20Sopenharmony_ci * we have calibration data for all cards though to make 598c2ecf20Sopenharmony_ci * this static */ 608c2ecf20Sopenharmony_cistatic const struct ieee80211_channel ath9k_5ghz_chantable[] = { 618c2ecf20Sopenharmony_ci /* _We_ call this UNII 1 */ 628c2ecf20Sopenharmony_ci CHAN5G(5180, 14), /* Channel 36 */ 638c2ecf20Sopenharmony_ci CHAN5G(5200, 15), /* Channel 40 */ 648c2ecf20Sopenharmony_ci CHAN5G(5220, 16), /* Channel 44 */ 658c2ecf20Sopenharmony_ci CHAN5G(5240, 17), /* Channel 48 */ 668c2ecf20Sopenharmony_ci /* _We_ call this UNII 2 */ 678c2ecf20Sopenharmony_ci CHAN5G(5260, 18), /* Channel 52 */ 688c2ecf20Sopenharmony_ci CHAN5G(5280, 19), /* Channel 56 */ 698c2ecf20Sopenharmony_ci CHAN5G(5300, 20), /* Channel 60 */ 708c2ecf20Sopenharmony_ci CHAN5G(5320, 21), /* Channel 64 */ 718c2ecf20Sopenharmony_ci /* _We_ call this "Middle band" */ 728c2ecf20Sopenharmony_ci CHAN5G(5500, 22), /* Channel 100 */ 738c2ecf20Sopenharmony_ci CHAN5G(5520, 23), /* Channel 104 */ 748c2ecf20Sopenharmony_ci CHAN5G(5540, 24), /* Channel 108 */ 758c2ecf20Sopenharmony_ci CHAN5G(5560, 25), /* Channel 112 */ 768c2ecf20Sopenharmony_ci CHAN5G(5580, 26), /* Channel 116 */ 778c2ecf20Sopenharmony_ci CHAN5G(5600, 27), /* Channel 120 */ 788c2ecf20Sopenharmony_ci CHAN5G(5620, 28), /* Channel 124 */ 798c2ecf20Sopenharmony_ci CHAN5G(5640, 29), /* Channel 128 */ 808c2ecf20Sopenharmony_ci CHAN5G(5660, 30), /* Channel 132 */ 818c2ecf20Sopenharmony_ci CHAN5G(5680, 31), /* Channel 136 */ 828c2ecf20Sopenharmony_ci CHAN5G(5700, 32), /* Channel 140 */ 838c2ecf20Sopenharmony_ci /* _We_ call this UNII 3 */ 848c2ecf20Sopenharmony_ci CHAN5G(5745, 33), /* Channel 149 */ 858c2ecf20Sopenharmony_ci CHAN5G(5765, 34), /* Channel 153 */ 868c2ecf20Sopenharmony_ci CHAN5G(5785, 35), /* Channel 157 */ 878c2ecf20Sopenharmony_ci CHAN5G(5805, 36), /* Channel 161 */ 888c2ecf20Sopenharmony_ci CHAN5G(5825, 37), /* Channel 165 */ 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* Atheros hardware rate code addition for short preamble */ 928c2ecf20Sopenharmony_ci#define SHPCHECK(__hw_rate, __flags) \ 938c2ecf20Sopenharmony_ci ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define RATE(_bitrate, _hw_rate, _flags) { \ 968c2ecf20Sopenharmony_ci .bitrate = (_bitrate), \ 978c2ecf20Sopenharmony_ci .flags = (_flags), \ 988c2ecf20Sopenharmony_ci .hw_value = (_hw_rate), \ 998c2ecf20Sopenharmony_ci .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic struct ieee80211_rate ath9k_legacy_rates[] = { 1038c2ecf20Sopenharmony_ci RATE(10, 0x1b, 0), 1048c2ecf20Sopenharmony_ci RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), 1058c2ecf20Sopenharmony_ci RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), 1068c2ecf20Sopenharmony_ci RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), 1078c2ecf20Sopenharmony_ci RATE(60, 0x0b, (IEEE80211_RATE_SUPPORTS_5MHZ | 1088c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1098c2ecf20Sopenharmony_ci RATE(90, 0x0f, (IEEE80211_RATE_SUPPORTS_5MHZ | 1108c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1118c2ecf20Sopenharmony_ci RATE(120, 0x0a, (IEEE80211_RATE_SUPPORTS_5MHZ | 1128c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1138c2ecf20Sopenharmony_ci RATE(180, 0x0e, (IEEE80211_RATE_SUPPORTS_5MHZ | 1148c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1158c2ecf20Sopenharmony_ci RATE(240, 0x09, (IEEE80211_RATE_SUPPORTS_5MHZ | 1168c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1178c2ecf20Sopenharmony_ci RATE(360, 0x0d, (IEEE80211_RATE_SUPPORTS_5MHZ | 1188c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1198c2ecf20Sopenharmony_ci RATE(480, 0x08, (IEEE80211_RATE_SUPPORTS_5MHZ | 1208c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1218c2ecf20Sopenharmony_ci RATE(540, 0x0c, (IEEE80211_RATE_SUPPORTS_5MHZ | 1228c2ecf20Sopenharmony_ci IEEE80211_RATE_SUPPORTS_10MHZ)), 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciint ath9k_cmn_init_channels_rates(struct ath_common *common) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct ath_hw *ah = (struct ath_hw *)common->ah; 1288c2ecf20Sopenharmony_ci void *channels; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) + 1318c2ecf20Sopenharmony_ci ARRAY_SIZE(ath9k_5ghz_chantable) != 1328c2ecf20Sopenharmony_ci ATH9K_NUM_CHANNELS); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { 1358c2ecf20Sopenharmony_ci channels = devm_kzalloc(ah->dev, 1368c2ecf20Sopenharmony_ci sizeof(ath9k_2ghz_chantable), GFP_KERNEL); 1378c2ecf20Sopenharmony_ci if (!channels) 1388c2ecf20Sopenharmony_ci return -ENOMEM; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci memcpy(channels, ath9k_2ghz_chantable, 1418c2ecf20Sopenharmony_ci sizeof(ath9k_2ghz_chantable)); 1428c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_2GHZ].channels = channels; 1438c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_2GHZ].band = NL80211_BAND_2GHZ; 1448c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_2GHZ].n_channels = 1458c2ecf20Sopenharmony_ci ARRAY_SIZE(ath9k_2ghz_chantable); 1468c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; 1478c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_2GHZ].n_bitrates = 1488c2ecf20Sopenharmony_ci ARRAY_SIZE(ath9k_legacy_rates); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { 1528c2ecf20Sopenharmony_ci channels = devm_kzalloc(ah->dev, 1538c2ecf20Sopenharmony_ci sizeof(ath9k_5ghz_chantable), GFP_KERNEL); 1548c2ecf20Sopenharmony_ci if (!channels) 1558c2ecf20Sopenharmony_ci return -ENOMEM; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci memcpy(channels, ath9k_5ghz_chantable, 1588c2ecf20Sopenharmony_ci sizeof(ath9k_5ghz_chantable)); 1598c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_5GHZ].channels = channels; 1608c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_5GHZ].band = NL80211_BAND_5GHZ; 1618c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_5GHZ].n_channels = 1628c2ecf20Sopenharmony_ci ARRAY_SIZE(ath9k_5ghz_chantable); 1638c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_5GHZ].bitrates = 1648c2ecf20Sopenharmony_ci ath9k_legacy_rates + 4; 1658c2ecf20Sopenharmony_ci common->sbands[NL80211_BAND_5GHZ].n_bitrates = 1668c2ecf20Sopenharmony_ci ARRAY_SIZE(ath9k_legacy_rates) - 4; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_init_channels_rates); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_civoid ath9k_cmn_setup_ht_cap(struct ath_hw *ah, 1738c2ecf20Sopenharmony_ci struct ieee80211_sta_ht_cap *ht_info) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 1768c2ecf20Sopenharmony_ci u8 tx_streams, rx_streams; 1778c2ecf20Sopenharmony_ci int i, max_streams; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci ht_info->ht_supported = true; 1808c2ecf20Sopenharmony_ci ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 1818c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_SM_PS | 1828c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_SGI_40 | 1838c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_DSSSCCK40; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) 1868c2ecf20Sopenharmony_ci ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) 1898c2ecf20Sopenharmony_ci ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 1928c2ecf20Sopenharmony_ci ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (AR_SREV_9271(ah) || AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) 1958c2ecf20Sopenharmony_ci max_streams = 1; 1968c2ecf20Sopenharmony_ci else if (AR_SREV_9462(ah)) 1978c2ecf20Sopenharmony_ci max_streams = 2; 1988c2ecf20Sopenharmony_ci else if (AR_SREV_9300_20_OR_LATER(ah)) 1998c2ecf20Sopenharmony_ci max_streams = 3; 2008c2ecf20Sopenharmony_ci else 2018c2ecf20Sopenharmony_ci max_streams = 2; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 2048c2ecf20Sopenharmony_ci if (max_streams >= 2) 2058c2ecf20Sopenharmony_ci ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; 2068c2ecf20Sopenharmony_ci ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* set up supported mcs set */ 2108c2ecf20Sopenharmony_ci memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 2118c2ecf20Sopenharmony_ci tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams); 2128c2ecf20Sopenharmony_ci rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n", 2158c2ecf20Sopenharmony_ci tx_streams, rx_streams); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (tx_streams != rx_streams) { 2188c2ecf20Sopenharmony_ci ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 2198c2ecf20Sopenharmony_ci ht_info->mcs.tx_params |= ((tx_streams - 1) << 2208c2ecf20Sopenharmony_ci IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci for (i = 0; i < rx_streams; i++) 2248c2ecf20Sopenharmony_ci ht_info->mcs.rx_mask[i] = 0xff; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_setup_ht_cap); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_civoid ath9k_cmn_reload_chainmask(struct ath_hw *ah) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (!(ah->caps.hw_caps & ATH9K_HW_CAP_HT)) 2358c2ecf20Sopenharmony_ci return; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) 2388c2ecf20Sopenharmony_ci ath9k_cmn_setup_ht_cap(ah, 2398c2ecf20Sopenharmony_ci &common->sbands[NL80211_BAND_2GHZ].ht_cap); 2408c2ecf20Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) 2418c2ecf20Sopenharmony_ci ath9k_cmn_setup_ht_cap(ah, 2428c2ecf20Sopenharmony_ci &common->sbands[NL80211_BAND_5GHZ].ht_cap); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_reload_chainmask); 245