/******************************************************************************
|
*
|
* Copyright(c) 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.
|
*
|
*****************************************************************************/
|
|
|
#include "halrf_precomp.h"
|
|
u32 phlrf_psd_log2base(struct rf_info *rf, u32 val)
|
{
|
u32 j;
|
u32 tmp, tmp2, val_integerd_b = 0, tindex, shiftcount = 0;
|
u32 result, val_fractiond_b = 0;
|
u32 table_fraction[21] = {
|
0, 432, 332, 274, 232, 200, 174, 151, 132, 115,
|
100, 86, 74, 62, 51, 42, 32, 23, 15, 7, 0};
|
|
if (val == 0)
|
return 0;
|
|
tmp = val;
|
|
while (1) {
|
if (tmp == 1)
|
break;
|
|
tmp = (tmp >> 1);
|
shiftcount++;
|
}
|
|
val_integerd_b = shiftcount + 1;
|
|
tmp2 = 1;
|
for (j = 1; j <= val_integerd_b; j++)
|
tmp2 = tmp2 * 2;
|
|
tmp = (val * 100) / tmp2;
|
tindex = tmp / 5;
|
|
if (tindex > 20)
|
tindex = 20;
|
|
val_fractiond_b = table_fraction[tindex];
|
|
result = val_integerd_b * 100 - val_fractiond_b;
|
|
return result;
|
}
|
|
void phlrf_rf_lna_setting(struct rf_info *rf, enum phlrf_lna_set type)
|
{
|
struct rtw_hal_com_t *hal_i = rf->hal_com;
|
|
switch (hal_i->chip_id) {
|
#ifdef RF_8852A_SUPPORT
|
case CHIP_WIFI6_8852A:
|
break;
|
#endif
|
default:
|
break;
|
}
|
|
}
|
|
void halrf_bkp(struct rf_info *rf, u32 *bp_reg, u32 *bp, u32 reg_num)
|
{
|
u32 i;
|
|
for (i = 0; i < reg_num; i++)
|
bp[i] = halrf_rreg(rf, bp_reg[i], MASKDWORD);
|
}
|
|
void halrf_bkprf(struct rf_info *rf, u32 *bp_reg, u32 bp[][4], u32 reg_num, u32 path_num)
|
{
|
u32 i, j;
|
|
for (i = 0; i < reg_num; i++) {
|
for (j = 0; j < path_num; j++)
|
bp[i][j] = halrf_rrf(rf, j, bp_reg[i], MASKRF);
|
}
|
}
|
|
void halrf_reload_bkp(struct rf_info *rf, u32 *bp_reg, u32 *bp, u32 reg_num)
|
{
|
u32 i;
|
|
for (i = 0; i < reg_num; i++)
|
halrf_wreg(rf, bp_reg[i], MASKDWORD, bp[i]);
|
}
|
|
void halrf_reload_bkprf(struct rf_info *rf,
|
u32 *bp_reg,
|
u32 bp[][4],
|
u32 reg_num,
|
u8 path_num)
|
{
|
u32 i, path;
|
|
for (i = 0; i < reg_num; i++) {
|
for (path = 0; path < path_num; path++)
|
halrf_wrf(rf, (enum rf_path)path, bp_reg[i],
|
MASKRF, bp[i][path]);
|
}
|
}
|
|
u8 halrf_kpath(struct rf_info *rf, enum phl_phy_idx phy_idx)
|
{
|
struct rtw_hal_com_t *hal_i = rf->hal_com;
|
|
u8 path = 0;
|
|
switch (hal_i->chip_id) {
|
#ifdef RF_8852A_SUPPORT
|
case CHIP_WIFI6_8852A:
|
path = halrf_kpath_8852a(rf, phy_idx);
|
break;
|
#endif
|
default:
|
break;
|
}
|
return path;
|
}
|
|
void halrf_wait_rx_mode(struct rf_info *rf, u8 kpath)
|
{
|
u8 path, rf_mode = 0;
|
u16 count = 0;
|
|
for (path = 0; path < 4; path++) {
|
if (kpath & BIT(path)) {
|
rf_mode = (u8)halrf_rrf(rf, path, 0x00, MASKRFMODE);
|
|
while (rf_mode == 2 && count < 2500) {
|
rf_mode = (u8)halrf_rrf(rf, path, 0x00, MASKRFMODE);
|
halrf_delay_us(rf, 2);
|
count++;
|
}
|
RF_DBG(rf, DBG_RF_RFK,
|
"[RFK] Wait S%d to Rx mode!! (count = %d)\n", path, count);
|
}
|
}
|
}
|
|
void halrf_tmac_tx_pause(struct rf_info *rf, enum phl_phy_idx band_idx, bool is_pause)
|
{
|
halrf_tx_pause(rf, band_idx, is_pause, PAUSE_RSON_RFK);
|
|
RF_DBG(rf, DBG_RF_RFK,"[RFK] Band%d Tx Pause %s!!\n",
|
band_idx, is_pause ? "on" : "off");
|
|
if (is_pause)
|
halrf_wait_rx_mode(rf, halrf_kpath(rf, band_idx));
|
}
|
|
void halrf_trigger_thermal(struct rf_info *rf)
|
{
|
struct rtw_hal_com_t *hal_i = rf->hal_com;
|
|
switch (hal_i->chip_id) {
|
#ifdef RF_8852A_SUPPORT
|
case CHIP_WIFI6_8852A:
|
halrf_trigger_thermal_8852a(rf, RF_PATH_A);
|
halrf_trigger_thermal_8852a(rf, RF_PATH_B);
|
break;
|
#endif
|
default:
|
break;
|
}
|
}
|
|
u8 halrf_only_get_thermal(struct rf_info *rf, enum rf_path path)
|
{
|
struct rtw_hal_com_t *hal_i = rf->hal_com;
|
|
switch (hal_i->chip_id) {
|
#ifdef RF_8852A_SUPPORT
|
case CHIP_WIFI6_8852A:
|
return halrf_only_get_thermal_8852a(rf, path);
|
break;
|
#endif
|
default:
|
break;
|
}
|
|
return 0;
|
}
|
|
void halrf_btc_rfk_ntfy(struct rf_info *rf, u8 phy_map, enum halrf_rfk_type type,
|
enum halrf_rfk_process process)
|
{
|
u32 cnt = 0;
|
u8 band;
|
/*idx : use BIT mask for RF path PATH A: 1, PATH B:2, PATH AB:3*/
|
|
band = rf->hal_com->band[(phy_map & 0x30) >> 5].cur_chandef.band;
|
|
phy_map = (band << 6) | phy_map;
|
|
RF_DBG(rf, DBG_RF_RFK, "[RFK] RFK notify (%s / PHY%d / K_type = %d / path_idx = %d / process = %s)\n",
|
band == 0 ? "2G" : (band == 1 ? "5G" : "6G"), (phy_map & 0x30) >> 5, type,
|
phy_map & 0xf, process == 0 ? "RFK_STOP" : (process == 1 ? "RFK_START" :
|
(process == 2 ? "ONE-SHOT_START" : "ONE-SHOT_STOP")));
|
#if 1
|
if (process == RFK_START && rf->is_bt_iqk_timeout == false) {
|
while (halrf_btc_ntfy(rf, phy_map, type, process) == 0 && cnt < 2500) {
|
halrf_delay_us(rf, 40);
|
cnt++;
|
}
|
if (cnt == 2500) {
|
RF_DBG(rf, DBG_RF_RFK, "[RFK] Wait BT IQK timeout!!!!\n");
|
rf->is_bt_iqk_timeout = true;
|
}
|
} else
|
halrf_btc_ntfy(rf, phy_map, type, process);
|
#endif
|
}
|
|
void halrf_fcs_init(struct rf_info *rf)
|
{
|
struct rtw_hal_com_t *hal_com = rf->hal_com;
|
|
#ifdef RF_8852A_SUPPORT
|
if (hal_com->chip_id == CHIP_WIFI6_8852A)
|
halrf_fcs_init_8852a(rf);
|
#endif
|
}
|
|
void halrf_fast_chl_sw_backup(struct rf_info *rf, u8 chl_index, u8 t_index)
|
{
|
u32 t[2];
|
|
t[0] = chl_index;
|
t[1] = t_index;
|
|
halrf_fill_h2c_cmd(rf, 8, FWCMD_H2C_BACKUP_RFK, 0xa, H2CB_TYPE_DATA, t);
|
RF_DBG(rf, DBG_RF_RFK, "FWCMD_H2C_BACKUP_RFK chl=%d t=%d\n", chl_index, t_index);
|
}
|
|
void halrf_fast_chl_sw_reload(struct rf_info *rf, u8 chl_index, u8 t_index)
|
{
|
u32 t[2];
|
|
t[0] = chl_index;
|
t[1] = t_index;
|
|
halrf_fill_h2c_cmd(rf, 8, FWCMD_H2C_RELOAD_RFK, 0xa, H2CB_TYPE_DATA, t);
|
RF_DBG(rf, DBG_RF_RFK, "FWCMD_H2C_RELOAD_RFK chl=%d t=%d\n", chl_index, t_index);
|
}
|
|
void halrf_quick_check_rf(void *rf_void)
|
{
|
struct rf_info *rf = (struct rf_info *)rf_void;
|
struct rtw_hal_com_t *hal_com = rf->hal_com;
|
|
#ifdef RF_8852A_SUPPORT
|
if (hal_com->chip_id == CHIP_WIFI6_8852A)
|
halrf_quick_check_rfrx_8852a(rf);
|
#endif
|
#ifdef RF_8852B_SUPPORT
|
if (hal_com->chip_id == CHIP_WIFI6_8852B)
|
halrf_quick_checkrf_8852b(rf);
|
#endif
|
}
|
|
void halrf_wifi_event_notify(void *rf_void,
|
enum phl_msg_evt_id event, enum phl_phy_idx phy_idx)
|
{
|
struct rf_info *rf = (struct rf_info *)rf_void;
|
|
if (event == MSG_EVT_SCAN_START) {
|
halrf_tssi_default_txagc(rf, phy_idx, true);
|
halrf_tssi_set_avg(rf, phy_idx, true);
|
halrf_dpk_track_onoff(rf, false);
|
} else if (event == MSG_EVT_SCAN_END) {
|
halrf_tssi_default_txagc(rf, phy_idx, false);
|
halrf_tssi_set_avg(rf, phy_idx, false);
|
halrf_dpk_track_onoff(rf, true);
|
} else if (event == MSG_EVT_DBG_RX_DUMP) {
|
halrf_quick_check_rf(rf);
|
} else if (event == MSG_EVT_SWCH_START) {
|
halrf_tssi_backup_txagc(rf, phy_idx, true);
|
}
|
}
|
|
void halrf_write_fwofld_start(struct rf_info *rf)
|
{
|
#ifdef HALRF_CONFIG_FW_IO_OFLD_SUPPORT
|
bool fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
|
rf->fw_ofld_enable = true;
|
|
RF_DBG(rf, DBG_RF_FW, "======> %s fw_ofld=%d rf->fw_ofld_enable=%d\n",
|
__func__, fw_ofld, rf->fw_ofld_enable);
|
#endif
|
}
|
|
void halrf_write_fwofld_end(struct rf_info *rf)
|
{
|
#ifdef HALRF_CONFIG_FW_IO_OFLD_SUPPORT
|
struct rtw_mac_cmd cmd = {0};
|
struct halrf_fw_offload *fwofld_info = &rf->fwofld;
|
bool fw_ofld = rf->phl_com->dev_cap.fw_cap.offload_cap & BIT(0);
|
u32 rtn;
|
|
RF_DBG(rf, DBG_RF_FW,
|
"======>%s src=%d type=%d lc=%d rf_path=%d\n",
|
__func__, fwofld_info->src, fwofld_info->type,
|
fwofld_info->lc, fwofld_info->rf_path);
|
|
RF_DBG(rf, DBG_RF_FW,
|
"======>%s offset=0x%x mask=0x%x value=0x%x fw_ofld=%d\n",
|
__func__, fwofld_info->offset, fwofld_info->mask,
|
fwofld_info->value, fw_ofld);
|
|
cmd.src = fwofld_info->src;
|
cmd.type = fwofld_info->type;
|
cmd.lc = 1;
|
cmd.rf_path = fwofld_info->rf_path;
|
cmd.offset = fwofld_info->offset;
|
cmd.value = fwofld_info->value;
|
cmd.mask = fwofld_info->mask;
|
|
if (fw_ofld) {
|
rtn = halrf_mac_add_cmd_ofld(rf, &cmd);
|
if (rtn) {
|
RF_WARNING("======>%s return fail error code = %d !!!\n",
|
__func__, rtn);
|
}
|
}
|
|
rf->fw_ofld_enable = false;
|
#endif
|
}
|
|
void halrf_ctrl_bw_ch(void *rf_void, enum phl_phy_idx phy, u8 central_ch,
|
enum band_type band, enum channel_width bw)
|
{
|
struct rf_info *rf = (struct rf_info *)rf_void;
|
|
halrf_ctl_ch(rf, central_ch);
|
halrf_ctl_bw(rf, bw);
|
halrf_rxbb_bw(rf, phy, bw);
|
}
|
|
u32 halrf_test_event_trigger(void *rf_void,
|
enum phl_phy_idx phy, enum halrf_event_idx idx, enum halrf_event_func func) {
|
|
struct rf_info *rf = (struct rf_info *)rf_void;
|
|
switch (idx) {
|
case RF_EVENT_PWR_TRK:
|
if (func == RF_EVENT_OFF)
|
halrf_tssi_disable(rf, phy);
|
else if (func == RF_EVENT_ON)
|
halrf_tssi_enable(rf, phy);
|
else if (func == RF_EVENT_TRIGGER)
|
halrf_tssi_trigger(rf, phy);
|
break;
|
|
case RF_EVENT_IQK:
|
if (func == RF_EVENT_OFF)
|
halrf_iqk_onoff(rf, true);
|
else if (func == RF_EVENT_ON)
|
halrf_iqk_onoff(rf, false);
|
else if (func == RF_EVENT_TRIGGER) {
|
halrf_nbiqk_enable(rf, false);
|
halrf_iqk_trigger(rf, phy, false);
|
}
|
break;
|
|
case RF_EVENT_DPK:
|
if (func == RF_EVENT_OFF)
|
halrf_dpk_onoff(rf, false);
|
else if (func == RF_EVENT_ON)
|
halrf_dpk_onoff(rf, true);
|
else if (func == RF_EVENT_TRIGGER)
|
halrf_dpk_trigger(rf, phy, false);
|
break;
|
|
case RF_EVENT_TXGAPK:
|
if (func == RF_EVENT_OFF)
|
halrf_gapk_disable(rf, phy);
|
else if (func == RF_EVENT_ON)
|
halrf_gapk_enable(rf, phy);
|
else if (func == RF_EVENT_TRIGGER)
|
halrf_gapk_trigger(rf, phy, true);
|
break;
|
|
case RF_EVENT_DACK:
|
if (func == RF_EVENT_OFF)
|
halrf_dack_onoff(rf, false);
|
else if (func == RF_EVENT_ON)
|
halrf_dack_onoff(rf, true);
|
else if (func == RF_EVENT_TRIGGER)
|
halrf_dack_trigger(rf, true);
|
break;
|
|
default:
|
break;
|
}
|
return 0;
|
}
|