From d4a1bd480003f3e1a0590bc46fbcb24f05652ca7 Mon Sep 17 00:00:00 2001
From: tzh <tanzhtanzh@gmail.com>
Date: Thu, 15 Aug 2024 06:56:47 +0000
Subject: [PATCH] feat(wfit/bt): update aic8800 wifi/bt drive and hal

---
 longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c |  495 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 326 insertions(+), 169 deletions(-)

diff --git a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c
old mode 100644
new mode 100755
index 996ea71..8d3b269
--- a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c
+++ b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c
@@ -13,9 +13,21 @@
 
 #include <linux/list.h>
 #include <linux/version.h>
+#include <linux/firmware.h>
 #include "aicsdio_txrxif.h"
 #include "aicsdio.h"
 #include "aic_bsp_driver.h"
+
+static u8 binding_enc_data[16];
+static bool need_binding_verify;
+
+int wcn_bind_verify_calculate_verify_data(uint8_t *din, uint8_t *dout);
+#ifndef CONFIG_PLATFORM_ALLWINNER
+int wcn_bind_verify_calculate_verify_data(uint8_t *din, uint8_t *dout)
+{
+	return 0;
+}
+#endif
 
 static void cmd_dump(const struct rwnx_cmd *cmd)
 {
@@ -45,6 +57,7 @@
 static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
 {
 	bool defer_push = false;
+	int err = 0;
 
 	spin_lock_bh(&cmd_mgr->lock);
 
@@ -98,7 +111,7 @@
 
 	if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) {
 		unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz);
-		if (!wait_for_completion_killable_timeout(&cmd->complete, tout)) {
+		if (!wait_for_completion_timeout(&cmd->complete, tout)) {
 			printk(KERN_CRIT"cmd timed-out\n");
 			cmd_dump(cmd);
 			spin_lock_bh(&cmd_mgr->lock);
@@ -108,6 +121,7 @@
 				cmd_complete(cmd_mgr, cmd);
 			}
 			spin_unlock_bh(&cmd_mgr->lock);
+			err = -ETIMEDOUT;
 		} else {
 			kfree(cmd);
 		}
@@ -115,7 +129,7 @@
 		cmd->result = 0;
 	}
 
-	return 0;
+	return err;
 }
 
 static int cmd_mgr_run_callback(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd,
@@ -178,9 +192,6 @@
 	struct rwnx_cmd *cur;
 
 	spin_lock_bh(&cmd_mgr->lock);
-	printk("q_sz/max: %2d / %2d - next tkn: %d\n",
-			 cmd_mgr->queue_sz, cmd_mgr->max_queue_sz,
-			 cmd_mgr->next_tkn);
 	list_for_each_entry(cur, &cmd_mgr->cmds, list) {
 		cmd_dump(cur);
 	}
@@ -301,7 +312,7 @@
 	struct lmac_msg *msg;
 	struct rwnx_cmd *cmd;
 	bool nonblock;
-	int ret;
+	int ret = 0;
 
 	msg = container_of((void *)msg_params, struct lmac_msg, param);
 	if (sdiodev->bus_if->state == BUS_DOWN_ST) {
@@ -332,7 +343,7 @@
 	if (!reqcfm)
 		kfree(cmd);
 
-	return 0;
+	return ret;
 }
 
 
@@ -413,27 +424,53 @@
 	return rwnx_send_msg(sdiodev, mem_mask_write_req, 1, DBG_MEM_MASK_WRITE_CFM, NULL);
 }
 
