1 /* 2 * Copyright (c) 2010 Broadcom Corporation 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef _BRCM_RATE_H_ 18 #define _BRCM_RATE_H_ 19 20 #include "types.h" 21 #include "d11.h" 22 #include "phy_hal.h" 23 24 extern const u8 rate_info[]; 25 extern const struct brcms_c_rateset cck_ofdm_mimo_rates; 26 extern const struct brcms_c_rateset ofdm_mimo_rates; 27 extern const struct brcms_c_rateset cck_ofdm_rates; 28 extern const struct brcms_c_rateset ofdm_rates; 29 extern const struct brcms_c_rateset cck_rates; 30 extern const struct brcms_c_rateset gphy_legacy_rates; 31 extern const struct brcms_c_rateset rate_limit_1_2; 32 33 struct brcms_mcs_info { 34 /* phy rate in kbps [20Mhz] */ 35 u32 phy_rate_20; 36 /* phy rate in kbps [40Mhz] */ 37 u32 phy_rate_40; 38 /* phy rate in kbps [20Mhz] with SGI */ 39 u32 phy_rate_20_sgi; 40 /* phy rate in kbps [40Mhz] with SGI */ 41 u32 phy_rate_40_sgi; 42 /* phy ctl byte 3, code rate, modulation type, # of streams */ 43 u8 tx_phy_ctl3; 44 /* matching legacy ofdm rate in 500bkps */ 45 u8 leg_ofdm; 46 }; 47 48 #define BRCMS_MAXMCS 32 /* max valid mcs index */ 49 #define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ 50 extern const struct brcms_mcs_info mcs_table[]; 51 52 #define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ 53 #define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ 54 55 /* returns num tx streams - 1 */ 56 static inline u8 mcs_2_txstreams(u8 mcs) 57 { 58 return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; 59 } 60 61 static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) 62 { 63 if (sgi) { 64 if (is40) 65 return mcs_table[mcs].phy_rate_40_sgi; 66 return mcs_table[mcs].phy_rate_20_sgi; 67 } 68 if (is40) 69 return mcs_table[mcs].phy_rate_40; 70 71 return mcs_table[mcs].phy_rate_20; 72 } 73 74 /* Macro to use the rate_info table */ 75 #define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ 76 77 /* 78 * rate spec : holds rate and mode specific information required to generate a 79 * tx frame. Legacy CCK and OFDM information is held in the same manner as was 80 * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO 81 * specific information 82 */ 83 84 /* rate spec bit fields */ 85 86 /* Either 500Kbps units or MIMO MCS idx */ 87 #define RSPEC_RATE_MASK 0x0000007F 88 /* mimo MCS is stored in RSPEC_RATE_MASK */ 89 #define RSPEC_MIMORATE 0x08000000 90 /* mimo bw mask */ 91 #define RSPEC_BW_MASK 0x00000700 92 /* mimo bw shift */ 93 #define RSPEC_BW_SHIFT 8 94 /* mimo Space/Time/Frequency mode mask */ 95 #define RSPEC_STF_MASK 0x00003800 96 /* mimo Space/Time/Frequency mode shift */ 97 #define RSPEC_STF_SHIFT 11 98 /* mimo coding type mask */ 99 #define RSPEC_CT_MASK 0x0000C000 100 /* mimo coding type shift */ 101 #define RSPEC_CT_SHIFT 14 102 /* mimo num STC streams per PLCP defn. */ 103 #define RSPEC_STC_MASK 0x00300000 104 /* mimo num STC streams per PLCP defn. */ 105 #define RSPEC_STC_SHIFT 20 106 /* mimo bit indicates adv coding in use */ 107 #define RSPEC_LDPC_CODING 0x00400000 108 /* mimo bit indicates short GI in use */ 109 #define RSPEC_SHORT_GI 0x00800000 110 /* bit indicates override both rate & mode */ 111 #define RSPEC_OVERRIDE 0x80000000 112 /* bit indicates override rate only */ 113 #define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 114 115 static inline bool rspec_active(u32 rspec) 116 { 117 return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); 118 } 119 120 static inline u8 rspec_phytxbyte2(u32 rspec) 121 { 122 return (rspec & 0xff00) >> 8; 123 } 124 125 static inline u32 rspec_get_bw(u32 rspec) 126 { 127 return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; 128 } 129 130 static inline bool rspec_issgi(u32 rspec) 131 { 132 return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; 133 } 134 135 static inline bool rspec_is40mhz(u32 rspec) 136 { 137 u32 bw = rspec_get_bw(rspec); 138 139 return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; 140 } 141 142 static inline uint rspec2rate(u32 rspec) 143 { 144 if (rspec & RSPEC_MIMORATE) 145 return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), 146 rspec_issgi(rspec)); 147 return rspec & RSPEC_RATE_MASK; 148 } 149 150 static inline u8 rspec_mimoplcp3(u32 rspec) 151 { 152 return (rspec & 0xf00000) >> 16; 153 } 154 155 static inline bool plcp3_issgi(u8 plcp) 156 { 157 return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; 158 } 159 160 static inline uint rspec_stc(u32 rspec) 161 { 162 return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; 163 } 164 165 static inline uint rspec_stf(u32 rspec) 166 { 167 return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; 168 } 169 170 static inline bool is_mcs_rate(u32 ratespec) 171 { 172 return (ratespec & RSPEC_MIMORATE) != 0; 173 } 174 175 static inline bool is_ofdm_rate(u32 ratespec) 176 { 177 return !is_mcs_rate(ratespec) && 178 (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); 179 } 180 181 static inline bool is_cck_rate(u32 ratespec) 182 { 183 u32 rate = (ratespec & BRCMS_RATE_MASK); 184 185 return !is_mcs_rate(ratespec) && ( 186 rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || 187 rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); 188 } 189 190 static inline bool is_single_stream(u8 mcs) 191 { 192 return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; 193 } 194 195 static inline u8 cck_rspec(u8 cck) 196 { 197 return cck & RSPEC_RATE_MASK; 198 } 199 200 /* Convert encoded rate value in plcp header to numerical rates in 500 KHz 201 * increments */ 202 static inline u8 ofdm_phy2mac_rate(u8 rlpt) 203 { 204 return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7]; 205 } 206 207 static inline u8 cck_phy2mac_rate(u8 signal) 208 { 209 return signal/5; 210 } 211 212 /* Rates specified in brcms_c_rateset_filter() */ 213 #define BRCMS_RATES_CCK_OFDM 0 214 #define BRCMS_RATES_CCK 1 215 #define BRCMS_RATES_OFDM 2 216 217 /* sanitize, and sort a rateset with the basic bit(s) preserved, validate 218 * rateset */ 219 bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, 220 const struct brcms_c_rateset *hw_rs, 221 bool check_brate, u8 txstreams); 222 /* copy rateset src to dst as-is (no masking or sorting) */ 223 void brcms_c_rateset_copy(const struct brcms_c_rateset *src, 224 struct brcms_c_rateset *dst); 225 226 /* would be nice to have these documented ... */ 227 u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); 228 229 void brcms_c_rateset_filter(struct brcms_c_rateset *src, 230 struct brcms_c_rateset *dst, bool basic_only, 231 u8 rates, uint xmask, bool mcsallow); 232 233 void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, 234 const struct brcms_c_rateset *rs_hw, uint phy_type, 235 int bandtype, bool cck_only, uint rate_mask, 236 bool mcsallow, u8 bw, u8 txstreams); 237 238 s16 brcms_c_rate_legacy_phyctl(uint rate); 239 240 void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); 241 void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); 242 void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams); 243 void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw); 244 245 #endif /* _BRCM_RATE_H_ */ 246