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>
1522eaf6c9SSean Wang #include <linux/gpio/consumer.h>
16e0b67035SSean Wang #include <linux/iopoll.h>
177237c4c9SSean Wang #include <linux/kernel.h>
187237c4c9SSean Wang #include <linux/module.h>
197237c4c9SSean Wang #include <linux/of.h>
2022eaf6c9SSean Wang #include <linux/pinctrl/consumer.h>
217237c4c9SSean Wang #include <linux/pm_runtime.h>
2222eaf6c9SSean Wang #include <linux/regulator/consumer.h>
237237c4c9SSean Wang #include <linux/serdev.h>
247237c4c9SSean Wang #include <linux/skbuff.h>
257237c4c9SSean Wang
267237c4c9SSean Wang #include <net/bluetooth/bluetooth.h>
277237c4c9SSean Wang #include <net/bluetooth/hci_core.h>
287237c4c9SSean Wang
297237c4c9SSean Wang #include "h4_recv.h"
30f5c3f989SSean Wang #include "btmtk.h"
317237c4c9SSean Wang
3222eaf6c9SSean Wang #define VERSION "0.2"
337237c4c9SSean Wang
347237c4c9SSean Wang #define MTK_STP_TLR_SIZE 2
357237c4c9SSean Wang
367237c4c9SSean Wang #define BTMTKUART_TX_STATE_ACTIVE 1
377237c4c9SSean Wang #define BTMTKUART_TX_STATE_WAKEUP 2
387237c4c9SSean Wang #define BTMTKUART_TX_WAIT_VND_EVT 3
3922eaf6c9SSean Wang #define BTMTKUART_REQUIRED_WAKEUP 4
4022eaf6c9SSean Wang
4122eaf6c9SSean Wang #define BTMTKUART_FLAG_STANDALONE_HW BIT(0)
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
4922eaf6c9SSean Wang struct btmtkuart_data {
5022eaf6c9SSean Wang unsigned int flags;
5122eaf6c9SSean Wang const char *fwname;
5222eaf6c9SSean Wang };
5322eaf6c9SSean Wang
547237c4c9SSean Wang struct btmtkuart_dev {
557237c4c9SSean Wang struct hci_dev *hdev;
567237c4c9SSean Wang struct serdev_device *serdev;
577237c4c9SSean Wang
5805582561SSean Wang struct clk *clk;
5905582561SSean Wang struct clk *osc;
6022eaf6c9SSean Wang struct regulator *vcc;
6122eaf6c9SSean Wang struct gpio_desc *reset;
62a3cb6d60SSean Wang struct gpio_desc *boot;
6322eaf6c9SSean Wang struct pinctrl *pinctrl;
6422eaf6c9SSean Wang struct pinctrl_state *pins_runtime;
6522eaf6c9SSean Wang struct pinctrl_state *pins_boot;
6622eaf6c9SSean Wang speed_t desired_speed;
6722eaf6c9SSean Wang speed_t curr_speed;
6822eaf6c9SSean Wang
697237c4c9SSean Wang struct work_struct tx_work;
707237c4c9SSean Wang unsigned long tx_state;
717237c4c9SSean Wang struct sk_buff_head txq;
727237c4c9SSean Wang
737237c4c9SSean Wang struct sk_buff *rx_skb;
74e0b67035SSean Wang struct sk_buff *evt_skb;
757237c4c9SSean Wang
767237c4c9SSean Wang u8 stp_pad[6];
777237c4c9SSean Wang u8 stp_cursor;
787237c4c9SSean Wang u16 stp_dlen;
7922eaf6c9SSean Wang
8022eaf6c9SSean Wang const struct btmtkuart_data *data;
817237c4c9SSean Wang };
827237c4c9SSean Wang
8322eaf6c9SSean Wang #define btmtkuart_is_standalone(bdev) \
8422eaf6c9SSean Wang ((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW)
8522eaf6c9SSean Wang #define btmtkuart_is_builtin_soc(bdev) \
8622eaf6c9SSean Wang !((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW)
8722eaf6c9SSean Wang
mtk_hci_wmt_sync(struct hci_dev * hdev,struct btmtk_hci_wmt_params * wmt_params)8888e5f366SSean Wang static int mtk_hci_wmt_sync(struct hci_dev *hdev,
8988e5f366SSean Wang struct btmtk_hci_wmt_params *wmt_params)
907237c4c9SSean Wang {
917237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
92e0b67035SSean Wang struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
93e0b67035SSean Wang u32 hlen, status = BTMTK_WMT_INVALID;
94e0b67035SSean Wang struct btmtk_hci_wmt_evt *wmt_evt;
95f5c3f989SSean Wang struct btmtk_hci_wmt_cmd *wc;
96f5c3f989SSean Wang struct btmtk_wmt_hdr *hdr;
977237c4c9SSean Wang int err;
987237c4c9SSean Wang
99f5c3f989SSean Wang /* Send the WMT command and wait until the WMT event returns */
10088e5f366SSean Wang hlen = sizeof(*hdr) + wmt_params->dlen;
1013e5f2d90SDinghao Liu if (hlen > 255) {
1023e5f2d90SDinghao Liu err = -EINVAL;
1033e5f2d90SDinghao Liu goto err_free_skb;
1043e5f2d90SDinghao Liu }
1057237c4c9SSean Wang
106f5c3f989SSean Wang wc = kzalloc(hlen, GFP_KERNEL);
107a76d269aSDan Carpenter if (!wc) {
108a76d269aSDan Carpenter err = -ENOMEM;
109a76d269aSDan Carpenter goto err_free_skb;
110a76d269aSDan Carpenter }
111f5c3f989SSean Wang
112f5c3f989SSean Wang hdr = &wc->hdr;
1137237c4c9SSean Wang hdr->dir = 1;
11488e5f366SSean Wang hdr->op = wmt_params->op;
11588e5f366SSean Wang hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
11688e5f366SSean Wang hdr->flag = wmt_params->flag;
117f5c3f989SSean Wang memcpy(wc->data, wmt_params->data, wmt_params->dlen);
1187237c4c9SSean Wang
1197237c4c9SSean Wang set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
1207237c4c9SSean Wang
121f5c3f989SSean Wang err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
1227237c4c9SSean Wang if (err < 0) {
1237237c4c9SSean Wang clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
124f5c3f989SSean Wang goto err_free_wc;
1257237c4c9SSean Wang }
1267237c4c9SSean Wang
1277237c4c9SSean Wang /* The vendor specific WMT commands are all answered by a vendor
1287237c4c9SSean Wang * specific event and will not have the Command Status or Command
1297237c4c9SSean Wang * Complete as with usual HCI command flow control.
1307237c4c9SSean Wang *
1317237c4c9SSean Wang * After sending the command, wait for BTMTKUART_TX_WAIT_VND_EVT
132adf5d730SSean Wang * state to be cleared. The driver specific event receive routine
1337237c4c9SSean Wang * will clear that state and with that indicate completion of the
1347237c4c9SSean Wang * WMT command.
1357237c4c9SSean Wang */
1367237c4c9SSean Wang err = wait_on_bit_timeout(&bdev->tx_state, BTMTKUART_TX_WAIT_VND_EVT,
1377237c4c9SSean Wang TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
1387237c4c9SSean Wang if (err == -EINTR) {
1397237c4c9SSean Wang bt_dev_err(hdev, "Execution of wmt command interrupted");
14077f328dbSSean Wang clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
141f5c3f989SSean Wang goto err_free_wc;
1427237c4c9SSean Wang }
1437237c4c9SSean Wang
1447237c4c9SSean Wang if (err) {
1457237c4c9SSean Wang bt_dev_err(hdev, "Execution of wmt command timed out");
14677f328dbSSean Wang clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
1473e5f2d90SDinghao Liu err = -ETIMEDOUT;
148f5c3f989SSean Wang goto err_free_wc;
1497237c4c9SSean Wang }
1507237c4c9SSean Wang
151e0b67035SSean Wang /* Parse and handle the return WMT event */
152e0b67035SSean Wang wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
153e0b67035SSean Wang if (wmt_evt->whdr.op != hdr->op) {
154e0b67035SSean Wang bt_dev_err(hdev, "Wrong op received %d expected %d",
155e0b67035SSean Wang wmt_evt->whdr.op, hdr->op);
156e0b67035SSean Wang err = -EIO;
157a76d269aSDan Carpenter goto err_free_wc;
158e0b67035SSean Wang }
159e0b67035SSean Wang
160e0b67035SSean Wang switch (wmt_evt->whdr.op) {
161f5c3f989SSean Wang case BTMTK_WMT_SEMAPHORE:
162e0b67035SSean Wang if (wmt_evt->whdr.flag == 2)
163e0b67035SSean Wang status = BTMTK_WMT_PATCH_UNDONE;
164e0b67035SSean Wang else
165e0b67035SSean Wang status = BTMTK_WMT_PATCH_DONE;
166e0b67035SSean Wang break;
167f5c3f989SSean Wang case BTMTK_WMT_FUNC_CTRL:
168e0b67035SSean Wang wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
169e0b67035SSean Wang if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
170e0b67035SSean Wang status = BTMTK_WMT_ON_DONE;
171e0b67035SSean Wang else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
172e0b67035SSean Wang status = BTMTK_WMT_ON_PROGRESS;
173e0b67035SSean Wang else
174e0b67035SSean Wang status = BTMTK_WMT_ON_UNDONE;
175e0b67035SSean Wang break;
176e0b67035SSean Wang }
177e0b67035SSean Wang
178e0b67035SSean Wang if (wmt_params->status)
179e0b67035SSean Wang *wmt_params->status = status;
180e0b67035SSean Wang
181a76d269aSDan Carpenter err_free_wc:
182a76d269aSDan Carpenter kfree(wc);
183e0b67035SSean Wang err_free_skb:
184e0b67035SSean Wang kfree_skb(bdev->evt_skb);
185e0b67035SSean Wang bdev->evt_skb = NULL;
186e0b67035SSean Wang
187e0b67035SSean Wang return err;
1887237c4c9SSean Wang }
1897237c4c9SSean Wang
btmtkuart_recv_event(struct hci_dev * hdev,struct sk_buff * skb)1907237c4c9SSean Wang static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
1917237c4c9SSean Wang {
1927237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
1937237c4c9SSean Wang struct hci_event_hdr *hdr = (void *)skb->data;
1947237c4c9SSean Wang int err;
1957237c4c9SSean Wang
196e0b67035SSean Wang /* When someone waits for the WMT event, the skb is being cloned
197e0b67035SSean Wang * and being processed the events from there then.
198e0b67035SSean Wang */
199e0b67035SSean Wang if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) {
200e0b67035SSean Wang bdev->evt_skb = skb_clone(skb, GFP_KERNEL);
201e0b67035SSean Wang if (!bdev->evt_skb) {
202e0b67035SSean Wang err = -ENOMEM;
203e0b67035SSean Wang goto err_out;
204e0b67035SSean Wang }
205e0b67035SSean Wang }
206e0b67035SSean Wang
2077237c4c9SSean Wang err = hci_recv_frame(hdev, skb);
208e0b67035SSean Wang if (err < 0)
209e0b67035SSean Wang goto err_free_skb;
2107237c4c9SSean Wang
2116ac034a7SSean Wang if (hdr->evt == HCI_EV_WMT) {
2127237c4c9SSean Wang if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT,
2137237c4c9SSean Wang &bdev->tx_state)) {
2147237c4c9SSean Wang /* Barrier to sync with other CPUs */
2157237c4c9SSean Wang smp_mb__after_atomic();
2167237c4c9SSean Wang wake_up_bit(&bdev->tx_state, BTMTKUART_TX_WAIT_VND_EVT);
2177237c4c9SSean Wang }
2187237c4c9SSean Wang }
2197237c4c9SSean Wang
220e0b67035SSean Wang return 0;
221e0b67035SSean Wang
222e0b67035SSean Wang err_free_skb:
223e0b67035SSean Wang kfree_skb(bdev->evt_skb);
224e0b67035SSean Wang bdev->evt_skb = NULL;
225e0b67035SSean Wang
226e0b67035SSean Wang err_out:
2277237c4c9SSean Wang return err;
2287237c4c9SSean Wang }
2297237c4c9SSean Wang
2307237c4c9SSean Wang static const struct h4_recv_pkt mtk_recv_pkts[] = {
2317237c4c9SSean Wang { H4_RECV_ACL, .recv = hci_recv_frame },
2327237c4c9SSean Wang { H4_RECV_SCO, .recv = hci_recv_frame },
2337237c4c9SSean Wang { H4_RECV_EVENT, .recv = btmtkuart_recv_event },
2347237c4c9SSean Wang };
2357237c4c9SSean Wang
btmtkuart_tx_work(struct work_struct * work)2367237c4c9SSean Wang static void btmtkuart_tx_work(struct work_struct *work)
2377237c4c9SSean Wang {
2387237c4c9SSean Wang struct btmtkuart_dev *bdev = container_of(work, struct btmtkuart_dev,
2397237c4c9SSean Wang tx_work);
2407237c4c9SSean Wang struct serdev_device *serdev = bdev->serdev;
2417237c4c9SSean Wang struct hci_dev *hdev = bdev->hdev;
2427237c4c9SSean Wang
2437237c4c9SSean Wang while (1) {
2447237c4c9SSean Wang clear_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state);
2457237c4c9SSean Wang
2467237c4c9SSean Wang while (1) {
2477237c4c9SSean Wang struct sk_buff *skb = skb_dequeue(&bdev->txq);
2487237c4c9SSean Wang int len;
2497237c4c9SSean Wang
2507237c4c9SSean Wang if (!skb)
2517237c4c9SSean Wang break;
2527237c4c9SSean Wang
2537237c4c9SSean Wang len = serdev_device_write_buf(serdev, skb->data,
2547237c4c9SSean Wang skb->len);
2557237c4c9SSean Wang hdev->stat.byte_tx += len;
2567237c4c9SSean Wang
2577237c4c9SSean Wang skb_pull(skb, len);
2587237c4c9SSean Wang if (skb->len > 0) {
2597237c4c9SSean Wang skb_queue_head(&bdev->txq, skb);
2607237c4c9SSean Wang break;
2617237c4c9SSean Wang }
2627237c4c9SSean Wang
2637237c4c9SSean Wang switch (hci_skb_pkt_type(skb)) {
2647237c4c9SSean Wang case HCI_COMMAND_PKT:
2657237c4c9SSean Wang hdev->stat.cmd_tx++;
2667237c4c9SSean Wang break;
2677237c4c9SSean Wang case HCI_ACLDATA_PKT:
2687237c4c9SSean Wang hdev->stat.acl_tx++;
2697237c4c9SSean Wang break;
2707237c4c9SSean Wang case HCI_SCODATA_PKT:
2717237c4c9SSean Wang hdev->stat.sco_tx++;
2727237c4c9SSean Wang break;
2737237c4c9SSean Wang }
2747237c4c9SSean Wang
2757237c4c9SSean Wang kfree_skb(skb);
2767237c4c9SSean Wang }
2777237c4c9SSean Wang
2787237c4c9SSean Wang if (!test_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state))
2797237c4c9SSean Wang break;
2807237c4c9SSean Wang }
2817237c4c9SSean Wang
2827237c4c9SSean Wang clear_bit(BTMTKUART_TX_STATE_ACTIVE, &bdev->tx_state);
2837237c4c9SSean Wang }
2847237c4c9SSean Wang
btmtkuart_tx_wakeup(struct btmtkuart_dev * bdev)2857237c4c9SSean Wang static void btmtkuart_tx_wakeup(struct btmtkuart_dev *bdev)
2867237c4c9SSean Wang {
2877237c4c9SSean Wang if (test_and_set_bit(BTMTKUART_TX_STATE_ACTIVE, &bdev->tx_state))
2887237c4c9SSean Wang set_bit(BTMTKUART_TX_STATE_WAKEUP, &bdev->tx_state);
2897237c4c9SSean Wang
2907237c4c9SSean Wang schedule_work(&bdev->tx_work);
2917237c4c9SSean Wang }
2927237c4c9SSean Wang
2937237c4c9SSean Wang static const unsigned char *
mtk_stp_split(struct btmtkuart_dev * bdev,const unsigned char * data,int count,int * sz_h4)2947237c4c9SSean Wang mtk_stp_split(struct btmtkuart_dev *bdev, const unsigned char *data, int count,
2957237c4c9SSean Wang int *sz_h4)
2967237c4c9SSean Wang {
2977237c4c9SSean Wang struct mtk_stp_hdr *shdr;
2987237c4c9SSean Wang
2997237c4c9SSean Wang /* The cursor is reset when all the data of STP is consumed out */
3007237c4c9SSean Wang if (!bdev->stp_dlen && bdev->stp_cursor >= 6)
3017237c4c9SSean Wang bdev->stp_cursor = 0;
3027237c4c9SSean Wang
3037237c4c9SSean Wang /* Filling pad until all STP info is obtained */
3047237c4c9SSean Wang while (bdev->stp_cursor < 6 && count > 0) {
3057237c4c9SSean Wang bdev->stp_pad[bdev->stp_cursor] = *data;
3067237c4c9SSean Wang bdev->stp_cursor++;
3077237c4c9SSean Wang data++;
3087237c4c9SSean Wang count--;
3097237c4c9SSean Wang }
3107237c4c9SSean Wang
3117237c4c9SSean Wang /* Retrieve STP info and have a sanity check */
3127237c4c9SSean Wang if (!bdev->stp_dlen && bdev->stp_cursor >= 6) {
3137237c4c9SSean Wang shdr = (struct mtk_stp_hdr *)&bdev->stp_pad[2];
3147237c4c9SSean Wang bdev->stp_dlen = be16_to_cpu(shdr->dlen) & 0x0fff;
3157237c4c9SSean Wang
3167237c4c9SSean Wang /* Resync STP when unexpected data is being read */
3177237c4c9SSean Wang if (shdr->prefix != 0x80 || bdev->stp_dlen > 2048) {
3187237c4c9SSean Wang bt_dev_err(bdev->hdev, "stp format unexpect (%d, %d)",
3197237c4c9SSean Wang shdr->prefix, bdev->stp_dlen);
3207237c4c9SSean Wang bdev->stp_cursor = 2;
3217237c4c9SSean Wang bdev->stp_dlen = 0;
3227237c4c9SSean Wang }
3237237c4c9SSean Wang }
3247237c4c9SSean Wang
3257237c4c9SSean Wang /* Directly quit when there's no data found for H4 can process */
3267237c4c9SSean Wang if (count <= 0)
3277237c4c9SSean Wang return NULL;
3287237c4c9SSean Wang
3297237c4c9SSean Wang /* Tranlate to how much the size of data H4 can handle so far */
3307237c4c9SSean Wang *sz_h4 = min_t(int, count, bdev->stp_dlen);
3317237c4c9SSean Wang
3327237c4c9SSean Wang /* Update the remaining size of STP packet */
3337237c4c9SSean Wang bdev->stp_dlen -= *sz_h4;
3347237c4c9SSean Wang
3357237c4c9SSean Wang /* Data points to STP payload which can be handled by H4 */
3367237c4c9SSean Wang return data;
3377237c4c9SSean Wang }
3387237c4c9SSean Wang
btmtkuart_recv(struct hci_dev * hdev,const u8 * data,size_t count)339*0f37a5c9SFrancesco Dolcini static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
3407237c4c9SSean Wang {
3417237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
3427237c4c9SSean Wang const unsigned char *p_left = data, *p_h4;
3437237c4c9SSean Wang int sz_left = count, sz_h4, adv;
3447237c4c9SSean Wang int err;
3457237c4c9SSean Wang
3467237c4c9SSean Wang while (sz_left > 0) {
3477237c4c9SSean Wang /* The serial data received from MT7622 BT controller is
3487237c4c9SSean Wang * at all time padded around with the STP header and tailer.
3497237c4c9SSean Wang *
3507237c4c9SSean Wang * A full STP packet is looking like
3517237c4c9SSean Wang * -----------------------------------
3527237c4c9SSean Wang * | STP header | H:4 | STP tailer |
3537237c4c9SSean Wang * -----------------------------------
3547237c4c9SSean Wang * but it doesn't guarantee to contain a full H:4 packet which
3557237c4c9SSean Wang * means that it's possible for multiple STP packets forms a
3567237c4c9SSean Wang * full H:4 packet that means extra STP header + length doesn't
3577237c4c9SSean Wang * indicate a full H:4 frame, things can fragment. Whose length
3587237c4c9SSean Wang * recorded in STP header just shows up the most length the
3597237c4c9SSean Wang * H:4 engine can handle currently.
3607237c4c9SSean Wang */
3617237c4c9SSean Wang
3627237c4c9SSean Wang p_h4 = mtk_stp_split(bdev, p_left, sz_left, &sz_h4);
3637237c4c9SSean Wang if (!p_h4)
3647237c4c9SSean Wang break;
3657237c4c9SSean Wang
3667237c4c9SSean Wang adv = p_h4 - p_left;
3677237c4c9SSean Wang sz_left -= adv;
3687237c4c9SSean Wang p_left += adv;
3697237c4c9SSean Wang
3707237c4c9SSean Wang bdev->rx_skb = h4_recv_buf(bdev->hdev, bdev->rx_skb, p_h4,
3717237c4c9SSean Wang sz_h4, mtk_recv_pkts,
372330ad75fSDan Carpenter ARRAY_SIZE(mtk_recv_pkts));
3737237c4c9SSean Wang if (IS_ERR(bdev->rx_skb)) {
3747237c4c9SSean Wang err = PTR_ERR(bdev->rx_skb);
3757237c4c9SSean Wang bt_dev_err(bdev->hdev,
3767237c4c9SSean Wang "Frame reassembly failed (%d)", err);
3777237c4c9SSean Wang bdev->rx_skb = NULL;
378*0f37a5c9SFrancesco Dolcini return;
3797237c4c9SSean Wang }
3807237c4c9SSean Wang
3817237c4c9SSean Wang sz_left -= sz_h4;
3827237c4c9SSean Wang p_left += sz_h4;
3837237c4c9SSean Wang }
3847237c4c9SSean Wang }
3857237c4c9SSean Wang
btmtkuart_receive_buf(struct serdev_device * serdev,const u8 * data,size_t count)3867237c4c9SSean Wang static int btmtkuart_receive_buf(struct serdev_device *serdev, const u8 *data,
3877237c4c9SSean Wang size_t count)
3887237c4c9SSean Wang {
3897237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
3907237c4c9SSean Wang
391*0f37a5c9SFrancesco Dolcini btmtkuart_recv(bdev->hdev, data, count);
3927237c4c9SSean Wang
3937237c4c9SSean Wang bdev->hdev->stat.byte_rx += count;
3947237c4c9SSean Wang
3957237c4c9SSean Wang return count;
3967237c4c9SSean Wang }
3977237c4c9SSean Wang
btmtkuart_write_wakeup(struct serdev_device * serdev)3987237c4c9SSean Wang static void btmtkuart_write_wakeup(struct serdev_device *serdev)
3997237c4c9SSean Wang {
4007237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
4017237c4c9SSean Wang
4027237c4c9SSean Wang btmtkuart_tx_wakeup(bdev);
4037237c4c9SSean Wang }
4047237c4c9SSean Wang
4057237c4c9SSean Wang static const struct serdev_device_ops btmtkuart_client_ops = {
4067237c4c9SSean Wang .receive_buf = btmtkuart_receive_buf,
4077237c4c9SSean Wang .write_wakeup = btmtkuart_write_wakeup,
4087237c4c9SSean Wang };
4097237c4c9SSean Wang
btmtkuart_open(struct hci_dev * hdev)4107237c4c9SSean Wang static int btmtkuart_open(struct hci_dev *hdev)
4117237c4c9SSean Wang {
4127237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
4137237c4c9SSean Wang struct device *dev;
4147237c4c9SSean Wang int err;
4157237c4c9SSean Wang
4167237c4c9SSean Wang err = serdev_device_open(bdev->serdev);
4177237c4c9SSean Wang if (err) {
4187237c4c9SSean Wang bt_dev_err(hdev, "Unable to open UART device %s",
4197237c4c9SSean Wang dev_name(&bdev->serdev->dev));
4207237c4c9SSean Wang goto err_open;
4217237c4c9SSean Wang }
4227237c4c9SSean Wang
42322eaf6c9SSean Wang if (btmtkuart_is_standalone(bdev)) {
42422eaf6c9SSean Wang if (bdev->curr_speed != bdev->desired_speed)
42522eaf6c9SSean Wang err = serdev_device_set_baudrate(bdev->serdev,
42622eaf6c9SSean Wang 115200);
42722eaf6c9SSean Wang else
42822eaf6c9SSean Wang err = serdev_device_set_baudrate(bdev->serdev,
42922eaf6c9SSean Wang bdev->desired_speed);
43022eaf6c9SSean Wang
43122eaf6c9SSean Wang if (err < 0) {
43222eaf6c9SSean Wang bt_dev_err(hdev, "Unable to set baudrate UART device %s",
43322eaf6c9SSean Wang dev_name(&bdev->serdev->dev));
43422eaf6c9SSean Wang goto err_serdev_close;
43522eaf6c9SSean Wang }
43622eaf6c9SSean Wang
43722eaf6c9SSean Wang serdev_device_set_flow_control(bdev->serdev, false);
43822eaf6c9SSean Wang }
43922eaf6c9SSean Wang
4407237c4c9SSean Wang bdev->stp_cursor = 2;
4417237c4c9SSean Wang bdev->stp_dlen = 0;
4427237c4c9SSean Wang
4437237c4c9SSean Wang dev = &bdev->serdev->dev;
4447237c4c9SSean Wang
4457237c4c9SSean Wang /* Enable the power domain and clock the device requires */
4467237c4c9SSean Wang pm_runtime_enable(dev);
447a1b2fdf9SZhang Qilong err = pm_runtime_resume_and_get(dev);
448a1b2fdf9SZhang Qilong if (err < 0)
4497237c4c9SSean Wang goto err_disable_rpm;
4507237c4c9SSean Wang
4517237c4c9SSean Wang err = clk_prepare_enable(bdev->clk);
4527237c4c9SSean Wang if (err < 0)
4537237c4c9SSean Wang goto err_put_rpm;
4547237c4c9SSean Wang
4557237c4c9SSean Wang return 0;
4567237c4c9SSean Wang
4577237c4c9SSean Wang err_put_rpm:
4587237c4c9SSean Wang pm_runtime_put_sync(dev);
4597237c4c9SSean Wang err_disable_rpm:
4607237c4c9SSean Wang pm_runtime_disable(dev);
46122eaf6c9SSean Wang err_serdev_close:
46222eaf6c9SSean Wang serdev_device_close(bdev->serdev);
4637237c4c9SSean Wang err_open:
4647237c4c9SSean Wang return err;
4657237c4c9SSean Wang }
4667237c4c9SSean Wang
btmtkuart_close(struct hci_dev * hdev)4677237c4c9SSean Wang static int btmtkuart_close(struct hci_dev *hdev)
4687237c4c9SSean Wang {
4697237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
4707237c4c9SSean Wang struct device *dev = &bdev->serdev->dev;
4717237c4c9SSean Wang
4727237c4c9SSean Wang /* Shutdown the clock and power domain the device requires */
4737237c4c9SSean Wang clk_disable_unprepare(bdev->clk);
4747237c4c9SSean Wang pm_runtime_put_sync(dev);
4757237c4c9SSean Wang pm_runtime_disable(dev);
4767237c4c9SSean Wang
4777237c4c9SSean Wang serdev_device_close(bdev->serdev);
4787237c4c9SSean Wang
4797237c4c9SSean Wang return 0;
4807237c4c9SSean Wang }
4817237c4c9SSean Wang
btmtkuart_flush(struct hci_dev * hdev)4827237c4c9SSean Wang static int btmtkuart_flush(struct hci_dev *hdev)
4837237c4c9SSean Wang {
4847237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
4857237c4c9SSean Wang
4867237c4c9SSean Wang /* Flush any pending characters */
4877237c4c9SSean Wang serdev_device_write_flush(bdev->serdev);
4887237c4c9SSean Wang skb_queue_purge(&bdev->txq);
4897237c4c9SSean Wang
4907237c4c9SSean Wang cancel_work_sync(&bdev->tx_work);
4917237c4c9SSean Wang
4927237c4c9SSean Wang kfree_skb(bdev->rx_skb);
4937237c4c9SSean Wang bdev->rx_skb = NULL;
4947237c4c9SSean Wang
4957237c4c9SSean Wang bdev->stp_cursor = 2;
4967237c4c9SSean Wang bdev->stp_dlen = 0;
4977237c4c9SSean Wang
4987237c4c9SSean Wang return 0;
4997237c4c9SSean Wang }
5007237c4c9SSean Wang
btmtkuart_func_query(struct hci_dev * hdev)501e0b67035SSean Wang static int btmtkuart_func_query(struct hci_dev *hdev)
502e0b67035SSean Wang {
503e0b67035SSean Wang struct btmtk_hci_wmt_params wmt_params;
504e0b67035SSean Wang int status, err;
505e0b67035SSean Wang u8 param = 0;
506e0b67035SSean Wang
507e0b67035SSean Wang /* Query whether the function is enabled */
508f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
509e0b67035SSean Wang wmt_params.flag = 4;
510e0b67035SSean Wang wmt_params.dlen = sizeof(param);
511e0b67035SSean Wang wmt_params.data = ¶m;
512e0b67035SSean Wang wmt_params.status = &status;
513e0b67035SSean Wang
514e0b67035SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
515e0b67035SSean Wang if (err < 0) {
516e0b67035SSean Wang bt_dev_err(hdev, "Failed to query function status (%d)", err);
517e0b67035SSean Wang return err;
518e0b67035SSean Wang }
519e0b67035SSean Wang
520e0b67035SSean Wang return status;
521e0b67035SSean Wang }
522e0b67035SSean Wang
btmtkuart_change_baudrate(struct hci_dev * hdev)52322eaf6c9SSean Wang static int btmtkuart_change_baudrate(struct hci_dev *hdev)
52422eaf6c9SSean Wang {
52522eaf6c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
52622eaf6c9SSean Wang struct btmtk_hci_wmt_params wmt_params;
527cac63f9bSSean Wang __le32 baudrate;
52822eaf6c9SSean Wang u8 param;
52922eaf6c9SSean Wang int err;
53022eaf6c9SSean Wang
53122eaf6c9SSean Wang /* Indicate the device to enter the probe state the host is
53222eaf6c9SSean Wang * ready to change a new baudrate.
53322eaf6c9SSean Wang */
53422eaf6c9SSean Wang baudrate = cpu_to_le32(bdev->desired_speed);
535f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_HIF;
53622eaf6c9SSean Wang wmt_params.flag = 1;
53722eaf6c9SSean Wang wmt_params.dlen = 4;
53822eaf6c9SSean Wang wmt_params.data = &baudrate;
53922eaf6c9SSean Wang wmt_params.status = NULL;
54022eaf6c9SSean Wang
54122eaf6c9SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
54222eaf6c9SSean Wang if (err < 0) {
54322eaf6c9SSean Wang bt_dev_err(hdev, "Failed to device baudrate (%d)", err);
54422eaf6c9SSean Wang return err;
54522eaf6c9SSean Wang }
54622eaf6c9SSean Wang
54722eaf6c9SSean Wang err = serdev_device_set_baudrate(bdev->serdev,
54822eaf6c9SSean Wang bdev->desired_speed);
54922eaf6c9SSean Wang if (err < 0) {
55022eaf6c9SSean Wang bt_dev_err(hdev, "Failed to set up host baudrate (%d)",
55122eaf6c9SSean Wang err);
55222eaf6c9SSean Wang return err;
55322eaf6c9SSean Wang }
55422eaf6c9SSean Wang
55522eaf6c9SSean Wang serdev_device_set_flow_control(bdev->serdev, false);
55622eaf6c9SSean Wang
55722eaf6c9SSean Wang /* Send a dummy byte 0xff to activate the new baudrate */
55822eaf6c9SSean Wang param = 0xff;
559d3a0fe6bSZijun Hu err = serdev_device_write_buf(bdev->serdev, ¶m, sizeof(param));
56022eaf6c9SSean Wang if (err < 0 || err < sizeof(param))
56122eaf6c9SSean Wang return err;
56222eaf6c9SSean Wang
56322eaf6c9SSean Wang serdev_device_wait_until_sent(bdev->serdev, 0);
56422eaf6c9SSean Wang
56522eaf6c9SSean Wang /* Wait some time for the device changing baudrate done */
56622eaf6c9SSean Wang usleep_range(20000, 22000);
56722eaf6c9SSean Wang
56822eaf6c9SSean Wang /* Test the new baudrate */
569f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_TEST;
57022eaf6c9SSean Wang wmt_params.flag = 7;
57122eaf6c9SSean Wang wmt_params.dlen = 0;
57222eaf6c9SSean Wang wmt_params.data = NULL;
57322eaf6c9SSean Wang wmt_params.status = NULL;
57422eaf6c9SSean Wang
57522eaf6c9SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
57622eaf6c9SSean Wang if (err < 0) {
57722eaf6c9SSean Wang bt_dev_err(hdev, "Failed to test new baudrate (%d)",
57822eaf6c9SSean Wang err);
57922eaf6c9SSean Wang return err;
58022eaf6c9SSean Wang }
58122eaf6c9SSean Wang
58222eaf6c9SSean Wang bdev->curr_speed = bdev->desired_speed;
58322eaf6c9SSean Wang
58422eaf6c9SSean Wang return 0;
58522eaf6c9SSean Wang }
58622eaf6c9SSean Wang
btmtkuart_setup(struct hci_dev * hdev)5877237c4c9SSean Wang static int btmtkuart_setup(struct hci_dev *hdev)
5887237c4c9SSean Wang {
58922eaf6c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
59088e5f366SSean Wang struct btmtk_hci_wmt_params wmt_params;
591e0b67035SSean Wang ktime_t calltime, delta, rettime;
592e0b67035SSean Wang struct btmtk_tci_sleep tci_sleep;
593e0b67035SSean Wang unsigned long long duration;
594e0b67035SSean Wang struct sk_buff *skb;
595e0b67035SSean Wang int err, status;
5967237c4c9SSean Wang u8 param = 0x1;
597e0b67035SSean Wang
598e0b67035SSean Wang calltime = ktime_get();
599e0b67035SSean Wang
60022eaf6c9SSean Wang /* Wakeup MCUSYS is required for certain devices before we start to
60122eaf6c9SSean Wang * do any setups.
60222eaf6c9SSean Wang */
60322eaf6c9SSean Wang if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) {
604f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_WAKEUP;
60522eaf6c9SSean Wang wmt_params.flag = 3;
60622eaf6c9SSean Wang wmt_params.dlen = 0;
60722eaf6c9SSean Wang wmt_params.data = NULL;
60822eaf6c9SSean Wang wmt_params.status = NULL;
60922eaf6c9SSean Wang
61022eaf6c9SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
61122eaf6c9SSean Wang if (err < 0) {
61222eaf6c9SSean Wang bt_dev_err(hdev, "Failed to wakeup the chip (%d)", err);
61322eaf6c9SSean Wang return err;
61422eaf6c9SSean Wang }
61522eaf6c9SSean Wang
61622eaf6c9SSean Wang clear_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state);
61722eaf6c9SSean Wang }
61822eaf6c9SSean Wang
61922eaf6c9SSean Wang if (btmtkuart_is_standalone(bdev))
62022eaf6c9SSean Wang btmtkuart_change_baudrate(hdev);
62122eaf6c9SSean Wang
622e0b67035SSean Wang /* Query whether the firmware is already download */
623f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_SEMAPHORE;
624e0b67035SSean Wang wmt_params.flag = 1;
625e0b67035SSean Wang wmt_params.dlen = 0;
626e0b67035SSean Wang wmt_params.data = NULL;
627e0b67035SSean Wang wmt_params.status = &status;
628e0b67035SSean Wang
629e0b67035SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
630e0b67035SSean Wang if (err < 0) {
631e0b67035SSean Wang bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
632e0b67035SSean Wang return err;
633e0b67035SSean Wang }
634e0b67035SSean Wang
635e0b67035SSean Wang if (status == BTMTK_WMT_PATCH_DONE) {
636e0b67035SSean Wang bt_dev_info(hdev, "Firmware already downloaded");
637e0b67035SSean Wang goto ignore_setup_fw;
638e0b67035SSean Wang }
6397237c4c9SSean Wang
6407237c4c9SSean Wang /* Setup a firmware which the device definitely requires */
641f5c3f989SSean Wang err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync);
6427237c4c9SSean Wang if (err < 0)
6437237c4c9SSean Wang return err;
6447237c4c9SSean Wang
645e0b67035SSean Wang ignore_setup_fw:
646e0b67035SSean Wang /* Query whether the device is already enabled */
647e0b67035SSean Wang err = readx_poll_timeout(btmtkuart_func_query, hdev, status,
648e0b67035SSean Wang status < 0 || status != BTMTK_WMT_ON_PROGRESS,
649e0b67035SSean Wang 2000, 5000000);
650e0b67035SSean Wang /* -ETIMEDOUT happens */
651e0b67035SSean Wang if (err < 0)
6527237c4c9SSean Wang return err;
653e0b67035SSean Wang
654e0b67035SSean Wang /* The other errors happen in btusb_mtk_func_query */
655e0b67035SSean Wang if (status < 0)
656e0b67035SSean Wang return status;
657e0b67035SSean Wang
658e0b67035SSean Wang if (status == BTMTK_WMT_ON_DONE) {
659e0b67035SSean Wang bt_dev_info(hdev, "function already on");
660e0b67035SSean Wang goto ignore_func_on;
6617237c4c9SSean Wang }
6627237c4c9SSean Wang
6637237c4c9SSean Wang /* Enable Bluetooth protocol */
664f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
66588e5f366SSean Wang wmt_params.flag = 0;
66688e5f366SSean Wang wmt_params.dlen = sizeof(param);
66788e5f366SSean Wang wmt_params.data = ¶m;
66888e5f366SSean Wang wmt_params.status = NULL;
66988e5f366SSean Wang
67088e5f366SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
6717237c4c9SSean Wang if (err < 0) {
6727237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
6737237c4c9SSean Wang return err;
6747237c4c9SSean Wang }
6757237c4c9SSean Wang
676e0b67035SSean Wang ignore_func_on:
677e0b67035SSean Wang /* Apply the low power environment setup */
678e0b67035SSean Wang tci_sleep.mode = 0x5;
679e0b67035SSean Wang tci_sleep.duration = cpu_to_le16(0x640);
680e0b67035SSean Wang tci_sleep.host_duration = cpu_to_le16(0x640);
681e0b67035SSean Wang tci_sleep.host_wakeup_pin = 0;
682e0b67035SSean Wang tci_sleep.time_compensation = 0;
683e0b67035SSean Wang
684e0b67035SSean Wang skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
685e0b67035SSean Wang HCI_INIT_TIMEOUT);
686e0b67035SSean Wang if (IS_ERR(skb)) {
687e0b67035SSean Wang err = PTR_ERR(skb);
688e0b67035SSean Wang bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
689e0b67035SSean Wang return err;
690e0b67035SSean Wang }
691e0b67035SSean Wang kfree_skb(skb);
692e0b67035SSean Wang
693e0b67035SSean Wang rettime = ktime_get();
694e0b67035SSean Wang delta = ktime_sub(rettime, calltime);
695e0b67035SSean Wang duration = (unsigned long long)ktime_to_ns(delta) >> 10;
696e0b67035SSean Wang
697e0b67035SSean Wang bt_dev_info(hdev, "Device setup in %llu usecs", duration);
698e0b67035SSean Wang
6997237c4c9SSean Wang return 0;
7007237c4c9SSean Wang }
7017237c4c9SSean Wang
btmtkuart_shutdown(struct hci_dev * hdev)7027237c4c9SSean Wang static int btmtkuart_shutdown(struct hci_dev *hdev)
7037237c4c9SSean Wang {
70488e5f366SSean Wang struct btmtk_hci_wmt_params wmt_params;
7057237c4c9SSean Wang u8 param = 0x0;
7067237c4c9SSean Wang int err;
7077237c4c9SSean Wang
7087237c4c9SSean Wang /* Disable the device */
709f5c3f989SSean Wang wmt_params.op = BTMTK_WMT_FUNC_CTRL;
71088e5f366SSean Wang wmt_params.flag = 0;
71188e5f366SSean Wang wmt_params.dlen = sizeof(param);
71288e5f366SSean Wang wmt_params.data = ¶m;
71388e5f366SSean Wang wmt_params.status = NULL;
71488e5f366SSean Wang
71588e5f366SSean Wang err = mtk_hci_wmt_sync(hdev, &wmt_params);
7167237c4c9SSean Wang if (err < 0) {
7177237c4c9SSean Wang bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
7187237c4c9SSean Wang return err;
7197237c4c9SSean Wang }
7207237c4c9SSean Wang
7217237c4c9SSean Wang return 0;
7227237c4c9SSean Wang }
7237237c4c9SSean Wang
btmtkuart_send_frame(struct hci_dev * hdev,struct sk_buff * skb)7247237c4c9SSean Wang static int btmtkuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
7257237c4c9SSean Wang {
7267237c4c9SSean Wang struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
7277237c4c9SSean Wang struct mtk_stp_hdr *shdr;
7287237c4c9SSean Wang int err, dlen, type = 0;
7297237c4c9SSean Wang
7307237c4c9SSean Wang /* Prepend skb with frame type */
7317237c4c9SSean Wang memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
7327237c4c9SSean Wang
7337237c4c9SSean Wang /* Make sure that there is enough rooms for STP header and trailer */
7347237c4c9SSean Wang if (unlikely(skb_headroom(skb) < sizeof(*shdr)) ||
7357237c4c9SSean Wang (skb_tailroom(skb) < MTK_STP_TLR_SIZE)) {
7367237c4c9SSean Wang err = pskb_expand_head(skb, sizeof(*shdr), MTK_STP_TLR_SIZE,
7377237c4c9SSean Wang GFP_ATOMIC);
7387237c4c9SSean Wang if (err < 0)
7397237c4c9SSean Wang return err;
7407237c4c9SSean Wang }
7417237c4c9SSean Wang
7427237c4c9SSean Wang /* Add the STP header */
7437237c4c9SSean Wang dlen = skb->len;
7447237c4c9SSean Wang shdr = skb_push(skb, sizeof(*shdr));
7457237c4c9SSean Wang shdr->prefix = 0x80;
7467237c4c9SSean Wang shdr->dlen = cpu_to_be16((dlen & 0x0fff) | (type << 12));
7477237c4c9SSean Wang shdr->cs = 0; /* MT7622 doesn't care about checksum value */
7487237c4c9SSean Wang
7497237c4c9SSean Wang /* Add the STP trailer */
7507237c4c9SSean Wang skb_put_zero(skb, MTK_STP_TLR_SIZE);
7517237c4c9SSean Wang
7527237c4c9SSean Wang skb_queue_tail(&bdev->txq, skb);
7537237c4c9SSean Wang
7547237c4c9SSean Wang btmtkuart_tx_wakeup(bdev);
7557237c4c9SSean Wang return 0;
7567237c4c9SSean Wang }
7577237c4c9SSean Wang
btmtkuart_parse_dt(struct serdev_device * serdev)75822eaf6c9SSean Wang static int btmtkuart_parse_dt(struct serdev_device *serdev)
75922eaf6c9SSean Wang {
76022eaf6c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
76122eaf6c9SSean Wang struct device_node *node = serdev->dev.of_node;
76222eaf6c9SSean Wang u32 speed = 921600;
76322eaf6c9SSean Wang int err;
76422eaf6c9SSean Wang
76522eaf6c9SSean Wang if (btmtkuart_is_standalone(bdev)) {
76622eaf6c9SSean Wang of_property_read_u32(node, "current-speed", &speed);
76722eaf6c9SSean Wang
76822eaf6c9SSean Wang bdev->desired_speed = speed;
76922eaf6c9SSean Wang
77022eaf6c9SSean Wang bdev->vcc = devm_regulator_get(&serdev->dev, "vcc");
77122eaf6c9SSean Wang if (IS_ERR(bdev->vcc)) {
77222eaf6c9SSean Wang err = PTR_ERR(bdev->vcc);
77322eaf6c9SSean Wang return err;
77422eaf6c9SSean Wang }
77522eaf6c9SSean Wang
77605582561SSean Wang bdev->osc = devm_clk_get_optional(&serdev->dev, "osc");
77705582561SSean Wang if (IS_ERR(bdev->osc)) {
77805582561SSean Wang err = PTR_ERR(bdev->osc);
77905582561SSean Wang return err;
78005582561SSean Wang }
78105582561SSean Wang
782a3cb6d60SSean Wang bdev->boot = devm_gpiod_get_optional(&serdev->dev, "boot",
783a3cb6d60SSean Wang GPIOD_OUT_LOW);
784a3cb6d60SSean Wang if (IS_ERR(bdev->boot)) {
785a3cb6d60SSean Wang err = PTR_ERR(bdev->boot);
786a3cb6d60SSean Wang return err;
787a3cb6d60SSean Wang }
788a3cb6d60SSean Wang
78922eaf6c9SSean Wang bdev->pinctrl = devm_pinctrl_get(&serdev->dev);
79022eaf6c9SSean Wang if (IS_ERR(bdev->pinctrl)) {
79122eaf6c9SSean Wang err = PTR_ERR(bdev->pinctrl);
79222eaf6c9SSean Wang return err;
79322eaf6c9SSean Wang }
79422eaf6c9SSean Wang
79522eaf6c9SSean Wang bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl,
79622eaf6c9SSean Wang "default");
797a3cb6d60SSean Wang if (IS_ERR(bdev->pins_boot) && !bdev->boot) {
79822eaf6c9SSean Wang err = PTR_ERR(bdev->pins_boot);
799a3cb6d60SSean Wang dev_err(&serdev->dev,
800a3cb6d60SSean Wang "Should assign RXD to LOW at boot stage\n");
80122eaf6c9SSean Wang return err;
80222eaf6c9SSean Wang }
80322eaf6c9SSean Wang
80422eaf6c9SSean Wang bdev->pins_runtime = pinctrl_lookup_state(bdev->pinctrl,
80522eaf6c9SSean Wang "runtime");
80622eaf6c9SSean Wang if (IS_ERR(bdev->pins_runtime)) {
80722eaf6c9SSean Wang err = PTR_ERR(bdev->pins_runtime);
80822eaf6c9SSean Wang return err;
80922eaf6c9SSean Wang }
81022eaf6c9SSean Wang
81122eaf6c9SSean Wang bdev->reset = devm_gpiod_get_optional(&serdev->dev, "reset",
81222eaf6c9SSean Wang GPIOD_OUT_LOW);
81322eaf6c9SSean Wang if (IS_ERR(bdev->reset)) {
81422eaf6c9SSean Wang err = PTR_ERR(bdev->reset);
81522eaf6c9SSean Wang return err;
81622eaf6c9SSean Wang }
81722eaf6c9SSean Wang } else if (btmtkuart_is_builtin_soc(bdev)) {
81822eaf6c9SSean Wang bdev->clk = devm_clk_get(&serdev->dev, "ref");
81922eaf6c9SSean Wang if (IS_ERR(bdev->clk))
82022eaf6c9SSean Wang return PTR_ERR(bdev->clk);
82122eaf6c9SSean Wang }
82222eaf6c9SSean Wang
82322eaf6c9SSean Wang return 0;
82422eaf6c9SSean Wang }
82522eaf6c9SSean Wang
btmtkuart_probe(struct serdev_device * serdev)8267237c4c9SSean Wang static int btmtkuart_probe(struct serdev_device *serdev)
8277237c4c9SSean Wang {
8287237c4c9SSean Wang struct btmtkuart_dev *bdev;
8297237c4c9SSean Wang struct hci_dev *hdev;
83022eaf6c9SSean Wang int err;
8317237c4c9SSean Wang
8327237c4c9SSean Wang bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL);
8337237c4c9SSean Wang if (!bdev)
8347237c4c9SSean Wang return -ENOMEM;
8357237c4c9SSean Wang
83622eaf6c9SSean Wang bdev->data = of_device_get_match_data(&serdev->dev);
83722eaf6c9SSean Wang if (!bdev->data)
83822eaf6c9SSean Wang return -ENODEV;
8397237c4c9SSean Wang
8407237c4c9SSean Wang bdev->serdev = serdev;
8417237c4c9SSean Wang serdev_device_set_drvdata(serdev, bdev);
8427237c4c9SSean Wang
8437237c4c9SSean Wang serdev_device_set_client_ops(serdev, &btmtkuart_client_ops);
8447237c4c9SSean Wang
84522eaf6c9SSean Wang err = btmtkuart_parse_dt(serdev);
84622eaf6c9SSean Wang if (err < 0)
84722eaf6c9SSean Wang return err;
84822eaf6c9SSean Wang
8497237c4c9SSean Wang INIT_WORK(&bdev->tx_work, btmtkuart_tx_work);
8507237c4c9SSean Wang skb_queue_head_init(&bdev->txq);
8517237c4c9SSean Wang
8527237c4c9SSean Wang /* Initialize and register HCI device */
8537237c4c9SSean Wang hdev = hci_alloc_dev();
8547237c4c9SSean Wang if (!hdev) {
8557237c4c9SSean Wang dev_err(&serdev->dev, "Can't allocate HCI device\n");
8567237c4c9SSean Wang return -ENOMEM;
8577237c4c9SSean Wang }
8587237c4c9SSean Wang
8597237c4c9SSean Wang bdev->hdev = hdev;
8607237c4c9SSean Wang
8617237c4c9SSean Wang hdev->bus = HCI_UART;
8627237c4c9SSean Wang hci_set_drvdata(hdev, bdev);
8637237c4c9SSean Wang
8647237c4c9SSean Wang hdev->open = btmtkuart_open;
8657237c4c9SSean Wang hdev->close = btmtkuart_close;
8667237c4c9SSean Wang hdev->flush = btmtkuart_flush;
8677237c4c9SSean Wang hdev->setup = btmtkuart_setup;
8687237c4c9SSean Wang hdev->shutdown = btmtkuart_shutdown;
8697237c4c9SSean Wang hdev->send = btmtkuart_send_frame;
8703640e7f4SSean Wang hdev->set_bdaddr = btmtk_set_bdaddr;
8717237c4c9SSean Wang SET_HCIDEV_DEV(hdev, &serdev->dev);
8727237c4c9SSean Wang
8737237c4c9SSean Wang hdev->manufacturer = 70;
8747237c4c9SSean Wang set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
8757237c4c9SSean Wang
87622eaf6c9SSean Wang if (btmtkuart_is_standalone(bdev)) {
87705582561SSean Wang err = clk_prepare_enable(bdev->osc);
87805582561SSean Wang if (err < 0)
8794803c54cSChuhong Yuan goto err_hci_free_dev;
88005582561SSean Wang
881a3cb6d60SSean Wang if (bdev->boot) {
882a3cb6d60SSean Wang gpiod_set_value_cansleep(bdev->boot, 1);
883a3cb6d60SSean Wang } else {
884a3cb6d60SSean Wang /* Switch to the specific pin state for the booting
885a3cb6d60SSean Wang * requires.
886a3cb6d60SSean Wang */
88722eaf6c9SSean Wang pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
888a3cb6d60SSean Wang }
88922eaf6c9SSean Wang
89022eaf6c9SSean Wang /* Power on */
89122eaf6c9SSean Wang err = regulator_enable(bdev->vcc);
8924803c54cSChuhong Yuan if (err < 0)
8934803c54cSChuhong Yuan goto err_clk_disable_unprepare;
89422eaf6c9SSean Wang
89522eaf6c9SSean Wang /* Reset if the reset-gpios is available otherwise the board
89622eaf6c9SSean Wang * -level design should be guaranteed.
89722eaf6c9SSean Wang */
89822eaf6c9SSean Wang if (bdev->reset) {
89922eaf6c9SSean Wang gpiod_set_value_cansleep(bdev->reset, 1);
90022eaf6c9SSean Wang usleep_range(1000, 2000);
90122eaf6c9SSean Wang gpiod_set_value_cansleep(bdev->reset, 0);
90222eaf6c9SSean Wang }
90322eaf6c9SSean Wang
90422eaf6c9SSean Wang /* Wait some time until device got ready and switch to the pin
90522eaf6c9SSean Wang * mode the device requires for UART transfers.
90622eaf6c9SSean Wang */
90722eaf6c9SSean Wang msleep(50);
908a3cb6d60SSean Wang
909a3cb6d60SSean Wang if (bdev->boot)
910a3cb6d60SSean Wang devm_gpiod_put(&serdev->dev, bdev->boot);
911a3cb6d60SSean Wang
91222eaf6c9SSean Wang pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime);
91322eaf6c9SSean Wang
91422eaf6c9SSean Wang /* A standalone device doesn't depends on power domain on SoC,
91522eaf6c9SSean Wang * so mark it as no callbacks.
91622eaf6c9SSean Wang */
91722eaf6c9SSean Wang pm_runtime_no_callbacks(&serdev->dev);
91822eaf6c9SSean Wang
91922eaf6c9SSean Wang set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state);
92022eaf6c9SSean Wang }
92122eaf6c9SSean Wang
92222eaf6c9SSean Wang err = hci_register_dev(hdev);
92322eaf6c9SSean Wang if (err < 0) {
9247237c4c9SSean Wang dev_err(&serdev->dev, "Can't register HCI device\n");
92522eaf6c9SSean Wang goto err_regulator_disable;
9267237c4c9SSean Wang }
9277237c4c9SSean Wang
9287237c4c9SSean Wang return 0;
92922eaf6c9SSean Wang
93022eaf6c9SSean Wang err_regulator_disable:
931a3cb6d60SSean Wang if (btmtkuart_is_standalone(bdev))
93222eaf6c9SSean Wang regulator_disable(bdev->vcc);
9334803c54cSChuhong Yuan err_clk_disable_unprepare:
9344803c54cSChuhong Yuan if (btmtkuart_is_standalone(bdev))
9354803c54cSChuhong Yuan clk_disable_unprepare(bdev->osc);
9364803c54cSChuhong Yuan err_hci_free_dev:
9374803c54cSChuhong Yuan hci_free_dev(hdev);
93822eaf6c9SSean Wang
93922eaf6c9SSean Wang return err;
9407237c4c9SSean Wang }
9417237c4c9SSean Wang
btmtkuart_remove(struct serdev_device * serdev)9427237c4c9SSean Wang static void btmtkuart_remove(struct serdev_device *serdev)
9437237c4c9SSean Wang {
9447237c4c9SSean Wang struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
9457237c4c9SSean Wang struct hci_dev *hdev = bdev->hdev;
9467237c4c9SSean Wang
94705582561SSean Wang if (btmtkuart_is_standalone(bdev)) {
94822eaf6c9SSean Wang regulator_disable(bdev->vcc);
94905582561SSean Wang clk_disable_unprepare(bdev->osc);
95005582561SSean Wang }
95122eaf6c9SSean Wang
9527237c4c9SSean Wang hci_unregister_dev(hdev);
9537237c4c9SSean Wang hci_free_dev(hdev);
9547237c4c9SSean Wang }
9557237c4c9SSean Wang
956a88ea43bSKrzysztof Kozlowski static const struct btmtkuart_data mt7622_data __maybe_unused = {
95722eaf6c9SSean Wang .fwname = FIRMWARE_MT7622,
95822eaf6c9SSean Wang };
95922eaf6c9SSean Wang
960a88ea43bSKrzysztof Kozlowski static const struct btmtkuart_data mt7663_data __maybe_unused = {
96122eaf6c9SSean Wang .flags = BTMTKUART_FLAG_STANDALONE_HW,
96222eaf6c9SSean Wang .fwname = FIRMWARE_MT7663,
96322eaf6c9SSean Wang };
96422eaf6c9SSean Wang
965a88ea43bSKrzysztof Kozlowski static const struct btmtkuart_data mt7668_data __maybe_unused = {
96622eaf6c9SSean Wang .flags = BTMTKUART_FLAG_STANDALONE_HW,
96722eaf6c9SSean Wang .fwname = FIRMWARE_MT7668,
96822eaf6c9SSean Wang };
96922eaf6c9SSean Wang
9707237c4c9SSean Wang #ifdef CONFIG_OF
9717237c4c9SSean Wang static const struct of_device_id mtk_of_match_table[] = {
97222eaf6c9SSean Wang { .compatible = "mediatek,mt7622-bluetooth", .data = &mt7622_data},
97322eaf6c9SSean Wang { .compatible = "mediatek,mt7663u-bluetooth", .data = &mt7663_data},
97422eaf6c9SSean Wang { .compatible = "mediatek,mt7668u-bluetooth", .data = &mt7668_data},
9757237c4c9SSean Wang { }
9767237c4c9SSean Wang };
9777237c4c9SSean Wang MODULE_DEVICE_TABLE(of, mtk_of_match_table);
9787237c4c9SSean Wang #endif
9797237c4c9SSean Wang
9807237c4c9SSean Wang static struct serdev_device_driver btmtkuart_driver = {
9817237c4c9SSean Wang .probe = btmtkuart_probe,
9827237c4c9SSean Wang .remove = btmtkuart_remove,
9837237c4c9SSean Wang .driver = {
9847237c4c9SSean Wang .name = "btmtkuart",
9857237c4c9SSean Wang .of_match_table = of_match_ptr(mtk_of_match_table),
9867237c4c9SSean Wang },
9877237c4c9SSean Wang };
9887237c4c9SSean Wang
9897237c4c9SSean Wang module_serdev_device_driver(btmtkuart_driver);
9907237c4c9SSean Wang
9917237c4c9SSean Wang MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
9927237c4c9SSean Wang MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION);
9937237c4c9SSean Wang MODULE_VERSION(VERSION);
9947237c4c9SSean Wang MODULE_LICENSE("GPL");
995