+int rwnx_send_dbg_binding_req(struct aic_sdio_dev *sdiodev, u8 *dout, u8 *binding_status)
+{
+	struct dbg_binding_req *binding_req;
 
-int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type)
+	/* Build the DBG_BINDING_REQ message */
+	binding_req = rwnx_msg_zalloc(DBG_BINDING_REQ, TASK_DBG, DRV_TASK_ID,
+									sizeof(struct dbg_binding_req));
+	if (!binding_req)
+		return -ENOMEM;
+
+	memcpy(binding_req->driver_data, dout, 16);
+
+	/* Send the DBG_MEM_MASK_WRITE_REQ message to LMAC FW */
+	return rwnx_send_msg(sdiodev, binding_req, 1, DBG_BINDING_CFM, binding_status);
+}
+
+int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm)
 {
 	struct dbg_start_app_req *start_app_req;
 
 	/* Build the DBG_START_APP_REQ message */
 	start_app_req = rwnx_msg_zalloc(DBG_START_APP_REQ, TASK_DBG, DRV_TASK_ID,
 									sizeof(struct dbg_start_app_req));
-	if (!start_app_req)
+	if (!start_app_req) {
+		printk("start app nomen\n");
 		return -ENOMEM;
+	}
 
 	/* Set parameters for the DBG_START_APP_REQ message */
 	start_app_req->bootaddr = boot_addr;
 	start_app_req->boottype = boot_type;
 
 	/* Send the DBG_START_APP_REQ message to LMAC FW */
-	return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, NULL);
+	return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, start_app_cfm);
 }
 
+static inline int dbg_binding_ind(struct rwnx_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+	struct dbg_binding_ind *ind = (struct dbg_binding_ind *)msg->param;
+	memcpy(binding_enc_data, ind->enc_data, 16);
+	need_binding_verify = true;
+
+	return 0;
+}
 
 static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = {
+	[MSG_I(DBG_BINDING_IND)] = (msg_cb_fct)dbg_binding_ind,
 };
 
 static msg_cb_fct *msg_hdlrs[] = {
@@ -446,129 +483,29 @@
 							msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]);
 }
 
-#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
-
-static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device)
-{
-	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 = snprintf(path, AICBSP_FW_PATH_MAX, "%s/%s", AICBSP_FW_PATH, name);
-	if (len >= AICBSP_FW_PATH_MAX) {
-		printk("%s: %s file's path too long\n", __func__, name);
-		*fw_buf = NULL;
-		__putname(path);
-		return -1;
-	}
-
-	printk("%s :firmware path = %s  \n", __func__, path);
-
-	/* open the firmware file */
-	fp = filp_open(path, O_RDONLY, 0);
-	if (IS_ERR_OR_NULL(fp)) {
-		printk("%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) {
-		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 = 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) {
-		printk("%s: %s file rdlen invalid %ld\n", __func__, name, 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;
-
-	return size;
-}
-
 int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr,
 							   const char *filename)
 {
-	struct device *dev = sdiodev->dev;
 	unsigned int i = 0;
 	int size;
 	u32 *dst = NULL;
 	int err = 0;
 
-	/* load aic firmware */
-	size = rwnx_load_firmware(&dst, filename, dev);
+	const struct firmware *fw = NULL;
+	int ret = request_firmware(&fw, filename, NULL);
+
+	printk("rwnx_request_firmware, name: %s\n", filename);
+	if (ret < 0) {
+		printk("Load %s fail\n", filename);
+		return ret;
+	}
+
+	size = fw->size;
+	dst = (u32 *)fw->data;
+
 	if (size <= 0) {
 		printk("wrong size of firmware file\n");
-		kfree(dst);
-		dst = NULL;
+		release_firmware(fw);
 		return -1;
 	}
 
@@ -590,11 +527,7 @@
 		}
 	}
 
-	if (dst) {
-		kfree(dst);
-		dst = NULL;
-	}
-
+	release_firmware(fw);
 	return err;
 }
 
@@ -618,8 +551,18 @@
 	int size;
 	struct aicbt_patch_table *head = NULL, *new = NULL, *cur = NULL;
 
