Files
aic8800d80/drivers/aic8800/aic_load_fw/aic_compat_8800d80.c
T

687 lines
28 KiB
C

#include "aic_txrxif.h"
#include "aicwf_usb.h"
#include "aicbluetooth.h"
#include "aic_compat_8800d80.h"
#include "aicwf_debug.h"
extern int ble_scan_wakeup_reboot_time;
extern uint32_t ad_data_filter_mask;
extern uint32_t gpio_num;//default select gpiob2 for fw_wakeup_host
extern uint32_t gpio_dft_lvl;//0:defalut pull down, 1:default pull up
int rwnx_plat_bin_fw_upload_2(struct aic_usb_dev *usbdev, u32 fw_addr,
char *filename);
int rwnx_request_firmware_common(struct aic_usb_dev *usbdev,
u32** buffer, const char *filename);
void rwnx_plat_userconfig_parsing(char *buffer, int size);
void rwnx_release_firmware_common(u32** buffer);
extern int testmode;
extern u8 chip_id;
extern u8 chip_mcu_id;
typedef u32 (*array2_tbl_t)[2];
#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH"
#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP"
#define AIC_PATCH_BLOCK_MAX 4
typedef struct {
uint32_t magic_num;
uint32_t pair_start;
uint32_t magic_num_2;
uint32_t pair_count;
uint32_t block_dst[AIC_PATCH_BLOCK_MAX];
uint32_t block_src[AIC_PATCH_BLOCK_MAX];
uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count
} aic_patch_t;
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
#define AIC_PATCH_ADDR(mem) ((u32) (aic_patch_str_base + AIC_PATCH_OFST(mem)))
#define USER_PWROFST_COVER_CALIB_FLAG (0x01U << 0)
#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1)
#define USER_TX_USE_ANA_F_FLAG (0x01U << 2)
#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3)
#define USER_HE_MU_EDCA_UPDATE_DISABLE_FLAG (0x01U << 4)
#define CFG_PWROFST_COVER_CALIB 1
#ifdef CONFIG_POWER_LIMIT
#define CFG_USER_CHAN_MAX_TXPWR_EN 1
#else
#define CFG_USER_CHAN_MAX_TXPWR_EN 0
#endif
#define CFG_USER_TX_USE_ANA_F 0
#ifdef CONFIG_BAND_STEERING
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 1
#else
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0
#endif
#define CFG_USER_EXT_FLAGS_EN (CFG_PWROFST_COVER_CALIB || CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F|| CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE)
u32 patch_tbl_d80[][2] =
{
#ifdef USE_5G
{0x00b4, 0xf3010001},
#else
{0x00b4, 0xf3010000},
#endif
#ifdef CONFIG_PLATFORM_HI
{0x0170, 0x00010001},//rx aggr counter
#else
{0x0170, 0x0001000A},//rx aggr counter
#endif
#if CFG_USER_EXT_FLAGS_EN
{0x0188, 0x00000000
#if CFG_PWROFST_COVER_CALIB
| USER_PWROFST_COVER_CALIB_FLAG
#endif
#if CFG_USER_CHAN_MAX_TXPWR_EN
| USER_CHAN_MAX_TXPWR_EN_FLAG
#endif
#if CFG_USER_TX_USE_ANA_F
| USER_TX_USE_ANA_F_FLAG
#endif
#if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE
| USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG
#endif
}, // user_ext_flags
#endif
#ifdef CONFIG_RADAR_OR_IR_DETECT
{0x0019c,0x00000B00},
#endif
};
//adap test
u32 adaptivity_patch_tbl_d80[][2] = {
{0x000C, 0x0000320A}, //linkloss_thd
{0x009C, 0x00000000}, //ac_param_conf
{0x0168, 0x00010000}, //tx_adaptivity_en
};
u32 syscfg_tbl_masked_8800d80[][3] = {
};
u32 syscfg_tbl_8800d80[][2] = {
#ifdef CONFIG_PMIC_SETTING
{0x70001408, 0x00000000}, // stop wdg
#endif /* CONFIG_PMIC_SETTING */
};
extern int adap_test;
#define NEW_PATCH_BUFFER_MAP 1
int aicwf_patch_config_8800d80(struct aic_usb_dev *usb_dev)
{
u32 rd_patch_addr;
u32 aic_patch_addr;
u32 config_base, aic_patch_str_base;
#if (NEW_PATCH_BUFFER_MAP)
u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val;
#endif
uint32_t start_addr = 0x001D7000;
u32 patch_addr = start_addr;
u32 patch_cnt = sizeof(patch_tbl_d80) / 4 / 2;
struct dbg_mem_read_cfm rd_patch_addr_cfm;
int ret = 0;
int cnt = 0;
//adap test
int adap_patch_cnt = 0;
if (adap_test) {
AICWFDBG(LOGINFO, "%s adap test \r\n", __func__);
adap_patch_cnt = sizeof(adaptivity_patch_tbl_d80)/sizeof(u32)/2;
}
if (chip_id == CHIP_REV_U01) {
rd_patch_addr = RAM_FMAC_FW_ADDR_8800D80 + 0x0198;
} else {
rd_patch_addr = RAM_FMAC_FW_ADDR_8800D80_U02 + 0x0198;
}
aic_patch_addr = rd_patch_addr + 8;
AICWFDBG(LOGERROR, "Read FW mem: %08x\n", rd_patch_addr);
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, rd_patch_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", rd_patch_addr, ret);
return ret;
}
AICWFDBG(LOGERROR, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
config_base = rd_patch_addr_cfm.memdata;
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, aic_patch_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "patch_str_base[0x%x] rd fail: %d\n", aic_patch_addr, ret);
return ret;
}
AICWFDBG(LOGERROR, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
aic_patch_str_base = rd_patch_addr_cfm.memdata;
#if (NEW_PATCH_BUFFER_MAP)
if (chip_id == CHIP_REV_U01) {
rd_version_addr = RAM_FMAC_FW_ADDR_8800D80 + 0x01C;
} else {
rd_version_addr = RAM_FMAC_FW_ADDR_8800D80_U02 + 0x01C;
}
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, rd_version_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "version val[0x%x] rd fail: %d\n", rd_version_addr, ret);
return ret;
}
rd_version_val = rd_patch_addr_cfm.memdata;
AICWFDBG(LOGINFO, "rd_version_val=%08X\n", rd_version_val);
usb_dev->fw_version_uint = rd_version_val;
if (rd_version_val > 0x06090100) {
patch_buff_addr = rd_patch_addr + 12;
ret = rwnx_send_dbg_mem_read_req(usb_dev, patch_buff_addr, &rd_patch_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "patch buf rd fail\n");
return ret;
}
AICWFDBG(LOGINFO, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
patch_buff_base = rd_patch_addr_cfm.memdata;
patch_addr = start_addr = patch_buff_base;
}
#endif
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM))) {
AICWFDBG(LOGERROR, "maigic_num[0x%x] write fail: %d\n", AIC_PATCH_ADDR(magic_num), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2))) {
AICWFDBG(LOGERROR, "maigic_num[0x%x] write fail: %d\n", AIC_PATCH_ADDR(magic_num_2), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(pair_start), patch_addr))) {
AICWFDBG(LOGERROR, "pair_start[0x%x] write fail: %d\n", AIC_PATCH_ADDR(pair_start), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt))) {
AICWFDBG(LOGERROR, "pair_count[0x%x] write fail: %d\n", AIC_PATCH_ADDR(pair_count), ret);
return ret;
}
for (cnt = 0; cnt < patch_cnt; cnt++) {
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt, patch_tbl_d80[cnt][0]+config_base))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt+4, patch_tbl_d80[cnt][1]))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
if (adap_test){
int tmp_cnt = patch_cnt + adap_patch_cnt;
for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) {
int tbl_idx = cnt - patch_cnt;
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt, adaptivity_patch_tbl_d80[tbl_idx][0]+config_base))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt+4, adaptivity_patch_tbl_d80[tbl_idx][1]))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
}
/*
* Patch block 0 ~ 3, that is void by default, can be set as:
*
* const u32 patch_block_0[3] = {0x11223344, 0x55667788, 0xaabbccdd};
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_dst[0]), 0x160000))) {
* printk("block_dst [0x%x] write fail: %d\n", (u32)(&aic_patch->block_dst[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_src[0]), 0x307000))) {
* printk("block_src [0x%x] write fail: %d\n", (u32)(&aic_patch->block_src[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_size[0]), sizeof(patch_block_0) / sizeof(u32)))) {
* printk("block_size[0x%x] write fail: %d\n", (u32)(&aic_patch->block_size[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_block_write_req(usb_dev, 0x307000, sizeof(patch_block_0), patch_block_0))) {
* printk("blk set fail: %d\n", ret);
* }
*/
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[0]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[1]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[2]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[3]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret);
return ret;
}
return 0;
}
#if 0
extern char aic_fw_path[200];
int rwnx_plat_userconfig_load_8800d80(struct aic_usb_dev *usb_dev){
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800D80;
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
/* load file */
size = rwnx_request_firmware_common(usb_dev, &dst, filename);
if (size <= 0) {
AICWFDBG(LOGERROR, "wrong size of firmware file\n");
dst = NULL;
return 0;
}
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_userconfig_parsing((char *)dst, size);
rwnx_release_firmware_common(&dst);
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
return 0;
}
#endif
int system_config_8800d80(struct aic_usb_dev *usb_dev){
int syscfg_num;
int ret, cnt;
const u32 mem_addr = 0x40500000;
const u32 cache_mem_addr = 0x40100020;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
if (((rd_mem_addr_cfm.memdata >> 25) & 0x01UL) == 0x00UL) {
chip_mcu_id = 1;
}
chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16);
printk("chip_id=%x, chip_mcu_id = %d\n", chip_id, chip_mcu_id);
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(usb_dev, cache_mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
rd_mem_addr_cfm.memdata |= 0x01;
ret = rwnx_send_dbg_mem_write_req(usb_dev, cache_mem_addr, rd_mem_addr_cfm.memdata);
if (ret) {
printk("%x write fail: %d\n", cache_mem_addr, ret);
return ret;
}
}
#if 1
syscfg_num = sizeof(syscfg_tbl_8800d80) / sizeof(u32) / 2;
for (cnt = 0; cnt < syscfg_num; cnt++) {
ret = rwnx_send_dbg_mem_write_req(usb_dev, syscfg_tbl_8800d80[cnt][0], syscfg_tbl_8800d80[cnt][1]);
if (ret) {
printk("%x write fail: %d\n", syscfg_tbl_8800d80[cnt][0], ret);
return ret;
}
}
syscfg_num = sizeof(syscfg_tbl_masked_8800d80) / sizeof(u32) / 3;
for (cnt = 0; cnt < syscfg_num; cnt++) {
ret = rwnx_send_dbg_mem_mask_write_req(usb_dev,
syscfg_tbl_masked_8800d80[cnt][0], syscfg_tbl_masked_8800d80[cnt][1], syscfg_tbl_masked_8800d80[cnt][2]);
if (ret) {
printk("%x mask write fail: %d\n", syscfg_tbl_masked_8800d80[cnt][0], ret);
return ret;
}
}
#endif
return 0;
}
static int aicbt_ext_patch_data_load(struct aic_usb_dev *usb_dev, struct aicbt_patch_info_t *patch_info)
{
int ret = 0;
uint32_t ext_patch_nb = patch_info->ext_patch_nb;
char ext_patch_file_name[50];
int index = 0;
uint32_t id = 0;
uint32_t addr = 0;
if (ext_patch_nb > 0){
for (index = 0; index < patch_info->ext_patch_nb; index++){
id = *(patch_info->ext_patch_param + (index * 2));
addr = *(patch_info->ext_patch_param + (index * 2) + 1);
memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name));
sprintf(ext_patch_file_name,"%s%d.bin",
FW_PATCH_BASE_NAME_8800D80_U02_EXT,
id);
AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n",
__func__,ext_patch_file_name, id, addr);
if (rwnx_plat_bin_fw_upload_android(usb_dev, addr, ext_patch_file_name)) {
ret = -1;
break;
}
}
}
return ret;
}
int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
{
struct aicbt_patch_table *head = NULL;
struct aicbt_patch_info_t patch_info = {
.info_len = 0,
.adid_addrinf = 0,
.addr_adid = 0,
.patch_addrinf = 0,
.addr_patch = 0,
.reset_addr = 0,
.reset_val = 0,
.adid_flag_addr = 0,
.adid_flag = 0,
};
int i = 0;
if (chip_id == CHIP_REV_U01) {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80);
} else {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80_U02);
}
if (head == NULL){
printk("aicbt_patch_table_alloc fail\n");
return -1;
}
if(head == NULL){
return -1;
}
if (chip_id == CHIP_REV_U01) {
patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80;
patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80;
} else if (chip_id == CHIP_REV_U02 || chip_id == CHIP_REV_U03) {
patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80_U02;
patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80_U02;
}
aicbt_patch_info_unpack(&patch_info, head);
if(patch_info.info_len == 0) {
printk("%s, aicbt_patch_info_unpack fail\n", __func__);
return -1;
}
printk("addr_adid 0x%x, addr_patch 0x%x\n", patch_info.addr_adid, patch_info.addr_patch);
if(testmode == FW_NORMAL_MODE){
if (chip_id != CHIP_REV_U01){
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80_U02)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
if (IS_CHIP_ID_H()){
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_H_U02))
return -1;
} else {
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_U02))
return -1;
}
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, FW_RAM_CALIBMODE_ADDR_8800D80_U02, FW_CALIBMODE_NAME_8800D80_U02)) {
return -1;
}
if (rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, 0x1e0000))
return -1;
#endif
if (aicwf_patch_config_8800d80(usb_dev)) {
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, HOST_START_APP_AUTO)) {
return -1;
}
}else {
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80)) {
return -1;
}
#if 0
if (rwnx_plat_bin_fw_patch_table_upload_android(usb_dev, FW_PATCH_TABLE_NAME_8800D80)) {
return -1;
}
#else
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80, FW_BASE_NAME_8800D80)) {
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80, HOST_START_APP_AUTO)) {
return -1;
}
}
}else if(testmode == FW_TEST_MODE){
if (chip_id != CHIP_REV_U01){
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80_U02)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
if (chip_mcu_id) {
int ret = 0;
ret = rwnx_plat_flash_bin_upload_android(usb_dev, FLASH_BIN_ADDR_8800M80, FLASH_BIN_8800M80);
if (ret && ret!= ENOENT) {
AICWFDBG(LOGERROR,"%s flash bin download fail \r\n", __func__);
return -1;
}
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80_U02, FW_RF_BASE_NAME_8800D80_U02)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80_U02, HOST_START_APP_AUTO)) {
return -1;
}
} else {
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80, FW_RF_BASE_NAME_8800D80)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80, HOST_START_APP_AUTO)) {
return -1;
}
}
}else if(testmode == FW_BLE_SCAN_AD_FILTER_MODE){
/*
data and ad_data_filter_mask instructions for use
ex.
data[18] = {0x46,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x30,0xff,0xff,0xff,0x43,0x52,0x45,0x4c,0x42};
mask = 1100 0000 0111 1111 1100 0000 0000 0000 = 0xc07fc000
data = 0x46,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x30,0xff,0xff,0xff,0x43,0x52,0x45,0x4c,0x42
mask = 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0...... fill 0
data & mask = "0x46 0x00" 0x00 0x00 0x00 0x00 0x00 0x00 0x00 "0x30 0xff 0xff 0x43 0x52 0x45 0x4c 0x42"
using data & mask value condition to wakeup host_wake_bt gpio
*/
struct ble_wakeup_param_t* wakeup_param = (struct ble_wakeup_param_t*)kmalloc(sizeof(struct ble_wakeup_param_t), GFP_KERNEL);
uint32_t *write_blocks = (uint32_t *)wakeup_param;
printk("%s ble scan wakeup \r\n", __func__);
memset(wakeup_param, 0, sizeof(struct ble_wakeup_param_t));
rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80, FW_BLE_SCAN_AD_FILTER_NAME);
wakeup_param->magic_num = 0x53454C42;//magic_num
wakeup_param->delay_scan_to = 1000;//delay start scan time(ms)
wakeup_param->reboot_to = ble_scan_wakeup_reboot_time;//reboot time
/******************************************************************/
///gpio_trigger_idx : 0 if wakeup_param->gpio_dft_lvl[0]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[0] = gpio_num;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[0] = gpio_dft_lvl;////0:defalut pull down, 1:default pull up
///gpio_trigger_idx : 1 if wakeup_param->gpio_dft_lvl[1]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[1] = 3;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[1] = 1;////0:defalut pull down, 1:default pull up
/********************************************************************/
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 0
{
const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[0].ad_len = 12;
wakeup_param->ad_filter[0].ad_type = 0x09;
memcpy(wakeup_param->ad_filter[0].ad_data, data,wakeup_param->ad_filter[0].ad_len-1);// 1111 1111 1110 0000 0000 0000 0000 0000 //0xffe00000
wakeup_param->ad_filter[0].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[0].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[0].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[0].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 1
{
const uint8_t data[2] = {0x12,0x18};
wakeup_param->ad_filter[1].ad_len = 3;
wakeup_param->ad_filter[1].ad_type = 0x3;
memcpy(wakeup_param->ad_filter[1].ad_data, data,wakeup_param->ad_filter[1].ad_len-1);// 1100 0000 0000 0000 0000 0000 0000 0000 //0xc0000000
wakeup_param->ad_filter[1].ad_data_mask = 0xc0000000;
wakeup_param->ad_filter[1].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[1].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[1].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 2
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[2].ad_len = 0;
wakeup_param->ad_filter[2].ad_type = 0;
//memcpy(wakeup_param->ad_filter[2].ad_data, data,wakeup_param->ad_filter[2].ad_len-1);// 1100 0000 0111 1111 1100 0000 0000 0000 //0xc07fc000
wakeup_param->ad_filter[2].ad_data_mask = 0;
wakeup_param->ad_filter[2].ad_role = ROLE_ONLY;
wakeup_param->ad_filter[2].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[2].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 3
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[3].ad_len = 0;
wakeup_param->ad_filter[3].ad_type = 0;
//memcpy(wakeup_param->ad_filter[2].ad_data, data,wakeup_param->ad_filter[2].ad_len-1);// 1100 0000 0111 1111 1100 0000 0000 0000 //0xc07fc000
wakeup_param->ad_filter[3].ad_data_mask = 0;
wakeup_param->ad_filter[3].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[3].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[3].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 4
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[4].ad_len = 0;
wakeup_param->ad_filter[4].ad_type = 0x09;
//memcpy(wakeup_param->ad_filter[4].ad_data, data,wakeup_param->ad_filter[4].ad_len-1);// 1111 1111 1110 0000 0000 0000 0000 0000 //0xffe00000
wakeup_param->ad_filter[4].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[4].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[4].gpio_trigger_idx = TG_IDX_0|TG_IDX_1;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[4].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[5] = 0;
}
for(i = 0; i < (sizeof(struct ble_wakeup_param_t)/4 +1); i++){
printk("write_blocks[%d]:0x%08X \r\n", i, write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FE00 + (4 * i), write_blocks[i]);
}
rwnx_send_dbg_start_app_req(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80, HOST_START_APP_AUTO);
kfree(wakeup_param);
return -1;
}
return 0;
}