/******************************************************************************
*
* Copyright(c) 2015 - 2017 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 _RTL8822CS_HALINIT_C_
#include <drv_types.h> /* PADAPTER, basic_types.h and etc. */
#include <hal_data.h> /* HAL_DATA_TYPE */
#include "../../hal_halmac.h" /* rtw_halmac_query_tx_page_num() */
#include "../rtl8822c.h" /* rtl8822c_hal_init(), rtl8822c_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_8822C));
#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);
rtl8822c_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__);
rtl8822c_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_8822C);
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_8822C));
#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_8822C);
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_8822C));
#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_8822C), cnt, rtw_read8(a, REG_HMETFR_8822C));
pwrctl->pre_ips_type = 0;
return _SUCCESS;
}
#endif /* CONFIG_FWLPS_IN_IPS */
u32 rtl8822cs_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 = rtl8822c_hal_init(adapter);
if (_FALSE == ok)
return _FAIL;
rtw_halmac_query_tx_page_num(adapter_to_dvobj(adapter));
rtl8822c_mac_verify(adapter);
rtl8822c_phy_init_haldm(adapter);
#ifdef CONFIG_BEAMFORMING
rtl8822c_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);
rtl8822c_init_misc(adapter);
return _SUCCESS;
}
u32 rtl8822cs_deinit(PADAPTER adapter)
{
#ifdef CONFIG_FWLPS_IN_IPS
if (fw_ips_enter(adapter) == _SUCCESS)
return _SUCCESS;
#endif
return rtl8822c_deinit(adapter);
}
void rtl8822cs_init_default_value(PADAPTER adapter)
{
PHAL_DATA_TYPE hal;
hal = GET_HAL_DATA(adapter);
rtl8822c_init_default_value(adapter);
/* interface related variable */
hal->SdioRxFIFOCnt = 0;
}