-	/* load aic firmware */
-	size = rwnx_load_firmware((u32 **)&rawdata, filename, NULL);
+	const struct firmware *fw = NULL;
+	int ret = request_firmware(&fw, filename, NULL);
+
+	printk("rwnx_request_firmware, name: %s\n", filename);
+	if (ret < 0) {
+		printk("Load %s fail\n", filename);
+		return NULL;
+	}
+
+	rawdata = (uint8_t *)fw->data;
+	size = fw->size;
+
 	if (size <= 0) {
 		printk("wrong size of firmware file\n");
 		goto err;
@@ -657,40 +600,66 @@
 		memcpy(cur->data, p, cur->len * 8);
 		p += cur->len * 8;
 	}
-	kfree(rawdata);
+	release_firmware(fw);
 	return head;
 
 err:
 	aicbt_patch_table_free(&head);
-	if (rawdata)
-		kfree(rawdata);
+	release_firmware(fw);
 	return NULL;
 }
 
-bool aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev)
+int aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev)
 {
-	if (rwnx_plat_bin_fw_upload_android(sdiodev, FW_RAM_ADID_BASE_ADDR, aicbsp_firmware_list[aicbsp_mode_index].bt_adid))
-		return false;
-	if (rwnx_plat_bin_fw_upload_android(sdiodev, FW_RAM_PATCH_BASE_ADDR, aicbsp_firmware_list[aicbsp_mode_index].bt_patch))
-		return false;
-	if (aicbsp_firmware_list[aicbsp_mode_index].bt_patch_test &&
-		rwnx_plat_bin_fw_upload_android(sdiodev, FW_PATCH_TEST_BASE_ADDR, aicbsp_firmware_list[aicbsp_mode_index].bt_patch_test))
-		return false;
-	return true;
+	uint32_t fw_ram_adid_base_addr = FW_RAM_ADID_BASE_ADDR;
+	if (aicbsp_info.chip_rev != CHIP_REV_U02)
+		fw_ram_adid_base_addr = FW_RAM_ADID_BASE_ADDR_U03;
+
+	if (rwnx_plat_bin_fw_upload_android(sdiodev, fw_ram_adid_base_addr, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid))
+		return -1;
+	if (rwnx_plat_bin_fw_upload_android(sdiodev, FW_RAM_PATCH_BASE_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch))
+		return -1;
+	return 0;
 }
+
+static struct aicbt_info_t aicbt_info = {
+	.btmode        = AICBT_BTMODE_DEFAULT,
+	.btport        = AICBT_BTPORT_DEFAULT,
+	.uart_baud     = AICBT_UART_BAUD_DEFAULT,
+	.uart_flowctrl = AICBT_UART_FC_DEFAULT,
+	.lpm_enable    = AICBT_LPM_ENABLE_DEFAULT,
+	.txpwr_lvl     = AICBT_TXPWR_LVL_DEFAULT,
+};
 
 int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev)
 {
 	struct aicbt_patch_table *head, *p;
 	int ret = 0, i;
 	uint32_t *data = NULL;
-	head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_mode_index].bt_table);
+	head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table);
 	for (p = head; p != NULL; p = p->next) {
 		data = p->data;
 		if (AICBT_PT_BTMODE == p->type) {
-			ret = rwnx_send_dbg_mem_write_req(sdiodev, *data, aicbsp_mode_index);
+			*(data + 1)  = aicbsp_info.hwinfo < 0;
+			*(data + 3)  = aicbsp_info.hwinfo;
+			*(data + 5)  = aicbsp_info.cpmode;
+
+			*(data + 7)  = aicbt_info.btmode;
+			*(data + 9)  = aicbt_info.btport;
+			*(data + 11) = aicbt_info.uart_baud;
+			*(data + 13) = aicbt_info.uart_flowctrl;
+			*(data + 15) = aicbt_info.lpm_enable;
+			*(data + 17) = aicbt_info.txpwr_lvl;
+
+			printk("%s bt uart baud: %d, flowctrl: %d, lpm_enable: %d, tx_pwr: %d\n", __func__,
+						aicbt_info.uart_baud, aicbt_info.uart_flowctrl, aicbt_info.lpm_enable, aicbt_info.txpwr_lvl);
+		}
+
+		if (AICBT_PT_VER == p->type) {
+			printk("aicbsp: bt patch version: %s\n", (char *)p->data);
 			continue;
 		}
+
 		for (i = 0; i < p->len; i++) {
 			ret = rwnx_send_dbg_mem_write_req(sdiodev, *data, *(data + 1));
 			if (ret != 0)
@@ -704,10 +673,19 @@
 	return 0;
 }
 
-void aicbt_init(struct aic_sdio_dev *sdiodev)
+int aicbt_init(struct aic_sdio_dev *sdiodev)
 {
-	aicbt_patch_trap_data_load(sdiodev);
-	aicbt_patch_table_load(sdiodev);
+	if (aicbt_patch_trap_data_load(sdiodev)) {
+		printk("aicbt_patch_trap_data_load fail\n");
+		return -1;
+	}
+
+	if (aicbt_patch_table_load(sdiodev)) {
+		 printk("aicbt_patch_table_load fail\n");
+		return -1;
+	}
+
+	return 0;
 }
 
 static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev)
