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