xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8821cs/hal/rtl8821c/rtl8821c_dm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2016 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 /* ************************************************************
16  * Description:
17  *
18  * This file is for 8821C dynamic mechanism
19  *
20  *
21  * ************************************************************ */
22 #define _RTL8812C_DM_C_
23 
24 /* ************************************************************
25  * include files
26  * ************************************************************
27  */
28 
29 #include <drv_types.h>
30 #include <rtl8821c_hal.h>
31 
32 /* ************************************************************
33  * Global var
34  * ************************************************************ */
35 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
dm_CheckPbcGPIO(PADAPTER adapter)36 static void dm_CheckPbcGPIO(PADAPTER adapter)
37 {
38 	u8 tmp1byte;
39 	u8 bPbcPressed = _FALSE;
40 
41 	if (!adapter->registrypriv.hw_wps_pbc)
42 		return;
43 
44 #ifdef CONFIG_USB_HCI
45 	tmp1byte = rtw_read8(adapter, GPIO_IO_SEL);
46 	tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
47 	rtw_write8(adapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
48 
49 	tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
50 	rtw_write8(adapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
51 
52 	tmp1byte = rtw_read8(adapter, GPIO_IO_SEL);
53 	tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
54 	rtw_write8(adapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
55 
56 	tmp1byte = rtw_read8(adapter, GPIO_IN);
57 	if (tmp1byte == 0xff)
58 		return;
59 
60 	if (tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT)
61 		bPbcPressed = _TRUE;
62 #else
63 	tmp1byte = rtw_read8(adapter, GPIO_IN);
64 
65 	if ((tmp1byte == 0xff) || adapter->init_adpt_in_progress)
66 		return;
67 
68 	if ((tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT) == 0)
69 		bPbcPressed = _TRUE;
70 #endif
71 
72 	if (_TRUE == bPbcPressed) {
73 	/*
74 	 * Here we only set bPbcPressed to true
75 	 * After trigger PBC, the variable will be set to false
76 	 */
77 		RTW_INFO("CheckPbcGPIO - PBC is pressed\n");
78 			rtw_request_wps_pbc_event(adapter);
79 	}
80 }
81 #endif /* CONFIG_SUPPORT_HW_WPS_PBC */
82 
83 
84 #ifdef CONFIG_PCI_HCI
85 /*
86  * Description:
87  *	Perform interrupt migration dynamically to reduce CPU utilization.
88  *
89  * Assumption:
90  *	1. Do not enable migration under WIFI test.
91  */
dm_InterruptMigration(PADAPTER adapter)92 void dm_InterruptMigration(PADAPTER adapter)
93 {
94 	PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
95 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
96 	BOOLEAN bCurrentIntMt, bCurrentACIntDisable;
97 	BOOLEAN IntMtToSet = _FALSE;
98 	BOOLEAN ACIntToSet = _FALSE;
99 
100 
101 	/* Retrieve current interrupt migration and Tx four ACs IMR settings first. */
102 	bCurrentIntMt = hal->bInterruptMigration;
103 	bCurrentACIntDisable = hal->bDisableTxInt;
104 
105 	/*
106 	 * <Roger_Notes> Currently we use busy traffic for reference instead of RxIntOK counts to prevent non-linear Rx statistics
107 	 * when interrupt migration is set before. 2010.03.05.
108 	 */
109 	if (!adapter->registrypriv.wifi_spec
110 		&& (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
111 		&& pmlmepriv->LinkDetectInfo.bHigherBusyTraffic) {
112 		IntMtToSet = _TRUE;
113 
114 		/* To check whether we should disable Tx interrupt or not. */
115 		if (pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic)
116 			ACIntToSet = _TRUE;
117 	}
118 
119 	/* Update current settings. */
120 	if (bCurrentIntMt != IntMtToSet) {
121 		RTW_INFO("%s: Update interrrupt migration(%d)\n", __FUNCTION__, IntMtToSet);
122 		if (IntMtToSet) {
123 			/*
124 			 * <Roger_Notes> Set interrrupt migration timer and corresponging Tx/Rx counter.
125 			 * timer 25ns*0xfa0=100us for 0xf packets.
126 			 * 2010.03.05.
127 			 */
128 			rtw_write32(adapter, REG_INT_MIG, 0xff000fa0); /* 0x306:Rx, 0x307:Tx */
129 			hal->bInterruptMigration = IntMtToSet;
130 		} else {
131 			/* Reset all interrupt migration settings. */
132 			rtw_write32(adapter, REG_INT_MIG, 0);
133 			hal->bInterruptMigration = IntMtToSet;
134 		}
135 	}
136 }
137 #endif /* CONFIG_PCI_HCI */
138 
139 /*
140  * ============================================================
141  * functions
142  * ============================================================
143  */
init_phydm_cominfo(PADAPTER adapter)144 static void init_phydm_cominfo(PADAPTER adapter)
145 {
146 	PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
147 	struct dm_struct *pDM_Odm = &hal->odmpriv;
148 
149 	Init_ODM_ComInfo(adapter);
150 
151 	odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_PACKAGE_TYPE, hal->PackageType);
152 
153 	RTW_INFO("%s: Fv=%d Cv=%d\n", __FUNCTION__, hal->version_id.VendorType, hal->version_id.CUTVersion);
154 	odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_FAB_VER, hal->version_id.VendorType);
155 	odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_CUT_VER, hal->version_id.CUTVersion);
156 
157 }
158 
rtl8821c_phy_init_dm_priv(PADAPTER adapter)159 void rtl8821c_phy_init_dm_priv(PADAPTER adapter)
160 {
161 	struct dm_struct *phydm = adapter_to_phydm(adapter);
162 
163 	init_phydm_cominfo(adapter);
164 	odm_init_all_timers(phydm);
165 }
166 
rtl8821c_phy_deinit_dm_priv(PADAPTER adapter)167 void rtl8821c_phy_deinit_dm_priv(PADAPTER adapter)
168 {
169 	struct dm_struct *phydm = adapter_to_phydm(adapter);
170 
171 	odm_cancel_all_timers(phydm);
172 }
173 
rtl8821c_phy_init_haldm(PADAPTER adapter)174 void rtl8821c_phy_init_haldm(PADAPTER adapter)
175 {
176 	rtw_phydm_init(adapter);
177 }
178 
check_rxfifo_full(PADAPTER adapter)179 static void check_rxfifo_full(PADAPTER adapter)
180 {
181 	struct dvobj_priv *psdpriv = adapter->dvobj;
182 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
183 	struct registry_priv *regsty = &adapter->registrypriv;
184 	u8 val8 = 0;
185 
186 	if (regsty->check_hw_status == 1) {
187 		/* switch counter to RX fifo */
188 		val8 = rtw_read8(adapter, REG_RXERR_RPT_8821C + 3);
189 		rtw_write8(adapter, REG_RXERR_RPT_8821C + 3, (val8 | 0xa0));
190 
191 		pdbgpriv->dbg_rx_fifo_last_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow;
192 		pdbgpriv->dbg_rx_fifo_curr_overflow = rtw_read16(adapter, REG_RXERR_RPT_8821C);
193 		if (pdbgpriv->dbg_rx_fifo_curr_overflow >= pdbgpriv->dbg_rx_fifo_last_overflow)
194 			pdbgpriv->dbg_rx_fifo_diff_overflow =
195 				pdbgpriv->dbg_rx_fifo_curr_overflow - pdbgpriv->dbg_rx_fifo_last_overflow;
196 		else
197 			pdbgpriv->dbg_rx_fifo_diff_overflow =
198 				(0xFFFF - pdbgpriv->dbg_rx_fifo_last_overflow)
199 				+ pdbgpriv->dbg_rx_fifo_curr_overflow;
200 
201 	}
202 }
203 
204 
rtl8821c_phy_haldm_watchdog(PADAPTER Adapter)205 void rtl8821c_phy_haldm_watchdog(PADAPTER Adapter)
206 {
207 	BOOLEAN bFwCurrentInPSMode = _FALSE;
208 	u8 bFwPSAwake = _TRUE;
209 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
210 	u8 in_lps = _FALSE;
211 	PADAPTER current_lps_iface = NULL, iface = NULL;
212 	struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
213 	u8 i = 0;
214 
215 	if (!rtw_is_hw_init_completed(Adapter))
216 		goto skip_dm;
217 
218 #ifdef CONFIG_LPS
219 	bFwCurrentInPSMode = pwrpriv->bFwCurrentInPSMode;
220 	rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, &bFwPSAwake);
221 #endif
222 
223 #ifdef CONFIG_P2P_PS
224 	/* Fw is under p2p powersaving mode, driver should stop dynamic mechanism.
225 	 modifed by thomas. 2011.06.11.*/
226 	if (Adapter->wdinfo.p2p_ps_mode)
227 		bFwPSAwake = _FALSE;
228 #endif /*CONFIG_P2P_PS*/
229 
230 	if ((rtw_is_hw_init_completed(Adapter))
231 		&& ((!bFwCurrentInPSMode) && bFwPSAwake)) {
232 
233 		/* check rx fifo */
234 		check_rxfifo_full(Adapter);
235 
236 		/* Dynamically switch RTS/CTS protection.*/
237 	}
238 
239 #ifdef CONFIG_LPS
240 	if (pwrpriv->bLeisurePs && bFwCurrentInPSMode && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
241 		in_lps = _TRUE;
242 
243 		for (i = 0; i < dvobj->iface_nums; i++) {
244 			iface = dvobj->padapters[i];
245 			if (pwrpriv->current_lps_hw_port_id == rtw_hal_get_port(iface)) {
246 				current_lps_iface = iface;
247 				rtw_lps_rfon_ctrl(current_lps_iface, rf_on);
248 				break;
249 			}
250 		}
251 
252 		if (!current_lps_iface) {
253 			RTW_WARN("Can't find a adapter with LPS to enable RFON function !\n");
254 			goto skip_dm;
255 		}
256 	}
257 #endif
258 
259 #ifdef CONFIG_BEAMFORMING
260 #ifdef RTW_BEAMFORMING_VERSION_2
261 	if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE) &&
262 			check_fwstate(&Adapter->mlmepriv, WIFI_ASOC_STATE))
263 		rtw_hal_beamforming_config_csirate(Adapter);
264 #endif
265 #endif
266 
267 #ifdef CONFIG_DISABLE_ODM
268 	goto skip_dm;
269 #endif
270 
271 	rtw_phydm_watchdog(Adapter, in_lps);
272 
273 skip_dm:
274 
275 #ifdef CONFIG_LPS
276 	if (current_lps_iface)
277 		rtw_lps_rfon_ctrl(current_lps_iface, rf_off);
278 #endif
279 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
280 	/* Check GPIO to determine current Pbc status.*/
281 	dm_CheckPbcGPIO(Adapter);
282 #endif
283 	return;
284 }
285 
286