@@ -716,12 +694,15 @@
 
 	/* memory access */
 	const u32 fw_addr = RAM_FMAC_FW_ADDR;
+	struct dbg_start_app_cfm start_app_cfm;
 
 	/* fw start */
-	ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO);
+	ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm);
 	if (ret) {
 		return -1;
 	}
+	aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF;
+
 	return 0;
 }
 
@@ -736,7 +717,7 @@
 	{0x40344058, 0x00800000, 0x00000000},// pll trx
 };
 
-static void aicwifi_sys_config(struct aic_sdio_dev *sdiodev)
+static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev)
 {
 	int ret, cnt;
 	int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3;
@@ -745,6 +726,7 @@
 			syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]);
 		if (ret) {
 			printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret);
+			return ret;
 		}
 	}
 
@@ -752,10 +734,13 @@
 				rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]);
 	if (ret) {
 		printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret);
+		return ret;
 	}
+
+	return 0;
 }
 
-static void aicwifi_patch_config(struct aic_sdio_dev *sdiodev)
+static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev)
 {
 	const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180;
 	u32 config_base;
@@ -765,53 +750,79 @@
 	struct dbg_mem_read_cfm rd_patch_addr_cfm;
 	int ret = 0;
 	u16 cnt = 0;
+	u32 patch_addr_reg = 0x1e5318;
+	u32 patch_num_reg = 0x1e531c;
+
+	if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) {
+		patch_addr_reg = 0x1e5304;
+		patch_num_reg = 0x1e5308;
+	}
 
 	ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm);
 	if (ret) {
 		printk("patch rd fail\n");
+		return ret;
 	}
 
 	config_base = rd_patch_addr_cfm.memdata;
 
-	ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x1e4d28, patch_addr);
+	ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr);
 	if (ret) {
-		printk("%x write fail\n", 0x1e4d28);
+		printk("0x%x write fail\n", patch_addr_reg);
+		return ret;
 	}
 
-	ret = rwnx_send_dbg_mem_write_req(sdiodev, 0x1e4d2c, patch_num);
+	ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num);
 	if (ret) {
-		printk("%x write fail\n", 0x1e4d2c);
+		printk("0x%x write fail\n", patch_num_reg);
+		return ret;
 	}
 
 	for (cnt = 0; cnt < patch_num/2; cnt += 1) {
 		ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base);
 		if (ret) {
 			printk("%x write fail\n", start_addr+8*cnt);
+			return ret;
 		}
 
 		ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]);
 		if (ret) {
 			printk("%x write fail\n", start_addr+8*cnt+4);
+			return ret;
 		}
 	}
+
+	return 0;
 }
 
