/****************************************************************************** * * 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" struct halrf_cmd_info { char name[16]; u8 id; }; enum HALRF_CMD_ID { HALRF_HELP, HALRF_SUPPORTABILITY, HALRF_DBG_COMP, HALRF_PROFILE, HALRF_IQK, HALRF_IQK_DEBUG, HALRF_DPK, HALRF_DACK, HALRF_DACK_DEBUG, HALRF_RX_DCK, HALRF_DUMP_RFK_REG, HALRF_LO_TEST, #ifdef CONFIG_2G_BAND_SHIFT HAL_BAND_SHIFT, #endif HALRF_RCK, HALRF_WATCHDOG, HALRF_SINGLETONE_EN, HALRF_IQK_BYPASS, HALRF_IQK_KLOG, HALRF_TSSI, HALRF_PWR_TABLE, HALRF_IQK_DBCC, HALRF_RFK_CHECK, HALRF_RFK_TEST, HALRF_TXGAPK, HALRF_FW_IQK, HALRF_DUMP, HALRF_IQK_RXIMR, HALRF_THER, HALRF_XTAL_TRK, HALRF_HWTX }; struct halrf_cmd_info halrf_cmd_i[] = { {"-h", HALRF_HELP}, {"ability", HALRF_SUPPORTABILITY}, {"dbg", HALRF_DBG_COMP}, {"profile", HALRF_PROFILE}, {"iqk", HALRF_IQK}, {"dpk", HALRF_DPK}, {"dack", HALRF_DACK}, {"dack_dbg", HALRF_DACK_DEBUG}, {"rx_dck", HALRF_RX_DCK}, {"dump_rfk_reg", HALRF_DUMP_RFK_REG}, {"lo_test", HALRF_LO_TEST}, {"rck", HALRF_RCK}, {"rfk_check", HALRF_RFK_CHECK}, #ifdef CONFIG_2G_BAND_SHIFT {"band_shift", HAL_BAND_SHIFT}, #endif {"watchdog_stop", HALRF_WATCHDOG}, {"iqk_tone", HALRF_SINGLETONE_EN}, {"iqk_bypass", HALRF_IQK_BYPASS}, {"iqk_klog", HALRF_IQK_KLOG}, {"iqk_dbcc", HALRF_IQK_DBCC}, {"iqk_rximr", HALRF_IQK_RXIMR}, {"tssi", HALRF_TSSI}, {"pwr_table", HALRF_PWR_TABLE}, {"test", HALRF_RFK_TEST}, {"txgapk", HALRF_TXGAPK}, {"iqk_fw", HALRF_FW_IQK}, {"dump", HALRF_DUMP}, {"ther", HALRF_THER}, {"xtal_trk", HALRF_XTAL_TRK}, {"hwtx", HALRF_HWTX}, }; void halrf_cmd_parser(struct rf_info *rf, char input[][RF_MAX_ARGV], u32 input_num, char *output, u32 out_len) { struct rf_dbg_cmd_info *rf_dbg_cmd = &rf->rf_dbg_cmd_i; u32 used = 0; u8 id = 0; u32 i, val_1 = 0, val_2 = 0; u32 halrf_ary_size = rf_dbg_cmd->cmd_size; RF_DBG_CNSL(out_len, used, output + used, out_len - used, "\n"); /* Parsing Cmd ID */ if (input_num) { for (i = 0; i < halrf_ary_size; i++) { if (_os_strcmp(halrf_cmd_i[i].name, input[0]) == 0) { id = halrf_cmd_i[i].id; break; } } if (i == halrf_ary_size) { RF_DBG_CNSL(out_len, used, output + used, out_len - used, "HALRF command not found!\n"); return; } } switch (id) { case HALRF_HELP: { RF_DBG_CNSL(out_len, used, output + used, out_len - used, "RF cmd ==>\n"); for (i = 0; i < halrf_ary_size - 1; i++) RF_DBG_CNSL(out_len, used, output + used, out_len - used, " %-5d: %s\n", i, halrf_cmd_i[i + 1].name); } break; case HALRF_SUPPORTABILITY: halrf_support_ability(rf, input, &used, output, &out_len); break; case HALRF_DBG_COMP: halrf_dbg_trace(rf, input, &used, output, &out_len); break; case HALRF_DUMP_RFK_REG: halrf_dump_rfk_reg(rf, input, &used, output, &out_len); break; case HALRF_IQK: halrf_iqk_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_DPK: halrf_dpk_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_DACK: halrf_dack_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_RX_DCK: halrf_rx_dck_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_LO_TEST: _os_sscanf(input[1], "%d", &val_1); _os_sscanf(input[2], "%d", &val_2); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "S%d LO test %s!!\n", val_2, val_1 ? "on" : "off"); halrf_lo_test(rf, (bool)val_1, val_2); break; case HALRF_RCK: halrf_rck_trigger(rf, HW_PHY_0); break; case HALRF_WATCHDOG: _os_sscanf(input[1], "%d", &val_1); rf->is_watchdog_stop = (bool)val_1; if (val_1 == true) RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Halrf watchdog STOP!!\n"); else RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Halrf watchdog GO!!\n"); break; case HALRF_SINGLETONE_EN: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "[IQK]single tone enable => 0: path 0; 1: path 1\n"); _os_sscanf(input[1], "%d", &val_1); halrf_iqk_toneleakage(rf, val_1 & 0x1); break; case HALRF_IQK_BYPASS: halrf_iqk_bypass_cmd(rf, input, &used, output, &out_len); break; case HALRF_IQK_KLOG: halrf_iqk_klog_cmd(rf, input, &used, output, &out_len); break; case HALRF_TSSI: halrf_tssi_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_PWR_TABLE: halrf_pwr_table_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_IQK_DBCC: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "[IQK]dbcc enable => 0: PHY0; 1: PHY1\n"); _os_sscanf(input[1], "%d", &val_1); halrf_iqk_dbcc(rf, val_1 & 0x1); break; case HALRF_RFK_CHECK: halrf_rfk_check_reg_cmd(rf, input, &used, output, &out_len); break; case HALRF_RFK_TEST: halrf_test_cmd(rf, input, &used, output, &out_len); break; case HALRF_TXGAPK: halrf_txgapk_dbg_cmd(rf, input, &used, output, &out_len); break; case HALRF_FW_IQK: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "[IQK] IQK TYPE => 0: DRV, 1: FW\n"); _os_sscanf(input[1], "%d", &val_1); halrf_enable_fw_iqk(rf, val_1 & 0x1); break; case HALRF_DUMP: halrf_dump_rf_reg_cmd(rf, input, &used, output, &out_len); break; case HALRF_IQK_RXIMR: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "[IQK] -path -idx \n"); _os_sscanf(input[1], "%d", &val_1); _os_sscanf(input[2], "%d", &val_2); i= halrf_iqk_get_rximr(rf, (u8)val_1, val_2); RF_DBG_CNSL(out_len, used, output + used, out_len - used, " dec, rximr = %d !!\n", i); break; case HALRF_THER: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Thermal A: %d\n", halrf_get_thermal(rf, RF_PATH_A)); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Thermal B: %d\n", halrf_get_thermal(rf, RF_PATH_B)); break; case HALRF_XTAL_TRK: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Xtal Tracking offset PHY0 : %d\n", halrf_xtal_tracking_offset(rf, 0)); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Xtal Tracking offset PHY1 : %d\n", halrf_xtal_tracking_offset(rf, 1)); break; case HALRF_HWTX: { u32 value[10] = {0}; u8 i; for (i = 0; i < 4; i++) if (input[i + 1]) _os_sscanf(input[i + 1], "%d", &value[i]); if (_os_strcmp(input[1], "-h") == 0) { RF_DBG_CNSL(out_len, used, output + used, out_len - used, "echo rf hwtx enable path cnt dB\n"); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Enable / Disable = 1 / 0\n"); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "PathA / PathB = 0 / 1\n"); RF_DBG_CNSL(out_len, used, output + used, out_len - used, "EX:echo rf hwtx 1 0 0 10\n"); } RF_DBG_CNSL(out_len, used, output + used, out_len - used, "==>Enable:%d Path:%d Count:%d Power:%ddB\n", value[0], value[1], value[2], value[3]); //halrf_tssi_hw_tx_8852a(rf, 0, path, cnt, dbm, T_HT_MF, 0, enable); if (value[0] == 1) { RF_DBG_CNSL(out_len, used, output + used, out_len - used, "HW TX Start\n"); halrf_btc_rfk_ntfy(rf, (BIT(HW_PHY_0) << 4), RF_BTC_TSSI, RFK_START); halrf_tmac_tx_pause(rf, HW_PHY_0, true); halrf_hw_tx(rf, (u8)value[1], (u16)value[2], (s16)(value[3] * 4), T_HT_MF, 0, 1); } if (value[0] == 0) { RF_DBG_CNSL(out_len, used, output + used, out_len - used, "HW TX Stop\n"); halrf_hw_tx(rf, (u8)value[1], (u16)value[2], (s16)(value[3] * 4), T_HT_MF, 0, 0); halrf_tx_mode_switch(rf, HW_PHY_0, 0); halrf_tmac_tx_pause(rf, HW_PHY_0, false); halrf_btc_rfk_ntfy(rf, (BIT(HW_PHY_0) << 4), RF_BTC_TSSI, RFK_STOP); } } break; default: RF_DBG_CNSL(out_len, used, output + used, out_len - used, "Do not support this command\n"); break; } } void halrf_cmd_parser_init(struct rf_info *rf) { struct rf_dbg_cmd_info *rf_dbg_cmd = &rf->rf_dbg_cmd_i; rf_dbg_cmd->cmd_size = sizeof(halrf_cmd_i) / sizeof(struct halrf_cmd_info); } #if 0 #ifndef strsep char *strsep(char **s, const char *ct) { char *sbegin = *s; char tmp = 0; char *end = &tmp; if (!sbegin) return NULL; //end = strpbrk(sbegin, ct); if (end) *end++ = '\0'; *s = end; return sbegin; } #endif #endif s32 halrf_cmd(struct rf_info *rf, char *input, char *output, u32 out_len) { char *token; u32 argc = 0; char argv[RF_MAX_ARGC][RF_MAX_ARGV]; do { token = _os_strsep(&input, ", "); //smae name in bb if (token) { if (_os_strlen(token) <= RF_MAX_ARGV) _os_strcpy(argv[argc], token); argc++; } else { break; } } while (argc < RF_MAX_ARGC); if (argc == 1) argv[0][_os_strlen(argv[0]) - 1] = '\0'; halrf_cmd_parser(rf, argv, argc, output, out_len); return 0; } u32 halrf_get_multiple(u8 pow, u8 base) { u8 i; u32 return_value = 1; for (i = 0; i < pow; i++) return_value *= base; /*base ^ pow*/ return return_value; } u32 halrf_str_2_dec(u8 val) { if (val >= 0x30 && val <= 0x39) /*0~9*/ return (val - 0x30); else if (val >= 0x41 && val <= 0x46) /*A~F*/ return (val - 0x41 + 10); else if (val >= 0x61 && val <= 0x66) /*a~f*/ return (val - 0x61 + 10); else return 1; } void halrf_scanf(char *in, enum rf_scanf_type type, u32 *out) { char buff[HALRF_DCMD_SCAN_LIMIT]; u32 multiple = 1; u8 text_num = 0; u8 base = 10; u8 i = 0, j = 0; *out = 0; for (i = 0; i < HALRF_DCMD_SCAN_LIMIT; i++) { if (in[i] != 0x0) { /* 0x0 = NULL. */ buff[i] = in[i]; continue; } if (type == DCMD_CHAR) { *out = *in; break; } base = (type == DCMD_DECIMAL) ? 10 : 16; text_num = i; for (j = 0; j < text_num; j++) { multiple = halrf_get_multiple(text_num - 1 - j, base); *out += halrf_str_2_dec(buff[j]) * multiple; } break; } }