/****************************************************************************** * * 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 _RTL8822ES_HALINIT_C_ #include /* PADAPTER, basic_types.h and etc. */ #include /* HAL_DATA_TYPE */ #include "../../hal_halmac.h" /* rtw_halmac_query_tx_page_num() */ #include "../rtl8822e.h" /* rtl8822e_hal_init(), rtl8822e_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__); #ifdef CONFIG_LPS_LCLK if (rtw_is_fw_ips_lclk_mode(a) == _FALSE) goto send_fwips_h2c; /* 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_8822E)); #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); send_fwips_h2c: #endif /* CONFIG_LPS_LCLK */ rtl8822e_set_FwPwrModeInIPS_cmd(a, 0); rtw_hal_set_hwreg(a, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); #ifdef CONFIG_LPS_LCLK #ifdef DBG_CHECK_FW_PS_STATE if (rtw_is_fw_ips_lclk_mode(a) == _TRUE) { 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 */ #endif /* CONFIG_LPS_LCLK */ 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__); rtl8822e_set_FwPwrModeInIPS_cmd(a, 0x1); #ifdef CONFIG_LPS_LCLK if (rtw_is_fw_ips_lclk_mode(a) == _FALSE) return _SUCCESS; /* * 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_8822E); 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_8822E)); #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_8822E); cnt++; RTW_DBG("%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_8822E)); #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_8822E), cnt, rtw_read8(a, REG_HMETFR_8822E)); pwrctl->pre_ips_type = 0; #endif /* CONFIG_LPS_LCLK */ return _SUCCESS; } #endif /* CONFIG_FWLPS_IN_IPS */ int rtl8822es_sdio_tx_format_update(PADAPTER adapter) { int ret = 0; struct dvobj_priv *d; enum halmac_sdio_tx_format format; const char *const sdio_tx_format_str[] = { "SDIO_TX_FORMAT_UNKNOWN", "SDIO_TX_FORMAT_AGG", "SDIO_TX_FORMAT_DUMMY_BLOCK", "SDIO_TX_FORMAT_DUMMY_AUTO" }; d = adapter_to_dvobj(adapter); if (MAX_XMITBUF_SZ > 32764) format = HALMAC_SDIO_DUMMY_AUTO_MODE; else format = HALMAC_SDIO_AGG_MODE; RTW_INFO("%s : MAX_XMITBUF_SZ = %d, switch to %s \n", __func__, MAX_XMITBUF_SZ, sdio_tx_format_str[format]); ret = rtw_halmac_sdio_set_tx_format(d, format); if (ret != 0) { RTW_ERR("%s : Switch to %s fail !\n", __func__, sdio_tx_format_str[format]); rtw_warn_on(1); } else RTW_INFO("%s Switch to %s ok !\n", __func__, sdio_tx_format_str[format]); return ret; } u32 rtl8822es_init(PADAPTER adapter) { u8 ok = _TRUE; PHAL_DATA_TYPE hal; hal = GET_HAL_DATA(adapter); #ifdef CONFIG_FWLPS_IN_IPS if (rtw_is_fw_ips_mode(adapter) == _TRUE) { if (fw_ips_leave(adapter) == _SUCCESS) return _SUCCESS; } #endif ok = rtl8822e_hal_init(adapter); if (_FALSE == ok) return _FAIL; rtw_halmac_query_tx_page_num(adapter_to_dvobj(adapter)); #ifdef CONFIG_SDIO_TX_FORMAT_DUMMY_AUTO if (rtl8822es_sdio_tx_format_update(adapter)) return _FAIL; #endif rtl8822e_mac_verify(adapter); rtl8822e_phy_init_haldm(adapter); #ifdef CONFIG_BEAMFORMING rtl8822e_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); rtl8822e_init_misc(adapter); return _SUCCESS; } u32 rtl8822es_deinit(PADAPTER adapter) { #ifdef CONFIG_FWLPS_IN_IPS if (rtw_is_fw_ips_mode(adapter) == _TRUE) { if (fw_ips_enter(adapter) == _SUCCESS) return _SUCCESS; } #endif return rtl8822e_deinit(adapter); } void rtl8822es_init_default_value(PADAPTER adapter) { PHAL_DATA_TYPE hal; hal = GET_HAL_DATA(adapter); rtl8822e_init_default_value(adapter); /* interface related variable */ hal->SdioRxFIFOCnt = 0; }