-void aicwifi_init(struct aic_sdio_dev *sdiodev)
+int aicwifi_init(struct aic_sdio_dev *sdiodev)
 {
-	if (rwnx_plat_bin_fw_upload_android(sdiodev, FW_WIFI_RAM_ADDR, aicbsp_firmware_list[aicbsp_mode_index].wl_fw)) {
+	if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) {
 		printk("download wifi fw fail\n");
-		return;
+		return -1;
 	}
 
-	aicwifi_patch_config(sdiodev);
-	aicwifi_sys_config(sdiodev);
+	if (aicwifi_patch_config(sdiodev)) {
+		printk("aicwifi_patch_config fail\n");
+		return -1;
+	}
 
-	aicwifi_start_from_bootrom(sdiodev);
+	if (aicwifi_sys_config(sdiodev)) {
+		printk("aicwifi_sys_config fail\n");
+		return -1;
+	}
+
+	if (aicwifi_start_from_bootrom(sdiodev)) {
+		printk("wifi start fail\n");
+		return -1;
+	}
+
+	return 0;
 }
 
 u32 aicbsp_syscfg_tbl[][2] = {
-	{0x40500014, 0x00000102}, // 1)
-	{0x40500018, 0x0000010D}, // 2)
+	{0x40500014, 0x00000101}, // 1)
+	{0x40500018, 0x00000109}, // 2)
 	{0x40500004, 0x00000010}, // 3) the order should not be changed
 
 	// def CONFIG_PMIC_SETTING
@@ -826,7 +837,7 @@
 	{0x50017008, 0x00000000}, // 4) stop wdg
 };
 
-static void aicbsp_system_config(struct aic_sdio_dev *sdiodev)
+static int aicbsp_system_config(struct aic_sdio_dev *sdiodev)
 {
 	int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2;
 	int ret, cnt;
@@ -834,15 +845,16 @@
 		ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]);
 		if (ret) {
 			sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret);
+			return ret;
 		}
 	}
+	return 0;
 }
 
 int aicbsp_platform_init(struct aic_sdio_dev *sdiodev)
 {
 	rwnx_cmd_mgr_init(&sdiodev->cmd_mgr);
 	sdiodev->cmd_mgr.sdiodev = (void *)sdiodev;
-	aicbsp_system_config(sdiodev);
 	return 0;
 }
 
@@ -851,18 +863,163 @@
 	(void)sdiodev;
 }
 
