net: wireless: rockchip_wlan: add rtl8723cs support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723cs / hal / rtl8703b / rtl8703b_dm.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 /* ************************************************************
21  * Description:
22  *
23  * This file is for 92CE/92CU dynamic mechanism only
24  *
25  *
26  * ************************************************************ */
27 #define _RTL8703B_DM_C_
28
29 /* ************************************************************
30  * include files
31  * ************************************************************ */
32 #include <rtl8703b_hal.h>
33
34 /* ************************************************************
35  * Global var
36  * ************************************************************ */
37
38
39 static VOID
40 dm_CheckProtection(
41         IN      PADAPTER        Adapter
42 )
43 {
44 #if 0
45         PMGNT_INFO              pMgntInfo = &(Adapter->MgntInfo);
46         u1Byte                  CurRate, RateThreshold;
47
48         if (pMgntInfo->pHTInfo->bCurBW40MHz)
49                 RateThreshold = MGN_MCS1;
50         else
51                 RateThreshold = MGN_MCS3;
52
53         if (Adapter->TxStats.CurrentInitTxRate <= RateThreshold) {
54                 pMgntInfo->bDmDisableProtect = TRUE;
55                 DbgPrint("Forced disable protect: %x\n", Adapter->TxStats.CurrentInitTxRate);
56         } else {
57                 pMgntInfo->bDmDisableProtect = FALSE;
58                 DbgPrint("Enable protect: %x\n", Adapter->TxStats.CurrentInitTxRate);
59         }
60 #endif
61 }
62
63 static VOID
64 dm_CheckStatistics(
65         IN      PADAPTER        Adapter
66 )
67 {
68 #if 0
69         if (!Adapter->MgntInfo.bMediaConnect)
70                 return;
71
72         /* 2008.12.10 tynli Add for getting Current_Tx_Rate_Reg flexibly. */
73         rtw_hal_get_hwreg(Adapter, HW_VAR_INIT_TX_RATE, (pu1Byte)(&Adapter->TxStats.CurrentInitTxRate));
74
75         /* Calculate current Tx Rate(Successful transmited!!) */
76
77         /* Calculate current Rx Rate(Successful received!!) */
78
79         /* for tx tx retry count */
80         rtw_hal_get_hwreg(Adapter, HW_VAR_RETRY_COUNT, (pu1Byte)(&Adapter->TxStats.NumTxRetryCount));
81 #endif
82 }
83 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
84 static void dm_CheckPbcGPIO(_adapter *padapter)
85 {
86         u8      tmp1byte;
87         u8      bPbcPressed = _FALSE;
88
89         if (!padapter->registrypriv.hw_wps_pbc)
90                 return;
91
92 #ifdef CONFIG_USB_HCI
93         tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
94         tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
95         rtw_write8(padapter, GPIO_IO_SEL, tmp1byte);    /* enable GPIO[2] as output mode */
96
97         tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
98         rtw_write8(padapter,  GPIO_IN, tmp1byte);               /* reset the floating voltage level */
99
100         tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
101         tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
102         rtw_write8(padapter, GPIO_IO_SEL, tmp1byte);    /* enable GPIO[2] as input mode */
103
104         tmp1byte = rtw_read8(padapter, GPIO_IN);
105
106         if (tmp1byte == 0xff)
107                 return ;
108
109         if (tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT)
110                 bPbcPressed = _TRUE;
111 #else
112         tmp1byte = rtw_read8(padapter, GPIO_IN);
113
114         if (tmp1byte == 0xff || padapter->init_adpt_in_progress)
115                 return ;
116
117         if ((tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT) == 0)
118                 bPbcPressed = _TRUE;
119 #endif
120
121         if (_TRUE == bPbcPressed) {
122                 /* Here we only set bPbcPressed to true */
123                 /* After trigger PBC, the variable will be set to false */
124                 RTW_INFO("CheckPbcGPIO - PBC is pressed\n");
125                 rtw_request_wps_pbc_event(padapter);
126         }
127 }
128 #endif /* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */
129
130
131 #ifdef CONFIG_PCI_HCI
132 /*
133  *      Description:
134  *              Perform interrupt migration dynamically to reduce CPU utilization.
135  *
136  *      Assumption:
137  *              1. Do not enable migration under WIFI test.
138  *
139  *      Created by Roger, 2010.03.05.
140  *   */
141 VOID
142 dm_InterruptMigration(
143         IN      PADAPTER        Adapter
144 )
145 {
146         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
147         struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
148         BOOLEAN                 bCurrentIntMt, bCurrentACIntDisable;
149         BOOLEAN                 IntMtToSet = _FALSE;
150         BOOLEAN                 ACIntToSet = _FALSE;
151
152
153         /* Retrieve current interrupt migration and Tx four ACs IMR settings first. */
154         bCurrentIntMt = pHalData->bInterruptMigration;
155         bCurrentACIntDisable = pHalData->bDisableTxInt;
156
157         /*  */
158         /* <Roger_Notes> Currently we use busy traffic for reference instead of RxIntOK counts to prevent non-linear Rx statistics */
159         /* when interrupt migration is set before. 2010.03.05. */
160         /*  */
161         if (!Adapter->registrypriv.wifi_spec &&
162             (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) &&
163             pmlmepriv->LinkDetectInfo.bHigherBusyTraffic) {
164                 IntMtToSet = _TRUE;
165
166                 /* To check whether we should disable Tx interrupt or not. */
167                 if (pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic)
168                         ACIntToSet = _TRUE;
169         }
170
171         /* Update current settings. */
172         if (bCurrentIntMt != IntMtToSet) {
173                 RTW_INFO("%s(): Update interrrupt migration(%d)\n", __FUNCTION__, IntMtToSet);
174                 if (IntMtToSet) {
175                         /*  */
176                         /* <Roger_Notes> Set interrrupt migration timer and corresponging Tx/Rx counter. */
177                         /* timer 25ns*0xfa0=100us for 0xf packets. */
178                         /* 2010.03.05. */
179                         /*  */
180                         rtw_write32(Adapter, REG_INT_MIG, 0xff000fa0);/* 0x306:Rx, 0x307:Tx */
181                         pHalData->bInterruptMigration = IntMtToSet;
182                 } else {
183                         /* Reset all interrupt migration settings. */
184                         rtw_write32(Adapter, REG_INT_MIG, 0);
185                         pHalData->bInterruptMigration = IntMtToSet;
186                 }
187         }
188
189 #if 0
190         if (bCurrentACIntDisable != ACIntToSet) {
191                 RTW_INFO("%s(): Update AC interrrupt(%d)\n", __FUNCTION__, ACIntToSet);
192                 if (ACIntToSet) { /*  Disable four ACs interrupts. */
193                         /* */
194                         /*  <Roger_Notes> Disable VO, VI, BE and BK four AC interrupts to gain more efficient CPU utilization. */
195                         /*  When extremely highly Rx OK occurs, we will disable Tx interrupts. */
196                         /*  2010.03.05. */
197                         /* */
198                         UpdateInterruptMask8192CE(Adapter, 0, RT_AC_INT_MASKS);
199                         pHalData->bDisableTxInt = ACIntToSet;
200                 } else { /*  Enable four ACs interrupts. */
201                         UpdateInterruptMask8192CE(Adapter, RT_AC_INT_MASKS, 0);
202                         pHalData->bDisableTxInt = ACIntToSet;
203                 }
204         }
205 #endif
206
207 }
208
209 #endif
210
211 /*
212  * Initialize GPIO setting registers
213  *   */
214 static void
215 dm_InitGPIOSetting(
216         IN      PADAPTER        Adapter
217 )
218 {
219         PHAL_DATA_TYPE          pHalData = GET_HAL_DATA(Adapter);
220
221         u8      tmp1byte;
222
223         tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
224         tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
225
226         rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
227 }
228 /* ************************************************************
229  * functions
230  * ************************************************************ */
231 static void Init_ODM_ComInfo_8703b(PADAPTER     Adapter)
232 {
233         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
234         struct PHY_DM_STRUCT            *pDM_Odm = &(pHalData->odmpriv);
235         u32 SupportAbility = 0;
236         u8      cut_ver, fab_ver;
237
238         Init_ODM_ComInfo(Adapter);
239
240         odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_PACKAGE_TYPE, pHalData->PackageType);
241
242         fab_ver = ODM_TSMC;
243         cut_ver = GET_CVID_CUT_VERSION(pHalData->version_id);
244
245         RTW_INFO("%s(): fab_ver=%d cut_ver=%d\n", __func__, fab_ver, cut_ver);
246         odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
247         odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
248
249 #ifdef CONFIG_DISABLE_ODM
250         SupportAbility = 0;
251 #else
252         SupportAbility =
253 #if 1
254                 ODM_RF_CALIBRATION |
255                 ODM_RF_TX_PWR_TRACK
256 #else
257                 0
258 #endif
259                 ;
260 #endif
261
262         odm_cmn_info_update(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility);
263 }
264
265 static void Update_ODM_ComInfo_8703b(PADAPTER   Adapter)
266 {
267         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
268         struct PHY_DM_STRUCT            *pDM_Odm = &(pHalData->odmpriv);
269         u32 SupportAbility = 0;
270
271         SupportAbility = 0
272                          | ODM_BB_DIG                                   /* For BB */
273                          | ODM_BB_RA_MASK
274                          | ODM_BB_FA_CNT
275                          | ODM_BB_RSSI_MONITOR
276                          | ODM_BB_CCK_PD
277                          | ODM_BB_CFO_TRACKING
278                          /* | ODM_BB_PWR_TRAIN */
279                          | ODM_BB_NHM_CNT
280                          | ODM_RF_TX_PWR_TRACK  /* For RF */
281                          | ODM_RF_CALIBRATION
282                          | ODM_MAC_EDCA_TURBO           /* For MAC */
283                          ;
284
285         if (rtw_odm_adaptivity_needed(Adapter) == _TRUE) {
286                 rtw_odm_adaptivity_config_msg(RTW_DBGDUMP, Adapter);
287                 SupportAbility |= ODM_BB_ADAPTIVITY;
288         }
289
290 #ifdef CONFIG_ANTENNA_DIVERSITY
291         if (pHalData->AntDivCfg)
292                 SupportAbility |= ODM_BB_ANT_DIV;
293 #endif
294
295 #if (MP_DRIVER == 1)
296         if (Adapter->registrypriv.mp_mode == 1) {
297                 SupportAbility = 0
298                                  | ODM_RF_CALIBRATION
299                                  | ODM_RF_TX_PWR_TRACK
300                                  ;
301         }
302 #endif/* (MP_DRIVER==1) */
303
304 #ifdef CONFIG_DISABLE_ODM
305         SupportAbility = 0;
306 #endif/* CONFIG_DISABLE_ODM */
307
308         odm_cmn_info_update(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility);
309 }
310
311 void
312 rtl8703b_InitHalDm(
313         IN      PADAPTER        Adapter
314 )
315 {
316         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
317         struct PHY_DM_STRUCT            *pDM_Odm = &(pHalData->odmpriv);
318
319         u8      i;
320
321 #ifdef CONFIG_USB_HCI
322         dm_InitGPIOSetting(Adapter);
323 #endif
324
325         pHalData->DM_Type = dm_type_by_driver;
326
327         Update_ODM_ComInfo_8703b(Adapter);
328
329         odm_dm_init(pDM_Odm);
330
331 }
332
333 VOID
334 rtl8703b_HalDmWatchDog(
335         IN      PADAPTER        Adapter
336 )
337 {
338         BOOLEAN         bFwCurrentInPSMode = _FALSE;
339         BOOLEAN         bFwPSAwake = _TRUE;
340         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
341
342 #ifdef CONFIG_MP_INCLUDED
343         /* #if MP_DRIVER */
344         if (Adapter->registrypriv.mp_mode == 1 && Adapter->mppriv.mp_dm == 0) /* for MP power tracking */
345                 return;
346         /* #endif */
347 #endif
348
349         if (!rtw_is_hw_init_completed(Adapter))
350                 goto skip_dm;
351
352 #ifdef CONFIG_LPS
353         bFwCurrentInPSMode = adapter_to_pwrctl(Adapter)->bFwCurrentInPSMode;
354         rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
355 #endif
356
357 #ifdef CONFIG_P2P
358         /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
359         /* modifed by thomas. 2011.06.11. */
360         if (Adapter->wdinfo.p2p_ps_mode)
361                 bFwPSAwake = _FALSE;
362 #endif /* CONFIG_P2P */
363
364
365         if ((rtw_is_hw_init_completed(Adapter))
366             && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
367                 /*  */
368                 /* Calculate Tx/Rx statistics. */
369                 /*  */
370                 dm_CheckStatistics(Adapter);
371                 rtw_hal_check_rxfifo_full(Adapter);
372                 /*  */
373                 /* Dynamically switch RTS/CTS protection. */
374                 /*  */
375                 /* dm_CheckProtection(Adapter); */
376
377 #ifdef CONFIG_PCI_HCI
378                 /* 20100630 Joseph: Disable Interrupt Migration mechanism temporarily because it degrades Rx throughput. */
379                 /* Tx Migration settings. */
380                 /* dm_InterruptMigration(Adapter); */
381
382                 /* if(Adapter->HalFunc.TxCheckStuckHandler(Adapter)) */
383                 /*      PlatformScheduleWorkItem(&(GET_HAL_DATA(Adapter)->HalResetWorkItem)); */
384 #endif
385         }
386
387         /* ODM */
388         if (rtw_is_hw_init_completed(Adapter)) {
389                 u8      bLinked = _FALSE;
390                 u8      bsta_state = _FALSE;
391                 u8      bBtDisabled = _TRUE;
392
393                 if (rtw_mi_check_status(Adapter, MI_ASSOC)) {
394                         bLinked = _TRUE;
395                         if (rtw_mi_check_status(Adapter, MI_STA_LINKED))
396                                 bsta_state = _TRUE;
397                 }
398
399                 odm_cmn_info_update(&pHalData->odmpriv , ODM_CMNINFO_LINK, bLinked);
400                 odm_cmn_info_update(&pHalData->odmpriv , ODM_CMNINFO_STATION_STATE, bsta_state);
401
402                 /* odm_cmn_info_update(&pHalData->odmpriv ,ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); */
403
404 #ifdef CONFIG_BT_COEXIST
405                 bBtDisabled = rtw_btcoex_IsBtDisabled(Adapter);
406 #endif /* CONFIG_BT_COEXIST */
407                 odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED, ((bBtDisabled == _TRUE) ? _FALSE : _TRUE));
408
409                 odm_dm_watchdog(&pHalData->odmpriv);
410         }
411
412 skip_dm:
413
414         /* Check GPIO to determine current RF on/off and Pbc status. */
415         /* Check Hardware Radio ON/OFF or not */
416         /* if(Adapter->MgntInfo.PowerSaveControl.bGpioRfSw) */
417         /* { */
418         /* RTPRINT(FPWR, PWRHW, ("dm_CheckRfCtrlGPIO\n")); */
419         /*      dm_CheckRfCtrlGPIO(Adapter); */
420         /* } */
421 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
422         dm_CheckPbcGPIO(Adapter);
423 #endif
424         return;
425 }
426
427 void rtl8703b_hal_dm_in_lps(PADAPTER padapter)
428 {
429         u32     PWDB_rssi = 0;
430         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
431         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(padapter);
432         struct PHY_DM_STRUCT            *pDM_Odm = &pHalData->odmpriv;
433         struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &pDM_Odm->dm_dig_table;
434         struct sta_priv *pstapriv = &padapter->stapriv;
435         struct sta_info *psta = NULL;
436
437         RTW_INFO("%s, rssi_min=%d\n", __func__, pDM_Odm->rssi_min);
438
439         /* update IGI */
440         odm_write_dig(pDM_Odm, pDM_Odm->rssi_min);
441
442
443         /* set rssi to fw */
444         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
445         if (psta && (psta->rssi_stat.undecorated_smoothed_pwdb > 0)) {
446                 PWDB_rssi = (psta->mac_id | (psta->rssi_stat.undecorated_smoothed_pwdb << 16));
447
448                 rtl8703b_set_rssi_cmd(padapter, (u8 *)&PWDB_rssi);
449         }
450
451 }
452
453 void rtl8703b_HalDmWatchDog_in_LPS(IN   PADAPTER        Adapter)
454 {
455         u8      bLinked = _FALSE;
456         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
457         struct mlme_priv        *pmlmepriv = &Adapter->mlmepriv;
458         struct PHY_DM_STRUCT            *pDM_Odm = &pHalData->odmpriv;
459         struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &pDM_Odm->dm_dig_table;
460         struct sta_priv *pstapriv = &Adapter->stapriv;
461         struct sta_info *psta = NULL;
462
463         if (!rtw_is_hw_init_completed(Adapter))
464                 goto skip_lps_dm;
465
466         if (rtw_mi_check_status(Adapter, MI_ASSOC))
467                 bLinked = _TRUE;
468
469         odm_cmn_info_update(&pHalData->odmpriv , ODM_CMNINFO_LINK, bLinked);
470
471         if (bLinked == _FALSE)
472                 goto skip_lps_dm;
473
474         if (!(pDM_Odm->support_ability & ODM_BB_RSSI_MONITOR))
475                 goto skip_lps_dm;
476
477
478         /* odm_dm_watchdog(&pHalData->odmpriv);  */
479         /* Do DIG by RSSI In LPS-32K */
480
481         /* .1 Find MIN-RSSI */
482         psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
483         if (psta == NULL)
484                 goto skip_lps_dm;
485
486         pHalData->entry_min_undecorated_smoothed_pwdb = psta->rssi_stat.undecorated_smoothed_pwdb;
487
488         RTW_INFO("cur_ig_value=%d, entry_min_undecorated_smoothed_pwdb = %d\n", pDM_DigTable->cur_ig_value, pHalData->entry_min_undecorated_smoothed_pwdb);
489
490         if (pHalData->entry_min_undecorated_smoothed_pwdb <= 0)
491                 goto skip_lps_dm;
492
493         pHalData->min_undecorated_pwdb_for_dm = pHalData->entry_min_undecorated_smoothed_pwdb;
494
495         pDM_Odm->rssi_min = pHalData->min_undecorated_pwdb_for_dm;
496
497         /* if(pDM_DigTable->cur_ig_value != pDM_Odm->rssi_min) */
498         if ((pDM_DigTable->cur_ig_value > pDM_Odm->rssi_min + 5) ||
499             (pDM_DigTable->cur_ig_value < pDM_Odm->rssi_min - 5)) {
500 #ifdef CONFIG_LPS
501                 rtw_dm_in_lps_wk_cmd(Adapter);
502 #endif /* CONFIG_LPS */
503         }
504
505
506 skip_lps_dm:
507
508         return;
509
510 }
511
512 void rtl8703b_init_dm_priv(IN PADAPTER Adapter)
513 {
514         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
515         struct PHY_DM_STRUCT            *podmpriv = &pHalData->odmpriv;
516         Init_ODM_ComInfo_8703b(Adapter);
517         odm_init_all_timers(podmpriv);
518
519 }
520
521 void rtl8703b_deinit_dm_priv(IN PADAPTER Adapter)
522 {
523         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
524         struct PHY_DM_STRUCT            *podmpriv = &pHalData->odmpriv;
525
526         odm_cancel_all_timers(podmpriv);
527
528 }