Message ID | 1542367879-28880-2-git-send-email-yhchuang@realtek.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kalle Valo |
Headers | show |
Series | rtw88: mac80211 driver for Realtek 802.11ac wireless network chips | expand |
Hi Kalle, This patch added a comment about our watch dog timer, please let me know if you are OK with it. Also if you have other questions about the series, just point it out and I will try to fix it. Thanks. Yan-Hsuan > -----Original Message----- > From: linux-wireless-owner@vger.kernel.org > [mailto:linux-wireless-owner@vger.kernel.org] On Behalf Of > yhchuang@realtek.com > Sent: Friday, November 16, 2018 7:31 PM > To: kvalo@codeaurora.org > Cc: Larry.Finger@lwfinger.net; linux-wireless@vger.kernel.org; Pkshih; Andy > Huang > Subject: [PATCH v2 01/13] rtw88: main files > > From: Yan-Hsuan Chuang <yhchuang@realtek.com> > > main files for Realtek 802.11ac wireless network chips > > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> > --- > drivers/net/wireless/realtek/rtw88/mac80211.c | 480 ++++++++++ > drivers/net/wireless/realtek/rtw88/main.c | 1190 > +++++++++++++++++++++++++ > drivers/net/wireless/realtek/rtw88/main.h | 1119 > +++++++++++++++++++++++ > drivers/net/wireless/realtek/rtw88/reg.h | 411 +++++++++ > 4 files changed, 3200 insertions(+) > create mode 100644 drivers/net/wireless/realtek/rtw88/mac80211.c > create mode 100644 drivers/net/wireless/realtek/rtw88/main.c > create mode 100644 drivers/net/wireless/realtek/rtw88/main.h > create mode 100644 drivers/net/wireless/realtek/rtw88/reg.h > > diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c > b/drivers/net/wireless/realtek/rtw88/mac80211.c > new file mode 100644 > index 0000000..17b3651 > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c > @@ -0,0 +1,480 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright(c) 2018 Realtek Corporation. > + */ > + > +#include "main.h" > +#include "sec.h" > +#include "tx.h" > +#include "fw.h" > +#include "mac.h" > +#include "ps.h" > +#include "reg.h" > +#include "debug.h" > + > +static void rtw_ops_tx(struct ieee80211_hw *hw, > + struct ieee80211_tx_control *control, > + struct sk_buff *skb) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_tx_pkt_info pkt_info = {0}; > + > + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) > + goto out; > + > + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb); > + if (rtw_hci_tx(rtwdev, &pkt_info, skb)) > + goto out; > + > + return; > + > +out: > + ieee80211_free_txskb(hw, skb); > +} > + > +static int rtw_ops_start(struct ieee80211_hw *hw) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + int ret; > + > + mutex_lock(&rtwdev->mutex); > + ret = rtw_core_start(rtwdev); > + mutex_unlock(&rtwdev->mutex); > + > + return ret; > +} > + > +static void rtw_ops_stop(struct ieee80211_hw *hw) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + > + mutex_lock(&rtwdev->mutex); > + rtw_core_stop(rtwdev); > + mutex_unlock(&rtwdev->mutex); > +} > + > +static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + int ret = 0; > + > + mutex_lock(&rtwdev->mutex); > + > + if (changed & IEEE80211_CONF_CHANGE_IDLE) { > + if (hw->conf.flags & IEEE80211_CONF_IDLE) { > + rtw_enter_ips(rtwdev); > + } else { > + ret = rtw_leave_ips(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to leave idle state\n"); > + goto out; > + } > + } > + } > + > + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) > + rtw_set_channel(rtwdev); > + > +out: > + mutex_unlock(&rtwdev->mutex); > + return ret; > +} > + > +static const struct rtw_vif_port rtw_vif_port[] = { > + [0] = { > + .mac_addr = {.addr = 0x0610}, > + .bssid = {.addr = 0x0618}, > + .net_type = {.addr = 0x0100, .mask = 0x30000}, > + .aid = {.addr = 0x06a8, .mask = 0x7ff}, > + }, > + [1] = { > + .mac_addr = {.addr = 0x0700}, > + .bssid = {.addr = 0x0708}, > + .net_type = {.addr = 0x0100, .mask = 0xc0000}, > + .aid = {.addr = 0x0710, .mask = 0x7ff}, > + }, > + [2] = { > + .mac_addr = {.addr = 0x1620}, > + .bssid = {.addr = 0x1628}, > + .net_type = {.addr = 0x1100, .mask = 0x3}, > + .aid = {.addr = 0x1600, .mask = 0x7ff}, > + }, > + [3] = { > + .mac_addr = {.addr = 0x1630}, > + .bssid = {.addr = 0x1638}, > + .net_type = {.addr = 0x1100, .mask = 0xc}, > + .aid = {.addr = 0x1604, .mask = 0x7ff}, > + }, > + [4] = { > + .mac_addr = {.addr = 0x1640}, > + .bssid = {.addr = 0x1648}, > + .net_type = {.addr = 0x1100, .mask = 0x30}, > + .aid = {.addr = 0x1608, .mask = 0x7ff}, > + }, > +}; > + > +static int rtw_ops_add_interface(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; > + enum rtw_net_type net_type; > + u32 config = 0; > + u8 port = 0; > + > + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; > + rtwvif->port = port; > + rtwvif->vif = vif; > + rtwvif->stats.tx_unicast = 0; > + rtwvif->stats.rx_unicast = 0; > + rtwvif->stats.tx_cnt = 0; > + rtwvif->stats.rx_cnt = 0; > + rtwvif->in_lps = false; > + rtwvif->conf = &rtw_vif_port[port]; > + > + mutex_lock(&rtwdev->mutex); > + > + switch (vif->type) { > + case NL80211_IFTYPE_AP: > + case NL80211_IFTYPE_MESH_POINT: > + net_type = RTW_NET_AP_MODE; > + break; > + case NL80211_IFTYPE_ADHOC: > + net_type = RTW_NET_AD_HOC; > + break; > + case NL80211_IFTYPE_STATION: > + default: > + net_type = RTW_NET_NO_LINK; > + break; > + } > + > + ether_addr_copy(rtwvif->mac_addr, vif->addr); > + config |= PORT_SET_MAC_ADDR; > + rtwvif->net_type = net_type; > + config |= PORT_SET_NET_TYPE; > + rtw_vif_port_config(rtwdev, rtwvif, config); > + > + mutex_unlock(&rtwdev->mutex); > + > + rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port); > + return 0; > +} > + > +static void rtw_ops_remove_interface(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; > + u32 config = 0; > + > + rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port); > + > + mutex_lock(&rtwdev->mutex); > + > + eth_zero_addr(rtwvif->mac_addr); > + config |= PORT_SET_MAC_ADDR; > + rtwvif->net_type = RTW_NET_NO_LINK; > + config |= PORT_SET_NET_TYPE; > + rtw_vif_port_config(rtwdev, rtwvif, config); > + > + mutex_unlock(&rtwdev->mutex); > +} > + > +static void rtw_ops_configure_filter(struct ieee80211_hw *hw, > + unsigned int changed_flags, > + unsigned int *new_flags, > + u64 multicast) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + > + *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL | > + FIF_BCN_PRBRESP_PROMISC; > + > + mutex_lock(&rtwdev->mutex); > + > + if (changed_flags & FIF_ALLMULTI) { > + if (*new_flags & FIF_ALLMULTI) > + rtwdev->hal.rcr |= BIT_AM | BIT_AB; > + else > + rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB); > + } > + if (changed_flags & FIF_FCSFAIL) { > + if (*new_flags & FIF_FCSFAIL) > + rtwdev->hal.rcr |= BIT_ACRC32; > + else > + rtwdev->hal.rcr &= ~(BIT_ACRC32); > + } > + if (changed_flags & FIF_OTHER_BSS) { > + if (*new_flags & FIF_OTHER_BSS) > + rtwdev->hal.rcr |= BIT_AAP; > + else > + rtwdev->hal.rcr &= ~(BIT_AAP); > + } > + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { > + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) > + rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA); > + else > + rtwdev->hal.rcr |= BIT_CBSSID_BCN; > + } > + > + rtw_dbg(rtwdev, "config rx filter, changed=0x%08x, new=0x%08x, > rcr=0x%08x\n", > + changed_flags, *new_flags, rtwdev->hal.rcr); > + > + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); > + > + mutex_unlock(&rtwdev->mutex); > +} > + > +static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + struct ieee80211_bss_conf *conf, > + u32 changed) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; > + u32 config = 0; > + > + mutex_lock(&rtwdev->mutex); > + > + if (changed & BSS_CHANGED_ASSOC) { > + struct rtw_chip_info *chip = rtwdev->chip; > + enum rtw_net_type net_type; > + > + if (conf->assoc) { > + net_type = RTW_NET_MGD_LINKED; > + chip->ops->do_iqk(rtwdev); > + > + rtwvif->aid = conf->aid; > + rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); > + rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); > + rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); > + rtw_fw_download_rsvd_page(rtwdev, vif); > + } else { > + net_type = RTW_NET_NO_LINK; > + rtwvif->aid = 0; > + rtw_reset_rsvd_page(rtwdev); > + } > + > + rtwvif->net_type = net_type; > + config |= PORT_SET_NET_TYPE; > + config |= PORT_SET_AID; > + } > + > + if (changed & BSS_CHANGED_BSSID) { > + ether_addr_copy(rtwvif->bssid, conf->bssid); > + config |= PORT_SET_BSSID; > + } > + > + if (changed & BSS_CHANGED_BEACON) > + rtw_fw_download_rsvd_page(rtwdev, vif); > + > + rtw_vif_port_config(rtwdev, rtwvif, config); > + > + mutex_unlock(&rtwdev->mutex); > +} > + > +static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) > +{ > + unsigned long mac_id; > + > + mac_id = find_first_zero_bit(rtwdev->mac_id_map, > RTW_MAX_MAC_ID_NUM); > + if (mac_id < RTW_MAX_MAC_ID_NUM) > + set_bit(mac_id, rtwdev->mac_id_map); > + > + return mac_id; > +} > + > +static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) > +{ > + clear_bit(mac_id, rtwdev->mac_id_map); > +} > + > +static int rtw_ops_sta_add(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + struct ieee80211_sta *sta) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; > + int ret = 0; > + > + mutex_lock(&rtwdev->mutex); > + > + si->mac_id = rtw_acquire_macid(rtwdev); > + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) { > + ret = -ENOSPC; > + goto out; > + } > + > + si->sta = sta; > + si->vif = vif; > + si->init_ra_lv = 1; > + ewma_rssi_init(&si->avg_rssi); > + > + rtw_update_sta_info(rtwdev, si); > + rtw_fw_media_status_report(rtwdev, si->mac_id, true); > + > + rtwdev->sta_cnt++; > + > + rtw_info(rtwdev, "sta %pM joined with macid %d\n", > + sta->addr, si->mac_id); > + > +out: > + mutex_unlock(&rtwdev->mutex); > + return ret; > +} > + > +static int rtw_ops_sta_remove(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + struct ieee80211_sta *sta) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; > + > + mutex_lock(&rtwdev->mutex); > + > + rtw_release_macid(rtwdev, si->mac_id); > + rtw_fw_media_status_report(rtwdev, si->mac_id, false); > + > + rtwdev->sta_cnt--; > + > + rtw_info(rtwdev, "sta %pM with macid %d left\n", > + sta->addr, si->mac_id); > + > + mutex_unlock(&rtwdev->mutex); > + return 0; > +} > + > +static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd > cmd, > + struct ieee80211_vif *vif, struct ieee80211_sta *sta, > + struct ieee80211_key_conf *key) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_sec_desc *sec = &rtwdev->sec; > + u8 hw_key_type; > + u8 hw_key_idx; > + int ret = 0; > + > + switch (key->cipher) { > + case WLAN_CIPHER_SUITE_WEP40: > + hw_key_type = RTW_CAM_WEP40; > + break; > + case WLAN_CIPHER_SUITE_WEP104: > + hw_key_type = RTW_CAM_WEP104; > + break; > + case WLAN_CIPHER_SUITE_TKIP: > + hw_key_type = RTW_CAM_TKIP; > + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; > + break; > + case WLAN_CIPHER_SUITE_CCMP: > + hw_key_type = RTW_CAM_AES; > + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; > + break; > + case WLAN_CIPHER_SUITE_AES_CMAC: > + case WLAN_CIPHER_SUITE_BIP_CMAC_256: > + case WLAN_CIPHER_SUITE_BIP_GMAC_128: > + case WLAN_CIPHER_SUITE_BIP_GMAC_256: > + /* suppress error messages */ > + return -EOPNOTSUPP; > + default: > + return -ENOTSUPP; > + } > + > + mutex_lock(&rtwdev->mutex); > + > + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { > + hw_key_idx = rtw_sec_get_free_cam(sec); > + } else { > + /* multiple interfaces? */ > + hw_key_idx = key->keyidx; > + } > + > + if (hw_key_idx > sec->total_cam_num) { > + ret = -ENOSPC; > + goto out; > + } > + > + switch (cmd) { > + case SET_KEY: > + /* need sw generated IV */ > + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; > + key->hw_key_idx = hw_key_idx; > + rtw_sec_write_cam(rtwdev, sec, sta, key, > + hw_key_type, hw_key_idx); > + break; > + case DISABLE_KEY: > + rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); > + break; > + } > + > +out: > + mutex_unlock(&rtwdev->mutex); > + > + return ret; > +} > + > +static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + struct ieee80211_ampdu_params *params) > +{ > + struct ieee80211_sta *sta = params->sta; > + u16 tid = params->tid; > + > + switch (params->action) { > + case IEEE80211_AMPDU_TX_START: > + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); > + break; > + case IEEE80211_AMPDU_TX_STOP_CONT: > + case IEEE80211_AMPDU_TX_STOP_FLUSH: > + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: > + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); > + break; > + case IEEE80211_AMPDU_TX_OPERATIONAL: > + case IEEE80211_AMPDU_RX_START: > + case IEEE80211_AMPDU_RX_STOP: > + break; > + default: > + WARN_ON(1); > + return -ENOTSUPP; > + } > + > + return 0; > +} > + > +static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + const u8 *mac_addr) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; > + > + rtw_leave_lps(rtwdev, rtwvif); > + > + rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE); > + rtw_flag_set(rtwdev, RTW_FLAG_SCANNING); > +} > + > +static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + > + rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING); > + rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE); > +} > + > +const struct ieee80211_ops rtw_ops = { > + .tx = rtw_ops_tx, > + .start = rtw_ops_start, > + .stop = rtw_ops_stop, > + .config = rtw_ops_config, > + .add_interface = rtw_ops_add_interface, > + .remove_interface = rtw_ops_remove_interface, > + .configure_filter = rtw_ops_configure_filter, > + .bss_info_changed = rtw_ops_bss_info_changed, > + .sta_add = rtw_ops_sta_add, > + .sta_remove = rtw_ops_sta_remove, > + .set_key = rtw_ops_set_key, > + .ampdu_action = rtw_ops_ampdu_action, > + .sw_scan_start = rtw_ops_sw_scan_start, > + .sw_scan_complete = rtw_ops_sw_scan_complete, > +}; > +EXPORT_SYMBOL(rtw_ops); > diff --git a/drivers/net/wireless/realtek/rtw88/main.c > b/drivers/net/wireless/realtek/rtw88/main.c > new file mode 100644 > index 0000000..a189c45 > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/main.c > @@ -0,0 +1,1190 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright(c) 2018 Realtek Corporation. > + */ > + > +#include "main.h" > +#include "regd.h" > +#include "fw.h" > +#include "ps.h" > +#include "sec.h" > +#include "mac.h" > +#include "phy.h" > +#include "reg.h" > +#include "efuse.h" > +#include "debug.h" > + > +static struct ieee80211_channel rtw_channeltable_2g[] = { > + {.center_freq = 2412, .hw_value = 1,}, > + {.center_freq = 2417, .hw_value = 2,}, > + {.center_freq = 2422, .hw_value = 3,}, > + {.center_freq = 2427, .hw_value = 4,}, > + {.center_freq = 2432, .hw_value = 5,}, > + {.center_freq = 2437, .hw_value = 6,}, > + {.center_freq = 2442, .hw_value = 7,}, > + {.center_freq = 2447, .hw_value = 8,}, > + {.center_freq = 2452, .hw_value = 9,}, > + {.center_freq = 2457, .hw_value = 10,}, > + {.center_freq = 2462, .hw_value = 11,}, > + {.center_freq = 2467, .hw_value = 12,}, > + {.center_freq = 2472, .hw_value = 13,}, > + {.center_freq = 2484, .hw_value = 14,}, > +}; > + > +static struct ieee80211_channel rtw_channeltable_5g[] = { > + {.center_freq = 5180, .hw_value = 36,}, > + {.center_freq = 5200, .hw_value = 40,}, > + {.center_freq = 5220, .hw_value = 44,}, > + {.center_freq = 5240, .hw_value = 48,}, > + {.center_freq = 5260, .hw_value = 52,}, > + {.center_freq = 5280, .hw_value = 56,}, > + {.center_freq = 5300, .hw_value = 60,}, > + {.center_freq = 5320, .hw_value = 64,}, > + {.center_freq = 5500, .hw_value = 100,}, > + {.center_freq = 5520, .hw_value = 104,}, > + {.center_freq = 5540, .hw_value = 108,}, > + {.center_freq = 5560, .hw_value = 112,}, > + {.center_freq = 5580, .hw_value = 116,}, > + {.center_freq = 5600, .hw_value = 120,}, > + {.center_freq = 5620, .hw_value = 124,}, > + {.center_freq = 5640, .hw_value = 128,}, > + {.center_freq = 5660, .hw_value = 132,}, > + {.center_freq = 5680, .hw_value = 136,}, > + {.center_freq = 5700, .hw_value = 140,}, > + {.center_freq = 5745, .hw_value = 149,}, > + {.center_freq = 5765, .hw_value = 153,}, > + {.center_freq = 5785, .hw_value = 157,}, > + {.center_freq = 5805, .hw_value = 161,}, > + {.center_freq = 5825, .hw_value = 165, > + .flags = IEEE80211_CHAN_NO_HT40MINUS}, > +}; > + > +static struct ieee80211_rate rtw_ratetable[] = { > + {.bitrate = 10, .hw_value = 0x00,}, > + {.bitrate = 20, .hw_value = 0x01,}, > + {.bitrate = 55, .hw_value = 0x02,}, > + {.bitrate = 110, .hw_value = 0x03,}, > + {.bitrate = 60, .hw_value = 0x04,}, > + {.bitrate = 90, .hw_value = 0x05,}, > + {.bitrate = 120, .hw_value = 0x06,}, > + {.bitrate = 180, .hw_value = 0x07,}, > + {.bitrate = 240, .hw_value = 0x08,}, > + {.bitrate = 360, .hw_value = 0x09,}, > + {.bitrate = 480, .hw_value = 0x0a,}, > + {.bitrate = 540, .hw_value = 0x0b,}, > +}; > + > +static struct ieee80211_supported_band rtw_band_2ghz = { > + .band = NL80211_BAND_2GHZ, > + > + .channels = rtw_channeltable_2g, > + .n_channels = ARRAY_SIZE(rtw_channeltable_2g), > + > + .bitrates = rtw_ratetable, > + .n_bitrates = ARRAY_SIZE(rtw_ratetable), > + > + .ht_cap = {0}, > + .vht_cap = {0}, > +}; > + > +static struct ieee80211_supported_band rtw_band_5ghz = { > + .band = NL80211_BAND_5GHZ, > + > + .channels = rtw_channeltable_5g, > + .n_channels = ARRAY_SIZE(rtw_channeltable_5g), > + > + /* 5G has no CCK rates */ > + .bitrates = rtw_ratetable + 4, > + .n_bitrates = ARRAY_SIZE(rtw_ratetable) - 4, > + > + .ht_cap = {0}, > + .vht_cap = {0}, > +}; > + > +struct rtw_watch_dog_iter_data { > + struct rtw_vif *rtwvif; > + bool active; > + u8 assoc_cnt; > +}; > + > +static void rtw_vif_watch_dog_iter(void *data, u8 *mac, > + struct ieee80211_vif *vif) > +{ > + struct rtw_watch_dog_iter_data *iter_data = data; > + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; > + > + if (vif->type == NL80211_IFTYPE_STATION) { > + if (vif->bss_conf.assoc) { > + iter_data->assoc_cnt++; > + iter_data->rtwvif = rtwvif; > + } > + if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD || > + rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD) > + iter_data->active = true; > + } else { > + /* only STATION mode can enter lps */ > + iter_data->active = true; > + } > + > + rtwvif->stats.tx_unicast = 0; > + rtwvif->stats.rx_unicast = 0; > + rtwvif->stats.tx_cnt = 0; > + rtwvif->stats.rx_cnt = 0; > +} > + > +/* process TX/RX statistics periodically for hardware, > + * the information helps hardware to enhance performance > + */ > +static void rtw_watch_dog_work(struct work_struct *work) > +{ > + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, > + watch_dog_work.work); > + struct rtw_watch_dog_iter_data data = {}; > + > + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) > + return; > + > + ieee80211_queue_delayed_work(rtwdev->hw, > &rtwdev->watch_dog_work, > + RTW_WATCH_DOG_DELAY_TIME); > + > + /* reset tx/rx statictics */ > + rtwdev->stats.tx_unicast = 0; > + rtwdev->stats.rx_unicast = 0; > + rtwdev->stats.tx_cnt = 0; > + rtwdev->stats.rx_cnt = 0; > + > + rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); > + > + /* fw supports only one station associated to enter lps, if there are > + * more than two stations associated to the AP, then we can not enter > + * lps, because fw does not handle the overlapped beacon interval > + */ > + if (data.rtwvif && !data.active && data.assoc_cnt == 1) > + rtw_enter_lps(rtwdev, data.rtwvif); > + > + if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING)) > + return; > + > + rtw_phy_dynamic_mechanism(rtwdev); > + > + rtwdev->watch_dog_cnt++; > +} > + > +static void rtw_c2h_work(struct work_struct *work) > +{ > + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, c2h_work); > + struct sk_buff *skb, *tmp; > + > + skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { > + skb_unlink(skb, &rtwdev->c2h_queue); > + rtw_fw_c2h_cmd_handle(rtwdev, skb); > + dev_kfree_skb_any(skb); > + } > +} > + > +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, > + struct rtw_channel_params *chan_params) > +{ > + struct ieee80211_channel *channel = chandef->chan; > + enum nl80211_chan_width width = chandef->width; > + u32 primary_freq, center_freq; > + u8 center_chan; > + u8 bandwidth = RTW_CHANNEL_WIDTH_20; > + u8 primary_chan_idx = 0; > + > + center_chan = channel->hw_value; > + primary_freq = channel->center_freq; > + center_freq = chandef->center_freq1; > + > + switch (width) { > + case NL80211_CHAN_WIDTH_20_NOHT: > + case NL80211_CHAN_WIDTH_20: > + bandwidth = RTW_CHANNEL_WIDTH_20; > + primary_chan_idx = 0; > + break; > + case NL80211_CHAN_WIDTH_40: > + bandwidth = RTW_CHANNEL_WIDTH_40; > + if (primary_freq > center_freq) { > + primary_chan_idx = 1; > + center_chan -= 2; > + } else { > + primary_chan_idx = 2; > + center_chan += 2; > + } > + break; > + case NL80211_CHAN_WIDTH_80: > + bandwidth = RTW_CHANNEL_WIDTH_80; > + if (primary_freq > center_freq) { > + if (primary_freq - center_freq == 10) { > + primary_chan_idx = 1; > + center_chan -= 2; > + } else { > + primary_chan_idx = 3; > + center_chan -= 6; > + } > + } else { > + if (center_freq - primary_freq == 10) { > + primary_chan_idx = 2; > + center_chan += 2; > + } else { > + primary_chan_idx = 4; > + center_chan += 6; > + } > + } > + break; > + default: > + center_chan = 0; > + break; > + } > + > + chan_params->center_chan = center_chan; > + chan_params->bandwidth = bandwidth; > + chan_params->primary_chan_idx = primary_chan_idx; > +} > + > +void rtw_set_channel(struct rtw_dev *rtwdev) > +{ > + struct ieee80211_hw *hw = rtwdev->hw; > + struct rtw_hal *hal = &rtwdev->hal; > + struct rtw_chip_info *chip = rtwdev->chip; > + struct rtw_channel_params ch_param; > + u8 center_chan, bandwidth, primary_chan_idx; > + > + rtw_get_channel_params(&hw->conf.chandef, &ch_param); > + if (WARN(ch_param.center_chan == 0, "Invalid channel\n")) > + return; > + > + center_chan = ch_param.center_chan; > + bandwidth = ch_param.bandwidth; > + primary_chan_idx = ch_param.primary_chan_idx; > + > + hal->current_band_width = bandwidth; > + hal->current_channel = center_chan; > + hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : > RTW_BAND_2G; > + chip->ops->set_channel(rtwdev, center_chan, bandwidth, > primary_chan_idx); > + > + rtw_phy_set_tx_power_level(rtwdev, center_chan); > +} > + > +static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr) > +{ > + int i; > + > + for (i = 0; i < ETH_ALEN; i++) > + rtw_write8(rtwdev, start + i, addr[i]); > +} > + > +void rtw_vif_port_config(struct rtw_dev *rtwdev, > + struct rtw_vif *rtwvif, > + u32 config) > +{ > + u32 addr, mask; > + > + if (config & PORT_SET_MAC_ADDR) { > + addr = rtwvif->conf->mac_addr.addr; > + rtw_vif_write_addr(rtwdev, addr, rtwvif->mac_addr); > + } > + if (config & PORT_SET_BSSID) { > + addr = rtwvif->conf->bssid.addr; > + rtw_vif_write_addr(rtwdev, addr, rtwvif->bssid); > + } > + if (config & PORT_SET_NET_TYPE) { > + addr = rtwvif->conf->net_type.addr; > + mask = rtwvif->conf->net_type.mask; > + rtw_write32_mask(rtwdev, addr, mask, rtwvif->net_type); > + } > + if (config & PORT_SET_AID) { > + addr = rtwvif->conf->aid.addr; > + mask = rtwvif->conf->aid.mask; > + rtw_write32_mask(rtwdev, addr, mask, rtwvif->aid); > + } > +} > + > +static u8 hw_bw_cap_to_bitamp(u8 bw_cap) > +{ > + u8 bw = 0; > + > + switch (bw_cap) { > + case EFUSE_HW_CAP_IGNORE: > + case EFUSE_HW_CAP_SUPP_BW80: > + bw |= BIT(RTW_CHANNEL_WIDTH_80); > + /* fall through */ > + case EFUSE_HW_CAP_SUPP_BW40: > + bw |= BIT(RTW_CHANNEL_WIDTH_40); > + /* fall through */ > + default: > + bw |= BIT(RTW_CHANNEL_WIDTH_20); > + break; > + } > + > + return bw; > +} > + > +static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 > hw_ant_num) > +{ > + struct rtw_hal *hal = &rtwdev->hal; > + > + if (hw_ant_num == EFUSE_HW_CAP_IGNORE || > + hw_ant_num >= hal->rf_path_num) > + return; > + > + switch (hw_ant_num) { > + case 1: > + hal->rf_type = RF_1T1R; > + hal->rf_path_num = 1; > + hal->antenna_tx = BB_PATH_A; > + hal->antenna_rx = BB_PATH_A; > + break; > + default: > + WARN(1, "invalid hw configuration from efuse\n"); > + break; > + } > +} > + > +static u64 get_vht_ra_mask(struct ieee80211_sta *sta) > +{ > + u64 ra_mask = 0; > + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); > + u8 vht_mcs_cap; > + int i, nss; > + > + /* 4SS, every two bits for MCS7/8/9 */ > + for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 10) { > + vht_mcs_cap = mcs_map & 0x3; > + switch (vht_mcs_cap) { > + case 2: /* MCS9 */ > + ra_mask |= 0x3ff << nss; > + break; > + case 1: /* MCS8 */ > + ra_mask |= 0x1ff << nss; > + break; > + case 0: /* MCS7 */ > + ra_mask |= 0x0ff << nss; > + break; > + default: > + break; > + } > + } > + > + return ra_mask; > +} > + > +static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 > tx_num) > +{ > + u8 rate_id = 0; > + > + switch (wireless_set) { > + case WIRELESS_CCK: > + rate_id = RTW_RATEID_B_20M; > + break; > + case WIRELESS_OFDM: > + rate_id = RTW_RATEID_G; > + break; > + case WIRELESS_CCK | WIRELESS_OFDM: > + rate_id = RTW_RATEID_BG; > + break; > + case WIRELESS_OFDM | WIRELESS_HT: > + if (tx_num == 1) > + rate_id = RTW_RATEID_GN_N1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_GN_N2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR5_N_3SS; > + break; > + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_HT: > + if (bw_mode == RTW_CHANNEL_WIDTH_40) { > + if (tx_num == 1) > + rate_id = RTW_RATEID_BGN_40M_1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_BGN_40M_2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR5_N_3SS; > + else if (tx_num == 4) > + rate_id = RTW_RATEID_ARFR7_N_4SS; > + } else { > + if (tx_num == 1) > + rate_id = RTW_RATEID_BGN_20M_1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_BGN_20M_2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR5_N_3SS; > + else if (tx_num == 4) > + rate_id = RTW_RATEID_ARFR7_N_4SS; > + } > + break; > + case WIRELESS_OFDM | WIRELESS_VHT: > + if (tx_num == 1) > + rate_id = RTW_RATEID_ARFR1_AC_1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_ARFR0_AC_2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR4_AC_3SS; > + else if (tx_num == 4) > + rate_id = RTW_RATEID_ARFR6_AC_4SS; > + break; > + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_VHT: > + if (bw_mode >= RTW_CHANNEL_WIDTH_80) { > + if (tx_num == 1) > + rate_id = RTW_RATEID_ARFR1_AC_1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_ARFR0_AC_2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR4_AC_3SS; > + else if (tx_num == 4) > + rate_id = RTW_RATEID_ARFR6_AC_4SS; > + } else { > + if (tx_num == 1) > + rate_id = RTW_RATEID_ARFR2_AC_2G_1SS; > + else if (tx_num == 2) > + rate_id = RTW_RATEID_ARFR3_AC_2G_2SS; > + else if (tx_num == 3) > + rate_id = RTW_RATEID_ARFR4_AC_3SS; > + else if (tx_num == 4) > + rate_id = RTW_RATEID_ARFR6_AC_4SS; > + } > + break; > + default: > + break; > + } > + > + return rate_id; > +} > + > +#define RA_MASK_CCK_RATES 0x0000f > +#define RA_MASK_OFDM_RATES 0x00ff0 > +#define RA_MASK_HT_RATES_1SS (0xff000 << 0) > +#define RA_MASK_HT_RATES_2SS (0xff000 << 8) > +#define RA_MASK_HT_RATES_3SS (0xff000 << 16) > +#define RA_MASK_HT_RATES (RA_MASK_HT_RATES_1SS | \ > + RA_MASK_HT_RATES_2SS | \ > + RA_MASK_HT_RATES_3SS) > +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0) > +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10) > +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20) > +#define RA_MASK_VHT_RATES (RA_MASK_VHT_RATES_1SS | \ > + RA_MASK_VHT_RATES_2SS | \ > + RA_MASK_VHT_RATES_3SS) > +#define RA_MASK_CCK_IN_HT 0x00005 > +#define RA_MASK_CCK_IN_VHT 0x00005 > +#define RA_MASK_OFDM_IN_VHT 0x00010 > +#define RA_MASK_OFDM_IN_HT_2G 0x00010 > +#define RA_MASK_OFDM_IN_HT_5G 0x00030 > + > +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) > +{ > + struct ieee80211_sta *sta = si->sta; > + struct rtw_efuse *efuse = &rtwdev->efuse; > + struct rtw_hal *hal = &rtwdev->hal; > + u8 rssi_level; > + u8 wireless_set; > + u8 bw_mode; > + u8 rate_id; > + u8 rf_type = RF_1T1R; > + u8 stbc_en = 0; > + u8 ldpc_en = 0; > + u8 tx_num = 1; > + u64 ra_mask = 0; > + bool is_vht_enable = false; > + bool is_support_sgi = false; > + > + if (sta->vht_cap.vht_supported) { > + is_vht_enable = true; > + ra_mask |= get_vht_ra_mask(sta); > + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) > + stbc_en = VHT_STBC_EN; > + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) > + ldpc_en = VHT_LDPC_EN; > + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) > + is_support_sgi = true; > + } else if (sta->ht_cap.ht_supported) { > + ra_mask |= (sta->ht_cap.mcs.rx_mask[NL80211_BAND_5GHZ] << 20) > | > + (sta->ht_cap.mcs.rx_mask[NL80211_BAND_2GHZ] << 12); > + if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) > + stbc_en = HT_STBC_EN; > + if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) > + ldpc_en = HT_LDPC_EN; > + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20 || > + sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) > + is_support_sgi = true; > + } > + > + if (hal->current_band_type == RTW_BAND_5G) { > + ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; > + if (sta->vht_cap.vht_supported) { > + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; > + wireless_set = WIRELESS_OFDM | WIRELESS_VHT; > + } else if (sta->ht_cap.ht_supported) { > + ra_mask &= RA_MASK_HT_RATES | > RA_MASK_OFDM_IN_HT_5G; > + wireless_set = WIRELESS_OFDM | WIRELESS_HT; > + } else { > + wireless_set = WIRELESS_OFDM; > + } > + } else if (hal->current_band_type == RTW_BAND_2G) { > + ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; > + if (sta->vht_cap.vht_supported) { > + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT | > + RA_MASK_OFDM_IN_VHT; > + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | > + WIRELESS_HT | WIRELESS_VHT; > + } else if (sta->ht_cap.ht_supported) { > + ra_mask &= RA_MASK_HT_RATES | RA_MASK_CCK_IN_HT | > + RA_MASK_OFDM_IN_HT_2G; > + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | > + WIRELESS_HT; > + } else if (sta->supp_rates[0] <= 0xf) { > + wireless_set = WIRELESS_CCK; > + } else { > + wireless_set = WIRELESS_CCK | WIRELESS_OFDM; > + } > + } else { > + rtw_err(rtwdev, "Unknown band type\n"); > + wireless_set = 0; > + } > + > + if (efuse->hw_cap.nss == 1) { > + ra_mask &= RA_MASK_VHT_RATES_1SS; > + ra_mask &= RA_MASK_HT_RATES_1SS; > + } > + > + switch (sta->bandwidth) { > + case IEEE80211_STA_RX_BW_80: > + bw_mode = RTW_CHANNEL_WIDTH_80; > + break; > + case IEEE80211_STA_RX_BW_40: > + bw_mode = RTW_CHANNEL_WIDTH_40; > + break; > + default: > + bw_mode = RTW_CHANNEL_WIDTH_20; > + break; > + } > + > + if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { > + tx_num = 2; > + rf_type = RF_2T2R; > + } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { > + tx_num = 2; > + rf_type = RF_2T2R; > + } > + > + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); > + > + if (wireless_set != WIRELESS_CCK) { > + rssi_level = si->rssi_level; > + if (rssi_level == 0) > + ra_mask &= 0xffffffffffffffffULL; > + else if (rssi_level == 1) > + ra_mask &= 0xfffffffffffffff0ULL; > + else if (rssi_level == 2) > + ra_mask &= 0xffffffffffffefe0ULL; > + else if (rssi_level == 3) > + ra_mask &= 0xffffffffffffcfc0ULL; > + else if (rssi_level == 4) > + ra_mask &= 0xffffffffffff8f80ULL; > + else if (rssi_level >= 5) > + ra_mask &= 0xffffffffffff0f00ULL; > + } > + > + si->bw_mode = bw_mode; > + si->stbc_en = stbc_en; > + si->ldpc_en = ldpc_en; > + si->rf_type = rf_type; > + si->wireless_set = wireless_set; > + si->sgi_enable = is_support_sgi; > + si->vht_enable = is_vht_enable; > + si->ra_mask = ra_mask; > + si->rate_id = rate_id; > + > + rtw_fw_send_ra_info(rtwdev, si); > +} > + > +static int rtw_power_on(struct rtw_dev *rtwdev) > +{ > + struct rtw_chip_info *chip = rtwdev->chip; > + struct rtw_fw_state *fw = &rtwdev->fw; > + int ret; > + > + ret = rtw_hci_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup hci\n"); > + goto err; > + } > + > + /* power on MAC before firmware downloaded */ > + ret = rtw_mac_power_on(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to power on mac\n"); > + goto err; > + } > + > + wait_for_completion(&fw->completion); > + if (!fw->firmware) { > + ret = -EINVAL; > + rtw_err(rtwdev, "failed to load firmware\n"); > + goto err; > + } > + > + ret = rtw_download_firmware(rtwdev, fw->firmware->data, > + fw->firmware->size); > + if (ret) { > + rtw_err(rtwdev, "failed to download firmware\n"); > + goto err_off; > + } > + > + /* config mac after firmware downloaded */ > + ret = rtw_mac_init(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to configure mac\n"); > + goto err_off; > + } > + > + chip->ops->phy_set_param(rtwdev); > + > + ret = rtw_hci_start(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to start hci\n"); > + goto err_off; > + } > + > + return 0; > + > +err_off: > + rtw_mac_power_off(rtwdev); > + > +err: > + return ret; > +} > + > +int rtw_core_start(struct rtw_dev *rtwdev) > +{ > + int ret; > + > + ret = rtw_power_on(rtwdev); > + if (ret) > + return ret; > + > + rtwdev->h2c.last_box_num = 0; > + > + rtw_sec_enable_sec_engine(rtwdev); > + > + /* rcr reset after powered on */ > + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); > + > + ieee80211_queue_delayed_work(rtwdev->hw, > &rtwdev->watch_dog_work, > + RTW_WATCH_DOG_DELAY_TIME); > + > + rtw_flag_set(rtwdev, RTW_FLAG_RUNNING); > + > + return 0; > +} > + > +static void rtw_power_off(struct rtw_dev *rtwdev) > +{ > + rtwdev->hci.ops->stop(rtwdev); > + rtw_mac_power_off(rtwdev); > +} > + > +void rtw_core_stop(struct rtw_dev *rtwdev) > +{ > + rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING); > + rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING); > + > + cancel_delayed_work_sync(&rtwdev->watch_dog_work); > + > + rtw_power_off(rtwdev); > +} > + > +static void rtw_init_ht_cap(struct rtw_dev *rtwdev, > + struct ieee80211_sta_ht_cap *ht_cap) > +{ > + struct rtw_efuse *efuse = &rtwdev->efuse; > + > + ht_cap->ht_supported = true; > + ht_cap->cap = 0; > + ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | > + IEEE80211_HT_CAP_MAX_AMSDU | > + IEEE80211_HT_CAP_LDPC_CODING | > + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); > + if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40)) > + ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | > + IEEE80211_HT_CAP_DSSSCCK40 | > + IEEE80211_HT_CAP_SGI_40; > + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; > + ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; > + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; > + if (efuse->hw_cap.nss > 1) { > + ht_cap->mcs.rx_mask[0] = 0xFF; > + ht_cap->mcs.rx_mask[1] = 0xFF; > + ht_cap->mcs.rx_mask[4] = 0x01; > + ht_cap->mcs.rx_highest = cpu_to_le16(300); > + } else { > + ht_cap->mcs.rx_mask[0] = 0xFF; > + ht_cap->mcs.rx_mask[1] = 0x00; > + ht_cap->mcs.rx_mask[4] = 0x01; > + ht_cap->mcs.rx_highest = cpu_to_le16(150); > + } > +} > + > +static void rtw_init_vht_cap(struct rtw_dev *rtwdev, > + struct ieee80211_sta_vht_cap *vht_cap) > +{ > + struct rtw_efuse *efuse = &rtwdev->efuse; > + u16 mcs_map; > + __le16 highest; > + > + if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && > + efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) > + return; > + > + vht_cap->vht_supported = true; > + vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | > + IEEE80211_VHT_CAP_RXLDPC | > + IEEE80211_VHT_CAP_SHORT_GI_80 | > + IEEE80211_VHT_CAP_TXSTBC | > + IEEE80211_VHT_CAP_RXSTBC_1 | > + IEEE80211_VHT_CAP_HTC_VHT | > + > IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | > + 0; > + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | > + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; > + if (efuse->hw_cap.nss > 1) { > + highest = cpu_to_le16(780); > + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; > + } else { > + highest = cpu_to_le16(390); > + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; > + } > + > + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); > + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); > + vht_cap->vht_mcs.rx_highest = highest; > + vht_cap->vht_mcs.tx_highest = highest; > +} > + > +static void rtw_set_supported_band(struct ieee80211_hw *hw, > + struct rtw_chip_info *chip) > +{ > + struct rtw_dev *rtwdev = hw->priv; > + struct ieee80211_supported_band *sband; > + > + if (chip->band & RTW_BAND_2G) { > + sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL); > + if (!sband) > + goto err_out; > + if (chip->ht_supported) > + rtw_init_ht_cap(rtwdev, &sband->ht_cap); > + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; > + } > + > + if (chip->band & RTW_BAND_5G) { > + sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL); > + if (!sband) > + goto err_out; > + if (chip->ht_supported) > + rtw_init_ht_cap(rtwdev, &sband->ht_cap); > + if (chip->vht_supported) > + rtw_init_vht_cap(rtwdev, &sband->vht_cap); > + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; > + } > + > + return; > + > +err_out: > + rtw_err(rtwdev, "failed to set supported band\n"); > + kfree(sband); > + return; > +} > + > +static void rtw_unset_supported_band(struct ieee80211_hw *hw, > + struct rtw_chip_info *chip) > +{ > + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); > + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); > +} > + > +static void rtw_load_firmware_cb(const struct firmware *firmware, void > *context) > +{ > + struct rtw_dev *rtwdev = context; > + struct rtw_fw_state *fw = &rtwdev->fw; > + > + if (!firmware) > + rtw_err(rtwdev, "failed to request firmware\n"); > + > + fw->firmware = firmware; > + complete_all(&fw->completion); > +} > + > +static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name) > +{ > + struct rtw_fw_state *fw = &rtwdev->fw; > + int ret; > + > + init_completion(&fw->completion); > + > + ret = request_firmware_nowait(THIS_MODULE, true, fw_name, > rtwdev->dev, > + GFP_KERNEL, rtwdev, rtw_load_firmware_cb); > + if (ret) { > + rtw_err(rtwdev, "async firmware request failed\n"); > + return ret; > + } > + > + return 0; > +} > + > +static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) > +{ > + struct rtw_chip_info *chip = rtwdev->chip; > + struct rtw_hal *hal = &rtwdev->hal; > + struct rtw_efuse *efuse = &rtwdev->efuse; > + u32 wl_bt_pwr_ctrl; > + int ret = 0; > + > + switch (rtw_hci_type(rtwdev)) { > + case RTW_HCI_TYPE_PCIE: > + rtwdev->hci.rpwm_addr = 0x03d9; > + break; > + default: > + rtw_err(rtwdev, "unsupported hci type\n"); > + return -EINVAL; > + } > + > + wl_bt_pwr_ctrl = rtw_read32(rtwdev, REG_WL_BT_PWR_CTRL); > + if (wl_bt_pwr_ctrl & BIT_BT_FUNC_EN) > + rtwdev->efuse.btcoex = true; > + hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1); > + hal->fab_version = BIT_GET_VENDOR_ID(hal->chip_version) >> 2; > + hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version); > + hal->mp_chip = (hal->chip_version & BIT_RTL_ID) ? 0 : 1; > + if (hal->chip_version & BIT_RF_TYPE_ID) { > + hal->rf_type = RF_2T2R; > + hal->rf_path_num = 2; > + hal->antenna_tx = BB_PATH_AB; > + hal->antenna_rx = BB_PATH_AB; > + } else { > + hal->rf_type = RF_1T1R; > + hal->rf_path_num = 1; > + hal->antenna_tx = BB_PATH_A; > + hal->antenna_rx = BB_PATH_A; > + } > + > + if (hal->fab_version == 2) > + hal->fab_version = 1; > + else if (hal->fab_version == 1) > + hal->fab_version = 2; > + > + efuse->physical_size = chip->phy_efuse_size; > + efuse->logical_size = chip->log_efuse_size; > + efuse->protect_size = chip->ptct_efuse_size; > + > + /* default use ack */ > + rtwdev->hal.rcr |= BIT_VHT_DACK; > + > + return ret; > +} > + > +static int rtw_chip_efuse_enable(struct rtw_dev *rtwdev) > +{ > + struct rtw_fw_state *fw = &rtwdev->fw; > + int ret; > + > + ret = rtw_hci_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup hci\n"); > + goto err; > + } > + > + ret = rtw_mac_power_on(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to power on mac\n"); > + goto err; > + } > + > + rtw_write8(rtwdev, REG_C2HEVT, C2H_HW_FEATURE_DUMP); > + ret = rtw_download_firmware(rtwdev, fw->firmware->data, > + fw->firmware->size); > + if (ret) { > + rtw_err(rtwdev, "failed to download firmware\n"); > + goto err_off; > + } > + > + return 0; > + > +err_off: > + rtw_mac_power_off(rtwdev); > + > +err: > + return ret; > +} > + > +static int rtw_dump_hw_feature(struct rtw_dev *rtwdev) > +{ > + struct rtw_efuse *efuse = &rtwdev->efuse; > + struct efuse_hw_cap *hw_cap; > + u8 hw_feature[HW_FEATURE_LEN]; > + u8 id; > + int i; > + > + BUILD_BUG_ON(sizeof(*hw_cap) != HW_FEATURE_LEN); > + > + id = rtw_read8(rtwdev, REG_C2HEVT); > + if (id != C2H_HW_FEATURE_REPORT) { > + rtw_err(rtwdev, "failed to read hw feature report\n"); > + return -EBUSY; > + } > + > + for (i = 0; i < HW_FEATURE_LEN; i++) > + hw_feature[i] = rtw_read8(rtwdev, REG_C2HEVT + 2 + i); > + > + rtw_write8(rtwdev, REG_C2HEVT, 0); > + > + hw_cap = (struct efuse_hw_cap *)hw_feature; > + > + efuse->hw_cap.bw = hw_bw_cap_to_bitamp(hw_cap->bw); > + efuse->hw_cap.hci = hw_cap->hci; > + efuse->hw_cap.nss = hw_cap->nss; > + efuse->hw_cap.ptcl = hw_cap->ptcl; > + efuse->hw_cap.ant_num = hw_cap->ant_num; > + > + rtw_hw_config_rf_ant_num(rtwdev, efuse->hw_cap.ant_num); > + > + if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE) > + efuse->hw_cap.nss = rtwdev->hal.rf_path_num; > + > + rtw_dbg(rtwdev, "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, > ant_num=%d, nss=%d\n", > + efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl, > + efuse->hw_cap.ant_num, efuse->hw_cap.nss); > + > + return 0; > +} > + > +static void rtw_chip_efuse_disable(struct rtw_dev *rtwdev) > +{ > + rtw_hci_stop(rtwdev); > + rtw_mac_power_off(rtwdev); > +} > + > +static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) > +{ > + struct rtw_efuse *efuse = &rtwdev->efuse; > + int ret; > + > + mutex_lock(&rtwdev->mutex); > + > + /* power on mac to read efuse */ > + ret = rtw_chip_efuse_enable(rtwdev); > + if (ret) > + goto out; > + > + ret = rtw_parse_efuse_map(rtwdev); > + if (ret) > + goto out; > + > + ret = rtw_dump_hw_feature(rtwdev); > + if (ret) > + goto out; > + > + ret = rtw_check_supported_rfe(rtwdev); > + if (ret) > + goto out; > + > + if (efuse->crystal_cap == 0xff) > + efuse->crystal_cap = 0; > + if (efuse->pa_type_2g == 0xff) > + efuse->pa_type_2g = 0; > + if (efuse->pa_type_5g == 0xff) > + efuse->pa_type_5g = 0; > + if (efuse->lna_type_2g == 0xff) > + efuse->lna_type_2g = 0; > + if (efuse->lna_type_5g == 0xff) > + efuse->lna_type_5g = 0; > + if (efuse->channel_plan == 0xff) > + efuse->channel_plan = 0x7f; > + if (efuse->bt_setting & BIT(0)) > + efuse->share_ant = true; > + if (efuse->regd == 0xff) > + efuse->regd = 0; > + > + efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; > + efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; > + efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; > + efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0; > + > + rtw_chip_efuse_disable(rtwdev); > + > +out: > + mutex_unlock(&rtwdev->mutex); > + return ret; > +} > + > +static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) > +{ > + struct rtw_hal *hal = &rtwdev->hal; > + const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); > + > + if (!rfe_def) > + return -ENODEV; > + > + rtw_phy_setup_phy_cond(rtwdev, 0); > + > + rtw_hw_init_tx_power(hal); > + if (rtwdev->chip->id != RTW_CHIP_TYPE_8822C) > + rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); > + rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); > + rtw_phy_tx_power_by_rate_config(hal); > + rtw_phy_tx_power_limit_config(hal); > + > + return 0; > +} > + > +int rtw_chip_info_setup(struct rtw_dev *rtwdev) > +{ > + int ret; > + > + ret = rtw_chip_parameter_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup chip parameters\n"); > + goto err_out; > + } > + > + ret = rtw_chip_efuse_info_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup chip efuse info\n"); > + goto err_out; > + } > + > + ret = rtw_chip_board_info_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup chip board info\n"); > + goto err_out; > + } > + > + return 0; > + > +err_out: > + return ret; > +} > +EXPORT_SYMBOL(rtw_chip_info_setup); > + > +int rtw_core_init(struct rtw_dev *rtwdev) > +{ > + int ret; > + > + INIT_LIST_HEAD(&rtwdev->rsvd_page_list); > + > + INIT_DELAYED_WORK(&rtwdev->watch_dog_work, > rtw_watch_dog_work); > + INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work); > + INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); > + skb_queue_head_init(&rtwdev->c2h_queue); > + > + spin_lock_init(&rtwdev->dm_lock); > + spin_lock_init(&rtwdev->rf_lock); > + spin_lock_init(&rtwdev->h2c.lock); > + > + mutex_init(&rtwdev->mutex); > + mutex_init(&rtwdev->hal.tx_power_mutex); > + > + rtwdev->sec.total_cam_num = 32; > + rtwdev->hal.current_channel = 1; > + set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); > + > + mutex_lock(&rtwdev->mutex); > + rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false); > + mutex_unlock(&rtwdev->mutex); > + > + /* default rx filter setting */ > + rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV | > + BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | > + BIT_AB | BIT_AM | BIT_APM; > + > + ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name); > + if (ret) { > + rtw_warn(rtwdev, "no firmware loaded\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(rtw_core_init); > + > +void rtw_core_deinit(struct rtw_dev *rtwdev) > +{ > + struct rtw_fw_state *fw = &rtwdev->fw; > + struct rtw_rsvd_page *rsvd_pkt, *tmp; > + > + if (fw->firmware) > + release_firmware(fw->firmware); > + > + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { > + list_del(&rsvd_pkt->list); > + kfree(rsvd_pkt); > + } > + > + mutex_destroy(&rtwdev->mutex); > + mutex_destroy(&rtwdev->hal.tx_power_mutex); > +} > +EXPORT_SYMBOL(rtw_core_deinit); > + > +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) > +{ > + int max_tx_headroom = 0; > + int ret; > + > + /* TODO: USB & SDIO may need extra room? */ > + max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz; > + > + hw->extra_tx_headroom = max_tx_headroom; > + hw->queues = IEEE80211_NUM_ACS; > + hw->sta_data_size = sizeof(struct rtw_sta_info); > + hw->vif_data_size = sizeof(struct rtw_vif); > + > + ieee80211_hw_set(hw, SIGNAL_DBM); > + ieee80211_hw_set(hw, RX_INCLUDES_FCS); > + ieee80211_hw_set(hw, AMPDU_AGGREGATION); > + ieee80211_hw_set(hw, MFP_CAPABLE); > + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); > + ieee80211_hw_set(hw, SUPPORTS_PS); > + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); > + > + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_ADHOC) | > + BIT(NL80211_IFTYPE_MESH_POINT); > + > + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | > + WIPHY_FLAG_TDLS_EXTERNAL_SETUP; > + > + rtw_set_supported_band(hw, rtwdev->chip); > + SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); > + > + rtw_regd_init(rtwdev, rtw_regd_notifier); > + > + ret = ieee80211_register_hw(hw); > + if (ret) { > + rtw_err(rtwdev, "failed to register hw\n"); > + return ret; > + } > + > + if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2)) > + rtw_err(rtwdev, "regulatory_hint fail\n"); > + > + rtw_debugfs_init(rtwdev); > + > + return 0; > +} > +EXPORT_SYMBOL(rtw_register_hw); > + > +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) > +{ > + struct rtw_chip_info *chip = rtwdev->chip; > + > + ieee80211_unregister_hw(hw); > + rtw_unset_supported_band(hw, chip); > +} > +EXPORT_SYMBOL(rtw_unregister_hw); > + > +MODULE_AUTHOR("Realtek Corporation"); > +MODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/net/wireless/realtek/rtw88/main.h > b/drivers/net/wireless/realtek/rtw88/main.h > new file mode 100644 > index 0000000..b345fe0 > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/main.h > @@ -0,0 +1,1119 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* Copyright(c) 2018 Realtek Corporation. > + */ > + > +#ifndef __RTK_MAIN_H_ > +#define __RTK_MAIN_H_ > + > +#include <net/mac80211.h> > +#include <linux/vmalloc.h> > +#include <linux/firmware.h> > +#include <linux/average.h> > +#include <linux/bitops.h> > +#include <linux/bitfield.h> > + > +#define RTW_MAX_MAC_ID_NUM 32 > +#define RTW_MAX_SEC_CAM_NUM 32 > + > +#define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2) > + > +#define RFREG_MASK 0xfffff > +#define INV_RF_DATA 0xffffffff > +#define TX_PAGE_SIZE_SHIFT 7 > + > +#define RTW_CHANNEL_WIDTH_MAX 3 > +#define RTW_RF_PATH_MAX 4 > +#define HW_FEATURE_LEN 13 > + > +extern const struct ieee80211_ops rtw_ops; > +extern struct rtw_chip_info rtw8822b_hw_spec; > +extern struct rtw_chip_info rtw8822c_hw_spec; > + > +#define RTW_MAX_CHANNEL_NUM_2G 14 > +#define RTW_MAX_CHANNEL_NUM_5G 49 > + > +struct rtw_dev; > + > +enum rtw_hci_type { > + RTW_HCI_TYPE_PCIE, > + RTW_HCI_TYPE_USB, > + RTW_HCI_TYPE_SDIO, > + > + RTW_HCI_TYPE_UNDEFINE, > +}; > + > +struct rtw_hci { > + struct rtw_hci_ops *ops; > + enum rtw_hci_type type; > + > + u32 rpwm_addr; > + > + u8 bulkout_num; > +}; > + > +enum rtw_supported_band { > + RTW_BAND_2G = 1 << 0, > + RTW_BAND_5G = 1 << 1, > + RTW_BAND_60G = 1 << 2, > + > + RTW_BAND_MAX, > +}; > + > +enum rtw_bandwidth { > + RTW_CHANNEL_WIDTH_20 = 0, > + RTW_CHANNEL_WIDTH_40 = 1, > + RTW_CHANNEL_WIDTH_80 = 2, > + RTW_CHANNEL_WIDTH_160 = 3, > + RTW_CHANNEL_WIDTH_80_80 = 4, > + RTW_CHANNEL_WIDTH_5 = 5, > + RTW_CHANNEL_WIDTH_10 = 6, > +}; > + > +enum rtw_net_type { > + RTW_NET_NO_LINK = 0, > + RTW_NET_AD_HOC = 1, > + RTW_NET_MGD_LINKED = 2, > + RTW_NET_AP_MODE = 3, > +}; > + > +enum rtw_rf_type { > + RF_1T1R = 0, > + RF_1T2R = 1, > + RF_2T2R = 2, > + RF_2T3R = 3, > + RF_2T4R = 4, > + RF_3T3R = 5, > + RF_3T4R = 6, > + RF_4T4R = 7, > + RF_TYPE_MAX, > +}; > + > +enum rtw_rf_path { > + RF_PATH_A = 0, > + RF_PATH_B = 1, > + RF_PATH_C = 2, > + RF_PATH_D = 3, > +}; > + > +enum rtw_bb_path { > + BB_PATH_A = BIT(0), > + BB_PATH_B = BIT(1), > + BB_PATH_C = BIT(2), > + BB_PATH_D = BIT(3), > + > + BB_PATH_AB = (BB_PATH_A | BB_PATH_B), > + BB_PATH_AC = (BB_PATH_A | BB_PATH_C), > + BB_PATH_AD = (BB_PATH_A | BB_PATH_D), > + BB_PATH_BC = (BB_PATH_B | BB_PATH_C), > + BB_PATH_BD = (BB_PATH_B | BB_PATH_D), > + BB_PATH_CD = (BB_PATH_C | BB_PATH_D), > + > + BB_PATH_ABC = (BB_PATH_A | BB_PATH_B | BB_PATH_C), > + BB_PATH_ABD = (BB_PATH_A | BB_PATH_B | BB_PATH_D), > + BB_PATH_ACD = (BB_PATH_A | BB_PATH_C | BB_PATH_D), > + BB_PATH_BCD = (BB_PATH_B | BB_PATH_C | BB_PATH_D), > + > + BB_PATH_ABCD = (BB_PATH_A | BB_PATH_B | BB_PATH_C | BB_PATH_D), > +}; > + > +enum rtw_rate_section { > + RTW_RATE_SECTION_CCK = 0, > + RTW_RATE_SECTION_OFDM, > + RTW_RATE_SECTION_HT_1S, > + RTW_RATE_SECTION_HT_2S, > + RTW_RATE_SECTION_VHT_1S, > + RTW_RATE_SECTION_VHT_2S, > + > + /* keep last */ > + RTW_RATE_SECTION_MAX, > +}; > + > +enum rtw_wireless_set { > + WIRELESS_CCK = 0x00000001, > + WIRELESS_OFDM = 0x00000002, > + WIRELESS_HT = 0x00000004, > + WIRELESS_VHT = 0x00000008, > +}; > + > +#define HT_STBC_EN BIT(0) > +#define VHT_STBC_EN BIT(1) > +#define HT_LDPC_EN BIT(0) > +#define VHT_LDPC_EN BIT(1) > + > +enum rtw_chip_type { > + RTW_CHIP_TYPE_8822B, > + RTW_CHIP_TYPE_8822C, > +}; > + > +enum rtw_tx_queue_type { > + /* the order of AC queues matters */ > + RTW_TX_QUEUE_BK = 0x0, > + RTW_TX_QUEUE_BE = 0x1, > + RTW_TX_QUEUE_VI = 0x2, > + RTW_TX_QUEUE_VO = 0x3, > + > + RTW_TX_QUEUE_BCN = 0x4, > + RTW_TX_QUEUE_MGMT = 0x5, > + RTW_TX_QUEUE_HI0 = 0x6, > + RTW_TX_QUEUE_H2C = 0x7, > + /* keep it last */ > + RTK_MAX_TX_QUEUE_NUM > +}; > + > +enum rtw_rx_queue_type { > + RTW_RX_QUEUE_MPDU = 0x0, > + RTW_RX_QUEUE_C2H = 0x1, > + /* keep it last */ > + RTK_MAX_RX_QUEUE_NUM > +}; > + > +enum rtw_rate_index { > + RTW_RATEID_BGN_40M_2SS = 0, > + RTW_RATEID_BGN_40M_1SS = 1, > + RTW_RATEID_BGN_20M_2SS = 2, > + RTW_RATEID_BGN_20M_1SS = 3, > + RTW_RATEID_GN_N2SS = 4, > + RTW_RATEID_GN_N1SS = 5, > + RTW_RATEID_BG = 6, > + RTW_RATEID_G = 7, > + RTW_RATEID_B_20M = 8, > + RTW_RATEID_ARFR0_AC_2SS = 9, > + RTW_RATEID_ARFR1_AC_1SS = 10, > + RTW_RATEID_ARFR2_AC_2G_1SS = 11, > + RTW_RATEID_ARFR3_AC_2G_2SS = 12, > + RTW_RATEID_ARFR4_AC_3SS = 13, > + RTW_RATEID_ARFR5_N_3SS = 14, > + RTW_RATEID_ARFR7_N_4SS = 15, > + RTW_RATEID_ARFR6_AC_4SS = 16 > +}; > + > +enum rtw_trx_desc_rate { > + DESC_RATE1M = 0x00, > + DESC_RATE2M = 0x01, > + DESC_RATE5_5M = 0x02, > + DESC_RATE11M = 0x03, > + > + DESC_RATE6M = 0x04, > + DESC_RATE9M = 0x05, > + DESC_RATE12M = 0x06, > + DESC_RATE18M = 0x07, > + DESC_RATE24M = 0x08, > + DESC_RATE36M = 0x09, > + DESC_RATE48M = 0x0a, > + DESC_RATE54M = 0x0b, > + > + DESC_RATEMCS0 = 0x0c, > + DESC_RATEMCS1 = 0x0d, > + DESC_RATEMCS2 = 0x0e, > + DESC_RATEMCS3 = 0x0f, > + DESC_RATEMCS4 = 0x10, > + DESC_RATEMCS5 = 0x11, > + DESC_RATEMCS6 = 0x12, > + DESC_RATEMCS7 = 0x13, > + DESC_RATEMCS8 = 0x14, > + DESC_RATEMCS9 = 0x15, > + DESC_RATEMCS10 = 0x16, > + DESC_RATEMCS11 = 0x17, > + DESC_RATEMCS12 = 0x18, > + DESC_RATEMCS13 = 0x19, > + DESC_RATEMCS14 = 0x1a, > + DESC_RATEMCS15 = 0x1b, > + DESC_RATEMCS16 = 0x1c, > + DESC_RATEMCS17 = 0x1d, > + DESC_RATEMCS18 = 0x1e, > + DESC_RATEMCS19 = 0x1f, > + DESC_RATEMCS20 = 0x20, > + DESC_RATEMCS21 = 0x21, > + DESC_RATEMCS22 = 0x22, > + DESC_RATEMCS23 = 0x23, > + DESC_RATEMCS24 = 0x24, > + DESC_RATEMCS25 = 0x25, > + DESC_RATEMCS26 = 0x26, > + DESC_RATEMCS27 = 0x27, > + DESC_RATEMCS28 = 0x28, > + DESC_RATEMCS29 = 0x29, > + DESC_RATEMCS30 = 0x2a, > + DESC_RATEMCS31 = 0x2b, > + > + DESC_RATEVHT1SS_MCS0 = 0x2c, > + DESC_RATEVHT1SS_MCS1 = 0x2d, > + DESC_RATEVHT1SS_MCS2 = 0x2e, > + DESC_RATEVHT1SS_MCS3 = 0x2f, > + DESC_RATEVHT1SS_MCS4 = 0x30, > + DESC_RATEVHT1SS_MCS5 = 0x31, > + DESC_RATEVHT1SS_MCS6 = 0x32, > + DESC_RATEVHT1SS_MCS7 = 0x33, > + DESC_RATEVHT1SS_MCS8 = 0x34, > + DESC_RATEVHT1SS_MCS9 = 0x35, > + > + DESC_RATEVHT2SS_MCS0 = 0x36, > + DESC_RATEVHT2SS_MCS1 = 0x37, > + DESC_RATEVHT2SS_MCS2 = 0x38, > + DESC_RATEVHT2SS_MCS3 = 0x39, > + DESC_RATEVHT2SS_MCS4 = 0x3a, > + DESC_RATEVHT2SS_MCS5 = 0x3b, > + DESC_RATEVHT2SS_MCS6 = 0x3c, > + DESC_RATEVHT2SS_MCS7 = 0x3d, > + DESC_RATEVHT2SS_MCS8 = 0x3e, > + DESC_RATEVHT2SS_MCS9 = 0x3f, > + > + DESC_RATEVHT3SS_MCS0 = 0x40, > + DESC_RATEVHT3SS_MCS1 = 0x41, > + DESC_RATEVHT3SS_MCS2 = 0x42, > + DESC_RATEVHT3SS_MCS3 = 0x43, > + DESC_RATEVHT3SS_MCS4 = 0x44, > + DESC_RATEVHT3SS_MCS5 = 0x45, > + DESC_RATEVHT3SS_MCS6 = 0x46, > + DESC_RATEVHT3SS_MCS7 = 0x47, > + DESC_RATEVHT3SS_MCS8 = 0x48, > + DESC_RATEVHT3SS_MCS9 = 0x49, > + > + DESC_RATEVHT4SS_MCS0 = 0x4a, > + DESC_RATEVHT4SS_MCS1 = 0x4b, > + DESC_RATEVHT4SS_MCS2 = 0x4c, > + DESC_RATEVHT4SS_MCS3 = 0x4d, > + DESC_RATEVHT4SS_MCS4 = 0x4e, > + DESC_RATEVHT4SS_MCS5 = 0x4f, > + DESC_RATEVHT4SS_MCS6 = 0x50, > + DESC_RATEVHT4SS_MCS7 = 0x51, > + DESC_RATEVHT4SS_MCS8 = 0x52, > + DESC_RATEVHT4SS_MCS9 = 0x53, > + > + DESC_RATE_MAX, > +}; > + > +enum rtw_regulatory_domains { > + RTW_REGD_FCC = 0, > + RTW_REGD_MKK = 1, > + RTW_REGD_ETSI = 2, > + RTW_REGD_WW = 3, > + > + RTW_REGD_MAX > +}; > + > +enum rtw_flags { > + RTW_FLAG_RUNNING, > + RTW_FLAG_FW_RUNNING, > + RTW_FLAG_SCANNING, > + RTW_FLAG_INACTIVE_PS, > + RTW_FLAG_LEISURE_PS, > + RTW_FLAG_DIG_DISABLE, > + > + NUM_OF_RTW_FLAGS, > +}; > + > +/* the power index is represented by differences, which cck-1s & ht40-1s are > + * the base values, so for 1s's differences, there are only ht20 & ofdm > + */ > +struct rtw_2g_1s_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 ofdm:4; > + s8 bw20:4; > +#else > + s8 bw20:4; > + s8 ofdm:4; > +#endif > +} __packed; > + > +struct rtw_2g_ns_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 bw20:4; > + s8 bw40:4; > + s8 cck:4; > + s8 ofdm:4; > +#else > + s8 ofdm:4; > + s8 cck:4; > + s8 bw40:4; > + s8 bw20:4; > +#endif > +} __packed; > + > +struct rtw_2g_txpwr_idx { > + u8 cck_base[6]; > + u8 bw40_base[5]; > + struct rtw_2g_1s_pwr_idx_diff ht_1s_diff; > + struct rtw_2g_ns_pwr_idx_diff ht_2s_diff; > + struct rtw_2g_ns_pwr_idx_diff ht_3s_diff; > + struct rtw_2g_ns_pwr_idx_diff ht_4s_diff; > +}; > + > +struct rtw_5g_ht_1s_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 ofdm:4; > + s8 bw20:4; > +#else > + s8 bw20:4; > + s8 ofdm:4; > +#endif > +} __packed; > + > +struct rtw_5g_ht_ns_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 bw20:4; > + s8 bw40:4; > +#else > + s8 bw40:4; > + s8 bw20:4; > +#endif > +} __packed; > + > +struct rtw_5g_ofdm_ns_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 ofdm_3s:4; > + s8 ofdm_2s:4; > + s8 ofdm_4s:4; > + s8 res:4; > +#else > + s8 res:4; > + s8 ofdm_4s:4; > + s8 ofdm_2s:4; > + s8 ofdm_3s:4; > +#endif > +} __packed; > + > +struct rtw_5g_vht_ns_pwr_idx_diff { > +#ifdef __LITTLE_ENDIAN > + s8 bw160:4; > + s8 bw80:4; > +#else > + s8 bw80:4; > + s8 bw160:4; > +#endif > +} __packed; > + > +struct rtw_5g_txpwr_idx { > + u8 bw40_base[14]; > + struct rtw_5g_ht_1s_pwr_idx_diff ht_1s_diff; > + struct rtw_5g_ht_ns_pwr_idx_diff ht_2s_diff; > + struct rtw_5g_ht_ns_pwr_idx_diff ht_3s_diff; > + struct rtw_5g_ht_ns_pwr_idx_diff ht_4s_diff; > + struct rtw_5g_ofdm_ns_pwr_idx_diff ofdm_diff; > + struct rtw_5g_vht_ns_pwr_idx_diff vht_1s_diff; > + struct rtw_5g_vht_ns_pwr_idx_diff vht_2s_diff; > + struct rtw_5g_vht_ns_pwr_idx_diff vht_3s_diff; > + struct rtw_5g_vht_ns_pwr_idx_diff vht_4s_diff; > +}; > + > +struct rtw_txpwr_idx { > + struct rtw_2g_txpwr_idx pwr_idx_2g; > + struct rtw_5g_txpwr_idx pwr_idx_5g; > +}; > + > +struct rtw_timer_list { > + struct timer_list timer; > + void (*function)(void *data); > + void *args; > +}; > + > +struct rtw_channel_params { > + u8 center_chan; > + u8 bandwidth; > + u8 primary_chan_idx; > +}; > + > +struct rtw_hw_reg { > + u32 addr; > + u32 mask; > +}; > + > +struct rtw_backup_info { > + u8 len; > + u32 reg; > + u32 val; > +}; > + > +enum rtw_vif_port_set { > + PORT_SET_MAC_ADDR = BIT(0), > + PORT_SET_BSSID = BIT(1), > + PORT_SET_NET_TYPE = BIT(2), > + PORT_SET_AID = BIT(3), > +}; > + > +struct rtw_vif_port { > + struct rtw_hw_reg mac_addr; > + struct rtw_hw_reg bssid; > + struct rtw_hw_reg net_type; > + struct rtw_hw_reg aid; > +}; > + > +struct rtw_tx_pkt_info { > + u32 tx_pkt_size; > + u8 offset; > + u8 pkt_offset; > + u8 mac_id; > + u8 rate_id; > + u8 rate; > + u8 qsel; > + u8 bw; > + u8 sec_type; > + bool ampdu_en; > + u8 ampdu_factor; > + u8 ampdu_density; > + u16 seq; > + bool stbc; > + bool ldpc; > + bool dis_rate_fallback; > + bool bmc; > + bool use_rate; > + bool ls; > + bool fs; > + bool short_gi; > +}; > + > +struct rtw_rx_pkt_stat { > + bool phy_status; > + bool icv_err; > + bool crc_err; > + bool decrypted; > + bool is_c2h; > + > + s32 signal_power; > + u16 pkt_len; > + u8 bw; > + u8 drv_info_sz; > + u8 shift; > + u8 rate; > + u8 mac_id; > + u8 cam_id; > + u8 ppdu_cnt; > + u32 tsf_low; > + s8 rx_power[RTW_RF_PATH_MAX]; > + u8 rssi; > + u8 rxsc; > + struct rtw_sta_info *si; > + struct ieee80211_vif *vif; > +}; > + > +struct rtw_traffic_stats { > + /* units in bytes */ > + u64 tx_unicast; > + u64 rx_unicast; > + > + /* count for packets */ > + u64 tx_cnt; > + u64 rx_cnt; > + > + /* units in Mbps */ > + u32 tx_throughput; > + u32 rx_throughput; > +}; > + > +enum rtw_lps_mode { > + RTW_MODE_ACTIVE = 0, > + RTW_MODE_LPS = 1, > + RTW_MODE_WMM_PS = 2, > +}; > + > +enum rtw_pwr_state { > + RTW_RF_OFF = 0x0, > + RTW_RF_ON = 0x4, > + RTW_ALL_ON = 0xc, > +}; > + > +struct rtw_lps_conf { > + /* the interface to enter lps */ > + struct rtw_vif *rtwvif; > + enum rtw_lps_mode mode; > + enum rtw_pwr_state state; > + u8 awake_interval; > + u8 rlbm; > + u8 smart_ps; > + u8 port_id; > +}; > + > +enum rtw_hw_key_type { > + RTW_CAM_NONE = 0, > + RTW_CAM_WEP40 = 1, > + RTW_CAM_TKIP = 2, > + RTW_CAM_AES = 4, > + RTW_CAM_WEP104 = 5, > +}; > + > +struct rtw_cam_entry { > + bool valid; > + bool group; > + u8 addr[ETH_ALEN]; > + u8 hw_key_type; > + struct ieee80211_key_conf *key; > +}; > + > +struct rtw_sec_desc { > + /* search strategy */ > + bool default_key_search; > + > + u32 total_cam_num; > + struct rtw_cam_entry cam_table[RTW_MAX_SEC_CAM_NUM]; > + DECLARE_BITMAP(cam_map, RTW_MAX_SEC_CAM_NUM); > +}; > + > +#define RTW_BC_MC_MACID 1 > +DECLARE_EWMA(rssi, 10, 16); > + > +struct rtw_sta_info { > + struct ieee80211_sta *sta; > + struct ieee80211_vif *vif; > + > + struct ewma_rssi avg_rssi; > + u8 rssi_level; > + > + u8 mac_id; > + u8 rate_id; > + enum rtw_bandwidth bw_mode; > + enum rtw_rf_type rf_type; > + enum rtw_wireless_set wireless_set; > + u8 stbc_en:2; > + u8 ldpc_en:2; > + bool sgi_enable; > + bool vht_enable; > + bool updated; > + u8 init_ra_lv; > + u64 ra_mask; > +}; > + > +struct rtw_vif { > + struct ieee80211_vif *vif; > + enum rtw_net_type net_type; > + u16 aid; > + u8 mac_addr[ETH_ALEN]; > + u8 bssid[ETH_ALEN]; > + u8 port; > + const struct rtw_vif_port *conf; > + > + struct rtw_traffic_stats stats; > + bool in_lps; > +}; > + > +struct rtw_regulatory { > + char alpha2[2]; > + u8 chplan; > + u8 txpwr_regd; > +}; > + > +struct rtw_chip_ops { > + int (*mac_init)(struct rtw_dev *rtwdev); > + int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); > + void (*phy_set_param)(struct rtw_dev *rtwdev); > + void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, > + u8 bandwidth, u8 primary_chan_idx); > + void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, > + struct rtw_rx_pkt_stat *pkt_stat, > + struct ieee80211_rx_status *rx_status); > + u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, > + u32 addr, u32 mask); > + bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, > + u32 addr, u32 mask, u32 data); > + void (*set_tx_power_index)(struct rtw_dev *rtwdev, u8 power_index, > + u8 rf_path, u8 rate); > + int (*rsvd_page_dump)(struct rtw_dev *rtwdev, u8 *buf, u32 offset, > + u32 size); > + void (*set_antenna)(struct rtw_dev *rtwdev, u8 antenna_tx, > + u8 antenna_rx); > + void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable); > + void (*false_alarm_statistics)(struct rtw_dev *rtwdev); > + void (*do_iqk)(struct rtw_dev *rtwdev); > +}; > + > +#define RTW_PWR_POLLING_CNT 20000 > + > +#define RTW_PWR_CMD_READ 0x00 > +#define RTW_PWR_CMD_WRITE 0x01 > +#define RTW_PWR_CMD_POLLING 0x02 > +#define RTW_PWR_CMD_DELAY 0x03 > +#define RTW_PWR_CMD_END 0x04 > + > +/* define the base address of each block */ > +#define RTW_PWR_ADDR_MAC 0x00 > +#define RTW_PWR_ADDR_USB 0x01 > +#define RTW_PWR_ADDR_PCIE 0x02 > +#define RTW_PWR_ADDR_SDIO 0x03 > + > +#define RTW_PWR_INTF_SDIO_MSK BIT(0) > +#define RTW_PWR_INTF_USB_MSK BIT(1) > +#define RTW_PWR_INTF_PCI_MSK BIT(2) > +#define RTW_PWR_INTF_ALL_MSK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) > + > +#define RTW_PWR_CUT_A_MSK BIT(1) > +#define RTW_PWR_CUT_B_MSK BIT(2) > +#define RTW_PWR_CUT_C_MSK BIT(3) > +#define RTW_PWR_CUT_D_MSK BIT(4) > +#define RTW_PWR_CUT_E_MSK BIT(5) > +#define RTW_PWR_CUT_F_MSK BIT(6) > +#define RTW_PWR_CUT_G_MSK BIT(7) > +#define RTW_PWR_CUT_ALL_MSK 0xFF > + > +enum rtw_pwr_seq_cmd_delay_unit { > + RTW_PWR_DELAY_US, > + RTW_PWR_DELAY_MS, > +}; > + > +struct rtw_pwr_seq_cmd { > + u16 offset; > + u8 cut_mask; > + u8 intf_mask; > + u8 base:4; > + u8 cmd:4; > + u8 mask; > + u8 value; > +}; > + > +enum rtw_chip_ver { > + RTW_CHIP_VER_CUT_A = 0x00, > + RTW_CHIP_VER_CUT_B = 0x01, > + RTW_CHIP_VER_CUT_C = 0x02, > + RTW_CHIP_VER_CUT_D = 0x03, > + RTW_CHIP_VER_CUT_E = 0x04, > + RTW_CHIP_VER_CUT_F = 0x05, > + RTW_CHIP_VER_CUT_G = 0x06, > +}; > + > +#define RTW_INTF_PHY_PLATFORM_ALL 0 > + > +enum rtw_intf_phy_cut { > + RTW_INTF_PHY_CUT_A = BIT(0), > + RTW_INTF_PHY_CUT_B = BIT(1), > + RTW_INTF_PHY_CUT_C = BIT(2), > + RTW_INTF_PHY_CUT_D = BIT(3), > + RTW_INTF_PHY_CUT_E = BIT(4), > + RTW_INTF_PHY_CUT_F = BIT(5), > + RTW_INTF_PHY_CUT_G = BIT(6), > + RTW_INTF_PHY_CUT_ALL = 0xFFFF, > +}; > + > +enum rtw_ip_sel { > + RTW_IP_SEL_PHY = 0, > + RTW_IP_SEL_MAC = 1, > + RTW_IP_SEL_DBI = 2, > + > + RTW_IP_SEL_UNDEF = 0xFFFF > +}; > + > +enum rtw_pq_map_id { > + RTW_PQ_MAP_VO = 0x0, > + RTW_PQ_MAP_VI = 0x1, > + RTW_PQ_MAP_BE = 0x2, > + RTW_PQ_MAP_BK = 0x3, > + RTW_PQ_MAP_MG = 0x4, > + RTW_PQ_MAP_HI = 0x5, > + RTW_PQ_MAP_NUM = 0x6, > + > + RTW_PQ_MAP_UNDEF, > +}; > + > +enum rtw_dma_mapping { > + RTW_DMA_MAPPING_EXTRA = 0, > + RTW_DMA_MAPPING_LOW = 1, > + RTW_DMA_MAPPING_NORMAL = 2, > + RTW_DMA_MAPPING_HIGH = 3, > + > + RTW_DMA_MAPPING_UNDEF, > +}; > + > +struct rtw_rqpn { > + enum rtw_dma_mapping dma_map_vo; > + enum rtw_dma_mapping dma_map_vi; > + enum rtw_dma_mapping dma_map_be; > + enum rtw_dma_mapping dma_map_bk; > + enum rtw_dma_mapping dma_map_mg; > + enum rtw_dma_mapping dma_map_hi; > +}; > + > +struct rtw_page_table { > + u16 hq_num; > + u16 nq_num; > + u16 lq_num; > + u16 exq_num; > + u16 gapq_num; > +}; > + > +struct rtw_intf_phy_para { > + u16 offset; > + u16 value; > + u16 ip_sel; > + u16 cut_mask; > + u16 platform; > +}; > + > +struct rtw_intf_phy_para_table { > + struct rtw_intf_phy_para *usb2_para; > + struct rtw_intf_phy_para *usb3_para; > + struct rtw_intf_phy_para *gen1_para; > + struct rtw_intf_phy_para *gen2_para; > + u8 n_usb2_para; > + u8 n_usb3_para; > + u8 n_gen1_para; > + u8 n_gen2_para; > +}; > + > +struct rtw_table { > + const void *data; > + const u32 size; > + void (*parse)(struct rtw_dev *rtwdev, const struct rtw_table *tbl); > + void (*do_cfg)(struct rtw_dev *rtwdev, const struct rtw_table *tbl, > + u32 addr, u32 data); > + enum rtw_rf_path rf_path; > +}; > + > +static inline void rtw_load_table(struct rtw_dev *rtwdev, > + const struct rtw_table *tbl) > +{ > + (*tbl->parse)(rtwdev, tbl); > +} > + > +enum rtw_rfe_fem { > + RTW_RFE_IFEM, > + RTW_RFE_EFEM, > + RTW_RFE_IFEM2G_EFEM5G, > + RTW_RFE_NUM, > +}; > + > +struct rtw_rfe_def { > + const struct rtw_table *phy_pg_tbl; > + const struct rtw_table *txpwr_lmt_tbl; > +}; > + > +#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \ > + .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ > + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ > + } > + > +/* hardware configuration for each IC */ > +struct rtw_chip_info { > + struct rtw_chip_ops *ops; > + u8 id; > + > + const char *fw_name; > + u8 tx_pkt_desc_sz; > + u8 tx_buf_desc_sz; > + u8 rx_pkt_desc_sz; > + u8 rx_buf_desc_sz; > + u32 phy_efuse_size; > + u32 log_efuse_size; > + u32 ptct_efuse_size; > + u32 txff_size; > + u32 rxff_size; > + u8 band; > + u8 page_size; > + u8 csi_buf_pg_num; > + u8 dig_max; > + u8 dig_min; > + > + bool ht_supported; > + bool vht_supported; > + > + /* init values */ > + u8 sys_func_en; > + struct rtw_pwr_seq_cmd **pwr_on_seq; > + struct rtw_pwr_seq_cmd **pwr_off_seq; > + struct rtw_rqpn *rqpn_table; > + struct rtw_page_table *page_table; > + struct rtw_intf_phy_para_table *intf_table; > + > + struct rtw_hw_reg *dig; > + u32 rf_base_addr[2]; > + u32 rf_sipi_addr[2]; > + > + const struct rtw_table *mac_tbl; > + const struct rtw_table *agc_tbl; > + const struct rtw_table *bb_tbl; > + const struct rtw_table *rf_tbl[RTW_RF_PATH_MAX]; > + > + const struct rtw_rfe_def *rfe_defs; > + u32 rfe_defs_size; > +}; > + > +struct rtw_dm_info { > + u32 cck_fa_cnt; > + u32 ofdm_fa_cnt; > + u32 total_fa_cnt; > + u8 min_rssi; > + u8 pre_min_rssi; > + u16 fa_history[4]; > + u8 igi_history[4]; > + u8 igi_bitmap; > + bool damping; > + u8 damping_cnt; > + u8 damping_rssi; > + > + u8 cck_gi_u_bnd; > + u8 cck_gi_l_bnd; > +}; > + > +struct rtw_efuse { > + u32 size; > + u32 physical_size; > + u32 logical_size; > + u32 protect_size; > + > + u8 addr[ETH_ALEN]; > + u8 channel_plan; > + u8 country_code[2]; > + u8 rfe_option; > + u8 thermal_meter; > + u8 crystal_cap; > + u8 ant_div_cfg; > + u8 ant_div_type; > + u8 regd; > + > + u8 lna_type_2g; > + u8 lna_type_5g; > + u8 glna_type; > + u8 alna_type; > + bool ext_lna_2g; > + bool ext_lna_5g; > + u8 pa_type_2g; > + u8 pa_type_5g; > + u8 gpa_type; > + u8 apa_type; > + bool ext_pa_2g; > + bool ext_pa_5g; > + u8 x3d7; > + u8 x3d8; > + > + bool btcoex; > + /* bt share antenna with wifi */ > + bool share_ant; > + u8 bt_setting; > + > + struct { > + u8 hci; > + u8 bw; > + u8 ptcl; > + u8 nss; > + u8 ant_num; > + } hw_cap; > + > + struct rtw_txpwr_idx txpwr_idx_table[4]; > +}; > + > +struct rtw_phy_cond { > +#ifdef __LITTLE_ENDIAN > + u32 rfe:8; > + u32 intf:4; > + u32 pkg:4; > + u32 plat:4; > + u32 intf_rsvd:4; > + u32 cut:4; > + u32 branch:2; > + u32 neg:1; > + u32 pos:1; > +#else > + u32 pos:1; > + u32 neg:1; > + u32 branch:2; > + u32 cut:4; > + u32 intf_rsvd:4; > + u32 plat:4; > + u32 pkg:4; > + u32 intf:4; > + u32 rfe:8; > +#endif > + /* for intf:4 */ > + #define INTF_PCIE BIT(0) > + #define INTF_USB BIT(1) > + #define INTF_SDIO BIT(2) > + /* for branch:2 */ > + #define BRANCH_IF 0 > + #define BRANCH_ELIF 1 > + #define BRANCH_ELSE 2 > + #define BRANCH_ENDIF 3 > +}; > + > +struct rtw_fifo_conf { > + /* tx fifo information */ > + u16 rsvd_boundary; > + u16 rsvd_pg_num; > + u16 rsvd_drv_pg_num; > + u16 txff_pg_num; > + u16 acq_pg_num; > + u16 rsvd_drv_addr; > + u16 rsvd_h2c_info_addr; > + u16 rsvd_h2c_sta_info_addr; > + u16 rsvd_h2cq_addr; > + u16 rsvd_cpu_instr_addr; > + u16 rsvd_fw_txbuf_addr; > + u16 rsvd_csibuf_addr; > + enum rtw_dma_mapping pq_map[RTW_PQ_MAP_NUM]; > +}; > + > +struct rtw_fw_state { > + const struct firmware *firmware; > + struct completion completion; > + u16 version; > + u8 sub_version; > + u8 sub_index; > + u16 h2c_version; > +}; > + > +struct rtw_hal { > + u32 rcr; > + > + u32 chip_version; > + u8 fab_version; > + u8 cut_version; > + u8 mp_chip; > + u8 oem_id; > + struct rtw_phy_cond phy_cond; > + > + u8 ps_mode; > + u8 current_channel; > + u8 current_band_width; > + u8 current_band_type; > + u8 sec_ch_offset; > + u8 rf_type; > + u8 rf_path_num; > + u8 antenna_tx; > + u8 antenna_rx; > + > + /* protect tx power section */ > + struct mutex tx_power_mutex; > + s8 tx_pwr_by_rate_offset_2g[RTW_RF_PATH_MAX] > + [DESC_RATE_MAX]; > + s8 tx_pwr_by_rate_offset_5g[RTW_RF_PATH_MAX] > + [DESC_RATE_MAX]; > + s8 tx_pwr_by_rate_base_2g[RTW_RF_PATH_MAX] > + [RTW_RATE_SECTION_MAX]; > + s8 tx_pwr_by_rate_base_5g[RTW_RF_PATH_MAX] > + [RTW_RATE_SECTION_MAX]; > + s8 tx_pwr_limit_2g[RTW_REGD_MAX] > + [RTW_CHANNEL_WIDTH_MAX] > + [RTW_RATE_SECTION_MAX] > + [RTW_MAX_CHANNEL_NUM_2G]; > + s8 tx_pwr_limit_5g[RTW_REGD_MAX] > + [RTW_CHANNEL_WIDTH_MAX] > + [RTW_RATE_SECTION_MAX] > + [RTW_MAX_CHANNEL_NUM_5G]; > +}; > + > +struct rtw_dev { > + struct ieee80211_hw *hw; > + struct device *dev; > + > + struct rtw_hci hci; > + > + struct rtw_chip_info *chip; > + struct rtw_hal hal; > + struct rtw_fifo_conf fifo; > + struct rtw_fw_state fw; > + struct rtw_efuse efuse; > + struct rtw_sec_desc sec; > + struct rtw_traffic_stats stats; > + struct rtw_regulatory regd; > + > + struct rtw_dm_info dm_info; > + > + /* ensures exclusive access from mac80211 callbacks */ > + struct mutex mutex; > + > + /* lock for dm to use */ > + spinlock_t dm_lock; > + > + /* read/write rf register */ > + spinlock_t rf_lock; > + > + /* watch dog every 2 sec */ > + struct delayed_work watch_dog_work; > + u32 watch_dog_cnt; > + > + struct list_head rsvd_page_list; > + > + /* c2h cmd queue & handler work */ > + struct sk_buff_head c2h_queue; > + struct work_struct c2h_work; > + > + struct { > + /* incicate the mail box to use with fw */ > + u8 last_box_num; > + /* protect to send h2c to fw */ > + spinlock_t lock; > + u32 seq; > + } h2c; > + > + /* lps power state & handler work */ > + struct rtw_lps_conf lps_conf; > + struct delayed_work lps_work; > + > + struct dentry *debugfs; > + > + u8 sta_cnt; > + > + DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM); > + DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS); > + > + u8 mp_mode; > + > + /* hci related data, must be last */ > + u8 priv[0] __aligned(sizeof(void *)); > +}; > + > +#include "hci.h" > + > +static inline bool rtw_flag_check(struct rtw_dev *rtwdev, enum rtw_flags flag) > +{ > + return test_bit(flag, rtwdev->flags); > +} > + > +static inline void rtw_flag_clear(struct rtw_dev *rtwdev, enum rtw_flags flag) > +{ > + clear_bit(flag, rtwdev->flags); > +} > + > +static inline void rtw_flag_set(struct rtw_dev *rtwdev, enum rtw_flags flag) > +{ > + set_bit(flag, rtwdev->flags); > +} > + > +static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) > +{ > + __le16 fc = hdr->frame_control; > + u8 *bssid; > + > + if (ieee80211_has_tods(fc)) > + bssid = hdr->addr1; > + else if (ieee80211_has_fromds(fc)) > + bssid = hdr->addr2; > + else > + bssid = hdr->addr3; > + > + return bssid; > +} > + > +static inline bool check_hw_ready(struct rtw_dev *rtwdev, > + u32 addr, u32 mask, u32 target) > +{ > + u32 cnt; > + > + for (cnt = 0; cnt < 1000; cnt++) { > + if (rtw_read32_mask(rtwdev, addr, mask) == target) > + return true; > + > + udelay(10); > + } > + > + return false; > +} > + > +#define rtw_iterate_vifs(rtwdev, iterator, data) > \ > + ieee80211_iterate_active_interfaces(rtwdev->hw, > \ > + IEEE80211_IFACE_ITER_NORMAL, iterator, data) > +#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) > \ > + ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, > \ > + IEEE80211_IFACE_ITER_NORMAL, iterator, data) > +#define rtw_iterate_stas_atomic(rtwdev, iterator, data) > \ > + ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data) > + > +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, > + struct rtw_channel_params *ch_param); > +void rtw_set_channel(struct rtw_dev *rtwdev); > +void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, > + u32 config); > +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); > +int rtw_core_start(struct rtw_dev *rtwdev); > +void rtw_core_stop(struct rtw_dev *rtwdev); > +int rtw_chip_info_setup(struct rtw_dev *rtwdev); > +int rtw_core_init(struct rtw_dev *rtwdev); > +void rtw_core_deinit(struct rtw_dev *rtwdev); > +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); > +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); > + > +#endif > diff --git a/drivers/net/wireless/realtek/rtw88/reg.h > b/drivers/net/wireless/realtek/rtw88/reg.h > new file mode 100644 > index 0000000..6e81829 > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/reg.h > @@ -0,0 +1,411 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* Copyright(c) 2018 Realtek Corporation. > + */ > + > +#ifndef __RTW_REG_DEF_H__ > +#define __RTW_REG_DEF_H__ > + > +#define REG_SYS_FUNC_EN 0x0002 > +#define BIT_FEN_CPUEN BIT(2) > +#define BIT_FEN_BB_GLB_RST BIT(1) > +#define BIT_FEN_BB_RSTB BIT(0) > +#define REG_SYS_PW_CTRL 0x0004 > +#define REG_SYS_CLK_CTRL 0x0008 > +#define BIT_CPU_CLK_EN BIT(14) > + > +#define REG_RSV_CTRL 0x001C > +#define BIT_WLMCU_IOIF BIT(0) > +#define REG_RF_CTRL 0x001F > +#define BIT_RF_SDM_RSTB BIT(2) > +#define BIT_RF_RSTB BIT(1) > +#define BIT_RF_EN BIT(0) > + > +#define REG_AFE_CTRL1 0x0024 > +#define BIT_MAC_CLK_SEL (BIT(20) | BIT(21)) > +#define REG_EFUSE_CTRL 0x0030 > +#define BIT_EF_FLAG BIT(31) > +#define BIT_SHIFT_EF_ADDR 8 > +#define BIT_MASK_EF_ADDR 0x3ff > +#define BIT_MASK_EF_DATA 0xff > +#define BITS_EF_ADDR (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR) > + > +#define REG_LDO_EFUSE_CTRL 0x0034 > +#define BIT_MASK_EFUSE_BANK_SEL (BIT(8) | BIT(9)) > + > +#define REG_GPIO_MUXCFG 0x0040 > +#define BIT_FSPI_EN BIT(19) > +#define BIT_WLRFE_4_5_EN BIT(2) > + > +#define REG_LED_CFG 0x004C > +#define BIT_LNAON_SEL_EN BIT(26) > +#define BIT_PAPE_SEL_EN BIT(25) > +#define REG_PAD_CTRL1 0x0064 > +#define BIT_PAPE_WLBT_SEL BIT(29) > +#define BIT_LNAON_WLBT_SEL BIT(28) > +#define REG_WL_BT_PWR_CTRL 0x0068 > +#define BIT_BT_FUNC_EN BIT(18) > +#define BIT_BT_DIG_CLK_EN BIT(8) > +#define REG_HCI_OPT_CTRL 0x0074 > + > +#define REG_MCUFW_CTRL 0x0080 > +#define BIT_ANA_PORT_EN BIT(22) > +#define BIT_MAC_PORT_EN BIT(21) > +#define BIT_BOOT_FSPI_EN BIT(20) > +#define BIT_FW_INIT_RDY BIT(15) > +#define BIT_FW_DW_RDY BIT(14) > +#define BIT_RPWM_TOGGLE BIT(7) > +#define BIT_DMEM_CHKSUM_OK BIT(6) > +#define BIT_DMEM_DW_OK BIT(5) > +#define BIT_IMEM_CHKSUM_OK BIT(4) > +#define BIT_IMEM_DW_OK BIT(3) > +#define BIT_IMEM_BOOT_LOAD_CHECKSUM_OK BIT(2) > +#define BIT_MCUFWDL_EN BIT(0) > +#define BIT_CHECK_SUM_OK (BIT(4) | BIT(6)) > +#define FW_READY (BIT_FW_INIT_RDY | BIT_FW_DW_RDY | > \ > + BIT_IMEM_DW_OK | BIT_DMEM_DW_OK | > \ > + BIT_CHECK_SUM_OK) > +#define FW_READY_MASK 0xffff > + > +#define REG_SYS_CFG1 0x00F0 > +#define BIT_RTL_ID BIT(23) > +#define BIT_RF_TYPE_ID BIT(27) > +#define BIT_SHIFT_VENDOR_ID 16 > +#define BIT_MASK_VENDOR_ID 0xf > +#define BIT_VENDOR_ID(x) (((x) & BIT_MASK_VENDOR_ID) << > BIT_SHIFT_VENDOR_ID) > +#define BITS_VENDOR_ID (BIT_MASK_VENDOR_ID << > BIT_SHIFT_VENDOR_ID) > +#define BIT_CLEAR_VENDOR_ID(x) ((x) & (~BITS_VENDOR_ID)) > +#define BIT_GET_VENDOR_ID(x) (((x) >> BIT_SHIFT_VENDOR_ID) & > BIT_MASK_VENDOR_ID) > +#define BIT_SHIFT_CHIP_VER 12 > +#define BIT_MASK_CHIP_VER 0xf > +#define BIT_CHIP_VER(x) (((x) & BIT_MASK_CHIP_VER) << > BIT_SHIFT_CHIP_VER) > +#define BITS_CHIP_VER (BIT_MASK_CHIP_VER << > BIT_SHIFT_CHIP_VER) > +#define BIT_CLEAR_CHIP_VER(x) ((x) & (~BITS_CHIP_VER)) > +#define BIT_GET_CHIP_VER(x) (((x) >> BIT_SHIFT_CHIP_VER) & > BIT_MASK_CHIP_VER) > +#define REG_SYS_STATUS1 0x00F4 > +#define REG_SYS_STATUS2 0x00F8 > +#define REG_SYS_CFG2 0x00FC > +#define REG_WLRF1 0x00EC > +#define BIT_WLRF1_BBRF_EN (BIT(24) | BIT(25) | BIT(26)) > +#define REG_CR 0x0100 > +#define BIT_32K_CAL_TMR_EN BIT(10) > +#define BIT_MAC_SEC_EN BIT(9) > +#define BIT_ENSWBCN BIT(8) > +#define BIT_MACRXEN BIT(7) > +#define BIT_MACTXEN BIT(6) > +#define BIT_SCHEDULE_EN BIT(5) > +#define BIT_PROTOCOL_EN BIT(4) > +#define BIT_RXDMA_EN BIT(3) > +#define BIT_TXDMA_EN BIT(2) > +#define BIT_HCI_RXDMA_EN BIT(1) > +#define BIT_HCI_TXDMA_EN BIT(0) > +#define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | > BIT_TXDMA_EN | \ > + BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \ > + BIT_MACTXEN | BIT_MACRXEN) > +#define BIT_SHIFT_TXDMA_VOQ_MAP 4 > +#define BIT_MASK_TXDMA_VOQ_MAP 0x3 > +#define BIT_TXDMA_VOQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_VOQ_MAP) << BIT_SHIFT_TXDMA_VOQ_MAP) > +#define BIT_SHIFT_TXDMA_VIQ_MAP 6 > +#define BIT_MASK_TXDMA_VIQ_MAP 0x3 > +#define BIT_TXDMA_VIQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) > +#define REG_TXDMA_PQ_MAP 0x010C > +#define BIT_SHIFT_TXDMA_BEQ_MAP 8 > +#define BIT_MASK_TXDMA_BEQ_MAP 0x3 > +#define BIT_TXDMA_BEQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_BEQ_MAP) << BIT_SHIFT_TXDMA_BEQ_MAP) > +#define BIT_SHIFT_TXDMA_BKQ_MAP 10 > +#define BIT_MASK_TXDMA_BKQ_MAP 0x3 > +#define BIT_TXDMA_BKQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_BKQ_MAP) << BIT_SHIFT_TXDMA_BKQ_MAP) > +#define BIT_SHIFT_TXDMA_MGQ_MAP 12 > +#define BIT_MASK_TXDMA_MGQ_MAP 0x3 > +#define BIT_TXDMA_MGQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_MGQ_MAP) << > BIT_SHIFT_TXDMA_MGQ_MAP) > +#define BIT_SHIFT_TXDMA_HIQ_MAP 14 > +#define BIT_MASK_TXDMA_HIQ_MAP 0x3 > +#define BIT_TXDMA_HIQ_MAP(x) > \ > + (((x) & BIT_MASK_TXDMA_HIQ_MAP) << BIT_SHIFT_TXDMA_HIQ_MAP) > +#define BIT_SHIFT_TXSC_40M 4 > +#define BIT_MASK_TXSC_40M 0xf > +#define BIT_TXSC_40M(x) \ > + (((x) & BIT_MASK_TXSC_40M) << BIT_SHIFT_TXSC_40M) > +#define BIT_SHIFT_TXSC_20M 0 > +#define BIT_MASK_TXSC_20M 0xf > +#define BIT_TXSC_20M(x) \ > + (((x) & BIT_MASK_TXSC_20M) << BIT_SHIFT_TXSC_20M) > +#define BIT_SHIFT_MAC_CLK_SEL 20 > +#define MAC_CLK_HW_DEF_80M 0 > +#define MAC_CLK_HW_DEF_40M 1 > +#define MAC_CLK_HW_DEF_20M 2 > +#define MAC_CLK_SPEED 80 > + > +#define REG_CR 0x0100 > +#define REG_TRXFF_BNDY 0x0114 > +#define REG_RXFF_BNDY 0x011C > +#define REG_PKTBUF_DBG_CTRL 0x0140 > +#define REG_C2HEVT 0x01A0 > +#define REG_HMETFR 0x01CC > +#define REG_HMEBOX0 0x01D0 > +#define REG_HMEBOX1 0x01D4 > +#define REG_HMEBOX2 0x01D8 > +#define REG_HMEBOX3 0x01DC > +#define REG_HMEBOX0_EX 0x01F0 > +#define REG_HMEBOX1_EX 0x01F4 > +#define REG_HMEBOX2_EX 0x01F8 > +#define REG_HMEBOX3_EX 0x01FC > + > +#define REG_FIFOPAGE_CTRL_2 0x0204 > +#define BIT_BCN_VALID_V1 BIT(15) > +#define BIT_MASK_BCN_HEAD_1_V1 0xfff > +#define REG_AUTO_LLT_V1 0x0208 > +#define BIT_AUTO_INIT_LLT_V1 BIT(0) > +#define REG_TXDMA_OFFSET_CHK 0x020C > +#define REG_TXDMA_STATUS 0x0210 > +#define BTI_PAGE_OVF BIT(2) > +#define REG_RQPN_CTRL_1 0x0228 > +#define REG_RQPN_CTRL_2 0x022C > +#define BIT_LD_RQPN BIT(31) > +#define REG_FIFOPAGE_INFO_1 0x0230 > +#define REG_FIFOPAGE_INFO_2 0x0234 > +#define REG_FIFOPAGE_INFO_3 0x0238 > +#define REG_FIFOPAGE_INFO_4 0x023C > +#define REG_FIFOPAGE_INFO_5 0x0240 > +#define REG_H2C_HEAD 0x0244 > +#define REG_H2C_TAIL 0x0248 > +#define REG_H2C_READ_ADDR 0x024C > +#define REG_H2C_INFO 0x0254 > + > +#define REG_FWHW_TXQ_CTRL 0x0420 > +#define BIT_EN_WR_FREE_TAIL BIT(20) > +#define REG_BCNQ_BDNY_V1 0x0424 > +#define REG_LIFETIME_EN 0x0426 > +#define BIT_BA_PARSER_EN BIT(5) > +#define REG_SPEC_SIFS 0x0428 > +#define REG_DARFRC 0x0430 > +#define REG_DARFRCH 0x0434 > +#define REG_RARFRCH 0x043C > +#define REG_ARFR0 0x0444 > +#define REG_ARFRH0 0x0448 > +#define REG_ARFR1_V1 0x044C > +#define REG_ARFRH1_V1 0x0450 > +#define REG_CCK_CHECK 0x0454 > +#define BIT_CHECK_CCK_EN BIT(7) > +#define REG_AMPDU_MAX_TIME_V1 0x0455 > +#define REG_BCNQ1_BDNY_V1 0x0456 > +#define REG_TX_HANG_CTRL 0x045E > +#define BIT_EN_EOF_V1 BIT(2) > +#define REG_DATA_SC 0x0483 > +#define REG_ARFR4 0x049C > +#define REG_ARFRH4 0x04A0 > +#define REG_ARFR5 0x04A4 > +#define REG_ARFRH5 0x04A8 > +#define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC > +#define BIT_PRE_TX_CMD BIT(6) > +#define REG_PROT_MODE_CTRL 0x04C8 > +#define REG_BAR_MODE_CTRL 0x04CC > +#define REG_PRECNT_CTRL 0x04E5 > +#define BIT_EN_PRECNT BIT(11) > + > +#define REG_EDCA_VO_PARAM 0x0500 > +#define REG_EDCA_VI_PARAM 0x0504 > +#define REG_EDCA_BE_PARAM 0x0508 > +#define REG_EDCA_BK_PARAM 0x050C > +#define REG_PIFS 0x0512 > +#define REG_SIFS 0x0514 > +#define BIT_SHIFT_SIFS_OFDM_CTX 8 > +#define BIT_SHIFT_SIFS_CCK_TRX 16 > +#define BIT_SHIFT_SIFS_OFDM_TRX 24 > +#define REG_SLOT 0x051B > +#define REG_TX_PTCL_CTRL 0x0520 > +#define BIT_SIFS_BK_EN BIT(12) > +#define REG_TXPAUSE 0x0522 > +#define REG_RD_CTRL 0x0524 > +#define BIT_DIS_TXOP_CFE BIT(10) > +#define BIT_DIS_LSIG_CFE BIT(9) > +#define BIT_DIS_STBC_CFE BIT(8) > +#define REG_TBTT_PROHIBIT 0x0540 > +#define BIT_SHIFT_TBTT_HOLD_TIME_AP 8 > +#define REG_RD_NAV_NXT 0x0544 > +#define REG_BCN_CTRL 0x0550 > +#define BIT_DIS_TSF_UDT BIT(4) > +#define BIT_EN_BCN_FUNCTION BIT(3) > +#define REG_BCN_CTRL_CLINT0 0x0551 > +#define REG_DRVERLYINT 0x0558 > +#define REG_BCNDMATIM 0x0559 > +#define REG_USTIME_TSF 0x055C > +#define REG_BCN_MAX_ERR 0x055D > +#define REG_RXTSF_OFFSET_CCK 0x055E > +#define REG_MISC_CTRL 0x0577 > +#define BIT_EN_FREE_CNT BIT(3) > +#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1)) > +#define REG_TIMER0_SRC_SEL 0x05B4 > +#define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6)) > + > +#define REG_TCR 0x0604 > +#define REG_RCR 0x0608 > +#define BIT_APP_FCS BIT(31) > +#define BIT_APP_MIC BIT(30) > +#define BIT_APP_ICV BIT(29) > +#define BIT_APP_PHYSTS BIT(28) > +#define BIT_APP_BASSN BIT(27) > +#define BIT_VHT_DACK BIT(26) > +#define BIT_TCPOFLD_EN BIT(25) > +#define BIT_ENMBID BIT(24) > +#define BIT_LSIGEN BIT(23) > +#define BIT_MFBEN BIT(22) > +#define BIT_DISCHKPPDLLEN BIT(21) > +#define BIT_PKTCTL_DLEN BIT(20) > +#define BIT_TIM_PARSER_EN BIT(18) > +#define BIT_BC_MD_EN BIT(17) > +#define BIT_UC_MD_EN BIT(16) > +#define BIT_RXSK_PERPKT BIT(15) > +#define BIT_HTC_LOC_CTRL BIT(14) > +#define BIT_RPFM_CAM_ENABLE BIT(12) > +#define BIT_TA_BCN BIT(11) > +#define BIT_DISDECMYPKT BIT(10) > +#define BIT_AICV BIT(9) > +#define BIT_ACRC32 BIT(8) > +#define BIT_CBSSID_BCN BIT(7) > +#define BIT_CBSSID_DATA BIT(6) > +#define BIT_APWRMGT BIT(5) > +#define BIT_ADD3 BIT(4) > +#define BIT_AB BIT(3) > +#define BIT_AM BIT(2) > +#define BIT_APM BIT(1) > +#define BIT_AAP BIT(0) > +#define REG_RX_PKT_LIMIT 0x060C > +#define REG_RX_DRVINFO_SZ 0x060F > +#define BIT_APP_PHYSTS BIT(28) > +#define REG_USTIME_EDCA 0x0638 > +#define REG_RESP_SIFS_CCK 0x063C > +#define REG_RESP_SIFS_OFDM 0x063E > +#define REG_ACKTO 0x0640 > +#define REG_EIFS 0x0642 > +#define REG_NAV_CTRL 0x0650 > +#define REG_WMAC_TRXPTCL_CTL 0x0668 > +#define BIT_RFMOD (BIT(7) | BIT(8)) > +#define BIT_RFMOD_80M BIT(7) > +#define BIT_RFMOD_40M BIT(8) > +#define REG_WMAC_TRXPTCL_CTL_H 0x066C > +#define REG_RXFLTMAP0 0x06A0 > +#define REG_RXFLTMAP1 0x06A2 > +#define REG_RXFLTMAP2 0x06A4 > +#define REG_BBPSF_CTRL 0x06DC > + > +#define REG_WMAC_OPTION_FUNCTION 0x07D0 > +#define REG_WMAC_OPTION_FUNCTION_1 0x07D4 > + > +#define REG_CPU_DMEM_CON 0x1080 > +#define BIT_WL_PLATFORM_RST BIT(16) > +#define BIT_WL_SECURITY_CLK BIT(15) > +#define BIT_DDMA_EN BIT(8) > + > +#define REG_H2C_PKT_READADDR 0x10D0 > +#define REG_H2C_PKT_WRITEADDR 0x10D4 > +#define REG_FW_DBG7 0x10FC > +#define FW_KEY_MASK 0xffffff00 > + > +#define REG_CR_EXT 0x1100 > + > +#define REG_DDMA_CH0SA 0x1200 > +#define REG_DDMA_CH0DA 0x1204 > +#define REG_DDMA_CH0CTRL 0x1208 > +#define BIT_DDMACH0_OWN BIT(31) > +#define BIT_DDMACH0_CHKSUM_EN BIT(29) > +#define BIT_DDMACH0_CHKSUM_STS BIT(27) > +#define BIT_DDMACH0_RESET_CHKSUM_STS BIT(25) > +#define BIT_DDMACH0_CHKSUM_CONT BIT(24) > +#define BIT_MASK_DDMACH0_DLEN 0x3ffff > + > +#define REG_H2CQ_CSR 0x1330 > +#define BIT_H2CQ_FULL BIT(31) > +#define REG_FAST_EDCA_VOVI_SETTING 0x1448 > +#define REG_FAST_EDCA_BEBK_SETTING 0x144C > + > +#define REG_RXPSF_CTRL 0x1610 > +#define BIT_RXGCK_FIFOTHR_EN BIT(28) > + > +#define BIT_SHIFT_RXGCK_VHT_FIFOTHR 26 > +#define BIT_MASK_RXGCK_VHT_FIFOTHR 0x3 > +#define BIT_RXGCK_VHT_FIFOTHR(x) > \ > + (((x) & BIT_MASK_RXGCK_VHT_FIFOTHR) << > BIT_SHIFT_RXGCK_VHT_FIFOTHR) > +#define BITS_RXGCK_VHT_FIFOTHR > \ > + (BIT_MASK_RXGCK_VHT_FIFOTHR << BIT_SHIFT_RXGCK_VHT_FIFOTHR) > + > +#define BIT_SHIFT_RXGCK_HT_FIFOTHR 24 > +#define BIT_MASK_RXGCK_HT_FIFOTHR 0x3 > +#define BIT_RXGCK_HT_FIFOTHR(x) > \ > + (((x) & BIT_MASK_RXGCK_HT_FIFOTHR) << > BIT_SHIFT_RXGCK_HT_FIFOTHR) > +#define BITS_RXGCK_HT_FIFOTHR > \ > + (BIT_MASK_RXGCK_HT_FIFOTHR << BIT_SHIFT_RXGCK_HT_FIFOTHR) > + > +#define BIT_SHIFT_RXGCK_OFDM_FIFOTHR 22 > +#define BIT_MASK_RXGCK_OFDM_FIFOTHR 0x3 > +#define BIT_RXGCK_OFDM_FIFOTHR(x) > \ > + (((x) & BIT_MASK_RXGCK_OFDM_FIFOTHR) << > BIT_SHIFT_RXGCK_OFDM_FIFOTHR) > +#define BITS_RXGCK_OFDM_FIFOTHR > \ > + (BIT_MASK_RXGCK_OFDM_FIFOTHR << > BIT_SHIFT_RXGCK_OFDM_FIFOTHR) > + > +#define BIT_SHIFT_RXGCK_CCK_FIFOTHR 20 > +#define BIT_MASK_RXGCK_CCK_FIFOTHR 0x3 > +#define BIT_RXGCK_CCK_FIFOTHR(x) > \ > + (((x) & BIT_MASK_RXGCK_CCK_FIFOTHR) << > BIT_SHIFT_RXGCK_CCK_FIFOTHR) > +#define BITS_RXGCK_CCK_FIFOTHR > \ > + (BIT_MASK_RXGCK_CCK_FIFOTHR << BIT_SHIFT_RXGCK_CCK_FIFOTHR) > + > +#define BIT_RXGCK_OFDMCCA_EN BIT(16) > + > +#define BIT_SHIFT_RXPSF_PKTLENTHR 13 > +#define BIT_MASK_RXPSF_PKTLENTHR 0x7 > +#define BIT_RXPSF_PKTLENTHR(x) > \ > + (((x) & BIT_MASK_RXPSF_PKTLENTHR) << BIT_SHIFT_RXPSF_PKTLENTHR) > +#define BITS_RXPSF_PKTLENTHR > \ > + (BIT_MASK_RXPSF_PKTLENTHR << BIT_SHIFT_RXPSF_PKTLENTHR) > +#define BIT_CLEAR_RXPSF_PKTLENTHR(x) ((x) & (~BITS_RXPSF_PKTLENTHR)) > +#define BIT_SET_RXPSF_PKTLENTHR(x, v) > \ > + (BIT_CLEAR_RXPSF_PKTLENTHR(x) | BIT_RXPSF_PKTLENTHR(v)) > + > +#define BIT_RXPSF_CTRLEN BIT(12) > +#define BIT_RXPSF_VHTCHKEN BIT(11) > +#define BIT_RXPSF_HTCHKEN BIT(10) > +#define BIT_RXPSF_OFDMCHKEN BIT(9) > +#define BIT_RXPSF_CCKCHKEN BIT(8) > +#define BIT_RXPSF_OFDMRST BIT(7) > +#define BIT_RXPSF_CCKRST BIT(6) > +#define BIT_RXPSF_MHCHKEN BIT(5) > +#define BIT_RXPSF_CONT_ERRCHKEN BIT(4) > +#define BIT_RXPSF_ALL_ERRCHKEN BIT(3) > + > +#define BIT_SHIFT_RXPSF_ERRTHR 0 > +#define BIT_MASK_RXPSF_ERRTHR 0x7 > +#define BIT_RXPSF_ERRTHR(x) > \ > + (((x) & BIT_MASK_RXPSF_ERRTHR) << BIT_SHIFT_RXPSF_ERRTHR) > +#define BITS_RXPSF_ERRTHR (BIT_MASK_RXPSF_ERRTHR << > BIT_SHIFT_RXPSF_ERRTHR) > +#define BIT_CLEAR_RXPSF_ERRTHR(x) ((x) & (~BITS_RXPSF_ERRTHR)) > +#define BIT_GET_RXPSF_ERRTHR(x) > \ > + (((x) >> BIT_SHIFT_RXPSF_ERRTHR) & BIT_MASK_RXPSF_ERRTHR) > +#define BIT_SET_RXPSF_ERRTHR(x, v) > \ > + (BIT_CLEAR_RXPSF_ERRTHR(x) | BIT_RXPSF_ERRTHR(v)) > + > +#define REG_RXPSF_TYPE_CTRL 0x1614 > + > +#define REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 0x1700 > +#define REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 0x1704 > +#define REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 0x1708 > +#define LTECOEX_READY BIT(29) > +#define LTECOEX_ACCESS_CTRL > REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 > +#define LTECOEX_WRITE_DATA > REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 > +#define LTECOEX_READ_DATA > REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 > + > +#define RF_DTXLOK 0x08 > +#define RF_CFGCH 0x18 > +#define RF_LUTWA 0x33 > +#define RF_LUTWD1 0x3e > +#define RF_LUTWD0 0x3f > +#define RF_XTALX2 0xb8 > +#define RF_MALSEL 0xbe > +#define RF_LUTDBG 0xdf > +#define RF_LUTWE 0xef > + > +#endif > -- > 2.7.4 > > > ------Please consider the environment before printing this e-mail.
Tony Chuang <yhchuang@realtek.com> writes: > This patch added a comment about our watch dog timer, please let me > know if you are OK with it. Also if you have other questions about the > series, just point it out and I will try to fix it. Thanks. Thanks, I'll try to review the driver soon. But PLEASE do not top post, it makes my use of patchwork much more difficult. Just look at yourself how hard this page is to read now because you decided to include the full patch in your reply: https://patchwork.kernel.org/patch/10686099/ More info here: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#do_not_top_post_and_edit_your_quotes
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c new file mode 100644 index 0000000..17b3651 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2018 Realtek Corporation. + */ + +#include "main.h" +#include "sec.h" +#include "tx.h" +#include "fw.h" +#include "mac.h" +#include "ps.h" +#include "reg.h" +#include "debug.h" + +static void rtw_ops_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_tx_pkt_info pkt_info = {0}; + + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) + goto out; + + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb); + if (rtw_hci_tx(rtwdev, &pkt_info, skb)) + goto out; + + return; + +out: + ieee80211_free_txskb(hw, skb); +} + +static int rtw_ops_start(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret; + + mutex_lock(&rtwdev->mutex); + ret = rtw_core_start(rtwdev); + mutex_unlock(&rtwdev->mutex); + + return ret; +} + +static void rtw_ops_stop(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + + mutex_lock(&rtwdev->mutex); + rtw_core_stop(rtwdev); + mutex_unlock(&rtwdev->mutex); +} + +static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret = 0; + + mutex_lock(&rtwdev->mutex); + + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (hw->conf.flags & IEEE80211_CONF_IDLE) { + rtw_enter_ips(rtwdev); + } else { + ret = rtw_leave_ips(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave idle state\n"); + goto out; + } + } + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + rtw_set_channel(rtwdev); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static const struct rtw_vif_port rtw_vif_port[] = { + [0] = { + .mac_addr = {.addr = 0x0610}, + .bssid = {.addr = 0x0618}, + .net_type = {.addr = 0x0100, .mask = 0x30000}, + .aid = {.addr = 0x06a8, .mask = 0x7ff}, + }, + [1] = { + .mac_addr = {.addr = 0x0700}, + .bssid = {.addr = 0x0708}, + .net_type = {.addr = 0x0100, .mask = 0xc0000}, + .aid = {.addr = 0x0710, .mask = 0x7ff}, + }, + [2] = { + .mac_addr = {.addr = 0x1620}, + .bssid = {.addr = 0x1628}, + .net_type = {.addr = 0x1100, .mask = 0x3}, + .aid = {.addr = 0x1600, .mask = 0x7ff}, + }, + [3] = { + .mac_addr = {.addr = 0x1630}, + .bssid = {.addr = 0x1638}, + .net_type = {.addr = 0x1100, .mask = 0xc}, + .aid = {.addr = 0x1604, .mask = 0x7ff}, + }, + [4] = { + .mac_addr = {.addr = 0x1640}, + .bssid = {.addr = 0x1648}, + .net_type = {.addr = 0x1100, .mask = 0x30}, + .aid = {.addr = 0x1608, .mask = 0x7ff}, + }, +}; + +static int rtw_ops_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + enum rtw_net_type net_type; + u32 config = 0; + u8 port = 0; + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + rtwvif->port = port; + rtwvif->vif = vif; + rtwvif->stats.tx_unicast = 0; + rtwvif->stats.rx_unicast = 0; + rtwvif->stats.tx_cnt = 0; + rtwvif->stats.rx_cnt = 0; + rtwvif->in_lps = false; + rtwvif->conf = &rtw_vif_port[port]; + + mutex_lock(&rtwdev->mutex); + + switch (vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + net_type = RTW_NET_AP_MODE; + break; + case NL80211_IFTYPE_ADHOC: + net_type = RTW_NET_AD_HOC; + break; + case NL80211_IFTYPE_STATION: + default: + net_type = RTW_NET_NO_LINK; + break; + } + + ether_addr_copy(rtwvif->mac_addr, vif->addr); + config |= PORT_SET_MAC_ADDR; + rtwvif->net_type = net_type; + config |= PORT_SET_NET_TYPE; + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); + + rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port); + return 0; +} + +static void rtw_ops_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = 0; + + rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port); + + mutex_lock(&rtwdev->mutex); + + eth_zero_addr(rtwvif->mac_addr); + config |= PORT_SET_MAC_ADDR; + rtwvif->net_type = RTW_NET_NO_LINK; + config |= PORT_SET_NET_TYPE; + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); +} + +static void rtw_ops_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + u64 multicast) +{ + struct rtw_dev *rtwdev = hw->priv; + + *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL | + FIF_BCN_PRBRESP_PROMISC; + + mutex_lock(&rtwdev->mutex); + + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) + rtwdev->hal.rcr |= BIT_AM | BIT_AB; + else + rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB); + } + if (changed_flags & FIF_FCSFAIL) { + if (*new_flags & FIF_FCSFAIL) + rtwdev->hal.rcr |= BIT_ACRC32; + else + rtwdev->hal.rcr &= ~(BIT_ACRC32); + } + if (changed_flags & FIF_OTHER_BSS) { + if (*new_flags & FIF_OTHER_BSS) + rtwdev->hal.rcr |= BIT_AAP; + else + rtwdev->hal.rcr &= ~(BIT_AAP); + } + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA); + else + rtwdev->hal.rcr |= BIT_CBSSID_BCN; + } + + rtw_dbg(rtwdev, "config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n", + changed_flags, *new_flags, rtwdev->hal.rcr); + + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); + + mutex_unlock(&rtwdev->mutex); +} + +static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = 0; + + mutex_lock(&rtwdev->mutex); + + if (changed & BSS_CHANGED_ASSOC) { + struct rtw_chip_info *chip = rtwdev->chip; + enum rtw_net_type net_type; + + if (conf->assoc) { + net_type = RTW_NET_MGD_LINKED; + chip->ops->do_iqk(rtwdev); + + rtwvif->aid = conf->aid; + rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); + rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); + rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); + rtw_fw_download_rsvd_page(rtwdev, vif); + } else { + net_type = RTW_NET_NO_LINK; + rtwvif->aid = 0; + rtw_reset_rsvd_page(rtwdev); + } + + rtwvif->net_type = net_type; + config |= PORT_SET_NET_TYPE; + config |= PORT_SET_AID; + } + + if (changed & BSS_CHANGED_BSSID) { + ether_addr_copy(rtwvif->bssid, conf->bssid); + config |= PORT_SET_BSSID; + } + + if (changed & BSS_CHANGED_BEACON) + rtw_fw_download_rsvd_page(rtwdev, vif); + + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); +} + +static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) +{ + unsigned long mac_id; + + mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); + if (mac_id < RTW_MAX_MAC_ID_NUM) + set_bit(mac_id, rtwdev->mac_id_map); + + return mac_id; +} + +static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) +{ + clear_bit(mac_id, rtwdev->mac_id_map); +} + +static int rtw_ops_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + int ret = 0; + + mutex_lock(&rtwdev->mutex); + + si->mac_id = rtw_acquire_macid(rtwdev); + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) { + ret = -ENOSPC; + goto out; + } + + si->sta = sta; + si->vif = vif; + si->init_ra_lv = 1; + ewma_rssi_init(&si->avg_rssi); + + rtw_update_sta_info(rtwdev, si); + rtw_fw_media_status_report(rtwdev, si->mac_id, true); + + rtwdev->sta_cnt++; + + rtw_info(rtwdev, "sta %pM joined with macid %d\n", + sta->addr, si->mac_id); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static int rtw_ops_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + + mutex_lock(&rtwdev->mutex); + + rtw_release_macid(rtwdev, si->mac_id); + rtw_fw_media_status_report(rtwdev, si->mac_id, false); + + rtwdev->sta_cnt--; + + rtw_info(rtwdev, "sta %pM with macid %d left\n", + sta->addr, si->mac_id); + + mutex_unlock(&rtwdev->mutex); + return 0; +} + +static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sec_desc *sec = &rtwdev->sec; + u8 hw_key_type; + u8 hw_key_idx; + int ret = 0; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + hw_key_type = RTW_CAM_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + hw_key_type = RTW_CAM_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + hw_key_type = RTW_CAM_TKIP; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; + case WLAN_CIPHER_SUITE_CCMP: + hw_key_type = RTW_CAM_AES; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + /* suppress error messages */ + return -EOPNOTSUPP; + default: + return -ENOTSUPP; + } + + mutex_lock(&rtwdev->mutex); + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + hw_key_idx = rtw_sec_get_free_cam(sec); + } else { + /* multiple interfaces? */ + hw_key_idx = key->keyidx; + } + + if (hw_key_idx > sec->total_cam_num) { + ret = -ENOSPC; + goto out; + } + + switch (cmd) { + case SET_KEY: + /* need sw generated IV */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key->hw_key_idx = hw_key_idx; + rtw_sec_write_cam(rtwdev, sec, sta, key, + hw_key_type, hw_key_idx); + break; + case DISABLE_KEY: + rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); + break; + } + +out: + mutex_unlock(&rtwdev->mutex); + + return ret; +} + +static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + struct ieee80211_sta *sta = params->sta; + u16 tid = params->tid; + + switch (params->action) { + case IEEE80211_AMPDU_TX_START: + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + break; + default: + WARN_ON(1); + return -ENOTSUPP; + } + + return 0; +} + +static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + rtw_leave_lps(rtwdev, rtwvif); + + rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE); + rtw_flag_set(rtwdev, RTW_FLAG_SCANNING); +} + +static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + + rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING); + rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE); +} + +const struct ieee80211_ops rtw_ops = { + .tx = rtw_ops_tx, + .start = rtw_ops_start, + .stop = rtw_ops_stop, + .config = rtw_ops_config, + .add_interface = rtw_ops_add_interface, + .remove_interface = rtw_ops_remove_interface, + .configure_filter = rtw_ops_configure_filter, + .bss_info_changed = rtw_ops_bss_info_changed, + .sta_add = rtw_ops_sta_add, + .sta_remove = rtw_ops_sta_remove, + .set_key = rtw_ops_set_key, + .ampdu_action = rtw_ops_ampdu_action, + .sw_scan_start = rtw_ops_sw_scan_start, + .sw_scan_complete = rtw_ops_sw_scan_complete, +}; +EXPORT_SYMBOL(rtw_ops); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c new file mode 100644 index 0000000..a189c45 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -0,0 +1,1190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2018 Realtek Corporation. + */ + +#include "main.h" +#include "regd.h" +#include "fw.h" +#include "ps.h" +#include "sec.h" +#include "mac.h" +#include "phy.h" +#include "reg.h" +#include "efuse.h" +#include "debug.h" + +static struct ieee80211_channel rtw_channeltable_2g[] = { + {.center_freq = 2412, .hw_value = 1,}, + {.center_freq = 2417, .hw_value = 2,}, + {.center_freq = 2422, .hw_value = 3,}, + {.center_freq = 2427, .hw_value = 4,}, + {.center_freq = 2432, .hw_value = 5,}, + {.center_freq = 2437, .hw_value = 6,}, + {.center_freq = 2442, .hw_value = 7,}, + {.center_freq = 2447, .hw_value = 8,}, + {.center_freq = 2452, .hw_value = 9,}, + {.center_freq = 2457, .hw_value = 10,}, + {.center_freq = 2462, .hw_value = 11,}, + {.center_freq = 2467, .hw_value = 12,}, + {.center_freq = 2472, .hw_value = 13,}, + {.center_freq = 2484, .hw_value = 14,}, +}; + +static struct ieee80211_channel rtw_channeltable_5g[] = { + {.center_freq = 5180, .hw_value = 36,}, + {.center_freq = 5200, .hw_value = 40,}, + {.center_freq = 5220, .hw_value = 44,}, + {.center_freq = 5240, .hw_value = 48,}, + {.center_freq = 5260, .hw_value = 52,}, + {.center_freq = 5280, .hw_value = 56,}, + {.center_freq = 5300, .hw_value = 60,}, + {.center_freq = 5320, .hw_value = 64,}, + {.center_freq = 5500, .hw_value = 100,}, + {.center_freq = 5520, .hw_value = 104,}, + {.center_freq = 5540, .hw_value = 108,}, + {.center_freq = 5560, .hw_value = 112,}, + {.center_freq = 5580, .hw_value = 116,}, + {.center_freq = 5600, .hw_value = 120,}, + {.center_freq = 5620, .hw_value = 124,}, + {.center_freq = 5640, .hw_value = 128,}, + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, + {.center_freq = 5805, .hw_value = 161,}, + {.center_freq = 5825, .hw_value = 165, + .flags = IEEE80211_CHAN_NO_HT40MINUS}, +}; + +static struct ieee80211_rate rtw_ratetable[] = { + {.bitrate = 10, .hw_value = 0x00,}, + {.bitrate = 20, .hw_value = 0x01,}, + {.bitrate = 55, .hw_value = 0x02,}, + {.bitrate = 110, .hw_value = 0x03,}, + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static struct ieee80211_supported_band rtw_band_2ghz = { + .band = NL80211_BAND_2GHZ, + + .channels = rtw_channeltable_2g, + .n_channels = ARRAY_SIZE(rtw_channeltable_2g), + + .bitrates = rtw_ratetable, + .n_bitrates = ARRAY_SIZE(rtw_ratetable), + + .ht_cap = {0}, + .vht_cap = {0}, +}; + +static struct ieee80211_supported_band rtw_band_5ghz = { + .band = NL80211_BAND_5GHZ, + + .channels = rtw_channeltable_5g, + .n_channels = ARRAY_SIZE(rtw_channeltable_5g), + + /* 5G has no CCK rates */ + .bitrates = rtw_ratetable + 4, + .n_bitrates = ARRAY_SIZE(rtw_ratetable) - 4, + + .ht_cap = {0}, + .vht_cap = {0}, +}; + +struct rtw_watch_dog_iter_data { + struct rtw_vif *rtwvif; + bool active; + u8 assoc_cnt; +}; + +static void rtw_vif_watch_dog_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_watch_dog_iter_data *iter_data = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) { + if (vif->bss_conf.assoc) { + iter_data->assoc_cnt++; + iter_data->rtwvif = rtwvif; + } + if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD || + rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD) + iter_data->active = true; + } else { + /* only STATION mode can enter lps */ + iter_data->active = true; + } + + rtwvif->stats.tx_unicast = 0; + rtwvif->stats.rx_unicast = 0; + rtwvif->stats.tx_cnt = 0; + rtwvif->stats.rx_cnt = 0; +} + +/* process TX/RX statistics periodically for hardware, + * the information helps hardware to enhance performance + */ +static void rtw_watch_dog_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + watch_dog_work.work); + struct rtw_watch_dog_iter_data data = {}; + + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) + return; + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, + RTW_WATCH_DOG_DELAY_TIME); + + /* reset tx/rx statictics */ + rtwdev->stats.tx_unicast = 0; + rtwdev->stats.rx_unicast = 0; + rtwdev->stats.tx_cnt = 0; + rtwdev->stats.rx_cnt = 0; + + rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); + + /* fw supports only one station associated to enter lps, if there are + * more than two stations associated to the AP, then we can not enter + * lps, because fw does not handle the overlapped beacon interval + */ + if (data.rtwvif && !data.active && data.assoc_cnt == 1) + rtw_enter_lps(rtwdev, data.rtwvif); + + if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING)) + return; + + rtw_phy_dynamic_mechanism(rtwdev); + + rtwdev->watch_dog_cnt++; +} + +static void rtw_c2h_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, c2h_work); + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { + skb_unlink(skb, &rtwdev->c2h_queue); + rtw_fw_c2h_cmd_handle(rtwdev, skb); + dev_kfree_skb_any(skb); + } +} + +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *chan_params) +{ + struct ieee80211_channel *channel = chandef->chan; + enum nl80211_chan_width width = chandef->width; + u32 primary_freq, center_freq; + u8 center_chan; + u8 bandwidth = RTW_CHANNEL_WIDTH_20; + u8 primary_chan_idx = 0; + + center_chan = channel->hw_value; + primary_freq = channel->center_freq; + center_freq = chandef->center_freq1; + + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + bandwidth = RTW_CHANNEL_WIDTH_20; + primary_chan_idx = 0; + break; + case NL80211_CHAN_WIDTH_40: + bandwidth = RTW_CHANNEL_WIDTH_40; + if (primary_freq > center_freq) { + primary_chan_idx = 1; + center_chan -= 2; + } else { + primary_chan_idx = 2; + center_chan += 2; + } + break; + case NL80211_CHAN_WIDTH_80: + bandwidth = RTW_CHANNEL_WIDTH_80; + if (primary_freq > center_freq) { + if (primary_freq - center_freq == 10) { + primary_chan_idx = 1; + center_chan -= 2; + } else { + primary_chan_idx = 3; + center_chan -= 6; + } + } else { + if (center_freq - primary_freq == 10) { + primary_chan_idx = 2; + center_chan += 2; + } else { + primary_chan_idx = 4; + center_chan += 6; + } + } + break; + default: + center_chan = 0; + break; + } + + chan_params->center_chan = center_chan; + chan_params->bandwidth = bandwidth; + chan_params->primary_chan_idx = primary_chan_idx; +} + +void rtw_set_channel(struct rtw_dev *rtwdev) +{ + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_channel_params ch_param; + u8 center_chan, bandwidth, primary_chan_idx; + + rtw_get_channel_params(&hw->conf.chandef, &ch_param); + if (WARN(ch_param.center_chan == 0, "Invalid channel\n")) + return; + + center_chan = ch_param.center_chan; + bandwidth = ch_param.bandwidth; + primary_chan_idx = ch_param.primary_chan_idx; + + hal->current_band_width = bandwidth; + hal->current_channel = center_chan; + hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; + chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx); + + rtw_phy_set_tx_power_level(rtwdev, center_chan); +} + +static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr) +{ + int i; + + for (i = 0; i < ETH_ALEN; i++) + rtw_write8(rtwdev, start + i, addr[i]); +} + +void rtw_vif_port_config(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, + u32 config) +{ + u32 addr, mask; + + if (config & PORT_SET_MAC_ADDR) { + addr = rtwvif->conf->mac_addr.addr; + rtw_vif_write_addr(rtwdev, addr, rtwvif->mac_addr); + } + if (config & PORT_SET_BSSID) { + addr = rtwvif->conf->bssid.addr; + rtw_vif_write_addr(rtwdev, addr, rtwvif->bssid); + } + if (config & PORT_SET_NET_TYPE) { + addr = rtwvif->conf->net_type.addr; + mask = rtwvif->conf->net_type.mask; + rtw_write32_mask(rtwdev, addr, mask, rtwvif->net_type); + } + if (config & PORT_SET_AID) { + addr = rtwvif->conf->aid.addr; + mask = rtwvif->conf->aid.mask; + rtw_write32_mask(rtwdev, addr, mask, rtwvif->aid); + } +} + +static u8 hw_bw_cap_to_bitamp(u8 bw_cap) +{ + u8 bw = 0; + + switch (bw_cap) { + case EFUSE_HW_CAP_IGNORE: + case EFUSE_HW_CAP_SUPP_BW80: + bw |= BIT(RTW_CHANNEL_WIDTH_80); + /* fall through */ + case EFUSE_HW_CAP_SUPP_BW40: + bw |= BIT(RTW_CHANNEL_WIDTH_40); + /* fall through */ + default: + bw |= BIT(RTW_CHANNEL_WIDTH_20); + break; + } + + return bw; +} + +static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) +{ + struct rtw_hal *hal = &rtwdev->hal; + + if (hw_ant_num == EFUSE_HW_CAP_IGNORE || + hw_ant_num >= hal->rf_path_num) + return; + + switch (hw_ant_num) { + case 1: + hal->rf_type = RF_1T1R; + hal->rf_path_num = 1; + hal->antenna_tx = BB_PATH_A; + hal->antenna_rx = BB_PATH_A; + break; + default: + WARN(1, "invalid hw configuration from efuse\n"); + break; + } +} + +static u64 get_vht_ra_mask(struct ieee80211_sta *sta) +{ + u64 ra_mask = 0; + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); + u8 vht_mcs_cap; + int i, nss; + + /* 4SS, every two bits for MCS7/8/9 */ + for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 10) { + vht_mcs_cap = mcs_map & 0x3; + switch (vht_mcs_cap) { + case 2: /* MCS9 */ + ra_mask |= 0x3ff << nss; + break; + case 1: /* MCS8 */ + ra_mask |= 0x1ff << nss; + break; + case 0: /* MCS7 */ + ra_mask |= 0x0ff << nss; + break; + default: + break; + } + } + + return ra_mask; +} + +static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num) +{ + u8 rate_id = 0; + + switch (wireless_set) { + case WIRELESS_CCK: + rate_id = RTW_RATEID_B_20M; + break; + case WIRELESS_OFDM: + rate_id = RTW_RATEID_G; + break; + case WIRELESS_CCK | WIRELESS_OFDM: + rate_id = RTW_RATEID_BG; + break; + case WIRELESS_OFDM | WIRELESS_HT: + if (tx_num == 1) + rate_id = RTW_RATEID_GN_N1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_GN_N2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + break; + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_HT: + if (bw_mode == RTW_CHANNEL_WIDTH_40) { + if (tx_num == 1) + rate_id = RTW_RATEID_BGN_40M_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_BGN_40M_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR7_N_4SS; + } else { + if (tx_num == 1) + rate_id = RTW_RATEID_BGN_20M_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_BGN_20M_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR7_N_4SS; + } + break; + case WIRELESS_OFDM | WIRELESS_VHT: + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR1_AC_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR0_AC_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + break; + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_VHT: + if (bw_mode >= RTW_CHANNEL_WIDTH_80) { + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR1_AC_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR0_AC_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + } else { + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR2_AC_2G_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR3_AC_2G_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + } + break; + default: + break; + } + + return rate_id; +} + +#define RA_MASK_CCK_RATES 0x0000f +#define RA_MASK_OFDM_RATES 0x00ff0 +#define RA_MASK_HT_RATES_1SS (0xff000 << 0) +#define RA_MASK_HT_RATES_2SS (0xff000 << 8) +#define RA_MASK_HT_RATES_3SS (0xff000 << 16) +#define RA_MASK_HT_RATES (RA_MASK_HT_RATES_1SS | \ + RA_MASK_HT_RATES_2SS | \ + RA_MASK_HT_RATES_3SS) +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0) +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10) +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20) +#define RA_MASK_VHT_RATES (RA_MASK_VHT_RATES_1SS | \ + RA_MASK_VHT_RATES_2SS | \ + RA_MASK_VHT_RATES_3SS) +#define RA_MASK_CCK_IN_HT 0x00005 +#define RA_MASK_CCK_IN_VHT 0x00005 +#define RA_MASK_OFDM_IN_VHT 0x00010 +#define RA_MASK_OFDM_IN_HT_2G 0x00010 +#define RA_MASK_OFDM_IN_HT_5G 0x00030 + +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) +{ + struct ieee80211_sta *sta = si->sta; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_hal *hal = &rtwdev->hal; + u8 rssi_level; + u8 wireless_set; + u8 bw_mode; + u8 rate_id; + u8 rf_type = RF_1T1R; + u8 stbc_en = 0; + u8 ldpc_en = 0; + u8 tx_num = 1; + u64 ra_mask = 0; + bool is_vht_enable = false; + bool is_support_sgi = false; + + if (sta->vht_cap.vht_supported) { + is_vht_enable = true; + ra_mask |= get_vht_ra_mask(sta); + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + stbc_en = VHT_STBC_EN; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + ldpc_en = VHT_LDPC_EN; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + is_support_sgi = true; + } else if (sta->ht_cap.ht_supported) { + ra_mask |= (sta->ht_cap.mcs.rx_mask[NL80211_BAND_5GHZ] << 20) | + (sta->ht_cap.mcs.rx_mask[NL80211_BAND_2GHZ] << 12); + if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + stbc_en = HT_STBC_EN; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + ldpc_en = HT_LDPC_EN; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20 || + sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + is_support_sgi = true; + } + + if (hal->current_band_type == RTW_BAND_5G) { + ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; + if (sta->vht_cap.vht_supported) { + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_OFDM | WIRELESS_VHT; + } else if (sta->ht_cap.ht_supported) { + ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G; + wireless_set = WIRELESS_OFDM | WIRELESS_HT; + } else { + wireless_set = WIRELESS_OFDM; + } + } else if (hal->current_band_type == RTW_BAND_2G) { + ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; + if (sta->vht_cap.vht_supported) { + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT | + RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT | WIRELESS_VHT; + } else if (sta->ht_cap.ht_supported) { + ra_mask &= RA_MASK_HT_RATES | RA_MASK_CCK_IN_HT | + RA_MASK_OFDM_IN_HT_2G; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT; + } else if (sta->supp_rates[0] <= 0xf) { + wireless_set = WIRELESS_CCK; + } else { + wireless_set = WIRELESS_CCK | WIRELESS_OFDM; + } + } else { + rtw_err(rtwdev, "Unknown band type\n"); + wireless_set = 0; + } + + if (efuse->hw_cap.nss == 1) { + ra_mask &= RA_MASK_VHT_RATES_1SS; + ra_mask &= RA_MASK_HT_RATES_1SS; + } + + switch (sta->bandwidth) { + case IEEE80211_STA_RX_BW_80: + bw_mode = RTW_CHANNEL_WIDTH_80; + break; + case IEEE80211_STA_RX_BW_40: + bw_mode = RTW_CHANNEL_WIDTH_40; + break; + default: + bw_mode = RTW_CHANNEL_WIDTH_20; + break; + } + + if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { + tx_num = 2; + rf_type = RF_2T2R; + } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { + tx_num = 2; + rf_type = RF_2T2R; + } + + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); + + if (wireless_set != WIRELESS_CCK) { + rssi_level = si->rssi_level; + if (rssi_level == 0) + ra_mask &= 0xffffffffffffffffULL; + else if (rssi_level == 1) + ra_mask &= 0xfffffffffffffff0ULL; + else if (rssi_level == 2) + ra_mask &= 0xffffffffffffefe0ULL; + else if (rssi_level == 3) + ra_mask &= 0xffffffffffffcfc0ULL; + else if (rssi_level == 4) + ra_mask &= 0xffffffffffff8f80ULL; + else if (rssi_level >= 5) + ra_mask &= 0xffffffffffff0f00ULL; + } + + si->bw_mode = bw_mode; + si->stbc_en = stbc_en; + si->ldpc_en = ldpc_en; + si->rf_type = rf_type; + si->wireless_set = wireless_set; + si->sgi_enable = is_support_sgi; + si->vht_enable = is_vht_enable; + si->ra_mask = ra_mask; + si->rate_id = rate_id; + + rtw_fw_send_ra_info(rtwdev, si); +} + +static int rtw_power_on(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + ret = rtw_hci_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup hci\n"); + goto err; + } + + /* power on MAC before firmware downloaded */ + ret = rtw_mac_power_on(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to power on mac\n"); + goto err; + } + + wait_for_completion(&fw->completion); + if (!fw->firmware) { + ret = -EINVAL; + rtw_err(rtwdev, "failed to load firmware\n"); + goto err; + } + + ret = rtw_download_firmware(rtwdev, fw->firmware->data, + fw->firmware->size); + if (ret) { + rtw_err(rtwdev, "failed to download firmware\n"); + goto err_off; + } + + /* config mac after firmware downloaded */ + ret = rtw_mac_init(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to configure mac\n"); + goto err_off; + } + + chip->ops->phy_set_param(rtwdev); + + ret = rtw_hci_start(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to start hci\n"); + goto err_off; + } + + return 0; + +err_off: + rtw_mac_power_off(rtwdev); + +err: + return ret; +} + +int rtw_core_start(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_power_on(rtwdev); + if (ret) + return ret; + + rtwdev->h2c.last_box_num = 0; + + rtw_sec_enable_sec_engine(rtwdev); + + /* rcr reset after powered on */ + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, + RTW_WATCH_DOG_DELAY_TIME); + + rtw_flag_set(rtwdev, RTW_FLAG_RUNNING); + + return 0; +} + +static void rtw_power_off(struct rtw_dev *rtwdev) +{ + rtwdev->hci.ops->stop(rtwdev); + rtw_mac_power_off(rtwdev); +} + +void rtw_core_stop(struct rtw_dev *rtwdev) +{ + rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING); + rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING); + + cancel_delayed_work_sync(&rtwdev->watch_dog_work); + + rtw_power_off(rtwdev); +} + +static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_ht_cap *ht_cap) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + + ht_cap->ht_supported = true; + ht_cap->cap = 0; + ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_MAX_AMSDU | + IEEE80211_HT_CAP_LDPC_CODING | + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40)) + ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_DSSSCCK40 | + IEEE80211_HT_CAP_SGI_40; + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + if (efuse->hw_cap.nss > 1) { + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + ht_cap->mcs.rx_highest = cpu_to_le16(300); + } else { + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0x00; + ht_cap->mcs.rx_mask[4] = 0x01; + ht_cap->mcs.rx_highest = cpu_to_le16(150); + } +} + +static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_vht_cap *vht_cap) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + u16 mcs_map; + __le16 highest; + + if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && + efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) + return; + + vht_cap->vht_supported = true; + vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_RXLDPC | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_TXSTBC | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_HTC_VHT | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + 0; + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + if (efuse->hw_cap.nss > 1) { + highest = cpu_to_le16(780); + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; + } else { + highest = cpu_to_le16(390); + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; + } + + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = highest; + vht_cap->vht_mcs.tx_highest = highest; +} + +static void rtw_set_supported_band(struct ieee80211_hw *hw, + struct rtw_chip_info *chip) +{ + struct rtw_dev *rtwdev = hw->priv; + struct ieee80211_supported_band *sband; + + if (chip->band & RTW_BAND_2G) { + sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL); + if (!sband) + goto err_out; + if (chip->ht_supported) + rtw_init_ht_cap(rtwdev, &sband->ht_cap); + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; + } + + if (chip->band & RTW_BAND_5G) { + sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL); + if (!sband) + goto err_out; + if (chip->ht_supported) + rtw_init_ht_cap(rtwdev, &sband->ht_cap); + if (chip->vht_supported) + rtw_init_vht_cap(rtwdev, &sband->vht_cap); + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; + } + + return; + +err_out: + rtw_err(rtwdev, "failed to set supported band\n"); + kfree(sband); + return; +} + +static void rtw_unset_supported_band(struct ieee80211_hw *hw, + struct rtw_chip_info *chip) +{ + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); +} + +static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) +{ + struct rtw_dev *rtwdev = context; + struct rtw_fw_state *fw = &rtwdev->fw; + + if (!firmware) + rtw_err(rtwdev, "failed to request firmware\n"); + + fw->firmware = firmware; + complete_all(&fw->completion); +} + +static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + init_completion(&fw->completion); + + ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, + GFP_KERNEL, rtwdev, rtw_load_firmware_cb); + if (ret) { + rtw_err(rtwdev, "async firmware request failed\n"); + return ret; + } + + return 0; +} + +static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + u32 wl_bt_pwr_ctrl; + int ret = 0; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtwdev->hci.rpwm_addr = 0x03d9; + break; + default: + rtw_err(rtwdev, "unsupported hci type\n"); + return -EINVAL; + } + + wl_bt_pwr_ctrl = rtw_read32(rtwdev, REG_WL_BT_PWR_CTRL); + if (wl_bt_pwr_ctrl & BIT_BT_FUNC_EN) + rtwdev->efuse.btcoex = true; + hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1); + hal->fab_version = BIT_GET_VENDOR_ID(hal->chip_version) >> 2; + hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version); + hal->mp_chip = (hal->chip_version & BIT_RTL_ID) ? 0 : 1; + if (hal->chip_version & BIT_RF_TYPE_ID) { + hal->rf_type = RF_2T2R; + hal->rf_path_num = 2; + hal->antenna_tx = BB_PATH_AB; + hal->antenna_rx = BB_PATH_AB; + } else { + hal->rf_type = RF_1T1R; + hal->rf_path_num = 1; + hal->antenna_tx = BB_PATH_A; + hal->antenna_rx = BB_PATH_A; + } + + if (hal->fab_version == 2) + hal->fab_version = 1; + else if (hal->fab_version == 1) + hal->fab_version = 2; + + efuse->physical_size = chip->phy_efuse_size; + efuse->logical_size = chip->log_efuse_size; + efuse->protect_size = chip->ptct_efuse_size; + + /* default use ack */ + rtwdev->hal.rcr |= BIT_VHT_DACK; + + return ret; +} + +static int rtw_chip_efuse_enable(struct rtw_dev *rtwdev) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + ret = rtw_hci_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup hci\n"); + goto err; + } + + ret = rtw_mac_power_on(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to power on mac\n"); + goto err; + } + + rtw_write8(rtwdev, REG_C2HEVT, C2H_HW_FEATURE_DUMP); + ret = rtw_download_firmware(rtwdev, fw->firmware->data, + fw->firmware->size); + if (ret) { + rtw_err(rtwdev, "failed to download firmware\n"); + goto err_off; + } + + return 0; + +err_off: + rtw_mac_power_off(rtwdev); + +err: + return ret; +} + +static int rtw_dump_hw_feature(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct efuse_hw_cap *hw_cap; + u8 hw_feature[HW_FEATURE_LEN]; + u8 id; + int i; + + BUILD_BUG_ON(sizeof(*hw_cap) != HW_FEATURE_LEN); + + id = rtw_read8(rtwdev, REG_C2HEVT); + if (id != C2H_HW_FEATURE_REPORT) { + rtw_err(rtwdev, "failed to read hw feature report\n"); + return -EBUSY; + } + + for (i = 0; i < HW_FEATURE_LEN; i++) + hw_feature[i] = rtw_read8(rtwdev, REG_C2HEVT + 2 + i); + + rtw_write8(rtwdev, REG_C2HEVT, 0); + + hw_cap = (struct efuse_hw_cap *)hw_feature; + + efuse->hw_cap.bw = hw_bw_cap_to_bitamp(hw_cap->bw); + efuse->hw_cap.hci = hw_cap->hci; + efuse->hw_cap.nss = hw_cap->nss; + efuse->hw_cap.ptcl = hw_cap->ptcl; + efuse->hw_cap.ant_num = hw_cap->ant_num; + + rtw_hw_config_rf_ant_num(rtwdev, efuse->hw_cap.ant_num); + + if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE) + efuse->hw_cap.nss = rtwdev->hal.rf_path_num; + + rtw_dbg(rtwdev, "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n", + efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl, + efuse->hw_cap.ant_num, efuse->hw_cap.nss); + + return 0; +} + +static void rtw_chip_efuse_disable(struct rtw_dev *rtwdev) +{ + rtw_hci_stop(rtwdev); + rtw_mac_power_off(rtwdev); +} + +static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + int ret; + + mutex_lock(&rtwdev->mutex); + + /* power on mac to read efuse */ + ret = rtw_chip_efuse_enable(rtwdev); + if (ret) + goto out; + + ret = rtw_parse_efuse_map(rtwdev); + if (ret) + goto out; + + ret = rtw_dump_hw_feature(rtwdev); + if (ret) + goto out; + + ret = rtw_check_supported_rfe(rtwdev); + if (ret) + goto out; + + if (efuse->crystal_cap == 0xff) + efuse->crystal_cap = 0; + if (efuse->pa_type_2g == 0xff) + efuse->pa_type_2g = 0; + if (efuse->pa_type_5g == 0xff) + efuse->pa_type_5g = 0; + if (efuse->lna_type_2g == 0xff) + efuse->lna_type_2g = 0; + if (efuse->lna_type_5g == 0xff) + efuse->lna_type_5g = 0; + if (efuse->channel_plan == 0xff) + efuse->channel_plan = 0x7f; + if (efuse->bt_setting & BIT(0)) + efuse->share_ant = true; + if (efuse->regd == 0xff) + efuse->regd = 0; + + efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; + efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; + efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; + efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0; + + rtw_chip_efuse_disable(rtwdev); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); + + if (!rfe_def) + return -ENODEV; + + rtw_phy_setup_phy_cond(rtwdev, 0); + + rtw_hw_init_tx_power(hal); + if (rtwdev->chip->id != RTW_CHIP_TYPE_8822C) + rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); + rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); + rtw_phy_tx_power_by_rate_config(hal); + rtw_phy_tx_power_limit_config(hal); + + return 0; +} + +int rtw_chip_info_setup(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_chip_parameter_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip parameters\n"); + goto err_out; + } + + ret = rtw_chip_efuse_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip efuse info\n"); + goto err_out; + } + + ret = rtw_chip_board_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip board info\n"); + goto err_out; + } + + return 0; + +err_out: + return ret; +} +EXPORT_SYMBOL(rtw_chip_info_setup); + +int rtw_core_init(struct rtw_dev *rtwdev) +{ + int ret; + + INIT_LIST_HEAD(&rtwdev->rsvd_page_list); + + INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); + INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work); + INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); + skb_queue_head_init(&rtwdev->c2h_queue); + + spin_lock_init(&rtwdev->dm_lock); + spin_lock_init(&rtwdev->rf_lock); + spin_lock_init(&rtwdev->h2c.lock); + + mutex_init(&rtwdev->mutex); + mutex_init(&rtwdev->hal.tx_power_mutex); + + rtwdev->sec.total_cam_num = 32; + rtwdev->hal.current_channel = 1; + set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); + + mutex_lock(&rtwdev->mutex); + rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false); + mutex_unlock(&rtwdev->mutex); + + /* default rx filter setting */ + rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV | + BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | + BIT_AB | BIT_AM | BIT_APM; + + ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name); + if (ret) { + rtw_warn(rtwdev, "no firmware loaded\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(rtw_core_init); + +void rtw_core_deinit(struct rtw_dev *rtwdev) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + struct rtw_rsvd_page *rsvd_pkt, *tmp; + + if (fw->firmware) + release_firmware(fw->firmware); + + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { + list_del(&rsvd_pkt->list); + kfree(rsvd_pkt); + } + + mutex_destroy(&rtwdev->mutex); + mutex_destroy(&rtwdev->hal.tx_power_mutex); +} +EXPORT_SYMBOL(rtw_core_deinit); + +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) +{ + int max_tx_headroom = 0; + int ret; + + /* TODO: USB & SDIO may need extra room? */ + max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz; + + hw->extra_tx_headroom = max_tx_headroom; + hw->queues = IEEE80211_NUM_ACS; + hw->sta_data_size = sizeof(struct rtw_sta_info); + hw->vif_data_size = sizeof(struct rtw_vif); + + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, RX_INCLUDES_FCS); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | + WIPHY_FLAG_TDLS_EXTERNAL_SETUP; + + rtw_set_supported_band(hw, rtwdev->chip); + SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); + + rtw_regd_init(rtwdev, rtw_regd_notifier); + + ret = ieee80211_register_hw(hw); + if (ret) { + rtw_err(rtwdev, "failed to register hw\n"); + return ret; + } + + if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2)) + rtw_err(rtwdev, "regulatory_hint fail\n"); + + rtw_debugfs_init(rtwdev); + + return 0; +} +EXPORT_SYMBOL(rtw_register_hw); + +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + ieee80211_unregister_hw(hw); + rtw_unset_supported_band(hw, chip); +} +EXPORT_SYMBOL(rtw_unregister_hw); + +MODULE_AUTHOR("Realtek Corporation"); +MODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h new file mode 100644 index 0000000..b345fe0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -0,0 +1,1119 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2018 Realtek Corporation. + */ + +#ifndef __RTK_MAIN_H_ +#define __RTK_MAIN_H_ + +#include <net/mac80211.h> +#include <linux/vmalloc.h> +#include <linux/firmware.h> +#include <linux/average.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> + +#define RTW_MAX_MAC_ID_NUM 32 +#define RTW_MAX_SEC_CAM_NUM 32 + +#define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2) + +#define RFREG_MASK 0xfffff +#define INV_RF_DATA 0xffffffff +#define TX_PAGE_SIZE_SHIFT 7 + +#define RTW_CHANNEL_WIDTH_MAX 3 +#define RTW_RF_PATH_MAX 4 +#define HW_FEATURE_LEN 13 + +extern const struct ieee80211_ops rtw_ops; +extern struct rtw_chip_info rtw8822b_hw_spec; +extern struct rtw_chip_info rtw8822c_hw_spec; + +#define RTW_MAX_CHANNEL_NUM_2G 14 +#define RTW_MAX_CHANNEL_NUM_5G 49 + +struct rtw_dev; + +enum rtw_hci_type { + RTW_HCI_TYPE_PCIE, + RTW_HCI_TYPE_USB, + RTW_HCI_TYPE_SDIO, + + RTW_HCI_TYPE_UNDEFINE, +}; + +struct rtw_hci { + struct rtw_hci_ops *ops; + enum rtw_hci_type type; + + u32 rpwm_addr; + + u8 bulkout_num; +}; + +enum rtw_supported_band { + RTW_BAND_2G = 1 << 0, + RTW_BAND_5G = 1 << 1, + RTW_BAND_60G = 1 << 2, + + RTW_BAND_MAX, +}; + +enum rtw_bandwidth { + RTW_CHANNEL_WIDTH_20 = 0, + RTW_CHANNEL_WIDTH_40 = 1, + RTW_CHANNEL_WIDTH_80 = 2, + RTW_CHANNEL_WIDTH_160 = 3, + RTW_CHANNEL_WIDTH_80_80 = 4, + RTW_CHANNEL_WIDTH_5 = 5, + RTW_CHANNEL_WIDTH_10 = 6, +}; + +enum rtw_net_type { + RTW_NET_NO_LINK = 0, + RTW_NET_AD_HOC = 1, + RTW_NET_MGD_LINKED = 2, + RTW_NET_AP_MODE = 3, +}; + +enum rtw_rf_type { + RF_1T1R = 0, + RF_1T2R = 1, + RF_2T2R = 2, + RF_2T3R = 3, + RF_2T4R = 4, + RF_3T3R = 5, + RF_3T4R = 6, + RF_4T4R = 7, + RF_TYPE_MAX, +}; + +enum rtw_rf_path { + RF_PATH_A = 0, + RF_PATH_B = 1, + RF_PATH_C = 2, + RF_PATH_D = 3, +}; + +enum rtw_bb_path { + BB_PATH_A = BIT(0), + BB_PATH_B = BIT(1), + BB_PATH_C = BIT(2), + BB_PATH_D = BIT(3), + + BB_PATH_AB = (BB_PATH_A | BB_PATH_B), + BB_PATH_AC = (BB_PATH_A | BB_PATH_C), + BB_PATH_AD = (BB_PATH_A | BB_PATH_D), + BB_PATH_BC = (BB_PATH_B | BB_PATH_C), + BB_PATH_BD = (BB_PATH_B | BB_PATH_D), + BB_PATH_CD = (BB_PATH_C | BB_PATH_D), + + BB_PATH_ABC = (BB_PATH_A | BB_PATH_B | BB_PATH_C), + BB_PATH_ABD = (BB_PATH_A | BB_PATH_B | BB_PATH_D), + BB_PATH_ACD = (BB_PATH_A | BB_PATH_C | BB_PATH_D), + BB_PATH_BCD = (BB_PATH_B | BB_PATH_C | BB_PATH_D), + + BB_PATH_ABCD = (BB_PATH_A | BB_PATH_B | BB_PATH_C | BB_PATH_D), +}; + +enum rtw_rate_section { + RTW_RATE_SECTION_CCK = 0, + RTW_RATE_SECTION_OFDM, + RTW_RATE_SECTION_HT_1S, + RTW_RATE_SECTION_HT_2S, + RTW_RATE_SECTION_VHT_1S, + RTW_RATE_SECTION_VHT_2S, + + /* keep last */ + RTW_RATE_SECTION_MAX, +}; + +enum rtw_wireless_set { + WIRELESS_CCK = 0x00000001, + WIRELESS_OFDM = 0x00000002, + WIRELESS_HT = 0x00000004, + WIRELESS_VHT = 0x00000008, +}; + +#define HT_STBC_EN BIT(0) +#define VHT_STBC_EN BIT(1) +#define HT_LDPC_EN BIT(0) +#define VHT_LDPC_EN BIT(1) + +enum rtw_chip_type { + RTW_CHIP_TYPE_8822B, + RTW_CHIP_TYPE_8822C, +}; + +enum rtw_tx_queue_type { + /* the order of AC queues matters */ + RTW_TX_QUEUE_BK = 0x0, + RTW_TX_QUEUE_BE = 0x1, + RTW_TX_QUEUE_VI = 0x2, + RTW_TX_QUEUE_VO = 0x3, + + RTW_TX_QUEUE_BCN = 0x4, + RTW_TX_QUEUE_MGMT = 0x5, + RTW_TX_QUEUE_HI0 = 0x6, + RTW_TX_QUEUE_H2C = 0x7, + /* keep it last */ + RTK_MAX_TX_QUEUE_NUM +}; + +enum rtw_rx_queue_type { + RTW_RX_QUEUE_MPDU = 0x0, + RTW_RX_QUEUE_C2H = 0x1, + /* keep it last */ + RTK_MAX_RX_QUEUE_NUM +}; + +enum rtw_rate_index { + RTW_RATEID_BGN_40M_2SS = 0, + RTW_RATEID_BGN_40M_1SS = 1, + RTW_RATEID_BGN_20M_2SS = 2, + RTW_RATEID_BGN_20M_1SS = 3, + RTW_RATEID_GN_N2SS = 4, + RTW_RATEID_GN_N1SS = 5, + RTW_RATEID_BG = 6, + RTW_RATEID_G = 7, + RTW_RATEID_B_20M = 8, + RTW_RATEID_ARFR0_AC_2SS = 9, + RTW_RATEID_ARFR1_AC_1SS = 10, + RTW_RATEID_ARFR2_AC_2G_1SS = 11, + RTW_RATEID_ARFR3_AC_2G_2SS = 12, + RTW_RATEID_ARFR4_AC_3SS = 13, + RTW_RATEID_ARFR5_N_3SS = 14, + RTW_RATEID_ARFR7_N_4SS = 15, + RTW_RATEID_ARFR6_AC_4SS = 16 +}; + +enum rtw_trx_desc_rate { + DESC_RATE1M = 0x00, + DESC_RATE2M = 0x01, + DESC_RATE5_5M = 0x02, + DESC_RATE11M = 0x03, + + DESC_RATE6M = 0x04, + DESC_RATE9M = 0x05, + DESC_RATE12M = 0x06, + DESC_RATE18M = 0x07, + DESC_RATE24M = 0x08, + DESC_RATE36M = 0x09, + DESC_RATE48M = 0x0a, + DESC_RATE54M = 0x0b, + + DESC_RATEMCS0 = 0x0c, + DESC_RATEMCS1 = 0x0d, + DESC_RATEMCS2 = 0x0e, + DESC_RATEMCS3 = 0x0f, + DESC_RATEMCS4 = 0x10, + DESC_RATEMCS5 = 0x11, + DESC_RATEMCS6 = 0x12, + DESC_RATEMCS7 = 0x13, + DESC_RATEMCS8 = 0x14, + DESC_RATEMCS9 = 0x15, + DESC_RATEMCS10 = 0x16, + DESC_RATEMCS11 = 0x17, + DESC_RATEMCS12 = 0x18, + DESC_RATEMCS13 = 0x19, + DESC_RATEMCS14 = 0x1a, + DESC_RATEMCS15 = 0x1b, + DESC_RATEMCS16 = 0x1c, + DESC_RATEMCS17 = 0x1d, + DESC_RATEMCS18 = 0x1e, + DESC_RATEMCS19 = 0x1f, + DESC_RATEMCS20 = 0x20, + DESC_RATEMCS21 = 0x21, + DESC_RATEMCS22 = 0x22, + DESC_RATEMCS23 = 0x23, + DESC_RATEMCS24 = 0x24, + DESC_RATEMCS25 = 0x25, + DESC_RATEMCS26 = 0x26, + DESC_RATEMCS27 = 0x27, + DESC_RATEMCS28 = 0x28, + DESC_RATEMCS29 = 0x29, + DESC_RATEMCS30 = 0x2a, + DESC_RATEMCS31 = 0x2b, + + DESC_RATEVHT1SS_MCS0 = 0x2c, + DESC_RATEVHT1SS_MCS1 = 0x2d, + DESC_RATEVHT1SS_MCS2 = 0x2e, + DESC_RATEVHT1SS_MCS3 = 0x2f, + DESC_RATEVHT1SS_MCS4 = 0x30, + DESC_RATEVHT1SS_MCS5 = 0x31, + DESC_RATEVHT1SS_MCS6 = 0x32, + DESC_RATEVHT1SS_MCS7 = 0x33, + DESC_RATEVHT1SS_MCS8 = 0x34, + DESC_RATEVHT1SS_MCS9 = 0x35, + + DESC_RATEVHT2SS_MCS0 = 0x36, + DESC_RATEVHT2SS_MCS1 = 0x37, + DESC_RATEVHT2SS_MCS2 = 0x38, + DESC_RATEVHT2SS_MCS3 = 0x39, + DESC_RATEVHT2SS_MCS4 = 0x3a, + DESC_RATEVHT2SS_MCS5 = 0x3b, + DESC_RATEVHT2SS_MCS6 = 0x3c, + DESC_RATEVHT2SS_MCS7 = 0x3d, + DESC_RATEVHT2SS_MCS8 = 0x3e, + DESC_RATEVHT2SS_MCS9 = 0x3f, + + DESC_RATEVHT3SS_MCS0 = 0x40, + DESC_RATEVHT3SS_MCS1 = 0x41, + DESC_RATEVHT3SS_MCS2 = 0x42, + DESC_RATEVHT3SS_MCS3 = 0x43, + DESC_RATEVHT3SS_MCS4 = 0x44, + DESC_RATEVHT3SS_MCS5 = 0x45, + DESC_RATEVHT3SS_MCS6 = 0x46, + DESC_RATEVHT3SS_MCS7 = 0x47, + DESC_RATEVHT3SS_MCS8 = 0x48, + DESC_RATEVHT3SS_MCS9 = 0x49, + + DESC_RATEVHT4SS_MCS0 = 0x4a, + DESC_RATEVHT4SS_MCS1 = 0x4b, + DESC_RATEVHT4SS_MCS2 = 0x4c, + DESC_RATEVHT4SS_MCS3 = 0x4d, + DESC_RATEVHT4SS_MCS4 = 0x4e, + DESC_RATEVHT4SS_MCS5 = 0x4f, + DESC_RATEVHT4SS_MCS6 = 0x50, + DESC_RATEVHT4SS_MCS7 = 0x51, + DESC_RATEVHT4SS_MCS8 = 0x52, + DESC_RATEVHT4SS_MCS9 = 0x53, + + DESC_RATE_MAX, +}; + +enum rtw_regulatory_domains { + RTW_REGD_FCC = 0, + RTW_REGD_MKK = 1, + RTW_REGD_ETSI = 2, + RTW_REGD_WW = 3, + + RTW_REGD_MAX +}; + +enum rtw_flags { + RTW_FLAG_RUNNING, + RTW_FLAG_FW_RUNNING, + RTW_FLAG_SCANNING, + RTW_FLAG_INACTIVE_PS, + RTW_FLAG_LEISURE_PS, + RTW_FLAG_DIG_DISABLE, + + NUM_OF_RTW_FLAGS, +}; + +/* the power index is represented by differences, which cck-1s & ht40-1s are + * the base values, so for 1s's differences, there are only ht20 & ofdm + */ +struct rtw_2g_1s_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm:4; + s8 bw20:4; +#else + s8 bw20:4; + s8 ofdm:4; +#endif +} __packed; + +struct rtw_2g_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw20:4; + s8 bw40:4; + s8 cck:4; + s8 ofdm:4; +#else + s8 ofdm:4; + s8 cck:4; + s8 bw40:4; + s8 bw20:4; +#endif +} __packed; + +struct rtw_2g_txpwr_idx { + u8 cck_base[6]; + u8 bw40_base[5]; + struct rtw_2g_1s_pwr_idx_diff ht_1s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_2s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_3s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_4s_diff; +}; + +struct rtw_5g_ht_1s_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm:4; + s8 bw20:4; +#else + s8 bw20:4; + s8 ofdm:4; +#endif +} __packed; + +struct rtw_5g_ht_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw20:4; + s8 bw40:4; +#else + s8 bw40:4; + s8 bw20:4; +#endif +} __packed; + +struct rtw_5g_ofdm_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm_3s:4; + s8 ofdm_2s:4; + s8 ofdm_4s:4; + s8 res:4; +#else + s8 res:4; + s8 ofdm_4s:4; + s8 ofdm_2s:4; + s8 ofdm_3s:4; +#endif +} __packed; + +struct rtw_5g_vht_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw160:4; + s8 bw80:4; +#else + s8 bw80:4; + s8 bw160:4; +#endif +} __packed; + +struct rtw_5g_txpwr_idx { + u8 bw40_base[14]; + struct rtw_5g_ht_1s_pwr_idx_diff ht_1s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_2s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_3s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_4s_diff; + struct rtw_5g_ofdm_ns_pwr_idx_diff ofdm_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_1s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_2s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_3s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_4s_diff; +}; + +struct rtw_txpwr_idx { + struct rtw_2g_txpwr_idx pwr_idx_2g; + struct rtw_5g_txpwr_idx pwr_idx_5g; +}; + +struct rtw_timer_list { + struct timer_list timer; + void (*function)(void *data); + void *args; +}; + +struct rtw_channel_params { + u8 center_chan; + u8 bandwidth; + u8 primary_chan_idx; +}; + +struct rtw_hw_reg { + u32 addr; + u32 mask; +}; + +struct rtw_backup_info { + u8 len; + u32 reg; + u32 val; +}; + +enum rtw_vif_port_set { + PORT_SET_MAC_ADDR = BIT(0), + PORT_SET_BSSID = BIT(1), + PORT_SET_NET_TYPE = BIT(2), + PORT_SET_AID = BIT(3), +}; + +struct rtw_vif_port { + struct rtw_hw_reg mac_addr; + struct rtw_hw_reg bssid; + struct rtw_hw_reg net_type; + struct rtw_hw_reg aid; +}; + +struct rtw_tx_pkt_info { + u32 tx_pkt_size; + u8 offset; + u8 pkt_offset; + u8 mac_id; + u8 rate_id; + u8 rate; + u8 qsel; + u8 bw; + u8 sec_type; + bool ampdu_en; + u8 ampdu_factor; + u8 ampdu_density; + u16 seq; + bool stbc; + bool ldpc; + bool dis_rate_fallback; + bool bmc; + bool use_rate; + bool ls; + bool fs; + bool short_gi; +}; + +struct rtw_rx_pkt_stat { + bool phy_status; + bool icv_err; + bool crc_err; + bool decrypted; + bool is_c2h; + + s32 signal_power; + u16 pkt_len; + u8 bw; + u8 drv_info_sz; + u8 shift; + u8 rate; + u8 mac_id; + u8 cam_id; + u8 ppdu_cnt; + u32 tsf_low; + s8 rx_power[RTW_RF_PATH_MAX]; + u8 rssi; + u8 rxsc; + struct rtw_sta_info *si; + struct ieee80211_vif *vif; +}; + +struct rtw_traffic_stats { + /* units in bytes */ + u64 tx_unicast; + u64 rx_unicast; + + /* count for packets */ + u64 tx_cnt; + u64 rx_cnt; + + /* units in Mbps */ + u32 tx_throughput; + u32 rx_throughput; +}; + +enum rtw_lps_mode { + RTW_MODE_ACTIVE = 0, + RTW_MODE_LPS = 1, + RTW_MODE_WMM_PS = 2, +}; + +enum rtw_pwr_state { + RTW_RF_OFF = 0x0, + RTW_RF_ON = 0x4, + RTW_ALL_ON = 0xc, +}; + +struct rtw_lps_conf { + /* the interface to enter lps */ + struct rtw_vif *rtwvif; + enum rtw_lps_mode mode; + enum rtw_pwr_state state; + u8 awake_interval; + u8 rlbm; + u8 smart_ps; + u8 port_id; +}; + +enum rtw_hw_key_type { + RTW_CAM_NONE = 0, + RTW_CAM_WEP40 = 1, + RTW_CAM_TKIP = 2, + RTW_CAM_AES = 4, + RTW_CAM_WEP104 = 5, +}; + +struct rtw_cam_entry { + bool valid; + bool group; + u8 addr[ETH_ALEN]; + u8 hw_key_type; + struct ieee80211_key_conf *key; +}; + +struct rtw_sec_desc { + /* search strategy */ + bool default_key_search; + + u32 total_cam_num; + struct rtw_cam_entry cam_table[RTW_MAX_SEC_CAM_NUM]; + DECLARE_BITMAP(cam_map, RTW_MAX_SEC_CAM_NUM); +}; + +#define RTW_BC_MC_MACID 1 +DECLARE_EWMA(rssi, 10, 16); + +struct rtw_sta_info { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + + struct ewma_rssi avg_rssi; + u8 rssi_level; + + u8 mac_id; + u8 rate_id; + enum rtw_bandwidth bw_mode; + enum rtw_rf_type rf_type; + enum rtw_wireless_set wireless_set; + u8 stbc_en:2; + u8 ldpc_en:2; + bool sgi_enable; + bool vht_enable; + bool updated; + u8 init_ra_lv; + u64 ra_mask; +}; + +struct rtw_vif { + struct ieee80211_vif *vif; + enum rtw_net_type net_type; + u16 aid; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 port; + const struct rtw_vif_port *conf; + + struct rtw_traffic_stats stats; + bool in_lps; +}; + +struct rtw_regulatory { + char alpha2[2]; + u8 chplan; + u8 txpwr_regd; +}; + +struct rtw_chip_ops { + int (*mac_init)(struct rtw_dev *rtwdev); + int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); + void (*phy_set_param)(struct rtw_dev *rtwdev); + void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, + u8 bandwidth, u8 primary_chan_idx); + void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status); + u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask); + bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data); + void (*set_tx_power_index)(struct rtw_dev *rtwdev, u8 power_index, + u8 rf_path, u8 rate); + int (*rsvd_page_dump)(struct rtw_dev *rtwdev, u8 *buf, u32 offset, + u32 size); + void (*set_antenna)(struct rtw_dev *rtwdev, u8 antenna_tx, + u8 antenna_rx); + void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable); + void (*false_alarm_statistics)(struct rtw_dev *rtwdev); + void (*do_iqk)(struct rtw_dev *rtwdev); +}; + +#define RTW_PWR_POLLING_CNT 20000 + +#define RTW_PWR_CMD_READ 0x00 +#define RTW_PWR_CMD_WRITE 0x01 +#define RTW_PWR_CMD_POLLING 0x02 +#define RTW_PWR_CMD_DELAY 0x03 +#define RTW_PWR_CMD_END 0x04 + +/* define the base address of each block */ +#define RTW_PWR_ADDR_MAC 0x00 +#define RTW_PWR_ADDR_USB 0x01 +#define RTW_PWR_ADDR_PCIE 0x02 +#define RTW_PWR_ADDR_SDIO 0x03 + +#define RTW_PWR_INTF_SDIO_MSK BIT(0) +#define RTW_PWR_INTF_USB_MSK BIT(1) +#define RTW_PWR_INTF_PCI_MSK BIT(2) +#define RTW_PWR_INTF_ALL_MSK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) + +#define RTW_PWR_CUT_A_MSK BIT(1) +#define RTW_PWR_CUT_B_MSK BIT(2) +#define RTW_PWR_CUT_C_MSK BIT(3) +#define RTW_PWR_CUT_D_MSK BIT(4) +#define RTW_PWR_CUT_E_MSK BIT(5) +#define RTW_PWR_CUT_F_MSK BIT(6) +#define RTW_PWR_CUT_G_MSK BIT(7) +#define RTW_PWR_CUT_ALL_MSK 0xFF + +enum rtw_pwr_seq_cmd_delay_unit { + RTW_PWR_DELAY_US, + RTW_PWR_DELAY_MS, +}; + +struct rtw_pwr_seq_cmd { + u16 offset; + u8 cut_mask; + u8 intf_mask; + u8 base:4; + u8 cmd:4; + u8 mask; + u8 value; +}; + +enum rtw_chip_ver { + RTW_CHIP_VER_CUT_A = 0x00, + RTW_CHIP_VER_CUT_B = 0x01, + RTW_CHIP_VER_CUT_C = 0x02, + RTW_CHIP_VER_CUT_D = 0x03, + RTW_CHIP_VER_CUT_E = 0x04, + RTW_CHIP_VER_CUT_F = 0x05, + RTW_CHIP_VER_CUT_G = 0x06, +}; + +#define RTW_INTF_PHY_PLATFORM_ALL 0 + +enum rtw_intf_phy_cut { + RTW_INTF_PHY_CUT_A = BIT(0), + RTW_INTF_PHY_CUT_B = BIT(1), + RTW_INTF_PHY_CUT_C = BIT(2), + RTW_INTF_PHY_CUT_D = BIT(3), + RTW_INTF_PHY_CUT_E = BIT(4), + RTW_INTF_PHY_CUT_F = BIT(5), + RTW_INTF_PHY_CUT_G = BIT(6), + RTW_INTF_PHY_CUT_ALL = 0xFFFF, +}; + +enum rtw_ip_sel { + RTW_IP_SEL_PHY = 0, + RTW_IP_SEL_MAC = 1, + RTW_IP_SEL_DBI = 2, + + RTW_IP_SEL_UNDEF = 0xFFFF +}; + +enum rtw_pq_map_id { + RTW_PQ_MAP_VO = 0x0, + RTW_PQ_MAP_VI = 0x1, + RTW_PQ_MAP_BE = 0x2, + RTW_PQ_MAP_BK = 0x3, + RTW_PQ_MAP_MG = 0x4, + RTW_PQ_MAP_HI = 0x5, + RTW_PQ_MAP_NUM = 0x6, + + RTW_PQ_MAP_UNDEF, +}; + +enum rtw_dma_mapping { + RTW_DMA_MAPPING_EXTRA = 0, + RTW_DMA_MAPPING_LOW = 1, + RTW_DMA_MAPPING_NORMAL = 2, + RTW_DMA_MAPPING_HIGH = 3, + + RTW_DMA_MAPPING_UNDEF, +}; + +struct rtw_rqpn { + enum rtw_dma_mapping dma_map_vo; + enum rtw_dma_mapping dma_map_vi; + enum rtw_dma_mapping dma_map_be; + enum rtw_dma_mapping dma_map_bk; + enum rtw_dma_mapping dma_map_mg; + enum rtw_dma_mapping dma_map_hi; +}; + +struct rtw_page_table { + u16 hq_num; + u16 nq_num; + u16 lq_num; + u16 exq_num; + u16 gapq_num; +}; + +struct rtw_intf_phy_para { + u16 offset; + u16 value; + u16 ip_sel; + u16 cut_mask; + u16 platform; +}; + +struct rtw_intf_phy_para_table { + struct rtw_intf_phy_para *usb2_para; + struct rtw_intf_phy_para *usb3_para; + struct rtw_intf_phy_para *gen1_para; + struct rtw_intf_phy_para *gen2_para; + u8 n_usb2_para; + u8 n_usb3_para; + u8 n_gen1_para; + u8 n_gen2_para; +}; + +struct rtw_table { + const void *data; + const u32 size; + void (*parse)(struct rtw_dev *rtwdev, const struct rtw_table *tbl); + void (*do_cfg)(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); + enum rtw_rf_path rf_path; +}; + +static inline void rtw_load_table(struct rtw_dev *rtwdev, + const struct rtw_table *tbl) +{ + (*tbl->parse)(rtwdev, tbl); +} + +enum rtw_rfe_fem { + RTW_RFE_IFEM, + RTW_RFE_EFEM, + RTW_RFE_IFEM2G_EFEM5G, + RTW_RFE_NUM, +}; + +struct rtw_rfe_def { + const struct rtw_table *phy_pg_tbl; + const struct rtw_table *txpwr_lmt_tbl; +}; + +#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \ + .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ + } + +/* hardware configuration for each IC */ +struct rtw_chip_info { + struct rtw_chip_ops *ops; + u8 id; + + const char *fw_name; + u8 tx_pkt_desc_sz; + u8 tx_buf_desc_sz; + u8 rx_pkt_desc_sz; + u8 rx_buf_desc_sz; + u32 phy_efuse_size; + u32 log_efuse_size; + u32 ptct_efuse_size; + u32 txff_size; + u32 rxff_size; + u8 band; + u8 page_size; + u8 csi_buf_pg_num; + u8 dig_max; + u8 dig_min; + + bool ht_supported; + bool vht_supported; + + /* init values */ + u8 sys_func_en; + struct rtw_pwr_seq_cmd **pwr_on_seq; + struct rtw_pwr_seq_cmd **pwr_off_seq; + struct rtw_rqpn *rqpn_table; + struct rtw_page_table *page_table; + struct rtw_intf_phy_para_table *intf_table; + + struct rtw_hw_reg *dig; + u32 rf_base_addr[2]; + u32 rf_sipi_addr[2]; + + const struct rtw_table *mac_tbl; + const struct rtw_table *agc_tbl; + const struct rtw_table *bb_tbl; + const struct rtw_table *rf_tbl[RTW_RF_PATH_MAX]; + + const struct rtw_rfe_def *rfe_defs; + u32 rfe_defs_size; +}; + +struct rtw_dm_info { + u32 cck_fa_cnt; + u32 ofdm_fa_cnt; + u32 total_fa_cnt; + u8 min_rssi; + u8 pre_min_rssi; + u16 fa_history[4]; + u8 igi_history[4]; + u8 igi_bitmap; + bool damping; + u8 damping_cnt; + u8 damping_rssi; + + u8 cck_gi_u_bnd; + u8 cck_gi_l_bnd; +}; + +struct rtw_efuse { + u32 size; + u32 physical_size; + u32 logical_size; + u32 protect_size; + + u8 addr[ETH_ALEN]; + u8 channel_plan; + u8 country_code[2]; + u8 rfe_option; + u8 thermal_meter; + u8 crystal_cap; + u8 ant_div_cfg; + u8 ant_div_type; + u8 regd; + + u8 lna_type_2g; + u8 lna_type_5g; + u8 glna_type; + u8 alna_type; + bool ext_lna_2g; + bool ext_lna_5g; + u8 pa_type_2g; + u8 pa_type_5g; + u8 gpa_type; + u8 apa_type; + bool ext_pa_2g; + bool ext_pa_5g; + u8 x3d7; + u8 x3d8; + + bool btcoex; + /* bt share antenna with wifi */ + bool share_ant; + u8 bt_setting; + + struct { + u8 hci; + u8 bw; + u8 ptcl; + u8 nss; + u8 ant_num; + } hw_cap; + + struct rtw_txpwr_idx txpwr_idx_table[4]; +}; + +struct rtw_phy_cond { +#ifdef __LITTLE_ENDIAN + u32 rfe:8; + u32 intf:4; + u32 pkg:4; + u32 plat:4; + u32 intf_rsvd:4; + u32 cut:4; + u32 branch:2; + u32 neg:1; + u32 pos:1; +#else + u32 pos:1; + u32 neg:1; + u32 branch:2; + u32 cut:4; + u32 intf_rsvd:4; + u32 plat:4; + u32 pkg:4; + u32 intf:4; + u32 rfe:8; +#endif + /* for intf:4 */ + #define INTF_PCIE BIT(0) + #define INTF_USB BIT(1) + #define INTF_SDIO BIT(2) + /* for branch:2 */ + #define BRANCH_IF 0 + #define BRANCH_ELIF 1 + #define BRANCH_ELSE 2 + #define BRANCH_ENDIF 3 +}; + +struct rtw_fifo_conf { + /* tx fifo information */ + u16 rsvd_boundary; + u16 rsvd_pg_num; + u16 rsvd_drv_pg_num; + u16 txff_pg_num; + u16 acq_pg_num; + u16 rsvd_drv_addr; + u16 rsvd_h2c_info_addr; + u16 rsvd_h2c_sta_info_addr; + u16 rsvd_h2cq_addr; + u16 rsvd_cpu_instr_addr; + u16 rsvd_fw_txbuf_addr; + u16 rsvd_csibuf_addr; + enum rtw_dma_mapping pq_map[RTW_PQ_MAP_NUM]; +}; + +struct rtw_fw_state { + const struct firmware *firmware; + struct completion completion; + u16 version; + u8 sub_version; + u8 sub_index; + u16 h2c_version; +}; + +struct rtw_hal { + u32 rcr; + + u32 chip_version; + u8 fab_version; + u8 cut_version; + u8 mp_chip; + u8 oem_id; + struct rtw_phy_cond phy_cond; + + u8 ps_mode; + u8 current_channel; + u8 current_band_width; + u8 current_band_type; + u8 sec_ch_offset; + u8 rf_type; + u8 rf_path_num; + u8 antenna_tx; + u8 antenna_rx; + + /* protect tx power section */ + struct mutex tx_power_mutex; + s8 tx_pwr_by_rate_offset_2g[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; + s8 tx_pwr_by_rate_offset_5g[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; + s8 tx_pwr_by_rate_base_2g[RTW_RF_PATH_MAX] + [RTW_RATE_SECTION_MAX]; + s8 tx_pwr_by_rate_base_5g[RTW_RF_PATH_MAX] + [RTW_RATE_SECTION_MAX]; + s8 tx_pwr_limit_2g[RTW_REGD_MAX] + [RTW_CHANNEL_WIDTH_MAX] + [RTW_RATE_SECTION_MAX] + [RTW_MAX_CHANNEL_NUM_2G]; + s8 tx_pwr_limit_5g[RTW_REGD_MAX] + [RTW_CHANNEL_WIDTH_MAX] + [RTW_RATE_SECTION_MAX] + [RTW_MAX_CHANNEL_NUM_5G]; +}; + +struct rtw_dev { + struct ieee80211_hw *hw; + struct device *dev; + + struct rtw_hci hci; + + struct rtw_chip_info *chip; + struct rtw_hal hal; + struct rtw_fifo_conf fifo; + struct rtw_fw_state fw; + struct rtw_efuse efuse; + struct rtw_sec_desc sec; + struct rtw_traffic_stats stats; + struct rtw_regulatory regd; + + struct rtw_dm_info dm_info; + + /* ensures exclusive access from mac80211 callbacks */ + struct mutex mutex; + + /* lock for dm to use */ + spinlock_t dm_lock; + + /* read/write rf register */ + spinlock_t rf_lock; + + /* watch dog every 2 sec */ + struct delayed_work watch_dog_work; + u32 watch_dog_cnt; + + struct list_head rsvd_page_list; + + /* c2h cmd queue & handler work */ + struct sk_buff_head c2h_queue; + struct work_struct c2h_work; + + struct { + /* incicate the mail box to use with fw */ + u8 last_box_num; + /* protect to send h2c to fw */ + spinlock_t lock; + u32 seq; + } h2c; + + /* lps power state & handler work */ + struct rtw_lps_conf lps_conf; + struct delayed_work lps_work; + + struct dentry *debugfs; + + u8 sta_cnt; + + DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM); + DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS); + + u8 mp_mode; + + /* hci related data, must be last */ + u8 priv[0] __aligned(sizeof(void *)); +}; + +#include "hci.h" + +static inline bool rtw_flag_check(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + return test_bit(flag, rtwdev->flags); +} + +static inline void rtw_flag_clear(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + clear_bit(flag, rtwdev->flags); +} + +static inline void rtw_flag_set(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + set_bit(flag, rtwdev->flags); +} + +static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) +{ + __le16 fc = hdr->frame_control; + u8 *bssid; + + if (ieee80211_has_tods(fc)) + bssid = hdr->addr1; + else if (ieee80211_has_fromds(fc)) + bssid = hdr->addr2; + else + bssid = hdr->addr3; + + return bssid; +} + +static inline bool check_hw_ready(struct rtw_dev *rtwdev, + u32 addr, u32 mask, u32 target) +{ + u32 cnt; + + for (cnt = 0; cnt < 1000; cnt++) { + if (rtw_read32_mask(rtwdev, addr, mask) == target) + return true; + + udelay(10); + } + + return false; +} + +#define rtw_iterate_vifs(rtwdev, iterator, data) \ + ieee80211_iterate_active_interfaces(rtwdev->hw, \ + IEEE80211_IFACE_ITER_NORMAL, iterator, data) +#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \ + ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \ + IEEE80211_IFACE_ITER_NORMAL, iterator, data) +#define rtw_iterate_stas_atomic(rtwdev, iterator, data) \ + ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data) + +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *ch_param); +void rtw_set_channel(struct rtw_dev *rtwdev); +void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, + u32 config); +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); +int rtw_core_start(struct rtw_dev *rtwdev); +void rtw_core_stop(struct rtw_dev *rtwdev); +int rtw_chip_info_setup(struct rtw_dev *rtwdev); +int rtw_core_init(struct rtw_dev *rtwdev); +void rtw_core_deinit(struct rtw_dev *rtwdev); +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h new file mode 100644 index 0000000..6e81829 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2018 Realtek Corporation. + */ + +#ifndef __RTW_REG_DEF_H__ +#define __RTW_REG_DEF_H__ + +#define REG_SYS_FUNC_EN 0x0002 +#define BIT_FEN_CPUEN BIT(2) +#define BIT_FEN_BB_GLB_RST BIT(1) +#define BIT_FEN_BB_RSTB BIT(0) +#define REG_SYS_PW_CTRL 0x0004 +#define REG_SYS_CLK_CTRL 0x0008 +#define BIT_CPU_CLK_EN BIT(14) + +#define REG_RSV_CTRL 0x001C +#define BIT_WLMCU_IOIF BIT(0) +#define REG_RF_CTRL 0x001F +#define BIT_RF_SDM_RSTB BIT(2) +#define BIT_RF_RSTB BIT(1) +#define BIT_RF_EN BIT(0) + +#define REG_AFE_CTRL1 0x0024 +#define BIT_MAC_CLK_SEL (BIT(20) | BIT(21)) +#define REG_EFUSE_CTRL 0x0030 +#define BIT_EF_FLAG BIT(31) +#define BIT_SHIFT_EF_ADDR 8 +#define BIT_MASK_EF_ADDR 0x3ff +#define BIT_MASK_EF_DATA 0xff +#define BITS_EF_ADDR (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR) + +#define REG_LDO_EFUSE_CTRL 0x0034 +#define BIT_MASK_EFUSE_BANK_SEL (BIT(8) | BIT(9)) + +#define REG_GPIO_MUXCFG 0x0040 +#define BIT_FSPI_EN BIT(19) +#define BIT_WLRFE_4_5_EN BIT(2) + +#define REG_LED_CFG 0x004C +#define BIT_LNAON_SEL_EN BIT(26) +#define BIT_PAPE_SEL_EN BIT(25) +#define REG_PAD_CTRL1 0x0064 +#define BIT_PAPE_WLBT_SEL BIT(29) +#define BIT_LNAON_WLBT_SEL BIT(28) +#define REG_WL_BT_PWR_CTRL 0x0068 +#define BIT_BT_FUNC_EN BIT(18) +#define BIT_BT_DIG_CLK_EN BIT(8) +#define REG_HCI_OPT_CTRL 0x0074 + +#define REG_MCUFW_CTRL 0x0080 +#define BIT_ANA_PORT_EN BIT(22) +#define BIT_MAC_PORT_EN BIT(21) +#define BIT_BOOT_FSPI_EN BIT(20) +#define BIT_FW_INIT_RDY BIT(15) +#define BIT_FW_DW_RDY BIT(14) +#define BIT_RPWM_TOGGLE BIT(7) +#define BIT_DMEM_CHKSUM_OK BIT(6) +#define BIT_DMEM_DW_OK BIT(5) +#define BIT_IMEM_CHKSUM_OK BIT(4) +#define BIT_IMEM_DW_OK BIT(3) +#define BIT_IMEM_BOOT_LOAD_CHECKSUM_OK BIT(2) +#define BIT_MCUFWDL_EN BIT(0) +#define BIT_CHECK_SUM_OK (BIT(4) | BIT(6)) +#define FW_READY (BIT_FW_INIT_RDY | BIT_FW_DW_RDY | \ + BIT_IMEM_DW_OK | BIT_DMEM_DW_OK | \ + BIT_CHECK_SUM_OK) +#define FW_READY_MASK 0xffff + +#define REG_SYS_CFG1 0x00F0 +#define BIT_RTL_ID BIT(23) +#define BIT_RF_TYPE_ID BIT(27) +#define BIT_SHIFT_VENDOR_ID 16 +#define BIT_MASK_VENDOR_ID 0xf +#define BIT_VENDOR_ID(x) (((x) & BIT_MASK_VENDOR_ID) << BIT_SHIFT_VENDOR_ID) +#define BITS_VENDOR_ID (BIT_MASK_VENDOR_ID << BIT_SHIFT_VENDOR_ID) +#define BIT_CLEAR_VENDOR_ID(x) ((x) & (~BITS_VENDOR_ID)) +#define BIT_GET_VENDOR_ID(x) (((x) >> BIT_SHIFT_VENDOR_ID) & BIT_MASK_VENDOR_ID) +#define BIT_SHIFT_CHIP_VER 12 +#define BIT_MASK_CHIP_VER 0xf +#define BIT_CHIP_VER(x) (((x) & BIT_MASK_CHIP_VER) << BIT_SHIFT_CHIP_VER) +#define BITS_CHIP_VER (BIT_MASK_CHIP_VER << BIT_SHIFT_CHIP_VER) +#define BIT_CLEAR_CHIP_VER(x) ((x) & (~BITS_CHIP_VER)) +#define BIT_GET_CHIP_VER(x) (((x) >> BIT_SHIFT_CHIP_VER) & BIT_MASK_CHIP_VER) +#define REG_SYS_STATUS1 0x00F4 +#define REG_SYS_STATUS2 0x00F8 +#define REG_SYS_CFG2 0x00FC +#define REG_WLRF1 0x00EC +#define BIT_WLRF1_BBRF_EN (BIT(24) | BIT(25) | BIT(26)) +#define REG_CR 0x0100 +#define BIT_32K_CAL_TMR_EN BIT(10) +#define BIT_MAC_SEC_EN BIT(9) +#define BIT_ENSWBCN BIT(8) +#define BIT_MACRXEN BIT(7) +#define BIT_MACTXEN BIT(6) +#define BIT_SCHEDULE_EN BIT(5) +#define BIT_PROTOCOL_EN BIT(4) +#define BIT_RXDMA_EN BIT(3) +#define BIT_TXDMA_EN BIT(2) +#define BIT_HCI_RXDMA_EN BIT(1) +#define BIT_HCI_TXDMA_EN BIT(0) +#define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \ + BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \ + BIT_MACTXEN | BIT_MACRXEN) +#define BIT_SHIFT_TXDMA_VOQ_MAP 4 +#define BIT_MASK_TXDMA_VOQ_MAP 0x3 +#define BIT_TXDMA_VOQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_VOQ_MAP) << BIT_SHIFT_TXDMA_VOQ_MAP) +#define BIT_SHIFT_TXDMA_VIQ_MAP 6 +#define BIT_MASK_TXDMA_VIQ_MAP 0x3 +#define BIT_TXDMA_VIQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) +#define REG_TXDMA_PQ_MAP 0x010C +#define BIT_SHIFT_TXDMA_BEQ_MAP 8 +#define BIT_MASK_TXDMA_BEQ_MAP 0x3 +#define BIT_TXDMA_BEQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_BEQ_MAP) << BIT_SHIFT_TXDMA_BEQ_MAP) +#define BIT_SHIFT_TXDMA_BKQ_MAP 10 +#define BIT_MASK_TXDMA_BKQ_MAP 0x3 +#define BIT_TXDMA_BKQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_BKQ_MAP) << BIT_SHIFT_TXDMA_BKQ_MAP) +#define BIT_SHIFT_TXDMA_MGQ_MAP 12 +#define BIT_MASK_TXDMA_MGQ_MAP 0x3 +#define BIT_TXDMA_MGQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_MGQ_MAP) << BIT_SHIFT_TXDMA_MGQ_MAP) +#define BIT_SHIFT_TXDMA_HIQ_MAP 14 +#define BIT_MASK_TXDMA_HIQ_MAP 0x3 +#define BIT_TXDMA_HIQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_HIQ_MAP) << BIT_SHIFT_TXDMA_HIQ_MAP) +#define BIT_SHIFT_TXSC_40M 4 +#define BIT_MASK_TXSC_40M 0xf +#define BIT_TXSC_40M(x) \ + (((x) & BIT_MASK_TXSC_40M) << BIT_SHIFT_TXSC_40M) +#define BIT_SHIFT_TXSC_20M 0 +#define BIT_MASK_TXSC_20M 0xf +#define BIT_TXSC_20M(x) \ + (((x) & BIT_MASK_TXSC_20M) << BIT_SHIFT_TXSC_20M) +#define BIT_SHIFT_MAC_CLK_SEL 20 +#define MAC_CLK_HW_DEF_80M 0 +#define MAC_CLK_HW_DEF_40M 1 +#define MAC_CLK_HW_DEF_20M 2 +#define MAC_CLK_SPEED 80 + +#define REG_CR 0x0100 +#define REG_TRXFF_BNDY 0x0114 +#define REG_RXFF_BNDY 0x011C +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_C2HEVT 0x01A0 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX0 0x01D0 +#define REG_HMEBOX1 0x01D4 +#define REG_HMEBOX2 0x01D8 +#define REG_HMEBOX3 0x01DC +#define REG_HMEBOX0_EX 0x01F0 +#define REG_HMEBOX1_EX 0x01F4 +#define REG_HMEBOX2_EX 0x01F8 +#define REG_HMEBOX3_EX 0x01FC + +#define REG_FIFOPAGE_CTRL_2 0x0204 +#define BIT_BCN_VALID_V1 BIT(15) +#define BIT_MASK_BCN_HEAD_1_V1 0xfff +#define REG_AUTO_LLT_V1 0x0208 +#define BIT_AUTO_INIT_LLT_V1 BIT(0) +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define BTI_PAGE_OVF BIT(2) +#define REG_RQPN_CTRL_1 0x0228 +#define REG_RQPN_CTRL_2 0x022C +#define BIT_LD_RQPN BIT(31) +#define REG_FIFOPAGE_INFO_1 0x0230 +#define REG_FIFOPAGE_INFO_2 0x0234 +#define REG_FIFOPAGE_INFO_3 0x0238 +#define REG_FIFOPAGE_INFO_4 0x023C +#define REG_FIFOPAGE_INFO_5 0x0240 +#define REG_H2C_HEAD 0x0244 +#define REG_H2C_TAIL 0x0248 +#define REG_H2C_READ_ADDR 0x024C +#define REG_H2C_INFO 0x0254 + +#define REG_FWHW_TXQ_CTRL 0x0420 +#define BIT_EN_WR_FREE_TAIL BIT(20) +#define REG_BCNQ_BDNY_V1 0x0424 +#define REG_LIFETIME_EN 0x0426 +#define BIT_BA_PARSER_EN BIT(5) +#define REG_SPEC_SIFS 0x0428 +#define REG_DARFRC 0x0430 +#define REG_DARFRCH 0x0434 +#define REG_RARFRCH 0x043C +#define REG_ARFR0 0x0444 +#define REG_ARFRH0 0x0448 +#define REG_ARFR1_V1 0x044C +#define REG_ARFRH1_V1 0x0450 +#define REG_CCK_CHECK 0x0454 +#define BIT_CHECK_CCK_EN BIT(7) +#define REG_AMPDU_MAX_TIME_V1 0x0455 +#define REG_BCNQ1_BDNY_V1 0x0456 +#define REG_TX_HANG_CTRL 0x045E +#define BIT_EN_EOF_V1 BIT(2) +#define REG_DATA_SC 0x0483 +#define REG_ARFR4 0x049C +#define REG_ARFRH4 0x04A0 +#define REG_ARFR5 0x04A4 +#define REG_ARFRH5 0x04A8 +#define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC +#define BIT_PRE_TX_CMD BIT(6) +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_PRECNT_CTRL 0x04E5 +#define BIT_EN_PRECNT BIT(11) + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_PIFS 0x0512 +#define REG_SIFS 0x0514 +#define BIT_SHIFT_SIFS_OFDM_CTX 8 +#define BIT_SHIFT_SIFS_CCK_TRX 16 +#define BIT_SHIFT_SIFS_OFDM_TRX 24 +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define BIT_SIFS_BK_EN BIT(12) +#define REG_TXPAUSE 0x0522 +#define REG_RD_CTRL 0x0524 +#define BIT_DIS_TXOP_CFE BIT(10) +#define BIT_DIS_LSIG_CFE BIT(9) +#define BIT_DIS_STBC_CFE BIT(8) +#define REG_TBTT_PROHIBIT 0x0540 +#define BIT_SHIFT_TBTT_HOLD_TIME_AP 8 +#define REG_RD_NAV_NXT 0x0544 +#define REG_BCN_CTRL 0x0550 +#define BIT_DIS_TSF_UDT BIT(4) +#define BIT_EN_BCN_FUNCTION BIT(3) +#define REG_BCN_CTRL_CLINT0 0x0551 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_USTIME_TSF 0x055C +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_MISC_CTRL 0x0577 +#define BIT_EN_FREE_CNT BIT(3) +#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1)) +#define REG_TIMER0_SRC_SEL 0x05B4 +#define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6)) + +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define BIT_APP_FCS BIT(31) +#define BIT_APP_MIC BIT(30) +#define BIT_APP_ICV BIT(29) +#define BIT_APP_PHYSTS BIT(28) +#define BIT_APP_BASSN BIT(27) +#define BIT_VHT_DACK BIT(26) +#define BIT_TCPOFLD_EN BIT(25) +#define BIT_ENMBID BIT(24) +#define BIT_LSIGEN BIT(23) +#define BIT_MFBEN BIT(22) +#define BIT_DISCHKPPDLLEN BIT(21) +#define BIT_PKTCTL_DLEN BIT(20) +#define BIT_TIM_PARSER_EN BIT(18) +#define BIT_BC_MD_EN BIT(17) +#define BIT_UC_MD_EN BIT(16) +#define BIT_RXSK_PERPKT BIT(15) +#define BIT_HTC_LOC_CTRL BIT(14) +#define BIT_RPFM_CAM_ENABLE BIT(12) +#define BIT_TA_BCN BIT(11) +#define BIT_DISDECMYPKT BIT(10) +#define BIT_AICV BIT(9) +#define BIT_ACRC32 BIT(8) +#define BIT_CBSSID_BCN BIT(7) +#define BIT_CBSSID_DATA BIT(6) +#define BIT_APWRMGT BIT(5) +#define BIT_ADD3 BIT(4) +#define BIT_AB BIT(3) +#define BIT_AM BIT(2) +#define BIT_APM BIT(1) +#define BIT_AAP BIT(0) +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DRVINFO_SZ 0x060F +#define BIT_APP_PHYSTS BIT(28) +#define REG_USTIME_EDCA 0x0638 +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_EIFS 0x0642 +#define REG_NAV_CTRL 0x0650 +#define REG_WMAC_TRXPTCL_CTL 0x0668 +#define BIT_RFMOD (BIT(7) | BIT(8)) +#define BIT_RFMOD_80M BIT(7) +#define BIT_RFMOD_40M BIT(8) +#define REG_WMAC_TRXPTCL_CTL_H 0x066C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BBPSF_CTRL 0x06DC + +#define REG_WMAC_OPTION_FUNCTION 0x07D0 +#define REG_WMAC_OPTION_FUNCTION_1 0x07D4 + +#define REG_CPU_DMEM_CON 0x1080 +#define BIT_WL_PLATFORM_RST BIT(16) +#define BIT_WL_SECURITY_CLK BIT(15) +#define BIT_DDMA_EN BIT(8) + +#define REG_H2C_PKT_READADDR 0x10D0 +#define REG_H2C_PKT_WRITEADDR 0x10D4 +#define REG_FW_DBG7 0x10FC +#define FW_KEY_MASK 0xffffff00 + +#define REG_CR_EXT 0x1100 + +#define REG_DDMA_CH0SA 0x1200 +#define REG_DDMA_CH0DA 0x1204 +#define REG_DDMA_CH0CTRL 0x1208 +#define BIT_DDMACH0_OWN BIT(31) +#define BIT_DDMACH0_CHKSUM_EN BIT(29) +#define BIT_DDMACH0_CHKSUM_STS BIT(27) +#define BIT_DDMACH0_RESET_CHKSUM_STS BIT(25) +#define BIT_DDMACH0_CHKSUM_CONT BIT(24) +#define BIT_MASK_DDMACH0_DLEN 0x3ffff + +#define REG_H2CQ_CSR 0x1330 +#define BIT_H2CQ_FULL BIT(31) +#define REG_FAST_EDCA_VOVI_SETTING 0x1448 +#define REG_FAST_EDCA_BEBK_SETTING 0x144C + +#define REG_RXPSF_CTRL 0x1610 +#define BIT_RXGCK_FIFOTHR_EN BIT(28) + +#define BIT_SHIFT_RXGCK_VHT_FIFOTHR 26 +#define BIT_MASK_RXGCK_VHT_FIFOTHR 0x3 +#define BIT_RXGCK_VHT_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_VHT_FIFOTHR) << BIT_SHIFT_RXGCK_VHT_FIFOTHR) +#define BITS_RXGCK_VHT_FIFOTHR \ + (BIT_MASK_RXGCK_VHT_FIFOTHR << BIT_SHIFT_RXGCK_VHT_FIFOTHR) + +#define BIT_SHIFT_RXGCK_HT_FIFOTHR 24 +#define BIT_MASK_RXGCK_HT_FIFOTHR 0x3 +#define BIT_RXGCK_HT_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_HT_FIFOTHR) << BIT_SHIFT_RXGCK_HT_FIFOTHR) +#define BITS_RXGCK_HT_FIFOTHR \ + (BIT_MASK_RXGCK_HT_FIFOTHR << BIT_SHIFT_RXGCK_HT_FIFOTHR) + +#define BIT_SHIFT_RXGCK_OFDM_FIFOTHR 22 +#define BIT_MASK_RXGCK_OFDM_FIFOTHR 0x3 +#define BIT_RXGCK_OFDM_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_OFDM_FIFOTHR) << BIT_SHIFT_RXGCK_OFDM_FIFOTHR) +#define BITS_RXGCK_OFDM_FIFOTHR \ + (BIT_MASK_RXGCK_OFDM_FIFOTHR << BIT_SHIFT_RXGCK_OFDM_FIFOTHR) + +#define BIT_SHIFT_RXGCK_CCK_FIFOTHR 20 +#define BIT_MASK_RXGCK_CCK_FIFOTHR 0x3 +#define BIT_RXGCK_CCK_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_CCK_FIFOTHR) << BIT_SHIFT_RXGCK_CCK_FIFOTHR) +#define BITS_RXGCK_CCK_FIFOTHR \ + (BIT_MASK_RXGCK_CCK_FIFOTHR << BIT_SHIFT_RXGCK_CCK_FIFOTHR) + +#define BIT_RXGCK_OFDMCCA_EN BIT(16) + +#define BIT_SHIFT_RXPSF_PKTLENTHR 13 +#define BIT_MASK_RXPSF_PKTLENTHR 0x7 +#define BIT_RXPSF_PKTLENTHR(x) \ + (((x) & BIT_MASK_RXPSF_PKTLENTHR) << BIT_SHIFT_RXPSF_PKTLENTHR) +#define BITS_RXPSF_PKTLENTHR \ + (BIT_MASK_RXPSF_PKTLENTHR << BIT_SHIFT_RXPSF_PKTLENTHR) +#define BIT_CLEAR_RXPSF_PKTLENTHR(x) ((x) & (~BITS_RXPSF_PKTLENTHR)) +#define BIT_SET_RXPSF_PKTLENTHR(x, v) \ + (BIT_CLEAR_RXPSF_PKTLENTHR(x) | BIT_RXPSF_PKTLENTHR(v)) + +#define BIT_RXPSF_CTRLEN BIT(12) +#define BIT_RXPSF_VHTCHKEN BIT(11) +#define BIT_RXPSF_HTCHKEN BIT(10) +#define BIT_RXPSF_OFDMCHKEN BIT(9) +#define BIT_RXPSF_CCKCHKEN BIT(8) +#define BIT_RXPSF_OFDMRST BIT(7) +#define BIT_RXPSF_CCKRST BIT(6) +#define BIT_RXPSF_MHCHKEN BIT(5) +#define BIT_RXPSF_CONT_ERRCHKEN BIT(4) +#define BIT_RXPSF_ALL_ERRCHKEN BIT(3) + +#define BIT_SHIFT_RXPSF_ERRTHR 0 +#define BIT_MASK_RXPSF_ERRTHR 0x7 +#define BIT_RXPSF_ERRTHR(x) \ + (((x) & BIT_MASK_RXPSF_ERRTHR) << BIT_SHIFT_RXPSF_ERRTHR) +#define BITS_RXPSF_ERRTHR (BIT_MASK_RXPSF_ERRTHR << BIT_SHIFT_RXPSF_ERRTHR) +#define BIT_CLEAR_RXPSF_ERRTHR(x) ((x) & (~BITS_RXPSF_ERRTHR)) +#define BIT_GET_RXPSF_ERRTHR(x) \ + (((x) >> BIT_SHIFT_RXPSF_ERRTHR) & BIT_MASK_RXPSF_ERRTHR) +#define BIT_SET_RXPSF_ERRTHR(x, v) \ + (BIT_CLEAR_RXPSF_ERRTHR(x) | BIT_RXPSF_ERRTHR(v)) + +#define REG_RXPSF_TYPE_CTRL 0x1614 + +#define REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 0x1700 +#define REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 0x1704 +#define REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 0x1708 +#define LTECOEX_READY BIT(29) +#define LTECOEX_ACCESS_CTRL REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 +#define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 +#define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 + +#define RF_DTXLOK 0x08 +#define RF_CFGCH 0x18 +#define RF_LUTWA 0x33 +#define RF_LUTWD1 0x3e +#define RF_LUTWD0 0x3f +#define RF_XTALX2 0xb8 +#define RF_MALSEL 0xbe +#define RF_LUTDBG 0xdf +#define RF_LUTWE 0xef + +#endif