/****************************************************************************** * * Copyright(c) 2015 - 2019 Realtek Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * *****************************************************************************/ #define _RTL8822BS_HALINIT_C_ #include /* PADAPTER, basic_types.h and etc. */ #include /* HAL_DATA_TYPE */ #include "../../hal_halmac.h" /* rtw_halmac_query_tx_page_num() */ #include "../rtl8822b.h" /* rtl8822b_hal_init(), rtl8822b_phy_init_haldm() and etc. */ #ifdef CONFIG_FWLPS_IN_IPS static u8 fw_ips_leave(struct _ADAPTER *a) { struct sreset_priv *psrtpriv = &GET_HAL_DATA(a)->srestpriv; struct debug_priv *pdbgpriv = &adapter_to_dvobj(a)->drv_dbg; struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(a); systime start_time; u8 cpwm_orig, cpwm_now, rpwm; u8 bMacPwrCtrlOn = _TRUE; if ((pwrctl->bips_processing == _FALSE) || (psrtpriv->silent_reset_inprogress == _TRUE) || (GET_HAL_DATA(a)->bFWReady == _FALSE) || (pwrctl->pre_ips_type != 0)) return _FAIL; RTW_INFO("%s: Leaving FW_IPS\n", __func__); /* for polling cpwm */ cpwm_orig = 0; rtw_hal_get_hwreg(a, HW_VAR_CPWM, &cpwm_orig); /* set rpwm */ #if 1 rtw_hal_get_hwreg(a, HW_VAR_RPWM_TOG, &rpwm); rpwm += 0x80; #else rpwm = pwrctl->tog; #endif rpwm |= PS_ACK; rtw_hal_set_hwreg(a, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); RTW_INFO("%s: write rpwm=%02x\n", __FUNCTION__, rpwm); pwrctl->tog = (rpwm + 0x80) & 0x80; /* do polling cpwm */ start_time = rtw_get_current_time(); do { rtw_mdelay_os(1); rtw_hal_get_hwreg(a, HW_VAR_CPWM, &cpwm_now); if ((cpwm_orig ^ cpwm_now) & 0x80) { #ifdef DBG_CHECK_FW_PS_STATE RTW_INFO("%s: polling cpwm ok when leaving IPS in FWLPS state," " cost %d ms," " cpwm_orig=0x%02x, cpwm_now=0x%02x, 0x100=0x%x\n", __FUNCTION__, rtw_get_passing_time_ms(start_time), cpwm_orig, cpwm_now, rtw_read8(a, REG_CR_8822B)); #endif /* DBG_CHECK_FW_PS_STATE */ break; } if (rtw_get_passing_time_ms(start_time) > 100) { RTW_ERR("%s: polling cpwm timeout when leaving IPS in FWLPS state\n", __FUNCTION__); break; } } while (1); rtl8822b_set_FwPwrModeInIPS_cmd(a, 0); rtw_hal_set_hwreg(a, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); #ifdef DBG_CHECK_FW_PS_STATE if (rtw_fw_ps_state(a) == _FAIL) { RTW_INFO("after hal init, fw ps state in 32k\n"); pdbgpriv->dbg_ips_drvopen_fail_cnt++; } #endif /* DBG_CHECK_FW_PS_STATE */ return _SUCCESS; } static u8 fw_ips_enter(struct _ADAPTER *a) { struct sreset_priv *psrtpriv = &GET_HAL_DATA(a)->srestpriv; struct debug_priv *pdbgpriv = &adapter_to_dvobj(a)->drv_dbg; struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(a); systime start_time; int cnt = 0; u8 val8 = 0, rpwm; if ((pwrctl->bips_processing == _FALSE) || (psrtpriv->silent_reset_inprogress == _TRUE) || (GET_HAL_DATA(a)->bFWReady == _FALSE) || (a->netif_up == _FALSE)) { pdbgpriv->dbg_carddisable_cnt++; pwrctl->pre_ips_type = 1; return _FAIL; } RTW_INFO("%s: issue H2C to FW when entering IPS\n", __FUNCTION__); rtl8822b_set_FwPwrModeInIPS_cmd(a, 0x1); /* * poll 0x1cc to make sure H2C command already finished by FW; * MAC_0x1cc=0 means H2C done by FW. */ start_time = rtw_get_current_time(); do { rtw_mdelay_os(10); val8 = rtw_read8(a, REG_HMETFR_8822B); cnt++; if (!val8) break; if (rtw_get_passing_time_ms(start_time) > 100) { RTW_ERR("%s: fail to wait H2C, REG_HMETFR=0x%x, cnt=%d\n", __FUNCTION__, val8, cnt); #ifdef DBG_CHECK_FW_PS_STATE RTW_WARN("MAC_1C0=0x%08x, MAC_1C4=0x%08x, MAC_1C8=0x%08x, MAC_1CC=0x%08x\n", rtw_read32(a, 0x1c0), rtw_read32(a, 0x1c4), rtw_read32(a, 0x1c8), rtw_read32(a, REG_HMETFR_8822B)); #endif /* DBG_CHECK_FW_PS_STATE */ goto exit; } } while (1); /* H2C done, enter 32k */ /* set rpwm to enter 32k */ #if 1 rtw_hal_get_hwreg(a, HW_VAR_RPWM_TOG, &rpwm); rpwm += 0x80; #else rpwm = pwrctl->tog; #endif rpwm |= PS_STATE_S0; rtw_hal_set_hwreg(a, HW_VAR_SET_RPWM, &rpwm); RTW_INFO("%s: write rpwm=%02x\n", __FUNCTION__, rpwm); pwrctl->tog = (rpwm + 0x80) & 0x80; cnt = val8 = 0; start_time = rtw_get_current_time(); do { val8 = rtw_read8(a, REG_CR_8822B); cnt++; RTW_INFO("%s: polling 0x100=0x%x, cnt=%d\n", __FUNCTION__, val8, cnt); if (val8 == 0xEA) { RTW_INFO("%s: polling 0x100=0xEA, cnt=%d, cost %d ms\n", __FUNCTION__, cnt, rtw_get_passing_time_ms(start_time)); break; } if (rtw_get_passing_time_ms(start_time) > 100) { RTW_ERR("%s: polling polling 0x100=0xEA timeout! cnt=%d\n", __FUNCTION__, cnt); #ifdef DBG_CHECK_FW_PS_STATE RTW_WARN("MAC_1C0=0x%08x, MAC_1C4=0x%08x, MAC_1C8=0x%08x, MAC_1CC=0x%08x\n", rtw_read32(a, 0x1c0), rtw_read32(a, 0x1c4), rtw_read32(a, 0x1c8), rtw_read32(a, REG_HMETFR_8822B)); #endif /* DBG_CHECK_FW_PS_STATE */ break; } rtw_mdelay_os(10); } while (1); exit: RTW_INFO("polling done when entering IPS, check result: 0x100=0x%02x, cnt=%d, MAC_1cc=0x%02x\n", rtw_read8(a, REG_CR_8822B), cnt, rtw_read8(a, REG_HMETFR_8822B)); pwrctl->pre_ips_type = 0; return _SUCCESS; } #endif /* CONFIG_FWLPS_IN_IPS */ u32 rtl8822bs_init(PADAPTER adapter) { u8 ok = _TRUE; PHAL_DATA_TYPE hal; hal = GET_HAL_DATA(adapter); #ifdef CONFIG_FWLPS_IN_IPS if (fw_ips_leave(adapter) == _SUCCESS) return _SUCCESS; #endif ok = rtl8822b_hal_init(adapter); if (_FALSE == ok) return _FAIL; rtw_halmac_query_tx_page_num(adapter_to_dvobj(adapter)); rtl8822b_mac_verify(adapter); rtl8822b_phy_init_haldm(adapter); #ifdef CONFIG_BEAMFORMING rtl8822b_phy_bf_init(adapter); #endif #ifdef CONFIG_FW_MULTI_PORT_SUPPORT /*HW /FW init*/ rtw_hal_set_default_port_id_cmd(adapter, 0); #endif #ifdef CONFIG_BT_COEXIST /* Init BT hw config. */ if (hal->EEPROMBluetoothCoexist == _TRUE) { rtw_btcoex_HAL_Initialize(adapter, _FALSE); #ifdef CONFIG_FW_MULTI_PORT_SUPPORT rtw_hal_set_wifi_btc_port_id_cmd(adapter); #endif } else #endif /* CONFIG_BT_COEXIST */ rtw_btcoex_wifionly_hw_config(adapter); rtl8822b_init_misc(adapter); return _SUCCESS; } u32 rtl8822bs_deinit(PADAPTER adapter) { #ifdef CONFIG_FWLPS_IN_IPS if (fw_ips_enter(adapter) == _SUCCESS) return _SUCCESS; #endif return rtl8822b_deinit(adapter); } void rtl8822bs_init_default_value(PADAPTER adapter) { PHAL_DATA_TYPE hal; hal = GET_HAL_DATA(adapter); rtl8822b_init_default_value(adapter); /* interface related variable */ hal->SdioRxFIFOCnt = 0; }