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_btlpm/aic8800_btlpm.c |  136 +++++++++++++++++++++++++++++++++++++--------
 1 files changed, 112 insertions(+), 24 deletions(-)

diff --git a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btsdio/lpm.c b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c
old mode 100644
new mode 100755
similarity index 88%
rename from longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btsdio/lpm.c
rename to longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c
index 37394b5..b106196
--- a/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btsdio/lpm.c
+++ b/longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c
@@ -62,7 +62,7 @@
 /*
  * Defines
  */
-
+#define DRV_RELEASE_TAG  "aic-btlpm-20220429-002"
 #define VERSION		"1.3.3"
 #define PROC_DIR	"bluetooth/sleep"
 
@@ -107,7 +107,9 @@
 #define BT_PROTO	0x01
 #define BT_TXDATA	0x02
 #define BT_ASLEEP	0x04
-#define BT_RXTIMER	0x20
+#define BT_TXIDLE	0x08
+#define BT_PAUSE	0x09
+#define BT_RXTIMER	0x0a
 
 #if BT_BLUEDROID_SUPPORT
 static bool has_lpm_enabled;
@@ -210,7 +212,8 @@
 			BT_DBG("already asleep");
 			return;
 		}
-		if (bsi->uport->ops->tx_empty(bsi->uport)) {
+		if (bsi->uport->ops->tx_empty(bsi->uport) ||
+			(test_bit(BT_PAUSE, &flags) && test_bit(BT_TXIDLE, &flags))) {
 			BT_DBG("going to sleep...");
 			set_bit(BT_ASLEEP, &flags);
 			/*Deactivating UART */
@@ -241,9 +244,23 @@
 		set_bit(BT_RXTIMER, &flags);
 		hsuart_power(1);
 	} else {
+		static int tx_idle_cnt;
+		if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert && test_bit(BT_TXIDLE, &flags))
+			tx_idle_cnt++;
+		else
+			tx_idle_cnt = 0;
+
 		mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ));
-		if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert) {
-			BT_DBG("force retrigger bt wake");
+		set_bit(BT_RXTIMER, &flags);
+
+		if (test_bit(BT_PAUSE, &flags)) {
+			BT_DBG("rx wake du BT_PAUSE:%lx", flags);
+			///enable bt sleep immediately
+			gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
+		} else if ((gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert
+					&& !test_bit(BT_TXIDLE, &flags)) || tx_idle_cnt > 5) {
+			tx_idle_cnt = 0;
+			BT_DBG("force retrigger bt wake:%lx", flags);
 			gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert);
 			msleep(20);
 			gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
@@ -290,6 +307,7 @@
 #endif
 		gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert);
 		clear_bit(BT_ASLEEP, &flags);
+		clear_bit(BT_TXIDLE, &flags);
 		power_on_uart = 1;
 	}
 
@@ -337,11 +355,20 @@
 		return -EFAULT;
 
 	if (b == '0') {
+#if 1
+		set_bit(BT_PAUSE, &flags);
+		set_bit(BT_TXIDLE, &flags);
+		clear_bit(BT_TXDATA, &flags);
+		/* deassert BT_WAKE */
+		gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
+#else
 		/* HCI_DEV_UNREG */
 		bluesleep_stop();
 		has_lpm_enabled = false;
 		bsi->uport = NULL;
+#endif
 	} else {
+		clear_bit(BT_PAUSE, &flags);
 		/* HCI_DEV_REG */
 		if (!has_lpm_enabled) {
 			has_lpm_enabled = true;
@@ -388,6 +415,24 @@
 	return count;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops lpm_fops = {
+	.proc_open    = bluesleep_lpm_proc_open,
+	.proc_read    = seq_read,
+	.proc_lseek   = seq_lseek,
+	.proc_release = single_release,
+	.proc_write   = bluesleep_write_proc_lpm,
+};
+static const struct proc_ops btwrite_fops = {
+	.proc_open    = bluesleep_btwrite_proc_open,
+	.proc_read    = seq_read,
+	.proc_lseek   = seq_lseek,
+	.proc_release = single_release,
+	.proc_write   = bluesleep_write_proc_btwrite,
+};
+
+#else
+
 static const struct file_operations lpm_fops = {
 	.owner		= THIS_MODULE,
 	.open		= bluesleep_lpm_proc_open,
@@ -404,6 +449,8 @@
 	.release	= single_release,
 	.write		= bluesleep_write_proc_btwrite,
 };
+#endif
+
 #else
 /**
  * Handles HCI device events.
@@ -454,6 +501,8 @@
 	BT_DBG("Tx has been idle\n");
 	spin_lock_irqsave(&rw_lock, irq_flags);
 	gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
+	set_bit(BT_TXIDLE, &flags);
+	clear_bit(BT_TXDATA, &flags);
 	bluesleep_tx_idle();
 	spin_unlock_irqrestore(&rw_lock, irq_flags);
 }
@@ -513,6 +562,9 @@
 
 	/* start the timer */
 	mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL*HZ));
+	/*deassert BT_WAKE first*/
+	gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
+	msleep(20);
 
 	/* assert BT_WAKE */
 	gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert);
@@ -542,7 +594,7 @@
 /**
  * Stops the Sleep-Mode Protocol on the Host.
  */
-static void bluesleep_stop(void)
+static __attribute__((unused)) void bluesleep_stop(void)
 {
 	unsigned long irq_flags;
 
@@ -742,9 +794,9 @@
 	return of_find_device_by_node(np);
 }
 
