1948 lines
71 KiB
C
1948 lines
71 KiB
C
/**
|
|
******************************************************************************
|
|
*
|
|
* @file rwnx_platform.c
|
|
*
|
|
* Copyright (C) RivieraWaves 2012-2019
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
#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 <linux/firmware.h>
|
|
#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
|
|
|
|
|