/******************************************************************************
|
*
|
* Copyright(c) 2016 - 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.
|
*
|
*****************************************************************************/
|
#define _RTL8852B_BTC_C_
|
|
#include "../../hal_headers_le.h"
|
#include "../hal_btc.h"
|
|
#ifdef CONFIG_BTCOEX
|
#ifdef CONFIG_RTL8852B
|
|
#include "btc_8852b.h"
|
|
/* WL rssi threshold in % (dbm = % - 110)
|
* array size limit by BTC_WL_RSSI_THMAX
|
* BT rssi threshold in % (dbm = % - 100)
|
* array size limit by BTC_BT_RSSI_THMAX
|
*/
|
static const u8 btc_8852b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {60, 50, 40, 30};
|
static const u8 btc_8852b_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {40, 36, 31, 28};
|
|
static struct btc_chip_ops btc_8852b_ops = {
|
_8852b_rfe_type,
|
_8852b_init_cfg,
|
_8852b_wl_pri,
|
_8852b_wl_tx_power,
|
_8852b_wl_rx_gain,
|
_8852b_wl_s1_standby,
|
_8852b_wl_req_mac,
|
_8852b_update_bt_cnt,
|
_8852b_bt_rssi
|
};
|
|
/* Set WL/BT periodical moniter reg, Max size: CXMREG_MAX*/
|
static struct fbtc_mreg btc_8852b_mon_reg[] = {
|
{REG_MAC, 4, 0xda24},
|
{REG_MAC, 4, 0xda28},
|
{REG_MAC, 4, 0xda2c},
|
{REG_MAC, 4, 0xda30},
|
{REG_MAC, 4, 0xda4c},
|
{REG_MAC, 4, 0xda10},
|
{REG_MAC, 4, 0xda20},
|
{REG_MAC, 4, 0xda34},
|
{REG_MAC, 4, 0xcef4},
|
{REG_MAC, 4, 0x8424},
|
{REG_MAC, 4, 0xd200},
|
{REG_MAC, 4, 0xd220},
|
{REG_BB, 4, 0x980},
|
/*{REG_RF, 2, 0x2},*/ /* for RF, bytes->path, 1:A, 2:B... */
|
/*{REG_RF, 2, 0x18},*/
|
/*{REG_BT_RF, 2, 0x9},*/
|
/*{REG_BT_MODEM, 2, 0xa} */
|
};
|
|
/* wl_tx_power: 255->original, else-> bit7:signed bit, ex: 13:13dBm, 0x85:-5dBm
|
* wl_rx_gain: 0->original, 1-> for Free-run, 2-> for BTG co-rx
|
* bt_tx_power: decrease power, 0->original, 5 -> decreas 5dB.
|
* bt_rx_gain: BT LNA constrain Level, 7->original
|
*/
|
|
struct btc_rf_trx_para btc_8852b_rf_ul[] = {
|
{255, 0, 0, 7}, /* 0 -> original */
|
{255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
|
{255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
|
{255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
|
{255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
|
{255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */
|
{6, 1, 0, 7},
|
{13, 1, 0, 7},
|
{13, 1, 0, 7}
|
};
|
|
struct btc_rf_trx_para btc_8852b_rf_dl[] = {
|
{255, 0, 0, 7}, /* 0 -> original */
|
{255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
|
{255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
|
{255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
|
{255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
|
{255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */
|
{255, 1, 0, 7},
|
{255, 1, 0, 7},
|
{255, 1, 0, 7}
|
};
|
|
const struct btc_chip chip_8852b = {
|
CHIP_WIFI6_8852B, /* chip id */
|
0x0, /* chip para ver */
|
0x6, /* desired bt_ver */
|
0x06010000, /* desired halbtc ver */
|
0x1, /* scoreboard version */
|
0x1, /* mailbox version*/
|
BTC_COEX_RTK_MODE, /* pta_mode */
|
BTC_COEX_INNER, /* pta_direction */
|
6, /* afh_guard_ch */
|
btc_8852b_wl_rssi_thres, /* wl rssi threshold level */
|
btc_8852b_bt_rssi_thres, /* bt rssi threshold level */
|
(u8)2, /* rssi tolerance */
|
&btc_8852b_ops, /* chip-dependent function */
|
ARRAY_SIZE(btc_8852b_mon_reg),
|
btc_8852b_mon_reg, /* wl moniter register */
|
ARRAY_SIZE(btc_8852b_rf_ul),
|
btc_8852b_rf_ul,
|
ARRAY_SIZE(btc_8852b_rf_dl),
|
btc_8852b_rf_dl
|
};
|
|
void _8852b_rfe_type(struct btc_t *btc)
|
{
|
struct rtw_phl_com_t *p = btc->phl;
|
struct rtw_hal_com_t *h = btc->hal;
|
struct btc_module *module = &btc->mdinfo;
|
|
PHL_INFO("[BTC], %s !! \n", __FUNCTION__);
|
|
module->rfe_type = p->dev_cap.rfe_type;/* get from final capability of device */
|
module->kt_ver = h->cv;
|
module->bt_solo = 0;
|
module->switch_type = BTC_SWITCH_INTERNAL;
|
|
#if BTC_NON_SHARED_ANT_FREERUN
|
module->ant.num = 3;
|
#else
|
if (module->rfe_type > 0)
|
module->ant.num = (module->rfe_type % 2? 2 : 3);
|
else
|
module->ant.num = 2;
|
#endif
|
module->ant.diversity = 0;
|
module->ant.isolation = 10;
|
|
if (module->ant.num == 3) {
|
module->ant.type = BTC_ANT_DEDICATED;
|
module->bt_pos = BTC_BT_ALONE;
|
} else {
|
module->ant.type = BTC_ANT_SHARED;
|
module->bt_pos = BTC_BT_BTG;
|
}
|
}
|
|
void _8852b_wl_tx_power(struct btc_t *btc, u32 level)
|
{
|
/*
|
* =========== All-Time WL Tx power control ===========
|
* (ex: all-time fix WL Tx 10dBm , don¡¦t care GNT _BT and GNT _LTE)
|
* Turn off per-packet power control
|
* 0xD220[1] = 0, 0xD220[2] = 0;
|
*
|
* disable using related power table
|
* 0xd208[20] = 0, 0xd208[21] = 0, 0xd21c[17] = 0, 0xd20c[29] = 0;
|
*
|
* enable force tx power mode and value
|
* 0xD200[9] = 1;
|
* 0xD200[8:0] = 0x28; S(9,2): 1step= 0.25dB, i.e. 40*0.25 = 10 dBm
|
* =======================================================
|
*
|
* =========== per-packet Tx power control ===========
|
* (ex: GNT_BT = 1 -> 5dBm, GNT _BT = 0 -> 10dBm)
|
* Turn on per-packet power control
|
* 0xD220[1] = 1, 0xD220[2] = 0;
|
* 0xD220[11:3] = 0x14; S(9,2): 1step = 0.25dB, i.e. 20*0.25 = 5 dBm
|
*
|
* disable using related power table
|
* 0xd208[20] = 0, 0xd208[21] = 0, 0xd21c[17] = 0, 0xd20c[29] = 0;
|
*
|
* enable force tx power mode and value
|
* 0xD200[9] = 1;
|
* 0xD200[8:0] = 0x28; S(9,2), sign, 1 step = 0.25dB, i.e. 40*0.25 = 10 dBm
|
* =========================================================================
|
*
|
* level define:
|
* if level = 255 -> back to original (btc don't control)
|
* else in dBm --> bit7->signed bit, ex: 0xa-> +10dBm, 0x85-> -5dBm
|
* pwr_val define:
|
bit15~0 --> All-time (GNT_BT = 0) Tx power control
|
bit31~16 --> Per-Packet (GNT_BT = 1) Tx power control
|
*/
|
u32 pwr_val;
|
|
if (level == BTC_WL_DEF_TX_PWR) { /* back to original */
|
pwr_val = bMASKDW;
|
} else { /* only apply "force tx power" */
|
pwr_val = (level & 0x7f) << 2; /* to fit s(9,2) format */
|
if (pwr_val > BTC_WL_DEF_TX_PWR)
|
pwr_val = BTC_WL_DEF_TX_PWR;
|
|
if (level & BIT(7)) /* negative value */
|
pwr_val |= BIT(8); /* to fit s(9,2) format */
|
pwr_val |= bMASKHW;
|
}
|
|
rtw_hal_rf_wl_tx_power_control(btc->hal, pwr_val);
|
}
|
|
void _8852b_set_wl_lna2(struct btc_t *btc, u8 level)
|
{
|
/* level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB
|
* level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
|
* To improve BT ACI in co-rx
|
*/
|
#if 0 /* RDC: disable this function for A-cut RxA TIA gain bug,
|
* it should be enabled for B-cut if nug fixed */
|
switch (level) {
|
case 0: /* default */
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x1000);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x33, bMASKRF, 0x3);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x17);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x33, bMASKRF, 0x2);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x15);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x0);
|
break;
|
case 1: /* Fix LNA2=5 */
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x1000);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x33, bMASKRF, 0x3);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x5);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x33, bMASKRF, 0x2);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x15);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x0);
|
break;
|
}
|
#endif
|
}
|
|
void _8852b_wl_rx_gain(struct btc_t *btc, u32 level)
|
{
|
/* wl bb setting for FDD -> rtw_hal_bb_ctrl_btc_preagc()
|
* OP1db Back-off(no LNA6) + Fixed TIA corner + RX_BB Back-off +
|
* DFIR Type 3
|
*/
|
|
switch (level) {
|
case 0: /* original */
|
rtw_hal_bb_ctrl_btc_preagc(btc->hal, false);
|
/* _8852b_set_wl_lna2(btc, 0); */
|
break;
|
case 1: /* for FDD free-run */
|
rtw_hal_bb_ctrl_btc_preagc(btc->hal, true);
|
/* _8852b_set_wl_lna2(btc, 0); */
|
break;
|
case 2: /* for BTG Co-Rx*/
|
rtw_hal_bb_ctrl_btc_preagc(btc->hal, false);
|
/* _8852b_set_wl_lna2(btc, 1); */
|
break;
|
}
|
}
|
|
u8 _8852b_bt_rssi(struct btc_t *btc, u8 val)
|
{
|
val = (val <= 127? 100 : (val >= 156? val - 156 : 0));
|
val = val + 6; /* compensate offset */
|
|
if (val > 100)
|
val = 100;
|
|
return (val);
|
}
|
|
void _8852b_set_wl_trx_mask(struct btc_t *btc, u8 path, u8 group, u32 val)
|
{
|
_write_wl_rf_reg(btc, path, 0xef, bMASKRF, 0x20000);
|
_write_wl_rf_reg(btc, path, 0x33, bMASKRF, group);
|
_write_wl_rf_reg(btc, path, 0x3f, bMASKRF, val);
|
_write_wl_rf_reg(btc, path, 0xef, bMASKRF, 0x0);
|
}
|
|
void _8852b_wl_s1_standby(struct btc_t *btc, u32 state)
|
{
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x80000);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x33, bMASKRF, 0x1);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3e, bMASKRF, 0x31);
|
|
/* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */
|
if (state == 1)
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x00579);
|
else
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x3f, bMASKRF, 0x00020);
|
|
_write_wl_rf_reg(btc, RF_PATH_B, 0xef, bMASKRF, 0x0);
|
}
|
|
void _8852b_wl_req_mac(struct btc_t *btc, u8 mac_id)
|
{
|
u32 val1;
|
|
val1 = _read_cx_reg(btc, R_BTC_CFG);
|
|
if (mac_id == HW_PHY_0)
|
val1 = val1 & (~B_BTC_WL_SRC);
|
else
|
val1 = val1 | B_BTC_WL_SRC;
|
|
_write_cx_reg(btc, R_BTC_CFG, val1);
|
}
|
|
void _8852b_update_bt_cnt(struct btc_t *btc)
|
{
|
struct btc_cx *cx = &btc->cx;
|
u32 val, val1;
|
|
val = _read_cx_reg(btc, R_BTC_BT_STAST_HIGH);
|
cx->cnt_bt[BTC_BCNT_HIPRI_TX] = val & bMASKLW;
|
cx->cnt_bt[BTC_BCNT_HIPRI_RX] = (val & bMASKHW) >> 16;
|
|
val = _read_cx_reg(btc, R_BTC_BT_STAST_LOW);
|
cx->cnt_bt[BTC_BCNT_LOPRI_TX] = val & bMASKLW;
|
cx->cnt_bt[BTC_BCNT_LOPRI_RX] = (val & bMASKHW) >> 16;
|
|
/* clock-gate off before reset counter*/
|
val1 = _read_cx_reg(btc, R_BTC_CFG);
|
_write_cx_reg(btc, R_BTC_CFG, val1 | B_BTC_DIS_BTC_CLK_G);
|
|
val = _read_cx_reg(btc, R_BTC_CSR_MODE);
|
_write_cx_reg(btc, R_BTC_CSR_MODE, val & (~B_BTC_BT_CNT_REST));
|
_write_cx_reg(btc, R_BTC_CSR_MODE, val | B_BTC_BT_CNT_REST);
|
|
_write_cx_reg(btc, R_BTC_CFG, val1 & (~B_BTC_DIS_BTC_CLK_G));
|
}
|
|
void _8852b_init_cfg(struct btc_t *btc)
|
{
|
struct rtw_hal_com_t *h = btc->hal;
|
struct btc_module *module = &btc->mdinfo;
|
u32 val = 0;
|
|
PHL_INFO("[BTC], %s !! \n", __FUNCTION__);
|
|
/* PTA init */
|
rtw_hal_mac_coex_init(h, chip_8852b.pta_mode, chip_8852b.pta_direction);
|
|
/* set WL Tx response = Hi-Pri */
|
btc->chip->ops->wl_pri(btc, BTC_PRI_MASK_TX_RESP, true);
|
|
/* set WL Tx beacon = Hi-Pri */
|
btc->chip->ops->wl_pri(btc, BTC_PRI_MASK_BEACON, true);
|
|
/* set rf gnt debug off*/
|
_write_wl_rf_reg(btc, RF_PATH_A, 0x2, bMASKRF, 0x0);
|
_write_wl_rf_reg(btc, RF_PATH_B, 0x2, bMASKRF, 0x0);
|
|
/* set WL Tx thru in TRX mask table if GNT_WL=0 && BT_S1=ss group */
|
if (module->ant.type == BTC_ANT_SHARED) {
|
_8852b_set_wl_trx_mask(btc, RF_PATH_A, BTC_BT_SS_GROUP, 0x5ff);
|
_8852b_set_wl_trx_mask(btc, RF_PATH_B, BTC_BT_SS_GROUP, 0x5ff);
|
/* set path-A(S0) Tx/Rx no-mask if GNT_WL=0 && BT_S1=tx group */
|
_8852b_set_wl_trx_mask(btc, RF_PATH_A, BTC_BT_TX_GROUP, 0x5ff);
|
} else { /* set WL Tx stb if GNT_WL = 0 && BT_S1 = ss group for 3-ant */
|
_8852b_set_wl_trx_mask(btc, RF_PATH_A, BTC_BT_SS_GROUP, 0x5df);
|
_8852b_set_wl_trx_mask(btc, RF_PATH_B, BTC_BT_SS_GROUP, 0x5df);
|
}
|
|
/* set PTA break table */
|
_write_cx_reg(btc, R_BTC_BREAK_TABLE, 0xf0ffffff);
|
|
/* enable BT counter 0xda40[16,2] = 2b'11 */
|
val = _read_cx_reg(btc, R_BTC_CSR_MODE);
|
_write_cx_reg(btc, R_BTC_CSR_MODE, val | BIT16 | BIT2);
|
}
|
|
void _8852b_wl_pri (struct btc_t *btc, u8 map, bool state)
|
{
|
u32 reg = 0, bitmap = 0, val = 0;
|
|
switch (map) {
|
case BTC_PRI_MASK_TX_RESP:
|
reg = R_BTC_BT_COEX_MSK_TABLE;
|
bitmap = B_BTC_PRI_MASK_TX_RESP_V1;
|
break;
|
case BTC_PRI_MASK_BEACON:
|
reg = R_BTC_WL_PRI_MSK;
|
bitmap = B_BTC_PTA_WL_PRI_MASK_BCNQ;
|
break;
|
case BTC_PRI_MASK_RX_CCK:
|
reg = R_BTC_BT_COEX_MSK_TABLE;
|
bitmap = B_BTC_PRI_MASK_RXCCK_V1;
|
break;
|
}
|
|
val = _read_cx_reg(btc, reg);
|
if (state)
|
val = val | bitmap;
|
else
|
val = val & (~bitmap);
|
|
_write_cx_reg(btc, reg, val);
|
}
|
|
#endif /* CONFIG_RTL8852B */
|
#endif
|