Commit | Line | Data |
---|---|---|
5b435de0 AS |
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" | |
1433c59b | 22 | #include "phy_hal.h" |
5b435de0 AS |
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 */ | |
5b435de0 AS |
202 | static inline u8 ofdm_phy2mac_rate(u8 rlpt) |
203 | { | |
1433c59b | 204 | return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7]; |
5b435de0 AS |
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 | extern bool | |
220 | brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, | |
221 | const struct brcms_c_rateset *hw_rs, | |
222 | bool check_brate, u8 txstreams); | |
223 | /* copy rateset src to dst as-is (no masking or sorting) */ | |
224 | extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, | |
225 | struct brcms_c_rateset *dst); | |
226 | ||
227 | /* would be nice to have these documented ... */ | |
228 | extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); | |
229 | ||
230 | extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, | |
231 | struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, | |
232 | bool mcsallow); | |
233 | ||
234 | extern void | |
235 | brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, | |
236 | const struct brcms_c_rateset *rs_hw, uint phy_type, | |
237 | int bandtype, bool cck_only, uint rate_mask, | |
238 | bool mcsallow, u8 bw, u8 txstreams); | |
239 | ||
240 | extern s16 brcms_c_rate_legacy_phyctl(uint rate); | |
241 | ||
242 | extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); | |
243 | extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); | |
244 | extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, | |
245 | u8 txstreams); | |
246 | extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, | |
247 | u8 bw); | |
248 | ||
249 | #endif /* _BRCM_RATE_H_ */ |