summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorSean Wang <sean.wang@mediatek.com>2019-02-14 18:19:37 -0500
committerMarcel Holtmann <marcel@holtmann.org>2019-02-18 08:08:55 -0500
commite0b67035a90b58d01f911fed77b6e3da153da66e (patch)
tree2a8b0a394cbd2674ebc9709c16594c80bc80d541 /drivers/bluetooth
parent88e5f366a1903bfb717ad37a72f4657dae4d81da (diff)
Bluetooth: mediatek: update the common setup between MT7622 and other devices
Update the setup sequence on MT7622 to apply the same flow with MT7663U and MT7668U USB [1] as much as possible. These additional commands are required to parse the corresponding event to determine what current state the Bluetooth device is on and thus it's necessary to extend mtk_hci_wmt_sync to support the reading status in the same patch. [1] http://lists.infradead.org/pipermail/linux-mediatek/2019-January/017074.html Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btmtkuart.c204
1 files changed, 190 insertions, 14 deletions
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index 4451b1db139a..e73b1013ba73 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -12,6 +12,7 @@
12#include <linux/atomic.h> 12#include <linux/atomic.h>
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/firmware.h> 14#include <linux/firmware.h>
15#include <linux/iopoll.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/of.h> 18#include <linux/of.h>
@@ -37,7 +38,17 @@
37enum { 38enum {
38 MTK_WMT_PATCH_DWNLD = 0x1, 39 MTK_WMT_PATCH_DWNLD = 0x1,
39 MTK_WMT_FUNC_CTRL = 0x6, 40 MTK_WMT_FUNC_CTRL = 0x6,
40 MTK_WMT_RST = 0x7 41 MTK_WMT_RST = 0x7,
42 MTK_WMT_SEMAPHORE = 0x17,
43};
44
45enum {
46 BTMTK_WMT_INVALID,
47 BTMTK_WMT_PATCH_UNDONE,
48 BTMTK_WMT_PATCH_DONE,
49 BTMTK_WMT_ON_UNDONE,
50 BTMTK_WMT_ON_DONE,
51 BTMTK_WMT_ON_PROGRESS,
41}; 52};
42 53
43struct mtk_stp_hdr { 54struct mtk_stp_hdr {
@@ -58,6 +69,24 @@ struct mtk_hci_wmt_cmd {
58 u8 data[256]; 69 u8 data[256];
59} __packed; 70} __packed;
60 71
72struct btmtk_hci_wmt_evt {
73 struct hci_event_hdr hhdr;
74 struct mtk_wmt_hdr whdr;
75} __packed;
76
77struct btmtk_hci_wmt_evt_funcc {
78 struct btmtk_hci_wmt_evt hwhdr;
79 __be16 status;
80} __packed;
81
82struct btmtk_tci_sleep {
83 u8 mode;
84 __le16 duration;
85 __le16 host_duration;
86 u8 host_wakeup_pin;
87 u8 time_compensation;
88} __packed;
89
61struct btmtk_hci_wmt_params { 90struct btmtk_hci_wmt_params {
62 u8 op; 91 u8 op;
63 u8 flag; 92 u8 flag;
@@ -76,6 +105,7 @@ struct btmtkuart_dev {
76 struct sk_buff_head txq; 105 struct sk_buff_head txq;
77 106
78 struct sk_buff *rx_skb; 107 struct sk_buff *rx_skb;
108 struct sk_buff *evt_skb;
79 109
80 u8 stp_pad[6]; 110 u8 stp_pad[6];
81 u8 stp_cursor; 111 u8 stp_cursor;
@@ -86,9 +116,11 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
86 struct btmtk_hci_wmt_params *wmt_params) 116 struct btmtk_hci_wmt_params *wmt_params)
87{ 117{
88 struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); 118 struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
119 struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
120 u32 hlen, status = BTMTK_WMT_INVALID;
121 struct btmtk_hci_wmt_evt *wmt_evt;
89 struct mtk_hci_wmt_cmd wc; 122 struct mtk_hci_wmt_cmd wc;
90 struct mtk_wmt_hdr *hdr; 123 struct mtk_wmt_hdr *hdr;
91 u32 hlen;
92 int err; 124 int err;
93 125
94 hlen = sizeof(*hdr) + wmt_params->dlen; 126 hlen = sizeof(*hdr) + wmt_params->dlen;
@@ -133,7 +165,41 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
133 return -ETIMEDOUT; 165 return -ETIMEDOUT;
134 } 166 }
135 167
136 return 0; 168 /* Parse and handle the return WMT event */
169 wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
170 if (wmt_evt->whdr.op != hdr->op) {
171 bt_dev_err(hdev, "Wrong op received %d expected %d",
172 wmt_evt->whdr.op, hdr->op);
173 err = -EIO;
174 goto err_free_skb;
175 }
176
177 switch (wmt_evt->whdr.op) {
178 case MTK_WMT_SEMAPHORE:
179 if (wmt_evt->whdr.flag == 2)
180 status = BTMTK_WMT_PATCH_UNDONE;
181 else
182 status = BTMTK_WMT_PATCH_DONE;
183 break;
184 case MTK_WMT_FUNC_CTRL:
185 wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
186 if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
187 status = BTMTK_WMT_ON_DONE;
188 else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
189 status = BTMTK_WMT_ON_PROGRESS;
190 else
191 status = BTMTK_WMT_ON_UNDONE;
192 break;
193 }
194
195 if (wmt_params->status)
196 *wmt_params->status = status;
197
198err_free_skb:
199 kfree_skb(bdev->evt_skb);
200 bdev->evt_skb = NULL;
201
202 return err;
137} 203}
138 204
139static int mtk_setup_fw(struct hci_dev *hdev) 205static int mtk_setup_fw(struct hci_dev *hdev)
@@ -184,13 +250,29 @@ static int mtk_setup_fw(struct hci_dev *hdev)
184 if (err < 0) { 250 if (err < 0) {
185 bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", 251 bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
186 err); 252 err);
187 break; 253 goto free_fw;
188 } 254 }
189 255
190 fw_size -= dlen; 256 fw_size -= dlen;
191 fw_ptr += dlen; 257 fw_ptr += dlen;
192 } 258 }
193 259
260 wmt_params.op = MTK_WMT_RST;
261 wmt_params.flag = 4;
262 wmt_params.dlen = 0;
263 wmt_params.data = NULL;
264 wmt_params.status = NULL;
265
266 /* Activate funciton the firmware providing to */
267 err = mtk_hci_wmt_sync(hdev, &wmt_params);
268 if (err < 0) {
269 bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
270 goto free_fw;
271 }
272
273 /* Wait a few moments for firmware activation done */
274 usleep_range(10000, 12000);
275
194free_fw: 276free_fw:
195 release_firmware(fw); 277 release_firmware(fw);
196 return err; 278 return err;
@@ -209,7 +291,20 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
209 if (hdr->evt == 0xe4) 291 if (hdr->evt == 0xe4)
210 hdr->evt = HCI_EV_VENDOR; 292 hdr->evt = HCI_EV_VENDOR;
211 293
294 /* When someone waits for the WMT event, the skb is being cloned
295 * and being processed the events from there then.
296 */
297 if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) {
298 bdev->evt_skb = skb_clone(skb, GFP_KERNEL);
299 if (!bdev->evt_skb) {
300 err = -ENOMEM;
301 goto err_out;
302 }
303 }
304
212 err = hci_recv_frame(hdev, skb); 305 err = hci_recv_frame(hdev, skb);
306 if (err < 0)
307 goto err_free_skb;
213 308
214 if (hdr->evt == HCI_EV_VENDOR) { 309 if (hdr->evt == HCI_EV_VENDOR) {
215 if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, 310 if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT,
@@ -220,6 +315,13 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
220 } 315 }
221 } 316 }
222 317
318 return 0;
319
320err_free_skb:
321 kfree_skb(bdev->evt_skb);
322 bdev->evt_skb = NULL;
323
324err_out:
223 return err; 325 return err;
224} 326}
225 327
@@ -482,28 +584,79 @@ static int btmtkuart_flush(struct hci_dev *hdev)
482 return 0; 584 return 0;
483} 585}
484 586
587static int btmtkuart_func_query(struct hci_dev *hdev)
588{
589 struct btmtk_hci_wmt_params wmt_params;
590 int status, err;
591 u8 param = 0;
592
593 /* Query whether the function is enabled */
594 wmt_params.op = MTK_WMT_FUNC_CTRL;
595 wmt_params.flag = 4;
596 wmt_params.dlen = sizeof(param);
597 wmt_params.data = &param;
598 wmt_params.status = &status;
599
600 err = mtk_hci_wmt_sync(hdev, &wmt_params);
601 if (err < 0) {
602 bt_dev_err(hdev, "Failed to query function status (%d)", err);
603 return err;
604 }
605
606 return status;
607}
608
485static int btmtkuart_setup(struct hci_dev *hdev) 609static int btmtkuart_setup(struct hci_dev *hdev)
486{ 610{
487 struct btmtk_hci_wmt_params wmt_params; 611 struct btmtk_hci_wmt_params wmt_params;
612 ktime_t calltime, delta, rettime;
613 struct btmtk_tci_sleep tci_sleep;
614 unsigned long long duration;
615 struct sk_buff *skb;
616 int err, status;
488 u8 param = 0x1; 617 u8 param = 0x1;
489 int err = 0;
490 618
491 /* Setup a firmware which the device definitely requires */ 619 calltime = ktime_get();
492 err = mtk_setup_fw(hdev);
493 if (err < 0)
494 return err;
495 620
496 wmt_params.op = MTK_WMT_RST; 621 /* Query whether the firmware is already download */
497 wmt_params.flag = 4; 622 wmt_params.op = MTK_WMT_SEMAPHORE;
623 wmt_params.flag = 1;
498 wmt_params.dlen = 0; 624 wmt_params.dlen = 0;
499 wmt_params.data = NULL; 625 wmt_params.data = NULL;
500 wmt_params.status = NULL; 626 wmt_params.status = &status;
501 627
502 /* Activate funciton the firmware providing to */
503 err = mtk_hci_wmt_sync(hdev, &wmt_params); 628 err = mtk_hci_wmt_sync(hdev, &wmt_params);
504 if (err < 0) { 629 if (err < 0) {
505 bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); 630 bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
631 return err;
632 }
633
634 if (status == BTMTK_WMT_PATCH_DONE) {
635 bt_dev_info(hdev, "Firmware already downloaded");
636 goto ignore_setup_fw;
637 }
638
639 /* Setup a firmware which the device definitely requires */
640 err = mtk_setup_fw(hdev);
641 if (err < 0)
506 return err; 642 return err;
643
644ignore_setup_fw:
645 /* Query whether the device is already enabled */
646 err = readx_poll_timeout(btmtkuart_func_query, hdev, status,
647 status < 0 || status != BTMTK_WMT_ON_PROGRESS,
648 2000, 5000000);
649 /* -ETIMEDOUT happens */
650 if (err < 0)
651 return err;
652
653 /* The other errors happen in btusb_mtk_func_query */
654 if (status < 0)
655 return status;
656
657 if (status == BTMTK_WMT_ON_DONE) {
658 bt_dev_info(hdev, "function already on");
659 goto ignore_func_on;
507 } 660 }
508 661
509 /* Enable Bluetooth protocol */ 662 /* Enable Bluetooth protocol */
@@ -519,6 +672,29 @@ static int btmtkuart_setup(struct hci_dev *hdev)
519 return err; 672 return err;
520 } 673 }
521 674
675ignore_func_on:
676 /* Apply the low power environment setup */
677 tci_sleep.mode = 0x5;
678 tci_sleep.duration = cpu_to_le16(0x640);
679 tci_sleep.host_duration = cpu_to_le16(0x640);
680 tci_sleep.host_wakeup_pin = 0;
681 tci_sleep.time_compensation = 0;
682
683 skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
684 HCI_INIT_TIMEOUT);
685 if (IS_ERR(skb)) {
686 err = PTR_ERR(skb);
687 bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
688 return err;
689 }
690 kfree_skb(skb);
691
692 rettime = ktime_get();
693 delta = ktime_sub(rettime, calltime);
694 duration = (unsigned long long)ktime_to_ns(delta) >> 10;
695
696 bt_dev_info(hdev, "Device setup in %llu usecs", duration);
697
522 return 0; 698 return 0;
523} 699}
524 700