/******************************************************************************
|
*
|
* Copyright(c) 2007 - 2020 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.
|
*
|
* The full GNU General Public License is included in this distribution in the
|
* file called LICENSE.
|
*
|
* Contact Information:
|
* wlanfae <wlanfae@realtek.com>
|
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
|
* Hsinchu 300, Taiwan.
|
*
|
* Larry Finger <Larry.Finger@lwfinger.net>
|
*
|
*****************************************************************************/
|
#include "halrf_precomp.h"
|
|
u32 halrf_get_sys_time(struct rf_info *rf)
|
{
|
return 0;
|
}
|
|
u32 halrf_cal_bit_shift(u32 bit_mask)
|
{
|
u32 i;
|
|
for (i = 0; i <= 31; i++) {
|
if ((bit_mask >> i) & BIT0)
|
break;
|
}
|
return i;
|
}
|
|
void halrf_wmac(struct rf_info *rf, u32 addr, u32 mask, u32 val)
|
{
|
u32 ori_val, bit_shift;
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
//u32 fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
u32 rtn;
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
|
|
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start = true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] MAC addr=0x%08x val=0x%08x\n",
|
addr, val);
|
|
cmd.src = RTW_MAC_MAC_CMD_OFLD;
|
cmd.type = RTW_MAC_WRITE_OFLD;
|
cmd.lc = 0;
|
cmd.offset = (u16)addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
rf->fw_w_count++;
|
}
|
else
|
#endif
|
{
|
if (mask != MASKDWORD) {
|
ori_val = halrf_rmac32(rf, addr);
|
bit_shift = halrf_cal_bit_shift(mask);
|
val = ((ori_val) & (~mask)) |( ((val << bit_shift)) & mask);
|
}
|
halrf_wmac32(rf, addr, val);
|
}
|
rf->w_count++;
|
}
|
|
u32 halrf_rmac32(struct rf_info *rf, u32 addr)
|
{
|
u32 reg_val = 0;
|
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
if (rf->fw_ofld_start == true)
|
halrf_write_fwofld_end(rf);
|
#endif
|
rf->r_count++;
|
reg_val = hal_read32((rf)->hal_com, addr);
|
return reg_val;
|
}
|
void halrf_wreg(struct rf_info *rf, u32 addr, u32 mask, u32 val)
|
{
|
u32 ori_val, bit_shift;
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
// u32 fw_ofld = rf->phl_com->dev_cap.io_ofld; //rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
u32 rtn;
|
#endif
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
// u32 page_temp;
|
// u32 offset_temp;
|
// u32 temp = 0;
|
|
// page_temp = addr & 0xff00;
|
// offset_temp = addr & 0xff;
|
|
// if ((page_temp != 0x4c00) && (page_temp != 0x4d00)) {
|
// if (offset_temp <= 0x9c)
|
// temp = halrf_r32(rf, offset_temp | 0x4c00);
|
// }
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start = true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] BB addr=0x%08x mask=0x%08x val=0x%08x\n",
|
addr, mask, val);
|
|
cmd.src = RTW_MAC_BB_CMD_OFLD;
|
cmd.type = RTW_MAC_WRITE_OFLD;
|
cmd.lc = 0;
|
cmd.offset = (u16)addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
|
rf->fw_w_count++;
|
}
|
else
|
#endif
|
{
|
if (mask != MASKDWORD) {
|
ori_val = halrf_r32(rf, addr);
|
bit_shift = halrf_cal_bit_shift(mask);
|
val = ((ori_val) & (~mask)) |( ((val << bit_shift)) & mask);
|
}
|
halrf_w32(rf, addr, val);
|
}
|
rf->w_count++;
|
// if ((page_temp != 0x4c00) && (page_temp != 0x4d00)) {
|
// if (offset_temp <= 0x9c)
|
// halrf_w32(rf, offset_temp | 0x4c00, temp);
|
// }
|
}
|
|
u32 halrf_rreg(struct rf_info *rf, u32 addr, u32 mask)
|
{
|
u32 reg_val = 0, ori_val, bit_shift;
|
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
if (rf->fw_ofld_start == true)
|
halrf_write_fwofld_trigger(rf);
|
|
#endif
|
ori_val = halrf_r32(rf, addr);
|
bit_shift = halrf_cal_bit_shift(mask);
|
reg_val = (ori_val & mask) >> bit_shift;
|
rf->r_count++;
|
return reg_val;
|
}
|
|
u32 halrf_rrf(struct rf_info *rf, enum rf_path path, u32 addr, u32 mask)
|
{
|
static u32 operate2 = 0;
|
u32 val = 0;
|
|
if (_os_atomic_inc_return(rf->hal_com->drv_priv, (void*)&operate2) > 1) {
|
RF_WARNING("RF read race %x %x %x!!!!!!!!!!!!!!", path, addr, mask);
|
}
|
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
if (rf->fw_ofld_start == true)
|
halrf_write_fwofld_trigger(rf);
|
#endif
|
|
val = rtw_hal_read_rf_reg((rf)->hal_com, path, addr, mask);
|
_os_atomic_dec(rf->hal_com->drv_priv, (void*)&operate2);
|
rf->r_count++;
|
return val;
|
}
|
|
void halrf_wrf(struct rf_info *rf, enum rf_path path, u32 addr, u32 mask, u32 val)
|
{
|
static u32 operate2 = 0;
|
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
// u32 fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
u32 rtn;
|
u32 direct_addr, offset_write_rf[2] = {0xe000, 0xf000};
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
|
if (_os_atomic_inc_return(rf->hal_com->drv_priv, (void*)&operate2) > 1) {
|
RF_WARNING("RF write race %x %x %x %x!!!!!!!!!!!!!!", path, addr, mask, val);
|
}
|
|
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start = true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] RF addr=0x%08x mask=0x%08x val=0x%08x path=%d\n",
|
addr, mask, val, path);
|
|
if (addr & BIT(16)) { /*RF D-die*/
|
/*==== Calculate offset ====*/
|
addr &= 0xff;
|
direct_addr = offset_write_rf[path] + (addr << 2);
|
|
cmd.src = RTW_MAC_BB_CMD_OFLD;
|
cmd.type = RTW_MAC_WRITE_OFLD;
|
cmd.lc = 0;
|
cmd.offset = (u16)direct_addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
} else {
|
cmd.src = RTW_MAC_RF_CMD_OFLD;
|
cmd.type = RTW_MAC_WRITE_OFLD;
|
cmd.lc = 0;
|
cmd.rf_path = path;
|
cmd.offset = (u16)addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
}
|
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] cmd.src=0x%x addr=0x%x\n", cmd.src, addr);
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
|
rf->fw_w_count++;
|
} else
|
#endif
|
rtw_hal_write_rf_reg((rf)->hal_com, path, addr, mask, val);
|
|
_os_atomic_dec(rf->hal_com->drv_priv, (void*)&operate2);
|
rf->w_count++;
|
}
|
|
bool halrf_polling_bb(struct rf_info *rf, u32 addr, u32 mask, u32 val, u32 count)
|
{
|
bool result = true;
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
// u32 fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
u32 rtn;
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start = true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] Polling BB addr=0x%08x mask=0x%08x val=0x%08x\n",
|
addr, mask, val);
|
|
cmd.src = RTW_MAC_BB_CMD_OFLD;
|
cmd.type = RTW_MAC_COMPARE_OFLD;
|
cmd.lc = 0;
|
cmd.offset = (u16)addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
if (rtn == 0)
|
result = true;
|
else
|
result = false;
|
}
|
else
|
#endif
|
{
|
u32 c = 0;
|
while (halrf_rreg(rf, addr, mask) != val) {
|
c++;
|
halrf_delay_us(rf, 1);
|
if (c > count) {
|
result = false;
|
break;
|
}
|
}
|
}
|
|
return result;
|
}
|
|
bool halrf_polling_rf(struct rf_info *rf, u32 path, u32 addr, u32 mask, u32 val, u32 count)
|
{
|
bool result = true;
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
// u32 fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
|
u32 rtn;
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start = true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] Polling RF path=%d addr=0x%08x mask=0x%08x val=0x%08x\n",
|
path, addr, mask, val);
|
|
if (addr & BIT(16))
|
cmd.src = RTW_MAC_RF_DDIE_CMD_OFLD;
|
else
|
cmd.src = RTW_MAC_RF_CMD_OFLD;
|
|
|
cmd.type = RTW_MAC_COMPARE_OFLD;
|
cmd.lc = 0;
|
cmd.rf_path = path;
|
cmd.offset = (u16)addr;
|
cmd.value = val;
|
cmd.mask = mask;
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
if (rtn == 0)
|
result = true;
|
else
|
result = false;
|
}
|
else
|
#endif
|
{
|
u32 c = 0;
|
while (halrf_rrf(rf, path, addr, mask) != val) {
|
c++;
|
halrf_delay_us(rf, 1);
|
if (c > count) {
|
result = false;
|
break;
|
}
|
}
|
}
|
|
return result;
|
}
|
|
|
void halrf_delay_us(struct rf_info *rf, u32 count)
|
{
|
#if defined(HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT) || defined(HALRF_CONFIG_FW_IO_OFLD_SUPPORT)
|
struct rtw_mac_cmd cmd = {0};
|
// u32 fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
bool fw_ofld = rf->phl_com->dev_cap.io_ofld;
|
u32 rtn;
|
|
#ifdef HALRF_CONFIG_FW_DBCC_OFLD_SUPPORT
|
fw_ofld = 1;
|
#endif
|
|
if (fw_ofld == true && rf->fw_ofld_enable == true) {
|
rf->fw_ofld_start= true;
|
RF_DBG(rf, DBG_RF_FW,
|
"[FW_Ofld] ======>%s count=%d\n",
|
__func__, count);
|
|
cmd.type = RTW_MAC_DELAY_OFLD;
|
cmd.lc = 0;
|
cmd.value = count;
|
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
|
rf->fw_delay_us_count = rf->fw_delay_us_count + count;
|
}
|
else
|
#endif
|
{
|
u32 i;
|
|
for (i = 0; i < count; i++)
|
halrf_os_delay_us(rf, 1);
|
}
|
}
|
|
void halrf_fill_h2c_cmd(struct rf_info *rf, u16 cmdlen, u8 cmdid,
|
u8 classid, u32 cmdtype, u32 *pval)
|
{
|
u32 rt_val = 0;
|
struct rtw_g6_h2c_hdr hdr = {0};
|
struct rtw_hal_com_t *hal_com = NULL;
|
|
hdr.h2c_class = classid;
|
hdr.h2c_func = cmdid;
|
hdr.type = cmdtype;
|
hdr.content_len = cmdlen;
|
hal_com = rf->hal_com;
|
RF_DBG(rf, DBG_RF_IQK, "[IQK]======>%s H2C: %x %x %x\n",
|
__func__, classid, cmdid, cmdlen);
|
rt_val = rtw_hal_mac_send_h2c(hal_com, &hdr, pval);
|
if (rt_val != 0) {
|
RF_WARNING("Error H2C CLASS=%d, ID=%d\n", classid, cmdid);
|
RF_DBG(rf, DBG_RF_IQK, "Error H2C CLASS=%d, ID=%d\n", classid, cmdid);
|
}
|
}
|