/** ****************************************************************************** * * @file rwnx_platform.c * * Copyright (C) RivieraWaves 2012-2019 * ****************************************************************************** */ #include #include #include #include #include "rwnx_platform.h" #include "reg_access.h" #include "hal_desc.h" #include "rwnx_main.h" #include "rwnx_pci.h" #ifndef CONFIG_RWNX_FHOST #include "ipc_host.h" #endif /* !CONFIG_RWNX_FHOST */ #include "rwnx_msg_tx.h" #ifdef AICWF_SDIO_SUPPORT #include "aicwf_sdio.h" #endif #ifdef AICWF_USB_SUPPORT #include "aicwf_usb.h" #endif #include "md5.h" #include "aicwf_compat_8800dc.h" #include "aicwf_compat_8800d80.h" #ifdef CONFIG_USE_FW_REQUEST #include #endif #define FW_PATH_MAX_LEN 200 extern char aic_fw_path[FW_PATH_MAX_LEN]; //Parser state #define INIT 0 #define CMD 1 #define PRINT 2 #define GET_VALUE 3 struct rwnx_plat *g_rwnx_plat; typedef struct { txpwr_lvl_conf_t txpwr_lvl; txpwr_lvl_conf_v2_t txpwr_lvl_v2; txpwr_lvl_conf_v3_t txpwr_lvl_v3; txpwr_ofst_conf_t txpwr_ofst; xtal_cap_conf_t xtal_cap; } userconfig_info_t; userconfig_info_t userconfig_info = { .txpwr_lvl = { .enable = 1, .dsss = 9, .ofdmlowrate_2g4 = 8, .ofdm64qam_2g4 = 8, .ofdm256qam_2g4 = 8, .ofdm1024qam_2g4 = 8, .ofdmlowrate_5g = 11, .ofdm64qam_5g = 10, .ofdm256qam_5g = 9, .ofdm1024qam_5g = 9 }, .txpwr_lvl_v2 = { .enable = 1, .pwrlvl_11b_11ag_2g4 = //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, .pwrlvl_11n_11ac_2g4 = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, .pwrlvl_11ax_2g4 = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, }, .txpwr_lvl_v3 = { .enable = 1, .pwrlvl_11b_11ag_2g4 = //1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M { 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, .pwrlvl_11n_11ac_2g4 = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, .pwrlvl_11ax_2g4 = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, .pwrlvl_11a_5g = //NA, NA, NA, NA, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M { 0x80, 0x80, 0x80, 0x80, 20, 20, 20, 20, 18, 18, 16, 16}, .pwrlvl_11n_11ac_5g = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15}, .pwrlvl_11ax_5g = //MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10,MCS11 { 20, 20, 20, 20, 18, 18, 16, 16, 16, 15, 14, 14}, }, .txpwr_ofst = { .enable = 1, .chan_1_4 = 0, .chan_5_9 = 0, .chan_10_13 = 0, .chan_36_64 = 0, .chan_100_120 = 0, .chan_122_140 = 0, .chan_142_165 = 0, }, .xtal_cap = { .enable = 0, .xtal_cap = 24, .xtal_cap_fine = 31, }, }; #ifdef CONFIG_RWNX_TL4 /** * rwnx_plat_tl4_fw_upload() - Load the requested FW into embedded side. * * @rwnx_plat: pointer to platform structure * @fw_addr: Virtual address where the fw must be loaded * @filename: Name of the fw. * * Load a fw, stored as a hex file, into the specified address */ static int rwnx_plat_tl4_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, char *filename) { struct device *dev = rwnx_platform_get_dev(rwnx_plat); const struct firmware *fw; int err = 0; u32 *dst; u8 const *file_data; char typ0, typ1; u32 addr0, addr1; u32 dat0, dat1; int remain; err = request_firmware(&fw, filename, dev); if (err) { return err; } file_data = fw->data; remain = fw->size; /* Copy the file on the Embedded side */ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); /* Walk through all the lines of the configuration file */ while (remain >= 16) { u32 data, offset; if (sscanf(file_data, "%c:%08X %04X", &typ0, &addr0, &dat0) != 3) break; if ((addr0 & 0x01) != 0) { addr0 = addr0 - 1; dat0 = 0; } else { file_data += 16; remain -= 16; } if ((remain < 16) || (sscanf(file_data, "%c:%08X %04X", &typ1, &addr1, &dat1) != 3) || (typ1 != typ0) || (addr1 != (addr0 + 1))) { typ1 = typ0; addr1 = addr0 + 1; dat1 = 0; } else { file_data += 16; remain -= 16; } if (typ0 == 'C') { offset = 0x00200000; if ((addr1 % 4) == 3) offset += 2*(addr1 - 3); else offset += 2*(addr1 + 1); data = dat1 | (dat0 << 16); } else { offset = 2*(addr1 - 1); data = dat0 | (dat1 << 16); } dst = (u32 *)(fw_addr + offset); *dst = data; } release_firmware(fw); return err; } #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); #endif #if 0 /** * rwnx_plat_bin_fw_upload() - Load the requested binary FW into embedded side. * * @rwnx_plat: pointer to platform structure * @fw_addr: Virtual address where the fw must be loaded * @filename: Name of the fw. * * Load a fw, stored as a binary file, into the specified address */ static int rwnx_plat_bin_fw_upload(struct rwnx_plat *rwnx_plat, u8 *fw_addr, char *filename) { const struct firmware *fw; struct device *dev = rwnx_platform_get_dev(rwnx_plat); int err = 0; unsigned int i, size; u32 *src, *dst; err = request_firmware(&fw, filename, dev); if (err) { return err; } /* Copy the file on the Embedded side */ dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr); src = (u32 *)fw->data; dst = (u32 *)fw_addr; size = (unsigned int)fw->size; /* check potential platform bug on multiple stores vs memcpy */ for (i = 0; i < size; i += 4) { *dst++ = *src++; } release_firmware(fw); return err; } #endif #define MD5(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] #define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n" static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) { #ifdef CONFIG_USE_FW_REQUEST const struct firmware *fw = NULL; u32 *dst = NULL; void *buffer=NULL; MD5_CTX md5; unsigned char decrypt[16]; int size = 0; int ret = 0; printk("%s: request firmware = %s \n", __func__ ,name); ret = request_firmware(&fw, name, NULL); if (ret < 0) { printk("Load %s fail\n", name); release_firmware(fw); return -1; } size = fw->size; dst = (u32 *)fw->data; if (size <= 0) { printk("wrong size of firmware file\n"); release_firmware(fw); return -1; } buffer = vmalloc(size); memset(buffer, 0, size); memcpy(buffer, dst, size); *fw_buf = buffer; MD5Init(&md5); MD5Update(&md5, (unsigned char *)buffer, size); MD5Final(&md5, decrypt); printk(MD5PINRT, MD5(decrypt)); release_firmware(fw); return size; #else void *buffer = NULL; char *path = NULL; struct file *fp = NULL; int size = 0, len = 0, i = 0; ssize_t rdlen = 0; u32 *src = NULL, *dst = NULL; MD5_CTX md5; unsigned char decrypt[16]; /* get the firmware path */ path = __getname(); if (!path) { *fw_buf = NULL; return -1; } len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", aic_fw_path, name); //len = snprintf(path, FW_PATH_MAX_LEN, "%s", name); if (len >= FW_PATH_MAX_LEN) { AICWFDBG(LOGERROR, "%s: %s file's path too long\n", __func__, name); *fw_buf = NULL; __putname(path); return -1; } AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__, path); /* open the firmware file */ fp = filp_open(path, O_RDONLY, 0); if (IS_ERR_OR_NULL(fp)) { AICWFDBG(LOGERROR, "%s: %s file failed to open\n", __func__, name); *fw_buf = NULL; __putname(path); fp = NULL; return -1; } size = i_size_read(file_inode(fp)); if (size <= 0) { AICWFDBG(LOGERROR, "%s: %s file size invalid %d\n", __func__, name, size); *fw_buf = NULL; __putname(path); filp_close(fp, NULL); fp = NULL; return -1; } /* start to read from firmware file */ buffer = kzalloc(size, GFP_KERNEL); if (!buffer) { *fw_buf = NULL; __putname(path); filp_close(fp, NULL); fp = NULL; return -1; } #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) rdlen = kernel_read(fp, buffer, size, &fp->f_pos); #else rdlen = kernel_read(fp, fp->f_pos, buffer, size); #endif if (size != rdlen) { AICWFDBG(LOGERROR, "%s: %s file rdlen invalid %d\n", __func__, name, (int)rdlen); *fw_buf = NULL; __putname(path); filp_close(fp, NULL); fp = NULL; kfree(buffer); buffer = NULL; return -1; } if (rdlen > 0) { fp->f_pos += rdlen; } /*start to transform the data format*/ src = (u32 *)buffer; dst = (u32 *)kzalloc(size, GFP_KERNEL); if (!dst) { *fw_buf = NULL; __putname(path); filp_close(fp, NULL); fp = NULL; kfree(buffer); buffer = NULL; return -1; } for (i = 0; i < (size/4); i++) { dst[i] = src[i]; } __putname(path); filp_close(fp, NULL); fp = NULL; kfree(buffer); buffer = NULL; *fw_buf = dst; MD5Init(&md5); MD5Update(&md5, (unsigned char *)dst, size); MD5Final(&md5, decrypt); AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); return size; #endif } /* buffer is allocated by kzalloc */ int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw, u32** buffer, const char *filename) { int size; AICWFDBG(LOGINFO, "### Load file %s\n", filename); size = rwnx_load_firmware(buffer, filename, NULL); return size; } static void rwnx_restore_firmware(u32 **fw_buf) { #ifdef CONFIG_USE_FW_REQUEST vfree(*fw_buf); #else kfree(*fw_buf); #endif *fw_buf = NULL; } void rwnx_release_firmware_common(u32** buffer) { rwnx_restore_firmware(buffer); } /** * rwnx_plat_bin_fw_upload_2() - Load the requested binary FW into embedded side. * * @rwnx_hw: Main driver data * @fw_addr: Address where the fw must be loaded * @filename: Name of the fw. * * Load a fw, stored as a binary file, into the specified address */ int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, char *filename) { int err = 0; unsigned int i = 0, size; // u32 *src; u32 *dst=NULL; /* Copy the file on the Embedded side */ AICWFDBG(LOGINFO, "### Upload %s firmware, @ = %x\n", filename, fw_addr); size = rwnx_request_firmware_common(rwnx_hw, &dst, filename); if (!dst) { AICWFDBG(LOGERROR, "No such file or directory\n"); return -1; } if (size <= 0) { AICWFDBG(LOGERROR, "wrong size of firmware file\n"); dst = NULL; err = -1; } AICWFDBG(LOGINFO, "size=%d, dst[0]=%x\n", size, dst[0]); if (size > 512) { for (; i < (size - 512); i += 512) { //printk("wr blk 0: %p -> %x\r\n", dst + i / 4, fw_addr + i); err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, 512, dst + i / 4); if (err) { AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); break; } } } if (!err && (i < size)) { //printk("wr blk 1: %p -> %x\r\n", dst + i / 4, fw_addr + i); err = rwnx_send_dbg_mem_block_write_req(rwnx_hw, fw_addr + i, size - i, dst + i / 4); if (err) { AICWFDBG(LOGERROR, "bin upload fail: %x, err:%d\r\n", fw_addr + i, err); } } if (dst) { rwnx_release_firmware_common(&dst); } return err; } typedef struct { txpwr_idx_conf_t txpwr_idx; txpwr_ofst_conf_t txpwr_ofst; xtal_cap_conf_t xtal_cap; } nvram_info_t; nvram_info_t nvram_info = { .txpwr_idx = { .enable = 1, .dsss = 9, .ofdmlowrate_2g4 = 8, .ofdm64qam_2g4 = 8, .ofdm256qam_2g4 = 8, .ofdm1024qam_2g4 = 8, .ofdmlowrate_5g = 11, .ofdm64qam_5g = 10, .ofdm256qam_5g = 9, .ofdm1024qam_5g = 9 }, .txpwr_ofst = { .enable = 1, .chan_1_4 = 0, .chan_5_9 = 0, .chan_10_13 = 0, .chan_36_64 = 0, .chan_100_120 = 0, .chan_122_140 = 0, .chan_142_165 = 0, }, .xtal_cap = { .enable = 0, .xtal_cap = 24, .xtal_cap_fine = 31, }, }; void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst) { txpwr_ofst->enable = userconfig_info.txpwr_ofst.enable; txpwr_ofst->chan_1_4 = userconfig_info.txpwr_ofst.chan_1_4; txpwr_ofst->chan_5_9 = userconfig_info.txpwr_ofst.chan_5_9; txpwr_ofst->chan_10_13 = userconfig_info.txpwr_ofst.chan_10_13; txpwr_ofst->chan_36_64 = userconfig_info.txpwr_ofst.chan_36_64; txpwr_ofst->chan_100_120 = userconfig_info.txpwr_ofst.chan_100_120; txpwr_ofst->chan_122_140 = userconfig_info.txpwr_ofst.chan_122_140; txpwr_ofst->chan_142_165 = userconfig_info.txpwr_ofst.chan_142_165; AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, txpwr_ofst->enable); AICWFDBG(LOGINFO, "%s:chan_1_4 :%d\r\n", __func__, txpwr_ofst->chan_1_4); AICWFDBG(LOGINFO, "%s:chan_5_9 :%d\r\n", __func__, txpwr_ofst->chan_5_9); AICWFDBG(LOGINFO, "%s:chan_10_13 :%d\r\n", __func__, txpwr_ofst->chan_10_13); AICWFDBG(LOGINFO, "%s:chan_36_64 :%d\r\n", __func__, txpwr_ofst->chan_36_64); AICWFDBG(LOGINFO, "%s:chan_100_120:%d\r\n", __func__, txpwr_ofst->chan_100_120); AICWFDBG(LOGINFO, "%s:chan_122_140:%d\r\n", __func__, txpwr_ofst->chan_122_140); AICWFDBG(LOGINFO, "%s:chan_142_165:%d\r\n", __func__, txpwr_ofst->chan_142_165); } void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx) { memcpy(txpwr_idx, &(nvram_info.txpwr_idx), sizeof(txpwr_idx_conf_t)); } void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst) { memcpy(txpwr_ofst, &(nvram_info.txpwr_ofst), sizeof(txpwr_ofst_conf_t)); } void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) { *xtal_cap = nvram_info.xtal_cap; AICWFDBG(LOGINFO, "%s:enable :%d\r\n", __func__, xtal_cap->enable); AICWFDBG(LOGINFO, "%s:xtal_cap :%d\r\n", __func__, xtal_cap->xtal_cap); AICWFDBG(LOGINFO, "%s:xtal_cap_fine:%d\r\n", __func__, xtal_cap->xtal_cap_fine); } #define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} struct parse_match_t { char keyname[64]; int offset; }; static const char *parse_key_prefix[] = { [0x01] = "module0_", [0x21] = "module1_", }; static const struct parse_match_t parse_match_tab[] = { MATCH_NODE(nvram_info_t, txpwr_idx.enable, "enable"), MATCH_NODE(nvram_info_t, txpwr_idx.dsss, "dsss"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_2g4, "ofdmlowrate_2g4"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_2g4, "ofdm64qam_2g4"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_2g4, "ofdm256qam_2g4"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_2g4, "ofdm1024qam_2g4"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdmlowrate_5g, "ofdmlowrate_5g"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm64qam_5g, "ofdm64qam_5g"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_5g, "ofdm256qam_5g"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_5g, "ofdm1024qam_5g"), MATCH_NODE(nvram_info_t, txpwr_ofst.enable, "ofst_enable"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_1_4, "ofst_chan_1_4"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_5_9, "ofst_chan_5_9"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_10_13, "ofst_chan_10_13"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_36_64, "ofst_chan_36_64"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_100_120, "ofst_chan_100_120"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_122_140, "ofst_chan_122_140"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_142_165, "ofst_chan_142_165"), MATCH_NODE(nvram_info_t, xtal_cap.enable, "xtal_enable"), MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap, "xtal_cap"), MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap_fine, "xtal_cap_fine"), }; static int parse_key_val(const char *str, const char *key, char *val) { const char *p = NULL; const char *dst = NULL; int keysize = 0; int bufsize = 0; if (str == NULL || key == NULL || val == NULL) return -1; keysize = strlen(key); bufsize = strlen(str); if (bufsize <= keysize) return -1; p = str; while (*p != 0 && *p == ' ') p++; if (*p == '#') return -1; if (str + bufsize - p <= keysize) return -1; if (strncmp(p, key, keysize) != 0) return -1; p += keysize; while (*p != 0 && *p == ' ') p++; if (*p != '=') return -1; p++; while (*p != 0 && *p == ' ') p++; if (*p == '"') p++; dst = p; while (*p != 0) p++; p--; while (*p == ' ') p--; if (*p == '"') p--; while (*p == '\r' || *p == '\n') p--; p++; strncpy(val, dst, p -dst); val[p - dst] = 0; return 0; } int rwnx_atoi(char *value) { int len = 0; int i = 0; int result = 0; int flag = 1; if (value[0] == '-') { flag = -1; value++; } len = strlen(value); for (i = 0;i < len ;i++) { result = result * 10; if (value[i] >= 48 && value[i] <= 57) { result += value[i] - 48; } else { result = 0; break; } } return result * flag; } void rwnx_plat_nvram_set_value(char *command, char *value) { //TODO send command AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); if (!strcmp(command, "enable")) { userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); userconfig_info.txpwr_lvl_v2.enable = rwnx_atoi(value); } else if (!strcmp(command, "dsss")) { userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); } else if (!strcmp(command, "ofdmlowrate_2g4")) { userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm64qam_2g4")) { userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm256qam_2g4")) { userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm1024qam_2g4")) { userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdmlowrate_5g")) { userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm64qam_5g")) { userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm256qam_5g")) { userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm1024qam_5g")) { userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { userconfig_info.txpwr_lvl_v2.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); } else if (!strcmp(command, "ofst_enable")) { userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_1_4")) { userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_5_9")) { userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_10_13")) { userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_36_64")) { userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_100_120")) { userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_122_140")) { userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_142_165")) { userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); } else if (!strcmp(command, "xtal_enable")) { userconfig_info.xtal_cap.enable = rwnx_atoi(value); } else if (!strcmp(command, "xtal_cap")) { userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); } else if (!strcmp(command, "xtal_cap_fine")) { userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); } else { AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); } } void rwnx_plat_nvram_set_value_v3(char *command, char *value) { //TODO send command AICWFDBG(LOGINFO, "%s:command=%s value=%s\n", __func__, command, value); if (!strcmp(command, "enable")) { userconfig_info.txpwr_lvl.enable = rwnx_atoi(value); userconfig_info.txpwr_lvl_v3.enable = rwnx_atoi(value); } else if (!strcmp(command, "dsss")) { userconfig_info.txpwr_lvl.dsss = rwnx_atoi(value); } else if (!strcmp(command, "ofdmlowrate_2g4")) { userconfig_info.txpwr_lvl.ofdmlowrate_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm64qam_2g4")) { userconfig_info.txpwr_lvl.ofdm64qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm256qam_2g4")) { userconfig_info.txpwr_lvl.ofdm256qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdm1024qam_2g4")) { userconfig_info.txpwr_lvl.ofdm1024qam_2g4 = rwnx_atoi(value); } else if (!strcmp(command, "ofdmlowrate_5g")) { userconfig_info.txpwr_lvl.ofdmlowrate_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm64qam_5g")) { userconfig_info.txpwr_lvl.ofdm64qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm256qam_5g")) { userconfig_info.txpwr_lvl.ofdm256qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "ofdm1024qam_5g")) { userconfig_info.txpwr_lvl.ofdm1024qam_5g = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_1m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_2m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_5m5_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_11m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_6m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_9m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_12m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_18m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_24m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_36m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_48m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11b_11ag_54m_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[11] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs0_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs1_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs2_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs3_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs4_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs5_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs6_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs7_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs8_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs9_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs0_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs1_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs2_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs3_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs4_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs5_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs6_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs7_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs8_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs9_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs10_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs11_2g4")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[11] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_1m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_2m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_5m5_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_11m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_6m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_9m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_12m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_18m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_24m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_36m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_48m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11a_54m_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[11] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs0_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs1_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs2_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs3_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs4_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs5_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs6_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs7_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs8_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11n_11ac_mcs9_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs0_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[0] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs1_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[1] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs2_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[2] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs3_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[3] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs4_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[4] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs5_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[5] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs6_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[6] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs7_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[7] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs8_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[8] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs9_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[9] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs10_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[11] = rwnx_atoi(value); } else if (!strcmp(command, "ofst_enable")) { userconfig_info.txpwr_ofst.enable = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_1_4")) { userconfig_info.txpwr_ofst.chan_1_4 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_5_9")) { userconfig_info.txpwr_ofst.chan_5_9 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_10_13")) { userconfig_info.txpwr_ofst.chan_10_13 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_36_64")) { userconfig_info.txpwr_ofst.chan_36_64 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_100_120")) { userconfig_info.txpwr_ofst.chan_100_120 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_122_140")) { userconfig_info.txpwr_ofst.chan_122_140 = rwnx_atoi(value); } else if (!strcmp(command, "ofst_chan_142_165")) { userconfig_info.txpwr_ofst.chan_142_165 = rwnx_atoi(value); } else if (!strcmp(command, "xtal_enable")) { userconfig_info.xtal_cap.enable = rwnx_atoi(value); } else if (!strcmp(command, "xtal_cap")) { userconfig_info.xtal_cap.xtal_cap = rwnx_atoi(value); } else if (!strcmp(command, "xtal_cap_fine")) { userconfig_info.xtal_cap.xtal_cap_fine = rwnx_atoi(value); } else { AICWFDBG(LOGERROR, "invalid cmd: %s\n", command); } } void rwnx_plat_userconfig_parsing2(char *buffer, int size) { int i = 0; int parse_state = 0; char command[30]; char value[100]; int char_counter = 0; memset(command, 0, 30); memset(value, 0, 100); for (i = 0; i < size; i++) { //Send command or print nvram log when char is \r or \n if (buffer[i] == 0x0a || buffer[i] == 0x0d) { if (command[0] != 0 && value[0] != 0) { if (parse_state == PRINT) { AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); } else if (parse_state == GET_VALUE) { rwnx_plat_nvram_set_value(command, value); } } //Reset command value and char_counter memset(command, 0, 30); memset(value, 0, 100); char_counter = 0; parse_state = INIT; continue; } //Switch parser state if (parse_state == INIT) { if (buffer[i] == '#') { parse_state = PRINT; continue; } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { parse_state = INIT; continue; } else { parse_state = CMD; } } //Fill data to command and value if (parse_state == PRINT) { command[0] = 0x01; value[char_counter] = buffer[i]; char_counter++; } else if (parse_state == CMD) { if (command[0] != 0 && buffer[i] == '=') { parse_state = GET_VALUE; char_counter = 0; continue; } command[char_counter] = buffer[i]; char_counter++; } else if (parse_state == GET_VALUE) { value[char_counter] = buffer[i]; char_counter++; } } } void rwnx_plat_userconfig_parsing3(char *buffer, int size) { int i = 0; int parse_state = 0; char command[30]; char value[100]; int char_counter = 0; memset(command, 0, 30); memset(value, 0, 100); for (i = 0; i < size; i++) { //Send command or print nvram log when char is \r or \n if (buffer[i] == 0x0a || buffer[i] == 0x0d) { if (command[0] != 0 && value[0] != 0) { if (parse_state == PRINT) { AICWFDBG(LOGINFO, "%s:%s\r\n", __func__, value); } else if (parse_state == GET_VALUE) { rwnx_plat_nvram_set_value_v3(command, value); } } //Reset command value and char_counter memset(command, 0, 30); memset(value, 0, 100); char_counter = 0; parse_state = INIT; continue; } //Switch parser state if (parse_state == INIT) { if (buffer[i] == '#') { parse_state = PRINT; continue; } else if (buffer[i] == 0x0a || buffer[i] == 0x0d) { parse_state = INIT; continue; } else { parse_state = CMD; } } //Fill data to command and value if (parse_state == PRINT) { command[0] = 0x01; value[char_counter] = buffer[i]; char_counter++; } else if (parse_state == CMD) { if (command[0] != 0 && buffer[i] == '=') { parse_state = GET_VALUE; char_counter = 0; continue; } command[char_counter] = buffer[i]; char_counter++; } else if (parse_state == GET_VALUE) { value[char_counter] = buffer[i]; char_counter++; } } } void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int size) { char conf[100], keyname[64]; char *line; char *data; int i = 0, err, len = 0; long val; if (size <= 0) { pr_err("Config buffer size %d error\n", size); return; } printk("%s rwnx_hw->vendor_info:0x%02X \r\n", __func__, rwnx_hw->vendor_info); if (rwnx_hw->vendor_info == 0x00 || (rwnx_hw->vendor_info > (sizeof(parse_key_prefix) / sizeof(parse_key_prefix[0]) - 1))) { printk("Unsuppor vendor info config\n"); printk("Using module0 config\n"); rwnx_hw->vendor_info = 0x01; //return; } data = vmalloc(size + 1); if (!data) { pr_err("vmalloc fail\n"); return; } memcpy(data, buffer, size); buffer = data; while (1) { line = buffer; if (*line == 0) break; while (*buffer != '\r' && *buffer != '\n' && *buffer != 0 && len++ < size) buffer++; while ((*buffer == '\r' || *buffer == '\n') && len++ < size) *buffer++ = 0; if (len >= size) *buffer = 0; // store value to data struct for (i = 0; i < sizeof(parse_match_tab) / sizeof(parse_match_tab[0]); i++) { sprintf(&keyname[0], "%s%s", parse_key_prefix[rwnx_hw->vendor_info], parse_match_tab[i].keyname); if (parse_key_val(line, keyname, conf) == 0) { err = kstrtol(conf, 0, &val); *(unsigned long *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; printk("%s, %s = %ld\n", __func__, parse_match_tab[i].keyname, val); break; } } } vfree(data); } static int aic_load_firmware(u32 ** fw_buf, char *fw_path,const char *name, struct device *device) { #ifdef CONFIG_USE_FW_REQUEST const struct firmware *fw = NULL; u32 *dst = NULL; void *buffer=NULL; MD5_CTX md5; unsigned char decrypt[16]; int size = 0; int ret = 0; AICWFDBG(LOGINFO, "%s: request firmware = %s \n", __func__ ,name); ret = request_firmware(&fw, name, NULL); if (ret < 0) { AICWFDBG(LOGERROR, "Load %s fail\n", name); release_firmware(fw); return -1; } size = fw->size; dst = (u32 *)fw->data; if (size <= 0) { AICWFDBG(LOGERROR, "wrong size of firmware file\n"); release_firmware(fw); return -1; } buffer = vmalloc(size); memset(buffer, 0, size); memcpy(buffer, dst, size); *fw_buf = buffer; MD5Init(&md5); MD5Update(&md5, (unsigned char *)buffer, size); MD5Final(&md5, decrypt); AICWFDBG(LOGINFO, MD5PINRT, MD5(decrypt)); release_firmware(fw); return size; #else void *buffer=NULL; char *path=NULL; struct file *fp=NULL; int size = 0, len=0, i=0; ssize_t rdlen=0; u32 *src=NULL, *dst = NULL; /* get the firmware path */ path = __getname(); if (!path){ *fw_buf=NULL; return -1; } len = sprintf(path, "%s/%s",fw_path, name); AICWFDBG(LOGINFO, "%s :firmware path = %s \n", __func__ ,path); /* open the firmware file */ fp=filp_open(path, O_RDONLY, 0); if(IS_ERR(fp) || (!fp)){ printk("%s: %s file failed to open\n", __func__, name); if(IS_ERR(fp)){ printk("is_Err\n"); } if((!fp)){ printk("null\n"); } *fw_buf=NULL; __putname(path); fp=NULL; return -1; } size = i_size_read(file_inode(fp)); if(size<=0){ printk("%s: %s file size invalid %d\n", __func__, name, size); *fw_buf=NULL; __putname(path); filp_close(fp,NULL); fp=NULL; return -1; } /* start to read from firmware file */ buffer = vmalloc(size); memset(buffer, 0, size); if(!buffer){ *fw_buf=NULL; __putname(path); filp_close(fp,NULL); fp=NULL; return -1; } #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 16) rdlen = kernel_read(fp, buffer, size, &fp->f_pos); #else rdlen = kernel_read(fp, fp->f_pos, buffer, size); #endif if(size != rdlen){ printk("%s: %s file rdlen invalid %d %d\n", __func__, name, (int)rdlen, size); *fw_buf=NULL; __putname(path); filp_close(fp,NULL); fp=NULL; vfree(buffer); buffer=NULL; return -1; } if(rdlen > 0){ fp->f_pos += rdlen; //printk("f_pos=%d\n", (int)fp->f_pos); } /*start to transform the data format*/ src = (u32*)buffer; //printk("malloc dst\n"); dst = (u32*)vmalloc(size); memset(dst, 0, size); if(!dst){ *fw_buf=NULL; __putname(path); filp_close(fp,NULL); fp=NULL; vfree(buffer); buffer=NULL; return -1; } for(i=0;i<(size/4);i++){ dst[i] = src[i]; } __putname(path); filp_close(fp,NULL); fp=NULL; vfree(buffer); buffer=NULL; *fw_buf = dst; return size; #endif } #define FW_USERCONFIG_NAME "aic_userconfig.txt" int rwnx_plat_userconfig_upload_android(struct rwnx_hw *rwnx_hw, char *fw_path, char *filename) { int size; u32 *dst=NULL; printk("userconfig file path:%s \r\n", filename); /* load aic firmware */ size = aic_load_firmware(&dst, fw_path ,filename, NULL); if(size <= 0){ printk("wrong size of firmware file\n"); vfree(dst); dst = NULL; return 0; } /* Copy the file on the Embedded side */ printk("### Upload %s userconfig, size=%d\n", filename, size); rwnx_plat_userconfig_parsing(rwnx_hw, (char *)dst, size); if (dst) { vfree(dst); dst = NULL; } printk("userconfig download complete\n\n"); return 0; } /** * rwnx_plat_fmac_load() - Load FW code * * @rwnx_hw: Main driver data */ #if 0 static int rwnx_plat_fmac_load(struct rwnx_hw *rwnx_hw, char *fw_path) { int ret = 0; RWNX_DBG(RWNX_FN_ENTRY_STR); ret = rwnx_plat_userconfig_upload_android(rwnx_hw, fw_path, FW_USERCONFIG_NAME); return ret; } #endif /** * rwnx_platform_reset() - Reset the platform * * @rwnx_plat: platform data */ static int rwnx_platform_reset(struct rwnx_plat *rwnx_plat) { u32 regval; #if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) return 0; #endif /* the doc states that SOFT implies FPGA_B_RESET * adding FPGA_B_RESET is clearer */ RWNX_REG_WRITE(SOFT_RESET | FPGA_B_RESET, rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); msleep(100); regval = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); if (regval & SOFT_RESET) { dev_err(rwnx_platform_get_dev(rwnx_plat), "reset: failed\n"); return -EIO; } RWNX_REG_WRITE(regval & ~FPGA_B_RESET, rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR); msleep(100); return 0; } /** * rwmx_platform_save_config() - Save hardware config before reload * * @rwnx_plat: Pointer to platform data * * Return configuration registers values. */ static void *rwnx_term_save_config(struct rwnx_plat *rwnx_plat) { const u32 *reg_list; u32 *reg_value, *res; int i, size = 0; if (rwnx_plat->get_config_reg) { size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); } if (size <= 0) return NULL; res = kmalloc(sizeof(u32) * size, GFP_KERNEL); if (!res) return NULL; reg_value = res; for (i = 0; i < size; i++) { *reg_value++ = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, *reg_list++); } return res; } #if 0 /** * rwmx_platform_restore_config() - Restore hardware config after reload * * @rwnx_plat: Pointer to platform data * @reg_value: Pointer of value to restore * (obtained with rwmx_platform_save_config()) * * Restore configuration registers value. */ static void rwnx_term_restore_config(struct rwnx_plat *rwnx_plat, u32 *reg_value) { const u32 *reg_list; int i, size = 0; if (!reg_value || !rwnx_plat->get_config_reg) return; size = rwnx_plat->get_config_reg(rwnx_plat, ®_list); for (i = 0; i < size; i++) { RWNX_REG_WRITE(*reg_value++, rwnx_plat, RWNX_ADDR_SYSTEM, *reg_list++); } } #endif #ifndef CONFIG_RWNX_FHOST #if 0 static int rwnx_check_fw_compatibility(struct rwnx_hw *rwnx_hw) { struct ipc_shared_env_tag *shared = rwnx_hw->ipc_env->shared; #ifdef CONFIG_RWNX_FULLMAC struct wiphy *wiphy = rwnx_hw->wiphy; #endif //CONFIG_RWNX_FULLMAC #ifdef CONFIG_RWNX_OLD_IPC int ipc_shared_version = 10; #else //CONFIG_RWNX_OLD_IPC int ipc_shared_version = 11; #endif //CONFIG_RWNX_OLD_IPC int res = 0; if (shared->comp_info.ipc_shared_version != ipc_shared_version) { wiphy_err(wiphy, "Different versions of IPC shared version between driver and FW (%d != %d)\n ", ipc_shared_version, shared->comp_info.ipc_shared_version); res = -1; } if (shared->comp_info.radarbuf_cnt != IPC_RADARBUF_CNT) { wiphy_err(wiphy, "Different number of host buffers available for Radar events handling "\ "between driver and FW (%d != %d)\n", IPC_RADARBUF_CNT, shared->comp_info.radarbuf_cnt); res = -1; } if (shared->comp_info.unsuprxvecbuf_cnt != IPC_UNSUPRXVECBUF_CNT) { wiphy_err(wiphy, "Different number of host buffers available for unsupported Rx vectors "\ "handling between driver and FW (%d != %d)\n", IPC_UNSUPRXVECBUF_CNT, shared->comp_info.unsuprxvecbuf_cnt); res = -1; } #ifdef CONFIG_RWNX_FULLMAC if (shared->comp_info.rxdesc_cnt != IPC_RXDESC_CNT) { wiphy_err(wiphy, "Different number of shared descriptors available for Data RX handling "\ "between driver and FW (%d != %d)\n", IPC_RXDESC_CNT, shared->comp_info.rxdesc_cnt); res = -1; } #endif /* CONFIG_RWNX_FULLMAC */ if (shared->comp_info.rxbuf_cnt != IPC_RXBUF_CNT) { wiphy_err(wiphy, "Different number of host buffers available for Data Rx handling "\ "between driver and FW (%d != %d)\n", IPC_RXBUF_CNT, shared->comp_info.rxbuf_cnt); res = -1; } if (shared->comp_info.msge2a_buf_cnt != IPC_MSGE2A_BUF_CNT) { wiphy_err(wiphy, "Different number of host buffers available for Emb->App MSGs "\ "sending between driver and FW (%d != %d)\n", IPC_MSGE2A_BUF_CNT, shared->comp_info.msge2a_buf_cnt); res = -1; } if (shared->comp_info.dbgbuf_cnt != IPC_DBGBUF_CNT) { wiphy_err(wiphy, "Different number of host buffers available for debug messages "\ "sending between driver and FW (%d != %d)\n", IPC_DBGBUF_CNT, shared->comp_info.dbgbuf_cnt); res = -1; } if (shared->comp_info.bk_txq != NX_TXDESC_CNT0) { wiphy_err(wiphy, "Driver and FW have different sizes of BK TX queue (%d != %d)\n", NX_TXDESC_CNT0, shared->comp_info.bk_txq); res = -1; } if (shared->comp_info.be_txq != NX_TXDESC_CNT1) { wiphy_err(wiphy, "Driver and FW have different sizes of BE TX queue (%d != %d)\n", NX_TXDESC_CNT1, shared->comp_info.be_txq); res = -1; } if (shared->comp_info.vi_txq != NX_TXDESC_CNT2) { wiphy_err(wiphy, "Driver and FW have different sizes of VI TX queue (%d != %d)\n", NX_TXDESC_CNT2, shared->comp_info.vi_txq); res = -1; } if (shared->comp_info.vo_txq != NX_TXDESC_CNT3) { wiphy_err(wiphy, "Driver and FW have different sizes of VO TX queue (%d != %d)\n", NX_TXDESC_CNT3, shared->comp_info.vo_txq); res = -1; } #if NX_TXQ_CNT == 5 if (shared->comp_info.bcn_txq != NX_TXDESC_CNT4) { wiphy_err(wiphy, "Driver and FW have different sizes of BCN TX queue (%d != %d)\n", NX_TXDESC_CNT4, shared->comp_info.bcn_txq); res = -1; } #else if (shared->comp_info.bcn_txq > 0) { wiphy_err(wiphy, "BCMC enabled in firmware but disabled in driver\n"); res = -1; } #endif /* NX_TXQ_CNT == 5 */ if (shared->comp_info.ipc_shared_size != sizeof(ipc_shared_env)) { wiphy_err(wiphy, "Different sizes of IPC shared between driver and FW (%zd != %d)\n", sizeof(ipc_shared_env), shared->comp_info.ipc_shared_size); res = -1; } if (shared->comp_info.msg_api != MSG_API_VER) { wiphy_warn(wiphy, "WARNING: Different supported message API versions between "\ "driver and FW (%d != %d)\n", MSG_API_VER, shared->comp_info.msg_api); } return res; } #endif #endif /* !CONFIG_RWNX_FHOST */ void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl) { txpwr_lvl->enable = userconfig_info.txpwr_lvl.enable; txpwr_lvl->dsss = userconfig_info.txpwr_lvl.dsss; txpwr_lvl->ofdmlowrate_2g4 = userconfig_info.txpwr_lvl.ofdmlowrate_2g4; txpwr_lvl->ofdm64qam_2g4 = userconfig_info.txpwr_lvl.ofdm64qam_2g4; txpwr_lvl->ofdm256qam_2g4 = userconfig_info.txpwr_lvl.ofdm256qam_2g4; txpwr_lvl->ofdm1024qam_2g4 = userconfig_info.txpwr_lvl.ofdm1024qam_2g4; txpwr_lvl->ofdmlowrate_5g = userconfig_info.txpwr_lvl.ofdmlowrate_5g; txpwr_lvl->ofdm64qam_5g = userconfig_info.txpwr_lvl.ofdm64qam_5g; txpwr_lvl->ofdm256qam_5g = userconfig_info.txpwr_lvl.ofdm256qam_5g; txpwr_lvl->ofdm1024qam_5g = userconfig_info.txpwr_lvl.ofdm1024qam_5g; AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl->enable); AICWFDBG(LOGINFO, "%s:dsss:%d\r\n", __func__, txpwr_lvl->dsss); AICWFDBG(LOGINFO, "%s:ofdmlowrate_2g4:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_2g4); AICWFDBG(LOGINFO, "%s:ofdm64qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm64qam_2g4); AICWFDBG(LOGINFO, "%s:ofdm256qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm256qam_2g4); AICWFDBG(LOGINFO, "%s:ofdm1024qam_2g4:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_2g4); AICWFDBG(LOGINFO, "%s:ofdmlowrate_5g:%d\r\n", __func__, txpwr_lvl->ofdmlowrate_5g); AICWFDBG(LOGINFO, "%s:ofdm64qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm64qam_5g); AICWFDBG(LOGINFO, "%s:ofdm256qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm256qam_5g); AICWFDBG(LOGINFO, "%s:ofdm1024qam_5g:%d\r\n", __func__, txpwr_lvl->ofdm1024qam_5g); } void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2) { *txpwr_lvl_v2 = userconfig_info.txpwr_lvl_v2; AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v2->enable); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[10]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[11]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v2->pwrlvl_11n_11ac_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[10]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v2->pwrlvl_11ax_2g4[11]); } void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3) { *txpwr_lvl_v3 = userconfig_info.txpwr_lvl_v3; AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_v3->enable); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_1m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_2m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_5m5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_11m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_6m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_9m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_12m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_18m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_24m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_36m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_48m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[10]); AICWFDBG(LOGINFO, "%s:lvl_11b_11ag_54m_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[11]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_2g4:%d\r\n",__func__, txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[0]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[1]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[2]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[3]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[4]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[5]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[6]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[7]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[8]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[10]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_2g4:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_2g4[11]); AICWFDBG(LOGINFO, "%s:lvl_11a_1m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[0]); AICWFDBG(LOGINFO, "%s:lvl_11a_2m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[1]); AICWFDBG(LOGINFO, "%s:lvl_11a_5m5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[2]); AICWFDBG(LOGINFO, "%s:lvl_11a_11m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[3]); AICWFDBG(LOGINFO, "%s:lvl_11a_6m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[4]); AICWFDBG(LOGINFO, "%s:lvl_11a_9m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[5]); AICWFDBG(LOGINFO, "%s:lvl_11a_12m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[6]); AICWFDBG(LOGINFO, "%s:lvl_11a_18m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[7]); AICWFDBG(LOGINFO, "%s:lvl_11a_24m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[8]); AICWFDBG(LOGINFO, "%s:lvl_11a_36m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[9]); AICWFDBG(LOGINFO, "%s:lvl_11a_48m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[10]); AICWFDBG(LOGINFO, "%s:lvl_11a_54m_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11a_5g[11]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[0]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[1]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[2]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[3]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[4]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[5]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[6]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[7]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[8]); AICWFDBG(LOGINFO, "%s:lvl_11n_11ac_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11n_11ac_5g[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs0_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[0]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs1_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[1]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs2_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[2]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs3_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[3]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs4_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[4]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs5_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[5]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs6_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[6]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs7_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[7]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs8_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[8]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs9_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[9]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs10_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[10]); AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); } /** * rwnx_plat_userconfig_load ---Load aic_userconfig.txt *@filename name of config */ static int rwnx_plat_userconfig_load(struct rwnx_hw *rwnx_hw) { if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8801){ rwnx_plat_userconfig_upload_android(rwnx_hw, aic_fw_path, FW_USERCONFIG_NAME); }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC){ rwnx_plat_userconfig_load_8800dc(rwnx_hw); }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW){ rwnx_plat_userconfig_load_8800dw(rwnx_hw); }else if(rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ rwnx_plat_userconfig_load_8800d80(rwnx_hw); } return 0; } /** * rwnx_platform_on() - Start the platform * * @rwnx_hw: Main driver data * @config: Config to restore (NULL if nothing to restore) * * It starts the platform : * - load fw and ucodes * - initialize IPC * - boot the fw * - enable link communication/IRQ * * Called by 802.11 part */ int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config) { int ret; struct rwnx_plat *rwnx_plat = rwnx_hw->plat; (void)ret; RWNX_DBG(RWNX_FN_ENTRY_STR); if (rwnx_plat->enabled) return 0; #ifndef CONFIG_ROM_PATCH_EN #ifdef CONFIG_DOWNLOAD_FW ret = rwnx_plat_fmac_load(rwnx_hw, (char*)config); if (ret) return ret; #endif /* !CONFIG_ROM_PATCH_EN */ #endif #if 0 ret = rwnx_plat_patch_load(rwnx_hw); if (ret) { return ret; } #endif rwnx_plat_userconfig_load(rwnx_hw); //rwnx_plat->enabled = true; return 0; } /** * rwnx_platform_off() - Stop the platform * * @rwnx_hw: Main driver data * @config: Updated with pointer to config, to be able to restore it with * rwnx_platform_on(). It's up to the caller to free the config. Set to NULL * if configuration is not needed. * * Called by 802.11 part */ void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config) { #if defined(AICWF_USB_SUPPORT) || defined(AICWF_SDIO_SUPPORT) tasklet_kill(&rwnx_hw->task); rwnx_hw->plat->enabled = false; return ; #endif if (!rwnx_hw->plat->enabled) { if (config) *config = NULL; return; } if (config) *config = rwnx_term_save_config(rwnx_hw->plat); rwnx_hw->plat->disable(rwnx_hw); tasklet_kill(&rwnx_hw->task); rwnx_platform_reset(rwnx_hw->plat); rwnx_hw->plat->enabled = false; } /** * rwnx_platform_init() - Initialize the platform * * @rwnx_plat: platform data (already updated by platform driver) * @platform_data: Pointer to store the main driver data pointer (aka rwnx_hw) * That will be set as driver data for the platform driver * Return: 0 on success, < 0 otherwise * * Called by the platform driver after it has been probed */ int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data) { RWNX_DBG(RWNX_FN_ENTRY_STR); rwnx_plat->enabled = false; g_rwnx_plat = rwnx_plat; #if defined CONFIG_RWNX_FULLMAC return rwnx_cfg80211_init(rwnx_plat, platform_data); #elif defined CONFIG_RWNX_FHOST return rwnx_fhost_init(rwnx_plat, platform_data); #endif } /** * rwnx_platform_deinit() - Deinitialize the platform * * @rwnx_hw: main driver data * * Called by the platform driver after it is removed */ void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw) { RWNX_DBG(RWNX_FN_ENTRY_STR); #if defined CONFIG_RWNX_FULLMAC rwnx_cfg80211_deinit(rwnx_hw); #elif defined CONFIG_RWNX_FHOST rwnx_fhost_deinit(rwnx_hw); #endif } /** * rwnx_platform_register_drv() - Register all possible platform drivers */ int rwnx_platform_register_drv(void) { return rwnx_pci_register_drv(); } /** * rwnx_platform_unregister_drv() - Unegister all platform drivers */ void rwnx_platform_unregister_drv(void) { return rwnx_pci_unregister_drv(); } struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) { #ifdef AICWF_SDIO_SUPPORT return rwnx_plat->sdiodev->dev; #endif #ifdef AICWF_USB_SUPPORT return rwnx_plat->usbdev->dev; #endif return &(rwnx_plat->pci_dev->dev); } #ifndef CONFIG_RWNX_SDM MODULE_FIRMWARE(RWNX_AGC_FW_NAME); MODULE_FIRMWARE(RWNX_FCU_FW_NAME); MODULE_FIRMWARE(RWNX_LDPC_RAM_NAME); #endif MODULE_FIRMWARE(RWNX_MAC_FW_NAME); #ifndef CONFIG_RWNX_TL4 MODULE_FIRMWARE(RWNX_MAC_FW_NAME2); #endif