113f71050SOleksij Rempel /* 213f71050SOleksij Rempel * Copyright (c) 2008-2011 Atheros Communications Inc. 313f71050SOleksij Rempel * 413f71050SOleksij Rempel * Permission to use, copy, modify, and/or distribute this software for any 513f71050SOleksij Rempel * purpose with or without fee is hereby granted, provided that the above 613f71050SOleksij Rempel * copyright notice and this permission notice appear in all copies. 713f71050SOleksij Rempel * 813f71050SOleksij Rempel * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 913f71050SOleksij Rempel * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1013f71050SOleksij Rempel * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1113f71050SOleksij Rempel * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1213f71050SOleksij Rempel * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1313f71050SOleksij Rempel * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1413f71050SOleksij Rempel * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1513f71050SOleksij Rempel */ 1613f71050SOleksij Rempel 1713f71050SOleksij Rempel /* We use the hw_value as an index into our private channel structure */ 1813f71050SOleksij Rempel 1913f71050SOleksij Rempel #include "common.h" 2013f71050SOleksij Rempel 2113f71050SOleksij Rempel #define CHAN2G(_freq, _idx) { \ 2257fbcce3SJohannes Berg .band = NL80211_BAND_2GHZ, \ 2313f71050SOleksij Rempel .center_freq = (_freq), \ 2413f71050SOleksij Rempel .hw_value = (_idx), \ 2513f71050SOleksij Rempel .max_power = 20, \ 2613f71050SOleksij Rempel } 2713f71050SOleksij Rempel 2813f71050SOleksij Rempel #define CHAN5G(_freq, _idx) { \ 2957fbcce3SJohannes Berg .band = NL80211_BAND_5GHZ, \ 3013f71050SOleksij Rempel .center_freq = (_freq), \ 3113f71050SOleksij Rempel .hw_value = (_idx), \ 3213f71050SOleksij Rempel .max_power = 20, \ 3313f71050SOleksij Rempel } 3413f71050SOleksij Rempel 3513f71050SOleksij Rempel /* Some 2 GHz radios are actually tunable on 2312-2732 3613f71050SOleksij Rempel * on 5 MHz steps, we support the channels which we know 3713f71050SOleksij Rempel * we have calibration data for all cards though to make 3813f71050SOleksij Rempel * this static */ 3913f71050SOleksij Rempel static const struct ieee80211_channel ath9k_2ghz_chantable[] = { 4013f71050SOleksij Rempel CHAN2G(2412, 0), /* Channel 1 */ 4113f71050SOleksij Rempel CHAN2G(2417, 1), /* Channel 2 */ 4213f71050SOleksij Rempel CHAN2G(2422, 2), /* Channel 3 */ 4313f71050SOleksij Rempel CHAN2G(2427, 3), /* Channel 4 */ 4413f71050SOleksij Rempel CHAN2G(2432, 4), /* Channel 5 */ 4513f71050SOleksij Rempel CHAN2G(2437, 5), /* Channel 6 */ 4613f71050SOleksij Rempel CHAN2G(2442, 6), /* Channel 7 */ 4713f71050SOleksij Rempel CHAN2G(2447, 7), /* Channel 8 */ 4813f71050SOleksij Rempel CHAN2G(2452, 8), /* Channel 9 */ 4913f71050SOleksij Rempel CHAN2G(2457, 9), /* Channel 10 */ 5013f71050SOleksij Rempel CHAN2G(2462, 10), /* Channel 11 */ 5113f71050SOleksij Rempel CHAN2G(2467, 11), /* Channel 12 */ 5213f71050SOleksij Rempel CHAN2G(2472, 12), /* Channel 13 */ 5313f71050SOleksij Rempel CHAN2G(2484, 13), /* Channel 14 */ 5413f71050SOleksij Rempel }; 5513f71050SOleksij Rempel 5613f71050SOleksij Rempel /* Some 5 GHz radios are actually tunable on XXXX-YYYY 5713f71050SOleksij Rempel * on 5 MHz steps, we support the channels which we know 5813f71050SOleksij Rempel * we have calibration data for all cards though to make 5913f71050SOleksij Rempel * this static */ 6013f71050SOleksij Rempel static const struct ieee80211_channel ath9k_5ghz_chantable[] = { 6113f71050SOleksij Rempel /* _We_ call this UNII 1 */ 6213f71050SOleksij Rempel CHAN5G(5180, 14), /* Channel 36 */ 6313f71050SOleksij Rempel CHAN5G(5200, 15), /* Channel 40 */ 6413f71050SOleksij Rempel CHAN5G(5220, 16), /* Channel 44 */ 6513f71050SOleksij Rempel CHAN5G(5240, 17), /* Channel 48 */ 6613f71050SOleksij Rempel /* _We_ call this UNII 2 */ 6713f71050SOleksij Rempel CHAN5G(5260, 18), /* Channel 52 */ 6813f71050SOleksij Rempel CHAN5G(5280, 19), /* Channel 56 */ 6913f71050SOleksij Rempel CHAN5G(5300, 20), /* Channel 60 */ 7013f71050SOleksij Rempel CHAN5G(5320, 21), /* Channel 64 */ 7113f71050SOleksij Rempel /* _We_ call this "Middle band" */ 7213f71050SOleksij Rempel CHAN5G(5500, 22), /* Channel 100 */ 7313f71050SOleksij Rempel CHAN5G(5520, 23), /* Channel 104 */ 7413f71050SOleksij Rempel CHAN5G(5540, 24), /* Channel 108 */ 7513f71050SOleksij Rempel CHAN5G(5560, 25), /* Channel 112 */ 7613f71050SOleksij Rempel CHAN5G(5580, 26), /* Channel 116 */ 7713f71050SOleksij Rempel CHAN5G(5600, 27), /* Channel 120 */ 7813f71050SOleksij Rempel CHAN5G(5620, 28), /* Channel 124 */ 7913f71050SOleksij Rempel CHAN5G(5640, 29), /* Channel 128 */ 8013f71050SOleksij Rempel CHAN5G(5660, 30), /* Channel 132 */ 8113f71050SOleksij Rempel CHAN5G(5680, 31), /* Channel 136 */ 8213f71050SOleksij Rempel CHAN5G(5700, 32), /* Channel 140 */ 8313f71050SOleksij Rempel /* _We_ call this UNII 3 */ 8413f71050SOleksij Rempel CHAN5G(5745, 33), /* Channel 149 */ 8513f71050SOleksij Rempel CHAN5G(5765, 34), /* Channel 153 */ 8613f71050SOleksij Rempel CHAN5G(5785, 35), /* Channel 157 */ 8713f71050SOleksij Rempel CHAN5G(5805, 36), /* Channel 161 */ 8813f71050SOleksij Rempel CHAN5G(5825, 37), /* Channel 165 */ 8913f71050SOleksij Rempel }; 9013f71050SOleksij Rempel 91*1fb148f5SPeter Große /* Atheros hardware rate code addition for short preamble */ 9213f71050SOleksij Rempel #define SHPCHECK(__hw_rate, __flags) \ 9313f71050SOleksij Rempel ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) 9413f71050SOleksij Rempel 9513f71050SOleksij Rempel #define RATE(_bitrate, _hw_rate, _flags) { \ 9613f71050SOleksij Rempel .bitrate = (_bitrate), \ 9713f71050SOleksij Rempel .flags = (_flags), \ 9813f71050SOleksij Rempel .hw_value = (_hw_rate), \ 9913f71050SOleksij Rempel .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ 10013f71050SOleksij Rempel } 10113f71050SOleksij Rempel 10213f71050SOleksij Rempel static struct ieee80211_rate ath9k_legacy_rates[] = { 10313f71050SOleksij Rempel RATE(10, 0x1b, 0), 10413f71050SOleksij Rempel RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), 10513f71050SOleksij Rempel RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), 10613f71050SOleksij Rempel RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), 10713f71050SOleksij Rempel RATE(60, 0x0b, (IEEE80211_RATE_SUPPORTS_5MHZ | 10813f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 10913f71050SOleksij Rempel RATE(90, 0x0f, (IEEE80211_RATE_SUPPORTS_5MHZ | 11013f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 11113f71050SOleksij Rempel RATE(120, 0x0a, (IEEE80211_RATE_SUPPORTS_5MHZ | 11213f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 11313f71050SOleksij Rempel RATE(180, 0x0e, (IEEE80211_RATE_SUPPORTS_5MHZ | 11413f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 11513f71050SOleksij Rempel RATE(240, 0x09, (IEEE80211_RATE_SUPPORTS_5MHZ | 11613f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 11713f71050SOleksij Rempel RATE(360, 0x0d, (IEEE80211_RATE_SUPPORTS_5MHZ | 11813f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 11913f71050SOleksij Rempel RATE(480, 0x08, (IEEE80211_RATE_SUPPORTS_5MHZ | 12013f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 12113f71050SOleksij Rempel RATE(540, 0x0c, (IEEE80211_RATE_SUPPORTS_5MHZ | 12213f71050SOleksij Rempel IEEE80211_RATE_SUPPORTS_10MHZ)), 12313f71050SOleksij Rempel }; 12413f71050SOleksij Rempel 12513f71050SOleksij Rempel int ath9k_cmn_init_channels_rates(struct ath_common *common) 12613f71050SOleksij Rempel { 12713f71050SOleksij Rempel struct ath_hw *ah = (struct ath_hw *)common->ah; 12813f71050SOleksij Rempel void *channels; 12913f71050SOleksij Rempel 13013f71050SOleksij Rempel BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) + 13113f71050SOleksij Rempel ARRAY_SIZE(ath9k_5ghz_chantable) != 13213f71050SOleksij Rempel ATH9K_NUM_CHANNELS); 13313f71050SOleksij Rempel 13413f71050SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { 13513f71050SOleksij Rempel channels = devm_kzalloc(ah->dev, 13613f71050SOleksij Rempel sizeof(ath9k_2ghz_chantable), GFP_KERNEL); 13713f71050SOleksij Rempel if (!channels) 13813f71050SOleksij Rempel return -ENOMEM; 13913f71050SOleksij Rempel 14013f71050SOleksij Rempel memcpy(channels, ath9k_2ghz_chantable, 14113f71050SOleksij Rempel sizeof(ath9k_2ghz_chantable)); 14257fbcce3SJohannes Berg common->sbands[NL80211_BAND_2GHZ].channels = channels; 14357fbcce3SJohannes Berg common->sbands[NL80211_BAND_2GHZ].band = NL80211_BAND_2GHZ; 14457fbcce3SJohannes Berg common->sbands[NL80211_BAND_2GHZ].n_channels = 14513f71050SOleksij Rempel ARRAY_SIZE(ath9k_2ghz_chantable); 14657fbcce3SJohannes Berg common->sbands[NL80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; 14757fbcce3SJohannes Berg common->sbands[NL80211_BAND_2GHZ].n_bitrates = 14813f71050SOleksij Rempel ARRAY_SIZE(ath9k_legacy_rates); 14913f71050SOleksij Rempel } 15013f71050SOleksij Rempel 15113f71050SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { 15213f71050SOleksij Rempel channels = devm_kzalloc(ah->dev, 15313f71050SOleksij Rempel sizeof(ath9k_5ghz_chantable), GFP_KERNEL); 15413f71050SOleksij Rempel if (!channels) 15513f71050SOleksij Rempel return -ENOMEM; 15613f71050SOleksij Rempel 15713f71050SOleksij Rempel memcpy(channels, ath9k_5ghz_chantable, 15813f71050SOleksij Rempel sizeof(ath9k_5ghz_chantable)); 15957fbcce3SJohannes Berg common->sbands[NL80211_BAND_5GHZ].channels = channels; 16057fbcce3SJohannes Berg common->sbands[NL80211_BAND_5GHZ].band = NL80211_BAND_5GHZ; 16157fbcce3SJohannes Berg common->sbands[NL80211_BAND_5GHZ].n_channels = 16213f71050SOleksij Rempel ARRAY_SIZE(ath9k_5ghz_chantable); 16357fbcce3SJohannes Berg common->sbands[NL80211_BAND_5GHZ].bitrates = 16413f71050SOleksij Rempel ath9k_legacy_rates + 4; 16557fbcce3SJohannes Berg common->sbands[NL80211_BAND_5GHZ].n_bitrates = 16613f71050SOleksij Rempel ARRAY_SIZE(ath9k_legacy_rates) - 4; 16713f71050SOleksij Rempel } 16813f71050SOleksij Rempel return 0; 16913f71050SOleksij Rempel } 17013f71050SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_init_channels_rates); 171b60d1052SOleksij Rempel 172b60d1052SOleksij Rempel void ath9k_cmn_setup_ht_cap(struct ath_hw *ah, 173b60d1052SOleksij Rempel struct ieee80211_sta_ht_cap *ht_info) 174b60d1052SOleksij Rempel { 175b60d1052SOleksij Rempel struct ath_common *common = ath9k_hw_common(ah); 176b60d1052SOleksij Rempel u8 tx_streams, rx_streams; 177b60d1052SOleksij Rempel int i, max_streams; 178b60d1052SOleksij Rempel 179b60d1052SOleksij Rempel ht_info->ht_supported = true; 180b60d1052SOleksij Rempel ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 181b60d1052SOleksij Rempel IEEE80211_HT_CAP_SM_PS | 182b60d1052SOleksij Rempel IEEE80211_HT_CAP_SGI_40 | 183b60d1052SOleksij Rempel IEEE80211_HT_CAP_DSSSCCK40; 184b60d1052SOleksij Rempel 185b60d1052SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) 186b60d1052SOleksij Rempel ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; 187b60d1052SOleksij Rempel 188b60d1052SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) 189b60d1052SOleksij Rempel ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 190b60d1052SOleksij Rempel 191b60d1052SOleksij Rempel ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 192b60d1052SOleksij Rempel ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 193b60d1052SOleksij Rempel 19491884fadSOleksij Rempel if (AR_SREV_9271(ah) || AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) 195b60d1052SOleksij Rempel max_streams = 1; 196b60d1052SOleksij Rempel else if (AR_SREV_9462(ah)) 197b60d1052SOleksij Rempel max_streams = 2; 198b60d1052SOleksij Rempel else if (AR_SREV_9300_20_OR_LATER(ah)) 199b60d1052SOleksij Rempel max_streams = 3; 200b60d1052SOleksij Rempel else 201b60d1052SOleksij Rempel max_streams = 2; 202b60d1052SOleksij Rempel 203b60d1052SOleksij Rempel if (AR_SREV_9280_20_OR_LATER(ah)) { 204b60d1052SOleksij Rempel if (max_streams >= 2) 205b60d1052SOleksij Rempel ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; 206b60d1052SOleksij Rempel ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 207b60d1052SOleksij Rempel } 208b60d1052SOleksij Rempel 209b60d1052SOleksij Rempel /* set up supported mcs set */ 210b60d1052SOleksij Rempel memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 211b60d1052SOleksij Rempel tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams); 212b60d1052SOleksij Rempel rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams); 213b60d1052SOleksij Rempel 214b60d1052SOleksij Rempel ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n", 215b60d1052SOleksij Rempel tx_streams, rx_streams); 216b60d1052SOleksij Rempel 217b60d1052SOleksij Rempel if (tx_streams != rx_streams) { 218b60d1052SOleksij Rempel ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 219b60d1052SOleksij Rempel ht_info->mcs.tx_params |= ((tx_streams - 1) << 220b60d1052SOleksij Rempel IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 221b60d1052SOleksij Rempel } 222b60d1052SOleksij Rempel 223b60d1052SOleksij Rempel for (i = 0; i < rx_streams; i++) 224b60d1052SOleksij Rempel ht_info->mcs.rx_mask[i] = 0xff; 225b60d1052SOleksij Rempel 226b60d1052SOleksij Rempel ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 227b60d1052SOleksij Rempel } 228b60d1052SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_setup_ht_cap); 229b57ba3b2SOleksij Rempel 230b57ba3b2SOleksij Rempel void ath9k_cmn_reload_chainmask(struct ath_hw *ah) 231b57ba3b2SOleksij Rempel { 232b57ba3b2SOleksij Rempel struct ath_common *common = ath9k_hw_common(ah); 233b57ba3b2SOleksij Rempel 234b57ba3b2SOleksij Rempel if (!(ah->caps.hw_caps & ATH9K_HW_CAP_HT)) 235b57ba3b2SOleksij Rempel return; 236b57ba3b2SOleksij Rempel 237b57ba3b2SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) 238b57ba3b2SOleksij Rempel ath9k_cmn_setup_ht_cap(ah, 23957fbcce3SJohannes Berg &common->sbands[NL80211_BAND_2GHZ].ht_cap); 240b57ba3b2SOleksij Rempel if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) 241b57ba3b2SOleksij Rempel ath9k_cmn_setup_ht_cap(ah, 24257fbcce3SJohannes Berg &common->sbands[NL80211_BAND_5GHZ].ht_cap); 243b57ba3b2SOleksij Rempel } 244b57ba3b2SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_reload_chainmask); 245