xref: /openbmc/linux/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
193121c03SLarry Finger // SPDX-License-Identifier: GPL-2.0
293121c03SLarry Finger /* Copyright(c) 2009-2014  Realtek Corporation.*/
3f1d2b4d3SLarry Finger 
4f1d2b4d3SLarry Finger #include "../wifi.h"
5f1d2b4d3SLarry Finger #include "../efuse.h"
6f1d2b4d3SLarry Finger #include "../base.h"
7f1d2b4d3SLarry Finger #include "../regd.h"
8f1d2b4d3SLarry Finger #include "../cam.h"
9f1d2b4d3SLarry Finger #include "../ps.h"
10f1d2b4d3SLarry Finger #include "../pci.h"
11f1d2b4d3SLarry Finger #include "reg.h"
12f1d2b4d3SLarry Finger #include "def.h"
13f1d2b4d3SLarry Finger #include "phy.h"
14f1d2b4d3SLarry Finger #include "../rtl8723com/phy_common.h"
15f1d2b4d3SLarry Finger #include "dm.h"
16f1d2b4d3SLarry Finger #include "../rtl8723com/dm_common.h"
17f1d2b4d3SLarry Finger #include "fw.h"
18f1d2b4d3SLarry Finger #include "../rtl8723com/fw_common.h"
19f1d2b4d3SLarry Finger #include "led.h"
20f1d2b4d3SLarry Finger #include "hw.h"
21f1d2b4d3SLarry Finger #include "../pwrseqcmd.h"
22f1d2b4d3SLarry Finger #include "pwrseq.h"
23f1d2b4d3SLarry Finger #include "../btcoexist/rtl_btc.h"
2453ac7935SJérémy Lefaure #include <linux/kernel.h>
25f1d2b4d3SLarry Finger 
26f1d2b4d3SLarry Finger #define LLT_CONFIG	5
27f1d2b4d3SLarry Finger 
_rtl8723be_return_beacon_queue_skb(struct ieee80211_hw * hw)28f1d2b4d3SLarry Finger static void _rtl8723be_return_beacon_queue_skb(struct ieee80211_hw *hw)
29f1d2b4d3SLarry Finger {
30f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
31f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
32f1d2b4d3SLarry Finger 	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE];
33f1d2b4d3SLarry Finger 	struct sk_buff_head free_list;
34f1d2b4d3SLarry Finger 	unsigned long flags;
35f1d2b4d3SLarry Finger 
36f1d2b4d3SLarry Finger 	skb_queue_head_init(&free_list);
37f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
38f1d2b4d3SLarry Finger 	while (skb_queue_len(&ring->queue)) {
39f1d2b4d3SLarry Finger 		struct rtl_tx_desc *entry = &ring->desc[ring->idx];
400dc0b5c2SChristophe JAILLET 		struct sk_buff *skb = __skb_dequeue(&ring->queue);
410dc0b5c2SChristophe JAILLET 
420dc0b5c2SChristophe JAILLET 		dma_unmap_single(&rtlpci->pdev->dev,
430dc0b5c2SChristophe JAILLET 				 rtlpriv->cfg->ops->get_desc(hw, (u8 *)entry,
44f1d2b4d3SLarry Finger 						true, HW_DESC_TXBUFF_ADDR),
45f1d2b4d3SLarry Finger 				 skb->len, DMA_TO_DEVICE);
46f1d2b4d3SLarry Finger 		__skb_queue_tail(&free_list, skb);
47f1d2b4d3SLarry Finger 		ring->idx = (ring->idx + 1) % ring->entries;
48f1d2b4d3SLarry Finger 	}
49f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
50f1d2b4d3SLarry Finger 
51f1d2b4d3SLarry Finger 	__skb_queue_purge(&free_list);
52f1d2b4d3SLarry Finger }
53f1d2b4d3SLarry Finger 
_rtl8723be_set_bcn_ctrl_reg(struct ieee80211_hw * hw,u8 set_bits,u8 clear_bits)54f1d2b4d3SLarry Finger static void _rtl8723be_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
55f1d2b4d3SLarry Finger 					u8 set_bits, u8 clear_bits)
56f1d2b4d3SLarry Finger {
57f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
58f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
59f1d2b4d3SLarry Finger 
60f1d2b4d3SLarry Finger 	rtlpci->reg_bcn_ctrl_val |= set_bits;
61f1d2b4d3SLarry Finger 	rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
62f1d2b4d3SLarry Finger 
63f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val);
64f1d2b4d3SLarry Finger }
65f1d2b4d3SLarry Finger 
_rtl8723be_stop_tx_beacon(struct ieee80211_hw * hw)66f1d2b4d3SLarry Finger static void _rtl8723be_stop_tx_beacon(struct ieee80211_hw *hw)
67f1d2b4d3SLarry Finger {
68f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
69f1d2b4d3SLarry Finger 	u8 tmp1byte;
70f1d2b4d3SLarry Finger 
71f1d2b4d3SLarry Finger 	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
72f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
73f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
74f1d2b4d3SLarry Finger 	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
75f1d2b4d3SLarry Finger 	tmp1byte &= ~(BIT(0));
76f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
77f1d2b4d3SLarry Finger }
78f1d2b4d3SLarry Finger 
_rtl8723be_resume_tx_beacon(struct ieee80211_hw * hw)79f1d2b4d3SLarry Finger static void _rtl8723be_resume_tx_beacon(struct ieee80211_hw *hw)
80f1d2b4d3SLarry Finger {
81f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
82f1d2b4d3SLarry Finger 	u8 tmp1byte;
83f1d2b4d3SLarry Finger 
84f1d2b4d3SLarry Finger 	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
85f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
86f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
87f1d2b4d3SLarry Finger 	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
88f1d2b4d3SLarry Finger 	tmp1byte |= BIT(1);
89f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
90f1d2b4d3SLarry Finger }
91f1d2b4d3SLarry Finger 
_rtl8723be_enable_bcn_sub_func(struct ieee80211_hw * hw)92f1d2b4d3SLarry Finger static void _rtl8723be_enable_bcn_sub_func(struct ieee80211_hw *hw)
93f1d2b4d3SLarry Finger {
94f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(1));
95f1d2b4d3SLarry Finger }
96f1d2b4d3SLarry Finger 
_rtl8723be_disable_bcn_sub_func(struct ieee80211_hw * hw)97f1d2b4d3SLarry Finger static void _rtl8723be_disable_bcn_sub_func(struct ieee80211_hw *hw)
98f1d2b4d3SLarry Finger {
99f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, BIT(1), 0);
100f1d2b4d3SLarry Finger }
101f1d2b4d3SLarry Finger 
_rtl8723be_set_fw_clock_on(struct ieee80211_hw * hw,u8 rpwm_val,bool b_need_turn_off_ckk)102f1d2b4d3SLarry Finger static void _rtl8723be_set_fw_clock_on(struct ieee80211_hw *hw, u8 rpwm_val,
103f1d2b4d3SLarry Finger 				       bool b_need_turn_off_ckk)
104f1d2b4d3SLarry Finger {
105f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
106f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
107f1d2b4d3SLarry Finger 	bool b_support_remote_wake_up;
108f1d2b4d3SLarry Finger 	u32 count = 0, isr_regaddr, content;
109f1d2b4d3SLarry Finger 	bool b_schedule_timer = b_need_turn_off_ckk;
110f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN,
111f1d2b4d3SLarry Finger 				      (u8 *)(&b_support_remote_wake_up));
112f1d2b4d3SLarry Finger 
113f1d2b4d3SLarry Finger 	if (!rtlhal->fw_ready)
114f1d2b4d3SLarry Finger 		return;
115f1d2b4d3SLarry Finger 	if (!rtlpriv->psc.fw_current_inpsmode)
116f1d2b4d3SLarry Finger 		return;
117f1d2b4d3SLarry Finger 
118f1d2b4d3SLarry Finger 	while (1) {
119f1d2b4d3SLarry Finger 		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
120f1d2b4d3SLarry Finger 		if (rtlhal->fw_clk_change_in_progress) {
121f1d2b4d3SLarry Finger 			while (rtlhal->fw_clk_change_in_progress) {
122f1d2b4d3SLarry Finger 				spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
123f1d2b4d3SLarry Finger 				count++;
124f1d2b4d3SLarry Finger 				udelay(100);
125f1d2b4d3SLarry Finger 				if (count > 1000)
126f1d2b4d3SLarry Finger 					return;
127f1d2b4d3SLarry Finger 				spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
128f1d2b4d3SLarry Finger 			}
129f1d2b4d3SLarry Finger 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
130f1d2b4d3SLarry Finger 		} else {
131f1d2b4d3SLarry Finger 			rtlhal->fw_clk_change_in_progress = false;
132f1d2b4d3SLarry Finger 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
133f1d2b4d3SLarry Finger 			break;
134f1d2b4d3SLarry Finger 		}
135f1d2b4d3SLarry Finger 	}
136f1d2b4d3SLarry Finger 
137f1d2b4d3SLarry Finger 	if (IS_IN_LOW_POWER_STATE(rtlhal->fw_ps_state)) {
138f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM,
139f1d2b4d3SLarry Finger 					      (u8 *)(&rpwm_val));
140f1d2b4d3SLarry Finger 		if (FW_PS_IS_ACK(rpwm_val)) {
141f1d2b4d3SLarry Finger 			isr_regaddr = REG_HISR;
142f1d2b4d3SLarry Finger 			content = rtl_read_dword(rtlpriv, isr_regaddr);
143f1d2b4d3SLarry Finger 			while (!(content & IMR_CPWM) && (count < 500)) {
144f1d2b4d3SLarry Finger 				udelay(50);
145f1d2b4d3SLarry Finger 				count++;
146f1d2b4d3SLarry Finger 				content = rtl_read_dword(rtlpriv, isr_regaddr);
147f1d2b4d3SLarry Finger 			}
148e6dd230aSLarry Finger 
149f1d2b4d3SLarry Finger 			if (content & IMR_CPWM) {
150f1d2b4d3SLarry Finger 				rtl_write_word(rtlpriv, isr_regaddr, 0x0100);
151f1d2b4d3SLarry Finger 				rtlhal->fw_ps_state = FW_PS_STATE_RF_ON;
152f1d2b4d3SLarry Finger 				rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
153f1d2b4d3SLarry Finger 					"Receive CPWM INT!!! Set pHalData->FwPSState = %X\n",
154f1d2b4d3SLarry Finger 					rtlhal->fw_ps_state);
155f1d2b4d3SLarry Finger 			}
156f1d2b4d3SLarry Finger 		}
157f1d2b4d3SLarry Finger 
158f1d2b4d3SLarry Finger 		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
159f1d2b4d3SLarry Finger 		rtlhal->fw_clk_change_in_progress = false;
160f1d2b4d3SLarry Finger 		spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
161f1d2b4d3SLarry Finger 		if (b_schedule_timer)
162f1d2b4d3SLarry Finger 			mod_timer(&rtlpriv->works.fw_clockoff_timer,
163f1d2b4d3SLarry Finger 				  jiffies + MSECS(10));
164f1d2b4d3SLarry Finger 	} else  {
165f1d2b4d3SLarry Finger 		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
166f1d2b4d3SLarry Finger 		rtlhal->fw_clk_change_in_progress = false;
167f1d2b4d3SLarry Finger 		spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
168f1d2b4d3SLarry Finger 	}
169f1d2b4d3SLarry Finger }
170f1d2b4d3SLarry Finger 
_rtl8723be_set_fw_clock_off(struct ieee80211_hw * hw,u8 rpwm_val)171f1d2b4d3SLarry Finger static void _rtl8723be_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val)
172f1d2b4d3SLarry Finger {
173f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
174f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
175f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
176f1d2b4d3SLarry Finger 	struct rtl8192_tx_ring *ring;
177f1d2b4d3SLarry Finger 	enum rf_pwrstate rtstate;
178f1d2b4d3SLarry Finger 	bool b_schedule_timer = false;
179f1d2b4d3SLarry Finger 	u8 queue;
180f1d2b4d3SLarry Finger 
181f1d2b4d3SLarry Finger 	if (!rtlhal->fw_ready)
182f1d2b4d3SLarry Finger 		return;
183f1d2b4d3SLarry Finger 	if (!rtlpriv->psc.fw_current_inpsmode)
184f1d2b4d3SLarry Finger 		return;
185f1d2b4d3SLarry Finger 	if (!rtlhal->allow_sw_to_change_hwclc)
186f1d2b4d3SLarry Finger 		return;
187f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate));
188f1d2b4d3SLarry Finger 	if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF)
189f1d2b4d3SLarry Finger 		return;
190f1d2b4d3SLarry Finger 
191f1d2b4d3SLarry Finger 	for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) {
192f1d2b4d3SLarry Finger 		ring = &rtlpci->tx_ring[queue];
193f1d2b4d3SLarry Finger 		if (skb_queue_len(&ring->queue)) {
194f1d2b4d3SLarry Finger 			b_schedule_timer = true;
195f1d2b4d3SLarry Finger 			break;
196f1d2b4d3SLarry Finger 		}
197f1d2b4d3SLarry Finger 	}
198f1d2b4d3SLarry Finger 
199f1d2b4d3SLarry Finger 	if (b_schedule_timer) {
200f1d2b4d3SLarry Finger 		mod_timer(&rtlpriv->works.fw_clockoff_timer,
201f1d2b4d3SLarry Finger 			  jiffies + MSECS(10));
202f1d2b4d3SLarry Finger 		return;
203f1d2b4d3SLarry Finger 	}
204f1d2b4d3SLarry Finger 
205f1d2b4d3SLarry Finger 	if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) {
206f1d2b4d3SLarry Finger 		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
207f1d2b4d3SLarry Finger 		if (!rtlhal->fw_clk_change_in_progress) {
208f1d2b4d3SLarry Finger 			rtlhal->fw_clk_change_in_progress = true;
209f1d2b4d3SLarry Finger 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
210f1d2b4d3SLarry Finger 			rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val);
211f1d2b4d3SLarry Finger 			rtl_write_word(rtlpriv, REG_HISR, 0x0100);
212f1d2b4d3SLarry Finger 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
213f1d2b4d3SLarry Finger 						      (u8 *)(&rpwm_val));
214f1d2b4d3SLarry Finger 			spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
215f1d2b4d3SLarry Finger 			rtlhal->fw_clk_change_in_progress = false;
216f1d2b4d3SLarry Finger 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
217f1d2b4d3SLarry Finger 		} else {
218f1d2b4d3SLarry Finger 			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
219f1d2b4d3SLarry Finger 			mod_timer(&rtlpriv->works.fw_clockoff_timer,
220f1d2b4d3SLarry Finger 				  jiffies + MSECS(10));
221f1d2b4d3SLarry Finger 		}
222f1d2b4d3SLarry Finger 	}
223f1d2b4d3SLarry Finger 
224f1d2b4d3SLarry Finger }
225f1d2b4d3SLarry Finger 
_rtl8723be_set_fw_ps_rf_on(struct ieee80211_hw * hw)226f1d2b4d3SLarry Finger static void _rtl8723be_set_fw_ps_rf_on(struct ieee80211_hw *hw)
227f1d2b4d3SLarry Finger {
228f1d2b4d3SLarry Finger 	u8 rpwm_val = 0;
229f1d2b4d3SLarry Finger 	rpwm_val |= (FW_PS_STATE_RF_OFF | FW_PS_ACK);
230f1d2b4d3SLarry Finger 	_rtl8723be_set_fw_clock_on(hw, rpwm_val, true);
231f1d2b4d3SLarry Finger }
232f1d2b4d3SLarry Finger 
_rtl8723be_fwlps_leave(struct ieee80211_hw * hw)233f1d2b4d3SLarry Finger static void _rtl8723be_fwlps_leave(struct ieee80211_hw *hw)
234f1d2b4d3SLarry Finger {
235f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
236f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
237f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
238f1d2b4d3SLarry Finger 	bool fw_current_inps = false;
239f1d2b4d3SLarry Finger 	u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE;
240f1d2b4d3SLarry Finger 
241f1d2b4d3SLarry Finger 	if (ppsc->low_power_enable) {
242f1d2b4d3SLarry Finger 		rpwm_val = (FW_PS_STATE_ALL_ON | FW_PS_ACK);/* RF on */
243f1d2b4d3SLarry Finger 		_rtl8723be_set_fw_clock_on(hw, rpwm_val, false);
244f1d2b4d3SLarry Finger 		rtlhal->allow_sw_to_change_hwclc = false;
245f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
246f1d2b4d3SLarry Finger 					      (u8 *)(&fw_pwrmode));
247f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
248f1d2b4d3SLarry Finger 					      (u8 *)(&fw_current_inps));
249f1d2b4d3SLarry Finger 	} else {
250f1d2b4d3SLarry Finger 		rpwm_val = FW_PS_STATE_ALL_ON;	/* RF on */
251f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
252f1d2b4d3SLarry Finger 					      (u8 *)(&rpwm_val));
253f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
254f1d2b4d3SLarry Finger 					      (u8 *)(&fw_pwrmode));
255f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
256f1d2b4d3SLarry Finger 					      (u8 *)(&fw_current_inps));
257f1d2b4d3SLarry Finger 	}
258f1d2b4d3SLarry Finger 
259f1d2b4d3SLarry Finger }
260f1d2b4d3SLarry Finger 
_rtl8723be_fwlps_enter(struct ieee80211_hw * hw)261f1d2b4d3SLarry Finger static void _rtl8723be_fwlps_enter(struct ieee80211_hw *hw)
262f1d2b4d3SLarry Finger {
263f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
264f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
265f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
266f1d2b4d3SLarry Finger 	bool fw_current_inps = true;
267f1d2b4d3SLarry Finger 	u8 rpwm_val;
268f1d2b4d3SLarry Finger 
269f1d2b4d3SLarry Finger 	if (ppsc->low_power_enable) {
270f1d2b4d3SLarry Finger 		rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR;	/* RF off */
271f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
272f1d2b4d3SLarry Finger 					      (u8 *)(&fw_current_inps));
273f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
274f1d2b4d3SLarry Finger 					      (u8 *)(&ppsc->fwctrl_psmode));
275f1d2b4d3SLarry Finger 		rtlhal->allow_sw_to_change_hwclc = true;
276f1d2b4d3SLarry Finger 		_rtl8723be_set_fw_clock_off(hw, rpwm_val);
277f1d2b4d3SLarry Finger 	} else {
278f1d2b4d3SLarry Finger 		rpwm_val = FW_PS_STATE_RF_OFF;	/* RF off */
279f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
280f1d2b4d3SLarry Finger 					      (u8 *)(&fw_current_inps));
281f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
282f1d2b4d3SLarry Finger 					      (u8 *)(&ppsc->fwctrl_psmode));
283f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
284f1d2b4d3SLarry Finger 					      (u8 *)(&rpwm_val));
285f1d2b4d3SLarry Finger 	}
286f1d2b4d3SLarry Finger 
287f1d2b4d3SLarry Finger }
288f1d2b4d3SLarry Finger 
rtl8723be_get_hw_reg(struct ieee80211_hw * hw,u8 variable,u8 * val)289f1d2b4d3SLarry Finger void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
290f1d2b4d3SLarry Finger {
291f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
292f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
293f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
294f1d2b4d3SLarry Finger 
295f1d2b4d3SLarry Finger 	switch (variable) {
296f1d2b4d3SLarry Finger 	case HW_VAR_RCR:
297f1d2b4d3SLarry Finger 		*((u32 *)(val)) = rtlpci->receive_config;
298f1d2b4d3SLarry Finger 		break;
29992a1aa25SLarry Finger 	case HW_VAR_RF_STATE:
300f1d2b4d3SLarry Finger 		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
301f1d2b4d3SLarry Finger 		break;
302f1d2b4d3SLarry Finger 	case HW_VAR_FWLPS_RF_ON:{
30392a1aa25SLarry Finger 		enum rf_pwrstate rfstate;
30492a1aa25SLarry Finger 		u32 val_rcr;
305f1d2b4d3SLarry Finger 
306f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
307f1d2b4d3SLarry Finger 					      (u8 *)(&rfstate));
308f1d2b4d3SLarry Finger 		if (rfstate == ERFOFF) {
309f1d2b4d3SLarry Finger 			*((bool *)(val)) = true;
310f1d2b4d3SLarry Finger 		} else {
311f1d2b4d3SLarry Finger 			val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
312f1d2b4d3SLarry Finger 			val_rcr &= 0x00070000;
313f1d2b4d3SLarry Finger 			if (val_rcr)
314f1d2b4d3SLarry Finger 				*((bool *)(val)) = false;
315f1d2b4d3SLarry Finger 			else
316f1d2b4d3SLarry Finger 				*((bool *)(val)) = true;
317f1d2b4d3SLarry Finger 		}
318f1d2b4d3SLarry Finger 		}
319f1d2b4d3SLarry Finger 		break;
320f1d2b4d3SLarry Finger 	case HW_VAR_FW_PSMODE_STATUS:
321f1d2b4d3SLarry Finger 		*((bool *)(val)) = ppsc->fw_current_inpsmode;
322f1d2b4d3SLarry Finger 		break;
323f1d2b4d3SLarry Finger 	case HW_VAR_CORRECT_TSF:{
324f1d2b4d3SLarry Finger 		u64 tsf;
325f1d2b4d3SLarry Finger 		u32 *ptsf_low = (u32 *)&tsf;
326f1d2b4d3SLarry Finger 		u32 *ptsf_high = ((u32 *)&tsf) + 1;
327f1d2b4d3SLarry Finger 
328f1d2b4d3SLarry Finger 		*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
329f1d2b4d3SLarry Finger 		*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
3301cc49a5bSLarry Finger 
3311cc49a5bSLarry Finger 		*((u64 *)(val)) = tsf;
332f1d2b4d3SLarry Finger 		}
333e6dd230aSLarry Finger 		break;
334ad574889SJoe Perches 	case HAL_DEF_WOWLAN:
335f1d2b4d3SLarry Finger 		break;
336f1d2b4d3SLarry Finger 	default:
337f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
338f1d2b4d3SLarry Finger 			"switch case %#x not processed\n", variable);
339f1d2b4d3SLarry Finger 		break;
340f1d2b4d3SLarry Finger 	}
341f1d2b4d3SLarry Finger }
342f1d2b4d3SLarry Finger 
_rtl8723be_download_rsvd_page(struct ieee80211_hw * hw)343f1d2b4d3SLarry Finger static void _rtl8723be_download_rsvd_page(struct ieee80211_hw *hw)
344f1d2b4d3SLarry Finger {
345f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
346f1d2b4d3SLarry Finger 	u8 tmp_regcr, tmp_reg422, bcnvalid_reg;
347f1d2b4d3SLarry Finger 	u8 count = 0, dlbcn_count = 0;
348f1d2b4d3SLarry Finger 	bool b_recover = false;
349f1d2b4d3SLarry Finger 
350f1d2b4d3SLarry Finger 	tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
351f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_CR + 1,
352f1d2b4d3SLarry Finger 		       (tmp_regcr | BIT(0)));
353f1d2b4d3SLarry Finger 
354f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3));
355f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0);
356f1d2b4d3SLarry Finger 
357f1d2b4d3SLarry Finger 	tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
358f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6)));
359f1d2b4d3SLarry Finger 	if (tmp_reg422 & BIT(6))
360f1d2b4d3SLarry Finger 		b_recover = true;
361f1d2b4d3SLarry Finger 
362f1d2b4d3SLarry Finger 	do {
363f1d2b4d3SLarry Finger 		bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2);
364f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_TDECTRL + 2,
365f1d2b4d3SLarry Finger 			       (bcnvalid_reg | BIT(0)));
366f1d2b4d3SLarry Finger 		_rtl8723be_return_beacon_queue_skb(hw);
367f1d2b4d3SLarry Finger 
368f1d2b4d3SLarry Finger 		rtl8723be_set_fw_rsvdpagepkt(hw, 0);
369f1d2b4d3SLarry Finger 		bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2);
370f1d2b4d3SLarry Finger 		count = 0;
371f1d2b4d3SLarry Finger 		while (!(bcnvalid_reg & BIT(0)) && count < 20) {
372f1d2b4d3SLarry Finger 			count++;
373f1d2b4d3SLarry Finger 			udelay(10);
374f1d2b4d3SLarry Finger 			bcnvalid_reg = rtl_read_byte(rtlpriv,
375f1d2b4d3SLarry Finger 						     REG_TDECTRL + 2);
376f1d2b4d3SLarry Finger 		}
377f1d2b4d3SLarry Finger 		dlbcn_count++;
378f1d2b4d3SLarry Finger 	} while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5);
379f1d2b4d3SLarry Finger 
380f1d2b4d3SLarry Finger 	if (bcnvalid_reg & BIT(0))
381f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0));
382f1d2b4d3SLarry Finger 
383f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0);
384f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4));
385f1d2b4d3SLarry Finger 
386f1d2b4d3SLarry Finger 	if (b_recover)
387f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422);
388f1d2b4d3SLarry Finger 
389f1d2b4d3SLarry Finger 	tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
390f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0))));
391f1d2b4d3SLarry Finger }
392f1d2b4d3SLarry Finger 
rtl8723be_set_hw_reg(struct ieee80211_hw * hw,u8 variable,u8 * val)393f1d2b4d3SLarry Finger void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
394f1d2b4d3SLarry Finger {
395f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
396f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
397f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
398f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
399f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
400f1d2b4d3SLarry Finger 	u8 idx;
401f1d2b4d3SLarry Finger 
402f1d2b4d3SLarry Finger 	switch (variable) {
403f1d2b4d3SLarry Finger 	case HW_VAR_ETHER_ADDR:
404f1d2b4d3SLarry Finger 		for (idx = 0; idx < ETH_ALEN; idx++)
405f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]);
406f1d2b4d3SLarry Finger 		break;
407f1d2b4d3SLarry Finger 	case HW_VAR_BASIC_RATE:{
408f1d2b4d3SLarry Finger 		u16 b_rate_cfg = ((u16 *)val)[0];
409f1d2b4d3SLarry Finger 		u8 rate_index = 0;
410f1d2b4d3SLarry Finger 		b_rate_cfg = b_rate_cfg & 0x15f;
411f1d2b4d3SLarry Finger 		b_rate_cfg |= 0x01;
412f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff);
413f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_RRSR + 1, (b_rate_cfg >> 8) & 0xff);
414f1d2b4d3SLarry Finger 		while (b_rate_cfg > 0x1) {
415f1d2b4d3SLarry Finger 			b_rate_cfg = (b_rate_cfg >> 1);
416f1d2b4d3SLarry Finger 			rate_index++;
417f1d2b4d3SLarry Finger 		}
418f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index);
419f1d2b4d3SLarry Finger 		}
420f1d2b4d3SLarry Finger 		break;
421f1d2b4d3SLarry Finger 	case HW_VAR_BSSID:
422f1d2b4d3SLarry Finger 		for (idx = 0; idx < ETH_ALEN; idx++)
423f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]);
424f1d2b4d3SLarry Finger 
425f1d2b4d3SLarry Finger 		break;
426f1d2b4d3SLarry Finger 	case HW_VAR_SIFS:
427f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
428f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
429f1d2b4d3SLarry Finger 
430f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
431f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
432f1d2b4d3SLarry Finger 
433f1d2b4d3SLarry Finger 		if (!mac->ht_enable)
434f1d2b4d3SLarry Finger 			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e);
435f1d2b4d3SLarry Finger 		else
436f1d2b4d3SLarry Finger 			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
437f1d2b4d3SLarry Finger 				       *((u16 *)val));
438e6dd230aSLarry Finger 		break;
439f1d2b4d3SLarry Finger 	case HW_VAR_SLOT_TIME:{
440f1d2b4d3SLarry Finger 		u8 e_aci;
441f1d2b4d3SLarry Finger 
442f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
443f1d2b4d3SLarry Finger 			"HW_VAR_SLOT_TIME %x\n", val[0]);
444f1d2b4d3SLarry Finger 
445f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
446f1d2b4d3SLarry Finger 
447f1d2b4d3SLarry Finger 		for (e_aci = 0; e_aci < AC_MAX; e_aci++) {
448f1d2b4d3SLarry Finger 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
449f1d2b4d3SLarry Finger 						      (u8 *)(&e_aci));
450f1d2b4d3SLarry Finger 		}
451f1d2b4d3SLarry Finger 		}
452f1d2b4d3SLarry Finger 		break;
453f1d2b4d3SLarry Finger 	case HW_VAR_ACK_PREAMBLE:{
454f1d2b4d3SLarry Finger 		u8 reg_tmp;
455f1d2b4d3SLarry Finger 		u8 short_preamble = (bool)(*(u8 *)val);
456f1d2b4d3SLarry Finger 		reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL + 2);
457f1d2b4d3SLarry Finger 		if (short_preamble) {
458f1d2b4d3SLarry Finger 			reg_tmp |= 0x02;
459f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
460f1d2b4d3SLarry Finger 		} else {
461f1d2b4d3SLarry Finger 			reg_tmp &= 0xFD;
462f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
463f1d2b4d3SLarry Finger 		}
464f1d2b4d3SLarry Finger 		}
465f1d2b4d3SLarry Finger 		break;
466f1d2b4d3SLarry Finger 	case HW_VAR_WPA_CONFIG:
467f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val));
468f1d2b4d3SLarry Finger 		break;
469f1d2b4d3SLarry Finger 	case HW_VAR_AMPDU_MIN_SPACE:{
470f1d2b4d3SLarry Finger 		u8 min_spacing_to_set;
471f1d2b4d3SLarry Finger 		u8 sec_min_space;
472f1d2b4d3SLarry Finger 
473f1d2b4d3SLarry Finger 		min_spacing_to_set = *((u8 *)val);
474f1d2b4d3SLarry Finger 		if (min_spacing_to_set <= 7) {
475f1d2b4d3SLarry Finger 			sec_min_space = 0;
476f1d2b4d3SLarry Finger 
477f1d2b4d3SLarry Finger 			if (min_spacing_to_set < sec_min_space)
478f1d2b4d3SLarry Finger 				min_spacing_to_set = sec_min_space;
479f1d2b4d3SLarry Finger 
480f1d2b4d3SLarry Finger 			mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) |
481e6dd230aSLarry Finger 					      min_spacing_to_set);
482f1d2b4d3SLarry Finger 
483f1d2b4d3SLarry Finger 			*val = min_spacing_to_set;
484f1d2b4d3SLarry Finger 
485f1d2b4d3SLarry Finger 			rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
486f1d2b4d3SLarry Finger 				"Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
487f1d2b4d3SLarry Finger 				mac->min_space_cfg);
488f1d2b4d3SLarry Finger 
489f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
490f1d2b4d3SLarry Finger 				       mac->min_space_cfg);
491f1d2b4d3SLarry Finger 		}
492f1d2b4d3SLarry Finger 		}
493f1d2b4d3SLarry Finger 		break;
494f1d2b4d3SLarry Finger 	case HW_VAR_SHORTGI_DENSITY:{
495f1d2b4d3SLarry Finger 		u8 density_to_set;
496e6dd230aSLarry Finger 
497f1d2b4d3SLarry Finger 		density_to_set = *((u8 *)val);
498f1d2b4d3SLarry Finger 		mac->min_space_cfg |= (density_to_set << 3);
499f1d2b4d3SLarry Finger 
500f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
501f1d2b4d3SLarry Finger 			"Set HW_VAR_SHORTGI_DENSITY: %#x\n",
502f1d2b4d3SLarry Finger 			mac->min_space_cfg);
503f1d2b4d3SLarry Finger 
504f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
505f1d2b4d3SLarry Finger 			       mac->min_space_cfg);
506f1d2b4d3SLarry Finger 		}
507f1d2b4d3SLarry Finger 		break;
508f1d2b4d3SLarry Finger 	case HW_VAR_AMPDU_FACTOR:{
509f1d2b4d3SLarry Finger 		u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9};
510f1d2b4d3SLarry Finger 		u8 factor_toset;
511f1d2b4d3SLarry Finger 		u8 *p_regtoset = NULL;
512f1d2b4d3SLarry Finger 		u8 index = 0;
513f1d2b4d3SLarry Finger 
514f1d2b4d3SLarry Finger 		p_regtoset = regtoset_normal;
515f1d2b4d3SLarry Finger 
516f1d2b4d3SLarry Finger 		factor_toset = *((u8 *)val);
517f1d2b4d3SLarry Finger 		if (factor_toset <= 3) {
518f1d2b4d3SLarry Finger 			factor_toset = (1 << (factor_toset + 2));
519f1d2b4d3SLarry Finger 			if (factor_toset > 0xf)
520f1d2b4d3SLarry Finger 				factor_toset = 0xf;
521f1d2b4d3SLarry Finger 
522f1d2b4d3SLarry Finger 			for (index = 0; index < 4; index++) {
523f1d2b4d3SLarry Finger 				if ((p_regtoset[index] & 0xf0) >
524f1d2b4d3SLarry Finger 				    (factor_toset << 4))
525f1d2b4d3SLarry Finger 					p_regtoset[index] =
526f1d2b4d3SLarry Finger 						(p_regtoset[index] & 0x0f) |
527f1d2b4d3SLarry Finger 						(factor_toset << 4);
528f1d2b4d3SLarry Finger 
529f1d2b4d3SLarry Finger 				if ((p_regtoset[index] & 0x0f) > factor_toset)
530f1d2b4d3SLarry Finger 					p_regtoset[index] =
531f1d2b4d3SLarry Finger 						(p_regtoset[index] & 0xf0) |
532f1d2b4d3SLarry Finger 						(factor_toset);
533f1d2b4d3SLarry Finger 
534f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv,
535f1d2b4d3SLarry Finger 					       (REG_AGGLEN_LMT + index),
536e6dd230aSLarry Finger 					       p_regtoset[index]);
537f1d2b4d3SLarry Finger 
538f1d2b4d3SLarry Finger 			}
539f1d2b4d3SLarry Finger 
540f1d2b4d3SLarry Finger 			rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
541f1d2b4d3SLarry Finger 				"Set HW_VAR_AMPDU_FACTOR: %#x\n",
542f1d2b4d3SLarry Finger 				factor_toset);
543f1d2b4d3SLarry Finger 		}
544f1d2b4d3SLarry Finger 		}
545f1d2b4d3SLarry Finger 		break;
546f1d2b4d3SLarry Finger 	case HW_VAR_AC_PARAM:{
547f1d2b4d3SLarry Finger 		u8 e_aci = *((u8 *)val);
548f1d2b4d3SLarry Finger 		rtl8723_dm_init_edca_turbo(hw);
549f1d2b4d3SLarry Finger 
550f1d2b4d3SLarry Finger 		if (rtlpci->acm_method != EACMWAY2_SW)
551f1d2b4d3SLarry Finger 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
552f1d2b4d3SLarry Finger 						      (u8 *)(&e_aci));
553f1d2b4d3SLarry Finger 		}
554f1d2b4d3SLarry Finger 		break;
555f1d2b4d3SLarry Finger 	case HW_VAR_ACM_CTRL:{
556f1d2b4d3SLarry Finger 		u8 e_aci = *((u8 *)val);
557f1d2b4d3SLarry Finger 		union aci_aifsn *p_aci_aifsn =
558f1d2b4d3SLarry Finger 				(union aci_aifsn *)(&(mac->ac[0].aifs));
559f1d2b4d3SLarry Finger 		u8 acm = p_aci_aifsn->f.acm;
560f1d2b4d3SLarry Finger 		u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
561f1d2b4d3SLarry Finger 
562f1d2b4d3SLarry Finger 		acm_ctrl =
563f1d2b4d3SLarry Finger 		    acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
564f1d2b4d3SLarry Finger 
565f1d2b4d3SLarry Finger 		if (acm) {
566f1d2b4d3SLarry Finger 			switch (e_aci) {
567f1d2b4d3SLarry Finger 			case AC0_BE:
568f1d2b4d3SLarry Finger 				acm_ctrl |= ACMHW_BEQEN;
569f1d2b4d3SLarry Finger 				break;
570f1d2b4d3SLarry Finger 			case AC2_VI:
571f1d2b4d3SLarry Finger 				acm_ctrl |= ACMHW_VIQEN;
572f1d2b4d3SLarry Finger 				break;
573e6dd230aSLarry Finger 			case AC3_VO:
574f1d2b4d3SLarry Finger 				acm_ctrl |= ACMHW_VOQEN;
575f1d2b4d3SLarry Finger 				break;
576f1d2b4d3SLarry Finger 			default:
577f1d2b4d3SLarry Finger 				rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
578f1d2b4d3SLarry Finger 					"HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
579f1d2b4d3SLarry Finger 					acm);
580f1d2b4d3SLarry Finger 				break;
581f1d2b4d3SLarry Finger 			}
582f1d2b4d3SLarry Finger 		} else {
583f1d2b4d3SLarry Finger 			switch (e_aci) {
584f1d2b4d3SLarry Finger 			case AC0_BE:
585f1d2b4d3SLarry Finger 				acm_ctrl &= (~ACMHW_BEQEN);
586f1d2b4d3SLarry Finger 				break;
587f1d2b4d3SLarry Finger 			case AC2_VI:
588f1d2b4d3SLarry Finger 				acm_ctrl &= (~ACMHW_VIQEN);
589f1d2b4d3SLarry Finger 				break;
590e6dd230aSLarry Finger 			case AC3_VO:
591ad574889SJoe Perches 				acm_ctrl &= (~ACMHW_VOQEN);
592ad574889SJoe Perches 				break;
593f1d2b4d3SLarry Finger 			default:
594f1d2b4d3SLarry Finger 				rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
595f1d2b4d3SLarry Finger 					"switch case %#x not processed\n",
596f1d2b4d3SLarry Finger 					e_aci);
597e6dd230aSLarry Finger 				break;
598f1d2b4d3SLarry Finger 			}
599f1d2b4d3SLarry Finger 		}
600f1d2b4d3SLarry Finger 
601f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_QOS, DBG_TRACE,
602f1d2b4d3SLarry Finger 			"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
603f1d2b4d3SLarry Finger 			acm_ctrl);
604f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
605f1d2b4d3SLarry Finger 		}
606f1d2b4d3SLarry Finger 		break;
607f1d2b4d3SLarry Finger 	case HW_VAR_RCR:
608f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]);
609f1d2b4d3SLarry Finger 		rtlpci->receive_config = ((u32 *)(val))[0];
610f1d2b4d3SLarry Finger 		break;
611f1d2b4d3SLarry Finger 	case HW_VAR_RETRY_LIMIT:{
612f1d2b4d3SLarry Finger 		u8 retry_limit = ((u8 *)(val))[0];
613f1d2b4d3SLarry Finger 
614f1d2b4d3SLarry Finger 		rtl_write_word(rtlpriv, REG_RL,
615f1d2b4d3SLarry Finger 			       retry_limit << RETRY_LIMIT_SHORT_SHIFT |
616f1d2b4d3SLarry Finger 			       retry_limit << RETRY_LIMIT_LONG_SHIFT);
617f1d2b4d3SLarry Finger 		}
618f1d2b4d3SLarry Finger 		break;
619f1d2b4d3SLarry Finger 	case HW_VAR_DUAL_TSF_RST:
620f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
621f1d2b4d3SLarry Finger 		break;
622f1d2b4d3SLarry Finger 	case HW_VAR_EFUSE_BYTES:
623f1d2b4d3SLarry Finger 		rtlefuse->efuse_usedbytes = *((u16 *)val);
624f1d2b4d3SLarry Finger 		break;
625f1d2b4d3SLarry Finger 	case HW_VAR_EFUSE_USAGE:
626f1d2b4d3SLarry Finger 		rtlefuse->efuse_usedpercentage = *((u8 *)val);
627f1d2b4d3SLarry Finger 		break;
628f1d2b4d3SLarry Finger 	case HW_VAR_IO_CMD:
629f1d2b4d3SLarry Finger 		rtl8723be_phy_set_io_cmd(hw, (*(enum io_type *)val));
630f1d2b4d3SLarry Finger 		break;
631f1d2b4d3SLarry Finger 	case HW_VAR_SET_RPWM:{
632f1d2b4d3SLarry Finger 		u8 rpwm_val;
633f1d2b4d3SLarry Finger 
634f1d2b4d3SLarry Finger 		rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM);
635f1d2b4d3SLarry Finger 		udelay(1);
636f1d2b4d3SLarry Finger 
637f1d2b4d3SLarry Finger 		if (rpwm_val & BIT(7)) {
638f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val));
639f1d2b4d3SLarry Finger 		} else {
640f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
641f1d2b4d3SLarry Finger 				       ((*(u8 *)val) | BIT(7)));
642f1d2b4d3SLarry Finger 		}
643f1d2b4d3SLarry Finger 		}
644f1d2b4d3SLarry Finger 		break;
645f1d2b4d3SLarry Finger 	case HW_VAR_H2C_FW_PWRMODE:
646f1d2b4d3SLarry Finger 		rtl8723be_set_fw_pwrmode_cmd(hw, (*(u8 *)val));
647f1d2b4d3SLarry Finger 		break;
648f1d2b4d3SLarry Finger 	case HW_VAR_FW_PSMODE_STATUS:
649f1d2b4d3SLarry Finger 		ppsc->fw_current_inpsmode = *((bool *)val);
650f1d2b4d3SLarry Finger 		break;
651f1d2b4d3SLarry Finger 	case HW_VAR_RESUME_CLK_ON:
652f1d2b4d3SLarry Finger 		_rtl8723be_set_fw_ps_rf_on(hw);
653f1d2b4d3SLarry Finger 		break;
654f1d2b4d3SLarry Finger 	case HW_VAR_FW_LPS_ACTION:{
655f1d2b4d3SLarry Finger 		bool b_enter_fwlps = *((bool *)val);
656f1d2b4d3SLarry Finger 
657f1d2b4d3SLarry Finger 		if (b_enter_fwlps)
658f1d2b4d3SLarry Finger 			_rtl8723be_fwlps_enter(hw);
659f1d2b4d3SLarry Finger 		else
660f1d2b4d3SLarry Finger 			_rtl8723be_fwlps_leave(hw);
661f1d2b4d3SLarry Finger 		}
662f1d2b4d3SLarry Finger 		break;
663f1d2b4d3SLarry Finger 	case HW_VAR_H2C_FW_JOINBSSRPT:{
664f1d2b4d3SLarry Finger 		u8 mstatus = (*(u8 *)val);
665f1d2b4d3SLarry Finger 
666f1d2b4d3SLarry Finger 		if (mstatus == RT_MEDIA_CONNECT) {
667f1d2b4d3SLarry Finger 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
668f1d2b4d3SLarry Finger 			_rtl8723be_download_rsvd_page(hw);
669f1d2b4d3SLarry Finger 		}
670f1d2b4d3SLarry Finger 		rtl8723be_set_fw_media_status_rpt_cmd(hw, mstatus);
671f1d2b4d3SLarry Finger 		}
672f1d2b4d3SLarry Finger 		break;
673f1d2b4d3SLarry Finger 	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
674f1d2b4d3SLarry Finger 		rtl8723be_set_p2p_ps_offload_cmd(hw, (*(u8 *)val));
675f1d2b4d3SLarry Finger 		break;
676f1d2b4d3SLarry Finger 	case HW_VAR_AID:{
677f1d2b4d3SLarry Finger 		u16 u2btmp;
678f1d2b4d3SLarry Finger 		u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
679f1d2b4d3SLarry Finger 		u2btmp &= 0xC000;
680f1d2b4d3SLarry Finger 		rtl_write_word(rtlpriv, REG_BCN_PSR_RPT,
681f1d2b4d3SLarry Finger 			       (u2btmp | mac->assoc_id));
682f1d2b4d3SLarry Finger 		}
683f1d2b4d3SLarry Finger 		break;
684f1d2b4d3SLarry Finger 	case HW_VAR_CORRECT_TSF:{
685f1d2b4d3SLarry Finger 		u8 btype_ibss = ((u8 *)(val))[0];
686f1d2b4d3SLarry Finger 
687f1d2b4d3SLarry Finger 		if (btype_ibss)
688f1d2b4d3SLarry Finger 			_rtl8723be_stop_tx_beacon(hw);
689f1d2b4d3SLarry Finger 
690f1d2b4d3SLarry Finger 		_rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3));
691f1d2b4d3SLarry Finger 
692f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_TSFTR,
693f1d2b4d3SLarry Finger 				(u32) (mac->tsf & 0xffffffff));
694f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_TSFTR + 4,
695f1d2b4d3SLarry Finger 				(u32) ((mac->tsf >> 32) & 0xffffffff));
696f1d2b4d3SLarry Finger 
697f1d2b4d3SLarry Finger 		_rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0);
698f1d2b4d3SLarry Finger 
699f1d2b4d3SLarry Finger 		if (btype_ibss)
700f1d2b4d3SLarry Finger 			_rtl8723be_resume_tx_beacon(hw);
701f1d2b4d3SLarry Finger 		}
702f1d2b4d3SLarry Finger 		break;
703f1d2b4d3SLarry Finger 	case HW_VAR_KEEP_ALIVE:{
704f1d2b4d3SLarry Finger 		u8 array[2];
705f1d2b4d3SLarry Finger 		array[0] = 0xff;
706f1d2b4d3SLarry Finger 		array[1] = *((u8 *)val);
707e6dd230aSLarry Finger 		rtl8723be_fill_h2c_cmd(hw, H2C_8723B_KEEP_ALIVE_CTRL, 2, array);
708ad574889SJoe Perches 		}
709f1d2b4d3SLarry Finger 		break;
710f1d2b4d3SLarry Finger 	default:
711f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
712f1d2b4d3SLarry Finger 			"switch case %#x not processed\n", variable);
713f1d2b4d3SLarry Finger 		break;
714f1d2b4d3SLarry Finger 	}
715f1d2b4d3SLarry Finger }
716f1d2b4d3SLarry Finger 
_rtl8723be_llt_write(struct ieee80211_hw * hw,u32 address,u32 data)717f1d2b4d3SLarry Finger static bool _rtl8723be_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
718f1d2b4d3SLarry Finger {
719f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
720f1d2b4d3SLarry Finger 	bool status = true;
721f1d2b4d3SLarry Finger 	long count = 0;
722f1d2b4d3SLarry Finger 	u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
723f1d2b4d3SLarry Finger 		    _LLT_OP(_LLT_WRITE_ACCESS);
724f1d2b4d3SLarry Finger 
725f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
726f1d2b4d3SLarry Finger 
727f1d2b4d3SLarry Finger 	do {
728f1d2b4d3SLarry Finger 		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
7294e2b4378SLarry Finger 		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
730f1d2b4d3SLarry Finger 			break;
731f1d2b4d3SLarry Finger 
732f1d2b4d3SLarry Finger 		if (count > POLLING_LLT_THRESHOLD) {
733f1d2b4d3SLarry Finger 			pr_err("Failed to polling write LLT done at address %d!\n",
734f1d2b4d3SLarry Finger 			       address);
735f1d2b4d3SLarry Finger 			status = false;
736f1d2b4d3SLarry Finger 			break;
737f1d2b4d3SLarry Finger 		}
738f1d2b4d3SLarry Finger 	} while (++count);
739f1d2b4d3SLarry Finger 
740f1d2b4d3SLarry Finger 	return status;
741f1d2b4d3SLarry Finger }
742f1d2b4d3SLarry Finger 
_rtl8723be_llt_table_init(struct ieee80211_hw * hw)743f1d2b4d3SLarry Finger static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw)
74492a1aa25SLarry Finger {
745f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
746f1d2b4d3SLarry Finger 	unsigned short i;
74792a1aa25SLarry Finger 	u8 txpktbuf_bndy;
748f1d2b4d3SLarry Finger 	u8 maxpage;
749f1d2b4d3SLarry Finger 	bool status;
750f1d2b4d3SLarry Finger 
751f1d2b4d3SLarry Finger 	maxpage = 255;
752f1d2b4d3SLarry Finger 	txpktbuf_bndy = 245;
753f1d2b4d3SLarry Finger 
754f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_TRXFF_BNDY,
755f1d2b4d3SLarry Finger 			(0x27FF0000 | txpktbuf_bndy));
756f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
757f1d2b4d3SLarry Finger 
758f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
759f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
760f1d2b4d3SLarry Finger 
761f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
762f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_PBP, 0x31);
763f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
764f1d2b4d3SLarry Finger 
765f1d2b4d3SLarry Finger 	for (i = 0; i < (txpktbuf_bndy - 1); i++) {
766f1d2b4d3SLarry Finger 		status = _rtl8723be_llt_write(hw, i, i + 1);
767f1d2b4d3SLarry Finger 		if (!status)
768f1d2b4d3SLarry Finger 			return status;
769f1d2b4d3SLarry Finger 	}
770f1d2b4d3SLarry Finger 
771f1d2b4d3SLarry Finger 	status = _rtl8723be_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
77292a1aa25SLarry Finger 
773f1d2b4d3SLarry Finger 	if (!status)
774f1d2b4d3SLarry Finger 		return status;
775f1d2b4d3SLarry Finger 
776f1d2b4d3SLarry Finger 	for (i = txpktbuf_bndy; i < maxpage; i++) {
777f1d2b4d3SLarry Finger 		status = _rtl8723be_llt_write(hw, i, (i + 1));
77892a1aa25SLarry Finger 		if (!status)
779f1d2b4d3SLarry Finger 			return status;
780f1d2b4d3SLarry Finger 	}
781f1d2b4d3SLarry Finger 
782f1d2b4d3SLarry Finger 	status = _rtl8723be_llt_write(hw, maxpage, txpktbuf_bndy);
783f1d2b4d3SLarry Finger 	if (!status)
784f1d2b4d3SLarry Finger 		return status;
785f1d2b4d3SLarry Finger 
786f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RQPN, 0x80e40808);
787f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00);
788f1d2b4d3SLarry Finger 
789f1d2b4d3SLarry Finger 	return true;
790f1d2b4d3SLarry Finger }
791f1d2b4d3SLarry Finger 
_rtl8723be_gen_refresh_led_state(struct ieee80211_hw * hw)792d5efe153SLarry Finger static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw)
793f1d2b4d3SLarry Finger {
794f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
795f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
796f1d2b4d3SLarry Finger 	enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
797f1d2b4d3SLarry Finger 
798f1d2b4d3SLarry Finger 	if (rtlpriv->rtlhal.up_first_time)
799f1d2b4d3SLarry Finger 		return;
800f1d2b4d3SLarry Finger 
801f1d2b4d3SLarry Finger 	if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
802f1d2b4d3SLarry Finger 		rtl8723be_sw_led_on(hw, pin0);
803f1d2b4d3SLarry Finger 	else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
804f1d2b4d3SLarry Finger 		rtl8723be_sw_led_on(hw, pin0);
805f1d2b4d3SLarry Finger 	else
806f1d2b4d3SLarry Finger 		rtl8723be_sw_led_off(hw, pin0);
807f1d2b4d3SLarry Finger }
808f1d2b4d3SLarry Finger 
_rtl8723be_init_mac(struct ieee80211_hw * hw)809f1d2b4d3SLarry Finger static bool _rtl8723be_init_mac(struct ieee80211_hw *hw)
810f1d2b4d3SLarry Finger {
811f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
812f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
813f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
814f1d2b4d3SLarry Finger 	unsigned char bytetmp;
815f1d2b4d3SLarry Finger 	unsigned short wordtmp;
816f1d2b4d3SLarry Finger 
817f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
818f1d2b4d3SLarry Finger 
819f1d2b4d3SLarry Finger 	/*Auto Power Down to CHIP-off State*/
820f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7));
821f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
822f1d2b4d3SLarry Finger 
823e6dd230aSLarry Finger 	/* HW Power on sequence */
824f1d2b4d3SLarry Finger 	if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK,
825f1d2b4d3SLarry Finger 				      PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,
826f1d2b4d3SLarry Finger 				      RTL8723_NIC_ENABLE_FLOW)) {
827f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
828af8a41ccSPing-Ke Shih 			"init MAC Fail as power on failure\n");
829af8a41ccSPing-Ke Shih 		return false;
830af8a41ccSPing-Ke Shih 	}
831f1d2b4d3SLarry Finger 
832f1d2b4d3SLarry Finger 	if (rtlpriv->cfg->ops->get_btc_status())
833f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_ops->btc_power_on_setting(rtlpriv);
834f1d2b4d3SLarry Finger 
835f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL);
836f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3));
837f1d2b4d3SLarry Finger 
838f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4);
839f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp);
840f1d2b4d3SLarry Finger 
841f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_CR);
842f1d2b4d3SLarry Finger 	bytetmp = 0xff;
843f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_CR, bytetmp);
844f1d2b4d3SLarry Finger 	mdelay(2);
845f1d2b4d3SLarry Finger 
846f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_HWSEQ_CTRL);
847f1d2b4d3SLarry Finger 	bytetmp |= 0x7f;
848f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp);
849f1d2b4d3SLarry Finger 	mdelay(2);
850f1d2b4d3SLarry Finger 
851f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3);
852f1d2b4d3SLarry Finger 	if (bytetmp & BIT(0)) {
853f1d2b4d3SLarry Finger 		bytetmp = rtl_read_byte(rtlpriv, 0x7c);
854f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, 0x7c, bytetmp | BIT(6));
855f1d2b4d3SLarry Finger 	}
856f1d2b4d3SLarry Finger 
857f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR);
858f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp | BIT(3));
859f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1);
860f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp & (~BIT(4)));
86102686841SZheng Bin 
862f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_CR, 0x2ff);
863f1d2b4d3SLarry Finger 
864f1d2b4d3SLarry Finger 	if (!rtlhal->mac_func_enable) {
865f1d2b4d3SLarry Finger 		if (!_rtl8723be_llt_table_init(hw))
866f1d2b4d3SLarry Finger 			return false;
867f1d2b4d3SLarry Finger 	}
868f1d2b4d3SLarry Finger 
869f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
870f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff);
871f1d2b4d3SLarry Finger 
872f1d2b4d3SLarry Finger 	/* Enable FW Beamformer Interrupt */
873f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3);
874f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6));
875f1d2b4d3SLarry Finger 
876f1d2b4d3SLarry Finger 	wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
877f1d2b4d3SLarry Finger 	wordtmp &= 0xf;
878f1d2b4d3SLarry Finger 	wordtmp |= 0xF5B1;
879f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
880f1d2b4d3SLarry Finger 
881f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
882f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
883f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF);
884f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
885f1d2b4d3SLarry Finger 
886f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
887f1d2b4d3SLarry Finger 			((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) &
888f1d2b4d3SLarry Finger 			DMA_BIT_MASK(32));
889f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MGQ_DESA,
890f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[MGNT_QUEUE].dma &
891f1d2b4d3SLarry Finger 			DMA_BIT_MASK(32));
892f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_VOQ_DESA,
893f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32));
894f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_VIQ_DESA,
895f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32));
896f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_BEQ_DESA,
897f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32));
898f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_BKQ_DESA,
899f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32));
900f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HQ_DESA,
901f1d2b4d3SLarry Finger 			(u64) rtlpci->tx_ring[HIGH_QUEUE].dma &
902f1d2b4d3SLarry Finger 			DMA_BIT_MASK(32));
903f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RX_DESA,
904f1d2b4d3SLarry Finger 			(u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
905f1d2b4d3SLarry Finger 			DMA_BIT_MASK(32));
906f1d2b4d3SLarry Finger 
907f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 3);
908f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, bytetmp | 0x77);
909f1d2b4d3SLarry Finger 
910f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
911f1d2b4d3SLarry Finger 
912f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
913f1d2b4d3SLarry Finger 
914f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3);
915f1d2b4d3SLarry Finger 
916f1d2b4d3SLarry Finger 	/* <20130114, Kordan> The following setting is
917f1d2b4d3SLarry Finger 	 * only for DPDT and Fixed board type.
918f1d2b4d3SLarry Finger 	 * TODO:  A better solution is configure it
919f1d2b4d3SLarry Finger 	 * according EFUSE during the run-time.
920f1d2b4d3SLarry Finger 	 */
921f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x64, BIT(20), 0x0);/* 0x66[4]=0 */
922f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x64, BIT(24), 0x0);/* 0x66[8]=0 */
923f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x40, BIT(4), 0x0)/* 0x40[4]=0 */;
924f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x40, BIT(3), 0x1)/* 0x40[3]=1 */;
925f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x4C, BIT(24) | BIT(23), 0x2)/* 0x4C[24:23]=10 */;
926f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x944, BIT(1) | BIT(0), 0x3)/* 0x944[1:0]=11 */;
927f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x930, MASKBYTE0, 0x77)/* 0x930[7:0]=77 */;
928f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, 0x38, BIT(11), 0x1)/* 0x38[11]=1 */;
929f1d2b4d3SLarry Finger 
930f1d2b4d3SLarry Finger 	bytetmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
931f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, bytetmp & (~BIT(2)));
932f1d2b4d3SLarry Finger 
933f1d2b4d3SLarry Finger 	_rtl8723be_gen_refresh_led_state(hw);
934f1d2b4d3SLarry Finger 	return true;
935f1d2b4d3SLarry Finger }
936f1d2b4d3SLarry Finger 
_rtl8723be_hw_configure(struct ieee80211_hw * hw)937f1d2b4d3SLarry Finger static void _rtl8723be_hw_configure(struct ieee80211_hw *hw)
938f1d2b4d3SLarry Finger {
939f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
940f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
941f1d2b4d3SLarry Finger 	u32 reg_rrsr;
942f1d2b4d3SLarry Finger 
943f1d2b4d3SLarry Finger 	reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
944f1d2b4d3SLarry Finger 	/* Init value for RRSR. */
945f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr);
946f1d2b4d3SLarry Finger 
947f1d2b4d3SLarry Finger 	/* ARFB table 9 for 11ac 5G 2SS */
948f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000);
949f1d2b4d3SLarry Finger 
950f1d2b4d3SLarry Finger 	/* ARFB table 10 for 11ac 5G 1SS */
951f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000);
952f1d2b4d3SLarry Finger 
953f1d2b4d3SLarry Finger 	/* CF-End setting. */
954f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00);
955f1d2b4d3SLarry Finger 
956f1d2b4d3SLarry Finger 	/* 0x456 = 0x70, sugguested by Zhilin */
957f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70);
958f1d2b4d3SLarry Finger 
959f1d2b4d3SLarry Finger 	/* Set retry limit */
960f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_RL, 0x0707);
961f1d2b4d3SLarry Finger 
962f1d2b4d3SLarry Finger 	/* Set Data / Response auto rate fallack retry count */
963f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
964f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
965f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
966f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
967f1d2b4d3SLarry Finger 
968f1d2b4d3SLarry Finger 	rtlpci->reg_bcn_ctrl_val = 0x1d;
969f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
970f1d2b4d3SLarry Finger 
971f1d2b4d3SLarry Finger 	/* TBTT prohibit hold time. Suggested by designer TimChen. */
972f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); /* 8 ms */
973f1d2b4d3SLarry Finger 
974f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
975f1d2b4d3SLarry Finger 
976f1d2b4d3SLarry Finger 	/*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/
977f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666);
978f1d2b4d3SLarry Finger 
979f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80);
980f1d2b4d3SLarry Finger 
981f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20);
982f1d2b4d3SLarry Finger 
983f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x1F);
984f1d2b4d3SLarry Finger }
985f1d2b4d3SLarry Finger 
_rtl8723be_dbi_read(struct rtl_priv * rtlpriv,u16 addr)986f1d2b4d3SLarry Finger static u8 _rtl8723be_dbi_read(struct rtl_priv *rtlpriv, u16 addr)
987f1d2b4d3SLarry Finger {
988f1d2b4d3SLarry Finger 	u16 read_addr = addr & 0xfffc;
989f1d2b4d3SLarry Finger 	u8 ret = 0, tmp = 0, count = 0;
990f1d2b4d3SLarry Finger 
991f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr);
992f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2);
993f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG);
994f1d2b4d3SLarry Finger 	count = 0;
995f1d2b4d3SLarry Finger 	while (tmp && count < 20) {
996f1d2b4d3SLarry Finger 		udelay(10);
997f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG);
998f1d2b4d3SLarry Finger 		count++;
999f1d2b4d3SLarry Finger 	}
1000f1d2b4d3SLarry Finger 	if (0 == tmp) {
1001f1d2b4d3SLarry Finger 		read_addr = REG_DBI_RDATA + addr % 4;
1002f1d2b4d3SLarry Finger 		ret = rtl_read_byte(rtlpriv, read_addr);
1003f1d2b4d3SLarry Finger 	}
1004f1d2b4d3SLarry Finger 
1005f1d2b4d3SLarry Finger 	return ret;
1006f1d2b4d3SLarry Finger }
1007f1d2b4d3SLarry Finger 
_rtl8723be_dbi_write(struct rtl_priv * rtlpriv,u16 addr,u8 data)1008f1d2b4d3SLarry Finger static void _rtl8723be_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data)
1009f1d2b4d3SLarry Finger {
1010f1d2b4d3SLarry Finger 	u8 tmp = 0, count = 0;
1011f1d2b4d3SLarry Finger 	u16 write_addr = 0, remainder = addr % 4;
1012f1d2b4d3SLarry Finger 
1013f1d2b4d3SLarry Finger 	/* Write DBI 1Byte Data */
1014f1d2b4d3SLarry Finger 	write_addr = REG_DBI_WDATA + remainder;
1015f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, write_addr, data);
1016f1d2b4d3SLarry Finger 
1017f1d2b4d3SLarry Finger 	/* Write DBI 2Byte Address & Write Enable */
1018f1d2b4d3SLarry Finger 	write_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12));
1019f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_DBI_ADDR, write_addr);
1020f1d2b4d3SLarry Finger 
1021f1d2b4d3SLarry Finger 	/* Write DBI Write Flag */
1022f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1);
1023f1d2b4d3SLarry Finger 
1024f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG);
1025f1d2b4d3SLarry Finger 	count = 0;
1026f1d2b4d3SLarry Finger 	while (tmp && count < 20) {
1027f1d2b4d3SLarry Finger 		udelay(10);
1028f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG);
1029f1d2b4d3SLarry Finger 		count++;
1030f1d2b4d3SLarry Finger 	}
1031f1d2b4d3SLarry Finger }
1032f1d2b4d3SLarry Finger 
_rtl8723be_mdio_read(struct rtl_priv * rtlpriv,u8 addr)1033f1d2b4d3SLarry Finger static u16 _rtl8723be_mdio_read(struct rtl_priv *rtlpriv, u8 addr)
1034f1d2b4d3SLarry Finger {
1035f1d2b4d3SLarry Finger 	u16 ret = 0;
1036f1d2b4d3SLarry Finger 	u8 tmp = 0, count = 0;
1037f1d2b4d3SLarry Finger 
1038f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6));
1039f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6);
1040f1d2b4d3SLarry Finger 	count = 0;
1041f1d2b4d3SLarry Finger 	while (tmp && count < 20) {
1042f1d2b4d3SLarry Finger 		udelay(10);
1043f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6);
1044f1d2b4d3SLarry Finger 		count++;
1045f1d2b4d3SLarry Finger 	}
1046f1d2b4d3SLarry Finger 
1047f1d2b4d3SLarry Finger 	if (0 == tmp)
1048f1d2b4d3SLarry Finger 		ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA);
1049f1d2b4d3SLarry Finger 
1050f1d2b4d3SLarry Finger 	return ret;
1051f1d2b4d3SLarry Finger }
1052f1d2b4d3SLarry Finger 
_rtl8723be_mdio_write(struct rtl_priv * rtlpriv,u8 addr,u16 data)1053f1d2b4d3SLarry Finger static void _rtl8723be_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data)
1054f1d2b4d3SLarry Finger {
1055f1d2b4d3SLarry Finger 	u8 tmp = 0, count = 0;
1056f1d2b4d3SLarry Finger 
1057f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_MDIO_WDATA, data);
1058f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5));
1059f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5);
1060f1d2b4d3SLarry Finger 	count = 0;
1061f1d2b4d3SLarry Finger 	while (tmp && count < 20) {
1062f1d2b4d3SLarry Finger 		udelay(10);
1063f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5);
1064f1d2b4d3SLarry Finger 		count++;
1065f1d2b4d3SLarry Finger 	}
1066f1d2b4d3SLarry Finger }
1067f1d2b4d3SLarry Finger 
_rtl8723be_enable_aspm_back_door(struct ieee80211_hw * hw)1068f1d2b4d3SLarry Finger static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw)
1069f1d2b4d3SLarry Finger {
1070f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1071f1d2b4d3SLarry Finger 	u8 tmp8 = 0;
1072f1d2b4d3SLarry Finger 	u16 tmp16 = 0;
1073f1d2b4d3SLarry Finger 
1074f1d2b4d3SLarry Finger 	/* <Roger_Notes> Overwrite following ePHY parameter for
1075f1d2b4d3SLarry Finger 	 * some platform compatibility issue,
1076f1d2b4d3SLarry Finger 	 * especially when CLKReq is enabled, 2012.11.09.
1077f1d2b4d3SLarry Finger 	 */
1078f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x01);
1079f1d2b4d3SLarry Finger 	if (tmp16 != 0x0663)
1080f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x01, 0x0663);
1081f1d2b4d3SLarry Finger 
1082f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x04);
1083f1d2b4d3SLarry Finger 	if (tmp16 != 0x7544)
1084f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x04, 0x7544);
1085f1d2b4d3SLarry Finger 
1086f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x06);
1087f1d2b4d3SLarry Finger 	if (tmp16 != 0xB880)
1088f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x06, 0xB880);
1089f1d2b4d3SLarry Finger 
1090f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x07);
1091f1d2b4d3SLarry Finger 	if (tmp16 != 0x4000)
1092f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x07, 0x4000);
1093f1d2b4d3SLarry Finger 
1094f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x08);
1095f1d2b4d3SLarry Finger 	if (tmp16 != 0x9003)
1096f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x08, 0x9003);
1097f1d2b4d3SLarry Finger 
1098f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x09);
1099f1d2b4d3SLarry Finger 	if (tmp16 != 0x0D03)
1100f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x09, 0x0D03);
1101f1d2b4d3SLarry Finger 
1102f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0A);
1103f1d2b4d3SLarry Finger 	if (tmp16 != 0x4037)
1104f1d2b4d3SLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x0A, 0x4037);
1105f1d2b4d3SLarry Finger 
1106f1d2b4d3SLarry Finger 	tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0B);
1107f1d2b4d3SLarry Finger 	if (tmp16 != 0x0070)
110878dc897bSLarry Finger 		_rtl8723be_mdio_write(rtlpriv, 0x0B, 0x0070);
110978dc897bSLarry Finger 
1110f1d2b4d3SLarry Finger 	/* Configuration Space offset 0x70f BIT7 is used to control L0S */
1111f1d2b4d3SLarry Finger 	tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f);
1112f1d2b4d3SLarry Finger 	_rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7) |
1113f1d2b4d3SLarry Finger 			     ASPM_L1_LATENCY << 3);
1114f1d2b4d3SLarry Finger 
1115f1d2b4d3SLarry Finger 	/* Configuration Space offset 0x719 Bit3 is for L1
1116f1d2b4d3SLarry Finger 	 * BIT4 is for clock request
1117f1d2b4d3SLarry Finger 	 */
1118f1d2b4d3SLarry Finger 	tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x719);
1119f1d2b4d3SLarry Finger 	_rtl8723be_dbi_write(rtlpriv, 0x719, tmp8 | BIT(3) | BIT(4));
1120f1d2b4d3SLarry Finger }
1121f1d2b4d3SLarry Finger 
rtl8723be_enable_hw_security_config(struct ieee80211_hw * hw)1122f1d2b4d3SLarry Finger void rtl8723be_enable_hw_security_config(struct ieee80211_hw *hw)
1123e6dd230aSLarry Finger {
1124f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1125f1d2b4d3SLarry Finger 	u8 sec_reg_value;
1126f1d2b4d3SLarry Finger 
1127f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
1128f1d2b4d3SLarry Finger 		"PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
1129e6dd230aSLarry Finger 		rtlpriv->sec.pairwise_enc_algorithm,
1130f1d2b4d3SLarry Finger 		rtlpriv->sec.group_enc_algorithm);
1131f1d2b4d3SLarry Finger 
1132f1d2b4d3SLarry Finger 	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
1133f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
1134f1d2b4d3SLarry Finger 			"not open hw encryption\n");
1135f1d2b4d3SLarry Finger 		return;
1136f1d2b4d3SLarry Finger 	}
1137f1d2b4d3SLarry Finger 
1138f1d2b4d3SLarry Finger 	sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE;
1139f1d2b4d3SLarry Finger 
1140f1d2b4d3SLarry Finger 	if (rtlpriv->sec.use_defaultkey) {
1141f1d2b4d3SLarry Finger 		sec_reg_value |= SCR_TXUSEDK;
1142f1d2b4d3SLarry Finger 		sec_reg_value |= SCR_RXUSEDK;
1143f1d2b4d3SLarry Finger 	}
1144f1d2b4d3SLarry Finger 
1145e6dd230aSLarry Finger 	sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
1146f1d2b4d3SLarry Finger 
1147f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
1148f1d2b4d3SLarry Finger 
1149f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
1150f1d2b4d3SLarry Finger 		"The SECR-value %x\n", sec_reg_value);
1151f1d2b4d3SLarry Finger 
1152f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
1153f1d2b4d3SLarry Finger }
1154f1d2b4d3SLarry Finger 
_rtl8723be_poweroff_adapter(struct ieee80211_hw * hw)1155f1d2b4d3SLarry Finger static void _rtl8723be_poweroff_adapter(struct ieee80211_hw *hw)
1156f1d2b4d3SLarry Finger {
1157f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1158f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1159f1d2b4d3SLarry Finger 	u8 u1b_tmp;
1160f1d2b4d3SLarry Finger 
1161f1d2b4d3SLarry Finger 	rtlhal->mac_func_enable = false;
1162f1d2b4d3SLarry Finger 	/* Combo (PCIe + USB) Card and PCIe-MF Card */
1163f1d2b4d3SLarry Finger 	/* 1. Run LPS WL RFOFF flow */
1164f1d2b4d3SLarry Finger 	rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
1165f1d2b4d3SLarry Finger 				 PWR_INTF_PCI_MSK, RTL8723_NIC_LPS_ENTER_FLOW);
1166f1d2b4d3SLarry Finger 
1167f1d2b4d3SLarry Finger 	/* 2. 0x1F[7:0] = 0 */
1168f1d2b4d3SLarry Finger 	/* turn off RF */
1169f1d2b4d3SLarry Finger 	/* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */
1170f1d2b4d3SLarry Finger 	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) &&
1171f1d2b4d3SLarry Finger 	    rtlhal->fw_ready) {
1172f1d2b4d3SLarry Finger 		rtl8723be_firmware_selfreset(hw);
1173f1d2b4d3SLarry Finger 	}
1174f1d2b4d3SLarry Finger 
1175f1d2b4d3SLarry Finger 	/* Reset MCU. Suggested by Filen. */
1176f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
1177f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
1178f1d2b4d3SLarry Finger 
1179f1d2b4d3SLarry Finger 	/* g.	MCUFWDL 0x80[1:0]=0	 */
1180f1d2b4d3SLarry Finger 	/* reset MCU ready status */
1181f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
1182f1d2b4d3SLarry Finger 
1183f1d2b4d3SLarry Finger 	/* HW card disable configuration. */
1184f1d2b4d3SLarry Finger 	rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
1185f1d2b4d3SLarry Finger 				 PWR_INTF_PCI_MSK, RTL8723_NIC_DISABLE_FLOW);
1186f1d2b4d3SLarry Finger 
1187f1d2b4d3SLarry Finger 	/* Reset MCU IO Wrapper */
1188f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
1189f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
1190f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
1191f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0));
1192f1d2b4d3SLarry Finger 
1193f1d2b4d3SLarry Finger 	/* 7. RSV_CTRL 0x1C[7:0] = 0x0E */
1194f1d2b4d3SLarry Finger 	/* lock ISO/CLK/Power control register */
1195f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
1196f1d2b4d3SLarry Finger }
1197f1d2b4d3SLarry Finger 
_rtl8723be_check_pcie_dma_hang(struct rtl_priv * rtlpriv)1198f1d2b4d3SLarry Finger static bool _rtl8723be_check_pcie_dma_hang(struct rtl_priv *rtlpriv)
1199f1d2b4d3SLarry Finger {
1200f1d2b4d3SLarry Finger 	u8 tmp;
1201f1d2b4d3SLarry Finger 
1202f1d2b4d3SLarry Finger 	/* write reg 0x350 Bit[26]=1. Enable debug port. */
1203f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3);
1204f1d2b4d3SLarry Finger 	if (!(tmp & BIT(2))) {
1205f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2)));
1206f1d2b4d3SLarry Finger 		mdelay(100); /* Suggested by DD Justin_tsai. */
1207f1d2b4d3SLarry Finger 	}
1208f1d2b4d3SLarry Finger 
1209f1d2b4d3SLarry Finger 	/* read reg 0x350 Bit[25] if 1 : RX hang
1210e6dd230aSLarry Finger 	 * read reg 0x350 Bit[24] if 1 : TX hang
1211f1d2b4d3SLarry Finger 	 */
1212f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3);
1213f1d2b4d3SLarry Finger 	if ((tmp & BIT(0)) || (tmp & BIT(1))) {
1214f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1215f1d2b4d3SLarry Finger 			"CheckPcieDMAHang8723BE(): true!!\n");
1216f1d2b4d3SLarry Finger 		return true;
1217f1d2b4d3SLarry Finger 	}
1218f1d2b4d3SLarry Finger 	return false;
1219f1d2b4d3SLarry Finger }
1220f1d2b4d3SLarry Finger 
_rtl8723be_reset_pcie_interface_dma(struct rtl_priv * rtlpriv,bool mac_power_on)1221f1d2b4d3SLarry Finger static void _rtl8723be_reset_pcie_interface_dma(struct rtl_priv *rtlpriv,
1222f1d2b4d3SLarry Finger 						bool mac_power_on)
1223f1d2b4d3SLarry Finger {
1224e6dd230aSLarry Finger 	u8 tmp;
1225f1d2b4d3SLarry Finger 	bool release_mac_rx_pause;
1226f1d2b4d3SLarry Finger 	u8 backup_pcie_dma_pause;
1227f1d2b4d3SLarry Finger 
1228f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1229f1d2b4d3SLarry Finger 		"ResetPcieInterfaceDMA8723BE()\n");
1230f1d2b4d3SLarry Finger 
1231f1d2b4d3SLarry Finger 	/* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03"
1232f1d2b4d3SLarry Finger 	 * released by SD1 Alan.
1233f1d2b4d3SLarry Finger 	 * 2013.05.07, by tynli.
1234f1d2b4d3SLarry Finger 	 */
1235f1d2b4d3SLarry Finger 
1236f1d2b4d3SLarry Finger 	/* 1. disable register write lock
1237f1d2b4d3SLarry Finger 	 *	write 0x1C bit[1:0] = 2'h0
1238f1d2b4d3SLarry Finger 	 *	write 0xCC bit[2] = 1'b1
1239f1d2b4d3SLarry Finger 	 */
1240f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL);
1241f1d2b4d3SLarry Finger 	tmp &= ~(BIT(1) | BIT(0));
1242f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp);
1243f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
1244f1d2b4d3SLarry Finger 	tmp |= BIT(2);
1245f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
1246f1d2b4d3SLarry Finger 
1247f1d2b4d3SLarry Finger 	/* 2. Check and pause TRX DMA
1248f1d2b4d3SLarry Finger 	 *	write 0x284 bit[18] = 1'b1
1249f1d2b4d3SLarry Finger 	 *	write 0x301 = 0xFF
1250f1d2b4d3SLarry Finger 	 */
1251f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
1252f1d2b4d3SLarry Finger 	if (tmp & BIT(2)) {
1253f1d2b4d3SLarry Finger 		/* Already pause before the function for another purpose. */
1254f1d2b4d3SLarry Finger 		release_mac_rx_pause = false;
1255f1d2b4d3SLarry Finger 	} else {
1256f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2)));
1257f1d2b4d3SLarry Finger 		release_mac_rx_pause = true;
1258f1d2b4d3SLarry Finger 	}
1259f1d2b4d3SLarry Finger 
1260f1d2b4d3SLarry Finger 	backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1);
1261f1d2b4d3SLarry Finger 	if (backup_pcie_dma_pause != 0xFF)
1262f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF);
1263f1d2b4d3SLarry Finger 
1264f1d2b4d3SLarry Finger 	if (mac_power_on) {
1265f1d2b4d3SLarry Finger 		/* 3. reset TRX function
1266f1d2b4d3SLarry Finger 		 *	write 0x100 = 0x00
1267f1d2b4d3SLarry Finger 		 */
1268f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_CR, 0);
1269f1d2b4d3SLarry Finger 	}
1270f1d2b4d3SLarry Finger 
1271f1d2b4d3SLarry Finger 	/* 4. Reset PCIe DMA
1272f1d2b4d3SLarry Finger 	 *	write 0x003 bit[0] = 0
1273f1d2b4d3SLarry Finger 	 */
1274f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
1275f1d2b4d3SLarry Finger 	tmp &= ~(BIT(0));
1276f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
1277f1d2b4d3SLarry Finger 
1278f1d2b4d3SLarry Finger 	/* 5. Enable PCIe DMA
1279f1d2b4d3SLarry Finger 	 *	write 0x003 bit[0] = 1
1280f1d2b4d3SLarry Finger 	 */
1281f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
1282f1d2b4d3SLarry Finger 	tmp |= BIT(0);
1283f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
1284f1d2b4d3SLarry Finger 
1285f1d2b4d3SLarry Finger 	if (mac_power_on) {
1286f1d2b4d3SLarry Finger 		/* 6. enable TRX function
1287f1d2b4d3SLarry Finger 		 *	write 0x100 = 0xFF
1288f1d2b4d3SLarry Finger 		 */
1289f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_CR, 0xFF);
1290f1d2b4d3SLarry Finger 
1291f1d2b4d3SLarry Finger 		/* We should init LLT & RQPN and
1292f1d2b4d3SLarry Finger 		 * prepare Tx/Rx descrptor address later
1293f1d2b4d3SLarry Finger 		 * because MAC function is reset.
1294f1d2b4d3SLarry Finger 		 */
1295f1d2b4d3SLarry Finger 	}
1296f1d2b4d3SLarry Finger 
1297f1d2b4d3SLarry Finger 	/* 7. Restore PCIe autoload down bit
1298f1d2b4d3SLarry Finger 	 *	write 0xF8 bit[17] = 1'b1
1299f1d2b4d3SLarry Finger 	 */
1300f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2);
1301f1d2b4d3SLarry Finger 	tmp |= BIT(1);
1302f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp);
1303f1d2b4d3SLarry Finger 
1304f1d2b4d3SLarry Finger 	/* In MAC power on state, BB and RF maybe in ON state,
1305f1d2b4d3SLarry Finger 	 * if we release TRx DMA here
1306f1d2b4d3SLarry Finger 	 * it will cause packets to be started to Tx/Rx,
1307f1d2b4d3SLarry Finger 	 * so we release Tx/Rx DMA later.
1308f1d2b4d3SLarry Finger 	 */
1309f1d2b4d3SLarry Finger 	if (!mac_power_on) {
1310f1d2b4d3SLarry Finger 		/* 8. release TRX DMA
1311f1d2b4d3SLarry Finger 		 *	write 0x284 bit[18] = 1'b0
1312f1d2b4d3SLarry Finger 		 *	write 0x301 = 0x00
1313f1d2b4d3SLarry Finger 		 */
1314f1d2b4d3SLarry Finger 		if (release_mac_rx_pause) {
1315f1d2b4d3SLarry Finger 			tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
1316f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL,
1317f1d2b4d3SLarry Finger 				       (tmp & (~BIT(2))));
1318f1d2b4d3SLarry Finger 		}
1319f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1,
1320f1d2b4d3SLarry Finger 			       backup_pcie_dma_pause);
1321f1d2b4d3SLarry Finger 	}
1322f1d2b4d3SLarry Finger 
1323f1d2b4d3SLarry Finger 	/* 9. lock system register
1324f1d2b4d3SLarry Finger 	 *	write 0xCC bit[2] = 1'b0
1325f1d2b4d3SLarry Finger 	 */
1326f1d2b4d3SLarry Finger 	tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
1327f1d2b4d3SLarry Finger 	tmp &= ~(BIT(2));
1328f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
1329f1d2b4d3SLarry Finger }
1330f1d2b4d3SLarry Finger 
rtl8723be_hw_init(struct ieee80211_hw * hw)1331f1d2b4d3SLarry Finger int rtl8723be_hw_init(struct ieee80211_hw *hw)
1332f1d2b4d3SLarry Finger {
1333f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1334f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1335f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1336f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
1337f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1338f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1339f1d2b4d3SLarry Finger 	bool rtstatus = true;
1340f1d2b4d3SLarry Finger 	int err;
1341f1d2b4d3SLarry Finger 	u8 tmp_u1b;
1342f1d2b4d3SLarry Finger 	unsigned long flags;
1343f1d2b4d3SLarry Finger 
1344f1d2b4d3SLarry Finger 	/* reenable interrupts to not interfere with other devices */
1345f1d2b4d3SLarry Finger 	local_save_flags(flags);
1346f1d2b4d3SLarry Finger 	local_irq_enable();
1347f1d2b4d3SLarry Finger 
1348f1d2b4d3SLarry Finger 	rtlhal->fw_ready = false;
1349f1d2b4d3SLarry Finger 	rtlpriv->rtlhal.being_init_adapter = true;
1350f1d2b4d3SLarry Finger 	rtlpriv->intf_ops->disable_aspm(hw);
1351f1d2b4d3SLarry Finger 
1352f1d2b4d3SLarry Finger 	tmp_u1b = rtl_read_byte(rtlpriv, REG_CR);
1353f1d2b4d3SLarry Finger 	if (tmp_u1b != 0 && tmp_u1b != 0xea) {
1354f1d2b4d3SLarry Finger 		rtlhal->mac_func_enable = true;
1355f1d2b4d3SLarry Finger 	} else {
1356f1d2b4d3SLarry Finger 		rtlhal->mac_func_enable = false;
1357f1d2b4d3SLarry Finger 		rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON;
1358f1d2b4d3SLarry Finger 	}
1359f1d2b4d3SLarry Finger 
1360f1d2b4d3SLarry Finger 	if (_rtl8723be_check_pcie_dma_hang(rtlpriv)) {
1361f1d2b4d3SLarry Finger 		_rtl8723be_reset_pcie_interface_dma(rtlpriv,
1362f1d2b4d3SLarry Finger 						    rtlhal->mac_func_enable);
1363f1d2b4d3SLarry Finger 		rtlhal->mac_func_enable = false;
1364f1d2b4d3SLarry Finger 	}
1365f1d2b4d3SLarry Finger 	if (rtlhal->mac_func_enable) {
1366f1d2b4d3SLarry Finger 		_rtl8723be_poweroff_adapter(hw);
13674e2b4378SLarry Finger 		rtlhal->mac_func_enable = false;
1368f1d2b4d3SLarry Finger 	}
1369f1d2b4d3SLarry Finger 	rtstatus = _rtl8723be_init_mac(hw);
1370f1d2b4d3SLarry Finger 	if (!rtstatus) {
1371f1d2b4d3SLarry Finger 		pr_err("Init MAC failed\n");
1372f1d2b4d3SLarry Finger 		err = 1;
1373f1d2b4d3SLarry Finger 		goto exit;
1374f1d2b4d3SLarry Finger 	}
1375f1d2b4d3SLarry Finger 
1376f1d2b4d3SLarry Finger 	tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG);
1377e6dd230aSLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b & 0x7F);
1378f1d2b4d3SLarry Finger 
1379f1d2b4d3SLarry Finger 	err = rtl8723_download_fw(hw, true, FW_8723B_POLLING_TIMEOUT_COUNT);
1380f1d2b4d3SLarry Finger 	if (err) {
1381f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
1382f1d2b4d3SLarry Finger 			"Failed to download FW. Init HW without FW now..\n");
1383f1d2b4d3SLarry Finger 		err = 1;
1384f1d2b4d3SLarry Finger 		goto exit;
1385f1d2b4d3SLarry Finger 	}
1386f1d2b4d3SLarry Finger 	rtlhal->fw_ready = true;
1387f1d2b4d3SLarry Finger 
1388f1d2b4d3SLarry Finger 	rtlhal->last_hmeboxnum = 0;
1389f1d2b4d3SLarry Finger 	rtl8723be_phy_mac_config(hw);
1390f1d2b4d3SLarry Finger 	/* because last function modify RCR, so we update
1391f1d2b4d3SLarry Finger 	 * rcr var here, or TP will unstable for receive_config
1392f1d2b4d3SLarry Finger 	 * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
1393f1d2b4d3SLarry Finger 	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
1394f1d2b4d3SLarry Finger 	 */
1395f1d2b4d3SLarry Finger 	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
1396f1d2b4d3SLarry Finger 	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
1397f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
1398f1d2b4d3SLarry Finger 
1399f1d2b4d3SLarry Finger 	rtl8723be_phy_bb_config(hw);
1400f1d2b4d3SLarry Finger 	rtl8723be_phy_rf_config(hw);
1401f1d2b4d3SLarry Finger 
1402f1d2b4d3SLarry Finger 	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
1403f1d2b4d3SLarry Finger 						 RF_CHNLBW, RFREG_OFFSET_MASK);
1404f1d2b4d3SLarry Finger 	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
1405f1d2b4d3SLarry Finger 						 RF_CHNLBW, RFREG_OFFSET_MASK);
1406f1d2b4d3SLarry Finger 	rtlphy->rfreg_chnlval[0] &= 0xFFF03FF;
1407f1d2b4d3SLarry Finger 	rtlphy->rfreg_chnlval[0] |= (BIT(10) | BIT(11));
1408f1d2b4d3SLarry Finger 
1409f1d2b4d3SLarry Finger 	_rtl8723be_hw_configure(hw);
1410f1d2b4d3SLarry Finger 	rtlhal->mac_func_enable = true;
1411f1d2b4d3SLarry Finger 	rtl_cam_reset_all_entry(hw);
1412f1d2b4d3SLarry Finger 	rtl8723be_enable_hw_security_config(hw);
1413f1d2b4d3SLarry Finger 
1414f1d2b4d3SLarry Finger 	ppsc->rfpwr_state = ERFON;
1415f1d2b4d3SLarry Finger 
1416f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
1417f1d2b4d3SLarry Finger 	_rtl8723be_enable_aspm_back_door(hw);
1418f1d2b4d3SLarry Finger 	rtlpriv->intf_ops->enable_aspm(hw);
1419f1d2b4d3SLarry Finger 
1420f1d2b4d3SLarry Finger 	rtl8723be_bt_hw_init(hw);
1421f1d2b4d3SLarry Finger 
1422f1d2b4d3SLarry Finger 	if (ppsc->rfpwr_state == ERFON) {
1423f1d2b4d3SLarry Finger 		rtl8723be_phy_set_rfpath_switch(hw, 1);
1424f1d2b4d3SLarry Finger 		/* when use 1ant NIC, iqk will disturb BT music
1425f1d2b4d3SLarry Finger 		 * root cause is not clear now, is something
1426a7088392SPing-Ke Shih 		 * related with 'mdelay' and Reg[0x948]
1427a7088392SPing-Ke Shih 		 */
1428a7088392SPing-Ke Shih 		if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2 ||
1429f1d2b4d3SLarry Finger 		    !rtlpriv->cfg->ops->get_btc_status()) {
1430f1d2b4d3SLarry Finger 			rtl8723be_phy_iq_calibrate(hw,
1431f1d2b4d3SLarry Finger 						   (rtlphy->iqk_initialized ?
1432f1d2b4d3SLarry Finger 						    true : false));
1433f1d2b4d3SLarry Finger 			rtlphy->iqk_initialized = true;
1434f1d2b4d3SLarry Finger 		}
1435f1d2b4d3SLarry Finger 		rtl8723be_dm_check_txpower_tracking(hw);
1436f1d2b4d3SLarry Finger 		rtl8723be_phy_lc_calibrate(hw);
1437f1d2b4d3SLarry Finger 	}
1438f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_NAV_UPPER, ((30000 + 127) / 128));
1439f1d2b4d3SLarry Finger 
1440f1d2b4d3SLarry Finger 	/* Release Rx DMA. */
1441f1d2b4d3SLarry Finger 	tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
1442f1d2b4d3SLarry Finger 	if (tmp_u1b & BIT(2)) {
1443f1d2b4d3SLarry Finger 		/* Release Rx DMA if needed */
1444f1d2b4d3SLarry Finger 		tmp_u1b &= (~BIT(2));
1445f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b);
1446f1d2b4d3SLarry Finger 	}
1447f1d2b4d3SLarry Finger 	/* Release Tx/Rx PCIE DMA. */
1448f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0);
1449f1d2b4d3SLarry Finger 
1450f1d2b4d3SLarry Finger 	rtl8723be_dm_init(hw);
1451f1d2b4d3SLarry Finger exit:
1452f1d2b4d3SLarry Finger 	local_irq_restore(flags);
1453f1d2b4d3SLarry Finger 	rtlpriv->rtlhal.being_init_adapter = false;
1454f1d2b4d3SLarry Finger 	return err;
1455f1d2b4d3SLarry Finger }
1456f1d2b4d3SLarry Finger 
_rtl8723be_read_chip_version(struct ieee80211_hw * hw)1457f1d2b4d3SLarry Finger static enum version_8723e _rtl8723be_read_chip_version(struct ieee80211_hw *hw)
1458f1d2b4d3SLarry Finger {
1459f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1460f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
1461f1d2b4d3SLarry Finger 	enum version_8723e version = VERSION_UNKNOWN;
1462e6dd230aSLarry Finger 	u32 value32;
1463f1d2b4d3SLarry Finger 
1464f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1);
1465f1d2b4d3SLarry Finger 	if ((value32 & (CHIP_8723B)) != CHIP_8723B)
1466f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "unknown chip version\n");
1467f1d2b4d3SLarry Finger 	else
1468f1d2b4d3SLarry Finger 		version = (enum version_8723e)CHIP_8723B;
1469f1d2b4d3SLarry Finger 
1470f1d2b4d3SLarry Finger 	rtlphy->rf_type = RF_1T1R;
1471f1d2b4d3SLarry Finger 
1472f1d2b4d3SLarry Finger 	/* treat rtl8723be chip as  MP version in default */
1473f1d2b4d3SLarry Finger 	version = (enum version_8723e)(version | NORMAL_CHIP);
1474f1d2b4d3SLarry Finger 
1475f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
1476f1d2b4d3SLarry Finger 	/* cut version */
1477f1d2b4d3SLarry Finger 	version |= (enum version_8723e)(value32 & CHIP_VER_RTL_MASK);
1478e6dd230aSLarry Finger 	/* Manufacture */
1479f1d2b4d3SLarry Finger 	if (((value32 & EXT_VENDOR_ID) >> 18) == 0x01)
1480f1d2b4d3SLarry Finger 		version = (enum version_8723e)(version | CHIP_VENDOR_SMIC);
1481f1d2b4d3SLarry Finger 
1482f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1483f1d2b4d3SLarry Finger 		"Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ?
1484f1d2b4d3SLarry Finger 		"RF_2T2R" : "RF_1T1R");
1485f1d2b4d3SLarry Finger 
1486f1d2b4d3SLarry Finger 	return version;
1487f1d2b4d3SLarry Finger }
1488f1d2b4d3SLarry Finger 
_rtl8723be_set_media_status(struct ieee80211_hw * hw,enum nl80211_iftype type)1489f1d2b4d3SLarry Finger static int _rtl8723be_set_media_status(struct ieee80211_hw *hw,
1490f1d2b4d3SLarry Finger 				       enum nl80211_iftype type)
1491f1d2b4d3SLarry Finger {
1492f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1493f1d2b4d3SLarry Finger 	u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc;
1494f1d2b4d3SLarry Finger 	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
1495f1d2b4d3SLarry Finger 	u8 mode = MSR_NOLINK;
1496e6dd230aSLarry Finger 
1497f1d2b4d3SLarry Finger 	switch (type) {
1498f1d2b4d3SLarry Finger 	case NL80211_IFTYPE_UNSPECIFIED:
1499f1d2b4d3SLarry Finger 		mode = MSR_NOLINK;
1500f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
1501f1d2b4d3SLarry Finger 			"Set Network type to NO LINK!\n");
1502e6dd230aSLarry Finger 		break;
1503f1d2b4d3SLarry Finger 	case NL80211_IFTYPE_ADHOC:
1504f1d2b4d3SLarry Finger 	case NL80211_IFTYPE_MESH_POINT:
1505f1d2b4d3SLarry Finger 		mode = MSR_ADHOC;
1506f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
1507f1d2b4d3SLarry Finger 			"Set Network type to Ad Hoc!\n");
1508e6dd230aSLarry Finger 		break;
1509f1d2b4d3SLarry Finger 	case NL80211_IFTYPE_STATION:
1510f1d2b4d3SLarry Finger 		mode = MSR_INFRA;
1511f1d2b4d3SLarry Finger 		ledaction = LED_CTL_LINK;
1512f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
1513f1d2b4d3SLarry Finger 			"Set Network type to STA!\n");
1514e6dd230aSLarry Finger 		break;
1515f1d2b4d3SLarry Finger 	case NL80211_IFTYPE_AP:
1516f1d2b4d3SLarry Finger 		mode = MSR_AP;
1517f1d2b4d3SLarry Finger 		ledaction = LED_CTL_LINK;
15184e2b4378SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
1519f1d2b4d3SLarry Finger 			"Set Network type to AP!\n");
1520f1d2b4d3SLarry Finger 		break;
1521f1d2b4d3SLarry Finger 	default:
1522f1d2b4d3SLarry Finger 		pr_err("Network type %d not support!\n", type);
1523f1d2b4d3SLarry Finger 		return 1;
1524f1d2b4d3SLarry Finger 	}
1525f1d2b4d3SLarry Finger 
1526f1d2b4d3SLarry Finger 	/* MSR_INFRA == Link in infrastructure network;
1527f1d2b4d3SLarry Finger 	 * MSR_ADHOC == Link in ad hoc network;
1528f1d2b4d3SLarry Finger 	 * Therefore, check link state is necessary.
1529f1d2b4d3SLarry Finger 	 *
1530f1d2b4d3SLarry Finger 	 * MSR_AP == AP mode; link state is not cared here.
1531f1d2b4d3SLarry Finger 	 */
1532f1d2b4d3SLarry Finger 	if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1533f1d2b4d3SLarry Finger 		mode = MSR_NOLINK;
1534f1d2b4d3SLarry Finger 		ledaction = LED_CTL_NO_LINK;
1535f1d2b4d3SLarry Finger 	}
1536f1d2b4d3SLarry Finger 
1537f1d2b4d3SLarry Finger 	if (mode == MSR_NOLINK || mode == MSR_INFRA) {
1538f1d2b4d3SLarry Finger 		_rtl8723be_stop_tx_beacon(hw);
1539f1d2b4d3SLarry Finger 		_rtl8723be_enable_bcn_sub_func(hw);
1540e6dd230aSLarry Finger 	} else if (mode == MSR_ADHOC || mode == MSR_AP) {
1541f1d2b4d3SLarry Finger 		_rtl8723be_resume_tx_beacon(hw);
1542f1d2b4d3SLarry Finger 		_rtl8723be_disable_bcn_sub_func(hw);
1543f1d2b4d3SLarry Finger 	} else {
1544f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
1545f1d2b4d3SLarry Finger 			"Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n",
1546f1d2b4d3SLarry Finger 			mode);
1547f1d2b4d3SLarry Finger 	}
1548f1d2b4d3SLarry Finger 
1549f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, MSR, bt_msr | mode);
1550f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->led_control(hw, ledaction);
1551f1d2b4d3SLarry Finger 	if (mode == MSR_AP)
1552f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
1553f1d2b4d3SLarry Finger 	else
1554f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
1555f1d2b4d3SLarry Finger 	return 0;
1556f1d2b4d3SLarry Finger }
1557f1d2b4d3SLarry Finger 
rtl8723be_set_check_bssid(struct ieee80211_hw * hw,bool check_bssid)1558f1d2b4d3SLarry Finger void rtl8723be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
1559f1d2b4d3SLarry Finger {
1560f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1561f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1562f1d2b4d3SLarry Finger 	u32 reg_rcr = rtlpci->receive_config;
1563f1d2b4d3SLarry Finger 
1564f1d2b4d3SLarry Finger 	if (rtlpriv->psc.rfpwr_state != ERFON)
1565f1d2b4d3SLarry Finger 		return;
1566f1d2b4d3SLarry Finger 
1567f1d2b4d3SLarry Finger 	if (check_bssid) {
1568f1d2b4d3SLarry Finger 		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
1569f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
1570f1d2b4d3SLarry Finger 					      (u8 *)(&reg_rcr));
1571f1d2b4d3SLarry Finger 		_rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4));
1572f1d2b4d3SLarry Finger 	} else if (!check_bssid) {
1573f1d2b4d3SLarry Finger 		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
1574f1d2b4d3SLarry Finger 		_rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0);
1575f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
1576f1d2b4d3SLarry Finger 					      (u8 *)(&reg_rcr));
1577f1d2b4d3SLarry Finger 	}
1578f1d2b4d3SLarry Finger 
1579f1d2b4d3SLarry Finger }
1580f1d2b4d3SLarry Finger 
rtl8723be_set_network_type(struct ieee80211_hw * hw,enum nl80211_iftype type)1581f1d2b4d3SLarry Finger int rtl8723be_set_network_type(struct ieee80211_hw *hw,
1582f1d2b4d3SLarry Finger 			       enum nl80211_iftype type)
1583f1d2b4d3SLarry Finger {
1584f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1585f1d2b4d3SLarry Finger 
1586f1d2b4d3SLarry Finger 	if (_rtl8723be_set_media_status(hw, type))
1587f1d2b4d3SLarry Finger 		return -EOPNOTSUPP;
1588f1d2b4d3SLarry Finger 
1589f1d2b4d3SLarry Finger 	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1590f1d2b4d3SLarry Finger 		if (type != NL80211_IFTYPE_AP)
1591f1d2b4d3SLarry Finger 			rtl8723be_set_check_bssid(hw, true);
1592f1d2b4d3SLarry Finger 	} else {
1593f1d2b4d3SLarry Finger 		rtl8723be_set_check_bssid(hw, false);
1594f1d2b4d3SLarry Finger 	}
1595f1d2b4d3SLarry Finger 
1596f1d2b4d3SLarry Finger 	return 0;
1597f1d2b4d3SLarry Finger }
1598f1d2b4d3SLarry Finger 
1599f1d2b4d3SLarry Finger /* don't set REG_EDCA_BE_PARAM here
1600f1d2b4d3SLarry Finger  * because mac80211 will send pkt when scan
1601f1d2b4d3SLarry Finger  */
rtl8723be_set_qos(struct ieee80211_hw * hw,int aci)1602f1d2b4d3SLarry Finger void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci)
1603f1d2b4d3SLarry Finger {
1604f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1605f1d2b4d3SLarry Finger 
1606f1d2b4d3SLarry Finger 	rtl8723_dm_init_edca_turbo(hw);
1607f1d2b4d3SLarry Finger 	switch (aci) {
1608f1d2b4d3SLarry Finger 	case AC1_BK:
1609f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
1610f1d2b4d3SLarry Finger 		break;
1611f1d2b4d3SLarry Finger 	case AC0_BE:
1612f1d2b4d3SLarry Finger 		break;
1613f1d2b4d3SLarry Finger 	case AC2_VI:
1614f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
1615f1d2b4d3SLarry Finger 		break;
1616531940f9SLarry Finger 	case AC3_VO:
1617f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
1618f1d2b4d3SLarry Finger 		break;
1619f1d2b4d3SLarry Finger 	default:
1620f1d2b4d3SLarry Finger 		WARN_ONCE(true, "rtl8723be: invalid aci: %d !\n", aci);
1621f1d2b4d3SLarry Finger 		break;
1622f1d2b4d3SLarry Finger 	}
1623f1d2b4d3SLarry Finger }
1624f1d2b4d3SLarry Finger 
rtl8723be_enable_interrupt(struct ieee80211_hw * hw)1625f1d2b4d3SLarry Finger void rtl8723be_enable_interrupt(struct ieee80211_hw *hw)
1626f1d2b4d3SLarry Finger {
1627f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1628f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1629f1d2b4d3SLarry Finger 
1630f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
1631f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
1632f1d2b4d3SLarry Finger 	rtlpci->irq_enabled = true;
1633f1d2b4d3SLarry Finger 
1634f1d2b4d3SLarry Finger 	/*enable system interrupt*/
1635f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF);
1636f1d2b4d3SLarry Finger }
1637f1d2b4d3SLarry Finger 
rtl8723be_disable_interrupt(struct ieee80211_hw * hw)1638f1d2b4d3SLarry Finger void rtl8723be_disable_interrupt(struct ieee80211_hw *hw)
1639f1d2b4d3SLarry Finger {
1640f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1641f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1642f1d2b4d3SLarry Finger 
1643f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED);
1644f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED);
1645f1d2b4d3SLarry Finger 	rtlpci->irq_enabled = false;
1646f1d2b4d3SLarry Finger 	/*synchronize_irq(rtlpci->pdev->irq);*/
1647f1d2b4d3SLarry Finger }
1648f1d2b4d3SLarry Finger 
rtl8723be_card_disable(struct ieee80211_hw * hw)1649f1d2b4d3SLarry Finger void rtl8723be_card_disable(struct ieee80211_hw *hw)
1650f1d2b4d3SLarry Finger {
1651f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1652f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1653f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1654f1d2b4d3SLarry Finger 	enum nl80211_iftype opmode;
1655f1d2b4d3SLarry Finger 
1656f1d2b4d3SLarry Finger 	mac->link_state = MAC80211_NOLINK;
1657f1d2b4d3SLarry Finger 	opmode = NL80211_IFTYPE_UNSPECIFIED;
1658f1d2b4d3SLarry Finger 	_rtl8723be_set_media_status(hw, opmode);
1659f1d2b4d3SLarry Finger 	if (rtlpriv->rtlhal.driver_is_goingto_unload ||
1660f1d2b4d3SLarry Finger 	    ppsc->rfoff_reason > RF_CHANGE_BY_PS)
1661f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
1662a7088392SPing-Ke Shih 	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
1663f1d2b4d3SLarry Finger 	_rtl8723be_poweroff_adapter(hw);
1664f1d2b4d3SLarry Finger 
1665f1d2b4d3SLarry Finger 	/* after power off we should do iqk again */
1666f1d2b4d3SLarry Finger 	if (!rtlpriv->cfg->ops->get_btc_status())
166778aa6012SLarry Finger 		rtlpriv->phy.iqk_initialized = false;
1668f1d2b4d3SLarry Finger }
1669f1d2b4d3SLarry Finger 
rtl8723be_interrupt_recognized(struct ieee80211_hw * hw,struct rtl_int * intvec)1670f1d2b4d3SLarry Finger void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw,
1671f1d2b4d3SLarry Finger 				    struct rtl_int *intvec)
167278aa6012SLarry Finger {
167378aa6012SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1674f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
167578aa6012SLarry Finger 
1676f1d2b4d3SLarry Finger 	intvec->inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0];
167778aa6012SLarry Finger 	rtl_write_dword(rtlpriv, ISR, intvec->inta);
1678f1d2b4d3SLarry Finger 
1679f1d2b4d3SLarry Finger 	intvec->intb = rtl_read_dword(rtlpriv, REG_HISRE) &
1680f1d2b4d3SLarry Finger 				      rtlpci->irq_mask[1];
1681f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_HISRE, intvec->intb);
1682f1d2b4d3SLarry Finger }
1683f1d2b4d3SLarry Finger 
rtl8723be_set_beacon_related_registers(struct ieee80211_hw * hw)1684f1d2b4d3SLarry Finger void rtl8723be_set_beacon_related_registers(struct ieee80211_hw *hw)
1685f1d2b4d3SLarry Finger {
1686f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1687f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1688f1d2b4d3SLarry Finger 	u16 bcn_interval, atim_window;
1689f1d2b4d3SLarry Finger 
1690f1d2b4d3SLarry Finger 	bcn_interval = mac->beacon_interval;
1691f1d2b4d3SLarry Finger 	atim_window = 2;	/*FIX MERGE */
1692f1d2b4d3SLarry Finger 	rtl8723be_disable_interrupt(hw);
1693f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
1694f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
1695f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
1696f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18);
1697f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18);
1698f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, 0x606, 0x30);
1699f1d2b4d3SLarry Finger 	rtl8723be_enable_interrupt(hw);
1700f1d2b4d3SLarry Finger }
1701f1d2b4d3SLarry Finger 
rtl8723be_set_beacon_interval(struct ieee80211_hw * hw)1702f1d2b4d3SLarry Finger void rtl8723be_set_beacon_interval(struct ieee80211_hw *hw)
1703f1d2b4d3SLarry Finger {
1704e6dd230aSLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1705f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1706f1d2b4d3SLarry Finger 	u16 bcn_interval = mac->beacon_interval;
1707f1d2b4d3SLarry Finger 
1708f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_BEACON, DBG_DMESG,
1709f1d2b4d3SLarry Finger 		"beacon_interval:%d\n", bcn_interval);
1710f1d2b4d3SLarry Finger 	rtl8723be_disable_interrupt(hw);
1711f1d2b4d3SLarry Finger 	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
1712f1d2b4d3SLarry Finger 	rtl8723be_enable_interrupt(hw);
1713f1d2b4d3SLarry Finger }
1714f1d2b4d3SLarry Finger 
rtl8723be_update_interrupt_mask(struct ieee80211_hw * hw,u32 add_msr,u32 rm_msr)1715f1d2b4d3SLarry Finger void rtl8723be_update_interrupt_mask(struct ieee80211_hw *hw,
1716f1d2b4d3SLarry Finger 				   u32 add_msr, u32 rm_msr)
1717e6dd230aSLarry Finger {
1718f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1719f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1720f1d2b4d3SLarry Finger 
1721f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INTR, DBG_LOUD,
1722f1d2b4d3SLarry Finger 		"add_msr:%x, rm_msr:%x\n", add_msr, rm_msr);
1723f1d2b4d3SLarry Finger 
1724f1d2b4d3SLarry Finger 	if (add_msr)
1725f1d2b4d3SLarry Finger 		rtlpci->irq_mask[0] |= add_msr;
1726f1d2b4d3SLarry Finger 	if (rm_msr)
1727f1d2b4d3SLarry Finger 		rtlpci->irq_mask[0] &= (~rm_msr);
1728f1d2b4d3SLarry Finger 	rtl8723be_disable_interrupt(hw);
1729f1d2b4d3SLarry Finger 	rtl8723be_enable_interrupt(hw);
1730f1d2b4d3SLarry Finger }
1731f1d2b4d3SLarry Finger 
_rtl8723be_get_chnl_group(u8 chnl)1732f1d2b4d3SLarry Finger static u8 _rtl8723be_get_chnl_group(u8 chnl)
1733f1d2b4d3SLarry Finger {
1734f1d2b4d3SLarry Finger 	u8 group;
1735f1d2b4d3SLarry Finger 
1736f1d2b4d3SLarry Finger 	if (chnl < 3)
1737f1d2b4d3SLarry Finger 		group = 0;
1738f1d2b4d3SLarry Finger 	else if (chnl < 9)
1739f1d2b4d3SLarry Finger 		group = 1;
1740f1d2b4d3SLarry Finger 	else
1741f1d2b4d3SLarry Finger 		group = 2;
1742f1d2b4d3SLarry Finger 	return group;
1743f1d2b4d3SLarry Finger }
1744f1d2b4d3SLarry Finger 
_rtl8723be_read_power_value_fromprom(struct ieee80211_hw * hw,struct txpower_info_2g * pw2g,struct txpower_info_5g * pw5g,bool autoload_fail,u8 * hwinfo)1745f1d2b4d3SLarry Finger static void _rtl8723be_read_power_value_fromprom(struct ieee80211_hw *hw,
1746f1d2b4d3SLarry Finger 					struct txpower_info_2g *pw2g,
1747f1d2b4d3SLarry Finger 					struct txpower_info_5g *pw5g,
1748f1d2b4d3SLarry Finger 					bool autoload_fail, u8 *hwinfo)
1749e6dd230aSLarry Finger {
1750f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1751f1d2b4d3SLarry Finger 	u32 path, addr = EEPROM_TX_PWR_INX, group, cnt = 0;
1752f1d2b4d3SLarry Finger 
1753f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1754f1d2b4d3SLarry Finger 		"hal_ReadPowerValueFromPROM8723BE(): PROMContent[0x%x]=0x%x\n",
1755f1d2b4d3SLarry Finger 		(addr + 1), hwinfo[addr + 1]);
1756e6dd230aSLarry Finger 	if (0xFF == hwinfo[addr + 1])  /*YJ,add,120316*/
1757f1d2b4d3SLarry Finger 		autoload_fail = true;
1758f1d2b4d3SLarry Finger 
1759f1d2b4d3SLarry Finger 	if (autoload_fail) {
1760f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1761f1d2b4d3SLarry Finger 			"auto load fail : Use Default value!\n");
1762f1d2b4d3SLarry Finger 		for (path = 0; path < MAX_RF_PATH; path++) {
1763f1d2b4d3SLarry Finger 			/* 2.4G default value */
1764f1d2b4d3SLarry Finger 			for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) {
1765f1d2b4d3SLarry Finger 				pw2g->index_cck_base[path][group] = 0x2D;
1766f1d2b4d3SLarry Finger 				pw2g->index_bw40_base[path][group] = 0x2D;
1767f1d2b4d3SLarry Finger 			}
1768f1d2b4d3SLarry Finger 			for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) {
1769f1d2b4d3SLarry Finger 				if (cnt == 0) {
1770f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][0] = 0x02;
1771f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][0] = 0x04;
1772f1d2b4d3SLarry Finger 				} else {
1773f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][cnt] = 0xFE;
1774f1d2b4d3SLarry Finger 					pw2g->bw40_diff[path][cnt] = 0xFE;
1775f1d2b4d3SLarry Finger 					pw2g->cck_diff[path][cnt] = 0xFE;
1776f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][cnt] = 0xFE;
1777f1d2b4d3SLarry Finger 				}
1778f1d2b4d3SLarry Finger 			}
1779f1d2b4d3SLarry Finger 		}
1780f1d2b4d3SLarry Finger 		return;
1781f1d2b4d3SLarry Finger 	}
1782f1d2b4d3SLarry Finger 
1783f1d2b4d3SLarry Finger 	for (path = 0; path < MAX_RF_PATH; path++) {
1784f1d2b4d3SLarry Finger 		/*2.4G default value*/
1785f1d2b4d3SLarry Finger 		for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
1786f1d2b4d3SLarry Finger 			pw2g->index_cck_base[path][group] = hwinfo[addr++];
1787f1d2b4d3SLarry Finger 			if (pw2g->index_cck_base[path][group] == 0xFF)
1788f1d2b4d3SLarry Finger 				pw2g->index_cck_base[path][group] = 0x2D;
1789f1d2b4d3SLarry Finger 
1790f1d2b4d3SLarry Finger 		}
1791f1d2b4d3SLarry Finger 		for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
1792f1d2b4d3SLarry Finger 			pw2g->index_bw40_base[path][group] = hwinfo[addr++];
1793f1d2b4d3SLarry Finger 			if (pw2g->index_bw40_base[path][group] == 0xFF)
1794f1d2b4d3SLarry Finger 				pw2g->index_bw40_base[path][group] = 0x2D;
1795f1d2b4d3SLarry Finger 		}
1796f1d2b4d3SLarry Finger 		for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) {
1797f1d2b4d3SLarry Finger 			if (cnt == 0) {
1798f1d2b4d3SLarry Finger 				pw2g->bw40_diff[path][cnt] = 0;
1799f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1800f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][cnt] = 0x02;
1801f1d2b4d3SLarry Finger 				} else {
1802f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][cnt] =
1803f1d2b4d3SLarry Finger 						(hwinfo[addr] & 0xf0) >> 4;
1804f1d2b4d3SLarry Finger 					/*bit sign number to 8 bit sign number*/
1805f1d2b4d3SLarry Finger 					if (pw2g->bw20_diff[path][cnt] & BIT(3))
1806f1d2b4d3SLarry Finger 						pw2g->bw20_diff[path][cnt] |=
1807f1d2b4d3SLarry Finger 									  0xF0;
1808f1d2b4d3SLarry Finger 				}
1809f1d2b4d3SLarry Finger 
1810f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1811f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][cnt] = 0x04;
1812f1d2b4d3SLarry Finger 				} else {
1813f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][cnt] =
1814f1d2b4d3SLarry Finger 							(hwinfo[addr] & 0x0f);
1815f1d2b4d3SLarry Finger 					/*bit sign number to 8 bit sign number*/
1816f1d2b4d3SLarry Finger 					if (pw2g->ofdm_diff[path][cnt] & BIT(3))
1817f1d2b4d3SLarry Finger 						pw2g->ofdm_diff[path][cnt] |=
1818f1d2b4d3SLarry Finger 									  0xF0;
1819f1d2b4d3SLarry Finger 				}
1820f1d2b4d3SLarry Finger 				pw2g->cck_diff[path][cnt] = 0;
1821f1d2b4d3SLarry Finger 				addr++;
1822f1d2b4d3SLarry Finger 			} else {
1823f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1824f1d2b4d3SLarry Finger 					pw2g->bw40_diff[path][cnt] = 0xFE;
1825f1d2b4d3SLarry Finger 				} else {
1826f1d2b4d3SLarry Finger 					pw2g->bw40_diff[path][cnt] =
1827f1d2b4d3SLarry Finger 						(hwinfo[addr] & 0xf0) >> 4;
1828f1d2b4d3SLarry Finger 					if (pw2g->bw40_diff[path][cnt] & BIT(3))
1829f1d2b4d3SLarry Finger 						pw2g->bw40_diff[path][cnt] |=
1830f1d2b4d3SLarry Finger 									  0xF0;
1831f1d2b4d3SLarry Finger 				}
1832f1d2b4d3SLarry Finger 
1833f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1834f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][cnt] = 0xFE;
1835f1d2b4d3SLarry Finger 				} else {
1836f1d2b4d3SLarry Finger 					pw2g->bw20_diff[path][cnt] =
1837f1d2b4d3SLarry Finger 							(hwinfo[addr] & 0x0f);
1838f1d2b4d3SLarry Finger 					if (pw2g->bw20_diff[path][cnt] & BIT(3))
1839f1d2b4d3SLarry Finger 						pw2g->bw20_diff[path][cnt] |=
1840f1d2b4d3SLarry Finger 									  0xF0;
1841f1d2b4d3SLarry Finger 				}
1842f1d2b4d3SLarry Finger 				addr++;
1843f1d2b4d3SLarry Finger 
1844f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1845f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][cnt] = 0xFE;
1846f1d2b4d3SLarry Finger 				} else {
1847f1d2b4d3SLarry Finger 					pw2g->ofdm_diff[path][cnt] =
1848f1d2b4d3SLarry Finger 						(hwinfo[addr] & 0xf0) >> 4;
1849f1d2b4d3SLarry Finger 					if (pw2g->ofdm_diff[path][cnt] & BIT(3))
1850f1d2b4d3SLarry Finger 						pw2g->ofdm_diff[path][cnt] |=
1851f1d2b4d3SLarry Finger 									  0xF0;
1852f1d2b4d3SLarry Finger 				}
1853f1d2b4d3SLarry Finger 
1854f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF)
1855f1d2b4d3SLarry Finger 					pw2g->cck_diff[path][cnt] = 0xFE;
1856f1d2b4d3SLarry Finger 				else {
1857f1d2b4d3SLarry Finger 					pw2g->cck_diff[path][cnt] =
1858f1d2b4d3SLarry Finger 							(hwinfo[addr] & 0x0f);
1859f1d2b4d3SLarry Finger 					if (pw2g->cck_diff[path][cnt] & BIT(3))
1860f1d2b4d3SLarry Finger 						pw2g->cck_diff[path][cnt] |=
1861f1d2b4d3SLarry Finger 									 0xF0;
1862f1d2b4d3SLarry Finger 				}
1863f1d2b4d3SLarry Finger 				addr++;
1864f1d2b4d3SLarry Finger 			}
1865f1d2b4d3SLarry Finger 		}
1866f1d2b4d3SLarry Finger 
1867f1d2b4d3SLarry Finger 		/*5G default value*/
1868f1d2b4d3SLarry Finger 		for (group = 0; group < MAX_CHNL_GROUP_5G; group++) {
1869f1d2b4d3SLarry Finger 			pw5g->index_bw40_base[path][group] = hwinfo[addr++];
1870f1d2b4d3SLarry Finger 			if (pw5g->index_bw40_base[path][group] == 0xFF)
1871f1d2b4d3SLarry Finger 				pw5g->index_bw40_base[path][group] = 0xFE;
1872f1d2b4d3SLarry Finger 		}
1873f1d2b4d3SLarry Finger 
1874f1d2b4d3SLarry Finger 		for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) {
1875f1d2b4d3SLarry Finger 			if (cnt == 0) {
1876f1d2b4d3SLarry Finger 				pw5g->bw40_diff[path][cnt] = 0;
1877f1d2b4d3SLarry Finger 
1878f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1879f1d2b4d3SLarry Finger 					pw5g->bw20_diff[path][cnt] = 0;
1880f1d2b4d3SLarry Finger 				} else {
1881f1d2b4d3SLarry Finger 					pw5g->bw20_diff[path][0] =
1882f1d2b4d3SLarry Finger 						(hwinfo[addr] & 0xf0) >> 4;
1883f1d2b4d3SLarry Finger 					if (pw5g->bw20_diff[path][cnt] & BIT(3))
1884f1d2b4d3SLarry Finger 						pw5g->bw20_diff[path][cnt] |=
1885f1d2b4d3SLarry Finger 									  0xF0;
1886f1d2b4d3SLarry Finger 				}
1887f1d2b4d3SLarry Finger 
1888f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF)
1889f1d2b4d3SLarry Finger 					pw5g->ofdm_diff[path][cnt] = 0x04;
1890f1d2b4d3SLarry Finger 				else {
1891f1d2b4d3SLarry Finger 					pw5g->ofdm_diff[path][0] =
1892f1d2b4d3SLarry Finger 							(hwinfo[addr] & 0x0f);
1893f1d2b4d3SLarry Finger 					if (pw5g->ofdm_diff[path][cnt] & BIT(3))
1894f1d2b4d3SLarry Finger 						pw5g->ofdm_diff[path][cnt] |=
1895f1d2b4d3SLarry Finger 									  0xF0;
1896f1d2b4d3SLarry Finger 				}
1897f1d2b4d3SLarry Finger 				addr++;
1898f1d2b4d3SLarry Finger 			} else {
1899f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1900f1d2b4d3SLarry Finger 					pw5g->bw40_diff[path][cnt] = 0xFE;
1901f1d2b4d3SLarry Finger 				} else {
1902f1d2b4d3SLarry Finger 					pw5g->bw40_diff[path][cnt] =
1903f1d2b4d3SLarry Finger 						(hwinfo[addr] & 0xf0) >> 4;
1904f1d2b4d3SLarry Finger 					if (pw5g->bw40_diff[path][cnt] & BIT(3))
1905f1d2b4d3SLarry Finger 						pw5g->bw40_diff[path][cnt] |= 0xF0;
1906f1d2b4d3SLarry Finger 				}
1907f1d2b4d3SLarry Finger 
1908f1d2b4d3SLarry Finger 				if (hwinfo[addr] == 0xFF) {
1909f1d2b4d3SLarry Finger 					pw5g->bw20_diff[path][cnt] = 0xFE;
1910f1d2b4d3SLarry Finger 				} else {
1911f1d2b4d3SLarry Finger 					pw5g->bw20_diff[path][cnt] =
1912f1d2b4d3SLarry Finger 							(hwinfo[addr] & 0x0f);
1913f1d2b4d3SLarry Finger 					if (pw5g->bw20_diff[path][cnt] & BIT(3))
1914f1d2b4d3SLarry Finger 						pw5g->bw20_diff[path][cnt] |= 0xF0;
1915f1d2b4d3SLarry Finger 				}
1916f1d2b4d3SLarry Finger 				addr++;
1917f1d2b4d3SLarry Finger 			}
1918f1d2b4d3SLarry Finger 		}
1919f1d2b4d3SLarry Finger 
1920f1d2b4d3SLarry Finger 		if (hwinfo[addr] == 0xFF) {
1921f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][1] = 0xFE;
1922f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][2] = 0xFE;
1923f1d2b4d3SLarry Finger 		} else {
1924f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][1] = (hwinfo[addr] & 0xf0) >> 4;
1925f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][2] = (hwinfo[addr] & 0x0f);
1926f1d2b4d3SLarry Finger 		}
1927f1d2b4d3SLarry Finger 		addr++;
1928f1d2b4d3SLarry Finger 
1929f1d2b4d3SLarry Finger 		if (hwinfo[addr] == 0xFF)
1930f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][3] = 0xFE;
1931f1d2b4d3SLarry Finger 		else
1932f1d2b4d3SLarry Finger 			pw5g->ofdm_diff[path][3] = (hwinfo[addr] & 0x0f);
1933f1d2b4d3SLarry Finger 		addr++;
1934f1d2b4d3SLarry Finger 
1935f1d2b4d3SLarry Finger 		for (cnt = 1; cnt < MAX_TX_COUNT; cnt++) {
1936f1d2b4d3SLarry Finger 			if (pw5g->ofdm_diff[path][cnt] == 0xFF)
1937f1d2b4d3SLarry Finger 				pw5g->ofdm_diff[path][cnt] = 0xFE;
1938f1d2b4d3SLarry Finger 			else if (pw5g->ofdm_diff[path][cnt] & BIT(3))
1939f1d2b4d3SLarry Finger 				pw5g->ofdm_diff[path][cnt] |= 0xF0;
1940f1d2b4d3SLarry Finger 		}
1941f1d2b4d3SLarry Finger 	}
1942f1d2b4d3SLarry Finger }
1943f1d2b4d3SLarry Finger 
_rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw * hw,bool autoload_fail,u8 * hwinfo)1944f1d2b4d3SLarry Finger static void _rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
1945f1d2b4d3SLarry Finger 						   bool autoload_fail,
1946f1d2b4d3SLarry Finger 						   u8 *hwinfo)
1947f1d2b4d3SLarry Finger {
1948f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1949f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1950f1d2b4d3SLarry Finger 	struct txpower_info_2g pw2g;
1951f1d2b4d3SLarry Finger 	struct txpower_info_5g pw5g;
1952f1d2b4d3SLarry Finger 	u8 rf_path, index;
1953f1d2b4d3SLarry Finger 	u8 i;
1954f1d2b4d3SLarry Finger 
1955f1d2b4d3SLarry Finger 	_rtl8723be_read_power_value_fromprom(hw, &pw2g, &pw5g, autoload_fail,
1956f1d2b4d3SLarry Finger 					     hwinfo);
1957f1d2b4d3SLarry Finger 
1958f1d2b4d3SLarry Finger 	for (rf_path = 0; rf_path < 2; rf_path++) {
1959f1d2b4d3SLarry Finger 		for (i = 0; i < 14; i++) {
1960f1d2b4d3SLarry Finger 			index = _rtl8723be_get_chnl_group(i+1);
1961f1d2b4d3SLarry Finger 
1962f1d2b4d3SLarry Finger 			rtlefuse->txpwrlevel_cck[rf_path][i] =
1963f1d2b4d3SLarry Finger 					pw2g.index_cck_base[rf_path][index];
1964f1d2b4d3SLarry Finger 			rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
1965f1d2b4d3SLarry Finger 					pw2g.index_bw40_base[rf_path][index];
1966f1d2b4d3SLarry Finger 		}
1967f1d2b4d3SLarry Finger 		for (i = 0; i < MAX_TX_COUNT; i++) {
1968f1d2b4d3SLarry Finger 			rtlefuse->txpwr_ht20diff[rf_path][i] =
1969f1d2b4d3SLarry Finger 						pw2g.bw20_diff[rf_path][i];
1970f1d2b4d3SLarry Finger 			rtlefuse->txpwr_ht40diff[rf_path][i] =
1971f1d2b4d3SLarry Finger 						pw2g.bw40_diff[rf_path][i];
1972f1d2b4d3SLarry Finger 			rtlefuse->txpwr_legacyhtdiff[rf_path][i] =
1973f1d2b4d3SLarry Finger 						pw2g.ofdm_diff[rf_path][i];
1974f1d2b4d3SLarry Finger 		}
1975f1d2b4d3SLarry Finger 
1976f1d2b4d3SLarry Finger 		for (i = 0; i < 14; i++) {
1977f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
1978f1d2b4d3SLarry Finger 				"RF(%d)-Ch(%d) [CCK / HT40_1S ] = [0x%x / 0x%x ]\n",
1979f1d2b4d3SLarry Finger 				rf_path, i,
1980f1d2b4d3SLarry Finger 				rtlefuse->txpwrlevel_cck[rf_path][i],
1981f1d2b4d3SLarry Finger 				rtlefuse->txpwrlevel_ht40_1s[rf_path][i]);
1982f1d2b4d3SLarry Finger 		}
1983f1d2b4d3SLarry Finger 	}
1984f1d2b4d3SLarry Finger 
1985f1d2b4d3SLarry Finger 	if (!autoload_fail)
1986f1d2b4d3SLarry Finger 		rtlefuse->eeprom_thermalmeter =
1987f1d2b4d3SLarry Finger 					hwinfo[EEPROM_THERMAL_METER_88E];
1988f1d2b4d3SLarry Finger 	else
1989f1d2b4d3SLarry Finger 		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
1990f1d2b4d3SLarry Finger 
1991f1d2b4d3SLarry Finger 	if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) {
1992f1d2b4d3SLarry Finger 		rtlefuse->apk_thermalmeterignore = true;
1993f1d2b4d3SLarry Finger 		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
1994f1d2b4d3SLarry Finger 	}
1995f1d2b4d3SLarry Finger 
1996f1d2b4d3SLarry Finger 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
1997f1d2b4d3SLarry Finger 	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
1998f1d2b4d3SLarry Finger 		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
1999f1d2b4d3SLarry Finger 
2000f1d2b4d3SLarry Finger 	if (!autoload_fail) {
2001f1d2b4d3SLarry Finger 		rtlefuse->eeprom_regulatory =
2002f1d2b4d3SLarry Finger 			hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x07;/*bit0~2*/
2003f1d2b4d3SLarry Finger 		if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
2004f1d2b4d3SLarry Finger 			rtlefuse->eeprom_regulatory = 0;
2005f1d2b4d3SLarry Finger 	} else {
2006f1d2b4d3SLarry Finger 		rtlefuse->eeprom_regulatory = 0;
2007f1d2b4d3SLarry Finger 	}
20087fe1fe75SPing-Ke Shih 	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
20097fe1fe75SPing-Ke Shih 		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
20107fe1fe75SPing-Ke Shih }
20117fe1fe75SPing-Ke Shih 
_rtl8723be_read_package_type(struct ieee80211_hw * hw)20127fe1fe75SPing-Ke Shih static u8 _rtl8723be_read_package_type(struct ieee80211_hw *hw)
20137fe1fe75SPing-Ke Shih {
20147fe1fe75SPing-Ke Shih 	u8 package_type;
20157fe1fe75SPing-Ke Shih 	u8 value;
20167fe1fe75SPing-Ke Shih 
20177fe1fe75SPing-Ke Shih 	efuse_power_switch(hw, false, true);
20187fe1fe75SPing-Ke Shih 	if (!efuse_one_byte_read(hw, 0x1FB, &value))
20197fe1fe75SPing-Ke Shih 		value = 0;
20207fe1fe75SPing-Ke Shih 	efuse_power_switch(hw, false, false);
20217fe1fe75SPing-Ke Shih 
20227fe1fe75SPing-Ke Shih 	switch (value & 0x7) {
20237fe1fe75SPing-Ke Shih 	case 0x4:
20247fe1fe75SPing-Ke Shih 		package_type = PACKAGE_TFBGA79;
20257fe1fe75SPing-Ke Shih 		break;
20267fe1fe75SPing-Ke Shih 	case 0x5:
20277fe1fe75SPing-Ke Shih 		package_type = PACKAGE_TFBGA90;
20287fe1fe75SPing-Ke Shih 		break;
20297fe1fe75SPing-Ke Shih 	case 0x6:
20307fe1fe75SPing-Ke Shih 		package_type = PACKAGE_QFN68;
20317fe1fe75SPing-Ke Shih 		break;
20327fe1fe75SPing-Ke Shih 	case 0x7:
20337fe1fe75SPing-Ke Shih 		package_type = PACKAGE_TFBGA80;
20347fe1fe75SPing-Ke Shih 		break;
20357fe1fe75SPing-Ke Shih 	default:
20367fe1fe75SPing-Ke Shih 		package_type = PACKAGE_DEFAULT;
20377fe1fe75SPing-Ke Shih 		break;
20387fe1fe75SPing-Ke Shih 	}
2039f1d2b4d3SLarry Finger 
2040f1d2b4d3SLarry Finger 	return package_type;
2041f1d2b4d3SLarry Finger }
2042f1d2b4d3SLarry Finger 
_rtl8723be_read_adapter_info(struct ieee80211_hw * hw,bool pseudo_test)2043f1d2b4d3SLarry Finger static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw,
2044f1d2b4d3SLarry Finger 					 bool pseudo_test)
20459e9c9c24SLarry Finger {
20469e9c9c24SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
20479e9c9c24SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
20489e9c9c24SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
20499e9c9c24SLarry Finger 	int params[] = {RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID,
20509e9c9c24SLarry Finger 			EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR,
2051f1d2b4d3SLarry Finger 			EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID,
2052f1d2b4d3SLarry Finger 			COUNTRY_CODE_WORLD_WIDE_13};
2053f1d2b4d3SLarry Finger 	u8 *hwinfo;
2054f1d2b4d3SLarry Finger 	int i;
2055f1d2b4d3SLarry Finger 	bool is_toshiba_smid1 = false;
2056f1d2b4d3SLarry Finger 	bool is_toshiba_smid2 = false;
2057f1d2b4d3SLarry Finger 	bool is_samsung_smid = false;
2058f1d2b4d3SLarry Finger 	bool is_lenovo_smid = false;
2059f1d2b4d3SLarry Finger 	u16 toshiba_smid1[] = {
2060f1d2b4d3SLarry Finger 		0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180,
2061f1d2b4d3SLarry Finger 		0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180,
2062f1d2b4d3SLarry Finger 		0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185,
2063f1d2b4d3SLarry Finger 		0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185
2064f1d2b4d3SLarry Finger 	};
2065f1d2b4d3SLarry Finger 	u16 toshiba_smid2[] = {
2066f1d2b4d3SLarry Finger 		0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181,
2067f1d2b4d3SLarry Finger 		0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185
2068f1d2b4d3SLarry Finger 	};
2069f1d2b4d3SLarry Finger 	u16 samsung_smid[] = {
2070f1d2b4d3SLarry Finger 		0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192,
2071f1d2b4d3SLarry Finger 		0x8193, 0x9191, 0x9192, 0x9193
2072f1d2b4d3SLarry Finger 	};
2073f1d2b4d3SLarry Finger 	u16 lenovo_smid[] = {
2074f1d2b4d3SLarry Finger 		0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200
2075f1d2b4d3SLarry Finger 	};
2076f1d2b4d3SLarry Finger 
2077f1d2b4d3SLarry Finger 	if (pseudo_test) {
20789e9c9c24SLarry Finger 		/* needs to be added */
20799e9c9c24SLarry Finger 		return;
20805345ea6aSArnd Bergmann 	}
20815345ea6aSArnd Bergmann 
20829e9c9c24SLarry Finger 	hwinfo = kzalloc(HWSET_MAX_SIZE, GFP_KERNEL);
20839e9c9c24SLarry Finger 	if (!hwinfo)
2084f1d2b4d3SLarry Finger 		return;
2085f1d2b4d3SLarry Finger 
2086f1d2b4d3SLarry Finger 	if (rtl_get_hwinfo(hw, rtlpriv, HWSET_MAX_SIZE, hwinfo, params))
2087f1d2b4d3SLarry Finger 		goto exit;
2088f1d2b4d3SLarry Finger 
2089f1d2b4d3SLarry Finger 	/*parse xtal*/
2090f1d2b4d3SLarry Finger 	rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8723BE];
2091f1d2b4d3SLarry Finger 	if (rtlefuse->crystalcap == 0xFF)
2092f1d2b4d3SLarry Finger 		rtlefuse->crystalcap = 0x20;
2093f1d2b4d3SLarry Finger 
2094f1d2b4d3SLarry Finger 	_rtl8723be_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag,
2095f1d2b4d3SLarry Finger 					       hwinfo);
2096f1d2b4d3SLarry Finger 
2097881d53abSPing-Ke Shih 	rtl8723be_read_bt_coexist_info_from_hwpg(hw,
2098881d53abSPing-Ke Shih 						 rtlefuse->autoload_failflag,
2099881d53abSPing-Ke Shih 						 hwinfo);
2100881d53abSPing-Ke Shih 
2101e6dd230aSLarry Finger 	if (rtlpriv->btcoexist.btc_info.btcoexist == 1)
2102881d53abSPing-Ke Shih 		rtlefuse->board_type |= BIT(2); /* ODM_BOARD_BT */
2103881d53abSPing-Ke Shih 
21047fe1fe75SPing-Ke Shih 	rtlhal->board_type = rtlefuse->board_type;
21057fe1fe75SPing-Ke Shih 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2106f1d2b4d3SLarry Finger 		"board_type = 0x%x\n", rtlefuse->board_type);
2107f1d2b4d3SLarry Finger 
2108f1d2b4d3SLarry Finger 	rtlhal->package_type = _rtl8723be_read_package_type(hw);
2109f1d2b4d3SLarry Finger 
2110f1d2b4d3SLarry Finger 	/* set channel plan from efuse */
211153ac7935SJérémy Lefaure 	rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
2112f1d2b4d3SLarry Finger 
2113f1d2b4d3SLarry Finger 	if (rtlhal->oem_id == RT_CID_DEFAULT) {
2114f1d2b4d3SLarry Finger 		/* Does this one have a Toshiba SMID from group 1? */
2115f1d2b4d3SLarry Finger 		for (i = 0; i < ARRAY_SIZE(toshiba_smid1); i++) {
2116f1d2b4d3SLarry Finger 			if (rtlefuse->eeprom_smid == toshiba_smid1[i]) {
2117f1d2b4d3SLarry Finger 				is_toshiba_smid1 = true;
211853ac7935SJérémy Lefaure 				break;
2119f1d2b4d3SLarry Finger 			}
2120f1d2b4d3SLarry Finger 		}
2121f1d2b4d3SLarry Finger 		/* Does this one have a Toshiba SMID from group 2? */
2122f1d2b4d3SLarry Finger 		for (i = 0; i < ARRAY_SIZE(toshiba_smid2); i++) {
2123f1d2b4d3SLarry Finger 			if (rtlefuse->eeprom_smid == toshiba_smid2[i]) {
2124f1d2b4d3SLarry Finger 				is_toshiba_smid2 = true;
212553ac7935SJérémy Lefaure 				break;
2126f1d2b4d3SLarry Finger 			}
2127f1d2b4d3SLarry Finger 		}
2128f1d2b4d3SLarry Finger 		/* Does this one have a Samsung SMID? */
2129f1d2b4d3SLarry Finger 		for (i = 0; i < ARRAY_SIZE(samsung_smid); i++) {
2130f1d2b4d3SLarry Finger 			if (rtlefuse->eeprom_smid == samsung_smid[i]) {
2131f1d2b4d3SLarry Finger 				is_samsung_smid = true;
213253ac7935SJérémy Lefaure 				break;
2133f1d2b4d3SLarry Finger 			}
2134f1d2b4d3SLarry Finger 		}
2135f1d2b4d3SLarry Finger 		/* Does this one have a Lenovo SMID? */
2136f1d2b4d3SLarry Finger 		for (i = 0; i < ARRAY_SIZE(lenovo_smid); i++) {
2137f1d2b4d3SLarry Finger 			if (rtlefuse->eeprom_smid == lenovo_smid[i]) {
2138f1d2b4d3SLarry Finger 				is_lenovo_smid = true;
2139f1d2b4d3SLarry Finger 				break;
2140f1d2b4d3SLarry Finger 			}
2141f1d2b4d3SLarry Finger 		}
2142f1d2b4d3SLarry Finger 		switch (rtlefuse->eeprom_oemid) {
2143f1d2b4d3SLarry Finger 		case EEPROM_CID_DEFAULT:
2144f1d2b4d3SLarry Finger 			if (rtlefuse->eeprom_did == 0x8176) {
2145f1d2b4d3SLarry Finger 				if (rtlefuse->eeprom_svid == 0x10EC &&
2146f1d2b4d3SLarry Finger 				    is_toshiba_smid1) {
2147f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_TOSHIBA;
2148f1d2b4d3SLarry Finger 				} else if (rtlefuse->eeprom_svid == 0x1025) {
2149f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_ACER;
2150f1d2b4d3SLarry Finger 				} else if (rtlefuse->eeprom_svid == 0x10EC &&
2151f1d2b4d3SLarry Finger 					   is_samsung_smid) {
2152f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_SAMSUNG;
2153f1d2b4d3SLarry Finger 				} else if (rtlefuse->eeprom_svid == 0x10EC &&
2154f1d2b4d3SLarry Finger 					   is_lenovo_smid) {
2155f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_LENOVO;
2156f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x10EC &&
2157f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x8197) ||
2158f1d2b4d3SLarry Finger 					   (rtlefuse->eeprom_svid == 0x10EC &&
2159f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x9196)) {
2160f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_CLEVO;
2161f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x1028 &&
2162f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x8194) ||
2163f1d2b4d3SLarry Finger 					   (rtlefuse->eeprom_svid == 0x1028 &&
2164f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x8198) ||
2165f1d2b4d3SLarry Finger 					   (rtlefuse->eeprom_svid == 0x1028 &&
2166f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x9197) ||
2167f1d2b4d3SLarry Finger 					   (rtlefuse->eeprom_svid == 0x1028 &&
2168f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x9198)) {
2169f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_DELL;
2170f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x103C &&
2171f1d2b4d3SLarry Finger 					    rtlefuse->eeprom_smid == 0x1629)) {
2172f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_HP;
2173f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x1A32 &&
2174f1d2b4d3SLarry Finger 					   rtlefuse->eeprom_smid == 0x2315)) {
2175f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_QMI;
2176f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x10EC &&
2177f1d2b4d3SLarry Finger 					   rtlefuse->eeprom_smid == 0x8203)) {
2178f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_PRONETS;
2179f1d2b4d3SLarry Finger 				} else if ((rtlefuse->eeprom_svid == 0x1043 &&
2180f1d2b4d3SLarry Finger 					   rtlefuse->eeprom_smid == 0x84B5)) {
2181f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_EDIMAX_ASUS;
2182f1d2b4d3SLarry Finger 				} else {
2183f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_DEFAULT;
2184f1d2b4d3SLarry Finger 				}
2185f1d2b4d3SLarry Finger 			} else if (rtlefuse->eeprom_did == 0x8178) {
2186f1d2b4d3SLarry Finger 				if (rtlefuse->eeprom_svid == 0x10EC &&
2187f1d2b4d3SLarry Finger 				    is_toshiba_smid2)
2188f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_TOSHIBA;
2189f1d2b4d3SLarry Finger 				else if (rtlefuse->eeprom_svid == 0x1025)
2190f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_ACER;
2191f1d2b4d3SLarry Finger 				else if ((rtlefuse->eeprom_svid == 0x10EC &&
2192f1d2b4d3SLarry Finger 					  rtlefuse->eeprom_smid == 0x8186))
2193f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_819X_PRONETS;
2194f1d2b4d3SLarry Finger 				else if ((rtlefuse->eeprom_svid == 0x1043 &&
2195f1d2b4d3SLarry Finger 					  rtlefuse->eeprom_smid == 0x84B6))
2196f1d2b4d3SLarry Finger 					rtlhal->oem_id =
2197f1d2b4d3SLarry Finger 							RT_CID_819X_EDIMAX_ASUS;
2198f1d2b4d3SLarry Finger 				else
2199f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_DEFAULT;
2200f1d2b4d3SLarry Finger 			} else {
2201f1d2b4d3SLarry Finger 					rtlhal->oem_id = RT_CID_DEFAULT;
2202f1d2b4d3SLarry Finger 			}
2203f1d2b4d3SLarry Finger 			break;
2204f1d2b4d3SLarry Finger 		case EEPROM_CID_TOSHIBA:
2205f1d2b4d3SLarry Finger 			rtlhal->oem_id = RT_CID_TOSHIBA;
2206f1d2b4d3SLarry Finger 			break;
2207f1d2b4d3SLarry Finger 		case EEPROM_CID_CCX:
2208f1d2b4d3SLarry Finger 			rtlhal->oem_id = RT_CID_CCX;
2209f1d2b4d3SLarry Finger 			break;
2210f1d2b4d3SLarry Finger 		case EEPROM_CID_QMI:
2211f1d2b4d3SLarry Finger 			rtlhal->oem_id = RT_CID_819X_QMI;
2212f1d2b4d3SLarry Finger 			break;
2213f1d2b4d3SLarry Finger 		case EEPROM_CID_WHQL:
2214f1d2b4d3SLarry Finger 			break;
2215f1d2b4d3SLarry Finger 		default:
22169e9c9c24SLarry Finger 			rtlhal->oem_id = RT_CID_DEFAULT;
22179e9c9c24SLarry Finger 			break;
2218f1d2b4d3SLarry Finger 		}
2219f1d2b4d3SLarry Finger 	}
2220f1d2b4d3SLarry Finger exit:
2221f1d2b4d3SLarry Finger 	kfree(hwinfo);
2222f1d2b4d3SLarry Finger }
2223f1d2b4d3SLarry Finger 
_rtl8723be_hal_customized_behavior(struct ieee80211_hw * hw)2224f1d2b4d3SLarry Finger static void _rtl8723be_hal_customized_behavior(struct ieee80211_hw *hw)
2225d5efe153SLarry Finger {
2226f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2227f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2228d5efe153SLarry Finger 
2229f1d2b4d3SLarry Finger 	rtlpriv->ledctl.led_opendrain = true;
2230f1d2b4d3SLarry Finger 	switch (rtlhal->oem_id) {
2231f1d2b4d3SLarry Finger 	case RT_CID_819X_HP:
2232f1d2b4d3SLarry Finger 		rtlpriv->ledctl.led_opendrain = true;
2233f1d2b4d3SLarry Finger 		break;
2234f1d2b4d3SLarry Finger 	case RT_CID_819X_LENOVO:
2235f1d2b4d3SLarry Finger 	case RT_CID_DEFAULT:
2236f1d2b4d3SLarry Finger 	case RT_CID_TOSHIBA:
2237f1d2b4d3SLarry Finger 	case RT_CID_CCX:
2238f1d2b4d3SLarry Finger 	case RT_CID_819X_ACER:
2239e6dd230aSLarry Finger 	case RT_CID_WHQL:
2240f1d2b4d3SLarry Finger 	default:
2241f1d2b4d3SLarry Finger 		break;
2242f1d2b4d3SLarry Finger 	}
2243f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
2244f1d2b4d3SLarry Finger 		"RT Customized ID: 0x%02X\n", rtlhal->oem_id);
2245f1d2b4d3SLarry Finger }
2246f1d2b4d3SLarry Finger 
rtl8723be_read_eeprom_info(struct ieee80211_hw * hw)2247f1d2b4d3SLarry Finger void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw)
2248f1d2b4d3SLarry Finger {
2249f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2250f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2251f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
2252f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2253f1d2b4d3SLarry Finger 	u8 tmp_u1b;
2254f1d2b4d3SLarry Finger 
2255f1d2b4d3SLarry Finger 	rtlhal->version = _rtl8723be_read_chip_version(hw);
2256f1d2b4d3SLarry Finger 	if (get_rf_type(rtlphy) == RF_1T1R)
2257e6dd230aSLarry Finger 		rtlpriv->dm.rfpath_rxenable[0] = true;
2258f1d2b4d3SLarry Finger 	else
2259f1d2b4d3SLarry Finger 		rtlpriv->dm.rfpath_rxenable[0] =
2260f1d2b4d3SLarry Finger 		    rtlpriv->dm.rfpath_rxenable[1] = true;
2261e6dd230aSLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
2262f1d2b4d3SLarry Finger 		rtlhal->version);
2263f1d2b4d3SLarry Finger 	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
2264e6dd230aSLarry Finger 	if (tmp_u1b & BIT(4)) {
2265f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
2266f1d2b4d3SLarry Finger 		rtlefuse->epromtype = EEPROM_93C46;
2267f1d2b4d3SLarry Finger 	} else {
2268e6dd230aSLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
2269f1d2b4d3SLarry Finger 		rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
2270f1d2b4d3SLarry Finger 	}
2271f1d2b4d3SLarry Finger 	if (tmp_u1b & BIT(5)) {
22724e2b4378SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
2273f1d2b4d3SLarry Finger 		rtlefuse->autoload_failflag = false;
2274f1d2b4d3SLarry Finger 		_rtl8723be_read_adapter_info(hw, false);
2275f1d2b4d3SLarry Finger 	} else {
2276f1d2b4d3SLarry Finger 		pr_err("Autoload ERR!!\n");
2277f1d2b4d3SLarry Finger 	}
2278f1d2b4d3SLarry Finger 	_rtl8723be_hal_customized_behavior(hw);
2279f1d2b4d3SLarry Finger }
2280f1d2b4d3SLarry Finger 
_rtl8723be_mrate_idx_to_arfr_id(struct ieee80211_hw * hw,u8 rate_index)2281f1d2b4d3SLarry Finger static u8 _rtl8723be_mrate_idx_to_arfr_id(struct ieee80211_hw *hw,
2282f1d2b4d3SLarry Finger 					  u8 rate_index)
2283f1d2b4d3SLarry Finger {
2284f1d2b4d3SLarry Finger 	u8 ret = 0;
2285f1d2b4d3SLarry Finger 	switch (rate_index) {
2286f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_NGB:
2287f1d2b4d3SLarry Finger 		ret = 1;
2288f1d2b4d3SLarry Finger 		break;
2289f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_N:
2290f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_NG:
2291f1d2b4d3SLarry Finger 		ret = 5;
2292f1d2b4d3SLarry Finger 		break;
2293f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_NB:
2294f1d2b4d3SLarry Finger 		ret = 3;
2295f1d2b4d3SLarry Finger 		break;
2296f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_GB:
2297f1d2b4d3SLarry Finger 		ret = 6;
2298f1d2b4d3SLarry Finger 		break;
2299f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_G:
2300f1d2b4d3SLarry Finger 		ret = 7;
2301f1d2b4d3SLarry Finger 		break;
2302f1d2b4d3SLarry Finger 	case RATR_INX_WIRELESS_B:
2303f1d2b4d3SLarry Finger 		ret = 8;
2304f1d2b4d3SLarry Finger 		break;
2305f1d2b4d3SLarry Finger 	default:
2306f1d2b4d3SLarry Finger 		ret = 0;
2307f1d2b4d3SLarry Finger 		break;
2308f1d2b4d3SLarry Finger 	}
2309f1d2b4d3SLarry Finger 	return ret;
23101d22b177SPing-Ke Shih }
2311f1d2b4d3SLarry Finger 
rtl8723be_update_hal_rate_mask(struct ieee80211_hw * hw,struct ieee80211_sta * sta,u8 rssi_level,bool update_bw)2312f1d2b4d3SLarry Finger static void rtl8723be_update_hal_rate_mask(struct ieee80211_hw *hw,
2313f1d2b4d3SLarry Finger 					   struct ieee80211_sta *sta,
2314f1d2b4d3SLarry Finger 					   u8 rssi_level, bool update_bw)
2315f1d2b4d3SLarry Finger {
2316f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2317f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
2318*046d2e7cSSriram R 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2319f1d2b4d3SLarry Finger 	struct rtl_sta_info *sta_entry = NULL;
2320*046d2e7cSSriram R 	u32 ratr_bitmap;
2321f1d2b4d3SLarry Finger 	u8 ratr_index;
2322*046d2e7cSSriram R 	u8 curtxbw_40mhz = (sta->deflink.ht_cap.cap &
2323f1d2b4d3SLarry Finger 			      IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
2324f1d2b4d3SLarry Finger 	u8 curshortgi_40mhz = (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
2325f1d2b4d3SLarry Finger 				1 : 0;
2326f1d2b4d3SLarry Finger 	u8 curshortgi_20mhz = (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
2327f1d2b4d3SLarry Finger 				1 : 0;
2328f1d2b4d3SLarry Finger 	enum wireless_mode wirelessmode = 0;
2329f1d2b4d3SLarry Finger 	bool shortgi = false;
2330f1d2b4d3SLarry Finger 	u8 rate_mask[7];
2331f1d2b4d3SLarry Finger 	u8 macid = 0;
2332f1d2b4d3SLarry Finger 
2333f1d2b4d3SLarry Finger 	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
2334f1d2b4d3SLarry Finger 	wirelessmode = sta_entry->wireless_mode;
2335f1d2b4d3SLarry Finger 	if (mac->opmode == NL80211_IFTYPE_STATION ||
2336f1d2b4d3SLarry Finger 	    mac->opmode == NL80211_IFTYPE_MESH_POINT)
2337f1d2b4d3SLarry Finger 		curtxbw_40mhz = mac->bw_40;
2338*046d2e7cSSriram R 	else if (mac->opmode == NL80211_IFTYPE_AP ||
2339f1d2b4d3SLarry Finger 		 mac->opmode == NL80211_IFTYPE_ADHOC)
2340f1d2b4d3SLarry Finger 		macid = sta->aid + 1;
2341f1d2b4d3SLarry Finger 
2342f1d2b4d3SLarry Finger 	ratr_bitmap = sta->deflink.supp_rates[0];
2343*046d2e7cSSriram R 
2344*046d2e7cSSriram R 	if (mac->opmode == NL80211_IFTYPE_ADHOC)
2345f1d2b4d3SLarry Finger 		ratr_bitmap = 0xfff;
2346f1d2b4d3SLarry Finger 
2347f1d2b4d3SLarry Finger 	ratr_bitmap |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20 |
2348f1d2b4d3SLarry Finger 			sta->deflink.ht_cap.mcs.rx_mask[0] << 12);
2349f1d2b4d3SLarry Finger 	switch (wirelessmode) {
2350f1d2b4d3SLarry Finger 	case WIRELESS_MODE_B:
2351f1d2b4d3SLarry Finger 		ratr_index = RATR_INX_WIRELESS_B;
2352f1d2b4d3SLarry Finger 		if (ratr_bitmap & 0x0000000c)
2353f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x0000000d;
2354f1d2b4d3SLarry Finger 		else
2355f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x0000000f;
2356f1d2b4d3SLarry Finger 		break;
2357f1d2b4d3SLarry Finger 	case WIRELESS_MODE_G:
2358f1d2b4d3SLarry Finger 		ratr_index = RATR_INX_WIRELESS_GB;
2359f1d2b4d3SLarry Finger 
2360f1d2b4d3SLarry Finger 		if (rssi_level == 1)
2361f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x00000f00;
2362f1d2b4d3SLarry Finger 		else if (rssi_level == 2)
2363f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x00000ff0;
2364f1d2b4d3SLarry Finger 		else
2365f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x00000ff5;
2366f1d2b4d3SLarry Finger 		break;
2367f1d2b4d3SLarry Finger 	case WIRELESS_MODE_N_24G:
2368f1d2b4d3SLarry Finger 	case WIRELESS_MODE_N_5G:
2369f1d2b4d3SLarry Finger 		ratr_index = RATR_INX_WIRELESS_NGB;
2370f1d2b4d3SLarry Finger 		if (rtlphy->rf_type == RF_1T1R) {
2371f1d2b4d3SLarry Finger 			if (curtxbw_40mhz) {
2372f1d2b4d3SLarry Finger 				if (rssi_level == 1)
2373f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000f0000;
2374f1d2b4d3SLarry Finger 				else if (rssi_level == 2)
2375f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000ff000;
2376f1d2b4d3SLarry Finger 				else
2377f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000ff015;
2378f1d2b4d3SLarry Finger 			} else {
2379f1d2b4d3SLarry Finger 				if (rssi_level == 1)
2380f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000f0000;
2381f1d2b4d3SLarry Finger 				else if (rssi_level == 2)
2382f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000ff000;
2383f1d2b4d3SLarry Finger 				else
2384f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x000ff005;
2385f1d2b4d3SLarry Finger 			}
2386f1d2b4d3SLarry Finger 		} else {
2387f1d2b4d3SLarry Finger 			if (curtxbw_40mhz) {
2388f1d2b4d3SLarry Finger 				if (rssi_level == 1)
2389f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8f0000;
2390f1d2b4d3SLarry Finger 				else if (rssi_level == 2)
2391f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8ff000;
2392f1d2b4d3SLarry Finger 				else
2393f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8ff015;
2394f1d2b4d3SLarry Finger 			} else {
2395f1d2b4d3SLarry Finger 				if (rssi_level == 1)
2396f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8f0000;
2397f1d2b4d3SLarry Finger 				else if (rssi_level == 2)
2398f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8ff000;
2399f1d2b4d3SLarry Finger 				else
2400f1d2b4d3SLarry Finger 					ratr_bitmap &= 0x0f8ff005;
2401f1d2b4d3SLarry Finger 			}
2402f1d2b4d3SLarry Finger 		}
2403f1d2b4d3SLarry Finger 		if ((curtxbw_40mhz && curshortgi_40mhz) ||
2404f1d2b4d3SLarry Finger 		    (!curtxbw_40mhz && curshortgi_20mhz)) {
2405f1d2b4d3SLarry Finger 			if (macid == 0)
2406f1d2b4d3SLarry Finger 				shortgi = true;
2407f1d2b4d3SLarry Finger 			else if (macid == 1)
2408f1d2b4d3SLarry Finger 				shortgi = false;
2409f1d2b4d3SLarry Finger 		}
2410f1d2b4d3SLarry Finger 		break;
2411f1d2b4d3SLarry Finger 	default:
2412f1d2b4d3SLarry Finger 		ratr_index = RATR_INX_WIRELESS_NGB;
2413f1d2b4d3SLarry Finger 
2414f1d2b4d3SLarry Finger 		if (rtlphy->rf_type == RF_1T2R)
2415f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x000ff0ff;
2416f1d2b4d3SLarry Finger 		else
2417f1d2b4d3SLarry Finger 			ratr_bitmap &= 0x0f0ff0ff;
2418f1d2b4d3SLarry Finger 		break;
2419e6dd230aSLarry Finger 	}
2420f1d2b4d3SLarry Finger 
2421f1d2b4d3SLarry Finger 	sta_entry->ratr_index = ratr_index;
2422f1d2b4d3SLarry Finger 
2423f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG,
2424f1d2b4d3SLarry Finger 		"ratr_bitmap :%x\n", ratr_bitmap);
2425f1d2b4d3SLarry Finger 	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
24261d22b177SPing-Ke Shih 				       (ratr_index << 28);
2427f1d2b4d3SLarry Finger 	rate_mask[0] = macid;
2428f1d2b4d3SLarry Finger 	rate_mask[1] = _rtl8723be_mrate_idx_to_arfr_id(hw, ratr_index) |
2429f1d2b4d3SLarry Finger 						      (shortgi ? 0x80 : 0x00);
2430f1d2b4d3SLarry Finger 	rate_mask[2] = curtxbw_40mhz | ((!update_bw) << 3);
2431f1d2b4d3SLarry Finger 
2432f1d2b4d3SLarry Finger 	rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff);
2433e6dd230aSLarry Finger 	rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8);
2434f1d2b4d3SLarry Finger 	rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16);
2435f1d2b4d3SLarry Finger 	rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24);
2436f1d2b4d3SLarry Finger 
2437f1d2b4d3SLarry Finger 	rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG,
2438f1d2b4d3SLarry Finger 		"Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n",
2439f1d2b4d3SLarry Finger 		ratr_index, ratr_bitmap,
2440f1d2b4d3SLarry Finger 		rate_mask[0], rate_mask[1],
2441f1d2b4d3SLarry Finger 		rate_mask[2], rate_mask[3],
2442f1d2b4d3SLarry Finger 		rate_mask[4], rate_mask[5],
2443f1d2b4d3SLarry Finger 		rate_mask[6]);
2444f1d2b4d3SLarry Finger 	rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RA_MASK, 7, rate_mask);
2445f1d2b4d3SLarry Finger 	_rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0);
24461d22b177SPing-Ke Shih }
2447f1d2b4d3SLarry Finger 
rtl8723be_update_hal_rate_tbl(struct ieee80211_hw * hw,struct ieee80211_sta * sta,u8 rssi_level,bool update_bw)2448f1d2b4d3SLarry Finger void rtl8723be_update_hal_rate_tbl(struct ieee80211_hw *hw,
2449f1d2b4d3SLarry Finger 				   struct ieee80211_sta *sta,
24501d22b177SPing-Ke Shih 				   u8 rssi_level, bool update_bw)
2451f1d2b4d3SLarry Finger {
2452f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2453f1d2b4d3SLarry Finger 	if (rtlpriv->dm.useramask)
2454f1d2b4d3SLarry Finger 		rtl8723be_update_hal_rate_mask(hw, sta, rssi_level, update_bw);
2455f1d2b4d3SLarry Finger }
2456f1d2b4d3SLarry Finger 
rtl8723be_update_channel_access_setting(struct ieee80211_hw * hw)2457f1d2b4d3SLarry Finger void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw)
2458f1d2b4d3SLarry Finger {
2459f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2460f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2461f1d2b4d3SLarry Finger 	u16 sifs_timer;
2462f1d2b4d3SLarry Finger 
2463f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time);
2464f1d2b4d3SLarry Finger 	if (!mac->ht_enable)
2465f1d2b4d3SLarry Finger 		sifs_timer = 0x0a0a;
2466f1d2b4d3SLarry Finger 	else
2467f1d2b4d3SLarry Finger 		sifs_timer = 0x0e0e;
2468f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
2469f1d2b4d3SLarry Finger }
2470f1d2b4d3SLarry Finger 
rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw * hw,u8 * valid)2471f1d2b4d3SLarry Finger bool rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
247276d7b12cSChristos Gkekas {
2473f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2474f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2475f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
2476f1d2b4d3SLarry Finger 	enum rf_pwrstate e_rfpowerstate_toset;
2477f1d2b4d3SLarry Finger 	u8 u1tmp;
2478f1d2b4d3SLarry Finger 	bool b_actuallyset = false;
2479f1d2b4d3SLarry Finger 
2480f1d2b4d3SLarry Finger 	if (rtlpriv->rtlhal.being_init_adapter)
2481f1d2b4d3SLarry Finger 		return false;
2482f1d2b4d3SLarry Finger 
2483f1d2b4d3SLarry Finger 	if (ppsc->swrf_processing)
2484f1d2b4d3SLarry Finger 		return false;
2485f1d2b4d3SLarry Finger 
2486f1d2b4d3SLarry Finger 	spin_lock(&rtlpriv->locks.rf_ps_lock);
2487f1d2b4d3SLarry Finger 	if (ppsc->rfchange_inprogress) {
2488f1d2b4d3SLarry Finger 		spin_unlock(&rtlpriv->locks.rf_ps_lock);
2489f1d2b4d3SLarry Finger 		return false;
2490f1d2b4d3SLarry Finger 	} else {
2491f1d2b4d3SLarry Finger 		ppsc->rfchange_inprogress = true;
2492f1d2b4d3SLarry Finger 		spin_unlock(&rtlpriv->locks.rf_ps_lock);
2493f1d2b4d3SLarry Finger 	}
2494f1d2b4d3SLarry Finger 
2495f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2,
2496f1d2b4d3SLarry Finger 		       rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2) & ~(BIT(1)));
2497f1d2b4d3SLarry Finger 
2498f1d2b4d3SLarry Finger 	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2);
2499f1d2b4d3SLarry Finger 
2500f1d2b4d3SLarry Finger 	if (rtlphy->polarity_ctl)
2501f1d2b4d3SLarry Finger 		e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON;
2502e6dd230aSLarry Finger 	else
2503f1d2b4d3SLarry Finger 		e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF;
2504f1d2b4d3SLarry Finger 
2505f1d2b4d3SLarry Finger 	if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
2506f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2507f1d2b4d3SLarry Finger 			"GPIOChangeRF  - HW Radio ON, RF ON\n");
2508f1d2b4d3SLarry Finger 
2509e6dd230aSLarry Finger 		e_rfpowerstate_toset = ERFON;
2510f1d2b4d3SLarry Finger 		ppsc->hwradiooff = false;
2511f1d2b4d3SLarry Finger 		b_actuallyset = true;
2512f1d2b4d3SLarry Finger 	} else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) {
2513f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2514f1d2b4d3SLarry Finger 			"GPIOChangeRF  - HW Radio OFF, RF OFF\n");
2515f1d2b4d3SLarry Finger 
2516f1d2b4d3SLarry Finger 		e_rfpowerstate_toset = ERFOFF;
2517f1d2b4d3SLarry Finger 		ppsc->hwradiooff = true;
2518f1d2b4d3SLarry Finger 		b_actuallyset = true;
2519f1d2b4d3SLarry Finger 	}
2520f1d2b4d3SLarry Finger 
2521f1d2b4d3SLarry Finger 	if (b_actuallyset) {
2522f1d2b4d3SLarry Finger 		spin_lock(&rtlpriv->locks.rf_ps_lock);
2523f1d2b4d3SLarry Finger 		ppsc->rfchange_inprogress = false;
2524f1d2b4d3SLarry Finger 		spin_unlock(&rtlpriv->locks.rf_ps_lock);
2525f1d2b4d3SLarry Finger 	} else {
2526f1d2b4d3SLarry Finger 		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
2527f1d2b4d3SLarry Finger 			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
2528f1d2b4d3SLarry Finger 
2529f1d2b4d3SLarry Finger 		spin_lock(&rtlpriv->locks.rf_ps_lock);
2530f1d2b4d3SLarry Finger 		ppsc->rfchange_inprogress = false;
2531f1d2b4d3SLarry Finger 		spin_unlock(&rtlpriv->locks.rf_ps_lock);
2532f1d2b4d3SLarry Finger 	}
2533f1d2b4d3SLarry Finger 
2534f1d2b4d3SLarry Finger 	*valid = 1;
2535f1d2b4d3SLarry Finger 	return !ppsc->hwradiooff;
2536f1d2b4d3SLarry Finger 
2537f1d2b4d3SLarry Finger }
2538f1d2b4d3SLarry Finger 
rtl8723be_set_key(struct ieee80211_hw * hw,u32 key_index,u8 * p_macaddr,bool is_group,u8 enc_algo,bool is_wepkey,bool clear_all)2539f1d2b4d3SLarry Finger void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index,
2540f1d2b4d3SLarry Finger 		       u8 *p_macaddr, bool is_group, u8 enc_algo,
2541f1d2b4d3SLarry Finger 		       bool is_wepkey, bool clear_all)
2542f1d2b4d3SLarry Finger {
2543f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2544f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2545f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2546f1d2b4d3SLarry Finger 	u8 *macaddr = p_macaddr;
2547f1d2b4d3SLarry Finger 	u32 entry_id = 0;
2548f1d2b4d3SLarry Finger 	bool is_pairwise = false;
2549f1d2b4d3SLarry Finger 
2550f1d2b4d3SLarry Finger 	static u8 cam_const_addr[4][6] = {
2551f1d2b4d3SLarry Finger 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
2552f1d2b4d3SLarry Finger 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
2553f1d2b4d3SLarry Finger 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
2554f1d2b4d3SLarry Finger 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
2555f1d2b4d3SLarry Finger 	};
2556f1d2b4d3SLarry Finger 	static u8 cam_const_broad[] = {
2557f1d2b4d3SLarry Finger 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2558f1d2b4d3SLarry Finger 	};
2559f1d2b4d3SLarry Finger 
2560f1d2b4d3SLarry Finger 	if (clear_all) {
2561e6dd230aSLarry Finger 		u8 idx = 0;
2562f1d2b4d3SLarry Finger 		u8 cam_offset = 0;
2563f1d2b4d3SLarry Finger 		u8 clear_number = 5;
2564f1d2b4d3SLarry Finger 
2565f1d2b4d3SLarry Finger 		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
2566f1d2b4d3SLarry Finger 
2567f1d2b4d3SLarry Finger 		for (idx = 0; idx < clear_number; idx++) {
2568f1d2b4d3SLarry Finger 			rtl_cam_mark_invalid(hw, cam_offset + idx);
2569f1d2b4d3SLarry Finger 			rtl_cam_empty_entry(hw, cam_offset + idx);
2570f1d2b4d3SLarry Finger 
2571f1d2b4d3SLarry Finger 			if (idx < 5) {
2572f1d2b4d3SLarry Finger 				memset(rtlpriv->sec.key_buf[idx], 0,
2573f1d2b4d3SLarry Finger 				       MAX_KEY_LEN);
2574f1d2b4d3SLarry Finger 				rtlpriv->sec.key_len[idx] = 0;
2575f1d2b4d3SLarry Finger 			}
2576f1d2b4d3SLarry Finger 		}
2577f1d2b4d3SLarry Finger 
2578f1d2b4d3SLarry Finger 	} else {
2579f1d2b4d3SLarry Finger 		switch (enc_algo) {
2580f1d2b4d3SLarry Finger 		case WEP40_ENCRYPTION:
2581f1d2b4d3SLarry Finger 			enc_algo = CAM_WEP40;
2582f1d2b4d3SLarry Finger 			break;
2583f1d2b4d3SLarry Finger 		case WEP104_ENCRYPTION:
2584f1d2b4d3SLarry Finger 			enc_algo = CAM_WEP104;
2585f1d2b4d3SLarry Finger 			break;
2586f1d2b4d3SLarry Finger 		case TKIP_ENCRYPTION:
2587f1d2b4d3SLarry Finger 			enc_algo = CAM_TKIP;
2588f1d2b4d3SLarry Finger 			break;
2589e6dd230aSLarry Finger 		case AESCCMP_ENCRYPTION:
2590ad574889SJoe Perches 			enc_algo = CAM_AES;
2591f1d2b4d3SLarry Finger 			break;
2592f1d2b4d3SLarry Finger 		default:
2593f1d2b4d3SLarry Finger 			rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
2594f1d2b4d3SLarry Finger 				"switch case %#x not processed\n", enc_algo);
2595f1d2b4d3SLarry Finger 			enc_algo = CAM_TKIP;
2596f1d2b4d3SLarry Finger 			break;
2597f1d2b4d3SLarry Finger 		}
2598f1d2b4d3SLarry Finger 
2599f1d2b4d3SLarry Finger 		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
2600f1d2b4d3SLarry Finger 			macaddr = cam_const_addr[key_index];
2601f1d2b4d3SLarry Finger 			entry_id = key_index;
2602f1d2b4d3SLarry Finger 		} else {
2603f1d2b4d3SLarry Finger 			if (is_group) {
2604f1d2b4d3SLarry Finger 				macaddr = cam_const_broad;
2605f1d2b4d3SLarry Finger 				entry_id = key_index;
2606f1d2b4d3SLarry Finger 			} else {
26074e2b4378SLarry Finger 				if (mac->opmode == NL80211_IFTYPE_AP) {
2608f1d2b4d3SLarry Finger 					entry_id = rtl_cam_get_free_entry(hw,
2609f1d2b4d3SLarry Finger 								p_macaddr);
2610f1d2b4d3SLarry Finger 					if (entry_id >=  TOTAL_CAM_ENTRY) {
2611f1d2b4d3SLarry Finger 						pr_err("Can not find free hw security cam entry\n");
2612f1d2b4d3SLarry Finger 						return;
2613f1d2b4d3SLarry Finger 					}
2614f1d2b4d3SLarry Finger 				} else {
2615f1d2b4d3SLarry Finger 					entry_id = CAM_PAIRWISE_KEY_POSITION;
2616f1d2b4d3SLarry Finger 				}
2617f1d2b4d3SLarry Finger 
2618f1d2b4d3SLarry Finger 				key_index = PAIRWISE_KEYIDX;
2619f1d2b4d3SLarry Finger 				is_pairwise = true;
2620e6dd230aSLarry Finger 			}
2621f1d2b4d3SLarry Finger 		}
2622f1d2b4d3SLarry Finger 
2623f1d2b4d3SLarry Finger 		if (rtlpriv->sec.key_len[key_index] == 0) {
2624f1d2b4d3SLarry Finger 			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
2625f1d2b4d3SLarry Finger 				"delete one entry, entry_id is %d\n",
2626f1d2b4d3SLarry Finger 				entry_id);
2627e6dd230aSLarry Finger 			if (mac->opmode == NL80211_IFTYPE_AP)
2628f1d2b4d3SLarry Finger 				rtl_cam_del_entry(hw, p_macaddr);
2629f1d2b4d3SLarry Finger 			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
2630e6dd230aSLarry Finger 		} else {
26316b9e6f62SColin Ian King 			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
2632f1d2b4d3SLarry Finger 				"add one entry\n");
2633f1d2b4d3SLarry Finger 			if (is_pairwise) {
2634f1d2b4d3SLarry Finger 				rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
2635f1d2b4d3SLarry Finger 					"set Pairwise key\n");
2636f1d2b4d3SLarry Finger 
2637f1d2b4d3SLarry Finger 				rtl_cam_add_one_entry(hw, macaddr, key_index,
2638e6dd230aSLarry Finger 					       entry_id, enc_algo,
2639f1d2b4d3SLarry Finger 					       CAM_CONFIG_NO_USEDK,
2640f1d2b4d3SLarry Finger 					       rtlpriv->sec.key_buf[key_index]);
2641f1d2b4d3SLarry Finger 			} else {
2642f1d2b4d3SLarry Finger 				rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
2643f1d2b4d3SLarry Finger 					"set group key\n");
2644f1d2b4d3SLarry Finger 
2645f1d2b4d3SLarry Finger 				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
2646f1d2b4d3SLarry Finger 					rtl_cam_add_one_entry(hw,
2647f1d2b4d3SLarry Finger 						rtlefuse->dev_addr,
2648f1d2b4d3SLarry Finger 						PAIRWISE_KEYIDX,
2649f1d2b4d3SLarry Finger 						CAM_PAIRWISE_KEY_POSITION,
2650f1d2b4d3SLarry Finger 						enc_algo,
2651f1d2b4d3SLarry Finger 						CAM_CONFIG_NO_USEDK,
2652f1d2b4d3SLarry Finger 						rtlpriv->sec.key_buf
2653f1d2b4d3SLarry Finger 						[entry_id]);
2654f1d2b4d3SLarry Finger 				}
2655f1d2b4d3SLarry Finger 
2656f1d2b4d3SLarry Finger 				rtl_cam_add_one_entry(hw, macaddr, key_index,
2657f1d2b4d3SLarry Finger 						entry_id, enc_algo,
2658f1d2b4d3SLarry Finger 						CAM_CONFIG_NO_USEDK,
2659f1d2b4d3SLarry Finger 						rtlpriv->sec.key_buf[entry_id]);
2660f1d2b4d3SLarry Finger 			}
2661f1d2b4d3SLarry Finger 		}
2662f1d2b4d3SLarry Finger 	}
2663f1d2b4d3SLarry Finger }
2664f1d2b4d3SLarry Finger 
rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw * hw,bool auto_load_fail,u8 * hwinfo)2665c18d8f50SLarry Finger void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
2666f1d2b4d3SLarry Finger 					      bool auto_load_fail, u8 *hwinfo)
2667f1d2b4d3SLarry Finger {
2668f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2669f1d2b4d3SLarry Finger 	struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
2670f1d2b4d3SLarry Finger 	u8 value;
2671f1d2b4d3SLarry Finger 	u32 tmpu_32;
2672f1d2b4d3SLarry Finger 
2673f1d2b4d3SLarry Finger 	if (!auto_load_fail) {
2674f1d2b4d3SLarry Finger 		tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL);
2675f1d2b4d3SLarry Finger 		if (tmpu_32 & BIT(18))
2676f1d2b4d3SLarry Finger 			rtlpriv->btcoexist.btc_info.btcoexist = 1;
2677f1d2b4d3SLarry Finger 		else
26780de9b5dbSPing-Ke Shih 			rtlpriv->btcoexist.btc_info.btcoexist = 0;
2679af8a41ccSPing-Ke Shih 		value = hwinfo[EEPROM_RF_BT_SETTING_8723B];
2680f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B;
2681f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1);
2682f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.single_ant_path =
2683f1d2b4d3SLarry Finger 			 (value & 0x40 ? ANT_AUX : ANT_MAIN);	/*0xc3[6]*/
2684af8a41ccSPing-Ke Shih 	} else {
2685f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.btcoexist = 0;
2686f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B;
2687c18d8f50SLarry Finger 		rtlpriv->btcoexist.btc_info.ant_num = ANT_X2;
26880ff78adeSPing-Ke Shih 		rtlpriv->btcoexist.btc_info.single_ant_path = ANT_MAIN;
2689c18d8f50SLarry Finger 	}
2690af8a41ccSPing-Ke Shih 
26910ff78adeSPing-Ke Shih 	/* override ant_num / ant_path */
26920ff78adeSPing-Ke Shih 	if (mod_params->ant_sel) {
2693af8a41ccSPing-Ke Shih 		rtlpriv->btcoexist.btc_info.ant_num =
26940ff78adeSPing-Ke Shih 			(mod_params->ant_sel == 1 ? ANT_X1 : ANT_X2);
2695f1d2b4d3SLarry Finger 
2696f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_info.single_ant_path =
2697f1d2b4d3SLarry Finger 			(mod_params->ant_sel == 1 ? ANT_AUX : ANT_MAIN);
2698f1d2b4d3SLarry Finger 	}
2699f1d2b4d3SLarry Finger }
2700f1d2b4d3SLarry Finger 
rtl8723be_bt_reg_init(struct ieee80211_hw * hw)2701f1d2b4d3SLarry Finger void rtl8723be_bt_reg_init(struct ieee80211_hw *hw)
2702f1d2b4d3SLarry Finger {
2703f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2704f1d2b4d3SLarry Finger 
2705f1d2b4d3SLarry Finger 	/* 0:Low, 1:High, 2:From Efuse. */
2706f1d2b4d3SLarry Finger 	rtlpriv->btcoexist.reg_bt_iso = 2;
2707f1d2b4d3SLarry Finger 	/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
2708f1d2b4d3SLarry Finger 	rtlpriv->btcoexist.reg_bt_sco = 3;
2709f1d2b4d3SLarry Finger 	/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
2710f1d2b4d3SLarry Finger 	rtlpriv->btcoexist.reg_bt_sco = 0;
2711f1d2b4d3SLarry Finger }
2712f1d2b4d3SLarry Finger 
rtl8723be_bt_hw_init(struct ieee80211_hw * hw)2713f1d2b4d3SLarry Finger void rtl8723be_bt_hw_init(struct ieee80211_hw *hw)
2714f1d2b4d3SLarry Finger {
2715f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
2716f1d2b4d3SLarry Finger 
2717f1d2b4d3SLarry Finger 	if (rtlpriv->cfg->ops->get_btc_status())
2718f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv);
2719f1d2b4d3SLarry Finger 
2720f1d2b4d3SLarry Finger }
2721f1d2b4d3SLarry Finger 
rtl8723be_suspend(struct ieee80211_hw * hw)2722f1d2b4d3SLarry Finger void rtl8723be_suspend(struct ieee80211_hw *hw)
2723f1d2b4d3SLarry Finger {
2724f1d2b4d3SLarry Finger }
2725 
rtl8723be_resume(struct ieee80211_hw * hw)2726 void rtl8723be_resume(struct ieee80211_hw *hw)
2727 {
2728 }
2729