19aebfd4aSSean Wang // SPDX-License-Identifier: GPL-2.0
29aebfd4aSSean Wang // Copyright (c) 2019 MediaTek Inc.
39aebfd4aSSean Wang
49aebfd4aSSean Wang /*
59aebfd4aSSean Wang * Bluetooth support for MediaTek SDIO devices
69aebfd4aSSean Wang *
79aebfd4aSSean Wang * This file is written based on btsdio.c and btmtkuart.c.
89aebfd4aSSean Wang *
99aebfd4aSSean Wang * Author: Sean Wang <sean.wang@mediatek.com>
109aebfd4aSSean Wang *
119aebfd4aSSean Wang */
129aebfd4aSSean Wang
139aebfd4aSSean Wang #include <asm/unaligned.h>
149aebfd4aSSean Wang #include <linux/atomic.h>
158fafe702SChih-Ying Chiang #include <linux/gpio/consumer.h>
169aebfd4aSSean Wang #include <linux/init.h>
179aebfd4aSSean Wang #include <linux/iopoll.h>
189aebfd4aSSean Wang #include <linux/kernel.h>
199aebfd4aSSean Wang #include <linux/module.h>
208fafe702SChih-Ying Chiang #include <linux/of.h>
217f3c563cSSean Wang #include <linux/pm_runtime.h>
229aebfd4aSSean Wang #include <linux/skbuff.h>
239aebfd4aSSean Wang
249aebfd4aSSean Wang #include <linux/mmc/host.h>
259aebfd4aSSean Wang #include <linux/mmc/sdio_ids.h>
269aebfd4aSSean Wang #include <linux/mmc/sdio_func.h>
279aebfd4aSSean Wang
289aebfd4aSSean Wang #include <net/bluetooth/bluetooth.h>
299aebfd4aSSean Wang #include <net/bluetooth/hci_core.h>
309aebfd4aSSean Wang
319aebfd4aSSean Wang #include "h4_recv.h"
323a722044SSean Wang #include "btmtk.h"
339aebfd4aSSean Wang
349aebfd4aSSean Wang #define VERSION "0.1"
359aebfd4aSSean Wang
36e98aa38cSSean Wang #define MTKBTSDIO_AUTOSUSPEND_DELAY 1000
377f3c563cSSean Wang
38e98aa38cSSean Wang static bool enable_autosuspend = true;
397f3c563cSSean Wang
409aebfd4aSSean Wang struct btmtksdio_data {
419aebfd4aSSean Wang const char *fwname;
42c603bf1fSSean Wang u16 chipid;
4301ecc177SMark Chen bool lp_mbox_supported;
449aebfd4aSSean Wang };
459aebfd4aSSean Wang
469aebfd4aSSean Wang static const struct btmtksdio_data mt7663_data = {
479aebfd4aSSean Wang .fwname = FIRMWARE_MT7663,
48c603bf1fSSean Wang .chipid = 0x7663,
4901ecc177SMark Chen .lp_mbox_supported = false,
509aebfd4aSSean Wang };
519aebfd4aSSean Wang
529aebfd4aSSean Wang static const struct btmtksdio_data mt7668_data = {
539aebfd4aSSean Wang .fwname = FIRMWARE_MT7668,
54c603bf1fSSean Wang .chipid = 0x7668,
5501ecc177SMark Chen .lp_mbox_supported = false,
56c603bf1fSSean Wang };
57c603bf1fSSean Wang
58c603bf1fSSean Wang static const struct btmtksdio_data mt7921_data = {
59c603bf1fSSean Wang .fwname = FIRMWARE_MT7961,
60c603bf1fSSean Wang .chipid = 0x7921,
6101ecc177SMark Chen .lp_mbox_supported = true,
629aebfd4aSSean Wang };
639aebfd4aSSean Wang
649aebfd4aSSean Wang static const struct sdio_device_id btmtksdio_table[] = {
65baaa110dSPali Rohár {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7663),
669aebfd4aSSean Wang .driver_data = (kernel_ulong_t)&mt7663_data },
67baaa110dSPali Rohár {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7668),
689aebfd4aSSean Wang .driver_data = (kernel_ulong_t)&mt7668_data },
69c603bf1fSSean Wang {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7961),
70c603bf1fSSean Wang .driver_data = (kernel_ulong_t)&mt7921_data },
719aebfd4aSSean Wang { } /* Terminating entry */
729aebfd4aSSean Wang };
7353121a7cSBartosz Golaszewski MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
749aebfd4aSSean Wang
759aebfd4aSSean Wang #define MTK_REG_CHLPCR 0x4 /* W1S */
769aebfd4aSSean Wang #define C_INT_EN_SET BIT(0)
779aebfd4aSSean Wang #define C_INT_EN_CLR BIT(1)
782e47cc2bSSean Wang #define C_FW_OWN_REQ_SET BIT(8) /* For write */
792e47cc2bSSean Wang #define C_COM_DRV_OWN BIT(8) /* For read */
809aebfd4aSSean Wang #define C_FW_OWN_REQ_CLR BIT(9)
819aebfd4aSSean Wang
829aebfd4aSSean Wang #define MTK_REG_CSDIOCSR 0x8
839aebfd4aSSean Wang #define SDIO_RE_INIT_EN BIT(0)
849aebfd4aSSean Wang #define SDIO_INT_CTL BIT(2)
859aebfd4aSSean Wang
869aebfd4aSSean Wang #define MTK_REG_CHCR 0xc
879aebfd4aSSean Wang #define C_INT_CLR_CTRL BIT(1)
888fafe702SChih-Ying Chiang #define BT_RST_DONE BIT(8)
899aebfd4aSSean Wang
909aebfd4aSSean Wang /* CHISR have the same bits field definition with CHIER */
919aebfd4aSSean Wang #define MTK_REG_CHISR 0x10
929aebfd4aSSean Wang #define MTK_REG_CHIER 0x14
939aebfd4aSSean Wang #define FW_OWN_BACK_INT BIT(0)
949aebfd4aSSean Wang #define RX_DONE_INT BIT(1)
959aebfd4aSSean Wang #define TX_EMPTY BIT(2)
969aebfd4aSSean Wang #define TX_FIFO_OVERFLOW BIT(8)
972fc967ccSMark Chen #define FW_MAILBOX_INT BIT(15)
98db3f1f9bSSean Wang #define INT_MASK GENMASK(15, 0)
999aebfd4aSSean Wang #define RX_PKT_LEN GENMASK(31, 16)
1009aebfd4aSSean Wang
10101ecc177SMark Chen #define MTK_REG_CSICR 0xc0
10201ecc177SMark Chen #define CSICR_CLR_MBOX_ACK BIT(0)
1032fc967ccSMark Chen #define MTK_REG_PH2DSM0R 0xc4
1042fc967ccSMark Chen #define PH2DSM0R_DRIVER_OWN BIT(0)
10501ecc177SMark Chen #define MTK_REG_PD2HRM0R 0xdc
10601ecc177SMark Chen #define PD2HRM0R_DRV_OWN BIT(0)
1072fc967ccSMark Chen
1089aebfd4aSSean Wang #define MTK_REG_CTDR 0x18
1099aebfd4aSSean Wang
1109aebfd4aSSean Wang #define MTK_REG_CRDR 0x1c
1119aebfd4aSSean Wang
112184ea403SSean Wang #define MTK_REG_CRPLR 0x24
113184ea403SSean Wang
1149aebfd4aSSean Wang #define MTK_SDIO_BLOCK_SIZE 256
1159aebfd4aSSean Wang
1169aebfd4aSSean Wang #define BTMTKSDIO_TX_WAIT_VND_EVT 1
117d555b1f2SSean Wang #define BTMTKSDIO_HW_TX_READY 2
1184b4b2228SSean Wang #define BTMTKSDIO_FUNC_ENABLED 3
11901ecc177SMark Chen #define BTMTKSDIO_PATCH_ENABLED 4
1208fafe702SChih-Ying Chiang #define BTMTKSDIO_HW_RESET_ACTIVE 5
1219aebfd4aSSean Wang
1229aebfd4aSSean Wang struct mtkbtsdio_hdr {
1239aebfd4aSSean Wang __le16 len;
1249aebfd4aSSean Wang __le16 reserved;
1259aebfd4aSSean Wang u8 bt_type;
1269aebfd4aSSean Wang } __packed;
1279aebfd4aSSean Wang
1289aebfd4aSSean Wang struct btmtksdio_dev {
1299aebfd4aSSean Wang struct hci_dev *hdev;
1309aebfd4aSSean Wang struct sdio_func *func;
1317f3c563cSSean Wang struct device *dev;
1329aebfd4aSSean Wang
13326270bc1SSean Wang struct work_struct txrx_work;
1349aebfd4aSSean Wang unsigned long tx_state;
1359aebfd4aSSean Wang struct sk_buff_head txq;
1369aebfd4aSSean Wang
1379aebfd4aSSean Wang struct sk_buff *evt_skb;
1389aebfd4aSSean Wang
1399aebfd4aSSean Wang const struct btmtksdio_data *data;
1408fafe702SChih-Ying Chiang
1418fafe702SChih-Ying Chiang struct gpio_desc *reset;
1429aebfd4aSSean Wang };
1439aebfd4aSSean Wang
mtk_hci_wmt_sync(struct hci_dev * hdev,struct btmtk_hci_wmt_params * wmt_params)1449aebfd4aSSean Wang static int mtk_hci_wmt_sync(struct hci_dev *hdev,
1459aebfd4aSSean Wang struct btmtk_hci_wmt_params *wmt_params)
1469aebfd4aSSean Wang {
1479aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
1489aebfd4aSSean Wang struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
149c603bf1fSSean Wang struct btmtk_hci_wmt_evt_reg *wmt_evt_reg;
1509aebfd4aSSean Wang u32 hlen, status = BTMTK_WMT_INVALID;
1519aebfd4aSSean Wang struct btmtk_hci_wmt_evt *wmt_evt;
1523a722044SSean Wang struct btmtk_hci_wmt_cmd *wc;
1533a722044SSean Wang struct btmtk_wmt_hdr *hdr;
1549aebfd4aSSean Wang int err;
1559aebfd4aSSean Wang
1563a722044SSean Wang /* Send the WMT command and wait until the WMT event returns */
1579aebfd4aSSean Wang hlen = sizeof(*hdr) + wmt_params->dlen;
1589aebfd4aSSean Wang if (hlen > 255)
1599aebfd4aSSean Wang return -EINVAL;
1609aebfd4aSSean Wang
1613a722044SSean Wang wc = kzalloc(hlen, GFP_KERNEL);
1623a722044SSean Wang if (!wc)
1633a722044SSean Wang return -ENOMEM;
1643a722044SSean Wang
1653a722044SSean Wang hdr = &wc->hdr;
1669aebfd4aSSean Wang hdr->dir = 1;
1679aebfd4aSSean Wang hdr->op = wmt_params->op;
1689aebfd4aSSean Wang hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
1699aebfd4aSSean Wang hdr->flag = wmt_params->flag;
1703a722044SSean Wang memcpy(wc->data, wmt_params->data, wmt_params->dlen);
1719aebfd4aSSean Wang
1729aebfd4aSSean Wang set_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
1739aebfd4aSSean Wang
1743a722044SSean Wang err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
1759aebfd4aSSean Wang if (err < 0) {
1769aebfd4aSSean Wang clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
1773a722044SSean Wang goto err_free_wc;
1789aebfd4aSSean Wang }
1799aebfd4aSSean Wang
1809aebfd4aSSean Wang /* The vendor specific WMT commands are all answered by a vendor
1819aebfd4aSSean Wang * specific event and will not have the Command Status or Command
1829aebfd4aSSean Wang * Complete as with usual HCI command flow control.
1839aebfd4aSSean Wang *
1849aebfd4aSSean Wang * After sending the command, wait for BTMTKSDIO_TX_WAIT_VND_EVT
1859aebfd4aSSean Wang * state to be cleared. The driver specific event receive routine
1869aebfd4aSSean Wang * will clear that state and with that indicate completion of the
1879aebfd4aSSean Wang * WMT command.
1889aebfd4aSSean Wang */
1899aebfd4aSSean Wang err = wait_on_bit_timeout(&bdev->tx_state, BTMTKSDIO_TX_WAIT_VND_EVT,
1909aebfd4aSSean Wang TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
1919aebfd4aSSean Wang if (err == -EINTR) {
1929aebfd4aSSean Wang bt_dev_err(hdev, "Execution of wmt command interrupted");
1939aebfd4aSSean Wang clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
1943a722044SSean Wang goto err_free_wc;
1959aebfd4aSSean Wang }
1969aebfd4aSSean Wang
1979aebfd4aSSean Wang if (err) {
1989aebfd4aSSean Wang bt_dev_err(hdev, "Execution of wmt command timed out");
1999aebfd4aSSean Wang clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
2003a722044SSean Wang err = -ETIMEDOUT;
2013a722044SSean Wang goto err_free_wc;
2029aebfd4aSSean Wang }
2039aebfd4aSSean Wang
2049aebfd4aSSean Wang /* Parse and handle the return WMT event */
2059aebfd4aSSean Wang wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
2069aebfd4aSSean Wang if (wmt_evt->whdr.op != hdr->op) {
2079aebfd4aSSean Wang bt_dev_err(hdev, "Wrong op received %d expected %d",
2089aebfd4aSSean Wang wmt_evt->whdr.op, hdr->op);
2099aebfd4aSSean Wang err = -EIO;
2109aebfd4aSSean Wang goto err_free_skb;
2119aebfd4aSSean Wang }
2129aebfd4aSSean Wang
2139aebfd4aSSean Wang switch (wmt_evt->whdr.op) {
2143a722044SSean Wang case BTMTK_WMT_SEMAPHORE:
2159aebfd4aSSean Wang if (wmt_evt->whdr.flag == 2)
2169aebfd4aSSean Wang status = BTMTK_WMT_PATCH_UNDONE;
2179aebfd4aSSean Wang else
2189aebfd4aSSean Wang status = BTMTK_WMT_PATCH_DONE;
2199aebfd4aSSean Wang break;
2203a722044SSean Wang case BTMTK_WMT_FUNC_CTRL:
2219aebfd4aSSean Wang wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
2229aebfd4aSSean Wang if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
2239aebfd4aSSean Wang status = BTMTK_WMT_ON_DONE;
2249aebfd4aSSean Wang else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
2259aebfd4aSSean Wang status = BTMTK_WMT_ON_PROGRESS;
2269aebfd4aSSean Wang else
2279aebfd4aSSean Wang status = BTMTK_WMT_ON_UNDONE;
2289aebfd4aSSean Wang break;
229c603bf1fSSean Wang case BTMTK_WMT_PATCH_DWNLD:
230c603bf1fSSean Wang if (wmt_evt->whdr.flag == 2)
231c603bf1fSSean Wang status = BTMTK_WMT_PATCH_DONE;
232c603bf1fSSean Wang else if (wmt_evt->whdr.flag == 1)
233c603bf1fSSean Wang status = BTMTK_WMT_PATCH_PROGRESS;
234c603bf1fSSean Wang else
235c603bf1fSSean Wang status = BTMTK_WMT_PATCH_UNDONE;
236c603bf1fSSean Wang break;
237c603bf1fSSean Wang case BTMTK_WMT_REGISTER:
238c603bf1fSSean Wang wmt_evt_reg = (struct btmtk_hci_wmt_evt_reg *)wmt_evt;
239c603bf1fSSean Wang if (le16_to_cpu(wmt_evt->whdr.dlen) == 12)
240c603bf1fSSean Wang status = le32_to_cpu(wmt_evt_reg->val);
241c603bf1fSSean Wang break;
2429aebfd4aSSean Wang }
2439aebfd4aSSean Wang
2449aebfd4aSSean Wang if (wmt_params->status)
2459aebfd4aSSean Wang *wmt_params->status = status;
2469aebfd4aSSean Wang
2479aebfd4aSSean Wang err_free_skb:
2489aebfd4aSSean Wang kfree_skb(bdev->evt_skb);
2499aebfd4aSSean Wang bdev->evt_skb = NULL;
2503a722044SSean Wang err_free_wc:
2513a722044SSean Wang kfree(wc);
2529aebfd4aSSean Wang
2539aebfd4aSSean Wang return err;
2549aebfd4aSSean Wang }
2559aebfd4aSSean Wang
btmtksdio_tx_packet(struct btmtksdio_dev * bdev,struct sk_buff * skb)2569aebfd4aSSean Wang static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
2579aebfd4aSSean Wang struct sk_buff *skb)
2589aebfd4aSSean Wang {
2599aebfd4aSSean Wang struct mtkbtsdio_hdr *sdio_hdr;
2609aebfd4aSSean Wang int err;
2619aebfd4aSSean Wang
2629aebfd4aSSean Wang /* Make sure that there are enough rooms for SDIO header */
2639aebfd4aSSean Wang if (unlikely(skb_headroom(skb) < sizeof(*sdio_hdr))) {
2649aebfd4aSSean Wang err = pskb_expand_head(skb, sizeof(*sdio_hdr), 0,
2659aebfd4aSSean Wang GFP_ATOMIC);
2669aebfd4aSSean Wang if (err < 0)
2679aebfd4aSSean Wang return err;
2689aebfd4aSSean Wang }
2699aebfd4aSSean Wang
2709aebfd4aSSean Wang /* Prepend MediaTek SDIO Specific Header */
2719aebfd4aSSean Wang skb_push(skb, sizeof(*sdio_hdr));
2729aebfd4aSSean Wang
2739aebfd4aSSean Wang sdio_hdr = (void *)skb->data;
2749aebfd4aSSean Wang sdio_hdr->len = cpu_to_le16(skb->len);
2759aebfd4aSSean Wang sdio_hdr->reserved = cpu_to_le16(0);
2769aebfd4aSSean Wang sdio_hdr->bt_type = hci_skb_pkt_type(skb);
2779aebfd4aSSean Wang
278d555b1f2SSean Wang clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
2799aebfd4aSSean Wang err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
2809aebfd4aSSean Wang round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
2819aebfd4aSSean Wang if (err < 0)
2829aebfd4aSSean Wang goto err_skb_pull;
2839aebfd4aSSean Wang
2849aebfd4aSSean Wang bdev->hdev->stat.byte_tx += skb->len;
2859aebfd4aSSean Wang
2869aebfd4aSSean Wang kfree_skb(skb);
2879aebfd4aSSean Wang
2889aebfd4aSSean Wang return 0;
2899aebfd4aSSean Wang
2909aebfd4aSSean Wang err_skb_pull:
2919aebfd4aSSean Wang skb_pull(skb, sizeof(*sdio_hdr));
2929aebfd4aSSean Wang
2939aebfd4aSSean Wang return err;
2949aebfd4aSSean Wang }
2959aebfd4aSSean Wang
btmtksdio_drv_own_query(struct btmtksdio_dev * bdev)2969aebfd4aSSean Wang static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev)
2979aebfd4aSSean Wang {
2989aebfd4aSSean Wang return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL);
2999aebfd4aSSean Wang }
3009aebfd4aSSean Wang
btmtksdio_drv_own_query_79xx(struct btmtksdio_dev * bdev)30101ecc177SMark Chen static u32 btmtksdio_drv_own_query_79xx(struct btmtksdio_dev *bdev)
30201ecc177SMark Chen {
30301ecc177SMark Chen return sdio_readl(bdev->func, MTK_REG_PD2HRM0R, NULL);
30401ecc177SMark Chen }
30501ecc177SMark Chen
btmtksdio_chcr_query(struct btmtksdio_dev * bdev)3068fafe702SChih-Ying Chiang static u32 btmtksdio_chcr_query(struct btmtksdio_dev *bdev)
3078fafe702SChih-Ying Chiang {
3088fafe702SChih-Ying Chiang return sdio_readl(bdev->func, MTK_REG_CHCR, NULL);
3098fafe702SChih-Ying Chiang }
3108fafe702SChih-Ying Chiang
btmtksdio_fw_pmctrl(struct btmtksdio_dev * bdev)311c7e301d7SMark Chen static int btmtksdio_fw_pmctrl(struct btmtksdio_dev *bdev)
312c7e301d7SMark Chen {
313c7e301d7SMark Chen u32 status;
314c7e301d7SMark Chen int err;
315c7e301d7SMark Chen
316c7e301d7SMark Chen sdio_claim_host(bdev->func);
317c7e301d7SMark Chen
31801ecc177SMark Chen if (bdev->data->lp_mbox_supported &&
31901ecc177SMark Chen test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state)) {
32001ecc177SMark Chen sdio_writel(bdev->func, CSICR_CLR_MBOX_ACK, MTK_REG_CSICR,
32101ecc177SMark Chen &err);
32201ecc177SMark Chen err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev,
32301ecc177SMark Chen status, !(status & PD2HRM0R_DRV_OWN),
32401ecc177SMark Chen 2000, 1000000);
32501ecc177SMark Chen if (err < 0) {
32601ecc177SMark Chen bt_dev_err(bdev->hdev, "mailbox ACK not cleared");
32701ecc177SMark Chen goto out;
32801ecc177SMark Chen }
32901ecc177SMark Chen }
33001ecc177SMark Chen
331c7e301d7SMark Chen /* Return ownership to the device */
332c7e301d7SMark Chen sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err);
333c7e301d7SMark Chen if (err < 0)
334c7e301d7SMark Chen goto out;
335c7e301d7SMark Chen
336c7e301d7SMark Chen err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
337c7e301d7SMark Chen !(status & C_COM_DRV_OWN), 2000, 1000000);
338c7e301d7SMark Chen
339c7e301d7SMark Chen out:
340c7e301d7SMark Chen sdio_release_host(bdev->func);
341c7e301d7SMark Chen
342c7e301d7SMark Chen if (err < 0)
343c7e301d7SMark Chen bt_dev_err(bdev->hdev, "Cannot return ownership to device");
344c7e301d7SMark Chen
345c7e301d7SMark Chen return err;
346c7e301d7SMark Chen }
347c7e301d7SMark Chen
btmtksdio_drv_pmctrl(struct btmtksdio_dev * bdev)348c7e301d7SMark Chen static int btmtksdio_drv_pmctrl(struct btmtksdio_dev *bdev)
349c7e301d7SMark Chen {
350c7e301d7SMark Chen u32 status;
351c7e301d7SMark Chen int err;
352c7e301d7SMark Chen
353c7e301d7SMark Chen sdio_claim_host(bdev->func);
354c7e301d7SMark Chen
355c7e301d7SMark Chen /* Get ownership from the device */
356c7e301d7SMark Chen sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
357c7e301d7SMark Chen if (err < 0)
358c7e301d7SMark Chen goto out;
359c7e301d7SMark Chen
360c7e301d7SMark Chen err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
361c7e301d7SMark Chen status & C_COM_DRV_OWN, 2000, 1000000);
362c7e301d7SMark Chen
36301ecc177SMark Chen if (!err && bdev->data->lp_mbox_supported &&
36401ecc177SMark Chen test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state))
36501ecc177SMark Chen err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev,
36601ecc177SMark Chen status, status & PD2HRM0R_DRV_OWN,
36701ecc177SMark Chen 2000, 1000000);
36801ecc177SMark Chen
369c7e301d7SMark Chen out:
370c7e301d7SMark Chen sdio_release_host(bdev->func);
371c7e301d7SMark Chen
372c7e301d7SMark Chen if (err < 0)
373c7e301d7SMark Chen bt_dev_err(bdev->hdev, "Cannot get ownership from device");
374c7e301d7SMark Chen
375c7e301d7SMark Chen return err;
376c7e301d7SMark Chen }
377c7e301d7SMark Chen
btmtksdio_recv_event(struct hci_dev * hdev,struct sk_buff * skb)3789aebfd4aSSean Wang static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
3799aebfd4aSSean Wang {
3809aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
3819aebfd4aSSean Wang struct hci_event_hdr *hdr = (void *)skb->data;
3820fab6361SSean Wang u8 evt = hdr->evt;
3839aebfd4aSSean Wang int err;
3849aebfd4aSSean Wang
3859aebfd4aSSean Wang /* When someone waits for the WMT event, the skb is being cloned
3869aebfd4aSSean Wang * and being processed the events from there then.
3879aebfd4aSSean Wang */
3889aebfd4aSSean Wang if (test_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state)) {
3899aebfd4aSSean Wang bdev->evt_skb = skb_clone(skb, GFP_KERNEL);
3909aebfd4aSSean Wang if (!bdev->evt_skb) {
3919aebfd4aSSean Wang err = -ENOMEM;
3929aebfd4aSSean Wang goto err_out;
3939aebfd4aSSean Wang }
3949aebfd4aSSean Wang }
3959aebfd4aSSean Wang
3969aebfd4aSSean Wang err = hci_recv_frame(hdev, skb);
3979aebfd4aSSean Wang if (err < 0)
3989aebfd4aSSean Wang goto err_free_skb;
3999aebfd4aSSean Wang
4000fab6361SSean Wang if (evt == HCI_EV_WMT) {
4019aebfd4aSSean Wang if (test_and_clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT,
4029aebfd4aSSean Wang &bdev->tx_state)) {
4039aebfd4aSSean Wang /* Barrier to sync with other CPUs */
4049aebfd4aSSean Wang smp_mb__after_atomic();
4059aebfd4aSSean Wang wake_up_bit(&bdev->tx_state, BTMTKSDIO_TX_WAIT_VND_EVT);
4069aebfd4aSSean Wang }
4079aebfd4aSSean Wang }
4089aebfd4aSSean Wang
4099aebfd4aSSean Wang return 0;
4109aebfd4aSSean Wang
4119aebfd4aSSean Wang err_free_skb:
4129aebfd4aSSean Wang kfree_skb(bdev->evt_skb);
4139aebfd4aSSean Wang bdev->evt_skb = NULL;
4149aebfd4aSSean Wang
4159aebfd4aSSean Wang err_out:
4169aebfd4aSSean Wang return err;
4179aebfd4aSSean Wang }
4189aebfd4aSSean Wang
btmtksdio_recv_acl(struct hci_dev * hdev,struct sk_buff * skb)419db57b625SSean Wang static int btmtksdio_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
420db57b625SSean Wang {
421db57b625SSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
422db57b625SSean Wang u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
423db57b625SSean Wang
424db57b625SSean Wang switch (handle) {
425db57b625SSean Wang case 0xfc6f:
426db57b625SSean Wang /* Firmware dump from device: when the firmware hangs, the
427db57b625SSean Wang * device can no longer suspend and thus disable auto-suspend.
428db57b625SSean Wang */
429db57b625SSean Wang pm_runtime_forbid(bdev->dev);
430db57b625SSean Wang fallthrough;
431db57b625SSean Wang case 0x05ff:
432db57b625SSean Wang case 0x05fe:
433db57b625SSean Wang /* Firmware debug logging */
434db57b625SSean Wang return hci_recv_diag(hdev, skb);
435db57b625SSean Wang }
436db57b625SSean Wang
437db57b625SSean Wang return hci_recv_frame(hdev, skb);
438db57b625SSean Wang }
439db57b625SSean Wang
4409aebfd4aSSean Wang static const struct h4_recv_pkt mtk_recv_pkts[] = {
441db57b625SSean Wang { H4_RECV_ACL, .recv = btmtksdio_recv_acl },
4429aebfd4aSSean Wang { H4_RECV_SCO, .recv = hci_recv_frame },
4439aebfd4aSSean Wang { H4_RECV_EVENT, .recv = btmtksdio_recv_event },
4449aebfd4aSSean Wang };
4459aebfd4aSSean Wang
btmtksdio_rx_packet(struct btmtksdio_dev * bdev,u16 rx_size)4469aebfd4aSSean Wang static int btmtksdio_rx_packet(struct btmtksdio_dev *bdev, u16 rx_size)
4479aebfd4aSSean Wang {
4489aebfd4aSSean Wang const struct h4_recv_pkt *pkts = mtk_recv_pkts;
4499aebfd4aSSean Wang int pkts_count = ARRAY_SIZE(mtk_recv_pkts);
4509aebfd4aSSean Wang struct mtkbtsdio_hdr *sdio_hdr;
4519aebfd4aSSean Wang int err, i, pad_size;
4529aebfd4aSSean Wang struct sk_buff *skb;
4539aebfd4aSSean Wang u16 dlen;
4549aebfd4aSSean Wang
4559aebfd4aSSean Wang if (rx_size < sizeof(*sdio_hdr))
4569aebfd4aSSean Wang return -EILSEQ;
4579aebfd4aSSean Wang
4589aebfd4aSSean Wang /* A SDIO packet is exactly containing a Bluetooth packet */
4599aebfd4aSSean Wang skb = bt_skb_alloc(rx_size, GFP_KERNEL);
4609aebfd4aSSean Wang if (!skb)
4619aebfd4aSSean Wang return -ENOMEM;
4629aebfd4aSSean Wang
4639aebfd4aSSean Wang skb_put(skb, rx_size);
4649aebfd4aSSean Wang
4659aebfd4aSSean Wang err = sdio_readsb(bdev->func, skb->data, MTK_REG_CRDR, rx_size);
4669aebfd4aSSean Wang if (err < 0)
4679aebfd4aSSean Wang goto err_kfree_skb;
4689aebfd4aSSean Wang
4699aebfd4aSSean Wang sdio_hdr = (void *)skb->data;
4709aebfd4aSSean Wang
4719aebfd4aSSean Wang /* We assume the default error as -EILSEQ simply to make the error path
4729aebfd4aSSean Wang * be cleaner.
4739aebfd4aSSean Wang */
4749aebfd4aSSean Wang err = -EILSEQ;
4759aebfd4aSSean Wang
4769aebfd4aSSean Wang if (rx_size != le16_to_cpu(sdio_hdr->len)) {
4779aebfd4aSSean Wang bt_dev_err(bdev->hdev, "Rx size in sdio header is mismatched ");
4789aebfd4aSSean Wang goto err_kfree_skb;
4799aebfd4aSSean Wang }
4809aebfd4aSSean Wang
4819aebfd4aSSean Wang hci_skb_pkt_type(skb) = sdio_hdr->bt_type;
4829aebfd4aSSean Wang
4839aebfd4aSSean Wang /* Remove MediaTek SDIO header */
4849aebfd4aSSean Wang skb_pull(skb, sizeof(*sdio_hdr));
4859aebfd4aSSean Wang
4869aebfd4aSSean Wang /* We have to dig into the packet to get payload size and then know how
4879aebfd4aSSean Wang * many padding bytes at the tail, these padding bytes should be removed
4889aebfd4aSSean Wang * before the packet is indicated to the core layer.
4899aebfd4aSSean Wang */
4909aebfd4aSSean Wang for (i = 0; i < pkts_count; i++) {
4919aebfd4aSSean Wang if (sdio_hdr->bt_type == (&pkts[i])->type)
4929aebfd4aSSean Wang break;
4939aebfd4aSSean Wang }
4949aebfd4aSSean Wang
4959aebfd4aSSean Wang if (i >= pkts_count) {
4969aebfd4aSSean Wang bt_dev_err(bdev->hdev, "Invalid bt type 0x%02x",
4979aebfd4aSSean Wang sdio_hdr->bt_type);
4989aebfd4aSSean Wang goto err_kfree_skb;
4999aebfd4aSSean Wang }
5009aebfd4aSSean Wang
5019aebfd4aSSean Wang /* Remaining bytes cannot hold a header*/
5029aebfd4aSSean Wang if (skb->len < (&pkts[i])->hlen) {
5039aebfd4aSSean Wang bt_dev_err(bdev->hdev, "The size of bt header is mismatched");
5049aebfd4aSSean Wang goto err_kfree_skb;
5059aebfd4aSSean Wang }
5069aebfd4aSSean Wang
5079aebfd4aSSean Wang switch ((&pkts[i])->lsize) {
5089aebfd4aSSean Wang case 1:
5099aebfd4aSSean Wang dlen = skb->data[(&pkts[i])->loff];
5109aebfd4aSSean Wang break;
5119aebfd4aSSean Wang case 2:
5129aebfd4aSSean Wang dlen = get_unaligned_le16(skb->data +
5139aebfd4aSSean Wang (&pkts[i])->loff);
5149aebfd4aSSean Wang break;
5159aebfd4aSSean Wang default:
5169aebfd4aSSean Wang goto err_kfree_skb;
5179aebfd4aSSean Wang }
5189aebfd4aSSean Wang
5199aebfd4aSSean Wang pad_size = skb->len - (&pkts[i])->hlen - dlen;
5209aebfd4aSSean Wang
5219aebfd4aSSean Wang /* Remaining bytes cannot hold a payload */
5229aebfd4aSSean Wang if (pad_size < 0) {
5239aebfd4aSSean Wang bt_dev_err(bdev->hdev, "The size of bt payload is mismatched");
5249aebfd4aSSean Wang goto err_kfree_skb;
5259aebfd4aSSean Wang }
5269aebfd4aSSean Wang
5279aebfd4aSSean Wang /* Remove padding bytes */
5289aebfd4aSSean Wang skb_trim(skb, skb->len - pad_size);
5299aebfd4aSSean Wang
5309aebfd4aSSean Wang /* Complete frame */
5319aebfd4aSSean Wang (&pkts[i])->recv(bdev->hdev, skb);
5329aebfd4aSSean Wang
533bcaa7d72SSean Wang bdev->hdev->stat.byte_rx += rx_size;
534bcaa7d72SSean Wang
5359aebfd4aSSean Wang return 0;
5369aebfd4aSSean Wang
5379aebfd4aSSean Wang err_kfree_skb:
5389aebfd4aSSean Wang kfree_skb(skb);
5399aebfd4aSSean Wang
5409aebfd4aSSean Wang return err;
5419aebfd4aSSean Wang }
5429aebfd4aSSean Wang
btmtksdio_txrx_work(struct work_struct * work)54326270bc1SSean Wang static void btmtksdio_txrx_work(struct work_struct *work)
5449aebfd4aSSean Wang {
54526270bc1SSean Wang struct btmtksdio_dev *bdev = container_of(work, struct btmtksdio_dev,
54626270bc1SSean Wang txrx_work);
54726270bc1SSean Wang unsigned long txrx_timeout;
548184ea403SSean Wang u32 int_status, rx_size;
54926270bc1SSean Wang struct sk_buff *skb;
55026270bc1SSean Wang int err;
5517f3c563cSSean Wang
5527f3c563cSSean Wang pm_runtime_get_sync(bdev->dev);
5537f3c563cSSean Wang
5547f3c563cSSean Wang sdio_claim_host(bdev->func);
5557f3c563cSSean Wang
5569aebfd4aSSean Wang /* Disable interrupt */
55726270bc1SSean Wang sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
5589aebfd4aSSean Wang
55926270bc1SSean Wang txrx_timeout = jiffies + 5 * HZ;
56026270bc1SSean Wang
56126270bc1SSean Wang do {
56226270bc1SSean Wang int_status = sdio_readl(bdev->func, MTK_REG_CHISR, NULL);
5639aebfd4aSSean Wang
5649aebfd4aSSean Wang /* Ack an interrupt as soon as possible before any operation on
5659aebfd4aSSean Wang * hardware.
5669aebfd4aSSean Wang *
5679aebfd4aSSean Wang * Note that we don't ack any status during operations to avoid race
5689aebfd4aSSean Wang * condition between the host and the device such as it's possible to
5699aebfd4aSSean Wang * mistakenly ack RX_DONE for the next packet and then cause interrupts
5709aebfd4aSSean Wang * not be raised again but there is still pending data in the hardware
5719aebfd4aSSean Wang * FIFO.
5729aebfd4aSSean Wang */
57326270bc1SSean Wang sdio_writel(bdev->func, int_status, MTK_REG_CHISR, NULL);
574db3f1f9bSSean Wang int_status &= INT_MASK;
5759aebfd4aSSean Wang
5762fc967ccSMark Chen if ((int_status & FW_MAILBOX_INT) &&
5772fc967ccSMark Chen bdev->data->chipid == 0x7921) {
5782fc967ccSMark Chen sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
5792fc967ccSMark Chen MTK_REG_PH2DSM0R, 0);
5802fc967ccSMark Chen }
5812fc967ccSMark Chen
5829aebfd4aSSean Wang if (int_status & FW_OWN_BACK_INT)
583e1052fb2SSean Wang bt_dev_dbg(bdev->hdev, "Get fw own back");
5849aebfd4aSSean Wang
5859aebfd4aSSean Wang if (int_status & TX_EMPTY)
586d555b1f2SSean Wang set_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
587d555b1f2SSean Wang
5889aebfd4aSSean Wang else if (unlikely(int_status & TX_FIFO_OVERFLOW))
589e1052fb2SSean Wang bt_dev_warn(bdev->hdev, "Tx fifo overflow");
5909aebfd4aSSean Wang
591d555b1f2SSean Wang if (test_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state)) {
59210fe40e1SMark-yw Chen skb = skb_dequeue(&bdev->txq);
59310fe40e1SMark-yw Chen if (skb) {
59410fe40e1SMark-yw Chen err = btmtksdio_tx_packet(bdev, skb);
59510fe40e1SMark-yw Chen if (err < 0) {
59610fe40e1SMark-yw Chen bdev->hdev->stat.err_tx++;
59710fe40e1SMark-yw Chen skb_queue_head(&bdev->txq, skb);
59810fe40e1SMark-yw Chen }
59910fe40e1SMark-yw Chen }
60010fe40e1SMark-yw Chen }
60110fe40e1SMark-yw Chen
6029aebfd4aSSean Wang if (int_status & RX_DONE_INT) {
603184ea403SSean Wang rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL);
604184ea403SSean Wang rx_size = (rx_size & RX_PKT_LEN) >> 16;
6059aebfd4aSSean Wang if (btmtksdio_rx_packet(bdev, rx_size) < 0)
6069aebfd4aSSean Wang bdev->hdev->stat.err_rx++;
6079aebfd4aSSean Wang }
60826270bc1SSean Wang } while (int_status || time_is_before_jiffies(txrx_timeout));
60926270bc1SSean Wang
6109aebfd4aSSean Wang /* Enable interrupt */
61126270bc1SSean Wang sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
61226270bc1SSean Wang
61326270bc1SSean Wang sdio_release_host(bdev->func);
6147f3c563cSSean Wang
6157f3c563cSSean Wang pm_runtime_mark_last_busy(bdev->dev);
6167f3c563cSSean Wang pm_runtime_put_autosuspend(bdev->dev);
6179aebfd4aSSean Wang }
6189aebfd4aSSean Wang
btmtksdio_interrupt(struct sdio_func * func)61926270bc1SSean Wang static void btmtksdio_interrupt(struct sdio_func *func)
62026270bc1SSean Wang {
62126270bc1SSean Wang struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
62226270bc1SSean Wang
62326270bc1SSean Wang /* Disable interrupt */
62426270bc1SSean Wang sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
62526270bc1SSean Wang
62626270bc1SSean Wang schedule_work(&bdev->txrx_work);
62726270bc1SSean Wang }
62826270bc1SSean Wang
btmtksdio_open(struct hci_dev * hdev)6299aebfd4aSSean Wang static int btmtksdio_open(struct hci_dev *hdev)
6309aebfd4aSSean Wang {
6319aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
632c7e301d7SMark Chen u32 val;
6339aebfd4aSSean Wang int err;
6349aebfd4aSSean Wang
6359aebfd4aSSean Wang sdio_claim_host(bdev->func);
6369aebfd4aSSean Wang
6379aebfd4aSSean Wang err = sdio_enable_func(bdev->func);
6389aebfd4aSSean Wang if (err < 0)
6399aebfd4aSSean Wang goto err_release_host;
6409aebfd4aSSean Wang
6414b4b2228SSean Wang set_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
6424b4b2228SSean Wang
643c7e301d7SMark Chen err = btmtksdio_drv_pmctrl(bdev);
6449aebfd4aSSean Wang if (err < 0)
6459aebfd4aSSean Wang goto err_disable_func;
6469aebfd4aSSean Wang
6479aebfd4aSSean Wang /* Disable interrupt & mask out all interrupt sources */
6489aebfd4aSSean Wang sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, &err);
6499aebfd4aSSean Wang if (err < 0)
6509aebfd4aSSean Wang goto err_disable_func;
6519aebfd4aSSean Wang
6529aebfd4aSSean Wang sdio_writel(bdev->func, 0, MTK_REG_CHIER, &err);
6539aebfd4aSSean Wang if (err < 0)
6549aebfd4aSSean Wang goto err_disable_func;
6559aebfd4aSSean Wang
6569aebfd4aSSean Wang err = sdio_claim_irq(bdev->func, btmtksdio_interrupt);
6579aebfd4aSSean Wang if (err < 0)
6589aebfd4aSSean Wang goto err_disable_func;
6599aebfd4aSSean Wang
6609aebfd4aSSean Wang err = sdio_set_block_size(bdev->func, MTK_SDIO_BLOCK_SIZE);
6619aebfd4aSSean Wang if (err < 0)
6629aebfd4aSSean Wang goto err_release_irq;
6639aebfd4aSSean Wang
6649aebfd4aSSean Wang /* SDIO CMD 5 allows the SDIO device back to idle state an
6659aebfd4aSSean Wang * synchronous interrupt is supported in SDIO 4-bit mode
6669aebfd4aSSean Wang */
6675b23ac1aSSean Wang val = sdio_readl(bdev->func, MTK_REG_CSDIOCSR, &err);
6685b23ac1aSSean Wang if (err < 0)
6695b23ac1aSSean Wang goto err_release_irq;
6705b23ac1aSSean Wang
6715b23ac1aSSean Wang val |= SDIO_INT_CTL;
6725b23ac1aSSean Wang sdio_writel(bdev->func, val, MTK_REG_CSDIOCSR, &err);
6739aebfd4aSSean Wang if (err < 0)
6749aebfd4aSSean Wang goto err_release_irq;
6759aebfd4aSSean Wang
67677b210d1SSean Wang /* Explitly set write-1-clear method */
67777b210d1SSean Wang val = sdio_readl(bdev->func, MTK_REG_CHCR, &err);
67877b210d1SSean Wang if (err < 0)
67977b210d1SSean Wang goto err_release_irq;
68077b210d1SSean Wang
68177b210d1SSean Wang val |= C_INT_CLR_CTRL;
68277b210d1SSean Wang sdio_writel(bdev->func, val, MTK_REG_CHCR, &err);
6839aebfd4aSSean Wang if (err < 0)
6849aebfd4aSSean Wang goto err_release_irq;
6859aebfd4aSSean Wang
6869aebfd4aSSean Wang /* Setup interrupt sources */
6879aebfd4aSSean Wang sdio_writel(bdev->func, RX_DONE_INT | TX_EMPTY | TX_FIFO_OVERFLOW,
6889aebfd4aSSean Wang MTK_REG_CHIER, &err);
6899aebfd4aSSean Wang if (err < 0)
6909aebfd4aSSean Wang goto err_release_irq;
6919aebfd4aSSean Wang
6929aebfd4aSSean Wang /* Enable interrupt */
6939aebfd4aSSean Wang sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, &err);
6949aebfd4aSSean Wang if (err < 0)
6959aebfd4aSSean Wang goto err_release_irq;
6969aebfd4aSSean Wang
6979aebfd4aSSean Wang sdio_release_host(bdev->func);
6989aebfd4aSSean Wang
6999aebfd4aSSean Wang return 0;
7009aebfd4aSSean Wang
7019aebfd4aSSean Wang err_release_irq:
7029aebfd4aSSean Wang sdio_release_irq(bdev->func);
7039aebfd4aSSean Wang
7049aebfd4aSSean Wang err_disable_func:
7059aebfd4aSSean Wang sdio_disable_func(bdev->func);
7069aebfd4aSSean Wang
7079aebfd4aSSean Wang err_release_host:
7089aebfd4aSSean Wang sdio_release_host(bdev->func);
7099aebfd4aSSean Wang
7109aebfd4aSSean Wang return err;
7119aebfd4aSSean Wang }
7129aebfd4aSSean Wang
btmtksdio_close(struct hci_dev * hdev)7139aebfd4aSSean Wang static int btmtksdio_close(struct hci_dev *hdev)
7149aebfd4aSSean Wang {
7159aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
7169aebfd4aSSean Wang
7179aebfd4aSSean Wang sdio_claim_host(bdev->func);
7189aebfd4aSSean Wang
7199aebfd4aSSean Wang /* Disable interrupt */
7209aebfd4aSSean Wang sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
7219aebfd4aSSean Wang
7229aebfd4aSSean Wang sdio_release_irq(bdev->func);
7239aebfd4aSSean Wang
72426270bc1SSean Wang cancel_work_sync(&bdev->txrx_work);
72526270bc1SSean Wang
726c7e301d7SMark Chen btmtksdio_fw_pmctrl(bdev);
7279aebfd4aSSean Wang
7284b4b2228SSean Wang clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
7299aebfd4aSSean Wang sdio_disable_func(bdev->func);
7309aebfd4aSSean Wang
7319aebfd4aSSean Wang sdio_release_host(bdev->func);
7329aebfd4aSSean Wang
7339aebfd4aSSean Wang return 0;
7349aebfd4aSSean Wang }
7359aebfd4aSSean Wang
btmtksdio_flush(struct hci_dev * hdev)7369aebfd4aSSean Wang static int btmtksdio_flush(struct hci_dev *hdev)
7379aebfd4aSSean Wang {
7389aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
7399aebfd4aSSean Wang
7409aebfd4aSSean Wang skb_queue_purge(&bdev->txq);
7419aebfd4aSSean Wang
74226270bc1SSean Wang cancel_work_sync(&bdev->txrx_work);
7439aebfd4aSSean Wang
7449aebfd4aSSean Wang return 0;
7459aebfd4aSSean Wang }
7469aebfd4aSSean Wang
btmtksdio_func_query(struct hci_dev * hdev)7479aebfd4aSSean Wang static int btmtksdio_func_query(struct hci_dev *hdev)
7489aebfd4aSSean Wang {
7499aebfd4aSSean Wang struct btmtk_hci_wmt_params wmt_params;
7509aebfd4aSSean Wang int status, err;
7519aebfd4aSSean Wang u8 param = 0;
7529aebfd4aSSean Wang
7539aebfd4aSSean Wang /* Query whether the function is enabled */
7543a722044SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
7559aebfd4aSSean Wang wmt_params.flag = 4;
7569aebfd4aSSean Wang wmt_params.dlen = sizeof(param);
7579aebfd4aSSean Wang wmt_params.data = ¶m;
7589aebfd4aSSean Wang wmt_params.status = &status;
7599aebfd4aSSean Wang
7609aebfd4aSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
7619aebfd4aSSean Wang if (err < 0) {
7629aebfd4aSSean Wang bt_dev_err(hdev, "Failed to query function status (%d)", err);
7639aebfd4aSSean Wang return err;
7649aebfd4aSSean Wang }
7659aebfd4aSSean Wang
7669aebfd4aSSean Wang return status;
7679aebfd4aSSean Wang }
7689aebfd4aSSean Wang
mt76xx_setup(struct hci_dev * hdev,const char * fwname)769c603bf1fSSean Wang static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
7709aebfd4aSSean Wang {
77101ecc177SMark Chen struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
7729aebfd4aSSean Wang struct btmtk_hci_wmt_params wmt_params;
7739aebfd4aSSean Wang struct btmtk_tci_sleep tci_sleep;
7749aebfd4aSSean Wang struct sk_buff *skb;
7759aebfd4aSSean Wang int err, status;
7769aebfd4aSSean Wang u8 param = 0x1;
7779aebfd4aSSean Wang
7789aebfd4aSSean Wang /* Query whether the firmware is already download */
7793a722044SSean Wang wmt_params.op = BTMTK_WMT_SEMAPHORE;
7809aebfd4aSSean Wang wmt_params.flag = 1;
7819aebfd4aSSean Wang wmt_params.dlen = 0;
7829aebfd4aSSean Wang wmt_params.data = NULL;
7839aebfd4aSSean Wang wmt_params.status = &status;
7849aebfd4aSSean Wang
7859aebfd4aSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
7869aebfd4aSSean Wang if (err < 0) {
7879aebfd4aSSean Wang bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
7889aebfd4aSSean Wang return err;
7899aebfd4aSSean Wang }
7909aebfd4aSSean Wang
7919aebfd4aSSean Wang if (status == BTMTK_WMT_PATCH_DONE) {
7929aebfd4aSSean Wang bt_dev_info(hdev, "Firmware already downloaded");
7939aebfd4aSSean Wang goto ignore_setup_fw;
7949aebfd4aSSean Wang }
7959aebfd4aSSean Wang
7969aebfd4aSSean Wang /* Setup a firmware which the device definitely requires */
797c603bf1fSSean Wang err = btmtk_setup_firmware(hdev, fwname, mtk_hci_wmt_sync);
7989aebfd4aSSean Wang if (err < 0)
7999aebfd4aSSean Wang return err;
8009aebfd4aSSean Wang
8019aebfd4aSSean Wang ignore_setup_fw:
8029aebfd4aSSean Wang /* Query whether the device is already enabled */
8039aebfd4aSSean Wang err = readx_poll_timeout(btmtksdio_func_query, hdev, status,
8049aebfd4aSSean Wang status < 0 || status != BTMTK_WMT_ON_PROGRESS,
8059aebfd4aSSean Wang 2000, 5000000);
8069aebfd4aSSean Wang /* -ETIMEDOUT happens */
8079aebfd4aSSean Wang if (err < 0)
8089aebfd4aSSean Wang return err;
8099aebfd4aSSean Wang
8109aebfd4aSSean Wang /* The other errors happen in btusb_mtk_func_query */
8119aebfd4aSSean Wang if (status < 0)
8129aebfd4aSSean Wang return status;
8139aebfd4aSSean Wang
8149aebfd4aSSean Wang if (status == BTMTK_WMT_ON_DONE) {
8159aebfd4aSSean Wang bt_dev_info(hdev, "function already on");
8169aebfd4aSSean Wang goto ignore_func_on;
8179aebfd4aSSean Wang }
8189aebfd4aSSean Wang
8199aebfd4aSSean Wang /* Enable Bluetooth protocol */
8203a722044SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
8219aebfd4aSSean Wang wmt_params.flag = 0;
8229aebfd4aSSean Wang wmt_params.dlen = sizeof(param);
8239aebfd4aSSean Wang wmt_params.data = ¶m;
8249aebfd4aSSean Wang wmt_params.status = NULL;
8259aebfd4aSSean Wang
8269aebfd4aSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
8279aebfd4aSSean Wang if (err < 0) {
8289aebfd4aSSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
8299aebfd4aSSean Wang return err;
8309aebfd4aSSean Wang }
8319aebfd4aSSean Wang
83201ecc177SMark Chen set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
83301ecc177SMark Chen
8349aebfd4aSSean Wang ignore_func_on:
8359aebfd4aSSean Wang /* Apply the low power environment setup */
8369aebfd4aSSean Wang tci_sleep.mode = 0x5;
8379aebfd4aSSean Wang tci_sleep.duration = cpu_to_le16(0x640);
8389aebfd4aSSean Wang tci_sleep.host_duration = cpu_to_le16(0x640);
8399aebfd4aSSean Wang tci_sleep.host_wakeup_pin = 0;
8409aebfd4aSSean Wang tci_sleep.time_compensation = 0;
8419aebfd4aSSean Wang
8429aebfd4aSSean Wang skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
8439aebfd4aSSean Wang HCI_INIT_TIMEOUT);
8449aebfd4aSSean Wang if (IS_ERR(skb)) {
8459aebfd4aSSean Wang err = PTR_ERR(skb);
8469aebfd4aSSean Wang bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
8479aebfd4aSSean Wang return err;
8489aebfd4aSSean Wang }
8499aebfd4aSSean Wang kfree_skb(skb);
8509aebfd4aSSean Wang
851c603bf1fSSean Wang return 0;
852c603bf1fSSean Wang }
853c603bf1fSSean Wang
mt79xx_setup(struct hci_dev * hdev,const char * fwname)854c603bf1fSSean Wang static int mt79xx_setup(struct hci_dev *hdev, const char *fwname)
855c603bf1fSSean Wang {
85601ecc177SMark Chen struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
857c603bf1fSSean Wang struct btmtk_hci_wmt_params wmt_params;
858c603bf1fSSean Wang u8 param = 0x1;
859c603bf1fSSean Wang int err;
860c603bf1fSSean Wang
861c603bf1fSSean Wang err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync);
862c603bf1fSSean Wang if (err < 0) {
863c603bf1fSSean Wang bt_dev_err(hdev, "Failed to setup 79xx firmware (%d)", err);
864c603bf1fSSean Wang return err;
865c603bf1fSSean Wang }
866c603bf1fSSean Wang
86774697205SSean Wang err = btmtksdio_fw_pmctrl(bdev);
86874697205SSean Wang if (err < 0)
86974697205SSean Wang return err;
87074697205SSean Wang
87174697205SSean Wang err = btmtksdio_drv_pmctrl(bdev);
87274697205SSean Wang if (err < 0)
87374697205SSean Wang return err;
87474697205SSean Wang
875c603bf1fSSean Wang /* Enable Bluetooth protocol */
876c603bf1fSSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
877c603bf1fSSean Wang wmt_params.flag = 0;
878c603bf1fSSean Wang wmt_params.dlen = sizeof(param);
879c603bf1fSSean Wang wmt_params.data = ¶m;
880c603bf1fSSean Wang wmt_params.status = NULL;
881c603bf1fSSean Wang
882c603bf1fSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
883c603bf1fSSean Wang if (err < 0) {
884c603bf1fSSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
885c603bf1fSSean Wang return err;
886c603bf1fSSean Wang }
887c603bf1fSSean Wang
888630491ffSŁukasz Bartosik hci_set_msft_opcode(hdev, 0xFD30);
88916ada83bSSean Wang hci_set_aosp_capable(hdev);
89001ecc177SMark Chen set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
891630491ffSŁukasz Bartosik
892c603bf1fSSean Wang return err;
893c603bf1fSSean Wang }
894c603bf1fSSean Wang
btmtksdio_mtk_reg_read(struct hci_dev * hdev,u32 reg,u32 * val)8954b685879SSean Wang static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
896c603bf1fSSean Wang {
897c603bf1fSSean Wang struct btmtk_hci_wmt_params wmt_params;
8985677bcf6SSean Wang struct reg_read_cmd reg_read = {
899c603bf1fSSean Wang .type = 1,
900c603bf1fSSean Wang .num = 1,
901c603bf1fSSean Wang };
902c603bf1fSSean Wang u32 status;
903c603bf1fSSean Wang int err;
904c603bf1fSSean Wang
905c603bf1fSSean Wang reg_read.addr = cpu_to_le32(reg);
906c603bf1fSSean Wang wmt_params.op = BTMTK_WMT_REGISTER;
907c603bf1fSSean Wang wmt_params.flag = BTMTK_WMT_REG_READ;
908c603bf1fSSean Wang wmt_params.dlen = sizeof(reg_read);
909c603bf1fSSean Wang wmt_params.data = ®_read;
910c603bf1fSSean Wang wmt_params.status = &status;
911c603bf1fSSean Wang
912c603bf1fSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
913c603bf1fSSean Wang if (err < 0) {
914c603bf1fSSean Wang bt_dev_err(hdev, "Failed to read reg (%d)", err);
915c603bf1fSSean Wang return err;
916c603bf1fSSean Wang }
917c603bf1fSSean Wang
918c603bf1fSSean Wang *val = status;
919c603bf1fSSean Wang
920c603bf1fSSean Wang return err;
921c603bf1fSSean Wang }
922c603bf1fSSean Wang
btmtksdio_mtk_reg_write(struct hci_dev * hdev,u32 reg,u32 val,u32 mask)923191c8723SMark Chen static int btmtksdio_mtk_reg_write(struct hci_dev *hdev, u32 reg, u32 val, u32 mask)
924191c8723SMark Chen {
925191c8723SMark Chen struct btmtk_hci_wmt_params wmt_params;
926191c8723SMark Chen const struct reg_write_cmd reg_write = {
927191c8723SMark Chen .type = 1,
928191c8723SMark Chen .num = 1,
929191c8723SMark Chen .addr = cpu_to_le32(reg),
930191c8723SMark Chen .data = cpu_to_le32(val),
931191c8723SMark Chen .mask = cpu_to_le32(mask),
932191c8723SMark Chen };
933191c8723SMark Chen int err, status;
934191c8723SMark Chen
935191c8723SMark Chen wmt_params.op = BTMTK_WMT_REGISTER;
936191c8723SMark Chen wmt_params.flag = BTMTK_WMT_REG_WRITE;
937191c8723SMark Chen wmt_params.dlen = sizeof(reg_write);
938191c8723SMark Chen wmt_params.data = ®_write;
939191c8723SMark Chen wmt_params.status = &status;
940191c8723SMark Chen
941191c8723SMark Chen err = mtk_hci_wmt_sync(hdev, &wmt_params);
942191c8723SMark Chen if (err < 0)
943191c8723SMark Chen bt_dev_err(hdev, "Failed to write reg (%d)", err);
944191c8723SMark Chen
945191c8723SMark Chen return err;
946191c8723SMark Chen }
947191c8723SMark Chen
btmtksdio_get_data_path_id(struct hci_dev * hdev,__u8 * data_path_id)948d786105eSYake Yang static int btmtksdio_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
949d786105eSYake Yang {
950d786105eSYake Yang /* uses 1 as data path id for all the usecases */
951d786105eSYake Yang *data_path_id = 1;
952d786105eSYake Yang return 0;
953d786105eSYake Yang }
954d786105eSYake Yang
btmtksdio_get_codec_config_data(struct hci_dev * hdev,__u8 link,struct bt_codec * codec,__u8 * ven_len,__u8 ** ven_data)955f41b91faSYake Yang static int btmtksdio_get_codec_config_data(struct hci_dev *hdev,
956f41b91faSYake Yang __u8 link, struct bt_codec *codec,
957f41b91faSYake Yang __u8 *ven_len, __u8 **ven_data)
958f41b91faSYake Yang {
959f41b91faSYake Yang int err = 0;
960f41b91faSYake Yang
961f41b91faSYake Yang if (!ven_data || !ven_len)
962f41b91faSYake Yang return -EINVAL;
963f41b91faSYake Yang
964f41b91faSYake Yang *ven_len = 0;
965f41b91faSYake Yang *ven_data = NULL;
966f41b91faSYake Yang
967f41b91faSYake Yang if (link != ESCO_LINK) {
968f41b91faSYake Yang bt_dev_err(hdev, "Invalid link type(%u)", link);
969f41b91faSYake Yang return -EINVAL;
970f41b91faSYake Yang }
971f41b91faSYake Yang
972f41b91faSYake Yang *ven_data = kmalloc(sizeof(__u8), GFP_KERNEL);
973789f6b8aSSean Wang if (!*ven_data) {
974f41b91faSYake Yang err = -ENOMEM;
975f41b91faSYake Yang goto error;
976f41b91faSYake Yang }
977f41b91faSYake Yang
978f41b91faSYake Yang /* supports only CVSD and mSBC offload codecs */
979f41b91faSYake Yang switch (codec->id) {
980f41b91faSYake Yang case 0x02:
981f41b91faSYake Yang **ven_data = 0x00;
982f41b91faSYake Yang break;
983f41b91faSYake Yang case 0x05:
984f41b91faSYake Yang **ven_data = 0x01;
985f41b91faSYake Yang break;
986f41b91faSYake Yang default:
987f41b91faSYake Yang err = -EINVAL;
988f41b91faSYake Yang bt_dev_err(hdev, "Invalid codec id(%u)", codec->id);
989f41b91faSYake Yang goto error;
990f41b91faSYake Yang }
991f41b91faSYake Yang /* codec and its capabilities are pre-defined to ids
992f41b91faSYake Yang * preset id = 0x00 represents CVSD codec with sampling rate 8K
993f41b91faSYake Yang * preset id = 0x01 represents mSBC codec with sampling rate 16K
994f41b91faSYake Yang */
995f41b91faSYake Yang *ven_len = sizeof(__u8);
996f41b91faSYake Yang return err;
997f41b91faSYake Yang
998f41b91faSYake Yang error:
999f41b91faSYake Yang kfree(*ven_data);
1000f41b91faSYake Yang *ven_data = NULL;
1001f41b91faSYake Yang return err;
1002f41b91faSYake Yang }
1003f41b91faSYake Yang
btmtksdio_sco_setting(struct hci_dev * hdev)1004191c8723SMark Chen static int btmtksdio_sco_setting(struct hci_dev *hdev)
1005191c8723SMark Chen {
1006191c8723SMark Chen const struct btmtk_sco sco_setting = {
1007191c8723SMark Chen .clock_config = 0x49,
1008191c8723SMark Chen .channel_format_config = 0x80,
1009191c8723SMark Chen };
1010191c8723SMark Chen struct sk_buff *skb;
1011191c8723SMark Chen u32 val;
1012191c8723SMark Chen int err;
1013191c8723SMark Chen
1014191c8723SMark Chen /* Enable SCO over I2S/PCM for MediaTek chipset */
1015191c8723SMark Chen skb = __hci_cmd_sync(hdev, 0xfc72, sizeof(sco_setting),
1016191c8723SMark Chen &sco_setting, HCI_CMD_TIMEOUT);
1017191c8723SMark Chen if (IS_ERR(skb))
1018191c8723SMark Chen return PTR_ERR(skb);
1019191c8723SMark Chen
1020191c8723SMark Chen kfree_skb(skb);
1021191c8723SMark Chen
1022191c8723SMark Chen err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_0, &val);
1023191c8723SMark Chen if (err < 0)
1024191c8723SMark Chen return err;
1025191c8723SMark Chen
1026191c8723SMark Chen val |= 0x11000000;
1027191c8723SMark Chen err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_0, val, ~0);
1028191c8723SMark Chen if (err < 0)
1029191c8723SMark Chen return err;
1030191c8723SMark Chen
1031191c8723SMark Chen err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_1, &val);
1032191c8723SMark Chen if (err < 0)
1033191c8723SMark Chen return err;
1034191c8723SMark Chen
1035191c8723SMark Chen val |= 0x00000101;
1036d786105eSYake Yang err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0);
1037d786105eSYake Yang if (err < 0)
1038d786105eSYake Yang return err;
1039d786105eSYake Yang
1040d786105eSYake Yang hdev->get_data_path_id = btmtksdio_get_data_path_id;
1041f41b91faSYake Yang hdev->get_codec_config_data = btmtksdio_get_codec_config_data;
1042d786105eSYake Yang
1043d786105eSYake Yang return err;
1044191c8723SMark Chen }
1045191c8723SMark Chen
btmtksdio_reset_setting(struct hci_dev * hdev)10468fafe702SChih-Ying Chiang static int btmtksdio_reset_setting(struct hci_dev *hdev)
10478fafe702SChih-Ying Chiang {
10488fafe702SChih-Ying Chiang int err;
10498fafe702SChih-Ying Chiang u32 val;
10508fafe702SChih-Ying Chiang
10518fafe702SChih-Ying Chiang err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_1, &val);
10528fafe702SChih-Ying Chiang if (err < 0)
10538fafe702SChih-Ying Chiang return err;
10548fafe702SChih-Ying Chiang
10558fafe702SChih-Ying Chiang val |= 0x20; /* set the pin (bit field 11:8) work as GPIO mode */
10568fafe702SChih-Ying Chiang err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0);
10578fafe702SChih-Ying Chiang if (err < 0)
10588fafe702SChih-Ying Chiang return err;
10598fafe702SChih-Ying Chiang
10608fafe702SChih-Ying Chiang err = btmtksdio_mtk_reg_read(hdev, MT7921_BTSYS_RST, &val);
10618fafe702SChih-Ying Chiang if (err < 0)
10628fafe702SChih-Ying Chiang return err;
10638fafe702SChih-Ying Chiang
10648fafe702SChih-Ying Chiang val |= MT7921_BTSYS_RST_WITH_GPIO;
10658fafe702SChih-Ying Chiang return btmtksdio_mtk_reg_write(hdev, MT7921_BTSYS_RST, val, ~0);
10668fafe702SChih-Ying Chiang }
10678fafe702SChih-Ying Chiang
btmtksdio_setup(struct hci_dev * hdev)1068c603bf1fSSean Wang static int btmtksdio_setup(struct hci_dev *hdev)
1069c603bf1fSSean Wang {
1070c603bf1fSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
1071c603bf1fSSean Wang ktime_t calltime, delta, rettime;
1072c603bf1fSSean Wang unsigned long long duration;
1073c603bf1fSSean Wang char fwname[64];
1074c603bf1fSSean Wang int err, dev_id;
10758fafe702SChih-Ying Chiang u32 fw_version = 0, val;
1076c603bf1fSSean Wang
1077c603bf1fSSean Wang calltime = ktime_get();
1078d555b1f2SSean Wang set_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
1079c603bf1fSSean Wang
1080c603bf1fSSean Wang switch (bdev->data->chipid) {
1081c603bf1fSSean Wang case 0x7921:
10828fafe702SChih-Ying Chiang if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state)) {
10838fafe702SChih-Ying Chiang err = btmtksdio_mtk_reg_read(hdev, MT7921_DLSTATUS,
10848fafe702SChih-Ying Chiang &val);
10858fafe702SChih-Ying Chiang if (err < 0)
10868fafe702SChih-Ying Chiang return err;
10878fafe702SChih-Ying Chiang
10888fafe702SChih-Ying Chiang val &= ~BT_DL_STATE;
10898fafe702SChih-Ying Chiang err = btmtksdio_mtk_reg_write(hdev, MT7921_DLSTATUS,
10908fafe702SChih-Ying Chiang val, ~0);
10918fafe702SChih-Ying Chiang if (err < 0)
10928fafe702SChih-Ying Chiang return err;
10938fafe702SChih-Ying Chiang
10948fafe702SChih-Ying Chiang btmtksdio_fw_pmctrl(bdev);
10958fafe702SChih-Ying Chiang msleep(20);
10968fafe702SChih-Ying Chiang btmtksdio_drv_pmctrl(bdev);
10978fafe702SChih-Ying Chiang
10988fafe702SChih-Ying Chiang clear_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state);
10998fafe702SChih-Ying Chiang }
11008fafe702SChih-Ying Chiang
11014b685879SSean Wang err = btmtksdio_mtk_reg_read(hdev, 0x70010200, &dev_id);
1102c603bf1fSSean Wang if (err < 0) {
1103c603bf1fSSean Wang bt_dev_err(hdev, "Failed to get device id (%d)", err);
1104c603bf1fSSean Wang return err;
1105c603bf1fSSean Wang }
1106c603bf1fSSean Wang
11074b685879SSean Wang err = btmtksdio_mtk_reg_read(hdev, 0x80021004, &fw_version);
1108c603bf1fSSean Wang if (err < 0) {
1109c603bf1fSSean Wang bt_dev_err(hdev, "Failed to get fw version (%d)", err);
1110c603bf1fSSean Wang return err;
1111c603bf1fSSean Wang }
1112c603bf1fSSean Wang
1113c603bf1fSSean Wang snprintf(fwname, sizeof(fwname),
1114c603bf1fSSean Wang "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
1115c603bf1fSSean Wang dev_id & 0xffff, (fw_version & 0xff) + 1);
1116c603bf1fSSean Wang err = mt79xx_setup(hdev, fwname);
1117c603bf1fSSean Wang if (err < 0)
1118c603bf1fSSean Wang return err;
1119191c8723SMark Chen
1120191c8723SMark Chen /* Enable SCO over I2S/PCM */
1121191c8723SMark Chen err = btmtksdio_sco_setting(hdev);
1122191c8723SMark Chen if (err < 0) {
1123191c8723SMark Chen bt_dev_err(hdev, "Failed to enable SCO setting (%d)", err);
1124191c8723SMark Chen return err;
1125191c8723SMark Chen }
1126191c8723SMark Chen
11275ad80cfcSYake Yang /* Enable WBS with mSBC codec */
11285ad80cfcSYake Yang set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
11295ad80cfcSYake Yang
11308fafe702SChih-Ying Chiang /* Enable GPIO reset mechanism */
11318fafe702SChih-Ying Chiang if (bdev->reset) {
11328fafe702SChih-Ying Chiang err = btmtksdio_reset_setting(hdev);
11338fafe702SChih-Ying Chiang if (err < 0) {
11348fafe702SChih-Ying Chiang bt_dev_err(hdev, "Failed to enable Reset setting (%d)", err);
11358fafe702SChih-Ying Chiang devm_gpiod_put(bdev->dev, bdev->reset);
11368fafe702SChih-Ying Chiang bdev->reset = NULL;
11378fafe702SChih-Ying Chiang }
11388fafe702SChih-Ying Chiang }
11398fafe702SChih-Ying Chiang
1140546ff98eSYake Yang /* Valid LE States quirk for MediaTek 7921 */
1141546ff98eSYake Yang set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
1142546ff98eSYake Yang
1143c603bf1fSSean Wang break;
1144c603bf1fSSean Wang case 0x7663:
1145c603bf1fSSean Wang case 0x7668:
1146c603bf1fSSean Wang err = mt76xx_setup(hdev, bdev->data->fwname);
1147c603bf1fSSean Wang if (err < 0)
1148c603bf1fSSean Wang return err;
1149c603bf1fSSean Wang break;
1150c603bf1fSSean Wang default:
1151c603bf1fSSean Wang return -ENODEV;
1152c603bf1fSSean Wang }
1153c603bf1fSSean Wang
11549aebfd4aSSean Wang rettime = ktime_get();
11559aebfd4aSSean Wang delta = ktime_sub(rettime, calltime);
11569aebfd4aSSean Wang duration = (unsigned long long)ktime_to_ns(delta) >> 10;
11579aebfd4aSSean Wang
11587f3c563cSSean Wang pm_runtime_set_autosuspend_delay(bdev->dev,
11597f3c563cSSean Wang MTKBTSDIO_AUTOSUSPEND_DELAY);
11607f3c563cSSean Wang pm_runtime_use_autosuspend(bdev->dev);
11617f3c563cSSean Wang
11627f3c563cSSean Wang err = pm_runtime_set_active(bdev->dev);
11637f3c563cSSean Wang if (err < 0)
11647f3c563cSSean Wang return err;
11657f3c563cSSean Wang
11667f3c563cSSean Wang /* Default forbid runtime auto suspend, that can be allowed by
11677f3c563cSSean Wang * enable_autosuspend flag or the PM runtime entry under sysfs.
11687f3c563cSSean Wang */
11697f3c563cSSean Wang pm_runtime_forbid(bdev->dev);
11707f3c563cSSean Wang pm_runtime_enable(bdev->dev);
11717f3c563cSSean Wang
11727f3c563cSSean Wang if (enable_autosuspend)
11737f3c563cSSean Wang pm_runtime_allow(bdev->dev);
11747f3c563cSSean Wang
11759aebfd4aSSean Wang bt_dev_info(hdev, "Device setup in %llu usecs", duration);
11769aebfd4aSSean Wang
11779aebfd4aSSean Wang return 0;
11789aebfd4aSSean Wang }
11799aebfd4aSSean Wang
btmtksdio_shutdown(struct hci_dev * hdev)11809aebfd4aSSean Wang static int btmtksdio_shutdown(struct hci_dev *hdev)
11819aebfd4aSSean Wang {
11827f3c563cSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
11839aebfd4aSSean Wang struct btmtk_hci_wmt_params wmt_params;
11849aebfd4aSSean Wang u8 param = 0x0;
11859aebfd4aSSean Wang int err;
11869aebfd4aSSean Wang
11877f3c563cSSean Wang /* Get back the state to be consistent with the state
11887f3c563cSSean Wang * in btmtksdio_setup.
11897f3c563cSSean Wang */
11907f3c563cSSean Wang pm_runtime_get_sync(bdev->dev);
11917f3c563cSSean Wang
1192baabb7f5SSean Wang /* wmt command only works until the reset is complete */
1193baabb7f5SSean Wang if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
1194baabb7f5SSean Wang goto ignore_wmt_cmd;
1195baabb7f5SSean Wang
11969aebfd4aSSean Wang /* Disable the device */
11973a722044SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
11989aebfd4aSSean Wang wmt_params.flag = 0;
11999aebfd4aSSean Wang wmt_params.dlen = sizeof(param);
12009aebfd4aSSean Wang wmt_params.data = ¶m;
12019aebfd4aSSean Wang wmt_params.status = NULL;
12029aebfd4aSSean Wang
12039aebfd4aSSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
12049aebfd4aSSean Wang if (err < 0) {
12059aebfd4aSSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
12069aebfd4aSSean Wang return err;
12079aebfd4aSSean Wang }
12089aebfd4aSSean Wang
1209baabb7f5SSean Wang ignore_wmt_cmd:
12107f3c563cSSean Wang pm_runtime_put_noidle(bdev->dev);
12117f3c563cSSean Wang pm_runtime_disable(bdev->dev);
12127f3c563cSSean Wang
12139aebfd4aSSean Wang return 0;
12149aebfd4aSSean Wang }
12159aebfd4aSSean Wang
btmtksdio_send_frame(struct hci_dev * hdev,struct sk_buff * skb)12169aebfd4aSSean Wang static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
12179aebfd4aSSean Wang {
12189aebfd4aSSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
12199aebfd4aSSean Wang
12209aebfd4aSSean Wang switch (hci_skb_pkt_type(skb)) {
12219aebfd4aSSean Wang case HCI_COMMAND_PKT:
12229aebfd4aSSean Wang hdev->stat.cmd_tx++;
12239aebfd4aSSean Wang break;
12249aebfd4aSSean Wang
12259aebfd4aSSean Wang case HCI_ACLDATA_PKT:
12269aebfd4aSSean Wang hdev->stat.acl_tx++;
12279aebfd4aSSean Wang break;
12289aebfd4aSSean Wang
12299aebfd4aSSean Wang case HCI_SCODATA_PKT:
12309aebfd4aSSean Wang hdev->stat.sco_tx++;
12319aebfd4aSSean Wang break;
12329aebfd4aSSean Wang
12339aebfd4aSSean Wang default:
12349aebfd4aSSean Wang return -EILSEQ;
12359aebfd4aSSean Wang }
12369aebfd4aSSean Wang
12379aebfd4aSSean Wang skb_queue_tail(&bdev->txq, skb);
12389aebfd4aSSean Wang
123926270bc1SSean Wang schedule_work(&bdev->txrx_work);
12409aebfd4aSSean Wang
12419aebfd4aSSean Wang return 0;
12429aebfd4aSSean Wang }
12439aebfd4aSSean Wang
btmtksdio_cmd_timeout(struct hci_dev * hdev)12448fafe702SChih-Ying Chiang static void btmtksdio_cmd_timeout(struct hci_dev *hdev)
12458fafe702SChih-Ying Chiang {
12468fafe702SChih-Ying Chiang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
12478fafe702SChih-Ying Chiang u32 status;
12488fafe702SChih-Ying Chiang int err;
12498fafe702SChih-Ying Chiang
12508fafe702SChih-Ying Chiang if (!bdev->reset || bdev->data->chipid != 0x7921)
12518fafe702SChih-Ying Chiang return;
12528fafe702SChih-Ying Chiang
12538fafe702SChih-Ying Chiang pm_runtime_get_sync(bdev->dev);
12548fafe702SChih-Ying Chiang
12558fafe702SChih-Ying Chiang if (test_and_set_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
12568fafe702SChih-Ying Chiang return;
12578fafe702SChih-Ying Chiang
12588fafe702SChih-Ying Chiang sdio_claim_host(bdev->func);
12598fafe702SChih-Ying Chiang
12608fafe702SChih-Ying Chiang sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
12618fafe702SChih-Ying Chiang skb_queue_purge(&bdev->txq);
12628fafe702SChih-Ying Chiang cancel_work_sync(&bdev->txrx_work);
12638fafe702SChih-Ying Chiang
12648fafe702SChih-Ying Chiang gpiod_set_value_cansleep(bdev->reset, 1);
12658fafe702SChih-Ying Chiang msleep(100);
12668fafe702SChih-Ying Chiang gpiod_set_value_cansleep(bdev->reset, 0);
12678fafe702SChih-Ying Chiang
12688fafe702SChih-Ying Chiang err = readx_poll_timeout(btmtksdio_chcr_query, bdev, status,
12698fafe702SChih-Ying Chiang status & BT_RST_DONE, 100000, 2000000);
12708fafe702SChih-Ying Chiang if (err < 0) {
12718fafe702SChih-Ying Chiang bt_dev_err(hdev, "Failed to reset (%d)", err);
12728fafe702SChih-Ying Chiang goto err;
12738fafe702SChih-Ying Chiang }
12748fafe702SChih-Ying Chiang
12758fafe702SChih-Ying Chiang clear_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
12768fafe702SChih-Ying Chiang err:
12778fafe702SChih-Ying Chiang sdio_release_host(bdev->func);
12788fafe702SChih-Ying Chiang
12798fafe702SChih-Ying Chiang pm_runtime_put_noidle(bdev->dev);
12808fafe702SChih-Ying Chiang pm_runtime_disable(bdev->dev);
12818fafe702SChih-Ying Chiang
12828fafe702SChih-Ying Chiang hci_reset_dev(hdev);
12838fafe702SChih-Ying Chiang }
12848fafe702SChih-Ying Chiang
btmtksdio_sdio_inband_wakeup(struct hci_dev * hdev)1285*df332800SSean Wang static bool btmtksdio_sdio_inband_wakeup(struct hci_dev *hdev)
1286*df332800SSean Wang {
1287*df332800SSean Wang struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
1288*df332800SSean Wang
1289*df332800SSean Wang return device_may_wakeup(bdev->dev);
1290*df332800SSean Wang }
1291*df332800SSean Wang
btmtksdio_sdio_wakeup(struct hci_dev * hdev)1292ce64b3e9SMark Chen static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev)
1293ce64b3e9SMark Chen {
1294ce64b3e9SMark Chen struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
1295ce64b3e9SMark Chen bool may_wakeup = device_may_wakeup(bdev->dev);
1296ce64b3e9SMark Chen const struct btmtk_wakeon bt_awake = {
1297ce64b3e9SMark Chen .mode = 0x1,
1298ce64b3e9SMark Chen .gpo = 0,
1299ce64b3e9SMark Chen .active_high = 0x1,
1300ce64b3e9SMark Chen .enable_delay = cpu_to_le16(0xc80),
1301ce64b3e9SMark Chen .wakeup_delay = cpu_to_le16(0x20),
1302ce64b3e9SMark Chen };
1303ce64b3e9SMark Chen
1304ce64b3e9SMark Chen if (may_wakeup && bdev->data->chipid == 0x7921) {
1305ce64b3e9SMark Chen struct sk_buff *skb;
1306ce64b3e9SMark Chen
1307ce64b3e9SMark Chen skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake),
1308ce64b3e9SMark Chen &bt_awake, HCI_CMD_TIMEOUT);
1309ce64b3e9SMark Chen if (IS_ERR(skb))
1310ce64b3e9SMark Chen may_wakeup = false;
1311eb3f0517SYake Yang else
1312ce64b3e9SMark Chen kfree_skb(skb);
1313ce64b3e9SMark Chen }
1314ce64b3e9SMark Chen
1315ce64b3e9SMark Chen return may_wakeup;
1316ce64b3e9SMark Chen }
1317ce64b3e9SMark Chen
btmtksdio_probe(struct sdio_func * func,const struct sdio_device_id * id)13189aebfd4aSSean Wang static int btmtksdio_probe(struct sdio_func *func,
13199aebfd4aSSean Wang const struct sdio_device_id *id)
13209aebfd4aSSean Wang {
13219aebfd4aSSean Wang struct btmtksdio_dev *bdev;
13229aebfd4aSSean Wang struct hci_dev *hdev;
13239aebfd4aSSean Wang int err;
13249aebfd4aSSean Wang
13259aebfd4aSSean Wang bdev = devm_kzalloc(&func->dev, sizeof(*bdev), GFP_KERNEL);
13269aebfd4aSSean Wang if (!bdev)
13279aebfd4aSSean Wang return -ENOMEM;
13289aebfd4aSSean Wang
13299aebfd4aSSean Wang bdev->data = (void *)id->driver_data;
13309aebfd4aSSean Wang if (!bdev->data)
13319aebfd4aSSean Wang return -ENODEV;
13329aebfd4aSSean Wang
13337f3c563cSSean Wang bdev->dev = &func->dev;
13349aebfd4aSSean Wang bdev->func = func;
13359aebfd4aSSean Wang
133626270bc1SSean Wang INIT_WORK(&bdev->txrx_work, btmtksdio_txrx_work);
13379aebfd4aSSean Wang skb_queue_head_init(&bdev->txq);
13389aebfd4aSSean Wang
13399aebfd4aSSean Wang /* Initialize and register HCI device */
13409aebfd4aSSean Wang hdev = hci_alloc_dev();
13419aebfd4aSSean Wang if (!hdev) {
13429aebfd4aSSean Wang dev_err(&func->dev, "Can't allocate HCI device\n");
13439aebfd4aSSean Wang return -ENOMEM;
13449aebfd4aSSean Wang }
13459aebfd4aSSean Wang
13469aebfd4aSSean Wang bdev->hdev = hdev;
13479aebfd4aSSean Wang
13489aebfd4aSSean Wang hdev->bus = HCI_SDIO;
13499aebfd4aSSean Wang hci_set_drvdata(hdev, bdev);
13509aebfd4aSSean Wang
13519aebfd4aSSean Wang hdev->open = btmtksdio_open;
13529aebfd4aSSean Wang hdev->close = btmtksdio_close;
13538fafe702SChih-Ying Chiang hdev->cmd_timeout = btmtksdio_cmd_timeout;
13549aebfd4aSSean Wang hdev->flush = btmtksdio_flush;
13559aebfd4aSSean Wang hdev->setup = btmtksdio_setup;
13569aebfd4aSSean Wang hdev->shutdown = btmtksdio_shutdown;
13579aebfd4aSSean Wang hdev->send = btmtksdio_send_frame;
1358ce64b3e9SMark Chen hdev->wakeup = btmtksdio_sdio_wakeup;
1359*df332800SSean Wang /*
1360*df332800SSean Wang * If SDIO controller supports wake on Bluetooth, sending a wakeon
1361*df332800SSean Wang * command is not necessary.
1362*df332800SSean Wang */
1363*df332800SSean Wang if (device_can_wakeup(func->card->host->parent))
1364*df332800SSean Wang hdev->wakeup = btmtksdio_sdio_inband_wakeup;
1365*df332800SSean Wang else
1366*df332800SSean Wang hdev->wakeup = btmtksdio_sdio_wakeup;
1367877ec9e1SSean Wang hdev->set_bdaddr = btmtk_set_bdaddr;
1368877ec9e1SSean Wang
13699aebfd4aSSean Wang SET_HCIDEV_DEV(hdev, &func->dev);
13709aebfd4aSSean Wang
13719aebfd4aSSean Wang hdev->manufacturer = 70;
13729aebfd4aSSean Wang set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
13739aebfd4aSSean Wang
1374b062a0b9SYake Yang sdio_set_drvdata(func, bdev);
1375b062a0b9SYake Yang
13769aebfd4aSSean Wang err = hci_register_dev(hdev);
13779aebfd4aSSean Wang if (err < 0) {
13789aebfd4aSSean Wang dev_err(&func->dev, "Can't register HCI device\n");
13799aebfd4aSSean Wang hci_free_dev(hdev);
13809aebfd4aSSean Wang return err;
13819aebfd4aSSean Wang }
13829aebfd4aSSean Wang
13837f3c563cSSean Wang /* pm_runtime_enable would be done after the firmware is being
13847f3c563cSSean Wang * downloaded because the core layer probably already enables
13857f3c563cSSean Wang * runtime PM for this func such as the case host->caps &
13867f3c563cSSean Wang * MMC_CAP_POWER_OFF_CARD.
13877f3c563cSSean Wang */
13887f3c563cSSean Wang if (pm_runtime_enabled(bdev->dev))
13897f3c563cSSean Wang pm_runtime_disable(bdev->dev);
13907f3c563cSSean Wang
13917f3c563cSSean Wang /* As explaination in drivers/mmc/core/sdio_bus.c tells us:
13927f3c563cSSean Wang * Unbound SDIO functions are always suspended.
13937f3c563cSSean Wang * During probe, the function is set active and the usage count
13947f3c563cSSean Wang * is incremented. If the driver supports runtime PM,
13957f3c563cSSean Wang * it should call pm_runtime_put_noidle() in its probe routine and
13967f3c563cSSean Wang * pm_runtime_get_noresume() in its remove routine.
13977f3c563cSSean Wang *
13987f3c563cSSean Wang * So, put a pm_runtime_put_noidle here !
13997f3c563cSSean Wang */
14007f3c563cSSean Wang pm_runtime_put_noidle(bdev->dev);
14017f3c563cSSean Wang
1402ce64b3e9SMark Chen err = device_init_wakeup(bdev->dev, true);
1403ce64b3e9SMark Chen if (err)
1404ce64b3e9SMark Chen bt_dev_err(hdev, "failed to initialize device wakeup");
1405ce64b3e9SMark Chen
14068fafe702SChih-Ying Chiang bdev->dev->of_node = of_find_compatible_node(NULL, NULL,
14078fafe702SChih-Ying Chiang "mediatek,mt7921s-bluetooth");
14088fafe702SChih-Ying Chiang bdev->reset = devm_gpiod_get_optional(bdev->dev, "reset",
14098fafe702SChih-Ying Chiang GPIOD_OUT_LOW);
14108fafe702SChih-Ying Chiang if (IS_ERR(bdev->reset))
14118fafe702SChih-Ying Chiang err = PTR_ERR(bdev->reset);
14128fafe702SChih-Ying Chiang
1413ce64b3e9SMark Chen return err;
14149aebfd4aSSean Wang }
14159aebfd4aSSean Wang
btmtksdio_remove(struct sdio_func * func)14169aebfd4aSSean Wang static void btmtksdio_remove(struct sdio_func *func)
14179aebfd4aSSean Wang {
14189aebfd4aSSean Wang struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
14199aebfd4aSSean Wang struct hci_dev *hdev;
14209aebfd4aSSean Wang
14219aebfd4aSSean Wang if (!bdev)
14229aebfd4aSSean Wang return;
14239aebfd4aSSean Wang
14247f3c563cSSean Wang /* Be consistent the state in btmtksdio_probe */
14257f3c563cSSean Wang pm_runtime_get_noresume(bdev->dev);
14267f3c563cSSean Wang
14279aebfd4aSSean Wang hdev = bdev->hdev;
14289aebfd4aSSean Wang
14299aebfd4aSSean Wang sdio_set_drvdata(func, NULL);
14309aebfd4aSSean Wang hci_unregister_dev(hdev);
14319aebfd4aSSean Wang hci_free_dev(hdev);
14329aebfd4aSSean Wang }
14339aebfd4aSSean Wang
14347f3c563cSSean Wang #ifdef CONFIG_PM
btmtksdio_runtime_suspend(struct device * dev)14357f3c563cSSean Wang static int btmtksdio_runtime_suspend(struct device *dev)
14367f3c563cSSean Wang {
14377f3c563cSSean Wang struct sdio_func *func = dev_to_sdio_func(dev);
14387f3c563cSSean Wang struct btmtksdio_dev *bdev;
14397f3c563cSSean Wang int err;
14407f3c563cSSean Wang
14417f3c563cSSean Wang bdev = sdio_get_drvdata(func);
14427f3c563cSSean Wang if (!bdev)
14437f3c563cSSean Wang return 0;
14447f3c563cSSean Wang
14454b4b2228SSean Wang if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
14464b4b2228SSean Wang return 0;
14474b4b2228SSean Wang
1448561ae1d4SSean Wang sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
1449561ae1d4SSean Wang
1450c7e301d7SMark Chen err = btmtksdio_fw_pmctrl(bdev);
14517f3c563cSSean Wang
1452095519deSSean Wang bt_dev_dbg(bdev->hdev, "status (%d) return ownership to device", err);
14537f3c563cSSean Wang
14547f3c563cSSean Wang return err;
14557f3c563cSSean Wang }
14567f3c563cSSean Wang
btmtksdio_runtime_resume(struct device * dev)14577f3c563cSSean Wang static int btmtksdio_runtime_resume(struct device *dev)
14587f3c563cSSean Wang {
14597f3c563cSSean Wang struct sdio_func *func = dev_to_sdio_func(dev);
14607f3c563cSSean Wang struct btmtksdio_dev *bdev;
14617f3c563cSSean Wang int err;
14627f3c563cSSean Wang
14637f3c563cSSean Wang bdev = sdio_get_drvdata(func);
14647f3c563cSSean Wang if (!bdev)
14657f3c563cSSean Wang return 0;
14667f3c563cSSean Wang
14674b4b2228SSean Wang if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
14684b4b2228SSean Wang return 0;
14694b4b2228SSean Wang
1470c7e301d7SMark Chen err = btmtksdio_drv_pmctrl(bdev);
14717f3c563cSSean Wang
1472095519deSSean Wang bt_dev_dbg(bdev->hdev, "status (%d) get ownership from device", err);
14737f3c563cSSean Wang
14747f3c563cSSean Wang return err;
14757f3c563cSSean Wang }
14767f3c563cSSean Wang
14777f3c563cSSean Wang static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend,
14787f3c563cSSean Wang btmtksdio_runtime_resume, NULL);
14797f3c563cSSean Wang #define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
14807f3c563cSSean Wang #else /* CONFIG_PM */
14817f3c563cSSean Wang #define BTMTKSDIO_PM_OPS NULL
14827f3c563cSSean Wang #endif /* CONFIG_PM */
14837f3c563cSSean Wang
14849aebfd4aSSean Wang static struct sdio_driver btmtksdio_driver = {
14859aebfd4aSSean Wang .name = "btmtksdio",
14869aebfd4aSSean Wang .probe = btmtksdio_probe,
14879aebfd4aSSean Wang .remove = btmtksdio_remove,
14889aebfd4aSSean Wang .id_table = btmtksdio_table,
14897f3c563cSSean Wang .drv = {
14907f3c563cSSean Wang .owner = THIS_MODULE,
14917f3c563cSSean Wang .pm = BTMTKSDIO_PM_OPS,
14927f3c563cSSean Wang }
14939aebfd4aSSean Wang };
14949aebfd4aSSean Wang
1495a6094a46SSean Wang module_sdio_driver(btmtksdio_driver);
14969aebfd4aSSean Wang
14977f3c563cSSean Wang module_param(enable_autosuspend, bool, 0644);
14987f3c563cSSean Wang MODULE_PARM_DESC(enable_autosuspend, "Enable autosuspend by default");
14997f3c563cSSean Wang
15009aebfd4aSSean Wang MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
15019aebfd4aSSean Wang MODULE_DESCRIPTION("MediaTek Bluetooth SDIO driver ver " VERSION);
15029aebfd4aSSean Wang MODULE_VERSION(VERSION);
15039aebfd4aSSean Wang MODULE_LICENSE("GPL");
1504