18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2010 Broadcom Corporation 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 ANY 118c2ecf20Sopenharmony_ci * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 138c2ecf20Sopenharmony_ci * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 148c2ecf20Sopenharmony_ci * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#ifndef _BRCM_RATE_H_ 188c2ecf20Sopenharmony_ci#define _BRCM_RATE_H_ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "types.h" 218c2ecf20Sopenharmony_ci#include "d11.h" 228c2ecf20Sopenharmony_ci#include "phy_hal.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciextern const u8 rate_info[]; 258c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset cck_ofdm_mimo_rates; 268c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset ofdm_mimo_rates; 278c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset cck_ofdm_rates; 288c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset ofdm_rates; 298c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset cck_rates; 308c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset gphy_legacy_rates; 318c2ecf20Sopenharmony_ciextern const struct brcms_c_rateset rate_limit_1_2; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct brcms_mcs_info { 348c2ecf20Sopenharmony_ci /* phy rate in kbps [20Mhz] */ 358c2ecf20Sopenharmony_ci u32 phy_rate_20; 368c2ecf20Sopenharmony_ci /* phy rate in kbps [40Mhz] */ 378c2ecf20Sopenharmony_ci u32 phy_rate_40; 388c2ecf20Sopenharmony_ci /* phy rate in kbps [20Mhz] with SGI */ 398c2ecf20Sopenharmony_ci u32 phy_rate_20_sgi; 408c2ecf20Sopenharmony_ci /* phy rate in kbps [40Mhz] with SGI */ 418c2ecf20Sopenharmony_ci u32 phy_rate_40_sgi; 428c2ecf20Sopenharmony_ci /* phy ctl byte 3, code rate, modulation type, # of streams */ 438c2ecf20Sopenharmony_ci u8 tx_phy_ctl3; 448c2ecf20Sopenharmony_ci /* matching legacy ofdm rate in 500bkps */ 458c2ecf20Sopenharmony_ci u8 leg_ofdm; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define BRCMS_MAXMCS 32 /* max valid mcs index */ 498c2ecf20Sopenharmony_ci#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ 508c2ecf20Sopenharmony_ciextern const struct brcms_mcs_info mcs_table[]; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ 538c2ecf20Sopenharmony_ci#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* returns num tx streams - 1 */ 568c2ecf20Sopenharmony_cistatic inline u8 mcs_2_txstreams(u8 mcs) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci if (sgi) { 648c2ecf20Sopenharmony_ci if (is40) 658c2ecf20Sopenharmony_ci return mcs_table[mcs].phy_rate_40_sgi; 668c2ecf20Sopenharmony_ci return mcs_table[mcs].phy_rate_20_sgi; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci if (is40) 698c2ecf20Sopenharmony_ci return mcs_table[mcs].phy_rate_40; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return mcs_table[mcs].phy_rate_20; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* Macro to use the rate_info table */ 758c2ecf20Sopenharmony_ci#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * rate spec : holds rate and mode specific information required to generate a 798c2ecf20Sopenharmony_ci * tx frame. Legacy CCK and OFDM information is held in the same manner as was 808c2ecf20Sopenharmony_ci * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO 818c2ecf20Sopenharmony_ci * specific information 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* rate spec bit fields */ 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* Either 500Kbps units or MIMO MCS idx */ 878c2ecf20Sopenharmony_ci#define RSPEC_RATE_MASK 0x0000007F 888c2ecf20Sopenharmony_ci/* mimo MCS is stored in RSPEC_RATE_MASK */ 898c2ecf20Sopenharmony_ci#define RSPEC_MIMORATE 0x08000000 908c2ecf20Sopenharmony_ci/* mimo bw mask */ 918c2ecf20Sopenharmony_ci#define RSPEC_BW_MASK 0x00000700 928c2ecf20Sopenharmony_ci/* mimo bw shift */ 938c2ecf20Sopenharmony_ci#define RSPEC_BW_SHIFT 8 948c2ecf20Sopenharmony_ci/* mimo Space/Time/Frequency mode mask */ 958c2ecf20Sopenharmony_ci#define RSPEC_STF_MASK 0x00003800 968c2ecf20Sopenharmony_ci/* mimo Space/Time/Frequency mode shift */ 978c2ecf20Sopenharmony_ci#define RSPEC_STF_SHIFT 11 988c2ecf20Sopenharmony_ci/* mimo coding type mask */ 998c2ecf20Sopenharmony_ci#define RSPEC_CT_MASK 0x0000C000 1008c2ecf20Sopenharmony_ci/* mimo coding type shift */ 1018c2ecf20Sopenharmony_ci#define RSPEC_CT_SHIFT 14 1028c2ecf20Sopenharmony_ci/* mimo num STC streams per PLCP defn. */ 1038c2ecf20Sopenharmony_ci#define RSPEC_STC_MASK 0x00300000 1048c2ecf20Sopenharmony_ci/* mimo num STC streams per PLCP defn. */ 1058c2ecf20Sopenharmony_ci#define RSPEC_STC_SHIFT 20 1068c2ecf20Sopenharmony_ci/* mimo bit indicates adv coding in use */ 1078c2ecf20Sopenharmony_ci#define RSPEC_LDPC_CODING 0x00400000 1088c2ecf20Sopenharmony_ci/* mimo bit indicates short GI in use */ 1098c2ecf20Sopenharmony_ci#define RSPEC_SHORT_GI 0x00800000 1108c2ecf20Sopenharmony_ci/* bit indicates override both rate & mode */ 1118c2ecf20Sopenharmony_ci#define RSPEC_OVERRIDE 0x80000000 1128c2ecf20Sopenharmony_ci/* bit indicates override rate only */ 1138c2ecf20Sopenharmony_ci#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic inline bool rspec_active(u32 rspec) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic inline u8 rspec_phytxbyte2(u32 rspec) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci return (rspec & 0xff00) >> 8; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic inline u32 rspec_get_bw(u32 rspec) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic inline bool rspec_issgi(u32 rspec) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic inline bool rspec_is40mhz(u32 rspec) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci u32 bw = rspec_get_bw(rspec); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic inline uint rspec2rate(u32 rspec) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci if (rspec & RSPEC_MIMORATE) 1458c2ecf20Sopenharmony_ci return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), 1468c2ecf20Sopenharmony_ci rspec_issgi(rspec)); 1478c2ecf20Sopenharmony_ci return rspec & RSPEC_RATE_MASK; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic inline u8 rspec_mimoplcp3(u32 rspec) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci return (rspec & 0xf00000) >> 16; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic inline bool plcp3_issgi(u8 plcp) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic inline uint rspec_stc(u32 rspec) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic inline uint rspec_stf(u32 rspec) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic inline bool is_mcs_rate(u32 ratespec) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci return (ratespec & RSPEC_MIMORATE) != 0; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic inline bool is_ofdm_rate(u32 ratespec) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci return !is_mcs_rate(ratespec) && 1788c2ecf20Sopenharmony_ci (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic inline bool is_cck_rate(u32 ratespec) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci u32 rate = (ratespec & BRCMS_RATE_MASK); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return !is_mcs_rate(ratespec) && ( 1868c2ecf20Sopenharmony_ci rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || 1878c2ecf20Sopenharmony_ci rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic inline bool is_single_stream(u8 mcs) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic inline u8 cck_rspec(u8 cck) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci return cck & RSPEC_RATE_MASK; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/* Convert encoded rate value in plcp header to numerical rates in 500 KHz 2018c2ecf20Sopenharmony_ci * increments */ 2028c2ecf20Sopenharmony_cistatic inline u8 ofdm_phy2mac_rate(u8 rlpt) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7]; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic inline u8 cck_phy2mac_rate(u8 signal) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci return signal/5; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* Rates specified in brcms_c_rateset_filter() */ 2138c2ecf20Sopenharmony_ci#define BRCMS_RATES_CCK_OFDM 0 2148c2ecf20Sopenharmony_ci#define BRCMS_RATES_CCK 1 2158c2ecf20Sopenharmony_ci#define BRCMS_RATES_OFDM 2 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci/* sanitize, and sort a rateset with the basic bit(s) preserved, validate 2188c2ecf20Sopenharmony_ci * rateset */ 2198c2ecf20Sopenharmony_cibool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, 2208c2ecf20Sopenharmony_ci const struct brcms_c_rateset *hw_rs, 2218c2ecf20Sopenharmony_ci bool check_brate, u8 txstreams); 2228c2ecf20Sopenharmony_ci/* copy rateset src to dst as-is (no masking or sorting) */ 2238c2ecf20Sopenharmony_civoid brcms_c_rateset_copy(const struct brcms_c_rateset *src, 2248c2ecf20Sopenharmony_ci struct brcms_c_rateset *dst); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci/* would be nice to have these documented ... */ 2278c2ecf20Sopenharmony_ciu32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_civoid brcms_c_rateset_filter(struct brcms_c_rateset *src, 2308c2ecf20Sopenharmony_ci struct brcms_c_rateset *dst, bool basic_only, 2318c2ecf20Sopenharmony_ci u8 rates, uint xmask, bool mcsallow); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_civoid brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, 2348c2ecf20Sopenharmony_ci const struct brcms_c_rateset *rs_hw, uint phy_type, 2358c2ecf20Sopenharmony_ci int bandtype, bool cck_only, uint rate_mask, 2368c2ecf20Sopenharmony_ci bool mcsallow, u8 bw, u8 txstreams); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cis16 brcms_c_rate_legacy_phyctl(uint rate); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_civoid brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); 2418c2ecf20Sopenharmony_civoid brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); 2428c2ecf20Sopenharmony_civoid brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams); 2438c2ecf20Sopenharmony_civoid brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci#endif /* _BRCM_RATE_H_ */ 246