17237c4c9SSean Wang // SPDX-License-Identifier: GPL-2.0 27237c4c9SSean Wang // Copyright (c) 2018 MediaTek Inc. 37237c4c9SSean Wang 47237c4c9SSean Wang /* 57237c4c9SSean Wang * Bluetooth support for MediaTek serial devices 67237c4c9SSean Wang * 77237c4c9SSean Wang * Author: Sean Wang <sean.wang@mediatek.com> 87237c4c9SSean Wang * 97237c4c9SSean Wang */ 107237c4c9SSean Wang 117237c4c9SSean Wang #include <asm/unaligned.h> 127237c4c9SSean Wang #include <linux/atomic.h> 137237c4c9SSean Wang #include <linux/clk.h> 147237c4c9SSean Wang #include <linux/firmware.h> 157237c4c9SSean Wang #include <linux/kernel.h> 167237c4c9SSean Wang #include <linux/module.h> 177237c4c9SSean Wang #include <linux/of.h> 187237c4c9SSean Wang #include <linux/pm_runtime.h> 197237c4c9SSean Wang #include <linux/serdev.h> 207237c4c9SSean Wang #include <linux/skbuff.h> 217237c4c9SSean Wang 227237c4c9SSean Wang #include <net/bluetooth/bluetooth.h> 237237c4c9SSean Wang #include <net/bluetooth/hci_core.h> 247237c4c9SSean Wang 257237c4c9SSean Wang #include "h4_recv.h" 267237c4c9SSean Wang 277237c4c9SSean Wang #define VERSION "0.1" 287237c4c9SSean Wang 297237c4c9SSean Wang #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin" 307237c4c9SSean Wang 317237c4c9SSean Wang #define MTK_STP_TLR_SIZE 2 327237c4c9SSean Wang 337237c4c9SSean Wang #define BTMTKUART_TX_STATE_ACTIVE 1 347237c4c9SSean Wang #define BTMTKUART_TX_STATE_WAKEUP 2 357237c4c9SSean Wang #define BTMTKUART_TX_WAIT_VND_EVT 3 367237c4c9SSean Wang 377237c4c9SSean Wang enum { 387237c4c9SSean Wang MTK_WMT_PATCH_DWNLD = 0x1, 397237c4c9SSean Wang MTK_WMT_FUNC_CTRL = 0x6, 407237c4c9SSean Wang MTK_WMT_RST = 0x7 417237c4c9SSean Wang }; 427237c4c9SSean Wang 437237c4c9SSean Wang struct mtk_stp_hdr { 447237c4c9SSean Wang u8 prefix; 457237c4c9SSean Wang __be16 dlen; 467237c4c9SSean Wang u8 cs; 477237c4c9SSean Wang } __packed; 487237c4c9SSean Wang 497237c4c9SSean Wang struct mtk_wmt_hdr { 507237c4c9SSean Wang u8 dir; 517237c4c9SSean Wang u8 op; 527237c4c9SSean Wang __le16 dlen; 537237c4c9SSean Wang u8 flag; 547237c4c9SSean Wang } __packed; 557237c4c9SSean Wang 567237c4c9SSean Wang struct mtk_hci_wmt_cmd { 577237c4c9SSean Wang struct mtk_wmt_hdr hdr; 587237c4c9SSean Wang u8 data[256]; 597237c4c9SSean Wang } __packed; 607237c4c9SSean Wang 617237c4c9SSean Wang struct btmtkuart_dev { 627237c4c9SSean Wang struct hci_dev *hdev; 637237c4c9SSean Wang struct serdev_device *serdev; 647237c4c9SSean Wang struct clk *clk; 657237c4c9SSean Wang 667237c4c9SSean Wang struct work_struct tx_work; 677237c4c9SSean Wang unsigned long tx_state; 687237c4c9SSean Wang struct sk_buff_head txq; 697237c4c9SSean Wang 707237c4c9SSean Wang struct sk_buff *rx_skb; 717237c4c9SSean Wang 727237c4c9SSean Wang u8 stp_pad[6]; 737237c4c9SSean Wang u8 stp_cursor; 747237c4c9SSean Wang u16 stp_dlen; 757237c4c9SSean Wang }; 767237c4c9SSean Wang 777237c4c9SSean Wang static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, 787237c4c9SSean Wang const void *param) 797237c4c9SSean Wang { 807237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 817237c4c9SSean Wang struct mtk_hci_wmt_cmd wc; 827237c4c9SSean Wang struct mtk_wmt_hdr *hdr; 837237c4c9SSean Wang u32 hlen; 847237c4c9SSean Wang int err; 857237c4c9SSean Wang 867237c4c9SSean Wang hlen = sizeof(*hdr) + plen; 877237c4c9SSean Wang if (hlen > 255) 887237c4c9SSean Wang return -EINVAL; 897237c4c9SSean Wang 907237c4c9SSean Wang hdr = (struct mtk_wmt_hdr *)&wc; 917237c4c9SSean Wang hdr->dir = 1; 927237c4c9SSean Wang hdr->op = op; 937237c4c9SSean Wang hdr->dlen = cpu_to_le16(plen + 1); 947237c4c9SSean Wang hdr->flag = flag; 957237c4c9SSean Wang memcpy(wc.data, param, plen); 967237c4c9SSean Wang 977237c4c9SSean Wang set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); 987237c4c9SSean Wang 997237c4c9SSean Wang err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); 1007237c4c9SSean Wang if (err < 0) { 1017237c4c9SSean Wang clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); 1027237c4c9SSean Wang return err; 1037237c4c9SSean Wang } 1047237c4c9SSean Wang 1057237c4c9SSean Wang /* The vendor specific WMT commands are all answered by a vendor 1067237c4c9SSean Wang * specific event and will not have the Command Status or Command 1077237c4c9SSean Wang * Complete as with usual HCI command flow control. 1087237c4c9SSean Wang * 1097237c4c9SSean Wang * After sending the command, wait for BTMTKUART_TX_WAIT_VND_EVT 1107237c4c9SSean Wang * state to be cleared. The driver speicfic event receive routine 1117237c4c9SSean Wang * will clear that state and with that indicate completion of the 1127237c4c9SSean Wang * WMT command. 1137237c4c9SSean Wang */ 1147237c4c9SSean Wang err = wait_on_bit_timeout(&bdev->tx_state, BTMTKUART_TX_WAIT_VND_EVT, 1157237c4c9SSean Wang TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); 1167237c4c9SSean Wang if (err == -EINTR) { 1177237c4c9SSean Wang bt_dev_err(hdev, "Execution of wmt command interrupted"); 1187237c4c9SSean Wang return err; 1197237c4c9SSean Wang } 1207237c4c9SSean Wang 1217237c4c9SSean Wang if (err) { 1227237c4c9SSean Wang bt_dev_err(hdev, "Execution of wmt command timed out"); 1237237c4c9SSean Wang return -ETIMEDOUT; 1247237c4c9SSean Wang } 1257237c4c9SSean Wang 1267237c4c9SSean Wang return 0; 1277237c4c9SSean Wang } 1287237c4c9SSean Wang 1297237c4c9SSean Wang static int mtk_setup_fw(struct hci_dev *hdev) 1307237c4c9SSean Wang { 1317237c4c9SSean Wang const struct firmware *fw; 1327237c4c9SSean Wang const u8 *fw_ptr; 1337237c4c9SSean Wang size_t fw_size; 1347237c4c9SSean Wang int err, dlen; 1357237c4c9SSean Wang u8 flag; 1367237c4c9SSean Wang 1377237c4c9SSean Wang err = request_firmware(&fw, FIRMWARE_MT7622, &hdev->dev); 1387237c4c9SSean Wang if (err < 0) { 1397237c4c9SSean Wang bt_dev_err(hdev, "Failed to load firmware file (%d)", err); 1407237c4c9SSean Wang return err; 1417237c4c9SSean Wang } 1427237c4c9SSean Wang 1437237c4c9SSean Wang fw_ptr = fw->data; 1447237c4c9SSean Wang fw_size = fw->size; 1457237c4c9SSean Wang 1467237c4c9SSean Wang /* The size of patch header is 30 bytes, should be skip */ 147addb3ffbSGustavo A. R. Silva if (fw_size < 30) { 148addb3ffbSGustavo A. R. Silva err = -EINVAL; 149addb3ffbSGustavo A. R. Silva goto free_fw; 150addb3ffbSGustavo A. R. Silva } 1517237c4c9SSean Wang 1527237c4c9SSean Wang fw_size -= 30; 1537237c4c9SSean Wang fw_ptr += 30; 1547237c4c9SSean Wang flag = 1; 1557237c4c9SSean Wang 1567237c4c9SSean Wang while (fw_size > 0) { 1577237c4c9SSean Wang dlen = min_t(int, 250, fw_size); 1587237c4c9SSean Wang 1597237c4c9SSean Wang /* Tell device the position in sequence */ 1607237c4c9SSean Wang if (fw_size - dlen <= 0) 1617237c4c9SSean Wang flag = 3; 1627237c4c9SSean Wang else if (fw_size < fw->size - 30) 1637237c4c9SSean Wang flag = 2; 1647237c4c9SSean Wang 1657237c4c9SSean Wang err = mtk_hci_wmt_sync(hdev, MTK_WMT_PATCH_DWNLD, flag, dlen, 1667237c4c9SSean Wang fw_ptr); 1677237c4c9SSean Wang if (err < 0) { 1687237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", 1697237c4c9SSean Wang err); 1707237c4c9SSean Wang break; 1717237c4c9SSean Wang } 1727237c4c9SSean Wang 1737237c4c9SSean Wang fw_size -= dlen; 1747237c4c9SSean Wang fw_ptr += dlen; 1757237c4c9SSean Wang } 1767237c4c9SSean Wang 177addb3ffbSGustavo A. R. Silva free_fw: 1787237c4c9SSean Wang release_firmware(fw); 1797237c4c9SSean Wang return err; 1807237c4c9SSean Wang } 1817237c4c9SSean Wang 1827237c4c9SSean Wang static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb) 1837237c4c9SSean Wang { 1847237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 1857237c4c9SSean Wang struct hci_event_hdr *hdr = (void *)skb->data; 1867237c4c9SSean Wang int err; 1877237c4c9SSean Wang 1887237c4c9SSean Wang /* Fix up the vendor event id with 0xff for vendor specific instead 1897237c4c9SSean Wang * of 0xe4 so that event send via monitoring socket can be parsed 1907237c4c9SSean Wang * properly. 1917237c4c9SSean Wang */ 1927237c4c9SSean Wang if (hdr->evt == 0xe4) 1937237c4c9SSean Wang hdr->evt = HCI_EV_VENDOR; 1947237c4c9SSean Wang 1957237c4c9SSean Wang err = hci_recv_frame(hdev, skb); 1967237c4c9SSean Wang 1977237c4c9SSean Wang if (hdr->evt == HCI_EV_VENDOR) { 1987237c4c9SSean Wang if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, 1997237c4c9SSean Wang &bdev->tx_state)) { 2007237c4c9SSean Wang /* Barrier to sync with other CPUs */ 2017237c4c9SSean Wang smp_mb__after_atomic(); 2027237c4c9SSean Wang wake_up_bit(&bdev->tx_state, BTMTKUART_TX_WAIT_VND_EVT); 2037237c4c9SSean Wang } 2047237c4c9SSean Wang } 2057237c4c9SSean Wang 2067237c4c9SSean Wang return err; 2077237c4c9SSean Wang } 2087237c4c9SSean Wang 2097237c4c9SSean Wang static const struct h4_recv_pkt mtk_recv_pkts[] = { 2107237c4c9SSean Wang { H4_RECV_ACL, .recv = hci_recv_frame }, 2117237c4c9SSean Wang { H4_RECV_SCO, .recv = hci_recv_frame }, 2127237c4c9SSean Wang { H4_RECV_EVENT, .recv = btmtkuart_recv_event }, 2137237c4c9SSean Wang }; 2147237c4c9SSean Wang 2157237c4c9SSean Wang static void btmtkuart_tx_work(struct work_struct *work) 2167237c4c9SSean Wang { 2177237c4c9SSean Wang struct btmtkuart_dev *bdev = container_of(work, struct btmtkuart_dev, 2187237c4c9SSean Wang tx_work); 2197237c4c9SSean Wang struct serdev_device *serdev = bdev->serdev; 2207237c4c9SSean Wang struct hci_dev *hdev = bdev->hdev; 2217237c4c9SSean Wang 2227237c4c9SSean Wang while (1) { 2237237c4c9SSean Wang clear_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state); 2247237c4c9SSean Wang 2257237c4c9SSean Wang while (1) { 2267237c4c9SSean Wang struct sk_buff *skb = skb_dequeue(&bdev->txq); 2277237c4c9SSean Wang int len; 2287237c4c9SSean Wang 2297237c4c9SSean Wang if (!skb) 2307237c4c9SSean Wang break; 2317237c4c9SSean Wang 2327237c4c9SSean Wang len = serdev_device_write_buf(serdev, skb->data, 2337237c4c9SSean Wang skb->len); 2347237c4c9SSean Wang hdev->stat.byte_tx += len; 2357237c4c9SSean Wang 2367237c4c9SSean Wang skb_pull(skb, len); 2377237c4c9SSean Wang if (skb->len > 0) { 2387237c4c9SSean Wang skb_queue_head(&bdev->txq, skb); 2397237c4c9SSean Wang break; 2407237c4c9SSean Wang } 2417237c4c9SSean Wang 2427237c4c9SSean Wang switch (hci_skb_pkt_type(skb)) { 2437237c4c9SSean Wang case HCI_COMMAND_PKT: 2447237c4c9SSean Wang hdev->stat.cmd_tx++; 2457237c4c9SSean Wang break; 2467237c4c9SSean Wang case HCI_ACLDATA_PKT: 2477237c4c9SSean Wang hdev->stat.acl_tx++; 2487237c4c9SSean Wang break; 2497237c4c9SSean Wang case HCI_SCODATA_PKT: 2507237c4c9SSean Wang hdev->stat.sco_tx++; 2517237c4c9SSean Wang break; 2527237c4c9SSean Wang } 2537237c4c9SSean Wang 2547237c4c9SSean Wang kfree_skb(skb); 2557237c4c9SSean Wang } 2567237c4c9SSean Wang 2577237c4c9SSean Wang if (!test_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state)) 2587237c4c9SSean Wang break; 2597237c4c9SSean Wang } 2607237c4c9SSean Wang 2617237c4c9SSean Wang clear_bit(BTMTKUART_TX_STATE_ACTIVE, &bdev->tx_state); 2627237c4c9SSean Wang } 2637237c4c9SSean Wang 2647237c4c9SSean Wang static void btmtkuart_tx_wakeup(struct btmtkuart_dev *bdev) 2657237c4c9SSean Wang { 2667237c4c9SSean Wang if (test_and_set_bit(BTMTKUART_TX_STATE_ACTIVE, &bdev->tx_state)) 2677237c4c9SSean Wang set_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state); 2687237c4c9SSean Wang 2697237c4c9SSean Wang schedule_work(&bdev->tx_work); 2707237c4c9SSean Wang } 2717237c4c9SSean Wang 2727237c4c9SSean Wang static const unsigned char * 2737237c4c9SSean Wang mtk_stp_split(struct btmtkuart_dev *bdev, const unsigned char *data, int count, 2747237c4c9SSean Wang int *sz_h4) 2757237c4c9SSean Wang { 2767237c4c9SSean Wang struct mtk_stp_hdr *shdr; 2777237c4c9SSean Wang 2787237c4c9SSean Wang /* The cursor is reset when all the data of STP is consumed out */ 2797237c4c9SSean Wang if (!bdev->stp_dlen && bdev->stp_cursor >= 6) 2807237c4c9SSean Wang bdev->stp_cursor = 0; 2817237c4c9SSean Wang 2827237c4c9SSean Wang /* Filling pad until all STP info is obtained */ 2837237c4c9SSean Wang while (bdev->stp_cursor < 6 && count > 0) { 2847237c4c9SSean Wang bdev->stp_pad[bdev->stp_cursor] = *data; 2857237c4c9SSean Wang bdev->stp_cursor++; 2867237c4c9SSean Wang data++; 2877237c4c9SSean Wang count--; 2887237c4c9SSean Wang } 2897237c4c9SSean Wang 2907237c4c9SSean Wang /* Retrieve STP info and have a sanity check */ 2917237c4c9SSean Wang if (!bdev->stp_dlen && bdev->stp_cursor >= 6) { 2927237c4c9SSean Wang shdr = (struct mtk_stp_hdr *)&bdev->stp_pad[2]; 2937237c4c9SSean Wang bdev->stp_dlen = be16_to_cpu(shdr->dlen) & 0x0fff; 2947237c4c9SSean Wang 2957237c4c9SSean Wang /* Resync STP when unexpected data is being read */ 2967237c4c9SSean Wang if (shdr->prefix != 0x80 || bdev->stp_dlen > 2048) { 2977237c4c9SSean Wang bt_dev_err(bdev->hdev, "stp format unexpect (%d, %d)", 2987237c4c9SSean Wang shdr->prefix, bdev->stp_dlen); 2997237c4c9SSean Wang bdev->stp_cursor = 2; 3007237c4c9SSean Wang bdev->stp_dlen = 0; 3017237c4c9SSean Wang } 3027237c4c9SSean Wang } 3037237c4c9SSean Wang 3047237c4c9SSean Wang /* Directly quit when there's no data found for H4 can process */ 3057237c4c9SSean Wang if (count <= 0) 3067237c4c9SSean Wang return NULL; 3077237c4c9SSean Wang 3087237c4c9SSean Wang /* Tranlate to how much the size of data H4 can handle so far */ 3097237c4c9SSean Wang *sz_h4 = min_t(int, count, bdev->stp_dlen); 3107237c4c9SSean Wang 3117237c4c9SSean Wang /* Update the remaining size of STP packet */ 3127237c4c9SSean Wang bdev->stp_dlen -= *sz_h4; 3137237c4c9SSean Wang 3147237c4c9SSean Wang /* Data points to STP payload which can be handled by H4 */ 3157237c4c9SSean Wang return data; 3167237c4c9SSean Wang } 3177237c4c9SSean Wang 3187237c4c9SSean Wang static int btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count) 3197237c4c9SSean Wang { 3207237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 3217237c4c9SSean Wang const unsigned char *p_left = data, *p_h4; 3227237c4c9SSean Wang int sz_left = count, sz_h4, adv; 3237237c4c9SSean Wang int err; 3247237c4c9SSean Wang 3257237c4c9SSean Wang while (sz_left > 0) { 3267237c4c9SSean Wang /* The serial data received from MT7622 BT controller is 3277237c4c9SSean Wang * at all time padded around with the STP header and tailer. 3287237c4c9SSean Wang * 3297237c4c9SSean Wang * A full STP packet is looking like 3307237c4c9SSean Wang * ----------------------------------- 3317237c4c9SSean Wang * | STP header | H:4 | STP tailer | 3327237c4c9SSean Wang * ----------------------------------- 3337237c4c9SSean Wang * but it doesn't guarantee to contain a full H:4 packet which 3347237c4c9SSean Wang * means that it's possible for multiple STP packets forms a 3357237c4c9SSean Wang * full H:4 packet that means extra STP header + length doesn't 3367237c4c9SSean Wang * indicate a full H:4 frame, things can fragment. Whose length 3377237c4c9SSean Wang * recorded in STP header just shows up the most length the 3387237c4c9SSean Wang * H:4 engine can handle currently. 3397237c4c9SSean Wang */ 3407237c4c9SSean Wang 3417237c4c9SSean Wang p_h4 = mtk_stp_split(bdev, p_left, sz_left, &sz_h4); 3427237c4c9SSean Wang if (!p_h4) 3437237c4c9SSean Wang break; 3447237c4c9SSean Wang 3457237c4c9SSean Wang adv = p_h4 - p_left; 3467237c4c9SSean Wang sz_left -= adv; 3477237c4c9SSean Wang p_left += adv; 3487237c4c9SSean Wang 3497237c4c9SSean Wang bdev->rx_skb = h4_recv_buf(bdev->hdev, bdev->rx_skb, p_h4, 3507237c4c9SSean Wang sz_h4, mtk_recv_pkts, 351330ad75fSDan Carpenter ARRAY_SIZE(mtk_recv_pkts)); 3527237c4c9SSean Wang if (IS_ERR(bdev->rx_skb)) { 3537237c4c9SSean Wang err = PTR_ERR(bdev->rx_skb); 3547237c4c9SSean Wang bt_dev_err(bdev->hdev, 3557237c4c9SSean Wang "Frame reassembly failed (%d)", err); 3567237c4c9SSean Wang bdev->rx_skb = NULL; 3577237c4c9SSean Wang return err; 3587237c4c9SSean Wang } 3597237c4c9SSean Wang 3607237c4c9SSean Wang sz_left -= sz_h4; 3617237c4c9SSean Wang p_left += sz_h4; 3627237c4c9SSean Wang } 3637237c4c9SSean Wang 3647237c4c9SSean Wang return 0; 3657237c4c9SSean Wang } 3667237c4c9SSean Wang 3677237c4c9SSean Wang static int btmtkuart_receive_buf(struct serdev_device *serdev, const u8 *data, 3687237c4c9SSean Wang size_t count) 3697237c4c9SSean Wang { 3707237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); 3717237c4c9SSean Wang int err; 3727237c4c9SSean Wang 3737237c4c9SSean Wang err = btmtkuart_recv(bdev->hdev, data, count); 3747237c4c9SSean Wang if (err < 0) 3757237c4c9SSean Wang return err; 3767237c4c9SSean Wang 3777237c4c9SSean Wang bdev->hdev->stat.byte_rx += count; 3787237c4c9SSean Wang 3797237c4c9SSean Wang return count; 3807237c4c9SSean Wang } 3817237c4c9SSean Wang 3827237c4c9SSean Wang static void btmtkuart_write_wakeup(struct serdev_device *serdev) 3837237c4c9SSean Wang { 3847237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); 3857237c4c9SSean Wang 3867237c4c9SSean Wang btmtkuart_tx_wakeup(bdev); 3877237c4c9SSean Wang } 3887237c4c9SSean Wang 3897237c4c9SSean Wang static const struct serdev_device_ops btmtkuart_client_ops = { 3907237c4c9SSean Wang .receive_buf = btmtkuart_receive_buf, 3917237c4c9SSean Wang .write_wakeup = btmtkuart_write_wakeup, 3927237c4c9SSean Wang }; 3937237c4c9SSean Wang 3947237c4c9SSean Wang static int btmtkuart_open(struct hci_dev *hdev) 3957237c4c9SSean Wang { 3967237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 3977237c4c9SSean Wang struct device *dev; 3987237c4c9SSean Wang int err; 3997237c4c9SSean Wang 4007237c4c9SSean Wang err = serdev_device_open(bdev->serdev); 4017237c4c9SSean Wang if (err) { 4027237c4c9SSean Wang bt_dev_err(hdev, "Unable to open UART device %s", 4037237c4c9SSean Wang dev_name(&bdev->serdev->dev)); 4047237c4c9SSean Wang goto err_open; 4057237c4c9SSean Wang } 4067237c4c9SSean Wang 4077237c4c9SSean Wang bdev->stp_cursor = 2; 4087237c4c9SSean Wang bdev->stp_dlen = 0; 4097237c4c9SSean Wang 4107237c4c9SSean Wang dev = &bdev->serdev->dev; 4117237c4c9SSean Wang 4127237c4c9SSean Wang /* Enable the power domain and clock the device requires */ 4137237c4c9SSean Wang pm_runtime_enable(dev); 4147237c4c9SSean Wang err = pm_runtime_get_sync(dev); 4157237c4c9SSean Wang if (err < 0) { 4167237c4c9SSean Wang pm_runtime_put_noidle(dev); 4177237c4c9SSean Wang goto err_disable_rpm; 4187237c4c9SSean Wang } 4197237c4c9SSean Wang 4207237c4c9SSean Wang err = clk_prepare_enable(bdev->clk); 4217237c4c9SSean Wang if (err < 0) 4227237c4c9SSean Wang goto err_put_rpm; 4237237c4c9SSean Wang 4247237c4c9SSean Wang return 0; 4257237c4c9SSean Wang 4267237c4c9SSean Wang err_put_rpm: 4277237c4c9SSean Wang pm_runtime_put_sync(dev); 4287237c4c9SSean Wang err_disable_rpm: 4297237c4c9SSean Wang pm_runtime_disable(dev); 4307237c4c9SSean Wang err_open: 4317237c4c9SSean Wang return err; 4327237c4c9SSean Wang } 4337237c4c9SSean Wang 4347237c4c9SSean Wang static int btmtkuart_close(struct hci_dev *hdev) 4357237c4c9SSean Wang { 4367237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 4377237c4c9SSean Wang struct device *dev = &bdev->serdev->dev; 4387237c4c9SSean Wang 4397237c4c9SSean Wang /* Shutdown the clock and power domain the device requires */ 4407237c4c9SSean Wang clk_disable_unprepare(bdev->clk); 4417237c4c9SSean Wang pm_runtime_put_sync(dev); 4427237c4c9SSean Wang pm_runtime_disable(dev); 4437237c4c9SSean Wang 4447237c4c9SSean Wang serdev_device_close(bdev->serdev); 4457237c4c9SSean Wang 4467237c4c9SSean Wang return 0; 4477237c4c9SSean Wang } 4487237c4c9SSean Wang 4497237c4c9SSean Wang static int btmtkuart_flush(struct hci_dev *hdev) 4507237c4c9SSean Wang { 4517237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 4527237c4c9SSean Wang 4537237c4c9SSean Wang /* Flush any pending characters */ 4547237c4c9SSean Wang serdev_device_write_flush(bdev->serdev); 4557237c4c9SSean Wang skb_queue_purge(&bdev->txq); 4567237c4c9SSean Wang 4577237c4c9SSean Wang cancel_work_sync(&bdev->tx_work); 4587237c4c9SSean Wang 4597237c4c9SSean Wang kfree_skb(bdev->rx_skb); 4607237c4c9SSean Wang bdev->rx_skb = NULL; 4617237c4c9SSean Wang 4627237c4c9SSean Wang bdev->stp_cursor = 2; 4637237c4c9SSean Wang bdev->stp_dlen = 0; 4647237c4c9SSean Wang 4657237c4c9SSean Wang return 0; 4667237c4c9SSean Wang } 4677237c4c9SSean Wang 4687237c4c9SSean Wang static int btmtkuart_setup(struct hci_dev *hdev) 4697237c4c9SSean Wang { 4707237c4c9SSean Wang u8 param = 0x1; 4717237c4c9SSean Wang int err = 0; 4727237c4c9SSean Wang 4737237c4c9SSean Wang /* Setup a firmware which the device definitely requires */ 4747237c4c9SSean Wang err = mtk_setup_fw(hdev); 4757237c4c9SSean Wang if (err < 0) 4767237c4c9SSean Wang return err; 4777237c4c9SSean Wang 4787237c4c9SSean Wang /* Activate function the firmware providing to */ 4797237c4c9SSean Wang err = mtk_hci_wmt_sync(hdev, MTK_WMT_RST, 0x4, 0, 0); 4807237c4c9SSean Wang if (err < 0) { 4817237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); 4827237c4c9SSean Wang return err; 4837237c4c9SSean Wang } 4847237c4c9SSean Wang 4857237c4c9SSean Wang /* Enable Bluetooth protocol */ 4867237c4c9SSean Wang err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), 4877237c4c9SSean Wang ¶m); 4887237c4c9SSean Wang if (err < 0) { 4897237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); 4907237c4c9SSean Wang return err; 4917237c4c9SSean Wang } 4927237c4c9SSean Wang 4937237c4c9SSean Wang return 0; 4947237c4c9SSean Wang } 4957237c4c9SSean Wang 4967237c4c9SSean Wang static int btmtkuart_shutdown(struct hci_dev *hdev) 4977237c4c9SSean Wang { 4987237c4c9SSean Wang u8 param = 0x0; 4997237c4c9SSean Wang int err; 5007237c4c9SSean Wang 5017237c4c9SSean Wang /* Disable the device */ 5027237c4c9SSean Wang err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), 5037237c4c9SSean Wang ¶m); 5047237c4c9SSean Wang if (err < 0) { 5057237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); 5067237c4c9SSean Wang return err; 5077237c4c9SSean Wang } 5087237c4c9SSean Wang 5097237c4c9SSean Wang return 0; 5107237c4c9SSean Wang } 5117237c4c9SSean Wang 5127237c4c9SSean Wang static int btmtkuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 5137237c4c9SSean Wang { 5147237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 5157237c4c9SSean Wang struct mtk_stp_hdr *shdr; 5167237c4c9SSean Wang int err, dlen, type = 0; 5177237c4c9SSean Wang 5187237c4c9SSean Wang /* Prepend skb with frame type */ 5197237c4c9SSean Wang memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); 5207237c4c9SSean Wang 5217237c4c9SSean Wang /* Make sure that there is enough rooms for STP header and trailer */ 5227237c4c9SSean Wang if (unlikely(skb_headroom(skb) < sizeof(*shdr)) || 5237237c4c9SSean Wang (skb_tailroom(skb) < MTK_STP_TLR_SIZE)) { 5247237c4c9SSean Wang err = pskb_expand_head(skb, sizeof(*shdr), MTK_STP_TLR_SIZE, 5257237c4c9SSean Wang GFP_ATOMIC); 5267237c4c9SSean Wang if (err < 0) 5277237c4c9SSean Wang return err; 5287237c4c9SSean Wang } 5297237c4c9SSean Wang 5307237c4c9SSean Wang /* Add the STP header */ 5317237c4c9SSean Wang dlen = skb->len; 5327237c4c9SSean Wang shdr = skb_push(skb, sizeof(*shdr)); 5337237c4c9SSean Wang shdr->prefix = 0x80; 5347237c4c9SSean Wang shdr->dlen = cpu_to_be16((dlen & 0x0fff) | (type << 12)); 5357237c4c9SSean Wang shdr->cs = 0; /* MT7622 doesn't care about checksum value */ 5367237c4c9SSean Wang 5377237c4c9SSean Wang /* Add the STP trailer */ 5387237c4c9SSean Wang skb_put_zero(skb, MTK_STP_TLR_SIZE); 5397237c4c9SSean Wang 5407237c4c9SSean Wang skb_queue_tail(&bdev->txq, skb); 5417237c4c9SSean Wang 5427237c4c9SSean Wang btmtkuart_tx_wakeup(bdev); 5437237c4c9SSean Wang return 0; 5447237c4c9SSean Wang } 5457237c4c9SSean Wang 5467237c4c9SSean Wang static int btmtkuart_probe(struct serdev_device *serdev) 5477237c4c9SSean Wang { 5487237c4c9SSean Wang struct btmtkuart_dev *bdev; 5497237c4c9SSean Wang struct hci_dev *hdev; 5507237c4c9SSean Wang 5517237c4c9SSean Wang bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL); 5527237c4c9SSean Wang if (!bdev) 5537237c4c9SSean Wang return -ENOMEM; 5547237c4c9SSean Wang 5557237c4c9SSean Wang bdev->clk = devm_clk_get(&serdev->dev, "ref"); 5567237c4c9SSean Wang if (IS_ERR(bdev->clk)) 5577237c4c9SSean Wang return PTR_ERR(bdev->clk); 5587237c4c9SSean Wang 5597237c4c9SSean Wang bdev->serdev = serdev; 5607237c4c9SSean Wang serdev_device_set_drvdata(serdev, bdev); 5617237c4c9SSean Wang 5627237c4c9SSean Wang serdev_device_set_client_ops(serdev, &btmtkuart_client_ops); 5637237c4c9SSean Wang 5647237c4c9SSean Wang INIT_WORK(&bdev->tx_work, btmtkuart_tx_work); 5657237c4c9SSean Wang skb_queue_head_init(&bdev->txq); 5667237c4c9SSean Wang 5677237c4c9SSean Wang /* Initialize and register HCI device */ 5687237c4c9SSean Wang hdev = hci_alloc_dev(); 5697237c4c9SSean Wang if (!hdev) { 5707237c4c9SSean Wang dev_err(&serdev->dev, "Can't allocate HCI device\n"); 5717237c4c9SSean Wang return -ENOMEM; 5727237c4c9SSean Wang } 5737237c4c9SSean Wang 5747237c4c9SSean Wang bdev->hdev = hdev; 5757237c4c9SSean Wang 5767237c4c9SSean Wang hdev->bus = HCI_UART; 5777237c4c9SSean Wang hci_set_drvdata(hdev, bdev); 5787237c4c9SSean Wang 5797237c4c9SSean Wang hdev->open = btmtkuart_open; 5807237c4c9SSean Wang hdev->close = btmtkuart_close; 5817237c4c9SSean Wang hdev->flush = btmtkuart_flush; 5827237c4c9SSean Wang hdev->setup = btmtkuart_setup; 5837237c4c9SSean Wang hdev->shutdown = btmtkuart_shutdown; 5847237c4c9SSean Wang hdev->send = btmtkuart_send_frame; 5857237c4c9SSean Wang SET_HCIDEV_DEV(hdev, &serdev->dev); 5867237c4c9SSean Wang 5877237c4c9SSean Wang hdev->manufacturer = 70; 5887237c4c9SSean Wang set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); 5897237c4c9SSean Wang 5907237c4c9SSean Wang if (hci_register_dev(hdev) < 0) { 5917237c4c9SSean Wang dev_err(&serdev->dev, "Can't register HCI device\n"); 5927237c4c9SSean Wang hci_free_dev(hdev); 5937237c4c9SSean Wang return -ENODEV; 5947237c4c9SSean Wang } 5957237c4c9SSean Wang 5967237c4c9SSean Wang return 0; 5977237c4c9SSean Wang } 5987237c4c9SSean Wang 5997237c4c9SSean Wang static void btmtkuart_remove(struct serdev_device *serdev) 6007237c4c9SSean Wang { 6017237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); 6027237c4c9SSean Wang struct hci_dev *hdev = bdev->hdev; 6037237c4c9SSean Wang 6047237c4c9SSean Wang hci_unregister_dev(hdev); 6057237c4c9SSean Wang hci_free_dev(hdev); 6067237c4c9SSean Wang } 6077237c4c9SSean Wang 6087237c4c9SSean Wang #ifdef CONFIG_OF 6097237c4c9SSean Wang static const struct of_device_id mtk_of_match_table[] = { 6107237c4c9SSean Wang { .compatible = "mediatek,mt7622-bluetooth"}, 6117237c4c9SSean Wang { } 6127237c4c9SSean Wang }; 6137237c4c9SSean Wang MODULE_DEVICE_TABLE(of, mtk_of_match_table); 6147237c4c9SSean Wang #endif 6157237c4c9SSean Wang 6167237c4c9SSean Wang static struct serdev_device_driver btmtkuart_driver = { 6177237c4c9SSean Wang .probe = btmtkuart_probe, 6187237c4c9SSean Wang .remove = btmtkuart_remove, 6197237c4c9SSean Wang .driver = { 6207237c4c9SSean Wang .name = "btmtkuart", 6217237c4c9SSean Wang .of_match_table = of_match_ptr(mtk_of_match_table), 6227237c4c9SSean Wang }, 6237237c4c9SSean Wang }; 6247237c4c9SSean Wang 6257237c4c9SSean Wang module_serdev_device_driver(btmtkuart_driver); 6267237c4c9SSean Wang 6277237c4c9SSean Wang MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); 6287237c4c9SSean Wang MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION); 6297237c4c9SSean Wang MODULE_VERSION(VERSION); 6307237c4c9SSean Wang MODULE_LICENSE("GPL"); 6317237c4c9SSean Wang MODULE_FIRMWARE(FIRMWARE_MT7622); 632