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_main.c |  289 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 231 insertions(+), 58 deletions(-)

diff --git a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c
old mode 100644
new mode 100755
index 35c631f..0707704
--- a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c
+++ b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/version.h>
 #include <linux/platform_device.h>
+#include <linux/rfkill.h>
 #include "aic_bsp_driver.h"
 
 #define DRV_DESCRIPTION       "AIC BSP"
@@ -12,56 +13,62 @@
 #define DRV_AUTHOR            "AICSemi"
 #define DRV_VERS_MOD          "1.0"
 
+#if defined(AICWF_SDIO_SUPPORT)
+#define DRV_TYPE_NAME   "sdio"
+#elif defined(AICWF_USB_SUPPORT)
+#define DRV_TYPE_NAME   "usb"
+#else
+#define DRV_TYPE_NAME   "unknow"
+#endif
+
+#define DRV_RELEASE_TAG "aic-bsp-" DRV_TYPE_NAME "-20220429-002"
+
 static struct platform_device *aicbsp_pdev;
 
-const struct aicbsp_firmware aicbsp_firmware_list[] = {
-	[AICBSP_MODE_BT_ONLY_SW] = {
-		.desc          = "bt only mode with switch",
+const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02;
+
+const struct aicbsp_firmware fw_u02[] = {
+	[AICBSP_CPMODE_WORK] = {
+		.desc          = "normal work mode(sdio u02)",
 		.bt_adid       = "fw_adid.bin",
 		.bt_patch      = "fw_patch.bin",
 		.bt_table      = "fw_patch_table.bin",
-		.bt_patch_test = NULL,
 		.wl_fw         = "fmacfw.bin"
 	},
 
-	[AICBSP_MODE_BT_WIFI_COMBO] = {
-		.desc          = "wifi/bt combo mode",
+	[AICBSP_CPMODE_TEST] = {
+		.desc          = "rf test mode(sdio u02)",
 		.bt_adid       = "fw_adid.bin",
 		.bt_patch      = "fw_patch.bin",
 		.bt_table      = "fw_patch_table.bin",
-		.bt_patch_test = NULL,
-		.wl_fw         = "fmacfw.bin"
-	},
-
-	[AICBSP_MODE_BT_ONLY] = {
-		.desc          = "bt only mode without switch",
-		.bt_adid       = "fw_adid.bin",
-		.bt_patch      = "fw_patch.bin",
-		.bt_table      = "fw_patch_table.bin",
-		.bt_patch_test = NULL,
-		.wl_fw         = "fmacfw.bin"
-	},
-
-	[AICBSP_MODE_BT_ONLY_TEST] = {
-		.desc          = "bt only test mode",
-		.bt_adid       = "fw_adid.bin",
-		.bt_patch      = "fw_patch.bin",
-		.bt_table      = "fw_patch_table.bin",
-		.bt_patch_test = "fw_patch_test.bin",
-		.wl_fw         = "fmacfw_rf.bin"
-	},
-
-	[AICBSP_MODE_COMBO_TEST] = {
-		.desc          = "wifi/bt combo test mode",
-		.bt_adid       = "fw_adid.bin",
-		.bt_patch      = "fw_patch.bin",
-		.bt_table      = "fw_patch_table.bin",
-		.bt_patch_test = "fw_patch_test.bin",
 		.wl_fw         = "fmacfw_rf.bin"
 	},
 };
 
-uint32_t aicbsp_mode_index = AICBSP_MODE_DEFAULT;
+const struct aicbsp_firmware fw_u03[] = {
+	[AICBSP_CPMODE_WORK] = {
+		.desc          = "normal work mode(sdio u03/u04)",
+		.bt_adid       = "fw_adid_u03.bin",
+		.bt_patch      = "fw_patch_u03.bin",
+		.bt_table      = "fw_patch_table_u03.bin",
+		.wl_fw         = "fmacfw.bin"
+	},
+
+	[AICBSP_CPMODE_TEST] = {
+		.desc          = "rf test mode(sdio u03/u04)",
+		.bt_adid       = "fw_adid_u03.bin",
+		.bt_patch      = "fw_patch_u03.bin",
+		.bt_table      = "fw_patch_table_u03.bin",
+		.wl_fw         = "fmacfw_rf.bin"
+	},
+};
+
+struct aicbsp_info_t aicbsp_info = {
+	.hwinfo_r = AICBSP_HWINFO_DEFAULT,
+	.hwinfo   = AICBSP_HWINFO_DEFAULT,
+	.cpmode   = AICBSP_CPMODE_DEFAULT,
+};
+
 struct mutex aicbsp_power_lock;
 
 static struct platform_driver aicbsp_driver = {
@@ -73,96 +80,262 @@
 	//.remove = aicbsp_remove,
 };
 
-static ssize_t aicbsp_mode_show(struct device *dev,
+static int test_enable = -1;
+module_param(test_enable, int, S_IRUGO);
+MODULE_PARM_DESC(test_enable, "Set driver to test mode as default");
+
+static ssize_t cpmode_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	ssize_t count = 0;
 	uint8_t i = 0;
 
-	count += sprintf(&buf[count], "Support mode number:\n");
+	count += sprintf(&buf[count], "Support mode value:\n");
 
-	for (i = 0; i < sizeof(aicbsp_firmware_list) / sizeof(aicbsp_firmware_list[0]); i++) {
+	for (i = 0; i < AICBSP_CPMODE_MAX; i++) {
 		if (aicbsp_firmware_list[i].desc)
 			count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc);
 	}
 
-	count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_mode_index);
-	count += sprintf(&buf[count], "  BT ADID : %s\n", aicbsp_firmware_list[aicbsp_mode_index].bt_adid);
-	count += sprintf(&buf[count], "  BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_mode_index].bt_patch);
-	count += sprintf(&buf[count], "  BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_mode_index].bt_table);
-	count += sprintf(&buf[count], "  BT TEST : %s\n", aicbsp_firmware_list[aicbsp_mode_index].bt_patch_test);
-	count += sprintf(&buf[count], "  WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_mode_index].wl_fw);
+	count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode);
+	count += sprintf(&buf[count], "  BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid);
+	count += sprintf(&buf[count], "  BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch);
+	count += sprintf(&buf[count], "  BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table);
+	count += sprintf(&buf[count], "  WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw);
 	return count;
 }
 
-static ssize_t aicbsp_mode_store(struct device *dev,
+static ssize_t cpmode_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long val;
-	uint32_t max;
 	int err = kstrtoul(buf, 0, &val);
 	if (err)
 		return err;
 
-	max = sizeof(aicbsp_firmware_list) / sizeof(aicbsp_firmware_list[0]);
-	if (val >= max) {
-		pr_err("mode value must less than %d\n", max);
+	if (val >= AICBSP_CPMODE_MAX) {
+		pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX);
 		return -EINVAL;
 	}
 
-	aicbsp_mode_index = val;
+	aicbsp_info.cpmode = val;
 	printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc);
 
 	return count;
 }
 
-static DEVICE_ATTR(aicbsp_mode, S_IRUGO | S_IWUSR,
-		aicbsp_mode_show, aicbsp_mode_store);
+static ssize_t hwinfo_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t count = 0;
+
+	count += sprintf(&buf[count], "chip hw rev: ");
+	if (aicbsp_info.hwinfo_r < 0)
+		count += sprintf(&buf[count], "-1(not avalible)\n");
+	else
+		count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev);
+
+	count += sprintf(&buf[count], "hwinfo read: ");
+	if (aicbsp_info.hwinfo_r < 0)
+		count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r);
+	else
+		count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r);
+
+	if (aicbsp_info.hwinfo < 0)
+		count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo);
+	else
+		count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo);
+
+	return count;
+}
+
+static ssize_t hwinfo_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	long val;
+	int err = kstrtol(buf, 0, &val);
+
+	if (err) {
+		pr_err("invalid input\n");
+		return err;
+	}
+
+	if ((val == -1) || (val >= 0 && val <= 0xFF)) {
+		aicbsp_info.hwinfo = val;
+	} else {
+		pr_err("invalid values\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static ssize_t fwdebug_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t count = 0;
+
+	count += sprintf(&buf[count], "fw log status: %s\n",
+			aicbsp_info.fwlog_en ? "on" : "off");
+
+	return count;
+}
+
+static ssize_t fwdebug_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	long val;
+	int err = kstrtol(buf, 0, &val);
+
+	if (err) {
+		pr_err("invalid input\n");
+		return err;
+	}
+
+	if (val > 1 || val < 0) {
+		pr_err("must be 0 or 1\n");
+		return -EINVAL;
+	}
+
+	aicbsp_info.fwlog_en = val;
+	return count;
+}
+
+static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR,
+		cpmode_show, cpmode_store);
+
+static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR,
+		hwinfo_show, hwinfo_store);
+
+static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR,
+		fwdebug_show, fwdebug_store);
 
 static struct attribute *aicbsp_attributes[] = {
-	&dev_attr_aicbsp_mode.attr,
+	&dev_attr_cpmode.attr,
+	&dev_attr_hwinfo.attr,
+	&dev_attr_fwdebug.attr,
 	NULL,
 };
 
 static struct attribute_group aicbsp_attribute_group = {
-	.name  = "driver_mode",
+	.name  = "aicbsp_info",
 	.attrs = aicbsp_attributes,
 };
