// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "../wifi.h"
#include "../efuse.h"
#include "../base.h"
#include "../regd.h"
#include "../cam.h"
#include "../ps.h"
#include "../pci.h"
#include "../rtl8192d/reg.h"
#include "../rtl8192d/def.h"
#include "../rtl8192d/dm_common.h"
#include "../rtl8192d/fw_common.h"
#include "../rtl8192d/hw_common.h"
#include "../rtl8192d/phy_common.h"
#include "phy.h"
#include "dm.h"
#include "fw.h"
#include "led.h"
#include "sw.h"
#include "hw.h"
u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 value;
rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC));
rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct);
udelay(10);
value = rtl_read_dword(rtlpriv, REG_DBI_RDATA);
return value;
}
void rtl92de_write_dword_dbi(struct ieee80211_hw *hw,
u16 offset, u32 value, u8 direct)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000));
rtl_write_dword(rtlpriv, REG_DBI_WDATA, value);
rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct);
}
static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
u8 set_bits, u8 clear_bits)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpci->reg_bcn_ctrl_val |= set_bits;
rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
}
static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw)
{
_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1));
}
static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw)
{
_rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0);
}
void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
switch (variable) {
case HW_VAR_RCR:
*((u32 *) (val)) = rtlpci->receive_config;
break;
default:
rtl92d_get_hw_reg(hw, variable, val);
break;
}
}
void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
switch (variable) {
case HW_VAR_AC_PARAM: {
u8 e_aci = *val;
rtl92d_dm_init_edca_turbo(hw);
if (rtlpci->acm_method != EACMWAY2_SW)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
&e_aci);
break;
}
case HW_VAR_ACM_CTRL: {
u8 e_aci = *val;
union aci_aifsn *p_aci_aifsn =
(union aci_aifsn *)(&(mac->ac[0].aifs));
u8 acm = p_aci_aifsn->f.acm;
u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
if (acm) {
switch (e_aci) {
case AC0_BE:
acm_ctrl |= ACMHW_BEQEN;
break;
case AC2_VI:
acm_ctrl |= ACMHW_VIQEN;
break;
case AC3_VO:
acm_ctrl |= ACMHW_VOQEN;
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
"HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
acm);
break;
}
} else {
switch (e_aci) {
case AC0_BE:
acm_ctrl &= (~ACMHW_BEQEN);
break;
case AC2_VI:
acm_ctrl &= (~ACMHW_VIQEN);
break;
case AC3_VO:
acm_ctrl &= (~ACMHW_VOQEN);
break;
default:
pr_err("switch case %#x not processed\n",
e_aci);
break;
}
}
rtl_dbg(rtlpriv, COMP_QOS, DBG_TRACE,
"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
acm_ctrl);
rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
break;
}
case HW_VAR_RCR:
rtl_write_dword(rtlpriv, REG_RCR