18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2009-2010 Realtek Corporation.*/ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "../wifi.h" 58c2ecf20Sopenharmony_ci#include "../efuse.h" 68c2ecf20Sopenharmony_ci#include "../base.h" 78c2ecf20Sopenharmony_ci#include "../regd.h" 88c2ecf20Sopenharmony_ci#include "../cam.h" 98c2ecf20Sopenharmony_ci#include "../ps.h" 108c2ecf20Sopenharmony_ci#include "../pci.h" 118c2ecf20Sopenharmony_ci#include "reg.h" 128c2ecf20Sopenharmony_ci#include "def.h" 138c2ecf20Sopenharmony_ci#include "phy.h" 148c2ecf20Sopenharmony_ci#include "dm.h" 158c2ecf20Sopenharmony_ci#include "fw.h" 168c2ecf20Sopenharmony_ci#include "led.h" 178c2ecf20Sopenharmony_ci#include "hw.h" 188c2ecf20Sopenharmony_ci#include "../pwrseqcmd.h" 198c2ecf20Sopenharmony_ci#include "pwrseq.h" 208c2ecf20Sopenharmony_ci#include "../btcoexist/rtl_btc.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define LLT_CONFIG 5 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic void _rtl8821ae_return_beacon_queue_skb(struct ieee80211_hw *hw) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 278c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 288c2ecf20Sopenharmony_ci struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; 298c2ecf20Sopenharmony_ci struct sk_buff_head free_list; 308c2ecf20Sopenharmony_ci unsigned long flags; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci skb_queue_head_init(&free_list); 338c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); 348c2ecf20Sopenharmony_ci while (skb_queue_len(&ring->queue)) { 358c2ecf20Sopenharmony_ci struct rtl_tx_desc *entry = &ring->desc[ring->idx]; 368c2ecf20Sopenharmony_ci struct sk_buff *skb = __skb_dequeue(&ring->queue); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci dma_unmap_single(&rtlpci->pdev->dev, 398c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_desc(hw, (u8 *)entry, 408c2ecf20Sopenharmony_ci true, HW_DESC_TXBUFF_ADDR), 418c2ecf20Sopenharmony_ci skb->len, DMA_TO_DEVICE); 428c2ecf20Sopenharmony_ci __skb_queue_tail(&free_list, skb); 438c2ecf20Sopenharmony_ci ring->idx = (ring->idx + 1) % ring->entries; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci __skb_queue_purge(&free_list); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic void _rtl8821ae_set_bcn_ctrl_reg(struct ieee80211_hw *hw, 518c2ecf20Sopenharmony_ci u8 set_bits, u8 clear_bits) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 548c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci rtlpci->reg_bcn_ctrl_val |= set_bits; 578c2ecf20Sopenharmony_ci rtlpci->reg_bcn_ctrl_val &= ~clear_bits; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_civoid _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 658c2ecf20Sopenharmony_ci u8 tmp1byte; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); 688c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); 698c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); 708c2ecf20Sopenharmony_ci tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); 718c2ecf20Sopenharmony_ci tmp1byte &= ~(BIT(0)); 728c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_civoid _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 788c2ecf20Sopenharmony_ci u8 tmp1byte; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); 818c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); 828c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); 838c2ecf20Sopenharmony_ci tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); 848c2ecf20Sopenharmony_ci tmp1byte |= BIT(0); 858c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic void _rtl8821ae_enable_bcn_sub_func(struct ieee80211_hw *hw) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(1)); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic void _rtl8821ae_disable_bcn_sub_func(struct ieee80211_hw *hw) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(1), 0); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic void _rtl8821ae_set_fw_clock_on(struct ieee80211_hw *hw, 998c2ecf20Sopenharmony_ci u8 rpwm_val, bool b_need_turn_off_ckk) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1028c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1038c2ecf20Sopenharmony_ci bool b_support_remote_wake_up; 1048c2ecf20Sopenharmony_ci u32 count = 0, isr_regaddr, content; 1058c2ecf20Sopenharmony_ci bool b_schedule_timer = b_need_turn_off_ckk; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, 1088c2ecf20Sopenharmony_ci (u8 *)(&b_support_remote_wake_up)); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (!rtlhal->fw_ready) 1118c2ecf20Sopenharmony_ci return; 1128c2ecf20Sopenharmony_ci if (!rtlpriv->psc.fw_current_inpsmode) 1138c2ecf20Sopenharmony_ci return; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci while (1) { 1168c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 1178c2ecf20Sopenharmony_ci if (rtlhal->fw_clk_change_in_progress) { 1188c2ecf20Sopenharmony_ci while (rtlhal->fw_clk_change_in_progress) { 1198c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 1208c2ecf20Sopenharmony_ci count++; 1218c2ecf20Sopenharmony_ci udelay(100); 1228c2ecf20Sopenharmony_ci if (count > 1000) 1238c2ecf20Sopenharmony_ci goto change_done; 1248c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 1278c2ecf20Sopenharmony_ci } else { 1288c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = false; 1298c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 1308c2ecf20Sopenharmony_ci goto change_done; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_cichange_done: 1348c2ecf20Sopenharmony_ci if (IS_IN_LOW_POWER_STATE_8821AE(rtlhal->fw_ps_state)) { 1358c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, 1368c2ecf20Sopenharmony_ci (u8 *)(&rpwm_val)); 1378c2ecf20Sopenharmony_ci if (FW_PS_IS_ACK(rpwm_val)) { 1388c2ecf20Sopenharmony_ci isr_regaddr = REG_HISR; 1398c2ecf20Sopenharmony_ci content = rtl_read_dword(rtlpriv, isr_regaddr); 1408c2ecf20Sopenharmony_ci while (!(content & IMR_CPWM) && (count < 500)) { 1418c2ecf20Sopenharmony_ci udelay(50); 1428c2ecf20Sopenharmony_ci count++; 1438c2ecf20Sopenharmony_ci content = rtl_read_dword(rtlpriv, isr_regaddr); 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (content & IMR_CPWM) { 1478c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, isr_regaddr, 0x0100); 1488c2ecf20Sopenharmony_ci rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_8821AE; 1498c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 1508c2ecf20Sopenharmony_ci "Receive CPWM INT!!! Set rtlhal->FwPSState = %X\n", 1518c2ecf20Sopenharmony_ci rtlhal->fw_ps_state); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 1568c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = false; 1578c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 1588c2ecf20Sopenharmony_ci if (b_schedule_timer) 1598c2ecf20Sopenharmony_ci mod_timer(&rtlpriv->works.fw_clockoff_timer, 1608c2ecf20Sopenharmony_ci jiffies + MSECS(10)); 1618c2ecf20Sopenharmony_ci } else { 1628c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 1638c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = false; 1648c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic void _rtl8821ae_set_fw_clock_off(struct ieee80211_hw *hw, 1698c2ecf20Sopenharmony_ci u8 rpwm_val) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1728c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1738c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 1748c2ecf20Sopenharmony_ci struct rtl8192_tx_ring *ring; 1758c2ecf20Sopenharmony_ci enum rf_pwrstate rtstate; 1768c2ecf20Sopenharmony_ci bool b_schedule_timer = false; 1778c2ecf20Sopenharmony_ci u8 queue; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (!rtlhal->fw_ready) 1808c2ecf20Sopenharmony_ci return; 1818c2ecf20Sopenharmony_ci if (!rtlpriv->psc.fw_current_inpsmode) 1828c2ecf20Sopenharmony_ci return; 1838c2ecf20Sopenharmony_ci if (!rtlhal->allow_sw_to_change_hwclc) 1848c2ecf20Sopenharmony_ci return; 1858c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); 1868c2ecf20Sopenharmony_ci if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) 1878c2ecf20Sopenharmony_ci return; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { 1908c2ecf20Sopenharmony_ci ring = &rtlpci->tx_ring[queue]; 1918c2ecf20Sopenharmony_ci if (skb_queue_len(&ring->queue)) { 1928c2ecf20Sopenharmony_ci b_schedule_timer = true; 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (b_schedule_timer) { 1988c2ecf20Sopenharmony_ci mod_timer(&rtlpriv->works.fw_clockoff_timer, 1998c2ecf20Sopenharmony_ci jiffies + MSECS(10)); 2008c2ecf20Sopenharmony_ci return; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (FW_PS_STATE(rtlhal->fw_ps_state) != 2048c2ecf20Sopenharmony_ci FW_PS_STATE_RF_OFF_LOW_PWR_8821AE) { 2058c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 2068c2ecf20Sopenharmony_ci if (!rtlhal->fw_clk_change_in_progress) { 2078c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = true; 2088c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 2098c2ecf20Sopenharmony_ci rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); 2108c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_HISR, 0x0100); 2118c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, 2128c2ecf20Sopenharmony_ci (u8 *)(&rpwm_val)); 2138c2ecf20Sopenharmony_ci spin_lock_bh(&rtlpriv->locks.fw_ps_lock); 2148c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = false; 2158c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 2168c2ecf20Sopenharmony_ci } else { 2178c2ecf20Sopenharmony_ci spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); 2188c2ecf20Sopenharmony_ci mod_timer(&rtlpriv->works.fw_clockoff_timer, 2198c2ecf20Sopenharmony_ci jiffies + MSECS(10)); 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic void _rtl8821ae_set_fw_ps_rf_on(struct ieee80211_hw *hw) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci u8 rpwm_val = 0; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci rpwm_val |= (FW_PS_STATE_RF_OFF_8821AE | FW_PS_ACK); 2298c2ecf20Sopenharmony_ci _rtl8821ae_set_fw_clock_on(hw, rpwm_val, true); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void _rtl8821ae_fwlps_leave(struct ieee80211_hw *hw) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2358c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 2368c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2378c2ecf20Sopenharmony_ci bool fw_current_inps = false; 2388c2ecf20Sopenharmony_ci u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (ppsc->low_power_enable) { 2418c2ecf20Sopenharmony_ci rpwm_val = (FW_PS_STATE_ALL_ON_8821AE|FW_PS_ACK);/* RF on */ 2428c2ecf20Sopenharmony_ci _rtl8821ae_set_fw_clock_on(hw, rpwm_val, false); 2438c2ecf20Sopenharmony_ci rtlhal->allow_sw_to_change_hwclc = false; 2448c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, 2458c2ecf20Sopenharmony_ci (u8 *)(&fw_pwrmode)); 2468c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, 2478c2ecf20Sopenharmony_ci (u8 *)(&fw_current_inps)); 2488c2ecf20Sopenharmony_ci } else { 2498c2ecf20Sopenharmony_ci rpwm_val = FW_PS_STATE_ALL_ON_8821AE; /* RF on */ 2508c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, 2518c2ecf20Sopenharmony_ci (u8 *)(&rpwm_val)); 2528c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, 2538c2ecf20Sopenharmony_ci (u8 *)(&fw_pwrmode)); 2548c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, 2558c2ecf20Sopenharmony_ci (u8 *)(&fw_current_inps)); 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic void _rtl8821ae_fwlps_enter(struct ieee80211_hw *hw) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2628c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 2638c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2648c2ecf20Sopenharmony_ci bool fw_current_inps = true; 2658c2ecf20Sopenharmony_ci u8 rpwm_val; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (ppsc->low_power_enable) { 2688c2ecf20Sopenharmony_ci rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_8821AE; /* RF off */ 2698c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 2708c2ecf20Sopenharmony_ci HW_VAR_FW_PSMODE_STATUS, 2718c2ecf20Sopenharmony_ci (u8 *)(&fw_current_inps)); 2728c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 2738c2ecf20Sopenharmony_ci HW_VAR_H2C_FW_PWRMODE, 2748c2ecf20Sopenharmony_ci (u8 *)(&ppsc->fwctrl_psmode)); 2758c2ecf20Sopenharmony_ci rtlhal->allow_sw_to_change_hwclc = true; 2768c2ecf20Sopenharmony_ci _rtl8821ae_set_fw_clock_off(hw, rpwm_val); 2778c2ecf20Sopenharmony_ci } else { 2788c2ecf20Sopenharmony_ci rpwm_val = FW_PS_STATE_RF_OFF_8821AE; /* RF off */ 2798c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 2808c2ecf20Sopenharmony_ci HW_VAR_FW_PSMODE_STATUS, 2818c2ecf20Sopenharmony_ci (u8 *)(&fw_current_inps)); 2828c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 2838c2ecf20Sopenharmony_ci HW_VAR_H2C_FW_PWRMODE, 2848c2ecf20Sopenharmony_ci (u8 *)(&ppsc->fwctrl_psmode)); 2858c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 2868c2ecf20Sopenharmony_ci HW_VAR_SET_RPWM, 2878c2ecf20Sopenharmony_ci (u8 *)(&rpwm_val)); 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic void _rtl8821ae_download_rsvd_page(struct ieee80211_hw *hw, 2928c2ecf20Sopenharmony_ci bool dl_whole_packets) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2958c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 2968c2ecf20Sopenharmony_ci u8 tmp_regcr, tmp_reg422, bcnvalid_reg; 2978c2ecf20Sopenharmony_ci u8 count = 0, dlbcn_count = 0; 2988c2ecf20Sopenharmony_ci bool send_beacon = false; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); 3018c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr | BIT(0))); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); 3048c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); 3078c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, 3088c2ecf20Sopenharmony_ci tmp_reg422 & (~BIT(6))); 3098c2ecf20Sopenharmony_ci if (tmp_reg422 & BIT(6)) 3108c2ecf20Sopenharmony_ci send_beacon = true; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci do { 3138c2ecf20Sopenharmony_ci bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); 3148c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 2, 3158c2ecf20Sopenharmony_ci (bcnvalid_reg | BIT(0))); 3168c2ecf20Sopenharmony_ci _rtl8821ae_return_beacon_queue_skb(hw); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 3198c2ecf20Sopenharmony_ci rtl8812ae_set_fw_rsvdpagepkt(hw, false, 3208c2ecf20Sopenharmony_ci dl_whole_packets); 3218c2ecf20Sopenharmony_ci else 3228c2ecf20Sopenharmony_ci rtl8821ae_set_fw_rsvdpagepkt(hw, false, 3238c2ecf20Sopenharmony_ci dl_whole_packets); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); 3268c2ecf20Sopenharmony_ci count = 0; 3278c2ecf20Sopenharmony_ci while (!(bcnvalid_reg & BIT(0)) && count < 20) { 3288c2ecf20Sopenharmony_ci count++; 3298c2ecf20Sopenharmony_ci udelay(10); 3308c2ecf20Sopenharmony_ci bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci dlbcn_count++; 3338c2ecf20Sopenharmony_ci } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (!(bcnvalid_reg & BIT(0))) 3368c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 3378c2ecf20Sopenharmony_ci "Download RSVD page failed!\n"); 3388c2ecf20Sopenharmony_ci if (bcnvalid_reg & BIT(0) && rtlhal->enter_pnp_sleep) { 3398c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 2, bcnvalid_reg | BIT(0)); 3408c2ecf20Sopenharmony_ci _rtl8821ae_return_beacon_queue_skb(hw); 3418c2ecf20Sopenharmony_ci if (send_beacon) { 3428c2ecf20Sopenharmony_ci dlbcn_count = 0; 3438c2ecf20Sopenharmony_ci do { 3448c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 2, 3458c2ecf20Sopenharmony_ci bcnvalid_reg | BIT(0)); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci _rtl8821ae_return_beacon_queue_skb(hw); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 3508c2ecf20Sopenharmony_ci rtl8812ae_set_fw_rsvdpagepkt(hw, true, 3518c2ecf20Sopenharmony_ci false); 3528c2ecf20Sopenharmony_ci else 3538c2ecf20Sopenharmony_ci rtl8821ae_set_fw_rsvdpagepkt(hw, true, 3548c2ecf20Sopenharmony_ci false); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* check rsvd page download OK. */ 3578c2ecf20Sopenharmony_ci bcnvalid_reg = rtl_read_byte(rtlpriv, 3588c2ecf20Sopenharmony_ci REG_TDECTRL + 2); 3598c2ecf20Sopenharmony_ci count = 0; 3608c2ecf20Sopenharmony_ci while (!(bcnvalid_reg & BIT(0)) && count < 20) { 3618c2ecf20Sopenharmony_ci count++; 3628c2ecf20Sopenharmony_ci udelay(10); 3638c2ecf20Sopenharmony_ci bcnvalid_reg = 3648c2ecf20Sopenharmony_ci rtl_read_byte(rtlpriv, 3658c2ecf20Sopenharmony_ci REG_TDECTRL + 2); 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci dlbcn_count++; 3688c2ecf20Sopenharmony_ci } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (!(bcnvalid_reg & BIT(0))) 3718c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 3728c2ecf20Sopenharmony_ci "2 Download RSVD page failed!\n"); 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (bcnvalid_reg & BIT(0)) 3778c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0)); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); 3808c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (send_beacon) 3838c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (!rtlhal->enter_pnp_sleep) { 3868c2ecf20Sopenharmony_ci tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); 3878c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_civoid rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 3948c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 3958c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 3968c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci switch (variable) { 3998c2ecf20Sopenharmony_ci case HW_VAR_ETHER_ADDR: 4008c2ecf20Sopenharmony_ci *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_MACID); 4018c2ecf20Sopenharmony_ci *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_MACID + 4); 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci case HW_VAR_BSSID: 4048c2ecf20Sopenharmony_ci *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_BSSID); 4058c2ecf20Sopenharmony_ci *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_BSSID+4); 4068c2ecf20Sopenharmony_ci break; 4078c2ecf20Sopenharmony_ci case HW_VAR_MEDIA_STATUS: 4088c2ecf20Sopenharmony_ci val[0] = rtl_read_byte(rtlpriv, MSR) & 0x3; 4098c2ecf20Sopenharmony_ci break; 4108c2ecf20Sopenharmony_ci case HW_VAR_SLOT_TIME: 4118c2ecf20Sopenharmony_ci *((u8 *)(val)) = mac->slot_time; 4128c2ecf20Sopenharmony_ci break; 4138c2ecf20Sopenharmony_ci case HW_VAR_BEACON_INTERVAL: 4148c2ecf20Sopenharmony_ci *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_BCN_INTERVAL); 4158c2ecf20Sopenharmony_ci break; 4168c2ecf20Sopenharmony_ci case HW_VAR_ATIM_WINDOW: 4178c2ecf20Sopenharmony_ci *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_ATIMWND); 4188c2ecf20Sopenharmony_ci break; 4198c2ecf20Sopenharmony_ci case HW_VAR_RCR: 4208c2ecf20Sopenharmony_ci *((u32 *)(val)) = rtlpci->receive_config; 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci case HW_VAR_RF_STATE: 4238c2ecf20Sopenharmony_ci *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci case HW_VAR_FWLPS_RF_ON:{ 4268c2ecf20Sopenharmony_ci enum rf_pwrstate rfstate; 4278c2ecf20Sopenharmony_ci u32 val_rcr; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, 4308c2ecf20Sopenharmony_ci HW_VAR_RF_STATE, 4318c2ecf20Sopenharmony_ci (u8 *)(&rfstate)); 4328c2ecf20Sopenharmony_ci if (rfstate == ERFOFF) { 4338c2ecf20Sopenharmony_ci *((bool *)(val)) = true; 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci val_rcr = rtl_read_dword(rtlpriv, REG_RCR); 4368c2ecf20Sopenharmony_ci val_rcr &= 0x00070000; 4378c2ecf20Sopenharmony_ci if (val_rcr) 4388c2ecf20Sopenharmony_ci *((bool *)(val)) = false; 4398c2ecf20Sopenharmony_ci else 4408c2ecf20Sopenharmony_ci *((bool *)(val)) = true; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci break; } 4438c2ecf20Sopenharmony_ci case HW_VAR_FW_PSMODE_STATUS: 4448c2ecf20Sopenharmony_ci *((bool *)(val)) = ppsc->fw_current_inpsmode; 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci case HW_VAR_CORRECT_TSF:{ 4478c2ecf20Sopenharmony_ci u64 tsf; 4488c2ecf20Sopenharmony_ci u32 *ptsf_low = (u32 *)&tsf; 4498c2ecf20Sopenharmony_ci u32 *ptsf_high = ((u32 *)&tsf) + 1; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); 4528c2ecf20Sopenharmony_ci *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci *((u64 *)(val)) = tsf; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci break; } 4578c2ecf20Sopenharmony_ci case HAL_DEF_WOWLAN: 4588c2ecf20Sopenharmony_ci if (ppsc->wo_wlan_mode) 4598c2ecf20Sopenharmony_ci *((bool *)(val)) = true; 4608c2ecf20Sopenharmony_ci else 4618c2ecf20Sopenharmony_ci *((bool *)(val)) = false; 4628c2ecf20Sopenharmony_ci break; 4638c2ecf20Sopenharmony_ci default: 4648c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, 4658c2ecf20Sopenharmony_ci "switch case %#x not processed\n", variable); 4668c2ecf20Sopenharmony_ci break; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_civoid rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 4738c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 4748c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 4758c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 4768c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 4778c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 4788c2ecf20Sopenharmony_ci u8 idx; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci switch (variable) { 4818c2ecf20Sopenharmony_ci case HW_VAR_ETHER_ADDR:{ 4828c2ecf20Sopenharmony_ci for (idx = 0; idx < ETH_ALEN; idx++) { 4838c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, (REG_MACID + idx), 4848c2ecf20Sopenharmony_ci val[idx]); 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci case HW_VAR_BASIC_RATE:{ 4898c2ecf20Sopenharmony_ci u16 b_rate_cfg = ((u16 *)val)[0]; 4908c2ecf20Sopenharmony_ci b_rate_cfg = b_rate_cfg & 0x15f; 4918c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RRSR, b_rate_cfg); 4928c2ecf20Sopenharmony_ci break; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci case HW_VAR_BSSID:{ 4958c2ecf20Sopenharmony_ci for (idx = 0; idx < ETH_ALEN; idx++) { 4968c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, (REG_BSSID + idx), 4978c2ecf20Sopenharmony_ci val[idx]); 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci case HW_VAR_SIFS: 5028c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); 5038c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[0]); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); 5068c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); 5098c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM, val[0]); 5108c2ecf20Sopenharmony_ci break; 5118c2ecf20Sopenharmony_ci case HW_VAR_R2T_SIFS: 5128c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); 5138c2ecf20Sopenharmony_ci break; 5148c2ecf20Sopenharmony_ci case HW_VAR_SLOT_TIME:{ 5158c2ecf20Sopenharmony_ci u8 e_aci; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, 5188c2ecf20Sopenharmony_ci "HW_VAR_SLOT_TIME %x\n", val[0]); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SLOT, val[0]); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci for (e_aci = 0; e_aci < AC_MAX; e_aci++) { 5238c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 5248c2ecf20Sopenharmony_ci HW_VAR_AC_PARAM, 5258c2ecf20Sopenharmony_ci (u8 *)(&e_aci)); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci break; } 5288c2ecf20Sopenharmony_ci case HW_VAR_ACK_PREAMBLE:{ 5298c2ecf20Sopenharmony_ci u8 reg_tmp; 5308c2ecf20Sopenharmony_ci u8 short_preamble = (bool)(*(u8 *)val); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); 5338c2ecf20Sopenharmony_ci if (short_preamble) { 5348c2ecf20Sopenharmony_ci reg_tmp |= BIT(1); 5358c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, 5368c2ecf20Sopenharmony_ci reg_tmp); 5378c2ecf20Sopenharmony_ci } else { 5388c2ecf20Sopenharmony_ci reg_tmp &= (~BIT(1)); 5398c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 5408c2ecf20Sopenharmony_ci REG_TRXPTCL_CTL + 2, 5418c2ecf20Sopenharmony_ci reg_tmp); 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci break; } 5448c2ecf20Sopenharmony_ci case HW_VAR_WPA_CONFIG: 5458c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); 5468c2ecf20Sopenharmony_ci break; 5478c2ecf20Sopenharmony_ci case HW_VAR_AMPDU_MIN_SPACE:{ 5488c2ecf20Sopenharmony_ci u8 min_spacing_to_set; 5498c2ecf20Sopenharmony_ci u8 sec_min_space; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci min_spacing_to_set = *((u8 *)val); 5528c2ecf20Sopenharmony_ci if (min_spacing_to_set <= 7) { 5538c2ecf20Sopenharmony_ci sec_min_space = 0; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci if (min_spacing_to_set < sec_min_space) 5568c2ecf20Sopenharmony_ci min_spacing_to_set = sec_min_space; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci mac->min_space_cfg = ((mac->min_space_cfg & 5598c2ecf20Sopenharmony_ci 0xf8) | 5608c2ecf20Sopenharmony_ci min_spacing_to_set); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci *val = min_spacing_to_set; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, 5658c2ecf20Sopenharmony_ci "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", 5668c2ecf20Sopenharmony_ci mac->min_space_cfg); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 5698c2ecf20Sopenharmony_ci mac->min_space_cfg); 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci break; } 5728c2ecf20Sopenharmony_ci case HW_VAR_SHORTGI_DENSITY:{ 5738c2ecf20Sopenharmony_ci u8 density_to_set; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci density_to_set = *((u8 *)val); 5768c2ecf20Sopenharmony_ci mac->min_space_cfg |= (density_to_set << 3); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, 5798c2ecf20Sopenharmony_ci "Set HW_VAR_SHORTGI_DENSITY: %#x\n", 5808c2ecf20Sopenharmony_ci mac->min_space_cfg); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 5838c2ecf20Sopenharmony_ci mac->min_space_cfg); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci break; } 5868c2ecf20Sopenharmony_ci case HW_VAR_AMPDU_FACTOR:{ 5878c2ecf20Sopenharmony_ci u32 ampdu_len = (*((u8 *)val)); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 5908c2ecf20Sopenharmony_ci if (ampdu_len < VHT_AGG_SIZE_128K) 5918c2ecf20Sopenharmony_ci ampdu_len = 5928c2ecf20Sopenharmony_ci (0x2000 << (*((u8 *)val))) - 1; 5938c2ecf20Sopenharmony_ci else 5948c2ecf20Sopenharmony_ci ampdu_len = 0x1ffff; 5958c2ecf20Sopenharmony_ci } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 5968c2ecf20Sopenharmony_ci if (ampdu_len < HT_AGG_SIZE_64K) 5978c2ecf20Sopenharmony_ci ampdu_len = 5988c2ecf20Sopenharmony_ci (0x2000 << (*((u8 *)val))) - 1; 5998c2ecf20Sopenharmony_ci else 6008c2ecf20Sopenharmony_ci ampdu_len = 0xffff; 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci ampdu_len |= BIT(31); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, 6058c2ecf20Sopenharmony_ci REG_AMPDU_MAX_LENGTH_8812, ampdu_len); 6068c2ecf20Sopenharmony_ci break; } 6078c2ecf20Sopenharmony_ci case HW_VAR_AC_PARAM:{ 6088c2ecf20Sopenharmony_ci u8 e_aci = *((u8 *)val); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci rtl8821ae_dm_init_edca_turbo(hw); 6118c2ecf20Sopenharmony_ci if (rtlpci->acm_method != EACMWAY2_SW) 6128c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 6138c2ecf20Sopenharmony_ci HW_VAR_ACM_CTRL, 6148c2ecf20Sopenharmony_ci (u8 *)(&e_aci)); 6158c2ecf20Sopenharmony_ci break; } 6168c2ecf20Sopenharmony_ci case HW_VAR_ACM_CTRL:{ 6178c2ecf20Sopenharmony_ci u8 e_aci = *((u8 *)val); 6188c2ecf20Sopenharmony_ci union aci_aifsn *p_aci_aifsn = 6198c2ecf20Sopenharmony_ci (union aci_aifsn *)(&mac->ac[0].aifs); 6208c2ecf20Sopenharmony_ci u8 acm = p_aci_aifsn->f.acm; 6218c2ecf20Sopenharmony_ci u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci acm_ctrl = 6248c2ecf20Sopenharmony_ci acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci if (acm) { 6278c2ecf20Sopenharmony_ci switch (e_aci) { 6288c2ecf20Sopenharmony_ci case AC0_BE: 6298c2ecf20Sopenharmony_ci acm_ctrl |= ACMHW_BEQEN; 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci case AC2_VI: 6328c2ecf20Sopenharmony_ci acm_ctrl |= ACMHW_VIQEN; 6338c2ecf20Sopenharmony_ci break; 6348c2ecf20Sopenharmony_ci case AC3_VO: 6358c2ecf20Sopenharmony_ci acm_ctrl |= ACMHW_VOQEN; 6368c2ecf20Sopenharmony_ci break; 6378c2ecf20Sopenharmony_ci default: 6388c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, 6398c2ecf20Sopenharmony_ci "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", 6408c2ecf20Sopenharmony_ci acm); 6418c2ecf20Sopenharmony_ci break; 6428c2ecf20Sopenharmony_ci } 6438c2ecf20Sopenharmony_ci } else { 6448c2ecf20Sopenharmony_ci switch (e_aci) { 6458c2ecf20Sopenharmony_ci case AC0_BE: 6468c2ecf20Sopenharmony_ci acm_ctrl &= (~ACMHW_BEQEN); 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci case AC2_VI: 6498c2ecf20Sopenharmony_ci acm_ctrl &= (~ACMHW_VIQEN); 6508c2ecf20Sopenharmony_ci break; 6518c2ecf20Sopenharmony_ci case AC3_VO: 6528c2ecf20Sopenharmony_ci acm_ctrl &= (~ACMHW_VOQEN); 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci default: 6558c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, 6568c2ecf20Sopenharmony_ci "switch case %#x not processed\n", 6578c2ecf20Sopenharmony_ci e_aci); 6588c2ecf20Sopenharmony_ci break; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_QOS, DBG_TRACE, 6638c2ecf20Sopenharmony_ci "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", 6648c2ecf20Sopenharmony_ci acm_ctrl); 6658c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); 6668c2ecf20Sopenharmony_ci break; } 6678c2ecf20Sopenharmony_ci case HW_VAR_RCR: 6688c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); 6698c2ecf20Sopenharmony_ci rtlpci->receive_config = ((u32 *)(val))[0]; 6708c2ecf20Sopenharmony_ci break; 6718c2ecf20Sopenharmony_ci case HW_VAR_RETRY_LIMIT:{ 6728c2ecf20Sopenharmony_ci u8 retry_limit = ((u8 *)(val))[0]; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RL, 6758c2ecf20Sopenharmony_ci retry_limit << RETRY_LIMIT_SHORT_SHIFT | 6768c2ecf20Sopenharmony_ci retry_limit << RETRY_LIMIT_LONG_SHIFT); 6778c2ecf20Sopenharmony_ci break; } 6788c2ecf20Sopenharmony_ci case HW_VAR_DUAL_TSF_RST: 6798c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci case HW_VAR_EFUSE_BYTES: 6828c2ecf20Sopenharmony_ci rtlefuse->efuse_usedbytes = *((u16 *)val); 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci case HW_VAR_EFUSE_USAGE: 6858c2ecf20Sopenharmony_ci rtlefuse->efuse_usedpercentage = *((u8 *)val); 6868c2ecf20Sopenharmony_ci break; 6878c2ecf20Sopenharmony_ci case HW_VAR_IO_CMD: 6888c2ecf20Sopenharmony_ci rtl8821ae_phy_set_io_cmd(hw, (*(enum io_type *)val)); 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci case HW_VAR_SET_RPWM:{ 6918c2ecf20Sopenharmony_ci u8 rpwm_val; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); 6948c2ecf20Sopenharmony_ci udelay(1); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci if (rpwm_val & BIT(7)) { 6978c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, 6988c2ecf20Sopenharmony_ci (*(u8 *)val)); 6998c2ecf20Sopenharmony_ci } else { 7008c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, 7018c2ecf20Sopenharmony_ci ((*(u8 *)val) | BIT(7))); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci break; } 7058c2ecf20Sopenharmony_ci case HW_VAR_H2C_FW_PWRMODE: 7068c2ecf20Sopenharmony_ci rtl8821ae_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); 7078c2ecf20Sopenharmony_ci break; 7088c2ecf20Sopenharmony_ci case HW_VAR_FW_PSMODE_STATUS: 7098c2ecf20Sopenharmony_ci ppsc->fw_current_inpsmode = *((bool *)val); 7108c2ecf20Sopenharmony_ci break; 7118c2ecf20Sopenharmony_ci case HW_VAR_INIT_RTS_RATE: 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case HW_VAR_RESUME_CLK_ON: 7148c2ecf20Sopenharmony_ci _rtl8821ae_set_fw_ps_rf_on(hw); 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci case HW_VAR_FW_LPS_ACTION:{ 7178c2ecf20Sopenharmony_ci bool b_enter_fwlps = *((bool *)val); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (b_enter_fwlps) 7208c2ecf20Sopenharmony_ci _rtl8821ae_fwlps_enter(hw); 7218c2ecf20Sopenharmony_ci else 7228c2ecf20Sopenharmony_ci _rtl8821ae_fwlps_leave(hw); 7238c2ecf20Sopenharmony_ci break; } 7248c2ecf20Sopenharmony_ci case HW_VAR_H2C_FW_JOINBSSRPT:{ 7258c2ecf20Sopenharmony_ci u8 mstatus = (*(u8 *)val); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci if (mstatus == RT_MEDIA_CONNECT) { 7288c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, 7298c2ecf20Sopenharmony_ci NULL); 7308c2ecf20Sopenharmony_ci _rtl8821ae_download_rsvd_page(hw, false); 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci rtl8821ae_set_fw_media_status_rpt_cmd(hw, mstatus); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci break; } 7358c2ecf20Sopenharmony_ci case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: 7368c2ecf20Sopenharmony_ci rtl8821ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); 7378c2ecf20Sopenharmony_ci break; 7388c2ecf20Sopenharmony_ci case HW_VAR_AID:{ 7398c2ecf20Sopenharmony_ci u16 u2btmp; 7408c2ecf20Sopenharmony_ci u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); 7418c2ecf20Sopenharmony_ci u2btmp &= 0xC000; 7428c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | 7438c2ecf20Sopenharmony_ci mac->assoc_id)); 7448c2ecf20Sopenharmony_ci break; } 7458c2ecf20Sopenharmony_ci case HW_VAR_CORRECT_TSF:{ 7468c2ecf20Sopenharmony_ci u8 btype_ibss = ((u8 *)(val))[0]; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (btype_ibss) 7498c2ecf20Sopenharmony_ci _rtl8821ae_stop_tx_beacon(hw); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_TSFTR, 7548c2ecf20Sopenharmony_ci (u32)(mac->tsf & 0xffffffff)); 7558c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_TSFTR + 4, 7568c2ecf20Sopenharmony_ci (u32)((mac->tsf >> 32) & 0xffffffff)); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci if (btype_ibss) 7618c2ecf20Sopenharmony_ci _rtl8821ae_resume_tx_beacon(hw); 7628c2ecf20Sopenharmony_ci break; } 7638c2ecf20Sopenharmony_ci case HW_VAR_NAV_UPPER: { 7648c2ecf20Sopenharmony_ci u32 us_nav_upper = *(u32 *)val; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (us_nav_upper > HAL_92C_NAV_UPPER_UNIT * 0xFF) { 7678c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING, 7688c2ecf20Sopenharmony_ci "The setting value (0x%08X us) of NAV_UPPER is larger than (%d * 0xFF)!!!\n", 7698c2ecf20Sopenharmony_ci us_nav_upper, HAL_92C_NAV_UPPER_UNIT); 7708c2ecf20Sopenharmony_ci break; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_NAV_UPPER, 7738c2ecf20Sopenharmony_ci ((u8)((us_nav_upper + 7748c2ecf20Sopenharmony_ci HAL_92C_NAV_UPPER_UNIT - 1) / 7758c2ecf20Sopenharmony_ci HAL_92C_NAV_UPPER_UNIT))); 7768c2ecf20Sopenharmony_ci break; } 7778c2ecf20Sopenharmony_ci case HW_VAR_KEEP_ALIVE: { 7788c2ecf20Sopenharmony_ci u8 array[2]; 7798c2ecf20Sopenharmony_ci array[0] = 0xff; 7808c2ecf20Sopenharmony_ci array[1] = *((u8 *)val); 7818c2ecf20Sopenharmony_ci rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_KEEP_ALIVE_CTRL, 2, 7828c2ecf20Sopenharmony_ci array); 7838c2ecf20Sopenharmony_ci break; } 7848c2ecf20Sopenharmony_ci default: 7858c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, 7868c2ecf20Sopenharmony_ci "switch case %#x not processed\n", variable); 7878c2ecf20Sopenharmony_ci break; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic bool _rtl8821ae_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 7948c2ecf20Sopenharmony_ci bool status = true; 7958c2ecf20Sopenharmony_ci long count = 0; 7968c2ecf20Sopenharmony_ci u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | 7978c2ecf20Sopenharmony_ci _LLT_OP(_LLT_WRITE_ACCESS); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_LLT_INIT, value); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci do { 8028c2ecf20Sopenharmony_ci value = rtl_read_dword(rtlpriv, REG_LLT_INIT); 8038c2ecf20Sopenharmony_ci if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) 8048c2ecf20Sopenharmony_ci break; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci if (count > POLLING_LLT_THRESHOLD) { 8078c2ecf20Sopenharmony_ci pr_err("Failed to polling write LLT done at address %d!\n", 8088c2ecf20Sopenharmony_ci address); 8098c2ecf20Sopenharmony_ci status = false; 8108c2ecf20Sopenharmony_ci break; 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci } while (++count); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci return status; 8158c2ecf20Sopenharmony_ci} 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic bool _rtl8821ae_llt_table_init(struct ieee80211_hw *hw) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 8208c2ecf20Sopenharmony_ci unsigned short i; 8218c2ecf20Sopenharmony_ci u8 txpktbuf_bndy; 8228c2ecf20Sopenharmony_ci u32 rqpn; 8238c2ecf20Sopenharmony_ci u8 maxpage; 8248c2ecf20Sopenharmony_ci bool status; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci maxpage = 255; 8278c2ecf20Sopenharmony_ci txpktbuf_bndy = 0xF7; 8288c2ecf20Sopenharmony_ci rqpn = 0x80e60808; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); 8318c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, MAX_RX_DMA_BUFFER_SIZE - 1); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); 8368c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PBP, 0x31); 8398c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci for (i = 0; i < (txpktbuf_bndy - 1); i++) { 8428c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, i, i + 1); 8438c2ecf20Sopenharmony_ci if (!status) 8448c2ecf20Sopenharmony_ci return status; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); 8488c2ecf20Sopenharmony_ci if (!status) 8498c2ecf20Sopenharmony_ci return status; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci for (i = txpktbuf_bndy; i < maxpage; i++) { 8528c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, i, (i + 1)); 8538c2ecf20Sopenharmony_ci if (!status) 8548c2ecf20Sopenharmony_ci return status; 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, maxpage, txpktbuf_bndy); 8588c2ecf20Sopenharmony_ci if (!status) 8598c2ecf20Sopenharmony_ci return status; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RQPN, rqpn); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci return true; 8668c2ecf20Sopenharmony_ci} 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 8718c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 8728c2ecf20Sopenharmony_ci struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; 8738c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci if (rtlpriv->rtlhal.up_first_time) 8768c2ecf20Sopenharmony_ci return; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) 8798c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 8808c2ecf20Sopenharmony_ci rtl8812ae_sw_led_on(hw, pled0); 8818c2ecf20Sopenharmony_ci else 8828c2ecf20Sopenharmony_ci rtl8821ae_sw_led_on(hw, pled0); 8838c2ecf20Sopenharmony_ci else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) 8848c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 8858c2ecf20Sopenharmony_ci rtl8812ae_sw_led_on(hw, pled0); 8868c2ecf20Sopenharmony_ci else 8878c2ecf20Sopenharmony_ci rtl8821ae_sw_led_on(hw, pled0); 8888c2ecf20Sopenharmony_ci else 8898c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 8908c2ecf20Sopenharmony_ci rtl8812ae_sw_led_off(hw, pled0); 8918c2ecf20Sopenharmony_ci else 8928c2ecf20Sopenharmony_ci rtl8821ae_sw_led_off(hw, pled0); 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic bool _rtl8821ae_init_mac(struct ieee80211_hw *hw) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 8988c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 8998c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci u8 bytetmp = 0; 9028c2ecf20Sopenharmony_ci u16 wordtmp = 0; 9038c2ecf20Sopenharmony_ci bool mac_func_enable = rtlhal->mac_func_enable; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci /*Auto Power Down to CHIP-off State*/ 9088c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); 9098c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 9128c2ecf20Sopenharmony_ci /* HW Power on sequence*/ 9138c2ecf20Sopenharmony_ci if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, 9148c2ecf20Sopenharmony_ci PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, 9158c2ecf20Sopenharmony_ci RTL8812_NIC_ENABLE_FLOW)) { 9168c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 9178c2ecf20Sopenharmony_ci "init 8812 MAC Fail as power on failure\n"); 9188c2ecf20Sopenharmony_ci return false; 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci } else { 9218c2ecf20Sopenharmony_ci /* HW Power on sequence */ 9228c2ecf20Sopenharmony_ci if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_A_MSK, 9238c2ecf20Sopenharmony_ci PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, 9248c2ecf20Sopenharmony_ci RTL8821A_NIC_ENABLE_FLOW)){ 9258c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 9268c2ecf20Sopenharmony_ci "init 8821 MAC Fail as power on failure\n"); 9278c2ecf20Sopenharmony_ci return false; 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); 9328c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_CR); 9358c2ecf20Sopenharmony_ci bytetmp = 0xff; 9368c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR, bytetmp); 9378c2ecf20Sopenharmony_ci mdelay(2); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci bytetmp = 0xff; 9408c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); 9418c2ecf20Sopenharmony_ci mdelay(2); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 9448c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3); 9458c2ecf20Sopenharmony_ci if (bytetmp & BIT(0)) { 9468c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, 0x7c); 9478c2ecf20Sopenharmony_ci bytetmp |= BIT(6); 9488c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 0x7c, bytetmp); 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); 9538c2ecf20Sopenharmony_ci bytetmp &= ~BIT(4); 9548c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_CR, 0x2ff); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci if (!mac_func_enable) { 9598c2ecf20Sopenharmony_ci if (!_rtl8821ae_llt_table_init(hw)) 9608c2ecf20Sopenharmony_ci return false; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); 9648c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /* Enable FW Beamformer Interrupt */ 9678c2ecf20Sopenharmony_ci bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3); 9688c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6)); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); 9718c2ecf20Sopenharmony_ci wordtmp &= 0xf; 9728c2ecf20Sopenharmony_ci wordtmp |= 0xF5B1; 9738c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); 9768c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); 9778c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); 9788c2ecf20Sopenharmony_ci /*low address*/ 9798c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BCNQ_DESA, 9808c2ecf20Sopenharmony_ci rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); 9818c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_MGQ_DESA, 9828c2ecf20Sopenharmony_ci rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); 9838c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_VOQ_DESA, 9848c2ecf20Sopenharmony_ci rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); 9858c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_VIQ_DESA, 9868c2ecf20Sopenharmony_ci rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); 9878c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BEQ_DESA, 9888c2ecf20Sopenharmony_ci rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); 9898c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BKQ_DESA, 9908c2ecf20Sopenharmony_ci rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); 9918c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HQ_DESA, 9928c2ecf20Sopenharmony_ci rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); 9938c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RX_DESA, 9948c2ecf20Sopenharmony_ci rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_INT_MIG, 0); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_MCUTST_1, 0); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3); 10038c2ecf20Sopenharmony_ci _rtl8821ae_gen_refresh_led_state(hw); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci return true; 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic void _rtl8821ae_hw_configure(struct ieee80211_hw *hw) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 10118c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 10128c2ecf20Sopenharmony_ci u32 reg_rrsr; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); 10178c2ecf20Sopenharmony_ci /* ARFB table 9 for 11ac 5G 2SS */ 10188c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000); 10198c2ecf20Sopenharmony_ci /* ARFB table 10 for 11ac 5G 1SS */ 10208c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000); 10218c2ecf20Sopenharmony_ci /* ARFB table 11 for 11ac 24G 1SS */ 10228c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR2, 0x00000015); 10238c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR2 + 4, 0x003ff000); 10248c2ecf20Sopenharmony_ci /* ARFB table 12 for 11ac 24G 1SS */ 10258c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015); 10268c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000); 10278c2ecf20Sopenharmony_ci /* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */ 10288c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00); 10298c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /*Set retry limit*/ 10328c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RL, 0x0707); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* Set Data / Response auto rate fallack retry count*/ 10358c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); 10368c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); 10378c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); 10388c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci rtlpci->reg_bcn_ctrl_val = 0x1d; 10418c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci /* TBTT prohibit hold time. Suggested by designer TimChen. */ 10448c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci /* AGGR_BK_TIME Reg51A 0x16 */ 10478c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci /*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ 10508c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80); 10538c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); 10548c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, 0x1F1F); 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic u16 _rtl8821ae_mdio_read(struct rtl_priv *rtlpriv, u8 addr) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci u16 ret = 0; 10608c2ecf20Sopenharmony_ci u8 tmp = 0, count = 0; 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6)); 10638c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); 10648c2ecf20Sopenharmony_ci count = 0; 10658c2ecf20Sopenharmony_ci while (tmp && count < 20) { 10668c2ecf20Sopenharmony_ci udelay(10); 10678c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); 10688c2ecf20Sopenharmony_ci count++; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci if (0 == tmp) 10718c2ecf20Sopenharmony_ci ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA); 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci return ret; 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_cistatic void _rtl8821ae_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci u8 tmp = 0, count = 0; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_MDIO_WDATA, data); 10818c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5)); 10828c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); 10838c2ecf20Sopenharmony_ci count = 0; 10848c2ecf20Sopenharmony_ci while (tmp && count < 20) { 10858c2ecf20Sopenharmony_ci udelay(10); 10868c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); 10878c2ecf20Sopenharmony_ci count++; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci} 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_cistatic u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) 10928c2ecf20Sopenharmony_ci{ 10938c2ecf20Sopenharmony_ci u16 read_addr = addr & 0xfffc; 10948c2ecf20Sopenharmony_ci u8 tmp = 0, count = 0, ret = 0; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr); 10978c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2); 10988c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); 10998c2ecf20Sopenharmony_ci count = 0; 11008c2ecf20Sopenharmony_ci while (tmp && count < 20) { 11018c2ecf20Sopenharmony_ci udelay(10); 11028c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); 11038c2ecf20Sopenharmony_ci count++; 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci if (0 == tmp) { 11068c2ecf20Sopenharmony_ci read_addr = REG_DBI_RDATA + addr % 4; 11078c2ecf20Sopenharmony_ci ret = rtl_read_byte(rtlpriv, read_addr); 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci return ret; 11108c2ecf20Sopenharmony_ci} 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_cistatic void _rtl8821ae_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci u8 tmp = 0, count = 0; 11158c2ecf20Sopenharmony_ci u16 write_addr, remainder = addr % 4; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci write_addr = REG_DBI_WDATA + remainder; 11188c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, write_addr, data); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci write_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12)); 11218c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_DBI_ADDR, write_addr); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); 11268c2ecf20Sopenharmony_ci count = 0; 11278c2ecf20Sopenharmony_ci while (tmp && count < 20) { 11288c2ecf20Sopenharmony_ci udelay(10); 11298c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); 11308c2ecf20Sopenharmony_ci count++; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci} 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_cistatic void _rtl8821ae_enable_aspm_back_door(struct ieee80211_hw *hw) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 11378c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 11388c2ecf20Sopenharmony_ci u8 tmp; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 11418c2ecf20Sopenharmony_ci if (_rtl8821ae_mdio_read(rtlpriv, 0x04) != 0x8544) 11428c2ecf20Sopenharmony_ci _rtl8821ae_mdio_write(rtlpriv, 0x04, 0x8544); 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci if (_rtl8821ae_mdio_read(rtlpriv, 0x0b) != 0x0070) 11458c2ecf20Sopenharmony_ci _rtl8821ae_mdio_write(rtlpriv, 0x0b, 0x0070); 11468c2ecf20Sopenharmony_ci } 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x70f); 11498c2ecf20Sopenharmony_ci _rtl8821ae_dbi_write(rtlpriv, 0x70f, tmp | BIT(7) | 11508c2ecf20Sopenharmony_ci ASPM_L1_LATENCY << 3); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x719); 11538c2ecf20Sopenharmony_ci _rtl8821ae_dbi_write(rtlpriv, 0x719, tmp | BIT(3) | BIT(4)); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 11568c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); 11578c2ecf20Sopenharmony_ci _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp|BIT(4)); 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_civoid rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 11648c2ecf20Sopenharmony_ci u8 sec_reg_value; 11658c2ecf20Sopenharmony_ci u8 tmp; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 11688c2ecf20Sopenharmony_ci "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", 11698c2ecf20Sopenharmony_ci rtlpriv->sec.pairwise_enc_algorithm, 11708c2ecf20Sopenharmony_ci rtlpriv->sec.group_enc_algorithm); 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { 11738c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 11748c2ecf20Sopenharmony_ci "not open hw encryption\n"); 11758c2ecf20Sopenharmony_ci return; 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (rtlpriv->sec.use_defaultkey) { 11818c2ecf20Sopenharmony_ci sec_reg_value |= SCR_TXUSEDK; 11828c2ecf20Sopenharmony_ci sec_reg_value |= SCR_RXUSEDK; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_CR + 1); 11888c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, tmp | BIT(1)); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 11918c2ecf20Sopenharmony_ci "The SECR-value %x\n", sec_reg_value); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci/* Static MacID Mapping (cf. Used in MacIdDoStaticMapping) ---------- */ 11978c2ecf20Sopenharmony_ci#define MAC_ID_STATIC_FOR_DEFAULT_PORT 0 11988c2ecf20Sopenharmony_ci#define MAC_ID_STATIC_FOR_BROADCAST_MULTICAST 1 11998c2ecf20Sopenharmony_ci#define MAC_ID_STATIC_FOR_BT_CLIENT_START 2 12008c2ecf20Sopenharmony_ci#define MAC_ID_STATIC_FOR_BT_CLIENT_END 3 12018c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */ 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_cistatic void rtl8821ae_macid_initialize_mediastatus(struct ieee80211_hw *hw) 12048c2ecf20Sopenharmony_ci{ 12058c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 12068c2ecf20Sopenharmony_ci u8 media_rpt[4] = {RT_MEDIA_CONNECT, 1, 12078c2ecf20Sopenharmony_ci MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, 12088c2ecf20Sopenharmony_ci MAC_ID_STATIC_FOR_BT_CLIENT_END}; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 12118c2ecf20Sopenharmony_ci HW_VAR_H2C_FW_MEDIASTATUSRPT, media_rpt); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 12148c2ecf20Sopenharmony_ci "Initialize MacId media status: from %d to %d\n", 12158c2ecf20Sopenharmony_ci MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, 12168c2ecf20Sopenharmony_ci MAC_ID_STATIC_FOR_BT_CLIENT_END); 12178c2ecf20Sopenharmony_ci} 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_cistatic bool _rtl8821ae_check_pcie_dma_hang(struct ieee80211_hw *hw) 12208c2ecf20Sopenharmony_ci{ 12218c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 12228c2ecf20Sopenharmony_ci u8 tmp; 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci /* write reg 0x350 Bit[26]=1. Enable debug port. */ 12258c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); 12268c2ecf20Sopenharmony_ci if (!(tmp & BIT(2))) { 12278c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2))); 12288c2ecf20Sopenharmony_ci mdelay(100); 12298c2ecf20Sopenharmony_ci } 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* read reg 0x350 Bit[25] if 1 : RX hang */ 12328c2ecf20Sopenharmony_ci /* read reg 0x350 Bit[24] if 1 : TX hang */ 12338c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); 12348c2ecf20Sopenharmony_ci if ((tmp & BIT(0)) || (tmp & BIT(1))) { 12358c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 12368c2ecf20Sopenharmony_ci "CheckPcieDMAHang8821AE(): true! Reset PCIE DMA!\n"); 12378c2ecf20Sopenharmony_ci return true; 12388c2ecf20Sopenharmony_ci } else { 12398c2ecf20Sopenharmony_ci return false; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci} 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic bool _rtl8821ae_reset_pcie_interface_dma(struct ieee80211_hw *hw, 12448c2ecf20Sopenharmony_ci bool mac_power_on, 12458c2ecf20Sopenharmony_ci bool in_watchdog) 12468c2ecf20Sopenharmony_ci{ 12478c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 12488c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 12498c2ecf20Sopenharmony_ci u8 tmp; 12508c2ecf20Sopenharmony_ci bool release_mac_rx_pause; 12518c2ecf20Sopenharmony_ci u8 backup_pcie_dma_pause; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci /* 1. Disable register write lock. 0x1c[1] = 0 */ 12568c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); 12578c2ecf20Sopenharmony_ci tmp &= ~(BIT(1)); 12588c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); 12598c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 12608c2ecf20Sopenharmony_ci /* write 0xCC bit[2] = 1'b1 */ 12618c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); 12628c2ecf20Sopenharmony_ci tmp |= BIT(2); 12638c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci /* 2. Check and pause TRX DMA */ 12678c2ecf20Sopenharmony_ci /* write 0x284 bit[18] = 1'b1 */ 12688c2ecf20Sopenharmony_ci /* write 0x301 = 0xFF */ 12698c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 12708c2ecf20Sopenharmony_ci if (tmp & BIT(2)) { 12718c2ecf20Sopenharmony_ci /* Already pause before the function for another purpose. */ 12728c2ecf20Sopenharmony_ci release_mac_rx_pause = false; 12738c2ecf20Sopenharmony_ci } else { 12748c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); 12758c2ecf20Sopenharmony_ci release_mac_rx_pause = true; 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); 12788c2ecf20Sopenharmony_ci if (backup_pcie_dma_pause != 0xFF) 12798c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci if (mac_power_on) { 12828c2ecf20Sopenharmony_ci /* 3. reset TRX function */ 12838c2ecf20Sopenharmony_ci /* write 0x100 = 0x00 */ 12848c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR, 0); 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci /* 4. Reset PCIe DMA. 0x3[0] = 0 */ 12888c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 12898c2ecf20Sopenharmony_ci tmp &= ~(BIT(0)); 12908c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* 5. Enable PCIe DMA. 0x3[0] = 1 */ 12938c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 12948c2ecf20Sopenharmony_ci tmp |= BIT(0); 12958c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (mac_power_on) { 12988c2ecf20Sopenharmony_ci /* 6. enable TRX function */ 12998c2ecf20Sopenharmony_ci /* write 0x100 = 0xFF */ 13008c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR, 0xFF); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /* We should init LLT & RQPN and 13038c2ecf20Sopenharmony_ci * prepare Tx/Rx descrptor address later 13048c2ecf20Sopenharmony_ci * because MAC function is reset.*/ 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci /* 7. Restore PCIe autoload down bit */ 13088c2ecf20Sopenharmony_ci /* 8812AE does not has the defination. */ 13098c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 13108c2ecf20Sopenharmony_ci /* write 0xF8 bit[17] = 1'b1 */ 13118c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); 13128c2ecf20Sopenharmony_ci tmp |= BIT(1); 13138c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci /* In MAC power on state, BB and RF maybe in ON state, 13178c2ecf20Sopenharmony_ci * if we release TRx DMA here. 13188c2ecf20Sopenharmony_ci * it will cause packets to be started to Tx/Rx, 13198c2ecf20Sopenharmony_ci * so we release Tx/Rx DMA later.*/ 13208c2ecf20Sopenharmony_ci if (!mac_power_on/* || in_watchdog*/) { 13218c2ecf20Sopenharmony_ci /* 8. release TRX DMA */ 13228c2ecf20Sopenharmony_ci /* write 0x284 bit[18] = 1'b0 */ 13238c2ecf20Sopenharmony_ci /* write 0x301 = 0x00 */ 13248c2ecf20Sopenharmony_ci if (release_mac_rx_pause) { 13258c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 13268c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, 13278c2ecf20Sopenharmony_ci tmp & (~BIT(2))); 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 13308c2ecf20Sopenharmony_ci backup_pcie_dma_pause); 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 13348c2ecf20Sopenharmony_ci /* 9. lock system register */ 13358c2ecf20Sopenharmony_ci /* write 0xCC bit[2] = 1'b0 */ 13368c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); 13378c2ecf20Sopenharmony_ci tmp &= ~(BIT(2)); 13388c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci return true; 13418c2ecf20Sopenharmony_ci} 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_cistatic void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw) 13448c2ecf20Sopenharmony_ci{ 13458c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 13468c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 13478c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); 13488c2ecf20Sopenharmony_ci u8 fw_reason = 0; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci fw_reason = rtl_read_byte(rtlpriv, REG_MCUTST_WOWLAN); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "WOL Read 0x1c7 = %02X\n", 13538c2ecf20Sopenharmony_ci fw_reason); 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci ppsc->wakeup_reason = 0; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci rtlhal->last_suspend_sec = ktime_get_real_seconds(); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci switch (fw_reason) { 13608c2ecf20Sopenharmony_ci case FW_WOW_V2_PTK_UPDATE_EVENT: 13618c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_PTK_UPDATE; 13628c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13638c2ecf20Sopenharmony_ci "It's a WOL PTK Key update event!\n"); 13648c2ecf20Sopenharmony_ci break; 13658c2ecf20Sopenharmony_ci case FW_WOW_V2_GTK_UPDATE_EVENT: 13668c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_GTK_UPDATE; 13678c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13688c2ecf20Sopenharmony_ci "It's a WOL GTK Key update event!\n"); 13698c2ecf20Sopenharmony_ci break; 13708c2ecf20Sopenharmony_ci case FW_WOW_V2_DISASSOC_EVENT: 13718c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_DISASSOC; 13728c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13738c2ecf20Sopenharmony_ci "It's a disassociation event!\n"); 13748c2ecf20Sopenharmony_ci break; 13758c2ecf20Sopenharmony_ci case FW_WOW_V2_DEAUTH_EVENT: 13768c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_DEAUTH; 13778c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13788c2ecf20Sopenharmony_ci "It's a deauth event!\n"); 13798c2ecf20Sopenharmony_ci break; 13808c2ecf20Sopenharmony_ci case FW_WOW_V2_FW_DISCONNECT_EVENT: 13818c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_AP_LOST; 13828c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13838c2ecf20Sopenharmony_ci "It's a Fw disconnect decision (AP lost) event!\n"); 13848c2ecf20Sopenharmony_ci break; 13858c2ecf20Sopenharmony_ci case FW_WOW_V2_MAGIC_PKT_EVENT: 13868c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_MAGIC_PKT; 13878c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13888c2ecf20Sopenharmony_ci "It's a magic packet event!\n"); 13898c2ecf20Sopenharmony_ci break; 13908c2ecf20Sopenharmony_ci case FW_WOW_V2_UNICAST_PKT_EVENT: 13918c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_UNICAST_PKT; 13928c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13938c2ecf20Sopenharmony_ci "It's an unicast packet event!\n"); 13948c2ecf20Sopenharmony_ci break; 13958c2ecf20Sopenharmony_ci case FW_WOW_V2_PATTERN_PKT_EVENT: 13968c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_PATTERN_PKT; 13978c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 13988c2ecf20Sopenharmony_ci "It's a pattern match event!\n"); 13998c2ecf20Sopenharmony_ci break; 14008c2ecf20Sopenharmony_ci case FW_WOW_V2_RTD3_SSID_MATCH_EVENT: 14018c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_RTD3_SSID_MATCH; 14028c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 14038c2ecf20Sopenharmony_ci "It's an RTD3 Ssid match event!\n"); 14048c2ecf20Sopenharmony_ci break; 14058c2ecf20Sopenharmony_ci case FW_WOW_V2_REALWOW_V2_WAKEUPPKT: 14068c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_WAKEUPPKT; 14078c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 14088c2ecf20Sopenharmony_ci "It's an RealWoW wake packet event!\n"); 14098c2ecf20Sopenharmony_ci break; 14108c2ecf20Sopenharmony_ci case FW_WOW_V2_REALWOW_V2_ACKLOST: 14118c2ecf20Sopenharmony_ci ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_ACKLOST; 14128c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 14138c2ecf20Sopenharmony_ci "It's an RealWoW ack lost event!\n"); 14148c2ecf20Sopenharmony_ci break; 14158c2ecf20Sopenharmony_ci default: 14168c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, 14178c2ecf20Sopenharmony_ci "WOL Read 0x1c7 = %02X, Unknown reason!\n", 14188c2ecf20Sopenharmony_ci fw_reason); 14198c2ecf20Sopenharmony_ci break; 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci} 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_cistatic void _rtl8821ae_init_trx_desc_hw_address(struct ieee80211_hw *hw) 14248c2ecf20Sopenharmony_ci{ 14258c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 14268c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci /*low address*/ 14298c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BCNQ_DESA, 14308c2ecf20Sopenharmony_ci rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); 14318c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_MGQ_DESA, 14328c2ecf20Sopenharmony_ci rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); 14338c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_VOQ_DESA, 14348c2ecf20Sopenharmony_ci rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); 14358c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_VIQ_DESA, 14368c2ecf20Sopenharmony_ci rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); 14378c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BEQ_DESA, 14388c2ecf20Sopenharmony_ci rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); 14398c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BKQ_DESA, 14408c2ecf20Sopenharmony_ci rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); 14418c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HQ_DESA, 14428c2ecf20Sopenharmony_ci rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); 14438c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RX_DESA, 14448c2ecf20Sopenharmony_ci rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); 14458c2ecf20Sopenharmony_ci} 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_cistatic bool _rtl8821ae_init_llt_table(struct ieee80211_hw *hw, u32 boundary) 14488c2ecf20Sopenharmony_ci{ 14498c2ecf20Sopenharmony_ci bool status = true; 14508c2ecf20Sopenharmony_ci u32 i; 14518c2ecf20Sopenharmony_ci u32 txpktbuf_bndy = boundary; 14528c2ecf20Sopenharmony_ci u32 last_entry_of_txpktbuf = LAST_ENTRY_OF_TX_PKT_BUFFER; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci for (i = 0 ; i < (txpktbuf_bndy - 1) ; i++) { 14558c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, i , i + 1); 14568c2ecf20Sopenharmony_ci if (!status) 14578c2ecf20Sopenharmony_ci return status; 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); 14618c2ecf20Sopenharmony_ci if (!status) 14628c2ecf20Sopenharmony_ci return status; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci for (i = txpktbuf_bndy ; i < last_entry_of_txpktbuf ; i++) { 14658c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, i, (i + 1)); 14668c2ecf20Sopenharmony_ci if (!status) 14678c2ecf20Sopenharmony_ci return status; 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci status = _rtl8821ae_llt_write(hw, last_entry_of_txpktbuf, 14718c2ecf20Sopenharmony_ci txpktbuf_bndy); 14728c2ecf20Sopenharmony_ci if (!status) 14738c2ecf20Sopenharmony_ci return status; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci return status; 14768c2ecf20Sopenharmony_ci} 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_cistatic bool _rtl8821ae_dynamic_rqpn(struct ieee80211_hw *hw, u32 boundary, 14798c2ecf20Sopenharmony_ci u16 npq_rqpn_value, u32 rqpn_val) 14808c2ecf20Sopenharmony_ci{ 14818c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 14828c2ecf20Sopenharmony_ci u8 tmp; 14838c2ecf20Sopenharmony_ci bool ret = true; 14848c2ecf20Sopenharmony_ci u16 count = 0, tmp16; 14858c2ecf20Sopenharmony_ci bool support_remote_wakeup; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, 14888c2ecf20Sopenharmony_ci (u8 *)(&support_remote_wakeup)); 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 14918c2ecf20Sopenharmony_ci "boundary=%#X, NPQ_RQPNValue=%#X, RQPNValue=%#X\n", 14928c2ecf20Sopenharmony_ci boundary, npq_rqpn_value, rqpn_val); 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci /* stop PCIe DMA 14958c2ecf20Sopenharmony_ci * 1. 0x301[7:0] = 0xFE */ 14968c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci /* wait TXFF empty 14998c2ecf20Sopenharmony_ci * 2. polling till 0x41A[15:0]=0x07FF */ 15008c2ecf20Sopenharmony_ci tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); 15018c2ecf20Sopenharmony_ci while ((tmp16 & 0x07FF) != 0x07FF) { 15028c2ecf20Sopenharmony_ci udelay(100); 15038c2ecf20Sopenharmony_ci tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); 15048c2ecf20Sopenharmony_ci count++; 15058c2ecf20Sopenharmony_ci if ((count % 200) == 0) { 15068c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 15078c2ecf20Sopenharmony_ci "Tx queue is not empty for 20ms!\n"); 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci if (count >= 1000) { 15108c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 15118c2ecf20Sopenharmony_ci "Wait for Tx FIFO empty timeout!\n"); 15128c2ecf20Sopenharmony_ci break; 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci /* TX pause 15178c2ecf20Sopenharmony_ci * 3. reg 0x522=0xFF */ 15188c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci /* Wait TX State Machine OK 15218c2ecf20Sopenharmony_ci * 4. polling till reg 0x5FB~0x5F8 = 0x00000000 for 50ms */ 15228c2ecf20Sopenharmony_ci count = 0; 15238c2ecf20Sopenharmony_ci while (rtl_read_byte(rtlpriv, REG_SCH_TXCMD) != 0) { 15248c2ecf20Sopenharmony_ci udelay(100); 15258c2ecf20Sopenharmony_ci count++; 15268c2ecf20Sopenharmony_ci if (count >= 500) { 15278c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 15288c2ecf20Sopenharmony_ci "Wait for TX State Machine ready timeout !!\n"); 15298c2ecf20Sopenharmony_ci break; 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci } 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci /* stop RX DMA path 15348c2ecf20Sopenharmony_ci * 5. 0x284[18] = 1 15358c2ecf20Sopenharmony_ci * 6. wait till 0x284[17] == 1 15368c2ecf20Sopenharmony_ci * wait RX DMA idle */ 15378c2ecf20Sopenharmony_ci count = 0; 15388c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 15398c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); 15408c2ecf20Sopenharmony_ci do { 15418c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 15428c2ecf20Sopenharmony_ci udelay(10); 15438c2ecf20Sopenharmony_ci count++; 15448c2ecf20Sopenharmony_ci } while (!(tmp & BIT(1)) && count < 100); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 15478c2ecf20Sopenharmony_ci "Wait until Rx DMA Idle. count=%d REG[0x286]=0x%x\n", 15488c2ecf20Sopenharmony_ci count, tmp); 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci /* reset BB 15518c2ecf20Sopenharmony_ci * 7. 0x02 [0] = 0 */ 15528c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); 15538c2ecf20Sopenharmony_ci tmp &= ~(BIT(0)); 15548c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmp); 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci /* Reset TRX MAC 15578c2ecf20Sopenharmony_ci * 8. 0x100 = 0x00 15588c2ecf20Sopenharmony_ci * Delay (1ms) */ 15598c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR, 0x00); 15608c2ecf20Sopenharmony_ci udelay(1000); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci /* Disable MAC Security Engine 15638c2ecf20Sopenharmony_ci * 9. 0x100 bit[9]=0 */ 15648c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_CR + 1); 15658c2ecf20Sopenharmony_ci tmp &= ~(BIT(1)); 15668c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, tmp); 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci /* To avoid DD-Tim Circuit hang 15698c2ecf20Sopenharmony_ci * 10. 0x553 bit[5]=1 */ 15708c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_DUAL_TSF_RST); 15718c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (tmp | BIT(5))); 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci /* Enable MAC Security Engine 15748c2ecf20Sopenharmony_ci * 11. 0x100 bit[9]=1 */ 15758c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_CR + 1); 15768c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(1))); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* Enable TRX MAC 15798c2ecf20Sopenharmony_ci * 12. 0x100 = 0xFF 15808c2ecf20Sopenharmony_ci * Delay (1ms) */ 15818c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR, 0xFF); 15828c2ecf20Sopenharmony_ci udelay(1000); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci /* Enable BB 15858c2ecf20Sopenharmony_ci * 13. 0x02 [0] = 1 */ 15868c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); 15878c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, (tmp | BIT(0))); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci /* beacon setting 15908c2ecf20Sopenharmony_ci * 14,15. set beacon head page (reg 0x209 and 0x424) */ 15918c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TDECTRL + 1, (u8)boundary); 15928c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, (u8)boundary); 15938c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, (u8)boundary); 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci /* 16. WMAC_LBK_BF_HD 0x45D[7:0] 15968c2ecf20Sopenharmony_ci * WMAC_LBK_BF_HD */ 15978c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, 15988c2ecf20Sopenharmony_ci (u8)boundary); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_TRXFF_BNDY, boundary); 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci /* init LLT 16038c2ecf20Sopenharmony_ci * 17. init LLT */ 16048c2ecf20Sopenharmony_ci if (!_rtl8821ae_init_llt_table(hw, boundary)) { 16058c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING, 16068c2ecf20Sopenharmony_ci "Failed to init LLT table!\n"); 16078c2ecf20Sopenharmony_ci return false; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci /* reallocate RQPN 16118c2ecf20Sopenharmony_ci * 18. reallocate RQPN and init LLT */ 16128c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RQPN_NPQ, npq_rqpn_value); 16138c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RQPN, rqpn_val); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci /* release Tx pause 16168c2ecf20Sopenharmony_ci * 19. 0x522=0x00 */ 16178c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci /* enable PCIE DMA 16208c2ecf20Sopenharmony_ci * 20. 0x301[7:0] = 0x00 16218c2ecf20Sopenharmony_ci * 21. 0x284[18] = 0 */ 16228c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); 16238c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 16248c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp&~BIT(2))); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "End.\n"); 16278c2ecf20Sopenharmony_ci return ret; 16288c2ecf20Sopenharmony_ci} 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_cistatic void _rtl8821ae_simple_initialize_adapter(struct ieee80211_hw *hw) 16318c2ecf20Sopenharmony_ci{ 16328c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16338c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 16348c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) 16378c2ecf20Sopenharmony_ci /* Re-download normal Fw. */ 16388c2ecf20Sopenharmony_ci rtl8821ae_set_fw_related_for_wowlan(hw, false); 16398c2ecf20Sopenharmony_ci#endif 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci /* Re-Initialize LLT table. */ 16428c2ecf20Sopenharmony_ci if (rtlhal->re_init_llt_table) { 16438c2ecf20Sopenharmony_ci u32 rqpn = 0x80e70808; 16448c2ecf20Sopenharmony_ci u8 rqpn_npq = 0, boundary = 0xF8; 16458c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 16468c2ecf20Sopenharmony_ci rqpn = 0x80e90808; 16478c2ecf20Sopenharmony_ci boundary = 0xFA; 16488c2ecf20Sopenharmony_ci } 16498c2ecf20Sopenharmony_ci if (_rtl8821ae_dynamic_rqpn(hw, boundary, rqpn_npq, rqpn)) 16508c2ecf20Sopenharmony_ci rtlhal->re_init_llt_table = false; 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci ppsc->rfpwr_state = ERFON; 16548c2ecf20Sopenharmony_ci} 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_cistatic void _rtl8821ae_enable_l1off(struct ieee80211_hw *hw) 16578c2ecf20Sopenharmony_ci{ 16588c2ecf20Sopenharmony_ci u8 tmp = 0; 16598c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x160); 16648c2ecf20Sopenharmony_ci if (!(tmp & (BIT(2) | BIT(3)))) { 16658c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER | COMP_INIT, DBG_LOUD, 16668c2ecf20Sopenharmony_ci "0x160(%#x)return!!\n", tmp); 16678c2ecf20Sopenharmony_ci return; 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci tmp = _rtl8821ae_mdio_read(rtlpriv, 0x1b); 16718c2ecf20Sopenharmony_ci _rtl8821ae_mdio_write(rtlpriv, 0x1b, (tmp | BIT(4))); 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); 16748c2ecf20Sopenharmony_ci _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp | BIT(5)); 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); 16778c2ecf20Sopenharmony_ci} 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_cistatic void _rtl8821ae_enable_ltr(struct ieee80211_hw *hw) 16808c2ecf20Sopenharmony_ci{ 16818c2ecf20Sopenharmony_ci u8 tmp = 0; 16828c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci /* Check 0x98[10] */ 16878c2ecf20Sopenharmony_ci tmp = _rtl8821ae_dbi_read(rtlpriv, 0x99); 16888c2ecf20Sopenharmony_ci if (!(tmp & BIT(2))) { 16898c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 16908c2ecf20Sopenharmony_ci "<---0x99(%#x) return!!\n", tmp); 16918c2ecf20Sopenharmony_ci return; 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci /* LTR idle latency, 0x90 for 144us */ 16958c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, 0x798, 0x88908890); 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci /* LTR active latency, 0x3c for 60us */ 16988c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, 0x79c, 0x883c883c); 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, 0x7a4); 17018c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(4))); 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, 0x7a4); 17048c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 0x7a4, (tmp & (~BIT(0)))); 17058c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(0))); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); 17088c2ecf20Sopenharmony_ci} 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_cistatic bool _rtl8821ae_wowlan_initialize_adapter(struct ieee80211_hw *hw) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 17138c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 17148c2ecf20Sopenharmony_ci bool init_finished = true; 17158c2ecf20Sopenharmony_ci u8 tmp = 0; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* Get Fw wake up reason. */ 17188c2ecf20Sopenharmony_ci _rtl8821ae_get_wakeup_reason(hw); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci /* Patch Pcie Rx DMA hang after S3/S4 several times. 17218c2ecf20Sopenharmony_ci * The root cause has not be found. */ 17228c2ecf20Sopenharmony_ci if (_rtl8821ae_check_pcie_dma_hang(hw)) 17238c2ecf20Sopenharmony_ci _rtl8821ae_reset_pcie_interface_dma(hw, true, false); 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci /* Prepare Tx/Rx Desc Hw address. */ 17268c2ecf20Sopenharmony_ci _rtl8821ae_init_trx_desc_hw_address(hw); 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci /* Release Pcie Interface Rx DMA to allow wake packet DMA. */ 17298c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); 17308c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Enable PCIE Rx DMA.\n"); 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci /* Check wake up event. 17338c2ecf20Sopenharmony_ci * We should check wake packet bit before disable wowlan by H2C or 17348c2ecf20Sopenharmony_ci * Fw will clear the bit. */ 17358c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_FTISR + 3); 17368c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 17378c2ecf20Sopenharmony_ci "Read REG_FTISR 0x13f = %#X\n", tmp); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci /* Set the WoWLAN related function control disable. */ 17408c2ecf20Sopenharmony_ci rtl8821ae_set_fw_wowlan_mode(hw, false); 17418c2ecf20Sopenharmony_ci rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 0); 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci if (rtlhal->hw_rof_enable) { 17448c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); 17458c2ecf20Sopenharmony_ci if (tmp & BIT(1)) { 17468c2ecf20Sopenharmony_ci /* Clear GPIO9 ISR */ 17478c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); 17488c2ecf20Sopenharmony_ci init_finished = false; 17498c2ecf20Sopenharmony_ci } else { 17508c2ecf20Sopenharmony_ci init_finished = true; 17518c2ecf20Sopenharmony_ci } 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci if (init_finished) { 17558c2ecf20Sopenharmony_ci _rtl8821ae_simple_initialize_adapter(hw); 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci /* Release Pcie Interface Tx DMA. */ 17588c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); 17598c2ecf20Sopenharmony_ci /* Release Pcie RX DMA */ 17608c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, 0x02); 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_CR + 1); 17638c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & (~BIT(0)))); 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci _rtl8821ae_enable_l1off(hw); 17668c2ecf20Sopenharmony_ci _rtl8821ae_enable_ltr(hw); 17678c2ecf20Sopenharmony_ci } 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci return init_finished; 17708c2ecf20Sopenharmony_ci} 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_cistatic void _rtl8812ae_bb8812_config_1t(struct ieee80211_hw *hw) 17738c2ecf20Sopenharmony_ci{ 17748c2ecf20Sopenharmony_ci /* BB OFDM RX Path_A */ 17758c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0x808, 0xff, 0x11); 17768c2ecf20Sopenharmony_ci /* BB OFDM TX Path_A */ 17778c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0x80c, MASKLWORD, 0x1111); 17788c2ecf20Sopenharmony_ci /* BB CCK R/Rx Path_A */ 17798c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0xa04, 0x0c000000, 0x0); 17808c2ecf20Sopenharmony_ci /* MCS support */ 17818c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0x8bc, 0xc0000060, 0x4); 17828c2ecf20Sopenharmony_ci /* RF Path_B HSSI OFF */ 17838c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0xe00, 0xf, 0x4); 17848c2ecf20Sopenharmony_ci /* RF Path_B Power Down */ 17858c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0xe90, MASKDWORD, 0); 17868c2ecf20Sopenharmony_ci /* ADDA Path_B OFF */ 17878c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0); 17888c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0xe64, MASKDWORD, 0); 17898c2ecf20Sopenharmony_ci} 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_cistatic void _rtl8821ae_poweroff_adapter(struct ieee80211_hw *hw) 17928c2ecf20Sopenharmony_ci{ 17938c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 17948c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 17958c2ecf20Sopenharmony_ci u8 u1b_tmp; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = false; 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 18008c2ecf20Sopenharmony_ci /* Combo (PCIe + USB) Card and PCIe-MF Card */ 18018c2ecf20Sopenharmony_ci /* 1. Run LPS WL RFOFF flow */ 18028c2ecf20Sopenharmony_ci /* rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 18038c2ecf20Sopenharmony_ci "=====>CardDisableRTL8812E,RTL8821A_NIC_LPS_ENTER_FLOW\n"); 18048c2ecf20Sopenharmony_ci */ 18058c2ecf20Sopenharmony_ci rtl_hal_pwrseqcmdparsing(rtlpriv, 18068c2ecf20Sopenharmony_ci PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, 18078c2ecf20Sopenharmony_ci PWR_INTF_PCI_MSK, RTL8821A_NIC_LPS_ENTER_FLOW); 18088c2ecf20Sopenharmony_ci } 18098c2ecf20Sopenharmony_ci /* 2. 0x1F[7:0] = 0 */ 18108c2ecf20Sopenharmony_ci /* turn off RF */ 18118c2ecf20Sopenharmony_ci /* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */ 18128c2ecf20Sopenharmony_ci if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && 18138c2ecf20Sopenharmony_ci rtlhal->fw_ready) { 18148c2ecf20Sopenharmony_ci rtl8821ae_firmware_selfreset(hw); 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci /* Reset MCU. Suggested by Filen. */ 18188c2ecf20Sopenharmony_ci u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); 18198c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci /* g. MCUFWDL 0x80[1:0]=0 */ 18228c2ecf20Sopenharmony_ci /* reset MCU ready status */ 18238c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 18268c2ecf20Sopenharmony_ci /* HW card disable configuration. */ 18278c2ecf20Sopenharmony_ci rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, 18288c2ecf20Sopenharmony_ci PWR_INTF_PCI_MSK, RTL8821A_NIC_DISABLE_FLOW); 18298c2ecf20Sopenharmony_ci } else { 18308c2ecf20Sopenharmony_ci /* HW card disable configuration. */ 18318c2ecf20Sopenharmony_ci rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, 18328c2ecf20Sopenharmony_ci PWR_INTF_PCI_MSK, RTL8812_NIC_DISABLE_FLOW); 18338c2ecf20Sopenharmony_ci } 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci /* Reset MCU IO Wrapper */ 18368c2ecf20Sopenharmony_ci u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 18378c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); 18388c2ecf20Sopenharmony_ci u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 18398c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ 18428c2ecf20Sopenharmony_ci /* lock ISO/CLK/Power control register */ 18438c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); 18448c2ecf20Sopenharmony_ci} 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ciint rtl8821ae_hw_init(struct ieee80211_hw *hw) 18478c2ecf20Sopenharmony_ci{ 18488c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 18498c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 18508c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 18518c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 18528c2ecf20Sopenharmony_ci bool rtstatus = true; 18538c2ecf20Sopenharmony_ci int err; 18548c2ecf20Sopenharmony_ci u8 tmp_u1b; 18558c2ecf20Sopenharmony_ci bool support_remote_wakeup; 18568c2ecf20Sopenharmony_ci u32 nav_upper = WIFI_NAV_UPPER_US; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci rtlhal->being_init_adapter = true; 18598c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, 18608c2ecf20Sopenharmony_ci (u8 *)(&support_remote_wakeup)); 18618c2ecf20Sopenharmony_ci rtlpriv->intf_ops->disable_aspm(hw); 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci /*YP wowlan not considered*/ 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci tmp_u1b = rtl_read_byte(rtlpriv, REG_CR); 18668c2ecf20Sopenharmony_ci if (tmp_u1b != 0 && tmp_u1b != 0xEA) { 18678c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = true; 18688c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 18698c2ecf20Sopenharmony_ci "MAC has already power on.\n"); 18708c2ecf20Sopenharmony_ci } else { 18718c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = false; 18728c2ecf20Sopenharmony_ci rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; 18738c2ecf20Sopenharmony_ci } 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci if (support_remote_wakeup && 18768c2ecf20Sopenharmony_ci rtlhal->wake_from_pnp_sleep && 18778c2ecf20Sopenharmony_ci rtlhal->mac_func_enable) { 18788c2ecf20Sopenharmony_ci if (_rtl8821ae_wowlan_initialize_adapter(hw)) { 18798c2ecf20Sopenharmony_ci rtlhal->being_init_adapter = false; 18808c2ecf20Sopenharmony_ci return 0; 18818c2ecf20Sopenharmony_ci } 18828c2ecf20Sopenharmony_ci } 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci if (_rtl8821ae_check_pcie_dma_hang(hw)) { 18858c2ecf20Sopenharmony_ci _rtl8821ae_reset_pcie_interface_dma(hw, 18868c2ecf20Sopenharmony_ci rtlhal->mac_func_enable, 18878c2ecf20Sopenharmony_ci false); 18888c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = false; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci /* Reset MAC/BB/RF status if it is not powered off 18928c2ecf20Sopenharmony_ci * before calling initialize Hw flow to prevent 18938c2ecf20Sopenharmony_ci * from interface and MAC status mismatch. 18948c2ecf20Sopenharmony_ci * 2013.06.21, by tynli. Suggested by SD1 JackieLau. */ 18958c2ecf20Sopenharmony_ci if (rtlhal->mac_func_enable) { 18968c2ecf20Sopenharmony_ci _rtl8821ae_poweroff_adapter(hw); 18978c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = false; 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci rtstatus = _rtl8821ae_init_mac(hw); 19018c2ecf20Sopenharmony_ci if (!rtstatus) { 19028c2ecf20Sopenharmony_ci pr_err("Init MAC failed\n"); 19038c2ecf20Sopenharmony_ci err = 1; 19048c2ecf20Sopenharmony_ci return err; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG); 19088c2ecf20Sopenharmony_ci tmp_u1b &= 0x7F; 19098c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b); 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci err = rtl8821ae_download_fw(hw, false); 19128c2ecf20Sopenharmony_ci if (err) { 19138c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, 19148c2ecf20Sopenharmony_ci "Failed to download FW. Init HW without FW now\n"); 19158c2ecf20Sopenharmony_ci err = 1; 19168c2ecf20Sopenharmony_ci rtlhal->fw_ready = false; 19178c2ecf20Sopenharmony_ci return err; 19188c2ecf20Sopenharmony_ci } else { 19198c2ecf20Sopenharmony_ci rtlhal->fw_ready = true; 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci ppsc->fw_current_inpsmode = false; 19228c2ecf20Sopenharmony_ci rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; 19238c2ecf20Sopenharmony_ci rtlhal->fw_clk_change_in_progress = false; 19248c2ecf20Sopenharmony_ci rtlhal->allow_sw_to_change_hwclc = false; 19258c2ecf20Sopenharmony_ci rtlhal->last_hmeboxnum = 0; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci /*SIC_Init(Adapter); 19288c2ecf20Sopenharmony_ci if(rtlhal->AMPDUBurstMode) 19298c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv,REG_AMPDU_BURST_MODE_8812, 0x7F);*/ 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci rtl8821ae_phy_mac_config(hw); 19328c2ecf20Sopenharmony_ci /* because last function modify RCR, so we update 19338c2ecf20Sopenharmony_ci * rcr var here, or TP will unstable for receive_config 19348c2ecf20Sopenharmony_ci * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx 19358c2ecf20Sopenharmony_ci * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 19368c2ecf20Sopenharmony_ci rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); 19378c2ecf20Sopenharmony_ci rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); 19388c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);*/ 19398c2ecf20Sopenharmony_ci rtl8821ae_phy_bb_config(hw); 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci rtl8821ae_phy_rf_config(hw); 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci if (rtlpriv->phy.rf_type == RF_1T1R && 19448c2ecf20Sopenharmony_ci rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 19458c2ecf20Sopenharmony_ci _rtl8812ae_bb8812_config_1t(hw); 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci _rtl8821ae_hw_configure(hw); 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ci rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_2_4G); 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci /*set wireless mode*/ 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci rtlhal->mac_func_enable = true; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci rtl_cam_reset_all_entry(hw); 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci rtl8821ae_enable_hw_security_config(hw); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci ppsc->rfpwr_state = ERFON; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); 19628c2ecf20Sopenharmony_ci _rtl8821ae_enable_aspm_back_door(hw); 19638c2ecf20Sopenharmony_ci rtlpriv->intf_ops->enable_aspm(hw); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE && 19668c2ecf20Sopenharmony_ci (rtlhal->rfe_type == 1 || rtlhal->rfe_type == 5)) 19678c2ecf20Sopenharmony_ci rtl_set_bbreg(hw, 0x900, 0x00000303, 0x0302); 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci rtl8821ae_bt_hw_init(hw); 19708c2ecf20Sopenharmony_ci rtlpriv->rtlhal.being_init_adapter = false; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_NAV_UPPER, (u8 *)&nav_upper); 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci /* rtl8821ae_dm_check_txpower_tracking(hw); */ 19758c2ecf20Sopenharmony_ci /* rtl8821ae_phy_lc_calibrate(hw); */ 19768c2ecf20Sopenharmony_ci if (support_remote_wakeup) 19778c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_WOW_CTRL, 0); 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci /* Release Rx DMA*/ 19808c2ecf20Sopenharmony_ci tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 19818c2ecf20Sopenharmony_ci if (tmp_u1b & BIT(2)) { 19828c2ecf20Sopenharmony_ci /* Release Rx DMA if needed*/ 19838c2ecf20Sopenharmony_ci tmp_u1b &= ~BIT(2); 19848c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b); 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci /* Release Tx/Rx PCIE DMA if*/ 19888c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0); 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_ci rtl8821ae_dm_init(hw); 19918c2ecf20Sopenharmony_ci rtl8821ae_macid_initialize_mediastatus(hw); 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "%s() <====\n", __func__); 19948c2ecf20Sopenharmony_ci return err; 19958c2ecf20Sopenharmony_ci} 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_cistatic enum version_8821ae _rtl8821ae_read_chip_version(struct ieee80211_hw *hw) 19988c2ecf20Sopenharmony_ci{ 19998c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 20008c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 20018c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 20028c2ecf20Sopenharmony_ci enum version_8821ae version = VERSION_UNKNOWN; 20038c2ecf20Sopenharmony_ci u32 value32; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); 20068c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20078c2ecf20Sopenharmony_ci "ReadChipVersion8812A 0xF0 = 0x%x\n", value32); 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 20108c2ecf20Sopenharmony_ci rtlphy->rf_type = RF_2T2R; 20118c2ecf20Sopenharmony_ci else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) 20128c2ecf20Sopenharmony_ci rtlphy->rf_type = RF_1T1R; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20158c2ecf20Sopenharmony_ci "RF_Type is %x!!\n", rtlphy->rf_type); 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci if (value32 & TRP_VAUX_EN) { 20188c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 20198c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_2T2R) 20208c2ecf20Sopenharmony_ci version = VERSION_TEST_CHIP_2T2R_8812; 20218c2ecf20Sopenharmony_ci else 20228c2ecf20Sopenharmony_ci version = VERSION_TEST_CHIP_1T1R_8812; 20238c2ecf20Sopenharmony_ci } else 20248c2ecf20Sopenharmony_ci version = VERSION_TEST_CHIP_8821; 20258c2ecf20Sopenharmony_ci } else { 20268c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 20278c2ecf20Sopenharmony_ci u32 rtl_id = ((value32 & CHIP_VER_RTL_MASK) >> 12) + 1; 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_2T2R) 20308c2ecf20Sopenharmony_ci version = 20318c2ecf20Sopenharmony_ci (enum version_8821ae)(CHIP_8812 20328c2ecf20Sopenharmony_ci | NORMAL_CHIP | 20338c2ecf20Sopenharmony_ci RF_TYPE_2T2R); 20348c2ecf20Sopenharmony_ci else 20358c2ecf20Sopenharmony_ci version = (enum version_8821ae)(CHIP_8812 20368c2ecf20Sopenharmony_ci | NORMAL_CHIP); 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci version = (enum version_8821ae)(version | (rtl_id << 12)); 20398c2ecf20Sopenharmony_ci } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 20408c2ecf20Sopenharmony_ci u32 rtl_id = value32 & CHIP_VER_RTL_MASK; 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci version = (enum version_8821ae)(CHIP_8821 20438c2ecf20Sopenharmony_ci | NORMAL_CHIP | rtl_id); 20448c2ecf20Sopenharmony_ci } 20458c2ecf20Sopenharmony_ci } 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 20488c2ecf20Sopenharmony_ci /*WL_HWROF_EN.*/ 20498c2ecf20Sopenharmony_ci value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); 20508c2ecf20Sopenharmony_ci rtlhal->hw_rof_enable = ((value32 & WL_HWROF_EN) ? 1 : 0); 20518c2ecf20Sopenharmony_ci } 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci switch (version) { 20548c2ecf20Sopenharmony_ci case VERSION_TEST_CHIP_1T1R_8812: 20558c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20568c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_TEST_CHIP_1T1R_8812\n"); 20578c2ecf20Sopenharmony_ci break; 20588c2ecf20Sopenharmony_ci case VERSION_TEST_CHIP_2T2R_8812: 20598c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20608c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_TEST_CHIP_2T2R_8812\n"); 20618c2ecf20Sopenharmony_ci break; 20628c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_1T1R_8812: 20638c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20648c2ecf20Sopenharmony_ci "Chip Version ID:VERSION_NORMAL_TSMC_CHIP_1T1R_8812\n"); 20658c2ecf20Sopenharmony_ci break; 20668c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_2T2R_8812: 20678c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20688c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812\n"); 20698c2ecf20Sopenharmony_ci break; 20708c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_1T1R_8812_C_CUT: 20718c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20728c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_1T1R_8812 C CUT\n"); 20738c2ecf20Sopenharmony_ci break; 20748c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_2T2R_8812_C_CUT: 20758c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20768c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812 C CUT\n"); 20778c2ecf20Sopenharmony_ci break; 20788c2ecf20Sopenharmony_ci case VERSION_TEST_CHIP_8821: 20798c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20808c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_TEST_CHIP_8821\n"); 20818c2ecf20Sopenharmony_ci break; 20828c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_8821: 20838c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20848c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 A CUT\n"); 20858c2ecf20Sopenharmony_ci break; 20868c2ecf20Sopenharmony_ci case VERSION_NORMAL_TSMC_CHIP_8821_B_CUT: 20878c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20888c2ecf20Sopenharmony_ci "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 B CUT\n"); 20898c2ecf20Sopenharmony_ci break; 20908c2ecf20Sopenharmony_ci default: 20918c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 20928c2ecf20Sopenharmony_ci "Chip Version ID: Unknown (0x%X)\n", version); 20938c2ecf20Sopenharmony_ci break; 20948c2ecf20Sopenharmony_ci } 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci return version; 20978c2ecf20Sopenharmony_ci} 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_cistatic int _rtl8821ae_set_media_status(struct ieee80211_hw *hw, 21008c2ecf20Sopenharmony_ci enum nl80211_iftype type) 21018c2ecf20Sopenharmony_ci{ 21028c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 21038c2ecf20Sopenharmony_ci u8 bt_msr = rtl_read_byte(rtlpriv, MSR); 21048c2ecf20Sopenharmony_ci enum led_ctl_mode ledaction = LED_CTL_NO_LINK; 21058c2ecf20Sopenharmony_ci bt_msr &= 0xfc; 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0); 21088c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_BEACON, DBG_LOUD, 21098c2ecf20Sopenharmony_ci "clear 0x550 when set HW_VAR_MEDIA_STATUS\n"); 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci if (type == NL80211_IFTYPE_UNSPECIFIED || 21128c2ecf20Sopenharmony_ci type == NL80211_IFTYPE_STATION) { 21138c2ecf20Sopenharmony_ci _rtl8821ae_stop_tx_beacon(hw); 21148c2ecf20Sopenharmony_ci _rtl8821ae_enable_bcn_sub_func(hw); 21158c2ecf20Sopenharmony_ci } else if (type == NL80211_IFTYPE_ADHOC || 21168c2ecf20Sopenharmony_ci type == NL80211_IFTYPE_AP) { 21178c2ecf20Sopenharmony_ci _rtl8821ae_resume_tx_beacon(hw); 21188c2ecf20Sopenharmony_ci _rtl8821ae_disable_bcn_sub_func(hw); 21198c2ecf20Sopenharmony_ci } else { 21208c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, 21218c2ecf20Sopenharmony_ci "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", 21228c2ecf20Sopenharmony_ci type); 21238c2ecf20Sopenharmony_ci } 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci switch (type) { 21268c2ecf20Sopenharmony_ci case NL80211_IFTYPE_UNSPECIFIED: 21278c2ecf20Sopenharmony_ci bt_msr |= MSR_NOLINK; 21288c2ecf20Sopenharmony_ci ledaction = LED_CTL_LINK; 21298c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, 21308c2ecf20Sopenharmony_ci "Set Network type to NO LINK!\n"); 21318c2ecf20Sopenharmony_ci break; 21328c2ecf20Sopenharmony_ci case NL80211_IFTYPE_ADHOC: 21338c2ecf20Sopenharmony_ci bt_msr |= MSR_ADHOC; 21348c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, 21358c2ecf20Sopenharmony_ci "Set Network type to Ad Hoc!\n"); 21368c2ecf20Sopenharmony_ci break; 21378c2ecf20Sopenharmony_ci case NL80211_IFTYPE_STATION: 21388c2ecf20Sopenharmony_ci bt_msr |= MSR_INFRA; 21398c2ecf20Sopenharmony_ci ledaction = LED_CTL_LINK; 21408c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, 21418c2ecf20Sopenharmony_ci "Set Network type to STA!\n"); 21428c2ecf20Sopenharmony_ci break; 21438c2ecf20Sopenharmony_ci case NL80211_IFTYPE_AP: 21448c2ecf20Sopenharmony_ci bt_msr |= MSR_AP; 21458c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, 21468c2ecf20Sopenharmony_ci "Set Network type to AP!\n"); 21478c2ecf20Sopenharmony_ci break; 21488c2ecf20Sopenharmony_ci default: 21498c2ecf20Sopenharmony_ci pr_err("Network type %d not support!\n", type); 21508c2ecf20Sopenharmony_ci return 1; 21518c2ecf20Sopenharmony_ci } 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, MSR, bt_msr); 21548c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->led_control(hw, ledaction); 21558c2ecf20Sopenharmony_ci if ((bt_msr & MSR_MASK) == MSR_AP) 21568c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); 21578c2ecf20Sopenharmony_ci else 21588c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci return 0; 21618c2ecf20Sopenharmony_ci} 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_civoid rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) 21648c2ecf20Sopenharmony_ci{ 21658c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 21668c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 21678c2ecf20Sopenharmony_ci u32 reg_rcr = rtlpci->receive_config; 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci if (rtlpriv->psc.rfpwr_state != ERFON) 21708c2ecf20Sopenharmony_ci return; 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci if (check_bssid) { 21738c2ecf20Sopenharmony_ci reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); 21748c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, 21758c2ecf20Sopenharmony_ci (u8 *)(®_rcr)); 21768c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); 21778c2ecf20Sopenharmony_ci } else if (!check_bssid) { 21788c2ecf20Sopenharmony_ci reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); 21798c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); 21808c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 21818c2ecf20Sopenharmony_ci HW_VAR_RCR, (u8 *)(®_rcr)); 21828c2ecf20Sopenharmony_ci } 21838c2ecf20Sopenharmony_ci} 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ciint rtl8821ae_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) 21868c2ecf20Sopenharmony_ci{ 21878c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "%s!\n", __func__); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci if (_rtl8821ae_set_media_status(hw, type)) 21928c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { 21958c2ecf20Sopenharmony_ci if (type != NL80211_IFTYPE_AP) 21968c2ecf20Sopenharmony_ci rtl8821ae_set_check_bssid(hw, true); 21978c2ecf20Sopenharmony_ci } else { 21988c2ecf20Sopenharmony_ci rtl8821ae_set_check_bssid(hw, false); 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci return 0; 22028c2ecf20Sopenharmony_ci} 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ 22058c2ecf20Sopenharmony_civoid rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci) 22068c2ecf20Sopenharmony_ci{ 22078c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22088c2ecf20Sopenharmony_ci rtl8821ae_dm_init_edca_turbo(hw); 22098c2ecf20Sopenharmony_ci switch (aci) { 22108c2ecf20Sopenharmony_ci case AC1_BK: 22118c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); 22128c2ecf20Sopenharmony_ci break; 22138c2ecf20Sopenharmony_ci case AC0_BE: 22148c2ecf20Sopenharmony_ci /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ 22158c2ecf20Sopenharmony_ci break; 22168c2ecf20Sopenharmony_ci case AC2_VI: 22178c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); 22188c2ecf20Sopenharmony_ci break; 22198c2ecf20Sopenharmony_ci case AC3_VO: 22208c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); 22218c2ecf20Sopenharmony_ci break; 22228c2ecf20Sopenharmony_ci default: 22238c2ecf20Sopenharmony_ci WARN_ONCE(true, "rtl8821ae: invalid aci: %d !\n", aci); 22248c2ecf20Sopenharmony_ci break; 22258c2ecf20Sopenharmony_ci } 22268c2ecf20Sopenharmony_ci} 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_cistatic void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw) 22298c2ecf20Sopenharmony_ci{ 22308c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22318c2ecf20Sopenharmony_ci u32 tmp = rtl_read_dword(rtlpriv, REG_HISR); 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HISR, tmp); 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci tmp = rtl_read_dword(rtlpriv, REG_HISRE); 22368c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HISRE, tmp); 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci tmp = rtl_read_dword(rtlpriv, REG_HSISR); 22398c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HSISR, tmp); 22408c2ecf20Sopenharmony_ci} 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_civoid rtl8821ae_enable_interrupt(struct ieee80211_hw *hw) 22438c2ecf20Sopenharmony_ci{ 22448c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22458c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci if (rtlpci->int_clear) 22488c2ecf20Sopenharmony_ci rtl8821ae_clear_interrupt(hw);/*clear it here first*/ 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); 22518c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); 22528c2ecf20Sopenharmony_ci rtlpci->irq_enabled = true; 22538c2ecf20Sopenharmony_ci /* there are some C2H CMDs have been sent before 22548c2ecf20Sopenharmony_ci system interrupt is enabled, e.g., C2H, CPWM. 22558c2ecf20Sopenharmony_ci *So we need to clear all C2H events that FW has 22568c2ecf20Sopenharmony_ci notified, otherwise FW won't schedule any commands anymore. 22578c2ecf20Sopenharmony_ci */ 22588c2ecf20Sopenharmony_ci /* rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); */ 22598c2ecf20Sopenharmony_ci /*enable system interrupt*/ 22608c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); 22618c2ecf20Sopenharmony_ci} 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_civoid rtl8821ae_disable_interrupt(struct ieee80211_hw *hw) 22648c2ecf20Sopenharmony_ci{ 22658c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22668c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); 22698c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); 22708c2ecf20Sopenharmony_ci rtlpci->irq_enabled = false; 22718c2ecf20Sopenharmony_ci /*synchronize_irq(rtlpci->pdev->irq);*/ 22728c2ecf20Sopenharmony_ci} 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_cistatic void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw) 22758c2ecf20Sopenharmony_ci{ 22768c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22778c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 22788c2ecf20Sopenharmony_ci u16 cap_hdr; 22798c2ecf20Sopenharmony_ci u8 cap_pointer; 22808c2ecf20Sopenharmony_ci u8 cap_id = 0xff; 22818c2ecf20Sopenharmony_ci u8 pmcs_reg; 22828c2ecf20Sopenharmony_ci u8 cnt = 0; 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci /* Get the Capability pointer first, 22858c2ecf20Sopenharmony_ci * the Capability Pointer is located at 22868c2ecf20Sopenharmony_ci * offset 0x34 from the Function Header */ 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci pci_read_config_byte(rtlpci->pdev, 0x34, &cap_pointer); 22898c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 22908c2ecf20Sopenharmony_ci "PCI configuration 0x34 = 0x%2x\n", cap_pointer); 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci do { 22938c2ecf20Sopenharmony_ci pci_read_config_word(rtlpci->pdev, cap_pointer, &cap_hdr); 22948c2ecf20Sopenharmony_ci cap_id = cap_hdr & 0xFF; 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 22978c2ecf20Sopenharmony_ci "in pci configuration, cap_pointer%x = %x\n", 22988c2ecf20Sopenharmony_ci cap_pointer, cap_id); 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci if (cap_id == 0x01) { 23018c2ecf20Sopenharmony_ci break; 23028c2ecf20Sopenharmony_ci } else { 23038c2ecf20Sopenharmony_ci /* point to next Capability */ 23048c2ecf20Sopenharmony_ci cap_pointer = (cap_hdr >> 8) & 0xFF; 23058c2ecf20Sopenharmony_ci /* 0: end of pci capability, 0xff: invalid value */ 23068c2ecf20Sopenharmony_ci if (cap_pointer == 0x00 || cap_pointer == 0xff) { 23078c2ecf20Sopenharmony_ci cap_id = 0xff; 23088c2ecf20Sopenharmony_ci break; 23098c2ecf20Sopenharmony_ci } 23108c2ecf20Sopenharmony_ci } 23118c2ecf20Sopenharmony_ci } while (cnt++ < 200); 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci if (cap_id == 0x01) { 23148c2ecf20Sopenharmony_ci /* Get the PM CSR (Control/Status Register), 23158c2ecf20Sopenharmony_ci * The PME_Status is located at PM Capatibility offset 5, bit 7 23168c2ecf20Sopenharmony_ci */ 23178c2ecf20Sopenharmony_ci pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg); 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci if (pmcs_reg & BIT(7)) { 23208c2ecf20Sopenharmony_ci /* PME event occured, clear the PM_Status by write 1 */ 23218c2ecf20Sopenharmony_ci pmcs_reg = pmcs_reg | BIT(7); 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci pci_write_config_byte(rtlpci->pdev, cap_pointer + 5, 23248c2ecf20Sopenharmony_ci pmcs_reg); 23258c2ecf20Sopenharmony_ci /* Read it back to check */ 23268c2ecf20Sopenharmony_ci pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, 23278c2ecf20Sopenharmony_ci &pmcs_reg); 23288c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 23298c2ecf20Sopenharmony_ci "Clear PME status 0x%2x to 0x%2x\n", 23308c2ecf20Sopenharmony_ci cap_pointer + 5, pmcs_reg); 23318c2ecf20Sopenharmony_ci } else { 23328c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 23338c2ecf20Sopenharmony_ci "PME status(0x%2x) = 0x%2x\n", 23348c2ecf20Sopenharmony_ci cap_pointer + 5, pmcs_reg); 23358c2ecf20Sopenharmony_ci } 23368c2ecf20Sopenharmony_ci } else { 23378c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING, 23388c2ecf20Sopenharmony_ci "Cannot find PME Capability\n"); 23398c2ecf20Sopenharmony_ci } 23408c2ecf20Sopenharmony_ci} 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_civoid rtl8821ae_card_disable(struct ieee80211_hw *hw) 23438c2ecf20Sopenharmony_ci{ 23448c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 23458c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 23468c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); 23478c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtlpriv); 23488c2ecf20Sopenharmony_ci enum nl80211_iftype opmode; 23498c2ecf20Sopenharmony_ci bool support_remote_wakeup; 23508c2ecf20Sopenharmony_ci u8 tmp; 23518c2ecf20Sopenharmony_ci u32 count = 0; 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, 23548c2ecf20Sopenharmony_ci (u8 *)(&support_remote_wakeup)); 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci if (!(support_remote_wakeup && mac->opmode == NL80211_IFTYPE_STATION) 23598c2ecf20Sopenharmony_ci || !rtlhal->enter_pnp_sleep) { 23608c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Normal Power off\n"); 23618c2ecf20Sopenharmony_ci mac->link_state = MAC80211_NOLINK; 23628c2ecf20Sopenharmony_ci opmode = NL80211_IFTYPE_UNSPECIFIED; 23638c2ecf20Sopenharmony_ci _rtl8821ae_set_media_status(hw, opmode); 23648c2ecf20Sopenharmony_ci _rtl8821ae_poweroff_adapter(hw); 23658c2ecf20Sopenharmony_ci } else { 23668c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Wowlan Supported.\n"); 23678c2ecf20Sopenharmony_ci /* 3 <1> Prepare for configuring wowlan related infomations */ 23688c2ecf20Sopenharmony_ci /* Clear Fw WoWLAN event. */ 23698c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_MCUTST_WOWLAN, 0x0); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) 23728c2ecf20Sopenharmony_ci rtl8821ae_set_fw_related_for_wowlan(hw, true); 23738c2ecf20Sopenharmony_ci#endif 23748c2ecf20Sopenharmony_ci /* Dynamically adjust Tx packet boundary 23758c2ecf20Sopenharmony_ci * for download reserved page packet. 23768c2ecf20Sopenharmony_ci * reserve 30 pages for rsvd page */ 23778c2ecf20Sopenharmony_ci if (_rtl8821ae_dynamic_rqpn(hw, 0xE0, 0x3, 0x80c20d0d)) 23788c2ecf20Sopenharmony_ci rtlhal->re_init_llt_table = true; 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci /* 3 <2> Set Fw releted H2C cmd. */ 23818c2ecf20Sopenharmony_ci 23828c2ecf20Sopenharmony_ci /* Set WoWLAN related security information. */ 23838c2ecf20Sopenharmony_ci rtl8821ae_set_fw_global_info_cmd(hw); 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci _rtl8821ae_download_rsvd_page(hw, true); 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci /* Just enable AOAC related functions when we connect to AP. */ 23888c2ecf20Sopenharmony_ci printk("mac->link_state = %d\n", mac->link_state); 23898c2ecf20Sopenharmony_ci if (mac->link_state >= MAC80211_LINKED && 23908c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_STATION) { 23918c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); 23928c2ecf20Sopenharmony_ci rtl8821ae_set_fw_media_status_rpt_cmd(hw, 23938c2ecf20Sopenharmony_ci RT_MEDIA_CONNECT); 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci rtl8821ae_set_fw_wowlan_mode(hw, true); 23968c2ecf20Sopenharmony_ci /* Enable Fw Keep alive mechanism. */ 23978c2ecf20Sopenharmony_ci rtl8821ae_set_fw_keep_alive_cmd(hw, true); 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci /* Enable disconnect decision control. */ 24008c2ecf20Sopenharmony_ci rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(hw, true); 24018c2ecf20Sopenharmony_ci } 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci /* 3 <3> Hw Configutations */ 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci /* Wait untill Rx DMA Finished before host sleep. 24068c2ecf20Sopenharmony_ci * FW Pause Rx DMA may happens when received packet doing dma. 24078c2ecf20Sopenharmony_ci */ 24088c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, BIT(2)); 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 24118c2ecf20Sopenharmony_ci count = 0; 24128c2ecf20Sopenharmony_ci while (!(tmp & BIT(1)) && (count++ < 100)) { 24138c2ecf20Sopenharmony_ci udelay(10); 24148c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); 24158c2ecf20Sopenharmony_ci } 24168c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 24178c2ecf20Sopenharmony_ci "Wait Rx DMA Finished before host sleep. count=%d\n", 24188c2ecf20Sopenharmony_ci count); 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci /* reset trx ring */ 24218c2ecf20Sopenharmony_ci rtlpriv->intf_ops->reset_trx_ring(hw); 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x0); 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci _rtl8821ae_clear_pci_pme_status(hw); 24268c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); 24278c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_SYS_CLKR, tmp | BIT(3)); 24288c2ecf20Sopenharmony_ci /* prevent 8051 to be reset by PERST */ 24298c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x20); 24308c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x60); 24318c2ecf20Sopenharmony_ci } 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci if (rtlpriv->rtlhal.driver_is_goingto_unload || 24348c2ecf20Sopenharmony_ci ppsc->rfoff_reason > RF_CHANGE_BY_PS) 24358c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); 24368c2ecf20Sopenharmony_ci /* For wowlan+LPS+32k. */ 24378c2ecf20Sopenharmony_ci if (support_remote_wakeup && rtlhal->enter_pnp_sleep) { 24388c2ecf20Sopenharmony_ci /* Set the WoWLAN related function control enable. 24398c2ecf20Sopenharmony_ci * It should be the last H2C cmd in the WoWLAN flow. */ 24408c2ecf20Sopenharmony_ci rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 1); 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci /* Stop Pcie Interface Tx DMA. */ 24438c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); 24448c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Stop PCIE Tx DMA.\n"); 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci /* Wait for TxDMA idle. */ 24478c2ecf20Sopenharmony_ci count = 0; 24488c2ecf20Sopenharmony_ci do { 24498c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG); 24508c2ecf20Sopenharmony_ci udelay(10); 24518c2ecf20Sopenharmony_ci count++; 24528c2ecf20Sopenharmony_ci } while ((tmp != 0) && (count < 100)); 24538c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 24548c2ecf20Sopenharmony_ci "Wait Tx DMA Finished before host sleep. count=%d\n", 24558c2ecf20Sopenharmony_ci count); 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci if (rtlhal->hw_rof_enable) { 24588c2ecf20Sopenharmony_ci printk("hw_rof_enable\n"); 24598c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); 24608c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ci } 24638c2ecf20Sopenharmony_ci /* after power off we should do iqk again */ 24648c2ecf20Sopenharmony_ci rtlpriv->phy.iqk_initialized = false; 24658c2ecf20Sopenharmony_ci} 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_civoid rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw, 24688c2ecf20Sopenharmony_ci struct rtl_int *intvec) 24698c2ecf20Sopenharmony_ci{ 24708c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 24718c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci intvec->inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; 24748c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, ISR, intvec->inta); 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci intvec->intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; 24778c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_HISRE, intvec->intb); 24788c2ecf20Sopenharmony_ci} 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_civoid rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw) 24818c2ecf20Sopenharmony_ci{ 24828c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 24838c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 24848c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 24858c2ecf20Sopenharmony_ci u16 bcn_interval, atim_window; 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci bcn_interval = mac->beacon_interval; 24888c2ecf20Sopenharmony_ci atim_window = 2; /*FIX MERGE */ 24898c2ecf20Sopenharmony_ci rtl8821ae_disable_interrupt(hw); 24908c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); 24918c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); 24928c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); 24938c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); 24948c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); 24958c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, 0x606, 0x30); 24968c2ecf20Sopenharmony_ci rtlpci->reg_bcn_ctrl_val |= BIT(3); 24978c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); 24988c2ecf20Sopenharmony_ci rtl8821ae_enable_interrupt(hw); 24998c2ecf20Sopenharmony_ci} 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_civoid rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw) 25028c2ecf20Sopenharmony_ci{ 25038c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 25048c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 25058c2ecf20Sopenharmony_ci u16 bcn_interval = mac->beacon_interval; 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_BEACON, DBG_DMESG, 25088c2ecf20Sopenharmony_ci "beacon_interval:%d\n", bcn_interval); 25098c2ecf20Sopenharmony_ci rtl8821ae_disable_interrupt(hw); 25108c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); 25118c2ecf20Sopenharmony_ci rtl8821ae_enable_interrupt(hw); 25128c2ecf20Sopenharmony_ci} 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_civoid rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw, 25158c2ecf20Sopenharmony_ci u32 add_msr, u32 rm_msr) 25168c2ecf20Sopenharmony_ci{ 25178c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 25188c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INTR, DBG_LOUD, 25218c2ecf20Sopenharmony_ci "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ci if (add_msr) 25248c2ecf20Sopenharmony_ci rtlpci->irq_mask[0] |= add_msr; 25258c2ecf20Sopenharmony_ci if (rm_msr) 25268c2ecf20Sopenharmony_ci rtlpci->irq_mask[0] &= (~rm_msr); 25278c2ecf20Sopenharmony_ci rtl8821ae_disable_interrupt(hw); 25288c2ecf20Sopenharmony_ci rtl8821ae_enable_interrupt(hw); 25298c2ecf20Sopenharmony_ci} 25308c2ecf20Sopenharmony_ci 25318c2ecf20Sopenharmony_cistatic u8 _rtl8821ae_get_chnl_group(u8 chnl) 25328c2ecf20Sopenharmony_ci{ 25338c2ecf20Sopenharmony_ci u8 group = 0; 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci if (chnl <= 14) { 25368c2ecf20Sopenharmony_ci if (1 <= chnl && chnl <= 2) 25378c2ecf20Sopenharmony_ci group = 0; 25388c2ecf20Sopenharmony_ci else if (3 <= chnl && chnl <= 5) 25398c2ecf20Sopenharmony_ci group = 1; 25408c2ecf20Sopenharmony_ci else if (6 <= chnl && chnl <= 8) 25418c2ecf20Sopenharmony_ci group = 2; 25428c2ecf20Sopenharmony_ci else if (9 <= chnl && chnl <= 11) 25438c2ecf20Sopenharmony_ci group = 3; 25448c2ecf20Sopenharmony_ci else /*if (12 <= chnl && chnl <= 14)*/ 25458c2ecf20Sopenharmony_ci group = 4; 25468c2ecf20Sopenharmony_ci } else { 25478c2ecf20Sopenharmony_ci if (36 <= chnl && chnl <= 42) 25488c2ecf20Sopenharmony_ci group = 0; 25498c2ecf20Sopenharmony_ci else if (44 <= chnl && chnl <= 48) 25508c2ecf20Sopenharmony_ci group = 1; 25518c2ecf20Sopenharmony_ci else if (50 <= chnl && chnl <= 58) 25528c2ecf20Sopenharmony_ci group = 2; 25538c2ecf20Sopenharmony_ci else if (60 <= chnl && chnl <= 64) 25548c2ecf20Sopenharmony_ci group = 3; 25558c2ecf20Sopenharmony_ci else if (100 <= chnl && chnl <= 106) 25568c2ecf20Sopenharmony_ci group = 4; 25578c2ecf20Sopenharmony_ci else if (108 <= chnl && chnl <= 114) 25588c2ecf20Sopenharmony_ci group = 5; 25598c2ecf20Sopenharmony_ci else if (116 <= chnl && chnl <= 122) 25608c2ecf20Sopenharmony_ci group = 6; 25618c2ecf20Sopenharmony_ci else if (124 <= chnl && chnl <= 130) 25628c2ecf20Sopenharmony_ci group = 7; 25638c2ecf20Sopenharmony_ci else if (132 <= chnl && chnl <= 138) 25648c2ecf20Sopenharmony_ci group = 8; 25658c2ecf20Sopenharmony_ci else if (140 <= chnl && chnl <= 144) 25668c2ecf20Sopenharmony_ci group = 9; 25678c2ecf20Sopenharmony_ci else if (149 <= chnl && chnl <= 155) 25688c2ecf20Sopenharmony_ci group = 10; 25698c2ecf20Sopenharmony_ci else if (157 <= chnl && chnl <= 161) 25708c2ecf20Sopenharmony_ci group = 11; 25718c2ecf20Sopenharmony_ci else if (165 <= chnl && chnl <= 171) 25728c2ecf20Sopenharmony_ci group = 12; 25738c2ecf20Sopenharmony_ci else if (173 <= chnl && chnl <= 177) 25748c2ecf20Sopenharmony_ci group = 13; 25758c2ecf20Sopenharmony_ci else 25768c2ecf20Sopenharmony_ci WARN_ONCE(true, 25778c2ecf20Sopenharmony_ci "rtl8821ae: 5G, Channel %d in Group not found\n", 25788c2ecf20Sopenharmony_ci chnl); 25798c2ecf20Sopenharmony_ci } 25808c2ecf20Sopenharmony_ci return group; 25818c2ecf20Sopenharmony_ci} 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw, 25848c2ecf20Sopenharmony_ci struct txpower_info_2g *pwrinfo24g, 25858c2ecf20Sopenharmony_ci struct txpower_info_5g *pwrinfo5g, 25868c2ecf20Sopenharmony_ci bool autoload_fail, 25878c2ecf20Sopenharmony_ci u8 *hwinfo) 25888c2ecf20Sopenharmony_ci{ 25898c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 25908c2ecf20Sopenharmony_ci u32 rfpath, eeaddr = EEPROM_TX_PWR_INX, group, txcount = 0; 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 25938c2ecf20Sopenharmony_ci "hal_ReadPowerValueFromPROM8821ae(): hwinfo[0x%x]=0x%x\n", 25948c2ecf20Sopenharmony_ci (eeaddr + 1), hwinfo[eeaddr + 1]); 25958c2ecf20Sopenharmony_ci if (hwinfo[eeaddr + 1] == 0xFF) /*YJ,add,120316*/ 25968c2ecf20Sopenharmony_ci autoload_fail = true; 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ci if (autoload_fail) { 25998c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 26008c2ecf20Sopenharmony_ci "auto load fail : Use Default value!\n"); 26018c2ecf20Sopenharmony_ci for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { 26028c2ecf20Sopenharmony_ci /*2.4G default value*/ 26038c2ecf20Sopenharmony_ci for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { 26048c2ecf20Sopenharmony_ci pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; 26058c2ecf20Sopenharmony_ci pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; 26068c2ecf20Sopenharmony_ci } 26078c2ecf20Sopenharmony_ci for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { 26088c2ecf20Sopenharmony_ci if (txcount == 0) { 26098c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][0] = 0x02; 26108c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; 26118c2ecf20Sopenharmony_ci } else { 26128c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][txcount] = 0xFE; 26138c2ecf20Sopenharmony_ci pwrinfo24g->bw40_diff[rfpath][txcount] = 0xFE; 26148c2ecf20Sopenharmony_ci pwrinfo24g->cck_diff[rfpath][txcount] = 0xFE; 26158c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][txcount] = 0xFE; 26168c2ecf20Sopenharmony_ci } 26178c2ecf20Sopenharmony_ci } 26188c2ecf20Sopenharmony_ci /*5G default value*/ 26198c2ecf20Sopenharmony_ci for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) 26208c2ecf20Sopenharmony_ci pwrinfo5g->index_bw40_base[rfpath][group] = 0x2A; 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { 26238c2ecf20Sopenharmony_ci if (txcount == 0) { 26248c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][0] = 0x04; 26258c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][0] = 0x00; 26268c2ecf20Sopenharmony_ci pwrinfo5g->bw80_diff[rfpath][0] = 0xFE; 26278c2ecf20Sopenharmony_ci pwrinfo5g->bw160_diff[rfpath][0] = 0xFE; 26288c2ecf20Sopenharmony_ci } else { 26298c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][0] = 0xFE; 26308c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][0] = 0xFE; 26318c2ecf20Sopenharmony_ci pwrinfo5g->bw40_diff[rfpath][0] = 0xFE; 26328c2ecf20Sopenharmony_ci pwrinfo5g->bw80_diff[rfpath][0] = 0xFE; 26338c2ecf20Sopenharmony_ci pwrinfo5g->bw160_diff[rfpath][0] = 0xFE; 26348c2ecf20Sopenharmony_ci } 26358c2ecf20Sopenharmony_ci } 26368c2ecf20Sopenharmony_ci } 26378c2ecf20Sopenharmony_ci return; 26388c2ecf20Sopenharmony_ci } 26398c2ecf20Sopenharmony_ci 26408c2ecf20Sopenharmony_ci rtl_priv(hw)->efuse.txpwr_fromeprom = true; 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { 26438c2ecf20Sopenharmony_ci /*2.4G default value*/ 26448c2ecf20Sopenharmony_ci for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { 26458c2ecf20Sopenharmony_ci pwrinfo24g->index_cck_base[rfpath][group] = hwinfo[eeaddr++]; 26468c2ecf20Sopenharmony_ci if (pwrinfo24g->index_cck_base[rfpath][group] == 0xFF) 26478c2ecf20Sopenharmony_ci pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; 26488c2ecf20Sopenharmony_ci } 26498c2ecf20Sopenharmony_ci for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { 26508c2ecf20Sopenharmony_ci pwrinfo24g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++]; 26518c2ecf20Sopenharmony_ci if (pwrinfo24g->index_bw40_base[rfpath][group] == 0xFF) 26528c2ecf20Sopenharmony_ci pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { 26558c2ecf20Sopenharmony_ci if (txcount == 0) { 26568c2ecf20Sopenharmony_ci pwrinfo24g->bw40_diff[rfpath][txcount] = 0; 26578c2ecf20Sopenharmony_ci /*bit sign number to 8 bit sign number*/ 26588c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; 26598c2ecf20Sopenharmony_ci if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3)) 26608c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0; 26618c2ecf20Sopenharmony_ci /*bit sign number to 8 bit sign number*/ 26628c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); 26638c2ecf20Sopenharmony_ci if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3)) 26648c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci pwrinfo24g->cck_diff[rfpath][txcount] = 0; 26678c2ecf20Sopenharmony_ci eeaddr++; 26688c2ecf20Sopenharmony_ci } else { 26698c2ecf20Sopenharmony_ci pwrinfo24g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; 26708c2ecf20Sopenharmony_ci if (pwrinfo24g->bw40_diff[rfpath][txcount] & BIT(3)) 26718c2ecf20Sopenharmony_ci pwrinfo24g->bw40_diff[rfpath][txcount] |= 0xF0; 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); 26748c2ecf20Sopenharmony_ci if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3)) 26758c2ecf20Sopenharmony_ci pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0; 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci eeaddr++; 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; 26808c2ecf20Sopenharmony_ci if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3)) 26818c2ecf20Sopenharmony_ci pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0; 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci pwrinfo24g->cck_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); 26848c2ecf20Sopenharmony_ci if (pwrinfo24g->cck_diff[rfpath][txcount] & BIT(3)) 26858c2ecf20Sopenharmony_ci pwrinfo24g->cck_diff[rfpath][txcount] |= 0xF0; 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci eeaddr++; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci } 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci /*5G default value*/ 26928c2ecf20Sopenharmony_ci for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { 26938c2ecf20Sopenharmony_ci pwrinfo5g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++]; 26948c2ecf20Sopenharmony_ci if (pwrinfo5g->index_bw40_base[rfpath][group] == 0xFF) 26958c2ecf20Sopenharmony_ci pwrinfo5g->index_bw40_base[rfpath][group] = 0xFE; 26968c2ecf20Sopenharmony_ci } 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { 26998c2ecf20Sopenharmony_ci if (txcount == 0) { 27008c2ecf20Sopenharmony_ci pwrinfo5g->bw40_diff[rfpath][txcount] = 0; 27018c2ecf20Sopenharmony_ci 27028c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][0] = (hwinfo[eeaddr] & 0xf0) >> 4; 27038c2ecf20Sopenharmony_ci if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3)) 27048c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0; 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][0] = (hwinfo[eeaddr] & 0x0f); 27078c2ecf20Sopenharmony_ci if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3)) 27088c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0; 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci eeaddr++; 27118c2ecf20Sopenharmony_ci } else { 27128c2ecf20Sopenharmony_ci pwrinfo5g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; 27138c2ecf20Sopenharmony_ci if (pwrinfo5g->bw40_diff[rfpath][txcount] & BIT(3)) 27148c2ecf20Sopenharmony_ci pwrinfo5g->bw40_diff[rfpath][txcount] |= 0xF0; 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); 27178c2ecf20Sopenharmony_ci if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3)) 27188c2ecf20Sopenharmony_ci pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0; 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci eeaddr++; 27218c2ecf20Sopenharmony_ci } 27228c2ecf20Sopenharmony_ci } 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][1] = (hwinfo[eeaddr] & 0xf0) >> 4; 27258c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][2] = (hwinfo[eeaddr] & 0x0f); 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci eeaddr++; 27288c2ecf20Sopenharmony_ci 27298c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][3] = (hwinfo[eeaddr] & 0x0f); 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci eeaddr++; 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci for (txcount = 1; txcount < MAX_TX_COUNT; txcount++) { 27348c2ecf20Sopenharmony_ci if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3)) 27358c2ecf20Sopenharmony_ci pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0; 27368c2ecf20Sopenharmony_ci } 27378c2ecf20Sopenharmony_ci for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { 27388c2ecf20Sopenharmony_ci pwrinfo5g->bw80_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; 27398c2ecf20Sopenharmony_ci /* 4bit sign number to 8 bit sign number */ 27408c2ecf20Sopenharmony_ci if (pwrinfo5g->bw80_diff[rfpath][txcount] & BIT(3)) 27418c2ecf20Sopenharmony_ci pwrinfo5g->bw80_diff[rfpath][txcount] |= 0xF0; 27428c2ecf20Sopenharmony_ci /* 4bit sign number to 8 bit sign number */ 27438c2ecf20Sopenharmony_ci pwrinfo5g->bw160_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); 27448c2ecf20Sopenharmony_ci if (pwrinfo5g->bw160_diff[rfpath][txcount] & BIT(3)) 27458c2ecf20Sopenharmony_ci pwrinfo5g->bw160_diff[rfpath][txcount] |= 0xF0; 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci eeaddr++; 27488c2ecf20Sopenharmony_ci } 27498c2ecf20Sopenharmony_ci } 27508c2ecf20Sopenharmony_ci} 27518c2ecf20Sopenharmony_ci#if 0 27528c2ecf20Sopenharmony_cistatic void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, 27538c2ecf20Sopenharmony_ci bool autoload_fail, 27548c2ecf20Sopenharmony_ci u8 *hwinfo) 27558c2ecf20Sopenharmony_ci{ 27568c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 27578c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 27588c2ecf20Sopenharmony_ci struct txpower_info_2g pwrinfo24g; 27598c2ecf20Sopenharmony_ci struct txpower_info_5g pwrinfo5g; 27608c2ecf20Sopenharmony_ci u8 rf_path, index; 27618c2ecf20Sopenharmony_ci u8 i; 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, 27648c2ecf20Sopenharmony_ci &pwrinfo5g, autoload_fail, hwinfo); 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci for (rf_path = 0; rf_path < 2; rf_path++) { 27678c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { 27688c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(i + 1); 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci if (i == CHANNEL_MAX_NUMBER_2G - 1) { 27718c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_cck[rf_path][i] = 27728c2ecf20Sopenharmony_ci pwrinfo24g.index_cck_base[rf_path][5]; 27738c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = 27748c2ecf20Sopenharmony_ci pwrinfo24g.index_bw40_base[rf_path][index]; 27758c2ecf20Sopenharmony_ci } else { 27768c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_cck[rf_path][i] = 27778c2ecf20Sopenharmony_ci pwrinfo24g.index_cck_base[rf_path][index]; 27788c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = 27798c2ecf20Sopenharmony_ci pwrinfo24g.index_bw40_base[rf_path][index]; 27808c2ecf20Sopenharmony_ci } 27818c2ecf20Sopenharmony_ci } 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { 27848c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(channel5g[i]); 27858c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw40base[rf_path][i] = 27868c2ecf20Sopenharmony_ci pwrinfo5g.index_bw40_base[rf_path][index]; 27878c2ecf20Sopenharmony_ci } 27888c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { 27898c2ecf20Sopenharmony_ci u8 upper, lower; 27908c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); 27918c2ecf20Sopenharmony_ci upper = pwrinfo5g.index_bw40_base[rf_path][index]; 27928c2ecf20Sopenharmony_ci lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; 27958c2ecf20Sopenharmony_ci } 27968c2ecf20Sopenharmony_ci for (i = 0; i < MAX_TX_COUNT; i++) { 27978c2ecf20Sopenharmony_ci rtlefuse->txpwr_cckdiff[rf_path][i] = 27988c2ecf20Sopenharmony_ci pwrinfo24g.cck_diff[rf_path][i]; 27998c2ecf20Sopenharmony_ci rtlefuse->txpwr_legacyhtdiff[rf_path][i] = 28008c2ecf20Sopenharmony_ci pwrinfo24g.ofdm_diff[rf_path][i]; 28018c2ecf20Sopenharmony_ci rtlefuse->txpwr_ht20diff[rf_path][i] = 28028c2ecf20Sopenharmony_ci pwrinfo24g.bw20_diff[rf_path][i]; 28038c2ecf20Sopenharmony_ci rtlefuse->txpwr_ht40diff[rf_path][i] = 28048c2ecf20Sopenharmony_ci pwrinfo24g.bw40_diff[rf_path][i]; 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = 28078c2ecf20Sopenharmony_ci pwrinfo5g.ofdm_diff[rf_path][i]; 28088c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw20diff[rf_path][i] = 28098c2ecf20Sopenharmony_ci pwrinfo5g.bw20_diff[rf_path][i]; 28108c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw40diff[rf_path][i] = 28118c2ecf20Sopenharmony_ci pwrinfo5g.bw40_diff[rf_path][i]; 28128c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw80diff[rf_path][i] = 28138c2ecf20Sopenharmony_ci pwrinfo5g.bw80_diff[rf_path][i]; 28148c2ecf20Sopenharmony_ci } 28158c2ecf20Sopenharmony_ci } 28168c2ecf20Sopenharmony_ci 28178c2ecf20Sopenharmony_ci if (!autoload_fail) { 28188c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = 28198c2ecf20Sopenharmony_ci hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07;/*bit0~2*/ 28208c2ecf20Sopenharmony_ci if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) 28218c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = 0; 28228c2ecf20Sopenharmony_ci } else { 28238c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = 0; 28248c2ecf20Sopenharmony_ci } 28258c2ecf20Sopenharmony_ci 28268c2ecf20Sopenharmony_ci RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, 28278c2ecf20Sopenharmony_ci "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); 28288c2ecf20Sopenharmony_ci} 28298c2ecf20Sopenharmony_ci#endif 28308c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, 28318c2ecf20Sopenharmony_ci bool autoload_fail, 28328c2ecf20Sopenharmony_ci u8 *hwinfo) 28338c2ecf20Sopenharmony_ci{ 28348c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 28358c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 28368c2ecf20Sopenharmony_ci struct txpower_info_2g pwrinfo24g; 28378c2ecf20Sopenharmony_ci struct txpower_info_5g pwrinfo5g; 28388c2ecf20Sopenharmony_ci u8 rf_path, index; 28398c2ecf20Sopenharmony_ci u8 i; 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, 28428c2ecf20Sopenharmony_ci &pwrinfo5g, autoload_fail, hwinfo); 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci for (rf_path = 0; rf_path < 2; rf_path++) { 28458c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { 28468c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(i + 1); 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci if (i == CHANNEL_MAX_NUMBER_2G - 1) { 28498c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_cck[rf_path][i] = 28508c2ecf20Sopenharmony_ci pwrinfo24g.index_cck_base[rf_path][5]; 28518c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = 28528c2ecf20Sopenharmony_ci pwrinfo24g.index_bw40_base[rf_path][index]; 28538c2ecf20Sopenharmony_ci } else { 28548c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_cck[rf_path][i] = 28558c2ecf20Sopenharmony_ci pwrinfo24g.index_cck_base[rf_path][index]; 28568c2ecf20Sopenharmony_ci rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = 28578c2ecf20Sopenharmony_ci pwrinfo24g.index_bw40_base[rf_path][index]; 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci } 28608c2ecf20Sopenharmony_ci 28618c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { 28628c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(channel5g[i]); 28638c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw40base[rf_path][i] = 28648c2ecf20Sopenharmony_ci pwrinfo5g.index_bw40_base[rf_path][index]; 28658c2ecf20Sopenharmony_ci } 28668c2ecf20Sopenharmony_ci for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { 28678c2ecf20Sopenharmony_ci u8 upper, lower; 28688c2ecf20Sopenharmony_ci index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); 28698c2ecf20Sopenharmony_ci upper = pwrinfo5g.index_bw40_base[rf_path][index]; 28708c2ecf20Sopenharmony_ci lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; 28738c2ecf20Sopenharmony_ci } 28748c2ecf20Sopenharmony_ci for (i = 0; i < MAX_TX_COUNT; i++) { 28758c2ecf20Sopenharmony_ci rtlefuse->txpwr_cckdiff[rf_path][i] = 28768c2ecf20Sopenharmony_ci pwrinfo24g.cck_diff[rf_path][i]; 28778c2ecf20Sopenharmony_ci rtlefuse->txpwr_legacyhtdiff[rf_path][i] = 28788c2ecf20Sopenharmony_ci pwrinfo24g.ofdm_diff[rf_path][i]; 28798c2ecf20Sopenharmony_ci rtlefuse->txpwr_ht20diff[rf_path][i] = 28808c2ecf20Sopenharmony_ci pwrinfo24g.bw20_diff[rf_path][i]; 28818c2ecf20Sopenharmony_ci rtlefuse->txpwr_ht40diff[rf_path][i] = 28828c2ecf20Sopenharmony_ci pwrinfo24g.bw40_diff[rf_path][i]; 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = 28858c2ecf20Sopenharmony_ci pwrinfo5g.ofdm_diff[rf_path][i]; 28868c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw20diff[rf_path][i] = 28878c2ecf20Sopenharmony_ci pwrinfo5g.bw20_diff[rf_path][i]; 28888c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw40diff[rf_path][i] = 28898c2ecf20Sopenharmony_ci pwrinfo5g.bw40_diff[rf_path][i]; 28908c2ecf20Sopenharmony_ci rtlefuse->txpwr_5g_bw80diff[rf_path][i] = 28918c2ecf20Sopenharmony_ci pwrinfo5g.bw80_diff[rf_path][i]; 28928c2ecf20Sopenharmony_ci } 28938c2ecf20Sopenharmony_ci } 28948c2ecf20Sopenharmony_ci /*bit0~2*/ 28958c2ecf20Sopenharmony_ci if (!autoload_fail) { 28968c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07; 28978c2ecf20Sopenharmony_ci if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) 28988c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = 0; 28998c2ecf20Sopenharmony_ci } else { 29008c2ecf20Sopenharmony_ci rtlefuse->eeprom_regulatory = 0; 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, 29048c2ecf20Sopenharmony_ci "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); 29058c2ecf20Sopenharmony_ci} 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_cistatic void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, 29088c2ecf20Sopenharmony_ci bool autoload_fail) 29098c2ecf20Sopenharmony_ci{ 29108c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 29118c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_ci if (!autoload_fail) { 29148c2ecf20Sopenharmony_ci rtlhal->pa_type_2g = hwinfo[0XBC]; 29158c2ecf20Sopenharmony_ci rtlhal->lna_type_2g = hwinfo[0XBD]; 29168c2ecf20Sopenharmony_ci if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { 29178c2ecf20Sopenharmony_ci rtlhal->pa_type_2g = 0; 29188c2ecf20Sopenharmony_ci rtlhal->lna_type_2g = 0; 29198c2ecf20Sopenharmony_ci } 29208c2ecf20Sopenharmony_ci rtlhal->external_pa_2g = ((rtlhal->pa_type_2g & BIT(5)) && 29218c2ecf20Sopenharmony_ci (rtlhal->pa_type_2g & BIT(4))) ? 29228c2ecf20Sopenharmony_ci 1 : 0; 29238c2ecf20Sopenharmony_ci rtlhal->external_lna_2g = ((rtlhal->lna_type_2g & BIT(7)) && 29248c2ecf20Sopenharmony_ci (rtlhal->lna_type_2g & BIT(3))) ? 29258c2ecf20Sopenharmony_ci 1 : 0; 29268c2ecf20Sopenharmony_ci 29278c2ecf20Sopenharmony_ci rtlhal->pa_type_5g = hwinfo[0XBC]; 29288c2ecf20Sopenharmony_ci rtlhal->lna_type_5g = hwinfo[0XBF]; 29298c2ecf20Sopenharmony_ci if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { 29308c2ecf20Sopenharmony_ci rtlhal->pa_type_5g = 0; 29318c2ecf20Sopenharmony_ci rtlhal->lna_type_5g = 0; 29328c2ecf20Sopenharmony_ci } 29338c2ecf20Sopenharmony_ci rtlhal->external_pa_5g = ((rtlhal->pa_type_5g & BIT(1)) && 29348c2ecf20Sopenharmony_ci (rtlhal->pa_type_5g & BIT(0))) ? 29358c2ecf20Sopenharmony_ci 1 : 0; 29368c2ecf20Sopenharmony_ci rtlhal->external_lna_5g = ((rtlhal->lna_type_5g & BIT(7)) && 29378c2ecf20Sopenharmony_ci (rtlhal->lna_type_5g & BIT(3))) ? 29388c2ecf20Sopenharmony_ci 1 : 0; 29398c2ecf20Sopenharmony_ci } else { 29408c2ecf20Sopenharmony_ci rtlhal->external_pa_2g = 0; 29418c2ecf20Sopenharmony_ci rtlhal->external_lna_2g = 0; 29428c2ecf20Sopenharmony_ci rtlhal->external_pa_5g = 0; 29438c2ecf20Sopenharmony_ci rtlhal->external_lna_5g = 0; 29448c2ecf20Sopenharmony_ci } 29458c2ecf20Sopenharmony_ci} 29468c2ecf20Sopenharmony_ci 29478c2ecf20Sopenharmony_cistatic void _rtl8812ae_read_amplifier_type(struct ieee80211_hw *hw, u8 *hwinfo, 29488c2ecf20Sopenharmony_ci bool autoload_fail) 29498c2ecf20Sopenharmony_ci{ 29508c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 29518c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci u8 ext_type_pa_2g_a = (hwinfo[0XBD] & BIT(2)) >> 2; /* 0XBD[2] */ 29548c2ecf20Sopenharmony_ci u8 ext_type_pa_2g_b = (hwinfo[0XBD] & BIT(6)) >> 6; /* 0XBD[6] */ 29558c2ecf20Sopenharmony_ci u8 ext_type_pa_5g_a = (hwinfo[0XBF] & BIT(2)) >> 2; /* 0XBF[2] */ 29568c2ecf20Sopenharmony_ci u8 ext_type_pa_5g_b = (hwinfo[0XBF] & BIT(6)) >> 6; /* 0XBF[6] */ 29578c2ecf20Sopenharmony_ci /* 0XBD[1:0] */ 29588c2ecf20Sopenharmony_ci u8 ext_type_lna_2g_a = (hwinfo[0XBD] & (BIT(1) | BIT(0))) >> 0; 29598c2ecf20Sopenharmony_ci /* 0XBD[5:4] */ 29608c2ecf20Sopenharmony_ci u8 ext_type_lna_2g_b = (hwinfo[0XBD] & (BIT(5) | BIT(4))) >> 4; 29618c2ecf20Sopenharmony_ci /* 0XBF[1:0] */ 29628c2ecf20Sopenharmony_ci u8 ext_type_lna_5g_a = (hwinfo[0XBF] & (BIT(1) | BIT(0))) >> 0; 29638c2ecf20Sopenharmony_ci /* 0XBF[5:4] */ 29648c2ecf20Sopenharmony_ci u8 ext_type_lna_5g_b = (hwinfo[0XBF] & (BIT(5) | BIT(4))) >> 4; 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_ci _rtl8812ae_read_pa_type(hw, hwinfo, autoload_fail); 29678c2ecf20Sopenharmony_ci 29688c2ecf20Sopenharmony_ci /* [2.4G] Path A and B are both extPA */ 29698c2ecf20Sopenharmony_ci if ((rtlhal->pa_type_2g & (BIT(5) | BIT(4))) == (BIT(5) | BIT(4))) 29708c2ecf20Sopenharmony_ci rtlhal->type_gpa = ext_type_pa_2g_b << 2 | ext_type_pa_2g_a; 29718c2ecf20Sopenharmony_ci 29728c2ecf20Sopenharmony_ci /* [5G] Path A and B are both extPA */ 29738c2ecf20Sopenharmony_ci if ((rtlhal->pa_type_5g & (BIT(1) | BIT(0))) == (BIT(1) | BIT(0))) 29748c2ecf20Sopenharmony_ci rtlhal->type_apa = ext_type_pa_5g_b << 2 | ext_type_pa_5g_a; 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci /* [2.4G] Path A and B are both extLNA */ 29778c2ecf20Sopenharmony_ci if ((rtlhal->lna_type_2g & (BIT(7) | BIT(3))) == (BIT(7) | BIT(3))) 29788c2ecf20Sopenharmony_ci rtlhal->type_glna = ext_type_lna_2g_b << 2 | ext_type_lna_2g_a; 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci /* [5G] Path A and B are both extLNA */ 29818c2ecf20Sopenharmony_ci if ((rtlhal->lna_type_5g & (BIT(7) | BIT(3))) == (BIT(7) | BIT(3))) 29828c2ecf20Sopenharmony_ci rtlhal->type_alna = ext_type_lna_5g_b << 2 | ext_type_lna_5g_a; 29838c2ecf20Sopenharmony_ci} 29848c2ecf20Sopenharmony_ci 29858c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, 29868c2ecf20Sopenharmony_ci bool autoload_fail) 29878c2ecf20Sopenharmony_ci{ 29888c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 29898c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_ci if (!autoload_fail) { 29928c2ecf20Sopenharmony_ci rtlhal->pa_type_2g = hwinfo[0XBC]; 29938c2ecf20Sopenharmony_ci rtlhal->lna_type_2g = hwinfo[0XBD]; 29948c2ecf20Sopenharmony_ci if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { 29958c2ecf20Sopenharmony_ci rtlhal->pa_type_2g = 0; 29968c2ecf20Sopenharmony_ci rtlhal->lna_type_2g = 0; 29978c2ecf20Sopenharmony_ci } 29988c2ecf20Sopenharmony_ci rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(5)) ? 1 : 0; 29998c2ecf20Sopenharmony_ci rtlhal->external_lna_2g = (rtlhal->lna_type_2g & BIT(7)) ? 1 : 0; 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci rtlhal->pa_type_5g = hwinfo[0XBC]; 30028c2ecf20Sopenharmony_ci rtlhal->lna_type_5g = hwinfo[0XBF]; 30038c2ecf20Sopenharmony_ci if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { 30048c2ecf20Sopenharmony_ci rtlhal->pa_type_5g = 0; 30058c2ecf20Sopenharmony_ci rtlhal->lna_type_5g = 0; 30068c2ecf20Sopenharmony_ci } 30078c2ecf20Sopenharmony_ci rtlhal->external_pa_5g = (rtlhal->pa_type_5g & BIT(1)) ? 1 : 0; 30088c2ecf20Sopenharmony_ci rtlhal->external_lna_5g = (rtlhal->lna_type_5g & BIT(7)) ? 1 : 0; 30098c2ecf20Sopenharmony_ci } else { 30108c2ecf20Sopenharmony_ci rtlhal->external_pa_2g = 0; 30118c2ecf20Sopenharmony_ci rtlhal->external_lna_2g = 0; 30128c2ecf20Sopenharmony_ci rtlhal->external_pa_5g = 0; 30138c2ecf20Sopenharmony_ci rtlhal->external_lna_5g = 0; 30148c2ecf20Sopenharmony_ci } 30158c2ecf20Sopenharmony_ci} 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_rfe_type(struct ieee80211_hw *hw, u8 *hwinfo, 30188c2ecf20Sopenharmony_ci bool autoload_fail) 30198c2ecf20Sopenharmony_ci{ 30208c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 30218c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_ci if (!autoload_fail) { 30248c2ecf20Sopenharmony_ci if (hwinfo[EEPROM_RFE_OPTION] & BIT(7)) { 30258c2ecf20Sopenharmony_ci if (rtlhal->external_lna_5g) { 30268c2ecf20Sopenharmony_ci if (rtlhal->external_pa_5g) { 30278c2ecf20Sopenharmony_ci if (rtlhal->external_lna_2g && 30288c2ecf20Sopenharmony_ci rtlhal->external_pa_2g) 30298c2ecf20Sopenharmony_ci rtlhal->rfe_type = 3; 30308c2ecf20Sopenharmony_ci else 30318c2ecf20Sopenharmony_ci rtlhal->rfe_type = 0; 30328c2ecf20Sopenharmony_ci } else { 30338c2ecf20Sopenharmony_ci rtlhal->rfe_type = 2; 30348c2ecf20Sopenharmony_ci } 30358c2ecf20Sopenharmony_ci } else { 30368c2ecf20Sopenharmony_ci rtlhal->rfe_type = 4; 30378c2ecf20Sopenharmony_ci } 30388c2ecf20Sopenharmony_ci } else { 30398c2ecf20Sopenharmony_ci rtlhal->rfe_type = hwinfo[EEPROM_RFE_OPTION] & 0x3F; 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_ci if (rtlhal->rfe_type == 4 && 30428c2ecf20Sopenharmony_ci (rtlhal->external_pa_5g || 30438c2ecf20Sopenharmony_ci rtlhal->external_pa_2g || 30448c2ecf20Sopenharmony_ci rtlhal->external_lna_5g || 30458c2ecf20Sopenharmony_ci rtlhal->external_lna_2g)) { 30468c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 30478c2ecf20Sopenharmony_ci rtlhal->rfe_type = 2; 30488c2ecf20Sopenharmony_ci } 30498c2ecf20Sopenharmony_ci } 30508c2ecf20Sopenharmony_ci } else { 30518c2ecf20Sopenharmony_ci rtlhal->rfe_type = 0x04; 30528c2ecf20Sopenharmony_ci } 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 30558c2ecf20Sopenharmony_ci "RFE Type: 0x%2x\n", rtlhal->rfe_type); 30568c2ecf20Sopenharmony_ci} 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_cistatic void _rtl8812ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, 30598c2ecf20Sopenharmony_ci bool auto_load_fail, u8 *hwinfo) 30608c2ecf20Sopenharmony_ci{ 30618c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 30628c2ecf20Sopenharmony_ci u8 value; 30638c2ecf20Sopenharmony_ci 30648c2ecf20Sopenharmony_ci if (!auto_load_fail) { 30658c2ecf20Sopenharmony_ci value = *(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION]; 30668c2ecf20Sopenharmony_ci if (((value & 0xe0) >> 5) == 0x1) 30678c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 1; 30688c2ecf20Sopenharmony_ci else 30698c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 0; 30708c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_ci value = hwinfo[EEPROM_RF_BT_SETTING]; 30738c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); 30748c2ecf20Sopenharmony_ci } else { 30758c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 0; 30768c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; 30778c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; 30788c2ecf20Sopenharmony_ci } 30798c2ecf20Sopenharmony_ci /*move BT_InitHalVars() to init_sw_vars*/ 30808c2ecf20Sopenharmony_ci} 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, 30838c2ecf20Sopenharmony_ci bool auto_load_fail, u8 *hwinfo) 30848c2ecf20Sopenharmony_ci{ 30858c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 30868c2ecf20Sopenharmony_ci u8 value; 30878c2ecf20Sopenharmony_ci u32 tmpu_32; 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci if (!auto_load_fail) { 30908c2ecf20Sopenharmony_ci tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); 30918c2ecf20Sopenharmony_ci if (tmpu_32 & BIT(18)) 30928c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 1; 30938c2ecf20Sopenharmony_ci else 30948c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 0; 30958c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci value = hwinfo[EEPROM_RF_BT_SETTING]; 30988c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); 30998c2ecf20Sopenharmony_ci } else { 31008c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.btcoexist = 0; 31018c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; 31028c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; 31038c2ecf20Sopenharmony_ci } 31048c2ecf20Sopenharmony_ci /*move BT_InitHalVars() to init_sw_vars*/ 31058c2ecf20Sopenharmony_ci} 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_cistatic void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_test) 31088c2ecf20Sopenharmony_ci{ 31098c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 31108c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 31118c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 31128c2ecf20Sopenharmony_ci int params[] = {RTL_EEPROM_ID, EEPROM_VID, EEPROM_DID, 31138c2ecf20Sopenharmony_ci EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, 31148c2ecf20Sopenharmony_ci EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, 31158c2ecf20Sopenharmony_ci COUNTRY_CODE_WORLD_WIDE_13}; 31168c2ecf20Sopenharmony_ci u8 *hwinfo; 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci if (b_pseudo_test) { 31198c2ecf20Sopenharmony_ci ;/* need add */ 31208c2ecf20Sopenharmony_ci } 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci hwinfo = kzalloc(HWSET_MAX_SIZE, GFP_KERNEL); 31238c2ecf20Sopenharmony_ci if (!hwinfo) 31248c2ecf20Sopenharmony_ci return; 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_ci if (rtl_get_hwinfo(hw, rtlpriv, HWSET_MAX_SIZE, hwinfo, params)) 31278c2ecf20Sopenharmony_ci goto exit; 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci _rtl8821ae_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, 31308c2ecf20Sopenharmony_ci hwinfo); 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 31338c2ecf20Sopenharmony_ci _rtl8812ae_read_amplifier_type(hw, hwinfo, 31348c2ecf20Sopenharmony_ci rtlefuse->autoload_failflag); 31358c2ecf20Sopenharmony_ci _rtl8812ae_read_bt_coexist_info_from_hwpg(hw, 31368c2ecf20Sopenharmony_ci rtlefuse->autoload_failflag, hwinfo); 31378c2ecf20Sopenharmony_ci } else { 31388c2ecf20Sopenharmony_ci _rtl8821ae_read_pa_type(hw, hwinfo, rtlefuse->autoload_failflag); 31398c2ecf20Sopenharmony_ci _rtl8821ae_read_bt_coexist_info_from_hwpg(hw, 31408c2ecf20Sopenharmony_ci rtlefuse->autoload_failflag, hwinfo); 31418c2ecf20Sopenharmony_ci } 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci _rtl8821ae_read_rfe_type(hw, hwinfo, rtlefuse->autoload_failflag); 31448c2ecf20Sopenharmony_ci /*board type*/ 31458c2ecf20Sopenharmony_ci rtlefuse->board_type = ODM_BOARD_DEFAULT; 31468c2ecf20Sopenharmony_ci if (rtlhal->external_lna_2g != 0) 31478c2ecf20Sopenharmony_ci rtlefuse->board_type |= ODM_BOARD_EXT_LNA; 31488c2ecf20Sopenharmony_ci if (rtlhal->external_lna_5g != 0) 31498c2ecf20Sopenharmony_ci rtlefuse->board_type |= ODM_BOARD_EXT_LNA_5G; 31508c2ecf20Sopenharmony_ci if (rtlhal->external_pa_2g != 0) 31518c2ecf20Sopenharmony_ci rtlefuse->board_type |= ODM_BOARD_EXT_PA; 31528c2ecf20Sopenharmony_ci if (rtlhal->external_pa_5g != 0) 31538c2ecf20Sopenharmony_ci rtlefuse->board_type |= ODM_BOARD_EXT_PA_5G; 31548c2ecf20Sopenharmony_ci 31558c2ecf20Sopenharmony_ci if (rtlpriv->btcoexist.btc_info.btcoexist == 1) 31568c2ecf20Sopenharmony_ci rtlefuse->board_type |= ODM_BOARD_BT; 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci rtlhal->board_type = rtlefuse->board_type; 31598c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 31608c2ecf20Sopenharmony_ci "board_type = 0x%x\n", rtlefuse->board_type); 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; 31638c2ecf20Sopenharmony_ci if (rtlefuse->eeprom_channelplan == 0xff) 31648c2ecf20Sopenharmony_ci rtlefuse->eeprom_channelplan = 0x7F; 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_ci /* set channel plan from efuse */ 31678c2ecf20Sopenharmony_ci rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_ci /*parse xtal*/ 31708c2ecf20Sopenharmony_ci rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8821AE]; 31718c2ecf20Sopenharmony_ci if (rtlefuse->crystalcap == 0xFF) 31728c2ecf20Sopenharmony_ci rtlefuse->crystalcap = 0x20; 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ci rtlefuse->eeprom_thermalmeter = *(u8 *)&hwinfo[EEPROM_THERMAL_METER]; 31758c2ecf20Sopenharmony_ci if ((rtlefuse->eeprom_thermalmeter == 0xff) || 31768c2ecf20Sopenharmony_ci rtlefuse->autoload_failflag) { 31778c2ecf20Sopenharmony_ci rtlefuse->apk_thermalmeterignore = true; 31788c2ecf20Sopenharmony_ci rtlefuse->eeprom_thermalmeter = 0xff; 31798c2ecf20Sopenharmony_ci } 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; 31828c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 31838c2ecf20Sopenharmony_ci "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci if (!rtlefuse->autoload_failflag) { 31868c2ecf20Sopenharmony_ci rtlefuse->antenna_div_cfg = 31878c2ecf20Sopenharmony_ci (hwinfo[EEPROM_RF_BOARD_OPTION] & 0x18) >> 3; 31888c2ecf20Sopenharmony_ci if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xff) 31898c2ecf20Sopenharmony_ci rtlefuse->antenna_div_cfg = 0; 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci if (rtlpriv->btcoexist.btc_info.btcoexist == 1 && 31928c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ant_num == ANT_X1) 31938c2ecf20Sopenharmony_ci rtlefuse->antenna_div_cfg = 0; 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_ci rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; 31968c2ecf20Sopenharmony_ci if (rtlefuse->antenna_div_type == 0xff) 31978c2ecf20Sopenharmony_ci rtlefuse->antenna_div_type = FIXED_HW_ANTDIV; 31988c2ecf20Sopenharmony_ci } else { 31998c2ecf20Sopenharmony_ci rtlefuse->antenna_div_cfg = 0; 32008c2ecf20Sopenharmony_ci rtlefuse->antenna_div_type = 0; 32018c2ecf20Sopenharmony_ci } 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 32048c2ecf20Sopenharmony_ci "SWAS: bHwAntDiv = %x, TRxAntDivType = %x\n", 32058c2ecf20Sopenharmony_ci rtlefuse->antenna_div_cfg, rtlefuse->antenna_div_type); 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci rtlpriv->ledctl.led_opendrain = true; 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci if (rtlhal->oem_id == RT_CID_DEFAULT) { 32108c2ecf20Sopenharmony_ci switch (rtlefuse->eeprom_oemid) { 32118c2ecf20Sopenharmony_ci case RT_CID_DEFAULT: 32128c2ecf20Sopenharmony_ci break; 32138c2ecf20Sopenharmony_ci case EEPROM_CID_TOSHIBA: 32148c2ecf20Sopenharmony_ci rtlhal->oem_id = RT_CID_TOSHIBA; 32158c2ecf20Sopenharmony_ci break; 32168c2ecf20Sopenharmony_ci case EEPROM_CID_CCX: 32178c2ecf20Sopenharmony_ci rtlhal->oem_id = RT_CID_CCX; 32188c2ecf20Sopenharmony_ci break; 32198c2ecf20Sopenharmony_ci case EEPROM_CID_QMI: 32208c2ecf20Sopenharmony_ci rtlhal->oem_id = RT_CID_819X_QMI; 32218c2ecf20Sopenharmony_ci break; 32228c2ecf20Sopenharmony_ci case EEPROM_CID_WHQL: 32238c2ecf20Sopenharmony_ci break; 32248c2ecf20Sopenharmony_ci default: 32258c2ecf20Sopenharmony_ci break; 32268c2ecf20Sopenharmony_ci } 32278c2ecf20Sopenharmony_ci } 32288c2ecf20Sopenharmony_ciexit: 32298c2ecf20Sopenharmony_ci kfree(hwinfo); 32308c2ecf20Sopenharmony_ci} 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci/*static void _rtl8821ae_hal_customized_behavior(struct ieee80211_hw *hw) 32338c2ecf20Sopenharmony_ci{ 32348c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 32358c2ecf20Sopenharmony_ci struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); 32368c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_ci rtlpriv->ledctl.led_opendrain = true; 32398c2ecf20Sopenharmony_ci switch (rtlhal->oem_id) { 32408c2ecf20Sopenharmony_ci case RT_CID_819X_HP: 32418c2ecf20Sopenharmony_ci rtlpriv->ledctl.led_opendrain = true; 32428c2ecf20Sopenharmony_ci break; 32438c2ecf20Sopenharmony_ci case RT_CID_819X_LENOVO: 32448c2ecf20Sopenharmony_ci case RT_CID_DEFAULT: 32458c2ecf20Sopenharmony_ci case RT_CID_TOSHIBA: 32468c2ecf20Sopenharmony_ci case RT_CID_CCX: 32478c2ecf20Sopenharmony_ci case RT_CID_819X_ACER: 32488c2ecf20Sopenharmony_ci case RT_CID_WHQL: 32498c2ecf20Sopenharmony_ci default: 32508c2ecf20Sopenharmony_ci break; 32518c2ecf20Sopenharmony_ci } 32528c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 32538c2ecf20Sopenharmony_ci "RT Customized ID: 0x%02X\n", rtlhal->oem_id); 32548c2ecf20Sopenharmony_ci}*/ 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_civoid rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw) 32578c2ecf20Sopenharmony_ci{ 32588c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 32598c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 32608c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 32618c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 32628c2ecf20Sopenharmony_ci u8 tmp_u1b; 32638c2ecf20Sopenharmony_ci 32648c2ecf20Sopenharmony_ci rtlhal->version = _rtl8821ae_read_chip_version(hw); 32658c2ecf20Sopenharmony_ci if (get_rf_type(rtlphy) == RF_1T1R) 32668c2ecf20Sopenharmony_ci rtlpriv->dm.rfpath_rxenable[0] = true; 32678c2ecf20Sopenharmony_ci else 32688c2ecf20Sopenharmony_ci rtlpriv->dm.rfpath_rxenable[0] = 32698c2ecf20Sopenharmony_ci rtlpriv->dm.rfpath_rxenable[1] = true; 32708c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", 32718c2ecf20Sopenharmony_ci rtlhal->version); 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); 32748c2ecf20Sopenharmony_ci if (tmp_u1b & BIT(4)) { 32758c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); 32768c2ecf20Sopenharmony_ci rtlefuse->epromtype = EEPROM_93C46; 32778c2ecf20Sopenharmony_ci } else { 32788c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); 32798c2ecf20Sopenharmony_ci rtlefuse->epromtype = EEPROM_BOOT_EFUSE; 32808c2ecf20Sopenharmony_ci } 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci if (tmp_u1b & BIT(5)) { 32838c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); 32848c2ecf20Sopenharmony_ci rtlefuse->autoload_failflag = false; 32858c2ecf20Sopenharmony_ci _rtl8821ae_read_adapter_info(hw, false); 32868c2ecf20Sopenharmony_ci } else { 32878c2ecf20Sopenharmony_ci pr_err("Autoload ERR!!\n"); 32888c2ecf20Sopenharmony_ci } 32898c2ecf20Sopenharmony_ci /*hal_ReadRFType_8812A()*/ 32908c2ecf20Sopenharmony_ci /* _rtl8821ae_hal_customized_behavior(hw); */ 32918c2ecf20Sopenharmony_ci} 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_cistatic void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw, 32948c2ecf20Sopenharmony_ci struct ieee80211_sta *sta) 32958c2ecf20Sopenharmony_ci{ 32968c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 32978c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 32988c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 32998c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 33008c2ecf20Sopenharmony_ci u32 ratr_value; 33018c2ecf20Sopenharmony_ci u8 ratr_index = 0; 33028c2ecf20Sopenharmony_ci u8 b_nmode = mac->ht_enable; 33038c2ecf20Sopenharmony_ci u8 mimo_ps = IEEE80211_SMPS_OFF; 33048c2ecf20Sopenharmony_ci u16 shortgi_rate; 33058c2ecf20Sopenharmony_ci u32 tmp_ratr_value; 33068c2ecf20Sopenharmony_ci u8 curtxbw_40mhz = mac->bw_40; 33078c2ecf20Sopenharmony_ci u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? 33088c2ecf20Sopenharmony_ci 1 : 0; 33098c2ecf20Sopenharmony_ci u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? 33108c2ecf20Sopenharmony_ci 1 : 0; 33118c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode = mac->mode; 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci if (rtlhal->current_bandtype == BAND_ON_5G) 33148c2ecf20Sopenharmony_ci ratr_value = sta->supp_rates[1] << 4; 33158c2ecf20Sopenharmony_ci else 33168c2ecf20Sopenharmony_ci ratr_value = sta->supp_rates[0]; 33178c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_ADHOC) 33188c2ecf20Sopenharmony_ci ratr_value = 0xfff; 33198c2ecf20Sopenharmony_ci ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | 33208c2ecf20Sopenharmony_ci sta->ht_cap.mcs.rx_mask[0] << 12); 33218c2ecf20Sopenharmony_ci switch (wirelessmode) { 33228c2ecf20Sopenharmony_ci case WIRELESS_MODE_B: 33238c2ecf20Sopenharmony_ci if (ratr_value & 0x0000000c) 33248c2ecf20Sopenharmony_ci ratr_value &= 0x0000000d; 33258c2ecf20Sopenharmony_ci else 33268c2ecf20Sopenharmony_ci ratr_value &= 0x0000000f; 33278c2ecf20Sopenharmony_ci break; 33288c2ecf20Sopenharmony_ci case WIRELESS_MODE_G: 33298c2ecf20Sopenharmony_ci ratr_value &= 0x00000FF5; 33308c2ecf20Sopenharmony_ci break; 33318c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_24G: 33328c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_5G: 33338c2ecf20Sopenharmony_ci b_nmode = 1; 33348c2ecf20Sopenharmony_ci if (mimo_ps == IEEE80211_SMPS_STATIC) { 33358c2ecf20Sopenharmony_ci ratr_value &= 0x0007F005; 33368c2ecf20Sopenharmony_ci } else { 33378c2ecf20Sopenharmony_ci u32 ratr_mask; 33388c2ecf20Sopenharmony_ci 33398c2ecf20Sopenharmony_ci if (get_rf_type(rtlphy) == RF_1T2R || 33408c2ecf20Sopenharmony_ci get_rf_type(rtlphy) == RF_1T1R) 33418c2ecf20Sopenharmony_ci ratr_mask = 0x000ff005; 33428c2ecf20Sopenharmony_ci else 33438c2ecf20Sopenharmony_ci ratr_mask = 0x0f0ff005; 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_ci ratr_value &= ratr_mask; 33468c2ecf20Sopenharmony_ci } 33478c2ecf20Sopenharmony_ci break; 33488c2ecf20Sopenharmony_ci default: 33498c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T2R) 33508c2ecf20Sopenharmony_ci ratr_value &= 0x000ff0ff; 33518c2ecf20Sopenharmony_ci else 33528c2ecf20Sopenharmony_ci ratr_value &= 0x0f0ff0ff; 33538c2ecf20Sopenharmony_ci 33548c2ecf20Sopenharmony_ci break; 33558c2ecf20Sopenharmony_ci } 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci if ((rtlpriv->btcoexist.bt_coexistence) && 33588c2ecf20Sopenharmony_ci (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && 33598c2ecf20Sopenharmony_ci (rtlpriv->btcoexist.bt_cur_state) && 33608c2ecf20Sopenharmony_ci (rtlpriv->btcoexist.bt_ant_isolation) && 33618c2ecf20Sopenharmony_ci ((rtlpriv->btcoexist.bt_service == BT_SCO) || 33628c2ecf20Sopenharmony_ci (rtlpriv->btcoexist.bt_service == BT_BUSY))) 33638c2ecf20Sopenharmony_ci ratr_value &= 0x0fffcfc0; 33648c2ecf20Sopenharmony_ci else 33658c2ecf20Sopenharmony_ci ratr_value &= 0x0FFFFFFF; 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ci if (b_nmode && ((curtxbw_40mhz && 33688c2ecf20Sopenharmony_ci b_curshortgi_40mhz) || (!curtxbw_40mhz && 33698c2ecf20Sopenharmony_ci b_curshortgi_20mhz))) { 33708c2ecf20Sopenharmony_ci ratr_value |= 0x10000000; 33718c2ecf20Sopenharmony_ci tmp_ratr_value = (ratr_value >> 12); 33728c2ecf20Sopenharmony_ci 33738c2ecf20Sopenharmony_ci for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { 33748c2ecf20Sopenharmony_ci if ((1 << shortgi_rate) & tmp_ratr_value) 33758c2ecf20Sopenharmony_ci break; 33768c2ecf20Sopenharmony_ci } 33778c2ecf20Sopenharmony_ci 33788c2ecf20Sopenharmony_ci shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | 33798c2ecf20Sopenharmony_ci (shortgi_rate << 4) | (shortgi_rate); 33808c2ecf20Sopenharmony_ci } 33818c2ecf20Sopenharmony_ci 33828c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, 33858c2ecf20Sopenharmony_ci "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); 33868c2ecf20Sopenharmony_ci} 33878c2ecf20Sopenharmony_ci 33888c2ecf20Sopenharmony_cistatic u32 _rtl8821ae_rate_to_bitmap_2ssvht(__le16 vht_rate) 33898c2ecf20Sopenharmony_ci{ 33908c2ecf20Sopenharmony_ci u8 i, j, tmp_rate; 33918c2ecf20Sopenharmony_ci u32 rate_bitmap = 0; 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci for (i = j = 0; i < 4; i += 2, j += 10) { 33948c2ecf20Sopenharmony_ci tmp_rate = (le16_to_cpu(vht_rate) >> i) & 3; 33958c2ecf20Sopenharmony_ci 33968c2ecf20Sopenharmony_ci switch (tmp_rate) { 33978c2ecf20Sopenharmony_ci case 2: 33988c2ecf20Sopenharmony_ci rate_bitmap = rate_bitmap | (0x03ff << j); 33998c2ecf20Sopenharmony_ci break; 34008c2ecf20Sopenharmony_ci case 1: 34018c2ecf20Sopenharmony_ci rate_bitmap = rate_bitmap | (0x01ff << j); 34028c2ecf20Sopenharmony_ci break; 34038c2ecf20Sopenharmony_ci case 0: 34048c2ecf20Sopenharmony_ci rate_bitmap = rate_bitmap | (0x00ff << j); 34058c2ecf20Sopenharmony_ci break; 34068c2ecf20Sopenharmony_ci default: 34078c2ecf20Sopenharmony_ci break; 34088c2ecf20Sopenharmony_ci } 34098c2ecf20Sopenharmony_ci } 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci return rate_bitmap; 34128c2ecf20Sopenharmony_ci} 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_cistatic u32 _rtl8821ae_set_ra_vht_ratr_bitmap(struct ieee80211_hw *hw, 34158c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode, 34168c2ecf20Sopenharmony_ci u32 ratr_bitmap) 34178c2ecf20Sopenharmony_ci{ 34188c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 34198c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 34208c2ecf20Sopenharmony_ci u32 ret_bitmap = ratr_bitmap; 34218c2ecf20Sopenharmony_ci 34228c2ecf20Sopenharmony_ci if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40 34238c2ecf20Sopenharmony_ci || rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) 34248c2ecf20Sopenharmony_ci ret_bitmap = ratr_bitmap; 34258c2ecf20Sopenharmony_ci else if (wirelessmode == WIRELESS_MODE_AC_5G 34268c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_AC_24G) { 34278c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 34288c2ecf20Sopenharmony_ci ret_bitmap = ratr_bitmap & (~BIT21); 34298c2ecf20Sopenharmony_ci else 34308c2ecf20Sopenharmony_ci ret_bitmap = ratr_bitmap & (~(BIT31|BIT21)); 34318c2ecf20Sopenharmony_ci } 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci return ret_bitmap; 34348c2ecf20Sopenharmony_ci} 34358c2ecf20Sopenharmony_ci 34368c2ecf20Sopenharmony_cistatic u8 _rtl8821ae_get_vht_eni(enum wireless_mode wirelessmode, 34378c2ecf20Sopenharmony_ci u32 ratr_bitmap) 34388c2ecf20Sopenharmony_ci{ 34398c2ecf20Sopenharmony_ci u8 ret = 0; 34408c2ecf20Sopenharmony_ci if (wirelessmode < WIRELESS_MODE_N_24G) 34418c2ecf20Sopenharmony_ci ret = 0; 34428c2ecf20Sopenharmony_ci else if (wirelessmode == WIRELESS_MODE_AC_24G) { 34438c2ecf20Sopenharmony_ci if (ratr_bitmap & 0xfff00000) /* Mix , 2SS */ 34448c2ecf20Sopenharmony_ci ret = 3; 34458c2ecf20Sopenharmony_ci else /* Mix, 1SS */ 34468c2ecf20Sopenharmony_ci ret = 2; 34478c2ecf20Sopenharmony_ci } else if (wirelessmode == WIRELESS_MODE_AC_5G) { 34488c2ecf20Sopenharmony_ci ret = 1; 34498c2ecf20Sopenharmony_ci } /* VHT */ 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci return ret << 4; 34528c2ecf20Sopenharmony_ci} 34538c2ecf20Sopenharmony_ci 34548c2ecf20Sopenharmony_cistatic u8 _rtl8821ae_get_ra_ldpc(struct ieee80211_hw *hw, 34558c2ecf20Sopenharmony_ci u8 mac_id, struct rtl_sta_info *sta_entry, 34568c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode) 34578c2ecf20Sopenharmony_ci{ 34588c2ecf20Sopenharmony_ci u8 b_ldpc = 0; 34598c2ecf20Sopenharmony_ci /*not support ldpc, do not open*/ 34608c2ecf20Sopenharmony_ci return b_ldpc << 2; 34618c2ecf20Sopenharmony_ci} 34628c2ecf20Sopenharmony_ci 34638c2ecf20Sopenharmony_cistatic u8 _rtl8821ae_get_ra_rftype(struct ieee80211_hw *hw, 34648c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode, 34658c2ecf20Sopenharmony_ci u32 ratr_bitmap) 34668c2ecf20Sopenharmony_ci{ 34678c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 34688c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 34698c2ecf20Sopenharmony_ci u8 rf_type = RF_1T1R; 34708c2ecf20Sopenharmony_ci 34718c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 34728c2ecf20Sopenharmony_ci rf_type = RF_1T1R; 34738c2ecf20Sopenharmony_ci else if (wirelessmode == WIRELESS_MODE_AC_5G 34748c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_AC_24G 34758c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_AC_ONLY) { 34768c2ecf20Sopenharmony_ci if (ratr_bitmap & 0xffc00000) 34778c2ecf20Sopenharmony_ci rf_type = RF_2T2R; 34788c2ecf20Sopenharmony_ci } else if (wirelessmode == WIRELESS_MODE_N_5G 34798c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_N_24G) { 34808c2ecf20Sopenharmony_ci if (ratr_bitmap & 0xfff00000) 34818c2ecf20Sopenharmony_ci rf_type = RF_2T2R; 34828c2ecf20Sopenharmony_ci } 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ci return rf_type; 34858c2ecf20Sopenharmony_ci} 34868c2ecf20Sopenharmony_ci 34878c2ecf20Sopenharmony_cistatic bool _rtl8821ae_get_ra_shortgi(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 34888c2ecf20Sopenharmony_ci u8 mac_id) 34898c2ecf20Sopenharmony_ci{ 34908c2ecf20Sopenharmony_ci bool b_short_gi = false; 34918c2ecf20Sopenharmony_ci u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? 34928c2ecf20Sopenharmony_ci 1 : 0; 34938c2ecf20Sopenharmony_ci u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? 34948c2ecf20Sopenharmony_ci 1 : 0; 34958c2ecf20Sopenharmony_ci u8 b_curshortgi_80mhz = 0; 34968c2ecf20Sopenharmony_ci b_curshortgi_80mhz = (sta->vht_cap.cap & 34978c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SHORT_GI_80) ? 1 : 0; 34988c2ecf20Sopenharmony_ci 34998c2ecf20Sopenharmony_ci if (mac_id == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST) 35008c2ecf20Sopenharmony_ci b_short_gi = false; 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci if (b_curshortgi_40mhz || b_curshortgi_80mhz 35038c2ecf20Sopenharmony_ci || b_curshortgi_20mhz) 35048c2ecf20Sopenharmony_ci b_short_gi = true; 35058c2ecf20Sopenharmony_ci 35068c2ecf20Sopenharmony_ci return b_short_gi; 35078c2ecf20Sopenharmony_ci} 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_cistatic void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw, 35108c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u8 rssi_level, bool update_bw) 35118c2ecf20Sopenharmony_ci{ 35128c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 35138c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 35148c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 35158c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 35168c2ecf20Sopenharmony_ci u32 ratr_bitmap; 35178c2ecf20Sopenharmony_ci u8 ratr_index; 35188c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode = 0; 35198c2ecf20Sopenharmony_ci u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) 35208c2ecf20Sopenharmony_ci ? 1 : 0; 35218c2ecf20Sopenharmony_ci bool b_shortgi = false; 35228c2ecf20Sopenharmony_ci u8 rate_mask[7]; 35238c2ecf20Sopenharmony_ci u8 macid = 0; 35248c2ecf20Sopenharmony_ci u8 mimo_ps = IEEE80211_SMPS_OFF; 35258c2ecf20Sopenharmony_ci u8 rf_type; 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 35288c2ecf20Sopenharmony_ci wirelessmode = sta_entry->wireless_mode; 35298c2ecf20Sopenharmony_ci 35308c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RATR, DBG_LOUD, 35318c2ecf20Sopenharmony_ci "wireless mode = 0x%x\n", wirelessmode); 35328c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_STATION || 35338c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 35348c2ecf20Sopenharmony_ci curtxbw_40mhz = mac->bw_40; 35358c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_AP || 35368c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_ADHOC) 35378c2ecf20Sopenharmony_ci macid = sta->aid + 1; 35388c2ecf20Sopenharmony_ci if (wirelessmode == WIRELESS_MODE_N_5G || 35398c2ecf20Sopenharmony_ci wirelessmode == WIRELESS_MODE_AC_5G || 35408c2ecf20Sopenharmony_ci wirelessmode == WIRELESS_MODE_A) 35418c2ecf20Sopenharmony_ci ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4; 35428c2ecf20Sopenharmony_ci else 35438c2ecf20Sopenharmony_ci ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ]; 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_ADHOC) 35468c2ecf20Sopenharmony_ci ratr_bitmap = 0xfff; 35478c2ecf20Sopenharmony_ci 35488c2ecf20Sopenharmony_ci if (wirelessmode == WIRELESS_MODE_N_24G 35498c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_N_5G) 35508c2ecf20Sopenharmony_ci ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | 35518c2ecf20Sopenharmony_ci sta->ht_cap.mcs.rx_mask[0] << 12); 35528c2ecf20Sopenharmony_ci else if (wirelessmode == WIRELESS_MODE_AC_24G 35538c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_AC_5G 35548c2ecf20Sopenharmony_ci || wirelessmode == WIRELESS_MODE_AC_ONLY) 35558c2ecf20Sopenharmony_ci ratr_bitmap |= _rtl8821ae_rate_to_bitmap_2ssvht( 35568c2ecf20Sopenharmony_ci sta->vht_cap.vht_mcs.rx_mcs_map) << 12; 35578c2ecf20Sopenharmony_ci 35588c2ecf20Sopenharmony_ci b_shortgi = _rtl8821ae_get_ra_shortgi(hw, sta, macid); 35598c2ecf20Sopenharmony_ci rf_type = _rtl8821ae_get_ra_rftype(hw, wirelessmode, ratr_bitmap); 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci/*mac id owner*/ 35628c2ecf20Sopenharmony_ci switch (wirelessmode) { 35638c2ecf20Sopenharmony_ci case WIRELESS_MODE_B: 35648c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_B; 35658c2ecf20Sopenharmony_ci if (ratr_bitmap & 0x0000000c) 35668c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0000000d; 35678c2ecf20Sopenharmony_ci else 35688c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0000000f; 35698c2ecf20Sopenharmony_ci break; 35708c2ecf20Sopenharmony_ci case WIRELESS_MODE_G: 35718c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_GB; 35728c2ecf20Sopenharmony_ci 35738c2ecf20Sopenharmony_ci if (rssi_level == 1) 35748c2ecf20Sopenharmony_ci ratr_bitmap &= 0x00000f00; 35758c2ecf20Sopenharmony_ci else if (rssi_level == 2) 35768c2ecf20Sopenharmony_ci ratr_bitmap &= 0x00000ff0; 35778c2ecf20Sopenharmony_ci else 35788c2ecf20Sopenharmony_ci ratr_bitmap &= 0x00000ff5; 35798c2ecf20Sopenharmony_ci break; 35808c2ecf20Sopenharmony_ci case WIRELESS_MODE_A: 35818c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_G; 35828c2ecf20Sopenharmony_ci ratr_bitmap &= 0x00000ff0; 35838c2ecf20Sopenharmony_ci break; 35848c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_24G: 35858c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_5G: 35868c2ecf20Sopenharmony_ci if (wirelessmode == WIRELESS_MODE_N_24G) 35878c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_NGB; 35888c2ecf20Sopenharmony_ci else 35898c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_NG; 35908c2ecf20Sopenharmony_ci 35918c2ecf20Sopenharmony_ci if (mimo_ps == IEEE80211_SMPS_STATIC 35928c2ecf20Sopenharmony_ci || mimo_ps == IEEE80211_SMPS_DYNAMIC) { 35938c2ecf20Sopenharmony_ci if (rssi_level == 1) 35948c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000f0000; 35958c2ecf20Sopenharmony_ci else if (rssi_level == 2) 35968c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff000; 35978c2ecf20Sopenharmony_ci else 35988c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff005; 35998c2ecf20Sopenharmony_ci } else { 36008c2ecf20Sopenharmony_ci if (rf_type == RF_1T1R) { 36018c2ecf20Sopenharmony_ci if (curtxbw_40mhz) { 36028c2ecf20Sopenharmony_ci if (rssi_level == 1) 36038c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000f0000; 36048c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36058c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff000; 36068c2ecf20Sopenharmony_ci else 36078c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff015; 36088c2ecf20Sopenharmony_ci } else { 36098c2ecf20Sopenharmony_ci if (rssi_level == 1) 36108c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000f0000; 36118c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36128c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff000; 36138c2ecf20Sopenharmony_ci else 36148c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff005; 36158c2ecf20Sopenharmony_ci } 36168c2ecf20Sopenharmony_ci } else { 36178c2ecf20Sopenharmony_ci if (curtxbw_40mhz) { 36188c2ecf20Sopenharmony_ci if (rssi_level == 1) 36198c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0fff0000; 36208c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36218c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0ffff000; 36228c2ecf20Sopenharmony_ci else 36238c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0ffff015; 36248c2ecf20Sopenharmony_ci } else { 36258c2ecf20Sopenharmony_ci if (rssi_level == 1) 36268c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0fff0000; 36278c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36288c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0ffff000; 36298c2ecf20Sopenharmony_ci else 36308c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0ffff005; 36318c2ecf20Sopenharmony_ci } 36328c2ecf20Sopenharmony_ci } 36338c2ecf20Sopenharmony_ci } 36348c2ecf20Sopenharmony_ci break; 36358c2ecf20Sopenharmony_ci 36368c2ecf20Sopenharmony_ci case WIRELESS_MODE_AC_24G: 36378c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_AC_24N; 36388c2ecf20Sopenharmony_ci if (rssi_level == 1) 36398c2ecf20Sopenharmony_ci ratr_bitmap &= 0xfc3f0000; 36408c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36418c2ecf20Sopenharmony_ci ratr_bitmap &= 0xfffff000; 36428c2ecf20Sopenharmony_ci else 36438c2ecf20Sopenharmony_ci ratr_bitmap &= 0xffffffff; 36448c2ecf20Sopenharmony_ci break; 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci case WIRELESS_MODE_AC_5G: 36478c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_AC_5N; 36488c2ecf20Sopenharmony_ci 36498c2ecf20Sopenharmony_ci if (rf_type == RF_1T1R) { 36508c2ecf20Sopenharmony_ci if (rssi_level == 1) /*add by Gary for ac-series*/ 36518c2ecf20Sopenharmony_ci ratr_bitmap &= 0x003f8000; 36528c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36538c2ecf20Sopenharmony_ci ratr_bitmap &= 0x003ff000; 36548c2ecf20Sopenharmony_ci else 36558c2ecf20Sopenharmony_ci ratr_bitmap &= 0x003ff010; 36568c2ecf20Sopenharmony_ci } else { 36578c2ecf20Sopenharmony_ci if (rssi_level == 1) 36588c2ecf20Sopenharmony_ci ratr_bitmap &= 0xfe3f8000; 36598c2ecf20Sopenharmony_ci else if (rssi_level == 2) 36608c2ecf20Sopenharmony_ci ratr_bitmap &= 0xfffff000; 36618c2ecf20Sopenharmony_ci else 36628c2ecf20Sopenharmony_ci ratr_bitmap &= 0xfffff010; 36638c2ecf20Sopenharmony_ci } 36648c2ecf20Sopenharmony_ci break; 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci default: 36678c2ecf20Sopenharmony_ci ratr_index = RATR_INX_WIRELESS_NGB; 36688c2ecf20Sopenharmony_ci 36698c2ecf20Sopenharmony_ci if (rf_type == RF_1T2R) 36708c2ecf20Sopenharmony_ci ratr_bitmap &= 0x000ff0ff; 36718c2ecf20Sopenharmony_ci else 36728c2ecf20Sopenharmony_ci ratr_bitmap &= 0x0f8ff0ff; 36738c2ecf20Sopenharmony_ci break; 36748c2ecf20Sopenharmony_ci } 36758c2ecf20Sopenharmony_ci 36768c2ecf20Sopenharmony_ci ratr_index = rtl_mrate_idx_to_arfr_id(hw, ratr_index, wirelessmode); 36778c2ecf20Sopenharmony_ci sta_entry->ratr_index = ratr_index; 36788c2ecf20Sopenharmony_ci ratr_bitmap = _rtl8821ae_set_ra_vht_ratr_bitmap(hw, wirelessmode, 36798c2ecf20Sopenharmony_ci ratr_bitmap); 36808c2ecf20Sopenharmony_ci 36818c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RATR, DBG_LOUD, 36828c2ecf20Sopenharmony_ci "ratr_bitmap :%x\n", ratr_bitmap); 36838c2ecf20Sopenharmony_ci 36848c2ecf20Sopenharmony_ci /* *(u32 *)& rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | 36858c2ecf20Sopenharmony_ci (ratr_index << 28)); */ 36868c2ecf20Sopenharmony_ci 36878c2ecf20Sopenharmony_ci rate_mask[0] = macid; 36888c2ecf20Sopenharmony_ci rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00); 36898c2ecf20Sopenharmony_ci rate_mask[2] = rtlphy->current_chan_bw | ((!update_bw) << 3) 36908c2ecf20Sopenharmony_ci | _rtl8821ae_get_vht_eni(wirelessmode, ratr_bitmap) 36918c2ecf20Sopenharmony_ci | _rtl8821ae_get_ra_ldpc(hw, macid, sta_entry, wirelessmode); 36928c2ecf20Sopenharmony_ci 36938c2ecf20Sopenharmony_ci rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); 36948c2ecf20Sopenharmony_ci rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); 36958c2ecf20Sopenharmony_ci rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); 36968c2ecf20Sopenharmony_ci rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, 36998c2ecf20Sopenharmony_ci "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", 37008c2ecf20Sopenharmony_ci ratr_index, ratr_bitmap, 37018c2ecf20Sopenharmony_ci rate_mask[0], rate_mask[1], 37028c2ecf20Sopenharmony_ci rate_mask[2], rate_mask[3], 37038c2ecf20Sopenharmony_ci rate_mask[4], rate_mask[5], 37048c2ecf20Sopenharmony_ci rate_mask[6]); 37058c2ecf20Sopenharmony_ci rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RA_MASK, 7, rate_mask); 37068c2ecf20Sopenharmony_ci _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); 37078c2ecf20Sopenharmony_ci} 37088c2ecf20Sopenharmony_ci 37098c2ecf20Sopenharmony_civoid rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw, 37108c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u8 rssi_level, bool update_bw) 37118c2ecf20Sopenharmony_ci{ 37128c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 37138c2ecf20Sopenharmony_ci if (rtlpriv->dm.useramask) 37148c2ecf20Sopenharmony_ci rtl8821ae_update_hal_rate_mask(hw, sta, rssi_level, update_bw); 37158c2ecf20Sopenharmony_ci else 37168c2ecf20Sopenharmony_ci /*rtl_dbg(rtlpriv, COMP_RATR,DBG_LOUD, 37178c2ecf20Sopenharmony_ci "rtl8821ae_update_hal_rate_tbl() Error! 8821ae FW RA Only\n");*/ 37188c2ecf20Sopenharmony_ci rtl8821ae_update_hal_rate_table(hw, sta); 37198c2ecf20Sopenharmony_ci} 37208c2ecf20Sopenharmony_ci 37218c2ecf20Sopenharmony_civoid rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw) 37228c2ecf20Sopenharmony_ci{ 37238c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 37248c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 37258c2ecf20Sopenharmony_ci u16 wireless_mode = mac->mode; 37268c2ecf20Sopenharmony_ci u8 sifs_timer, r2t_sifs; 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, 37298c2ecf20Sopenharmony_ci (u8 *)&mac->slot_time); 37308c2ecf20Sopenharmony_ci if (wireless_mode == WIRELESS_MODE_G) 37318c2ecf20Sopenharmony_ci sifs_timer = 0x0a; 37328c2ecf20Sopenharmony_ci else 37338c2ecf20Sopenharmony_ci sifs_timer = 0x0e; 37348c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); 37358c2ecf20Sopenharmony_ci 37368c2ecf20Sopenharmony_ci r2t_sifs = 0xa; 37378c2ecf20Sopenharmony_ci 37388c2ecf20Sopenharmony_ci if (wireless_mode == WIRELESS_MODE_AC_5G && 37398c2ecf20Sopenharmony_ci (mac->vht_ldpc_cap & LDPC_VHT_ENABLE_RX) && 37408c2ecf20Sopenharmony_ci (mac->vht_stbc_cap & STBC_VHT_ENABLE_RX)) { 37418c2ecf20Sopenharmony_ci if (mac->vendor == PEER_ATH) 37428c2ecf20Sopenharmony_ci r2t_sifs = 0x8; 37438c2ecf20Sopenharmony_ci else 37448c2ecf20Sopenharmony_ci r2t_sifs = 0xa; 37458c2ecf20Sopenharmony_ci } else if (wireless_mode == WIRELESS_MODE_AC_5G) { 37468c2ecf20Sopenharmony_ci r2t_sifs = 0xa; 37478c2ecf20Sopenharmony_ci } 37488c2ecf20Sopenharmony_ci 37498c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_R2T_SIFS, (u8 *)&r2t_sifs); 37508c2ecf20Sopenharmony_ci} 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_cibool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) 37538c2ecf20Sopenharmony_ci{ 37548c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 37558c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 37568c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 37578c2ecf20Sopenharmony_ci enum rf_pwrstate e_rfpowerstate_toset; 37588c2ecf20Sopenharmony_ci u8 u1tmp = 0; 37598c2ecf20Sopenharmony_ci bool b_actuallyset = false; 37608c2ecf20Sopenharmony_ci 37618c2ecf20Sopenharmony_ci if (rtlpriv->rtlhal.being_init_adapter) 37628c2ecf20Sopenharmony_ci return false; 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci if (ppsc->swrf_processing) 37658c2ecf20Sopenharmony_ci return false; 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci spin_lock(&rtlpriv->locks.rf_ps_lock); 37688c2ecf20Sopenharmony_ci if (ppsc->rfchange_inprogress) { 37698c2ecf20Sopenharmony_ci spin_unlock(&rtlpriv->locks.rf_ps_lock); 37708c2ecf20Sopenharmony_ci return false; 37718c2ecf20Sopenharmony_ci } else { 37728c2ecf20Sopenharmony_ci ppsc->rfchange_inprogress = true; 37738c2ecf20Sopenharmony_ci spin_unlock(&rtlpriv->locks.rf_ps_lock); 37748c2ecf20Sopenharmony_ci } 37758c2ecf20Sopenharmony_ci 37768c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, 37778c2ecf20Sopenharmony_ci rtl_read_byte(rtlpriv, 37788c2ecf20Sopenharmony_ci REG_GPIO_IO_SEL_2) & ~(BIT(1))); 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); 37818c2ecf20Sopenharmony_ci 37828c2ecf20Sopenharmony_ci if (rtlphy->polarity_ctl) 37838c2ecf20Sopenharmony_ci e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; 37848c2ecf20Sopenharmony_ci else 37858c2ecf20Sopenharmony_ci e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { 37888c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG, 37898c2ecf20Sopenharmony_ci "GPIOChangeRF - HW Radio ON, RF ON\n"); 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci e_rfpowerstate_toset = ERFON; 37928c2ecf20Sopenharmony_ci ppsc->hwradiooff = false; 37938c2ecf20Sopenharmony_ci b_actuallyset = true; 37948c2ecf20Sopenharmony_ci } else if ((!ppsc->hwradiooff) 37958c2ecf20Sopenharmony_ci && (e_rfpowerstate_toset == ERFOFF)) { 37968c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG, 37978c2ecf20Sopenharmony_ci "GPIOChangeRF - HW Radio OFF, RF OFF\n"); 37988c2ecf20Sopenharmony_ci 37998c2ecf20Sopenharmony_ci e_rfpowerstate_toset = ERFOFF; 38008c2ecf20Sopenharmony_ci ppsc->hwradiooff = true; 38018c2ecf20Sopenharmony_ci b_actuallyset = true; 38028c2ecf20Sopenharmony_ci } 38038c2ecf20Sopenharmony_ci 38048c2ecf20Sopenharmony_ci if (b_actuallyset) { 38058c2ecf20Sopenharmony_ci spin_lock(&rtlpriv->locks.rf_ps_lock); 38068c2ecf20Sopenharmony_ci ppsc->rfchange_inprogress = false; 38078c2ecf20Sopenharmony_ci spin_unlock(&rtlpriv->locks.rf_ps_lock); 38088c2ecf20Sopenharmony_ci } else { 38098c2ecf20Sopenharmony_ci if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) 38108c2ecf20Sopenharmony_ci RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); 38118c2ecf20Sopenharmony_ci 38128c2ecf20Sopenharmony_ci spin_lock(&rtlpriv->locks.rf_ps_lock); 38138c2ecf20Sopenharmony_ci ppsc->rfchange_inprogress = false; 38148c2ecf20Sopenharmony_ci spin_unlock(&rtlpriv->locks.rf_ps_lock); 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci 38178c2ecf20Sopenharmony_ci *valid = 1; 38188c2ecf20Sopenharmony_ci return !ppsc->hwradiooff; 38198c2ecf20Sopenharmony_ci} 38208c2ecf20Sopenharmony_ci 38218c2ecf20Sopenharmony_civoid rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index, 38228c2ecf20Sopenharmony_ci u8 *p_macaddr, bool is_group, u8 enc_algo, 38238c2ecf20Sopenharmony_ci bool is_wepkey, bool clear_all) 38248c2ecf20Sopenharmony_ci{ 38258c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 38268c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 38278c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 38288c2ecf20Sopenharmony_ci u8 *macaddr = p_macaddr; 38298c2ecf20Sopenharmony_ci u32 entry_id = 0; 38308c2ecf20Sopenharmony_ci bool is_pairwise = false; 38318c2ecf20Sopenharmony_ci 38328c2ecf20Sopenharmony_ci static u8 cam_const_addr[4][6] = { 38338c2ecf20Sopenharmony_ci {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 38348c2ecf20Sopenharmony_ci {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 38358c2ecf20Sopenharmony_ci {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 38368c2ecf20Sopenharmony_ci {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} 38378c2ecf20Sopenharmony_ci }; 38388c2ecf20Sopenharmony_ci static u8 cam_const_broad[] = { 38398c2ecf20Sopenharmony_ci 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 38408c2ecf20Sopenharmony_ci }; 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci if (clear_all) { 38438c2ecf20Sopenharmony_ci u8 idx = 0; 38448c2ecf20Sopenharmony_ci u8 cam_offset = 0; 38458c2ecf20Sopenharmony_ci u8 clear_number = 5; 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_ci for (idx = 0; idx < clear_number; idx++) { 38508c2ecf20Sopenharmony_ci rtl_cam_mark_invalid(hw, cam_offset + idx); 38518c2ecf20Sopenharmony_ci rtl_cam_empty_entry(hw, cam_offset + idx); 38528c2ecf20Sopenharmony_ci 38538c2ecf20Sopenharmony_ci if (idx < 5) { 38548c2ecf20Sopenharmony_ci memset(rtlpriv->sec.key_buf[idx], 0, 38558c2ecf20Sopenharmony_ci MAX_KEY_LEN); 38568c2ecf20Sopenharmony_ci rtlpriv->sec.key_len[idx] = 0; 38578c2ecf20Sopenharmony_ci } 38588c2ecf20Sopenharmony_ci } 38598c2ecf20Sopenharmony_ci } else { 38608c2ecf20Sopenharmony_ci switch (enc_algo) { 38618c2ecf20Sopenharmony_ci case WEP40_ENCRYPTION: 38628c2ecf20Sopenharmony_ci enc_algo = CAM_WEP40; 38638c2ecf20Sopenharmony_ci break; 38648c2ecf20Sopenharmony_ci case WEP104_ENCRYPTION: 38658c2ecf20Sopenharmony_ci enc_algo = CAM_WEP104; 38668c2ecf20Sopenharmony_ci break; 38678c2ecf20Sopenharmony_ci case TKIP_ENCRYPTION: 38688c2ecf20Sopenharmony_ci enc_algo = CAM_TKIP; 38698c2ecf20Sopenharmony_ci break; 38708c2ecf20Sopenharmony_ci case AESCCMP_ENCRYPTION: 38718c2ecf20Sopenharmony_ci enc_algo = CAM_AES; 38728c2ecf20Sopenharmony_ci break; 38738c2ecf20Sopenharmony_ci default: 38748c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, 38758c2ecf20Sopenharmony_ci "switch case %#x not processed\n", enc_algo); 38768c2ecf20Sopenharmony_ci enc_algo = CAM_TKIP; 38778c2ecf20Sopenharmony_ci break; 38788c2ecf20Sopenharmony_ci } 38798c2ecf20Sopenharmony_ci 38808c2ecf20Sopenharmony_ci if (is_wepkey || rtlpriv->sec.use_defaultkey) { 38818c2ecf20Sopenharmony_ci macaddr = cam_const_addr[key_index]; 38828c2ecf20Sopenharmony_ci entry_id = key_index; 38838c2ecf20Sopenharmony_ci } else { 38848c2ecf20Sopenharmony_ci if (is_group) { 38858c2ecf20Sopenharmony_ci macaddr = cam_const_broad; 38868c2ecf20Sopenharmony_ci entry_id = key_index; 38878c2ecf20Sopenharmony_ci } else { 38888c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_AP) { 38898c2ecf20Sopenharmony_ci entry_id = rtl_cam_get_free_entry(hw, p_macaddr); 38908c2ecf20Sopenharmony_ci if (entry_id >= TOTAL_CAM_ENTRY) { 38918c2ecf20Sopenharmony_ci pr_err("an not find free hwsecurity cam entry\n"); 38928c2ecf20Sopenharmony_ci return; 38938c2ecf20Sopenharmony_ci } 38948c2ecf20Sopenharmony_ci } else { 38958c2ecf20Sopenharmony_ci entry_id = CAM_PAIRWISE_KEY_POSITION; 38968c2ecf20Sopenharmony_ci } 38978c2ecf20Sopenharmony_ci 38988c2ecf20Sopenharmony_ci key_index = PAIRWISE_KEYIDX; 38998c2ecf20Sopenharmony_ci is_pairwise = true; 39008c2ecf20Sopenharmony_ci } 39018c2ecf20Sopenharmony_ci } 39028c2ecf20Sopenharmony_ci 39038c2ecf20Sopenharmony_ci if (rtlpriv->sec.key_len[key_index] == 0) { 39048c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 39058c2ecf20Sopenharmony_ci "delete one entry, entry_id is %d\n", 39068c2ecf20Sopenharmony_ci entry_id); 39078c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_AP) 39088c2ecf20Sopenharmony_ci rtl_cam_del_entry(hw, p_macaddr); 39098c2ecf20Sopenharmony_ci rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); 39108c2ecf20Sopenharmony_ci } else { 39118c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 39128c2ecf20Sopenharmony_ci "add one entry\n"); 39138c2ecf20Sopenharmony_ci if (is_pairwise) { 39148c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 39158c2ecf20Sopenharmony_ci "set Pairwise key\n"); 39168c2ecf20Sopenharmony_ci 39178c2ecf20Sopenharmony_ci rtl_cam_add_one_entry(hw, macaddr, key_index, 39188c2ecf20Sopenharmony_ci entry_id, enc_algo, 39198c2ecf20Sopenharmony_ci CAM_CONFIG_NO_USEDK, 39208c2ecf20Sopenharmony_ci rtlpriv->sec.key_buf[key_index]); 39218c2ecf20Sopenharmony_ci } else { 39228c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 39238c2ecf20Sopenharmony_ci "set group key\n"); 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_ADHOC) { 39268c2ecf20Sopenharmony_ci rtl_cam_add_one_entry(hw, 39278c2ecf20Sopenharmony_ci rtlefuse->dev_addr, 39288c2ecf20Sopenharmony_ci PAIRWISE_KEYIDX, 39298c2ecf20Sopenharmony_ci CAM_PAIRWISE_KEY_POSITION, 39308c2ecf20Sopenharmony_ci enc_algo, 39318c2ecf20Sopenharmony_ci CAM_CONFIG_NO_USEDK, 39328c2ecf20Sopenharmony_ci rtlpriv->sec.key_buf 39338c2ecf20Sopenharmony_ci [entry_id]); 39348c2ecf20Sopenharmony_ci } 39358c2ecf20Sopenharmony_ci 39368c2ecf20Sopenharmony_ci rtl_cam_add_one_entry(hw, macaddr, key_index, 39378c2ecf20Sopenharmony_ci entry_id, enc_algo, 39388c2ecf20Sopenharmony_ci CAM_CONFIG_NO_USEDK, 39398c2ecf20Sopenharmony_ci rtlpriv->sec.key_buf[entry_id]); 39408c2ecf20Sopenharmony_ci } 39418c2ecf20Sopenharmony_ci } 39428c2ecf20Sopenharmony_ci } 39438c2ecf20Sopenharmony_ci} 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_civoid rtl8821ae_bt_reg_init(struct ieee80211_hw *hw) 39468c2ecf20Sopenharmony_ci{ 39478c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 39488c2ecf20Sopenharmony_ci 39498c2ecf20Sopenharmony_ci /* 0:Low, 1:High, 2:From Efuse. */ 39508c2ecf20Sopenharmony_ci rtlpriv->btcoexist.reg_bt_iso = 2; 39518c2ecf20Sopenharmony_ci /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ 39528c2ecf20Sopenharmony_ci rtlpriv->btcoexist.reg_bt_sco = 3; 39538c2ecf20Sopenharmony_ci /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ 39548c2ecf20Sopenharmony_ci rtlpriv->btcoexist.reg_bt_sco = 0; 39558c2ecf20Sopenharmony_ci} 39568c2ecf20Sopenharmony_ci 39578c2ecf20Sopenharmony_civoid rtl8821ae_bt_hw_init(struct ieee80211_hw *hw) 39588c2ecf20Sopenharmony_ci{ 39598c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 39608c2ecf20Sopenharmony_ci 39618c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 39628c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); 39638c2ecf20Sopenharmony_ci} 39648c2ecf20Sopenharmony_ci 39658c2ecf20Sopenharmony_civoid rtl8821ae_suspend(struct ieee80211_hw *hw) 39668c2ecf20Sopenharmony_ci{ 39678c2ecf20Sopenharmony_ci} 39688c2ecf20Sopenharmony_ci 39698c2ecf20Sopenharmony_civoid rtl8821ae_resume(struct ieee80211_hw *hw) 39708c2ecf20Sopenharmony_ci{ 39718c2ecf20Sopenharmony_ci} 39728c2ecf20Sopenharmony_ci 39738c2ecf20Sopenharmony_ci/* Turn on AAP (RCR:bit 0) for promicuous mode. */ 39748c2ecf20Sopenharmony_civoid rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw, 39758c2ecf20Sopenharmony_ci bool allow_all_da, bool write_into_reg) 39768c2ecf20Sopenharmony_ci{ 39778c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 39788c2ecf20Sopenharmony_ci struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 39798c2ecf20Sopenharmony_ci 39808c2ecf20Sopenharmony_ci if (allow_all_da) /* Set BIT0 */ 39818c2ecf20Sopenharmony_ci rtlpci->receive_config |= RCR_AAP; 39828c2ecf20Sopenharmony_ci else /* Clear BIT0 */ 39838c2ecf20Sopenharmony_ci rtlpci->receive_config &= ~RCR_AAP; 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci if (write_into_reg) 39868c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); 39878c2ecf20Sopenharmony_ci 39888c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, 39898c2ecf20Sopenharmony_ci "receive_config=0x%08X, write_into_reg=%d\n", 39908c2ecf20Sopenharmony_ci rtlpci->receive_config, write_into_reg); 39918c2ecf20Sopenharmony_ci} 39928c2ecf20Sopenharmony_ci 39938c2ecf20Sopenharmony_ci/* WKFMCAMAddAllEntry8812 */ 39948c2ecf20Sopenharmony_civoid rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, 39958c2ecf20Sopenharmony_ci struct rtl_wow_pattern *rtl_pattern, 39968c2ecf20Sopenharmony_ci u8 index) 39978c2ecf20Sopenharmony_ci{ 39988c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 39998c2ecf20Sopenharmony_ci u32 cam = 0; 40008c2ecf20Sopenharmony_ci u8 addr = 0; 40018c2ecf20Sopenharmony_ci u16 rxbuf_addr; 40028c2ecf20Sopenharmony_ci u8 tmp, count = 0; 40038c2ecf20Sopenharmony_ci u16 cam_start; 40048c2ecf20Sopenharmony_ci u16 offset; 40058c2ecf20Sopenharmony_ci 40068c2ecf20Sopenharmony_ci /* Count the WFCAM entry start offset. */ 40078c2ecf20Sopenharmony_ci 40088c2ecf20Sopenharmony_ci /* RX page size = 128 byte */ 40098c2ecf20Sopenharmony_ci offset = MAX_RX_DMA_BUFFER_SIZE_8812 / 128; 40108c2ecf20Sopenharmony_ci /* We should start from the boundry */ 40118c2ecf20Sopenharmony_ci cam_start = offset * 128; 40128c2ecf20Sopenharmony_ci 40138c2ecf20Sopenharmony_ci /* Enable Rx packet buffer access. */ 40148c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); 40158c2ecf20Sopenharmony_ci for (addr = 0; addr < WKFMCAM_ADDR_NUM; addr++) { 40168c2ecf20Sopenharmony_ci /* Set Rx packet buffer offset. 40178c2ecf20Sopenharmony_ci * RXBufer pointer increases 1, 40188c2ecf20Sopenharmony_ci * we can access 8 bytes in Rx packet buffer. 40198c2ecf20Sopenharmony_ci * CAM start offset (unit: 1 byte) = index*WKFMCAM_SIZE 40208c2ecf20Sopenharmony_ci * RXBufer addr = (CAM start offset + 40218c2ecf20Sopenharmony_ci * per entry offset of a WKFM CAM)/8 40228c2ecf20Sopenharmony_ci * * index: The index of the wake up frame mask 40238c2ecf20Sopenharmony_ci * * WKFMCAM_SIZE: the total size of one WKFM CAM 40248c2ecf20Sopenharmony_ci * * per entry offset of a WKFM CAM: Addr*4 bytes 40258c2ecf20Sopenharmony_ci */ 40268c2ecf20Sopenharmony_ci rxbuf_addr = (cam_start + index * WKFMCAM_SIZE + addr * 4) >> 3; 40278c2ecf20Sopenharmony_ci /* Set R/W start offset */ 40288c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_PKTBUF_DBG_CTRL, rxbuf_addr); 40298c2ecf20Sopenharmony_ci 40308c2ecf20Sopenharmony_ci if (addr == 0) { 40318c2ecf20Sopenharmony_ci cam = BIT(31) | rtl_pattern->crc; 40328c2ecf20Sopenharmony_ci 40338c2ecf20Sopenharmony_ci if (rtl_pattern->type == UNICAST_PATTERN) 40348c2ecf20Sopenharmony_ci cam |= BIT(24); 40358c2ecf20Sopenharmony_ci else if (rtl_pattern->type == MULTICAST_PATTERN) 40368c2ecf20Sopenharmony_ci cam |= BIT(25); 40378c2ecf20Sopenharmony_ci else if (rtl_pattern->type == BROADCAST_PATTERN) 40388c2ecf20Sopenharmony_ci cam |= BIT(26); 40398c2ecf20Sopenharmony_ci 40408c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); 40418c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE, 40428c2ecf20Sopenharmony_ci "WRITE entry[%d] 0x%x: %x\n", addr, 40438c2ecf20Sopenharmony_ci REG_PKTBUF_DBG_DATA_L, cam); 40448c2ecf20Sopenharmony_ci 40458c2ecf20Sopenharmony_ci /* Write to Rx packet buffer. */ 40468c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); 40478c2ecf20Sopenharmony_ci } else if (addr == 2 || addr == 4) {/* WKFM[127:0] */ 40488c2ecf20Sopenharmony_ci cam = rtl_pattern->mask[addr - 2]; 40498c2ecf20Sopenharmony_ci 40508c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); 40518c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE, 40528c2ecf20Sopenharmony_ci "WRITE entry[%d] 0x%x: %x\n", addr, 40538c2ecf20Sopenharmony_ci REG_PKTBUF_DBG_DATA_L, cam); 40548c2ecf20Sopenharmony_ci 40558c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); 40568c2ecf20Sopenharmony_ci } else if (addr == 3 || addr == 5) {/* WKFM[127:0] */ 40578c2ecf20Sopenharmony_ci cam = rtl_pattern->mask[addr - 2]; 40588c2ecf20Sopenharmony_ci 40598c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_H, cam); 40608c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE, 40618c2ecf20Sopenharmony_ci "WRITE entry[%d] 0x%x: %x\n", addr, 40628c2ecf20Sopenharmony_ci REG_PKTBUF_DBG_DATA_H, cam); 40638c2ecf20Sopenharmony_ci 40648c2ecf20Sopenharmony_ci rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0xf001); 40658c2ecf20Sopenharmony_ci } 40668c2ecf20Sopenharmony_ci 40678c2ecf20Sopenharmony_ci count = 0; 40688c2ecf20Sopenharmony_ci do { 40698c2ecf20Sopenharmony_ci tmp = rtl_read_byte(rtlpriv, REG_RXPKTBUF_CTRL); 40708c2ecf20Sopenharmony_ci udelay(2); 40718c2ecf20Sopenharmony_ci count++; 40728c2ecf20Sopenharmony_ci } while (tmp && count < 100); 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci WARN_ONCE((count >= 100), 40758c2ecf20Sopenharmony_ci "rtl8821ae: Write wake up frame mask FAIL %d value!\n", 40768c2ecf20Sopenharmony_ci tmp); 40778c2ecf20Sopenharmony_ci } 40788c2ecf20Sopenharmony_ci /* Disable Rx packet buffer access. */ 40798c2ecf20Sopenharmony_ci rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, 40808c2ecf20Sopenharmony_ci DISABLE_TRXPKT_BUF_ACCESS); 40818c2ecf20Sopenharmony_ci} 4082