rtl8821c_dm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 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 8821C dynamic mechanism
  24. *
  25. *
  26. * ************************************************************ */
  27. #define _RTL8812C_DM_C_
  28. /* ************************************************************
  29. * include files
  30. * ************************************************************
  31. */
  32. #include <drv_types.h>
  33. #include <rtl8821c_hal.h>
  34. /* ************************************************************
  35. * Global var
  36. * ************************************************************ */
  37. static void dm_CheckProtection(PADAPTER adapter)
  38. {
  39. }
  40. static void dm_CheckStatistics(PADAPTER adapter)
  41. {
  42. }
  43. #ifdef CONFIG_SUPPORT_HW_WPS_PBC
  44. static void dm_CheckPbcGPIO(PADAPTER adapter)
  45. {
  46. u8 tmp1byte;
  47. u8 bPbcPressed = _FALSE;
  48. if (!adapter->registrypriv.hw_wps_pbc)
  49. return;
  50. #ifdef CONFIG_USB_HCI
  51. tmp1byte = rtw_read8(adapter, GPIO_IO_SEL);
  52. tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
  53. rtw_write8(adapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
  54. tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
  55. rtw_write8(adapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
  56. tmp1byte = rtw_read8(adapter, GPIO_IO_SEL);
  57. tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
  58. rtw_write8(adapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
  59. tmp1byte = rtw_read8(adapter, GPIO_IN);
  60. if (tmp1byte == 0xff)
  61. return;
  62. if (tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT)
  63. bPbcPressed = _TRUE;
  64. #else
  65. tmp1byte = rtw_read8(adapter, GPIO_IN);
  66. if ((tmp1byte == 0xff) || adapter->init_adpt_in_progress)
  67. return;
  68. if ((tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT) == 0)
  69. bPbcPressed = _TRUE;
  70. #endif
  71. if (_TRUE == bPbcPressed) {
  72. /*
  73. * Here we only set bPbcPressed to true
  74. * After trigger PBC, the variable will be set to false
  75. */
  76. RTW_INFO("CheckPbcGPIO - PBC is pressed\n");
  77. rtw_request_wps_pbc_event(adapter);
  78. }
  79. }
  80. #endif /* CONFIG_SUPPORT_HW_WPS_PBC */
  81. #ifdef CONFIG_PCI_HCI
  82. /*
  83. * Description:
  84. * Perform interrupt migration dynamically to reduce CPU utilization.
  85. *
  86. * Assumption:
  87. * 1. Do not enable migration under WIFI test.
  88. */
  89. void dm_InterruptMigration(PADAPTER adapter)
  90. {
  91. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  92. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  93. BOOLEAN bCurrentIntMt, bCurrentACIntDisable;
  94. BOOLEAN IntMtToSet = _FALSE;
  95. BOOLEAN ACIntToSet = _FALSE;
  96. /* Retrieve current interrupt migration and Tx four ACs IMR settings first. */
  97. bCurrentIntMt = hal->bInterruptMigration;
  98. bCurrentACIntDisable = hal->bDisableTxInt;
  99. /*
  100. * <Roger_Notes> Currently we use busy traffic for reference instead of RxIntOK counts to prevent non-linear Rx statistics
  101. * when interrupt migration is set before. 2010.03.05.
  102. */
  103. if (!adapter->registrypriv.wifi_spec
  104. && (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
  105. && pmlmepriv->LinkDetectInfo.bHigherBusyTraffic) {
  106. IntMtToSet = _TRUE;
  107. /* To check whether we should disable Tx interrupt or not. */
  108. if (pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic)
  109. ACIntToSet = _TRUE;
  110. }
  111. /* Update current settings. */
  112. if (bCurrentIntMt != IntMtToSet) {
  113. RTW_INFO("%s: Update interrrupt migration(%d)\n", __FUNCTION__, IntMtToSet);
  114. if (IntMtToSet) {
  115. /*
  116. * <Roger_Notes> Set interrrupt migration timer and corresponging Tx/Rx counter.
  117. * timer 25ns*0xfa0=100us for 0xf packets.
  118. * 2010.03.05.
  119. */
  120. rtw_write32(adapter, REG_INT_MIG, 0xff000fa0); /* 0x306:Rx, 0x307:Tx */
  121. hal->bInterruptMigration = IntMtToSet;
  122. } else {
  123. /* Reset all interrupt migration settings. */
  124. rtw_write32(adapter, REG_INT_MIG, 0);
  125. hal->bInterruptMigration = IntMtToSet;
  126. }
  127. }
  128. }
  129. #endif /* CONFIG_PCI_HCI */
  130. /*
  131. * ============================================================
  132. * functions
  133. * ============================================================
  134. */
  135. static void init_phydm_cominfo(PADAPTER adapter)
  136. {
  137. PHAL_DATA_TYPE hal;
  138. struct PHY_DM_STRUCT *pDM_Odm;
  139. u32 SupportAbility = 0;
  140. u8 cut_ver = ODM_CUT_A, fab_ver = ODM_TSMC;
  141. hal = GET_HAL_DATA(adapter);
  142. pDM_Odm = &hal->odmpriv;
  143. Init_ODM_ComInfo(adapter);
  144. odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_PACKAGE_TYPE, hal->PackageType);
  145. if (IS_CHIP_VENDOR_TSMC(hal->version_id))
  146. fab_ver = ODM_TSMC;
  147. else if (IS_CHIP_VENDOR_UMC(hal->version_id))
  148. fab_ver = ODM_UMC;
  149. else if (IS_CHIP_VENDOR_SMIC(hal->version_id))
  150. fab_ver = ODM_UMC + 1;
  151. else
  152. RTW_INFO("%s: unknown fab_ver=%d !!\n",
  153. __FUNCTION__, GET_CVID_MANUFACTUER(hal->version_id));
  154. if (IS_A_CUT(hal->version_id))
  155. cut_ver = ODM_CUT_A;
  156. else if (IS_B_CUT(hal->version_id))
  157. cut_ver = ODM_CUT_B;
  158. else if (IS_C_CUT(hal->version_id))
  159. cut_ver = ODM_CUT_C;
  160. else if (IS_D_CUT(hal->version_id))
  161. cut_ver = ODM_CUT_D;
  162. else if (IS_E_CUT(hal->version_id))
  163. cut_ver = ODM_CUT_E;
  164. else if (IS_F_CUT(hal->version_id))
  165. cut_ver = ODM_CUT_F;
  166. else if (IS_I_CUT(hal->version_id))
  167. cut_ver = ODM_CUT_I;
  168. else if (IS_J_CUT(hal->version_id))
  169. cut_ver = ODM_CUT_J;
  170. else if (IS_K_CUT(hal->version_id))
  171. cut_ver = ODM_CUT_K;
  172. else
  173. RTW_INFO("%s: unknown cut_ver=%d !!\n",
  174. __FUNCTION__, GET_CVID_CUT_VERSION(hal->version_id));
  175. RTW_INFO("%s: fab_ver=%d cut_ver=%d\n", __FUNCTION__, fab_ver, cut_ver);
  176. odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
  177. odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
  178. SupportAbility = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK;
  179. #ifdef CONFIG_DISABLE_ODM
  180. SupportAbility = 0;
  181. #endif
  182. odm_cmn_info_update(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility);
  183. }
  184. void rtl8821c_phy_init_dm_priv(PADAPTER adapter)
  185. {
  186. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  187. struct PHY_DM_STRUCT *podmpriv = &hal->odmpriv;
  188. init_phydm_cominfo(adapter);
  189. odm_init_all_timers(podmpriv);
  190. /*PHYDM API - thermal trim*/
  191. phydm_get_thermal_trim_offset(podmpriv);
  192. /*PHYDM API - power trim*/
  193. phydm_get_power_trim_offset(podmpriv);
  194. }
  195. void rtl8821c_phy_deinit_dm_priv(PADAPTER adapter)
  196. {
  197. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  198. struct PHY_DM_STRUCT *podmpriv = &hal->odmpriv;
  199. odm_cancel_all_timers(podmpriv);
  200. }
  201. void rtl8821c_phy_init_haldm(PADAPTER adapter)
  202. {
  203. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  204. struct PHY_DM_STRUCT *pDM_Odm = &hal->odmpriv;
  205. hal->DM_Type = dm_type_by_driver;
  206. odm_dm_init(pDM_Odm);
  207. }
  208. void rtl8821c_phy_haldm_watchdog(PADAPTER Adapter)
  209. {
  210. BOOLEAN bFwCurrentInPSMode = _FALSE;
  211. BOOLEAN bFwPSAwake = _TRUE;
  212. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  213. struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv);
  214. if (!rtw_is_hw_init_completed(Adapter))
  215. goto skip_dm;
  216. #ifdef CONFIG_LPS
  217. bFwCurrentInPSMode = adapter_to_pwrctl(Adapter)->bFwCurrentInPSMode;
  218. rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
  219. #endif
  220. #ifdef CONFIG_P2P_PS
  221. /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism.
  222. modifed by thomas. 2011.06.11.*/
  223. if (Adapter->wdinfo.p2p_ps_mode)
  224. bFwPSAwake = _FALSE;
  225. #endif /*CONFIG_P2P_PS*/
  226. if ((rtw_is_hw_init_completed(Adapter))
  227. && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
  228. /* Calculate Tx/Rx statistics. */
  229. dm_CheckStatistics(Adapter);
  230. /* Dynamically switch RTS/CTS protection.*/
  231. /*dm_CheckProtection(Adapter);*/
  232. }
  233. #ifdef CONFIG_DISABLE_ODM
  234. goto skip_dm;
  235. #endif
  236. if (rtw_is_hw_init_completed(Adapter)) {
  237. u8 bLinked = _FALSE;
  238. u8 bsta_state = _FALSE;
  239. u8 bBtDisabled = _TRUE;
  240. #ifdef CONFIG_LPS_PG
  241. u8 is_in_lpspg = _FALSE;
  242. struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
  243. #endif
  244. if (rtw_mi_check_status(Adapter, MI_STA_LINKED) || rtw_mi_check_status(Adapter, MI_AP_ASSOC)) {
  245. bLinked = _TRUE;
  246. if (rtw_mi_check_status(Adapter, MI_STA_LINKED))
  247. bsta_state = _TRUE;
  248. }
  249. odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked);
  250. odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_STATION_STATE, bsta_state);
  251. #ifdef CONFIG_BT_COEXIST
  252. bBtDisabled = rtw_btcoex_IsBtDisabled(Adapter);
  253. odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED, ((bBtDisabled == _TRUE) ? _FALSE : _TRUE));
  254. #else
  255. odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED, _FALSE);
  256. #endif /* CONFIG_BT_COEXIST*/
  257. #ifdef CONFIG_LPS_PG
  258. if ((pwrpriv->lps_level == LPS_PG) && (pwrpriv->pwr_mode != PS_MODE_ACTIVE) && (pwrpriv->rpwm <= PS_STATE_S2))
  259. is_in_lpspg = _TRUE;
  260. odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_LPSPG, is_in_lpspg);
  261. #endif
  262. odm_dm_watchdog(&pHalData->odmpriv);
  263. }
  264. skip_dm:
  265. #ifdef CONFIG_SUPPORT_HW_WPS_PBC
  266. /* Check GPIO to determine current Pbc status.*/
  267. dm_CheckPbcGPIO(Adapter);
  268. #endif
  269. return;
  270. }
  271. void rtl8821c_phy_haldm_in_lps(PADAPTER adapter)
  272. {
  273. #if 0 /* phydm not ready */
  274. u32 PWDB_rssi = 0;
  275. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  276. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  277. struct PHY_DM_STRUCT *pDM_Odm = &hal->odmpriv;
  278. struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &pDM_Odm->dm_dig_table;
  279. struct sta_priv *pstapriv = &adapter->stapriv;
  280. struct sta_info *psta = NULL;
  281. RTW_INFO("%s: rssi_min=%d\n", __FUNCTION__, pDM_Odm->rssi_min);
  282. /* update IGI */
  283. odm_write_dig(pDM_Odm, pDM_Odm->rssi_min);
  284. /* set rssi to fw */
  285. psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
  286. if (psta && (psta->rssi_stat.undecorated_smoothed_pwdb > 0)) {
  287. PWDB_rssi = (psta->mac_id | (psta->rssi_stat.undecorated_smoothed_pwdb << 16));
  288. rtl8821c_set_FwRssiSetting_cmd(adapter, (u8 *)&PWDB_rssi);
  289. }
  290. #endif
  291. }
  292. void rtl8821c_phy_haldm_watchdog_in_lps(PADAPTER adapter)
  293. {
  294. #if 0 /* phydm not ready */
  295. u8 bLinked = _FALSE;
  296. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  297. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  298. struct PHY_DM_STRUCT *pDM_Odm = &hal->odmpriv;
  299. struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &pDM_Odm->dm_dig_table;
  300. struct sta_priv *pstapriv = &adapter->stapriv;
  301. struct sta_info *psta = NULL;
  302. #ifdef CONFIG_CONCURRENT_MODE
  303. PADAPTER pbuddy_adapter = adapter->pbuddy_adapter;
  304. #endif /* CONFIG_CONCURRENT_MODE */
  305. if (!rtw_is_hw_init_completed(adapter))
  306. goto skip_lps_dm;
  307. if (rtw_linked_check(adapter))
  308. bLinked = _TRUE;
  309. #ifdef CONFIG_CONCURRENT_MODE
  310. if (pbuddy_adapter && rtw_linked_check(pbuddy_adapter))
  311. bLinked = _TRUE;
  312. #endif /* CONFIG_CONCURRENT_MODE */
  313. odm_cmn_info_update(&hal->odmpriv, ODM_CMNINFO_LINK, bLinked);
  314. if (bLinked == _FALSE)
  315. goto skip_lps_dm;
  316. if (!(pDM_Odm->support_ability & ODM_BB_RSSI_MONITOR))
  317. goto skip_lps_dm;
  318. /* Do DIG by RSSI In LPS-32K */
  319. /* 1. Find MIN-RSSI */
  320. psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
  321. if (psta == NULL)
  322. goto skip_lps_dm;
  323. hal->entry_min_undecorated_smoothed_pwdb = psta->rssi_stat.undecorated_smoothed_pwdb;
  324. RTW_INFO("cur_ig_value=%d, entry_min_undecorated_smoothed_pwdb=%d\n",
  325. pDM_DigTable->cur_ig_value, hal->entry_min_undecorated_smoothed_pwdb);
  326. if (hal->entry_min_undecorated_smoothed_pwdb <= 0)
  327. goto skip_lps_dm;
  328. hal->min_undecorated_pwdb_for_dm = hal->entry_min_undecorated_smoothed_pwdb;
  329. pDM_Odm->rssi_min = hal->min_undecorated_pwdb_for_dm;
  330. #ifdef CONFIG_LPS
  331. if ((pDM_DigTable->cur_ig_value > pDM_Odm->rssi_min + 5)
  332. || (pDM_DigTable->cur_ig_value < pDM_Odm->rssi_min - 5))
  333. rtw_dm_in_lps_wk_cmd(adapter);
  334. #endif
  335. skip_lps_dm:
  336. #endif
  337. return;
  338. }