diff options
Diffstat (limited to 'drivers/bluetooth/btmtksdio.c')
| -rw-r--r-- | drivers/bluetooth/btmtksdio.c | 113 |
1 files changed, 89 insertions, 24 deletions
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index f9a3444753c2..fba3ab6d30a5 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -10,7 +10,7 @@ * */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/atomic.h> #include <linux/gpio/consumer.h> #include <linux/init.h> @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/skbuff.h> +#include <linux/usb.h> #include <linux/mmc/host.h> #include <linux/mmc/sdio_ids.h> @@ -28,7 +29,7 @@ #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> -#include "h4_recv.h" +#include "hci_uart.h" #include "btmtk.h" #define VERSION "0.1" @@ -118,6 +119,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define BTMTKSDIO_FUNC_ENABLED 3 #define BTMTKSDIO_PATCH_ENABLED 4 #define BTMTKSDIO_HW_RESET_ACTIVE 5 +#define BTMTKSDIO_BT_WAKE_ENABLED 6 struct mtkbtsdio_hdr { __le16 len; @@ -554,7 +556,7 @@ static void btmtksdio_txrx_work(struct work_struct *work) sdio_claim_host(bdev->func); /* Disable interrupt */ - sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0); + sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL); txrx_timeout = jiffies + 5 * HZ; @@ -576,7 +578,7 @@ static void btmtksdio_txrx_work(struct work_struct *work) if ((int_status & FW_MAILBOX_INT) && bdev->data->chipid == 0x7921) { sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN, - MTK_REG_PH2DSM0R, 0); + MTK_REG_PH2DSM0R, NULL); } if (int_status & FW_OWN_BACK_INT) @@ -608,11 +610,11 @@ static void btmtksdio_txrx_work(struct work_struct *work) } while (int_status || time_is_before_jiffies(txrx_timeout)); /* Enable interrupt */ - sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0); + if (bdev->func->irq_handler) + sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); sdio_release_host(bdev->func); - pm_runtime_mark_last_busy(bdev->dev); pm_runtime_put_autosuspend(bdev->dev); } @@ -620,8 +622,14 @@ static void btmtksdio_interrupt(struct sdio_func *func) { struct btmtksdio_dev *bdev = sdio_get_drvdata(func); + if (test_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state)) { + if (bdev->hdev->suspended) + pm_wakeup_event(bdev->dev, 0); + clear_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state); + } + /* Disable interrupt */ - sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0); + sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL); schedule_work(&bdev->txrx_work); } @@ -673,7 +681,7 @@ static int btmtksdio_open(struct hci_dev *hdev) if (err < 0) goto err_release_irq; - /* Explitly set write-1-clear method */ + /* Explicitly set write-1-clear method */ val = sdio_readl(bdev->func, MTK_REG_CHCR, &err); if (err < 0) goto err_release_irq; @@ -714,6 +722,10 @@ static int btmtksdio_close(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); + /* Skip btmtksdio_close if BTMTKSDIO_FUNC_ENABLED isn't set */ + if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) + return 0; + sdio_claim_host(bdev->func); /* Disable interrupt */ @@ -1110,6 +1122,9 @@ static int btmtksdio_setup(struct hci_dev *hdev) return err; } + btmtk_fw_get_filename(fwname, sizeof(fwname), dev_id, + fw_version, 0); + snprintf(fwname, sizeof(fwname), "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", dev_id & 0xffff, (fw_version & 0xff) + 1); @@ -1125,7 +1140,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) } /* Enable WBS with mSBC codec */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* Enable GPIO reset mechanism */ if (bdev->reset) { @@ -1137,9 +1152,6 @@ static int btmtksdio_setup(struct hci_dev *hdev) } } - /* Valid LE States quirk for MediaTek 7921 */ - set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); - break; case 0x7663: case 0x7668: @@ -1241,7 +1253,7 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } -static void btmtksdio_cmd_timeout(struct hci_dev *hdev) +static void btmtksdio_reset(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); u32 status; @@ -1257,6 +1269,12 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev) sdio_claim_host(bdev->func); + /* set drv_pmctrl if BT is closed before doing reset */ + if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) { + sdio_enable_func(bdev->func); + btmtksdio_drv_pmctrl(bdev); + } + sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL); skb_queue_purge(&bdev->txq); cancel_work_sync(&bdev->txrx_work); @@ -1272,6 +1290,12 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev) goto err; } + /* set fw_pmctrl back if BT is closed after doing reset */ + if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) { + btmtksdio_fw_pmctrl(bdev); + sdio_disable_func(bdev->func); + } + clear_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state); err: sdio_release_host(bdev->func); @@ -1320,6 +1344,8 @@ static int btmtksdio_probe(struct sdio_func *func, { struct btmtksdio_dev *bdev; struct hci_dev *hdev; + struct device_node *old_node; + bool restore_node; int err; bdev = devm_kzalloc(&func->dev, sizeof(*bdev), GFP_KERNEL); @@ -1350,7 +1376,7 @@ static int btmtksdio_probe(struct sdio_func *func, hdev->open = btmtksdio_open; hdev->close = btmtksdio_close; - hdev->cmd_timeout = btmtksdio_cmd_timeout; + hdev->reset = btmtksdio_reset; hdev->flush = btmtksdio_flush; hdev->setup = btmtksdio_setup; hdev->shutdown = btmtksdio_shutdown; @@ -1369,7 +1395,7 @@ static int btmtksdio_probe(struct sdio_func *func, SET_HCIDEV_DEV(hdev, &func->dev); hdev->manufacturer = 70; - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); sdio_set_drvdata(func, bdev); @@ -1388,7 +1414,7 @@ static int btmtksdio_probe(struct sdio_func *func, if (pm_runtime_enabled(bdev->dev)) pm_runtime_disable(bdev->dev); - /* As explaination in drivers/mmc/core/sdio_bus.c tells us: + /* As explanation in drivers/mmc/core/sdio_bus.c tells us: * Unbound SDIO functions are always suspended. * During probe, the function is set active and the usage count * is incremented. If the driver supports runtime PM, @@ -1399,17 +1425,28 @@ static int btmtksdio_probe(struct sdio_func *func, */ pm_runtime_put_noidle(bdev->dev); - err = device_init_wakeup(bdev->dev, true); + err = devm_device_init_wakeup(bdev->dev); if (err) bt_dev_err(hdev, "failed to initialize device wakeup"); - bdev->dev->of_node = of_find_compatible_node(NULL, NULL, - "mediatek,mt7921s-bluetooth"); + restore_node = false; + if (!of_device_is_compatible(bdev->dev->of_node, "mediatek,mt7921s-bluetooth")) { + restore_node = true; + old_node = bdev->dev->of_node; + bdev->dev->of_node = of_find_compatible_node(NULL, NULL, + "mediatek,mt7921s-bluetooth"); + } + bdev->reset = devm_gpiod_get_optional(bdev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(bdev->reset)) err = PTR_ERR(bdev->reset); + if (restore_node) { + of_node_put(bdev->dev->of_node); + bdev->dev->of_node = old_node; + } + return err; } @@ -1421,11 +1458,15 @@ static void btmtksdio_remove(struct sdio_func *func) if (!bdev) return; + hdev = bdev->hdev; + + /* Make sure to call btmtksdio_close before removing sdio card */ + if (test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) + btmtksdio_close(hdev); + /* Be consistent the state in btmtksdio_probe */ pm_runtime_get_noresume(bdev->dev); - hdev = bdev->hdev; - sdio_set_drvdata(func, NULL); hci_unregister_dev(hdev); hci_free_dev(hdev); @@ -1454,6 +1495,23 @@ static int btmtksdio_runtime_suspend(struct device *dev) return err; } +static int btmtksdio_system_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct btmtksdio_dev *bdev; + + bdev = sdio_get_drvdata(func); + if (!bdev) + return 0; + + if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) + return 0; + + set_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state); + + return btmtksdio_runtime_suspend(dev); +} + static int btmtksdio_runtime_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); @@ -1474,8 +1532,16 @@ static int btmtksdio_runtime_resume(struct device *dev) return err; } -static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend, - btmtksdio_runtime_resume, NULL); +static int btmtksdio_system_resume(struct device *dev) +{ + return btmtksdio_runtime_resume(dev); +} + +static const struct dev_pm_ops btmtksdio_pm_ops = { + SYSTEM_SLEEP_PM_OPS(btmtksdio_system_suspend, btmtksdio_system_resume) + RUNTIME_PM_OPS(btmtksdio_runtime_suspend, btmtksdio_runtime_resume, NULL) +}; + #define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops) #else /* CONFIG_PM */ #define BTMTKSDIO_PM_OPS NULL @@ -1487,7 +1553,6 @@ static struct sdio_driver btmtksdio_driver = { .remove = btmtksdio_remove, .id_table = btmtksdio_table, .drv = { - .owner = THIS_MODULE, .pm = BTMTKSDIO_PM_OPS, } }; |