-void aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev)
+int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev)
 {
-	aicbt_init(sdiodev);
-	aicwifi_init(sdiodev);
+	const u32 mem_addr = 0x40500000;
+	struct dbg_mem_read_cfm rd_mem_addr_cfm;
+
+	uint8_t binding_status;
+	uint8_t dout[16];
+
+	need_binding_verify = false;
+
+	if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm))
+		return -1;
+
+	aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16);
+	if (aicbsp_info.chip_rev != CHIP_REV_U02 &&
+		aicbsp_info.chip_rev != CHIP_REV_U03 &&
+		aicbsp_info.chip_rev != CHIP_REV_U04) {
+		pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev);
+		return -1;
+	}
+
+	printk("aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chip_rev);
+
+	if (aicbsp_info.chip_rev != CHIP_REV_U02)
+		aicbsp_firmware_list = fw_u03;
+
+	if (aicbsp_system_config(sdiodev))
+		return -1;
+
+	if (aicbt_init(sdiodev))
+		return -1;
+
+	if (aicwifi_init(sdiodev))
+		return -1;
+
+	if (need_binding_verify) {
+		printk("aicbsp: crypto data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+						binding_enc_data[0],  binding_enc_data[1],  binding_enc_data[2],  binding_enc_data[3],
+						binding_enc_data[4],  binding_enc_data[5],  binding_enc_data[6],  binding_enc_data[7],
+						binding_enc_data[8],  binding_enc_data[9],  binding_enc_data[10], binding_enc_data[11],
+						binding_enc_data[12], binding_enc_data[13], binding_enc_data[14], binding_enc_data[15]);
+
+		/* calculate verify data from crypto data */
+		if (wcn_bind_verify_calculate_verify_data(binding_enc_data, dout)) {
+			pr_err("aicbsp: %s, binding encrypt data incorrect\n", __func__);
+			return -1;
+		}
+
+		printk("aicbsp: verify data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+						dout[0],  dout[1],  dout[2],  dout[3],
+						dout[4],  dout[5],  dout[6],  dout[7],
+						dout[8],  dout[9],  dout[10], dout[11],
+						dout[12], dout[13], dout[14], dout[15]);
+
+		if (rwnx_send_dbg_binding_req(sdiodev, dout, &binding_status)) {
+			pr_err("aicbsp: %s, send binding request failn", __func__);
+			return -1;
+		}
+
+		if (binding_status) {
+			pr_err("aicbsp: %s, binding verify fail\n", __func__);
+			return -1;
+		}
+	}
+
+	if (aicwf_sdio_writeb(sdiodev, SDIOWIFI_WAKEUP_REG, 4)) {
+		sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG);
+		return -1;
+	}
+
+	return 0;
 }
 
 int aicbsp_get_feature(struct aicbsp_feature_t *feature)
 {
 	feature->sdio_clock = FEATURE_SDIO_CLOCK;
 	feature->sdio_phase = FEATURE_SDIO_PHASE;
-	if (aicbsp_mode_index == AICBSP_MODE_BT_ONLY_SW && FEATURE_5G_SUPPORT)
-		feature->band_5g_support = true;
+	feature->hwinfo     = aicbsp_info.hwinfo;
+	feature->fwlog_en   = aicbsp_info.fwlog_en;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(aicbsp_get_feature);
+
+#ifdef AICBSP_RESV_MEM_SUPPORT
+static struct skb_buff_pool resv_skb[] = {
+	{AIC_RESV_MEM_TXDATA, 1536*64, "resv_mem_txdata", 0, NULL},
+};
+
+int aicbsp_resv_mem_init(void)
+{
+	int i = 0;
+	for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) {
+		resv_skb[i].skb = dev_alloc_skb(resv_skb[i].size);
+	}
+	return 0;
+}
+
+int aicbsp_resv_mem_deinit(void)
+{
+	int i = 0;
+	for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) {
+		if (resv_skb[i].used == 0 && resv_skb[i].skb)
+			dev_kfree_skb(resv_skb[i].skb);
+	}
+	return 0;
+}
+
+struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id)
+{
+	if (resv_skb[id].size < length) {
+		pr_err("aicbsp: %s, no enough mem\n", __func__);
+		goto fail;
+	}
+
+	if (resv_skb[id].used) {
+		pr_err("aicbsp: %s, mem in use\n", __func__);
+		goto fail;
+	}
+
+	if (resv_skb[id].skb == NULL) {
+		pr_err("aicbsp: %s, mem not initialazed\n", __func__);
+		resv_skb[id].skb = dev_alloc_skb(resv_skb[id].size);
+		if (resv_skb[id].skb == NULL) {
+			pr_err("aicbsp: %s, mem reinitial still fail\n", __func__);
+			goto fail;
+		}
+	}
+
+	printk("aicbsp: %s, alloc %s succuss, id: %d, size: %d\n", __func__,
+			resv_skb[id].name, resv_skb[id].id, resv_skb[id].size);
+
+	resv_skb[id].used = 1;
+	return resv_skb[id].skb;
+
+fail:
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(aicbsp_resv_mem_alloc_skb);
+
+void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id)
+{
+	resv_skb[id].used = 0;
+	printk("aicbsp: %s, free %s succuss, id: %d, size: %d\n", __func__,
+			resv_skb[id].name, resv_skb[id].id, resv_skb[id].size);
+}
+EXPORT_SYMBOL_GPL(aicbsp_resv_mem_kfree_skb);
+
+#else
+
+int aicbsp_resv_mem_init(void)
+{
+	return 0;
+}
+
+int aicbsp_resv_mem_deinit(void)
+{
+	return 0;
+}
+
+#endif

--
Gitblit v1.6.2