/******************************************************************************
|
*
|
* 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.
|
*
|
*****************************************************************************/
|
#define _HAL_BTC_DBG_CMD_C_
|
#include "../hal_headers_le.h"
|
#include "hal_btc.h"
|
#include "halbtc_fw.h"
|
#include "halbtc_fwdef.h"
|
#include "halbtc_action.h"
|
#include "halbtc_def.h"
|
|
#ifdef CONFIG_BTCOEX
|
|
#define BTC_CNSL(max_buff_len, used_len, buff_addr, remain_len, fmt, ...)\
|
do { \
|
u32 *used_len_tmp = &(used_len); \
|
if (*used_len_tmp < max_buff_len) \
|
*used_len_tmp += _os_snprintf(buff_addr, remain_len, fmt, ##__VA_ARGS__);\
|
} while (0)
|
|
|
struct halbtc_cmd_info {
|
char name[16];
|
u8 id;
|
};
|
|
enum HALBTC_CMD_ID {
|
HALBTC_HELP,
|
HALBTC_SHOW,
|
HALBTC_READ_BT,
|
HALBTC_WRITE_BT,
|
HALBTC_SET_COEX,
|
HALBTC_UPDATE_POLICY,
|
HALBTC_TDMA,
|
HALBTC_SLOT,
|
HALBTC_SIG_GDBG_EN,
|
HALBTC_SGPIO_MAP,
|
HALBTC_TRACE_STEP,
|
HALBTC_WL_TX_POWER,
|
HALBTC_WL_RX_LNA,
|
HALBTC_BT_AFH_MAP,
|
HALBTC_BT_TX_POWER,
|
HALBTC_BT_RX_LNA,
|
HALBTC_BT_IGNO_WLAN,
|
HALBTC_SET_GNT_WL,
|
HALBTC_SET_GNT_BT,
|
HALBTC_SET_BT_PSD,
|
HALBTC_GET_WL_NHM_DBM,
|
HALBTC_SET_WL_TX1SS,
|
HALBTC_DBG
|
};
|
|
struct halbtc_cmd_info halbtc_cmd_i[] = {
|
{"-h", HALBTC_HELP},
|
{"show", HALBTC_SHOW},
|
{"rb", HALBTC_READ_BT},
|
{"wb", HALBTC_WRITE_BT},
|
{"mode", HALBTC_SET_COEX},
|
{"update", HALBTC_UPDATE_POLICY},
|
{"tdma", HALBTC_TDMA},
|
{"slot", HALBTC_SLOT},
|
{"sig", HALBTC_SIG_GDBG_EN},
|
{"gpio", HALBTC_SGPIO_MAP},
|
{"wpwr", HALBTC_WL_TX_POWER},
|
{"wlna", HALBTC_WL_RX_LNA},
|
{"afh", HALBTC_BT_AFH_MAP},
|
{"bpwr", HALBTC_BT_TX_POWER},
|
{"blna", HALBTC_BT_RX_LNA},
|
{"igwl", HALBTC_BT_IGNO_WLAN},
|
{"gwl", HALBTC_SET_GNT_WL},
|
{"gbt", HALBTC_SET_GNT_BT},
|
{"bpsd", HALBTC_SET_BT_PSD},
|
{"wnhm", HALBTC_GET_WL_NHM_DBM},
|
{"wtx1ss", HALBTC_SET_WL_TX1SS},
|
{"dbg", HALBTC_DBG}
|
};
|
|
static void _cmd_rb(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 i = 0, type = 0, addr = 0;
|
|
if (input_num < 3)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &type);
|
_os_sscanf(input[2], "%x", &addr);
|
|
if (type > 4)
|
goto help;
|
|
btc->dbg.rb_done = false;
|
btc->dbg.rb_val = 0xffffffff;
|
_read_bt_reg(btc, (u8)(type), (u16)addr);
|
for (i = 0; i < 50; i++) {
|
if (!btc->dbg.rb_done)
|
hal_mdelay(btc->hal, 10);
|
else
|
goto exit;
|
}
|
|
exit:
|
if (!btc->dbg.rb_done) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" timeout !! \n");
|
} else {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" rb %d(0x%x), val = 0x%x !! \n", type, addr, btc->dbg.rb_val);
|
}
|
return;
|
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" rb <type --- 0:rf, 1:modem, 2:bluewize, 3:vendor, 4:LE> <addr:16bits> \n");
|
return;
|
}
|
|
static void _show_cx_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_dm *dm = &btc->dm;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct rtw_hal_com_t *h = btc->hal;
|
u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
|
|
if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
|
return;
|
|
dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r========== [BTC COEX INFO (%s)] ==========",
|
id_to_str(BTC_STR_CHIPID, (u32)btc->chip->chip_id));
|
|
ver_main = (coex_ver & bMASKB3) >> 24;
|
ver_sub = (coex_ver & bMASKB2) >> 16;
|
ver_hotfix = (coex_ver & bMASKB1) >> 8;
|
id_branch = coex_ver & bMASKB0;
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : Coex:%d.%d.%d(branch:%d), ",
|
"[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
|
|
ver_main = (wl->ver_info.fw_coex & bMASKB3) >> 24;
|
ver_sub = (wl->ver_info.fw_coex & bMASKB2) >> 16;
|
ver_hotfix = (wl->ver_info.fw_coex & bMASKB1) >> 8;
|
id_branch = wl->ver_info.fw_coex & bMASKB0;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"WL_FW_coex:%d.%d.%d(branch:%d)",
|
ver_main, ver_sub, ver_hotfix, id_branch);
|
|
ver_main = (btc->chip->wlcx_desired & bMASKB3) >> 24;
|
ver_sub = (btc->chip->wlcx_desired & bMASKB2) >> 16;
|
ver_hotfix = (btc->chip->wlcx_desired & bMASKB1) >> 8;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"(%s, desired:%d.%d.%d), ",
|
(wl->ver_info.fw_coex >= btc->chip->wlcx_desired ?
|
"Match" : "Mis-Match"),
|
ver_main, ver_sub, ver_hotfix);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"BT_FW_coex:%d(%s, desired:%d)",
|
bt->ver_info.fw_coex,
|
(bt->ver_info.fw_coex >= btc->chip->btcx_desired ?
|
"Match" : "Mis-Match"),
|
btc->chip->btcx_desired);
|
|
if (bt->enable.now && bt->ver_info.fw == 0)
|
hal_btc_fw_en_rpt(btc, RPT_EN_BT_VER_INFO, 1);
|
else
|
hal_btc_fw_en_rpt(btc, RPT_EN_BT_VER_INFO, 0);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)",
|
"[sub_module]", (wl->ver_info.fw & bMASKB3) >> 24,
|
(wl->ver_info.fw & bMASKB2) >> 16,
|
(wl->ver_info.fw & bMASKB1) >> 8,
|
(wl->ver_info.fw & bMASKB0), bt->ver_info.fw,
|
(bt->run_patch_code ? "patch" : "ROM"));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : kt_ver:%x, rfe_type:0x%x, hw_id:0x%x, ant_iso:%d, ant_pg:%d, %s",
|
"[hw_info]", btc->mdinfo.kt_ver, btc->mdinfo.rfe_type,
|
((btc->phl->id.id & 0xff00) >> 8),
|
btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
|
(btc->mdinfo.ant.num > 1? "" : (btc->mdinfo.ant.single_pos?
|
"1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d",
|
btc->cx.other.type, h->dbcc_en, h->rfpath_tx_num,
|
h->rfpath_rx_num);
|
}
|
|
static void _show_wl_role_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_wl_link_info *plink = NULL;
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
|
struct btc_traffic t;
|
u8 i;
|
|
if (btc->hal->dbcc_en) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
|
"[dbcc_info]", wl_dinfo->op_band[HW_PHY_0],
|
wl_dinfo->scan_band[HW_PHY_0],
|
wl_dinfo->real_band[HW_PHY_0]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"PHY1_band(op:%d/scan:%d/real:%d)",
|
wl_dinfo->op_band[HW_PHY_1],
|
wl_dinfo->scan_band[HW_PHY_1],
|
wl_dinfo->real_band[HW_PHY_1]);
|
}
|
|
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
|
plink = &btc->cx.wl.link_info[i];
|
|
if (!plink->active)
|
continue;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r [port_%d] : role=%s(phy-%d), connect=%s(client_cnt=%d), mode=%s, ch=(ct:%d/pr:%d), bw=%s",
|
plink->pid,
|
id_to_str(BTC_STR_ROLE, (u32)plink->role),
|
plink->phy,
|
id_to_str(BTC_STR_MSTATE, (u32)plink->connected),
|
plink->client_cnt-1,
|
id_to_str(BTC_STR_WLMODE, (u32)plink->mode),
|
plink->chdef.center_ch, plink->chdef.chan,
|
id_to_str(BTC_STR_WLBW, (u32)plink->chdef.bw));
|
|
if (plink->connected == MLME_NO_LINK)
|
continue;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", mac_id=%d, noa(%d)=%d.%03dms",
|
plink->mac_id, plink->noa,
|
plink->noa_duration/1000, plink->noa_duration%1000);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
|
plink->pid, 110-plink->stat.rssi,
|
plink->stat.rssi, plink->busy,
|
(plink->dir == TRAFFIC_UL ? "UL" : "DL"));
|
|
t = plink->stat.traffic;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"tx[rate:%s/busy_level:%d/sts:0x%x/1ss:%s], ",
|
id_to_str(BTC_STR_RATE, (u32)t.tx_rate),
|
t.tx_lvl, t.tx_sts, (t.tx_1ss_limit ? "Y" : "N"));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"rx[rate:%s/busy_level:%d/sts:0x%x/drop:%d]",
|
id_to_str(BTC_STR_RATE, (u32)t.rx_rate),
|
t.rx_lvl, t.rx_sts, plink->rx_rate_drop_cnt);
|
}
|
}
|
|
static void _show_wl_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_cx *cx = &btc->cx;
|
struct btc_wl_info *wl = &cx->wl;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
|
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r========== [WL Status] ==========");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : link_mode:%s, mrole:%s, ",
|
"[status]",
|
id_to_str(BTC_STR_WLLINK, (u32)wl_rinfo->link_mode),
|
id_to_str(BTC_STR_MROLE, wl_rinfo->mrole_type));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"rf_off:%s, power_save:%d, init_ok:%s, nhm:%d(status=%d, ratio:%d)",
|
(wl->status.map.rf_off? "Y" : "N"),
|
wl->status.map.lps,
|
(wl->status.map.init_ok? "Y" : "N"),
|
wl->nhm.pwr,
|
wl->nhm.current_status, wl->nhm.ratio);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : scan:%s(band:%d/phy_map:0x%x), connecting:%s, roam:%s, 4way:%s",
|
"[scan]", (wl->status.map.scan? "Y" : "N"),
|
wl->scan_info.band[HW_PHY_0], wl->scan_info.phy_map,
|
(wl->status.map.connecting? "Y" : "N"),
|
(wl->status.map.roaming? "Y" : "N"),
|
(wl->status.map._4way? "Y" : "N"));
|
|
_show_wl_role_info(btc, used, input, input_num, output, out_len);
|
}
|
|
static void _show_dm_step(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_dm *dm = &btc->dm;
|
u32 n_begin = 0, n_end = 0, i = 0, cnt = 0;
|
u32 step_cnt = dm->dm_step.cnt;
|
|
if (step_cnt == 0)
|
return;
|
|
if (step_cnt <= BTC_DM_MAXSTEP)
|
n_begin = 1;
|
else
|
n_begin = step_cnt - BTC_DM_MAXSTEP + 1;
|
|
n_end = step_cnt;
|
|
if (n_begin > n_end)
|
return;
|
|
for (i = n_begin; i <= n_end; i++) {
|
if (cnt % 6 == 0)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : ", "[dm_steps]");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"-> %s", dm->dm_step.step[(i-1) % BTC_DM_MAXSTEP]);
|
cnt++;
|
}
|
}
|
|
static void _show_bt_profile_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
|
struct btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
|
struct btc_bt_hid_desc hid = bt_linfo->hid_desc;
|
struct btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
|
struct btc_bt_pan_desc pan = bt_linfo->pan_desc;
|
|
if (hfp.exist) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
|
"[HFP]",
|
(hfp.type == 0? "SCO" : "eSCO"),
|
bt_linfo->sut_pwr_level[0],
|
bt_linfo->golden_rx_shift[0]);
|
}
|
|
if (hid.exist) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d",
|
"[HID]",
|
(hid.type == BTC_HID_218? "2/18," : ""),
|
(hid.type & BTC_HID_418? "4/18," : ""),
|
(hid.type & BTC_HID_BLE? "BLE," : ""),
|
(hid.type & BTC_HID_RCU? "RCU," : ""),
|
(hid.type & BTC_HID_RCU_VOICE? "RCU-Voice," : ""),
|
hid.pair_cnt, bt_linfo->sut_pwr_level[1],
|
bt_linfo->golden_rx_shift[1]);
|
}
|
|
if (a2dp.exist) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
|
"[A2DP]",
|
(a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS"),
|
a2dp.bitpool, a2dp.flush_time);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d",
|
a2dp.vendor_id, a2dp.device_name,
|
bt_linfo->sut_pwr_level[2],
|
bt_linfo->golden_rx_shift[2]);
|
}
|
|
if (pan.exist) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : sut_pwr:%d, golden-rx:%d",
|
"[PAN]",
|
bt_linfo->sut_pwr_level[3],
|
bt_linfo->golden_rx_shift[3]);
|
}
|
}
|
|
static void _show_bt_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_cx *cx = &btc->cx;
|
struct btc_bt_info *bt = &cx->bt;
|
struct btc_wl_info *wl = &cx->wl;
|
struct btc_module *module = &btc->mdinfo;
|
struct btc_bt_link_info *bt_linfo = &bt->link_info;
|
u8 *afh = bt_linfo->afh_map;
|
|
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"%s", "\n\r========== [BT Status] ==========");
|
|
/*bt->btg_type = (bt->ver_info.fw & BIT(28) ? BTC_BT_BTG: BTC_BT_ALONE);*/
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : enable:%s, btg:%s%s, connect:%s, ",
|
"[status]", (bt->enable.now? "Y" : "N"),
|
(bt->btg_type? "Y" : "N"),
|
(bt->enable.now && (bt->btg_type != module->bt_pos)?
|
"(efuse-mismatch!!)" : ""),
|
(bt_linfo->status.map.connect? "Y" : "N"));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x",
|
(bt->igno_wl? "Y" : "N"),
|
(bt->mbx_avl? "Y" : "N"), bt->rfk_info.val);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : profile:%s%s%s%s%s ",
|
"[profile]",
|
((bt_linfo->profile_cnt.now == 0) ? "None," : ""),
|
(bt_linfo->hfp_desc.exist? "HFP," : ""),
|
(bt_linfo->hid_desc.exist? "HID," : ""),
|
(bt_linfo->a2dp_desc.exist?
|
(bt_linfo->a2dp_desc.sink ? "A2DP_sink," :"A2DP,") : ""),
|
(bt_linfo->pan_desc.exist? "PAN," : ""));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s",
|
(bt_linfo->multi_link.now? "Y" : "N"),
|
(bt_linfo->slave_role ? "Slave" : "Master"),
|
(bt_linfo->status.map.ble_connect? "Y" : "N"),
|
(bt_linfo->cqddr? "Y" : "N"),
|
(bt_linfo->a2dp_desc.active? "Y" : "N"),
|
(bt_linfo->pan_desc.active? "Y" : "N"));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s%s",
|
"[link]", bt_linfo->rssi-100,
|
(bt_linfo->tx_3M? 3 : 2),
|
(bt->pag? " paging!!" : ""),
|
(bt->inq? " inquirying!!" : ""),
|
(bt_linfo->status.map.acl_busy? " acl_busy!!" : ""),
|
(bt_linfo->status.map.mesh_busy? " mesh_busy!!" : ""));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
|
(bt_linfo->relink.now? " ReLink!!" : ""),
|
afh[0], afh[1], afh[2], afh[3], afh[4],
|
afh[5], afh[6], afh[7], afh[8], afh[9]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"wl_ch_map[en:%d/ch:%d/bw:%d]",
|
wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
|
"[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
|
cx->cnt_bt[BTC_BCNT_RELINK],
|
cx->cnt_bt[BTC_BCNT_RATECHG],
|
cx->cnt_bt[BTC_BCNT_REINIT],
|
cx->cnt_bt[BTC_BCNT_REENABLE]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d",
|
cx->cnt_bt[BTC_BCNT_ROLESW],
|
cx->cnt_bt[BTC_BCNT_AFH],
|
cx->cnt_bt[BTC_BCNT_INQPAG],
|
cx->cnt_bt[BTC_BCNT_INQ],
|
cx->cnt_bt[BTC_BCNT_PAGE],
|
cx->cnt_bt[BTC_BCNT_IGNOWL]);
|
|
_show_bt_profile_info(btc, used, input, input_num, output, out_len);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
|
"[bt_info]",
|
bt->raw_info[2], bt->raw_info[3],
|
bt->raw_info[4], bt->raw_info[5],
|
bt->raw_info[6], bt->raw_info[7],
|
(bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply"),
|
cx->cnt_bt[BTC_BCNT_INFOUPDATE],
|
cx->cnt_bt[BTC_BCNT_INFOSAME]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
|
"[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
|
cx->cnt_bt[BTC_BCNT_HIPRI_TX],
|
cx->cnt_bt[BTC_BCNT_LOPRI_RX],
|
cx->cnt_bt[BTC_BCNT_LOPRI_TX],
|
cx->cnt_bt[BTC_BCNT_POLUT]);
|
}
|
|
static void _show_fbtc_tdma(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_tdma *t = NULL;
|
|
pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
t = &pfwinfo->rpt_fbtc_tdma.finfo.tdma;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : ", "[tdma_policy]");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"type:%s, rx_flow_ctrl:%d, tx_flow_ctrl:%d, ",
|
id_to_str(BTC_STR_TDMA, (u32)t->type),
|
t->rxflctrl, t->txflctrl);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, null_role:0x%x, ",
|
t->wtgle_n, t->leak_n, t->ext_ctrl, t->rxflctrl_role);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"policy_type:%s",
|
id_to_str(BTC_STR_POLICY, (u32)btc->policy_type));
|
}
|
|
static void _show_dm_info(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_module *module = &btc->mdinfo;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
|
if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r========== [Mechanism Status %s] ==========",
|
(btc->ctrl.manual? "(Manual)":"(Auto)"));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, run_cnt:%d",
|
"[status]",
|
(module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated"),
|
dm->run_reason, dm->run_action,
|
id_to_str(BTC_STR_ANTPATH, dm->set_ant_path & 0xff),
|
dm->cnt_dm[BTC_DCNT_RUN]);
|
|
_show_fbtc_tdma(btc, used, input, input_num, output, out_len);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, ",
|
"[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
|
dm->freerun, btc->hal->btc_ctrl.lps);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"leak_ap:%d, fw_offload:%s%s, error_map:0x%x", dm->leak_ap,
|
(BTC_CX_FW_OFFLOAD? "Y" : "N"),
|
(dm->error.map.offload_mismatch?
|
"(Mis-Match!!)" : ""), dm->error.val);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d/1ss:%d], bt_slot_req:%d-TU, bt_scan_rx_low_pri:%d",
|
"[dm_drv_ctrl]", dm->wl_tx_limit.en,
|
dm->wl_tx_limit.tx_time, dm->wl_tx_limit.tx_retry,
|
dm->wl_tx_limit.tx_1ss, btc->bt_req_len, bt->scan_rx_low_pri);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : wl[rssi_lvl:%d/para_lvl:%d/tx_pwr:%d/rx_lvl:%d/_btg_rx:%d/stb_chg:%d] ",
|
"[dm_rf_ctrl]", wl->rssi_level, dm->trx_para_level,
|
dm->rf_trx_para.wl_tx_power, dm->rf_trx_para.wl_rx_gain,
|
dm->wl_btg_rx, dm->wl_stb_chg);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"bt[tx_pwr_dec:%d/rx_lna:%d(%s-tbl)]",
|
dm->rf_trx_para.bt_tx_power, dm->rf_trx_para.bt_rx_gain,
|
(bt->hi_lna_rx? "Hi" : "Ori"));
|
|
_show_dm_step(btc, used, input, input_num, output, out_len);
|
}
|
|
static void _show_mreg(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_mreg_val *pmreg = NULL;
|
struct fbtc_gpio_dbg *gdbg = NULL;
|
struct rtw_hal_com_t *h = btc->hal;
|
struct btc_cx *cx = &btc->cx;
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_gnt_ctrl gnt[2] = {0};
|
u8 i = 0, type = 0, cnt = 0;
|
u32 val, offset;
|
|
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r========== [HW Status] ==========");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
|
"[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
|
bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
|
cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
|
|
/* To avoid I/O if WL LPS or power-off */
|
if (wl->status.map.lps != BTC_LPS_RF_OFF && !wl->status.map.rf_off) {
|
rtw_hal_mac_get_grant(h, (u8*)gnt);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d/polut_type:%s]",
|
"[gnt_status]",
|
(_read_cx_ctrl(btc) == BTC_CTRL_BY_WL? "WL" : "BT"),
|
wl->pta_req_mac,
|
(gnt[0].gnt_wl_sw_en? "SW" : "HW"), gnt[0].gnt_wl,
|
(gnt[0].gnt_bt_sw_en? "SW" : "HW"), gnt[0].gnt_bt,
|
id_to_str(BTC_STR_POLUT, wl->bt_polut_type[HW_PHY_0]));
|
|
if (h->dbcc_en)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" ,phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d/polut_type:%s]",
|
(gnt[1].gnt_wl_sw_en? "SW" : "HW"),
|
gnt[1].gnt_wl,
|
(gnt[1].gnt_bt_sw_en? "SW" : "HW"),
|
gnt[1].gnt_bt,
|
id_to_str(BTC_STR_POLUT,
|
wl->bt_polut_type[HW_PHY_1]));
|
}
|
|
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
|
|
for (i = 0; i < pmreg->reg_num; i++) {
|
type = (u8)btc->chip->mon_reg[i].type;
|
offset = btc->chip->mon_reg[i].offset;
|
val = pmreg->mreg_val[i];
|
|
if (cnt % 6 == 0)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : %s_0x%x=0x%x",
|
"[reg]",
|
id_to_str(BTC_STR_REG, (u32)type),
|
offset, val);
|
else
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", %s_0x%x=0x%x",
|
id_to_str(BTC_STR_REG, (u32)type),
|
offset, val);
|
cnt++;
|
}
|
|
pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
|
if (!gdbg->en_map)
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : enable_map:0x%08x",
|
"[gpio_dbg]", gdbg->en_map);
|
|
for (i = 0; i < BTC_DBG_MAX1; i++) {
|
if (!(gdbg->en_map & BIT(i)))
|
continue;
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", %s->GPIO%d",
|
id_to_str(BTC_STR_GDBG, (u32)i),
|
gdbg->gpio_map[i]);
|
}
|
}
|
|
static void _show_summary(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_rpt_ctrl *prptctrl = NULL;
|
struct btc_cx *cx = &btc->cx;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_wl_info *wl = &cx->wl;
|
u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
|
u8 i;
|
|
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"%s", "\n\r========== [Statistics] ==========");
|
|
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
|
if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
|
!wl->status.map.rf_off) {
|
prptctrl = &pfwinfo->rpt_ctrl.finfo;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
|
"[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
|
prptctrl->rpt_info.cnt_h2c, pfwinfo->cnt_c2h,
|
prptctrl->rpt_info.cnt_c2h, prptctrl->rpt_info.len_c2h,
|
RTW_PHL_BTC_FWINFO_BUF);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
|
pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_info.cnt,
|
prptctrl->rpt_info.en);
|
|
if (dm->error.map.wl_fw_hang)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, " (WL FW Hang!!)");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
|
"[mailbox]", prptctrl->bt_mbx_info.cnt_send_ok,
|
prptctrl->bt_mbx_info.cnt_send_fail,
|
prptctrl->bt_mbx_info.cnt_recv);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
|
prptctrl->bt_mbx_info.a2dp.cnt_empty,
|
prptctrl->bt_mbx_info.a2dp.cnt_flowctrl,
|
prptctrl->bt_mbx_info.a2dp.cnt_tx,
|
prptctrl->bt_mbx_info.a2dp.cnt_ack,
|
prptctrl->bt_mbx_info.a2dp.cnt_nack);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
|
"[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
|
cx->cnt_wl[BTC_WCNT_RFK_GO],
|
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
|
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]",
|
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
|
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
|
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
|
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
|
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
|
} else {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
|
"[summary]", pfwinfo->cnt_h2c,
|
pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" WL FW rpt error!!(valid=%d, lps=%d, rf_off=%d)",
|
pcinfo->valid, wl->status.map.lps,
|
wl->status.map.rf_off);
|
}
|
|
for (i = 0; i < BTC_NCNT_MAX; i++)
|
cnt_sum += dm->cnt_notify[i];
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
|
"[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
|
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
|
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
|
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
|
cnt[BTC_NCNT_WL_STA]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
|
"[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
|
cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
|
cnt[BTC_NCNT_SPECIAL_PACKET]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"timer=%d, control=%d, customerize=%d, hub_msg=%d",
|
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
|
cnt[BTC_NCNT_CUSTOMERIZE], btc->hubmsg_cnt);
|
}
|
|
static void _show_error(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct fbtc_cysta *pcysta = NULL;
|
|
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
|
|
if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
|
pcysta->except_cnt == 0 &&
|
!pfwinfo->len_mismch && !pfwinfo->fver_mismch)
|
return;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : ", "[error]");
|
|
if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"overflow-cnt: %d, ",
|
pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
|
}
|
|
if (pfwinfo->len_mismch) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"len-mismatch: 0x%x, ",
|
pfwinfo->len_mismch);
|
}
|
|
if (pfwinfo->fver_mismch) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"fver-mismatch: 0x%x, ",
|
pfwinfo->fver_mismch);
|
}
|
|
/* cycle statistics exceptions */
|
if (pcysta->except_map || pcysta->except_cnt) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"exception-type: 0x%x, exception-cnt = %d",
|
pcysta->except_map, pcysta->except_cnt);
|
}
|
}
|
|
static void _show_fbtc_slots(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_dm *dm = &btc->dm;
|
struct fbtc_slot s;
|
u8 i = 0;
|
|
for (i = 0; i < CXST_MAX; i++) {
|
s = dm->slot_now[i];
|
if (i % 5 == 0)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : %s[%d/0x%x/%d]",
|
"[slot_list]",
|
id_to_str(BTC_STR_SLOT, (u32)i),
|
s.dur, s.cxtbl, s.cxtype);
|
else
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", %s[%d/0x%x/%d]",
|
id_to_str(BTC_STR_SLOT, (u32)i),
|
s.dur, s.cxtbl, s.cxtype);
|
}
|
}
|
|
static void _show_fbtc_cysta(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_cysta *pcysta = NULL;
|
u8 i, cnt = 0, slot_pair, divide_cnt = 12;
|
u16 cycle, c_begin, c_end, s_id;
|
|
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
|
"[slot_cnt]", pcysta->bcn_cnt[CXBCN_ALL],
|
pcysta->bcn_cnt[CXBCN_ALL_OK], pcysta->bcn_cnt[CXBCN_BT_SLOT],
|
pcysta->bcn_cnt[CXBCN_BT_OK]);
|
|
for (i = 0; i < CXST_MAX; i++) {
|
if (!pcysta->slot_cnt[i])
|
continue;
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", %s:%d",
|
id_to_str(BTC_STR_SLOT, (u32)i),
|
pcysta->slot_cnt[i]);
|
}
|
|
if (dm->tdma_now.rxflctrl) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", leak_rx:%d", pcysta->leak_slot.cnt_rximr);
|
}
|
|
if (pcysta->collision_cnt) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", collision:%d", pcysta->collision_cnt);
|
}
|
|
if (pcysta->skip_cnt) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", skip:%d", pcysta->skip_cnt);
|
}
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : cycle:%d, avg_t[wl:%d/bt:%d/lk:%d.%03d]",
|
"[cycle_time]",
|
pcysta->cycles,
|
pcysta->cycle_time.tavg[CXT_WL],
|
pcysta->cycle_time.tavg[CXT_BT],
|
pcysta->leak_slot.tavg/1000, pcysta->leak_slot.tavg%1000);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", max_t[wl:%d/bt:%d/lk:%d.%03d]",
|
pcysta->cycle_time.tmax[CXT_WL],
|
pcysta->cycle_time.tmax[CXT_BT],
|
pcysta->leak_slot.tamx/1000, pcysta->leak_slot.tamx%1000);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", maxdiff_t[wl:%d/bt:%d]",
|
pcysta->cycle_time.tmaxdiff[CXT_WL],
|
pcysta->cycle_time.tmaxdiff[CXT_BT]);
|
|
if (a2dp->exist) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : a2dp_ept:%d, a2dp_late:%d",
|
"[a2dp_t_sta]",
|
pcysta->a2dp_ept.cnt, pcysta->a2dp_ept.cnt_timeout);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
", avg_t:%d, max_t:%d",
|
pcysta->a2dp_ept.tavg, pcysta->a2dp_ept.tmax);
|
}
|
|
if (pcysta->cycles <= 1)
|
return;
|
|
/* 1 cycle = 1 wl-slot + 1 bt-slot */
|
slot_pair = BTC_CYCLE_SLOT_MAX/2;
|
|
if (pcysta->cycles <= slot_pair)
|
c_begin = 1;
|
else
|
c_begin = pcysta->cycles - slot_pair + 1;
|
|
c_end = pcysta->cycles;
|
|
if (a2dp->exist)
|
divide_cnt = 3;
|
else
|
divide_cnt = 12;
|
|
if (c_begin > c_end)
|
return;
|
|
for (cycle = c_begin; cycle <= c_end; cycle++) {
|
cnt++;
|
s_id = ((cycle-1) % slot_pair)*2;
|
|
if (cnt % divide_cnt == 1)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"\n\r %-15s : ", "[cycleT_ermtan]");
|
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"->b%d", pcysta->slot_step_time[s_id]);
|
#if 1
|
if (a2dp->exist)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"(%d/%d/%dM/%d/%d/%d)",
|
pcysta->a2dp_trx[s_id].empty_cnt,
|
pcysta->a2dp_trx[s_id].retry_cnt,
|
(pcysta->a2dp_trx[s_id].tx_rate ? 3:2),
|
pcysta->a2dp_trx[s_id].tx_cnt,
|
pcysta->a2dp_trx[s_id].ack_cnt,
|
pcysta->a2dp_trx[s_id].nack_cnt);
|
#endif
|
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"->w%d", pcysta->slot_step_time[s_id+1]);
|
#if 1
|
if (a2dp->exist)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"(%d/%d/%dM/%d/%d/%d)",
|
pcysta->a2dp_trx[s_id+1].empty_cnt,
|
pcysta->a2dp_trx[s_id+1].retry_cnt,
|
(pcysta->a2dp_trx[s_id+1].tx_rate ? 3:2),
|
pcysta->a2dp_trx[s_id+1].tx_cnt,
|
pcysta->a2dp_trx[s_id+1].ack_cnt,
|
pcysta->a2dp_trx[s_id+1].nack_cnt);
|
#endif
|
}
|
}
|
|
static void _show_fbtc_nullsta(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_cynullsta *ns = NULL;
|
u8 i = 0;
|
|
if (!btc->dm.tdma_now.rxflctrl)
|
return;
|
|
pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
|
|
for (i = CXNULL_STATE_0; i <= CXNULL_STATE_1; i++) {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : ", "[null_status]");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"null-%d", i);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"[Tx:%d/", ns->result[i][CXNULL_TX]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"ok:%d/", ns->result[i][CXNULL_OK]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"late:%d/", ns->result[i][CXNULL_LATE]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"fail:%d/", ns->result[i][CXNULL_FAIL]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"retry:%d/", ns->result[i][CXNULL_RETRY]);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"avg_t:%d.%03d/",
|
ns->tavg[i]/1000, ns->tavg[i]%1000);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"max_t:%d.%03d]",
|
ns->tmax[i]/1000, ns->tmax[i]%1000);
|
}
|
}
|
|
static void _show_fbtc_step(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btf_fwinfo *pfwinfo = &btc->fwinfo;
|
struct btc_rpt_cmn_info *pcinfo = NULL;
|
struct fbtc_steps *pstep = NULL;
|
u8 type, val;
|
u16 diff_t;
|
u32 i, cnt = 0, n_begin = 0, n_end = 0, array_idx = 0;
|
|
PHL_INFO("[BTC], %s(), rpt_en_map=0x%x\n", __func__, pfwinfo->rpt_en_map);
|
|
if ((pfwinfo->rpt_en_map & RPT_EN_FW_STEP_INFO) == 0)
|
return;
|
|
pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
|
if (!pcinfo->valid)
|
return;
|
|
pstep = &pfwinfo->rpt_fbtc_step.finfo;
|
|
if (pcinfo->req_fver != pstep->fver || !pstep->cnt)
|
return;
|
|
if (pstep->cnt <= FCXDEF_STEP)
|
n_begin = 1;
|
else
|
n_begin = pstep->cnt - FCXDEF_STEP + 1;
|
|
n_end = pstep->cnt;
|
|
if (n_begin > n_end)
|
return;
|
|
/* restore step info by using ring instead of FIFO */
|
for (i = n_begin; i <= n_end; i++) {
|
array_idx = (i - 1) % FCXDEF_STEP;
|
type = pstep->step[array_idx].type;
|
val = pstep->step[array_idx].val;
|
diff_t = pstep->step[array_idx].difft;
|
|
if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
|
continue;
|
|
if (cnt % 10 == 0)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"\n\r %-15s : ", "[fw_steps]");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"-> %s(%d)", (type == CXSTEP_SLOT?
|
id_to_str(BTC_STR_SLOT, (u32)val) :
|
id_to_str(BTC_STR_EVENT, (u32)val)),
|
diff_t);
|
cnt++;
|
}
|
}
|
|
static void _show_fw_dm_msg(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
|
return;
|
|
_show_error(btc, used, input, input_num, output, out_len);
|
_show_fbtc_slots(btc, used, input, input_num, output, out_len);
|
_show_fbtc_cysta(btc, used, input, input_num, output, out_len);
|
_show_fbtc_nullsta(btc, used, input, input_num, output, out_len);
|
_show_fbtc_step(btc, used, input, input_num, output, out_len);
|
}
|
|
static void _cmd_show(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 show_map = 0xff;
|
|
if (input_num > 1)
|
_os_sscanf(input[1], "%x", &show_map);
|
|
btc->dm.coex_info_map = show_map & 0xff;
|
|
_show_cx_info(btc, used, input, input_num, output, out_len);
|
_show_wl_info(btc, used, input, input_num, output, out_len);
|
_show_bt_info(btc, used, input, input_num, output, out_len);
|
_show_dm_info(btc, used, input, input_num, output, out_len);
|
_show_fw_dm_msg(btc, used, input, input_num, output, out_len);
|
_show_mreg(btc, used, input, input_num, output, out_len);
|
_show_summary(btc, used, input, input_num, output, out_len);
|
}
|
|
static void _cmd_dbg(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
struct btc_ops *ops = btc->ops;
|
u8 buf[8] = {0};
|
u32 len, n;
|
u32 val = 0, type = 0, i;
|
|
if ((input_num < 3) || (input_num > 10))
|
goto help;
|
|
len = input_num - 1;
|
_os_sscanf(input[1], "%d", &type);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" test type=%d", type);
|
|
buf[0] = (u8)(type & 0xff);
|
|
for (n = 2; n <= len; n++) {
|
_os_sscanf(input[n], "%x", &val);
|
buf[n-1] = (u8)(val & 0xff);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" para%d=0x%x", n-1, buf[n-1]);
|
}
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used, " \n");
|
|
switch (type) {
|
case 0: /* H2C-C2H loopback */
|
ops->fw_cmd(btc, BTFC_SET, SET_H2C_TEST, buf, (u16)len);
|
btc->dbg.rb_done = false;
|
btc->dbg.rb_val = 0xff;
|
for (i = 0; i < 50; i++) {
|
if (!btc->dbg.rb_done) {
|
hal_mdelay(btc->hal, 10);
|
} else {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
" H2C-C2H loopback data = 0x%x !!\n",
|
btc->dbg.rb_val);
|
return;
|
}
|
}
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" timeout !!\n");
|
break;
|
case 1: /* H2C-mailbox */
|
ops->fw_cmd(btc, BTFC_SET, SET_H2C_TEST, buf, (u16)len);
|
break;
|
case 2: /* bt slot request */
|
btc->bt_req_len = (u32)buf[1];
|
hal_btc_send_event(btc, (u8*)&btc->bt_req_len, 4,
|
BTC_HMSG_SET_BT_REQ_SLOT);
|
break;
|
case 3: /* fw_step debug */
|
if (buf[1] > 0)
|
hal_btc_fw_en_rpt(btc, RPT_EN_FW_STEP_INFO, 1);
|
else
|
hal_btc_fw_en_rpt(btc, RPT_EN_FW_STEP_INFO, 0);
|
break;
|
}
|
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" dbg <type> <para1:8bits> <para2:8bits>... \n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" dbg = 0: H2C-C2H loopback <para1: loopback data>\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" dbg = 1: H2C-mailbox <para1~para8: mailbox data>\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" dbg = 2: slot request for P2P+BT coex <para1: slot length (hex)>\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" dbg = 3: enable fw_step debug <para1:8bits>\n");
|
return;
|
}
|
|
static void _cmd_wb(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 type = 0, addr = 0, val = 0;
|
|
if (input_num < 4)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &type);
|
_os_sscanf(input[2], "%x", &addr);
|
_os_sscanf(input[3], "%x", &val);
|
|
if (type > 4)
|
goto help;
|
|
_write_bt_reg(btc, (u8)type, (u16)addr, val);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wb type=%d, addr=0x%x, val=0x%x !! \n", type, addr, val);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wb <type --- 0:rf, 1:modem, 2:bluewize, 3:vendor, 4:LE> <addr:16bits> <val> \n");
|
return;
|
}
|
|
static void _cmd_set_coex(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 mode = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &mode);
|
|
switch(mode) {
|
case 0: /* original */
|
btc->ctrl.manual = 0;
|
btc->ctrl.always_freerun = 0;
|
btc->dm.wl_only = 0;
|
btc->dm.bt_only = 0;
|
_set_init_info(btc);
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_INIT);
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_CTRL);
|
_run_coex(btc, __func__);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" recovery original coex mechanism !! \n");
|
break;
|
case 1: /* freeze */
|
btc->ctrl.manual = 1;
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_CTRL);
|
_run_coex(btc, __func__);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" freeze coex mechanism !! \n");
|
break;
|
case 2: /* fix freerun */
|
btc->ctrl.always_freerun = 1;
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_CTRL);
|
_run_coex(btc, __func__);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" freerun coex mechanism !! \n");
|
break;
|
case 3: /* fix wl only */
|
btc->dm.wl_only = 1;
|
_set_init_info(btc);
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_INIT);
|
_run_coex(btc, __func__);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" always WL-only coex mechanism!! \n");
|
break;
|
case 4: /* fix bt only */
|
btc->dm.bt_only = 1;
|
_set_init_info(btc);
|
hal_btc_fw_set_drv_info(btc, CXDRVINFO_INIT);
|
_run_coex(btc, __func__);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" always BT-only coex mechanism!! \n");
|
break;
|
}
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" mode <val--- 0:original, 1:freeze coex, 2:always-freerun, 3:always-WLonly, 4:always-BTonly> \n");
|
return;
|
}
|
|
static void _cmd_update_policy(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
hal_btc_fw_set_policy(btc, FC_EXEC, (u16)BTC_CXP_MANUAL<<8, __func__);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" Update tdma/slot policy !! \n");
|
}
|
|
static void _cmd_tdma(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 para1 = 0, para2 = 0;
|
u8 buf[8] = {0};
|
|
if (input_num < 3)
|
goto help;
|
|
_os_sscanf(input[1], "%x", ¶1);
|
_os_sscanf(input[2], "%x", ¶2);
|
|
buf[0] = (u8)((para1 & bMASKB3) >> 24);
|
buf[1] = (u8)((para1 & bMASKB2) >> 16);
|
buf[2] = (u8)((para1 & bMASKB1) >> 8);
|
buf[3] = (u8)(para1 & bMASKB0);
|
|
buf[4] = (u8)((para2 & bMASKB3) >> 24);
|
buf[5] = (u8)((para2 & bMASKB2) >> 16);
|
buf[6] = (u8)((para2 & bMASKB1) >> 8);
|
buf[7] = (u8)(para2 & bMASKB0);
|
|
if (!hal_btc_fw_set_1tdma(btc, (u16)sizeof(struct fbtc_tdma), buf))
|
goto help;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set tdma parameters1 type=%s, rxflctrl=0x%x, txflctrl=%d, wtgle_n=%d\n",
|
id_to_str(BTC_STR_TDMA, (u32)buf[0]), buf[1], buf[2], buf[3]);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set tdma parameters2 leak_n=%d, ext_ctrl=%x, rxflctrl_role=0x%x\n",
|
buf[4], buf[5], buf[6]);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" tdma <para1:32bits> <para2:32bits>\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <para1> bit[31:24]-> type --- 0:off, 1:fix, 2:auto, 3:auto2\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[23:19]-> rx_flow_ctrl --- send rx flow ctrl every n*w2b-slot\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[18:16]-> rx_flow_ctrl_type --- type 0:off, 1:null, 2:Qos-null, 3:cts\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[15:8] -> tx_flow_ctrl --- 0:off, 1:on\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[7:0] -> wtgle_n --- toggle coex table every n*w1-slot\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <para2> bit[31:24]-> leak_n --- enter leak slot every n*w2b-slot\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[23:16]-> ext_ctrl --- 0:off, 1:bcn-early_protect only 2:ext\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[15:8] -> resevrd\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bit[7:0] -> resevrd\n");
|
return;
|
}
|
|
static void _cmd_slot(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 sid = 0, dur = 0, cx_tbl = 0, cx_type = 0, i;
|
u32 *tmp32 = NULL;
|
u8 buf[9] = {0};
|
|
if (input_num < 5)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &sid);
|
_os_sscanf(input[2], "%d", &dur);
|
_os_sscanf(input[3], "%x", &cx_tbl);
|
_os_sscanf(input[4], "%d", &cx_type);
|
|
buf[0] = (u8) sid;
|
buf[1] = (u8)(dur & bMASKB0);
|
buf[2] = (u8)((dur & bMASKB1) >> 8);
|
|
tmp32 = (u32 *)&buf[3];
|
*tmp32 = cx_tbl;
|
|
buf[7] = (u8)(cx_type & bMASKB0);
|
buf[8] = (u8)((cx_type & bMASKB1) >> 8);
|
|
if (!hal_btc_fw_set_1slot(btc, (u16)sizeof(struct fbtc_slot)+1, buf))
|
goto help;
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set slot parameters: slot:%s, duration:%d, table:%08x, type=%s!!\n",
|
id_to_str(BTC_STR_SLOT, sid), dur, cx_tbl,
|
(cx_type? "iso" : "mix"));
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" slot <slot_id:8bits> <slot_duration:16bits> <coex_table:32bits> <type:16bits>\n");
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <slot_id> \n");
|
|
for (i = 0; i < CXST_MAX; i++) {
|
if ((i+1) % 5 == 1)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
" %d: %s",
|
i, id_to_str(BTC_STR_SLOT, i));
|
else
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
", %d: %s", i, id_to_str(BTC_STR_SLOT, i));
|
|
if (((i+1) % 5 == 0) || (i == CXST_MAX - 1))
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"\n");
|
}
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <slot_duration> unit: ms\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <coex_table> 32bits coex table\n");
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" <type> BT packet at WL slot 0: allowed, 1: isolated\n");
|
return;
|
}
|
|
static void _cmd_sig_gdbg_en(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 map = 0, i;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%x", &map);
|
|
hal_btc_fw_set_gpio_dbg(btc, CXDGPIO_EN_MAP, map);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" signal to gpio debug map = 0x%08x!!\n", map);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" sig <enable_map:hex/32bits> \n");
|
|
for (i = 0; i < BTC_DBG_MAX1; i++) {
|
if ((i+1) % 8 == 1)
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
" %d: %s",
|
i, id_to_str(BTC_STR_GDBG, i));
|
else
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
", %d: %s", i, id_to_str(BTC_STR_GDBG, i));
|
|
if (((i+1) % 8 == 0) || (i == BTC_DBG_MAX1 - 1))
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"\n");
|
}
|
return;
|
}
|
|
static void _cmd_sgpio_map(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 sig = 0, gpio = 0;
|
|
if (input_num < 3)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &sig);
|
_os_sscanf(input[2], "%d", &gpio);
|
|
if ((sig > 31) || (gpio > 7))
|
goto help;
|
|
hal_btc_fw_set_gpio_dbg(btc, CXDGPIO_MUX_MAP, ((gpio << 8) + sig));
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" signal-%s -> gpio-%d\n", id_to_str(BTC_STR_GDBG, sig), gpio);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" gpio <sig:0~31> <gpio:0~7>\n");
|
return;
|
}
|
|
static void _cmd_wl_tx_power(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 pwr = 0;
|
u8 is_negative = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &pwr);
|
if (pwr & BIT(31)) {
|
pwr = ~pwr + 1;
|
is_negative = 1;
|
}
|
|
pwr = pwr & bMASKB0;
|
|
if ((pwr != 255) && (pwr > 20))
|
goto help;
|
|
if (is_negative)
|
pwr |= BIT(7);
|
|
_set_wl_tx_power(btc, pwr);
|
|
if (pwr == 0xff)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set wl tx power level to original!!\n");
|
else if (is_negative)
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set wl tx power level = -%d dBm!!\n", pwr & 0x7f);
|
else
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set wl tx power level = +%d dBm!!\n", pwr & 0x7f);
|
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wpwr <wl_tx_power(dBm): -20dbm ~ +20dBm, 255-> original tx power\n");
|
return;
|
}
|
|
static void _cmd_wl_rx_lna(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 lna = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &lna);
|
|
_set_wl_rx_gain(btc, lna);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set wl rx level = %d!!\n", lna);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wlna <wl_rx_level: 0~7> \n");
|
return;
|
}
|
|
static void _cmd_bt_afh_map(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 en = 0, ch = 0, bw = 0;
|
|
if (input_num < 4)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &en);
|
_os_sscanf(input[2], "%d", &ch);
|
_os_sscanf(input[3], "%d", &bw);
|
|
btc->cx.wl.afh_info.en = (u8)en;
|
btc->cx.wl.afh_info.ch = (u8)ch;
|
btc->cx.wl.afh_info.bw = (u8)bw;
|
hal_btc_fw_set_bt(btc, SET_BT_WL_CH_INFO, 3, (u8*)&btc->cx.wl.afh_info);
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set bt afh map: en=%d, ch=%d, map=%d!!\n", en, ch, bw);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" afh <en: 0/1> <ch: 0~255> <bw: 0~255>\n");
|
return;
|
}
|
|
static void _cmd_bt_tx_power(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 pwr = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &pwr);
|
|
_set_bt_tx_power(btc, pwr);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" decrease bt tx power level = %d!!\n", pwr);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bpwr <decrease power: 0~255 > \n");
|
return;
|
}
|
|
static void _cmd_bt_rx_lna(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 lna = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &lna);
|
|
if (lna > 7)
|
goto help;
|
|
_set_bt_rx_gain(btc, lna);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set bt rx lna constrain level = %d!!\n", lna);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" blna <lna_constrain: 0~7> \n");
|
return;
|
}
|
|
static void _cmd_bt_igno_wlan(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 igno = 0;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &igno);
|
|
igno = igno & BIT(0);
|
|
_set_bt_ignore_wlan_act(btc, (u8)igno);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set bt ignore wlan = %d!!\n", igno);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" igwl <0: don't ignore wlan, 1: ignore wlan > \n");
|
return;
|
}
|
|
static void _cmd_set_gnt_wl(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 gwl = 0, phy_map = BTC_PHY_ALL;
|
|
if ((input_num != 2) && (input_num != 3))
|
goto help;
|
|
_os_sscanf(input[1], "%d", &gwl);
|
|
if (input_num == 3) {
|
_os_sscanf(input[2], "%d", &phy_map);
|
phy_map = (phy_map == 0? BTC_PHY_0 : BTC_PHY_1);
|
}
|
|
switch(gwl) {
|
case 0:
|
_set_gnt_wl(btc, (u8)phy_map, BTC_GNT_SW_LO);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_wl = SW-0 (phy_map=0x%x)\n", phy_map);
|
break;
|
case 1:
|
_set_gnt_wl(btc, (u8)phy_map, BTC_GNT_SW_HI);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_wl = SW-1 (phy_map=0x%x)\n", phy_map);
|
break;
|
case 2:
|
_set_gnt_wl(btc, (u8)phy_map, BTC_GNT_HW);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_wl = HW-PTA ctrl (phy_map=0x%x)\n", phy_map);
|
break;
|
}
|
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" gwl <0:SW_0, 1:SW_1, 2:HW_PTA> <0:PHY-0, 1:PHY-1, none:All> \n");
|
return;
|
}
|
|
static void _cmd_set_gnt_bt(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 gbt = 0, phy_map = BTC_PHY_ALL;
|
|
if ((input_num != 2) && (input_num != 3))
|
goto help;
|
|
_os_sscanf(input[1], "%d", &gbt);
|
|
if (input_num == 3) {
|
_os_sscanf(input[2], "%d", &phy_map);
|
phy_map = (phy_map == 0? BTC_PHY_0 : BTC_PHY_1);
|
}
|
|
switch(gbt) {
|
case 0:
|
_set_gnt_bt(btc, (u8)phy_map, BTC_GNT_SW_LO);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_bt = SW-0 (phy_map=0x%x)\n", phy_map);
|
break;
|
case 1:
|
_set_gnt_bt(btc, (u8)phy_map, BTC_GNT_SW_HI);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_bt = SW-1 (phy_map=0x%x)\n", phy_map);
|
break;
|
case 2:
|
_set_gnt_bt(btc, (u8)phy_map, BTC_GNT_HW);
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" set gnt_bt = HW-PTA ctrl (phy_map=0x%x)\n", phy_map);
|
break;
|
}
|
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" gbt <0:SW_0, 1:SW_1, 2:HW_PTA> <0:PHY-0, 1:PHY-1, none:All> \n");
|
return;
|
}
|
|
static void _cmd_set_bt_psd(struct btc_t *btc, u32 *used, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 idx = 0, type = 0;
|
|
if (input_num < 3)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &idx);
|
_os_sscanf(input[2], "%d", &type);
|
|
_set_bt_psd_report(btc, (u8)idx, (u8)type);
|
return;
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" bpsd <start_idex, dec-8bit> <report_type, dec-8bit> \n");
|
return;
|
}
|
|
void _get_wl_nhm_dbm(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_nhm *wl_nhm = &wl->nhm;
|
u8 set_result = false;
|
s8 bw_att_db = 13;
|
s8 nhm_pwr_dbm = 0;
|
s8 pwr = 0;
|
s8 cur_pwr = 0;
|
u16 save_index = 0;
|
bool new_data_flag = false;
|
struct watchdog_nhm_report nhm_rpt = {0};
|
|
if (wl->afh_info.bw < CHANNEL_WIDTH_5) {
|
|
if (wl->afh_info.bw != CHANNEL_WIDTH_80_80) {
|
bw_att_db =
|
13 + 3 * (s8)(wl->afh_info.bw - CHANNEL_WIDTH_20);
|
} else {
|
bw_att_db = 13 + 3 * 3;
|
}
|
}
|
|
rtw_hal_bb_nhm_mntr_result(btc->hal, &nhm_rpt, HW_PHY_0);
|
|
set_result = nhm_rpt.ccx_rpt_result;
|
|
if (set_result) {
|
nhm_pwr_dbm = nhm_rpt.nhm_pwr_dbm;
|
|
wl_nhm->instant_wl_nhm_dbm = nhm_pwr_dbm;
|
|
if (wl_nhm->start_flag == false) {
|
wl_nhm->start_flag = true;
|
pwr = nhm_pwr_dbm - bw_att_db;
|
new_data_flag = true;
|
} else {
|
pwr = wl_nhm->pwr;
|
if (wl_nhm->last_ccx_rpt_stamp !=
|
nhm_rpt.ccx_rpt_stamp) {
|
new_data_flag = true;
|
wl_nhm->current_status = 1; // new data
|
} else {
|
wl_nhm->current_status = 2; //duplicated data
|
}
|
}
|
|
if (new_data_flag) {
|
wl_nhm->last_ccx_rpt_stamp = nhm_rpt.ccx_rpt_stamp;
|
cur_pwr = nhm_pwr_dbm - bw_att_db;
|
wl_nhm->instant_wl_nhm_per_mhz = cur_pwr;
|
|
wl_nhm->valid_record_times += 1;
|
|
if (wl_nhm->valid_record_times == 0) {
|
wl_nhm->valid_record_times = 16;
|
}
|
|
save_index = (wl_nhm->valid_record_times + 16 - 1) % 16;
|
|
wl_nhm->ratio = nhm_rpt.nhm_ratio;
|
|
if (cur_pwr < pwr) {
|
pwr = cur_pwr;
|
wl_nhm->refresh = true;
|
} else {
|
pwr = (pwr >> 1) + (cur_pwr >> 1);
|
wl_nhm->refresh = false;
|
}
|
|
wl_nhm->pwr = pwr;
|
|
wl_nhm->record_pwr[(save_index & 0xF)] = pwr;
|
wl_nhm->record_ratio[(save_index & 0xF)] = nhm_rpt.nhm_ratio;
|
}
|
}
|
}
|
|
static void _cmd_get_wl_nhm_dbm(struct btc_t *btc, u32 *used,
|
char input[][MAX_ARGV], u32 input_num,
|
char *output, u32 out_len)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_nhm *wl_nhm = &wl->nhm;
|
u16 start_index = 0;
|
u16 stop_index = 0;
|
u16 i;
|
u32 show_record_num = 16;
|
|
if (input_num >= 3)
|
goto help;
|
|
_get_wl_nhm_dbm(btc);
|
|
_os_sscanf(input[1], "%d", &show_record_num);
|
|
if (show_record_num >= 16)
|
show_record_num = 16;
|
else if (show_record_num == 0)
|
show_record_num = 1;
|
|
if (wl_nhm->valid_record_times > 0) {
|
|
if (wl_nhm->current_status == 0) {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, "wl nhm failed this time\n");
|
}
|
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"nhm_psd = %d dBm/MHz, nhm_ratio = %d, status = %d, "
|
"valid_record_times = %d\n",
|
wl_nhm->pwr, wl_nhm->ratio,
|
wl_nhm->current_status, wl_nhm->valid_record_times);
|
|
stop_index = wl_nhm->valid_record_times;
|
if (wl_nhm->valid_record_times > (u16)show_record_num) {
|
start_index =
|
wl_nhm->valid_record_times - (u16)show_record_num;
|
}
|
|
for (i = start_index; i < stop_index; i++) {
|
if (i == start_index) {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"record_pwr(old->new) = %4d",
|
wl_nhm->record_pwr[(i + 16) & 0xF]);
|
|
} else if (i == (stop_index - 1)) {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, ", %4d dBm/MHz\n",
|
wl_nhm->record_pwr[(i + 16) & 0xF]);
|
} else {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, ", %4d",
|
wl_nhm->record_pwr[(i + 16) & 0xF]);
|
}
|
}
|
|
for (i = start_index; i < stop_index; i++) {
|
if (i == start_index) {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used,
|
"record_ratio(old->new) = %4d",
|
wl_nhm->record_ratio[(i + 16) & 0xF]);
|
|
} else if (i == (stop_index - 1)) {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, ", %4d percent\n",
|
wl_nhm->record_ratio[(i + 16) & 0xF]);
|
} else {
|
BTC_CNSL(out_len, *used, output + *used,
|
out_len - *used, ", %4d",
|
wl_nhm->record_ratio[(i + 16) & 0xF]);
|
}
|
}
|
|
} else {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"wl nhm not ready\n");
|
}
|
return;
|
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wnhm <last_record_num, dec,1-16, default:16> \n");
|
return;
|
}
|
|
u8 _btc_set_wl_tx_1ss(struct btc_t *btc, u8 port_id, bool enable)
|
{
|
struct rtw_hal_com_t *h = btc->hal;
|
enum rtw_hal_status set_reult;
|
|
set_reult = rtw_hal_btc_cfg_tx_1ss(h, btc->phl, port_id, enable);
|
if (set_reult != RTW_HAL_STATUS_SUCCESS)
|
return 1;
|
return 0;
|
}
|
|
static void _cmd_set_wl_tx_1ss(struct btc_t *btc, u32 *used,
|
char input[][MAX_ARGV], u32 input_num,
|
char *output, u32 out_len)
|
{
|
u32 port_id = 0xFFFFFFFF;
|
u8 j;
|
u8 set_reult;
|
bool enable = false;
|
u32 enable_input;
|
|
if (input_num < 2)
|
goto help;
|
|
_os_sscanf(input[1], "%d", &enable_input);
|
if (input_num >= 3)
|
_os_sscanf(input[2], "%d", &port_id);
|
|
enable = enable_input == 1 ? true : false;
|
|
if (port_id == 0xFFFFFFFF) {
|
for( j = 0; j < MAX_WIFI_ROLE_NUMBER; j++) {
|
set_reult = _btc_set_wl_tx_1ss(btc, j, enable);
|
if (set_reult == 1)
|
BTC_CNSL(out_len,
|
*used, output + *used, out_len - *used,
|
"port %d set 1ss to %d fail\n",
|
j, enable);
|
}
|
} else if (port_id < MAX_WIFI_ROLE_NUMBER) {
|
set_reult = _btc_set_wl_tx_1ss(btc, (u8)(port_id & 0xFF),
|
enable);
|
if (set_reult == 1)
|
BTC_CNSL(out_len,
|
*used, output + *used, out_len - *used,
|
"port %d set 1ss to %d fail\n",
|
port_id, enable);
|
} else {
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
"port %d is invalid\n", port_id);
|
}
|
return ;
|
|
help:
|
BTC_CNSL(out_len, *used, output + *used, out_len - *used,
|
" wtx1ss <enable(1/0), port_id(default:All)> \n");
|
return;
|
}
|
|
void halbtc_cmd_parser(struct btc_t *btc, char input[][MAX_ARGV],
|
u32 input_num, char *output, u32 out_len)
|
{
|
u32 used = 0;
|
u8 id = 0;
|
u32 i;
|
u32 array_size = sizeof(halbtc_cmd_i) / sizeof(struct halbtc_cmd_info);
|
|
BTC_CNSL(out_len, used, output + used, out_len - used, "\n");
|
|
/* Parsing Cmd ID */
|
if (input_num) {
|
for (i = 0; i < array_size; i++) {
|
if (_os_strcmp(halbtc_cmd_i[i].name, input[0]) == 0) {
|
id = halbtc_cmd_i[i].id;
|
break;
|
}
|
}
|
}
|
|
switch (id) {
|
case HALBTC_DBG:
|
_cmd_dbg(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SHOW:
|
_cmd_show(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_WRITE_BT:
|
_cmd_wb(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_READ_BT:
|
_cmd_rb(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SET_COEX:
|
_cmd_set_coex(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_UPDATE_POLICY:
|
_cmd_update_policy(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_TDMA:
|
_cmd_tdma(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SLOT:
|
_cmd_slot(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SIG_GDBG_EN:
|
_cmd_sig_gdbg_en(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SGPIO_MAP:
|
_cmd_sgpio_map(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_WL_TX_POWER:
|
_cmd_wl_tx_power(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_WL_RX_LNA:
|
_cmd_wl_rx_lna(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_BT_AFH_MAP:
|
_cmd_bt_afh_map(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_BT_TX_POWER:
|
_cmd_bt_tx_power(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_BT_RX_LNA:
|
_cmd_bt_rx_lna(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_BT_IGNO_WLAN:
|
_cmd_bt_igno_wlan(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SET_GNT_WL:
|
_cmd_set_gnt_wl(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SET_GNT_BT:
|
_cmd_set_gnt_bt(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SET_BT_PSD:
|
_cmd_set_bt_psd(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_GET_WL_NHM_DBM:
|
_cmd_get_wl_nhm_dbm(btc, &used, input, input_num, output, out_len);
|
break;
|
case HALBTC_SET_WL_TX1SS:
|
_cmd_set_wl_tx_1ss(btc, &used, input, input_num, output, out_len);
|
break;
|
default:
|
BTC_CNSL(out_len, used, output + used, out_len - used,
|
"command not supported !!\n");
|
|
/* fall through */
|
|
case HALBTC_HELP:
|
BTC_CNSL(out_len, used, output + used, out_len - used,
|
"BTC cmd ==>\n");
|
|
for (i = 0; i < array_size - 1; i++)
|
BTC_CNSL(out_len, used, output + used, out_len - used,
|
" %s\n", halbtc_cmd_i[i + 1].name);
|
break;
|
}
|
}
|
|
s32 halbtc_cmd(struct btc_t *btc, char *input, char *output, u32 out_len)
|
{
|
char *token;
|
u32 argc = 0;
|
char argv[MAX_ARGC][MAX_ARGV];
|
|
do {
|
token = _os_strsep(&input, ", ");
|
if (token) {
|
if (_os_strlen((u8 *)token) <= MAX_ARGV)
|
_os_strcpy(argv[argc], token);
|
|
argc++;
|
} else {
|
break;
|
}
|
} while (argc < MAX_ARGC);
|
#if 0
|
if (argc == 1)
|
argv[0][_os_strlen((u8 *)argv[0]) - 1] = '\0';
|
#endif
|
|
halbtc_cmd_parser(btc, argv, argc, output, out_len);
|
return 0;
|
}
|
|
#endif
|