-static int bluesleep_probe(struct platform_device *pdev)
+static int __init bluesleep_probe(struct platform_device *pdev)
 {
-	struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-btlpm");
+	struct device_node *np = pdev->dev.of_node;
 	struct device *dev = &pdev->dev;
 	enum of_gpio_flags config;
 	int ret, uart_index;
@@ -758,7 +810,8 @@
 	bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config);
 	if (!gpio_is_valid(bsi->host_wake)) {
 		BT_ERR("get gpio bt_hostwake failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err0;
 	}
 
 	/* set host_wake_assert */
@@ -774,13 +827,13 @@
 	if (ret < 0) {
 		BT_ERR("can't request bt_hostwake gpio %d\n",
 			bsi->host_wake);
-		return ret;
+		goto err0;
 	}
 	ret = gpio_direction_input(bsi->host_wake);
 	if (ret < 0) {
 		BT_ERR("can't request input direction bt_wake gpio %d\n",
 			bsi->host_wake);
-		return ret;
+		goto err1;
 	}
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
@@ -794,13 +847,13 @@
 		ret = device_init_wakeup(dev, true);
 		if (ret < 0) {
 			BT_ERR("device init wakeup failed!\n");
-			return ret;
+			goto err1;
 		}
 		ret = dev_pm_set_wake_irq(dev, gpio_to_irq(bsi->host_wake));
 		if (ret < 0) {
 			BT_ERR("can't enable wakeup src for bt_hostwake %d\n",
 				bsi->host_wake);
-			return ret;
+			goto err2;
 		}
 		bsi->wakeup_enable = 1;
 	}
@@ -808,14 +861,15 @@
 	bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config);
 	if (!gpio_is_valid(bsi->ext_wake)) {
 		BT_ERR("get gpio bt_wake failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err2;
 	}
 
 	ret = devm_gpio_request(dev, bsi->ext_wake, "bt_wake");
 	if (ret < 0) {
 		BT_ERR("can't request bt_wake gpio %d\n",
 			bsi->ext_wake);
-		return ret;
+		goto err2;
 	}
 
 	/* set ext_wake_assert */
@@ -832,8 +886,10 @@
 	if (ret < 0) {
 		BT_ERR("can't request output direction bt_wake gpio %d\n",
 			bsi->ext_wake);
-		return ret;
+		goto err3;
 	}
+	/*set ext_wake deassert as default*/
+	gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert);
 
 	/* 2.get bt_host_wake gpio irq */
 	bsi->host_wake_irq = gpio_to_irq(bsi->host_wake);
@@ -841,7 +897,7 @@
 		BT_ERR("map gpio [%d] to virq failed, errno = %d\n",
 				bsi->host_wake, bsi->host_wake_irq);
 		ret = -ENODEV;
-		return ret;
+		goto err3;
 	}
 
 	uart_index = DEFAULT_UART_INDEX;
@@ -865,7 +921,20 @@
 	wake_lock_init(&bsi->wake_lock, WAKE_LOCK_SUSPEND, "bluesleep");
 #endif
 	bsi->pdev = pdev;
+
 	return 0;
+
+err3:
+	devm_gpio_free(dev, bsi->ext_wake);
+err2:
+	device_init_wakeup(dev, false);
+err1:
+	devm_gpio_free(dev, bsi->host_wake);
+err0:
+	devm_kfree(dev, bsi);
+
+	BT_ERR("probe fail, err: %d", ret);
+	return ret;
 }
 
 static int bluesleep_remove(struct platform_device *pdev)
@@ -873,8 +942,6 @@
 	/* assert bt wake */
 	gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert);
 	if (test_bit(BT_PROTO, &flags)) {
-		if (disable_irq_wake(bsi->host_wake_irq))
-			BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
 		free_irq(bsi->host_wake_irq, &bsi->pdev->dev);
 		del_timer(&rx_timer);
 		if (test_bit(BT_ASLEEP, &flags))
@@ -897,19 +964,34 @@
 	return 0;
 }
 
+static const struct of_device_id sunxi_btlpm_ids[] = {
+	{ .compatible = "allwinner,sunxi-btlpm" },
+	{ /* Sentinel */ }
+};
+
+static struct platform_driver bluesleep_driver = {
+	.remove	= bluesleep_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "sunxi-btlpm",
+		.of_match_table	= sunxi_btlpm_ids,
+	},
+};
+
 /**
  * Initializes the module.
  * @return On success, 0. On error, -1, and <code>errno</code> is set
  * appropriately.
  */
-int bluesleep_init(struct platform_device *pdev)
+static int __init bluesleep_init(void)
 {
 	int retval;
 	struct proc_dir_entry *ent;
 
 	BT_DBG("BlueSleep Mode Driver Ver %s", VERSION);
+	BT_DBG("Driver Release Tag: %s", DRV_RELEASE_TAG);
 
-	retval = bluesleep_probe(pdev);
+	retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe);
 	if (retval)
 		return retval;
 
@@ -1024,11 +1106,12 @@
 /**
  * Cleans up the module.
  */
-int bluesleep_exit(struct platform_device *dev)
+static void __exit bluesleep_exit(void)
 {
 #if !BT_BLUEDROID_SUPPORT
 	hci_unregister_notifier(&hci_event_nblock);
 #endif
+	platform_driver_unregister(&bluesleep_driver);
 
 #if BT_BLUEDROID_SUPPORT
 	remove_proc_entry("btwrite", sleep_dir);
@@ -1042,7 +1125,12 @@
 #endif
 	remove_proc_entry("sleep", bluetooth_dir);
 	remove_proc_entry("bluetooth", 0);
-	bluesleep_remove(dev);
-	return 0;
 }
 
+module_init(bluesleep_init);
+module_exit(bluesleep_exit);
+
+MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION);
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif

--
Gitblit v1.6.2