+
+static int aicbt_set_power(void *data, bool blocked)
+{
+	pr_info("%s: start_block=%d\n", __func__, blocked);
+	if (!blocked) {
+		aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
+	} else {
+		aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF);
+	}
+
+	pr_info("%s: end_block=%d\n", __func__, blocked);
+	return 0;
+}
+
+static struct rfkill_ops aicbt_rfkill_ops = {
+	.set_block = aicbt_set_power,
+};
+
+static struct rfkill *aicbt_rfk;
+
+static int aicbt_rfkill_init(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	pr_info("-->%s\n", __func__);
+	aicbt_rfk = rfkill_alloc("bluetooth", &pdev->dev, RFKILL_TYPE_BLUETOOTH,
+			&aicbt_rfkill_ops, NULL);
+	if (!aicbt_rfk) {
+		rc = -ENOMEM;
+		goto err_rfkill_alloc;
+	}
+	/* userspace cannot take exclusive control */
+	rfkill_init_sw_state(aicbt_rfk, true);
+	rc = rfkill_register(aicbt_rfk);
+	if (rc)
+		goto err_rfkill_reg;
+
+	pr_info("<--%s\n", __func__);
+
+	return 0;
+
+err_rfkill_reg:
+	rfkill_destroy(aicbt_rfk);
+err_rfkill_alloc:
+	return rc;
+}
+
+static int aicbt_rfkill_remove(struct platform_device *dev)
+{
+	pr_info("-->%s\n", __func__);
+	rfkill_unregister(aicbt_rfk);
+	rfkill_destroy(aicbt_rfk);
+	pr_info("<--%s\n", __func__);
+	return 0;
+}
 
 static int __init aicbsp_init(void)
 {
 	int ret;
 	printk("%s\n", __func__);
+	printk("%s, Driver Release Tag: %s\n", __func__, DRV_RELEASE_TAG);
+
+	aicbsp_resv_mem_init();
+	mutex_init(&aicbsp_power_lock);
 	ret = platform_driver_register(&aicbsp_driver);
 	if (ret) {
 		pr_err("register platform driver failed: %d\n", ret);
-		return ret;
+		goto err0;
 	}
 
 	aicbsp_pdev = platform_device_alloc("aic-bsp", -1);
 	ret = platform_device_add(aicbsp_pdev);
 	if (ret) {
 		pr_err("register platform device failed: %d\n", ret);
-		return ret;
+		goto err1;
 	}
 
 	ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
 	if (ret) {
 		pr_err("register sysfs create group failed!\n");
-		return ret;
+		goto err2;
 	}
 
-	mutex_init(&aicbsp_power_lock);
+	if (test_enable == 1) {
+		aicbsp_info.cpmode = AICBSP_CPMODE_TEST,
+		printk("aicbsp: Test mode enable!!!\n");
+	}
+
+	ret = aicbt_rfkill_init(aicbsp_pdev);
+	if (ret) {
+		pr_err("register rfkill fail\n");
+		goto err3;
+	}
 
 	return 0;
+
+err3:
+	sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
+err2:
+	platform_device_del(aicbsp_pdev);
+err1:
+	platform_driver_unregister(&aicbsp_driver);
+err0:
+	mutex_destroy(&aicbsp_power_lock);
+	aicbsp_resv_mem_deinit();
+	return ret;
 }
 
 static void __exit aicbsp_exit(void)
 {
+	aicbt_rfkill_remove(aicbsp_pdev);
 	sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
 	platform_device_del(aicbsp_pdev);
 	platform_driver_unregister(&aicbsp_driver);
 	mutex_destroy(&aicbsp_power_lock);
+	aicbsp_resv_mem_deinit();
 	printk("%s\n", __func__);
 }
 

--
Gitblit v1.6.2