.. | .. |
---|
12 | 12 | #include <linux/atomic.h> |
---|
13 | 13 | #include <linux/clk.h> |
---|
14 | 14 | #include <linux/firmware.h> |
---|
| 15 | +#include <linux/gpio/consumer.h> |
---|
| 16 | +#include <linux/iopoll.h> |
---|
15 | 17 | #include <linux/kernel.h> |
---|
16 | 18 | #include <linux/module.h> |
---|
17 | 19 | #include <linux/of.h> |
---|
| 20 | +#include <linux/of_device.h> |
---|
| 21 | +#include <linux/pinctrl/consumer.h> |
---|
18 | 22 | #include <linux/pm_runtime.h> |
---|
| 23 | +#include <linux/regulator/consumer.h> |
---|
19 | 24 | #include <linux/serdev.h> |
---|
20 | 25 | #include <linux/skbuff.h> |
---|
21 | 26 | |
---|
.. | .. |
---|
24 | 29 | |
---|
25 | 30 | #include "h4_recv.h" |
---|
26 | 31 | |
---|
27 | | -#define VERSION "0.1" |
---|
| 32 | +#define VERSION "0.2" |
---|
28 | 33 | |
---|
29 | 34 | #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin" |
---|
| 35 | +#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" |
---|
| 36 | +#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" |
---|
30 | 37 | |
---|
31 | 38 | #define MTK_STP_TLR_SIZE 2 |
---|
32 | 39 | |
---|
33 | 40 | #define BTMTKUART_TX_STATE_ACTIVE 1 |
---|
34 | 41 | #define BTMTKUART_TX_STATE_WAKEUP 2 |
---|
35 | 42 | #define BTMTKUART_TX_WAIT_VND_EVT 3 |
---|
| 43 | +#define BTMTKUART_REQUIRED_WAKEUP 4 |
---|
| 44 | + |
---|
| 45 | +#define BTMTKUART_FLAG_STANDALONE_HW BIT(0) |
---|
36 | 46 | |
---|
37 | 47 | enum { |
---|
38 | 48 | MTK_WMT_PATCH_DWNLD = 0x1, |
---|
| 49 | + MTK_WMT_TEST = 0x2, |
---|
| 50 | + MTK_WMT_WAKEUP = 0x3, |
---|
| 51 | + MTK_WMT_HIF = 0x4, |
---|
39 | 52 | MTK_WMT_FUNC_CTRL = 0x6, |
---|
40 | | - MTK_WMT_RST = 0x7 |
---|
| 53 | + MTK_WMT_RST = 0x7, |
---|
| 54 | + MTK_WMT_SEMAPHORE = 0x17, |
---|
| 55 | +}; |
---|
| 56 | + |
---|
| 57 | +enum { |
---|
| 58 | + BTMTK_WMT_INVALID, |
---|
| 59 | + BTMTK_WMT_PATCH_UNDONE, |
---|
| 60 | + BTMTK_WMT_PATCH_DONE, |
---|
| 61 | + BTMTK_WMT_ON_UNDONE, |
---|
| 62 | + BTMTK_WMT_ON_DONE, |
---|
| 63 | + BTMTK_WMT_ON_PROGRESS, |
---|
41 | 64 | }; |
---|
42 | 65 | |
---|
43 | 66 | struct mtk_stp_hdr { |
---|
.. | .. |
---|
45 | 68 | __be16 dlen; |
---|
46 | 69 | u8 cs; |
---|
47 | 70 | } __packed; |
---|
| 71 | + |
---|
| 72 | +struct btmtkuart_data { |
---|
| 73 | + unsigned int flags; |
---|
| 74 | + const char *fwname; |
---|
| 75 | +}; |
---|
48 | 76 | |
---|
49 | 77 | struct mtk_wmt_hdr { |
---|
50 | 78 | u8 dir; |
---|
.. | .. |
---|
58 | 86 | u8 data[256]; |
---|
59 | 87 | } __packed; |
---|
60 | 88 | |
---|
| 89 | +struct btmtk_hci_wmt_evt { |
---|
| 90 | + struct hci_event_hdr hhdr; |
---|
| 91 | + struct mtk_wmt_hdr whdr; |
---|
| 92 | +} __packed; |
---|
| 93 | + |
---|
| 94 | +struct btmtk_hci_wmt_evt_funcc { |
---|
| 95 | + struct btmtk_hci_wmt_evt hwhdr; |
---|
| 96 | + __be16 status; |
---|
| 97 | +} __packed; |
---|
| 98 | + |
---|
| 99 | +struct btmtk_tci_sleep { |
---|
| 100 | + u8 mode; |
---|
| 101 | + __le16 duration; |
---|
| 102 | + __le16 host_duration; |
---|
| 103 | + u8 host_wakeup_pin; |
---|
| 104 | + u8 time_compensation; |
---|
| 105 | +} __packed; |
---|
| 106 | + |
---|
| 107 | +struct btmtk_hci_wmt_params { |
---|
| 108 | + u8 op; |
---|
| 109 | + u8 flag; |
---|
| 110 | + u16 dlen; |
---|
| 111 | + const void *data; |
---|
| 112 | + u32 *status; |
---|
| 113 | +}; |
---|
| 114 | + |
---|
61 | 115 | struct btmtkuart_dev { |
---|
62 | 116 | struct hci_dev *hdev; |
---|
63 | 117 | struct serdev_device *serdev; |
---|
| 118 | + |
---|
64 | 119 | struct clk *clk; |
---|
| 120 | + struct clk *osc; |
---|
| 121 | + struct regulator *vcc; |
---|
| 122 | + struct gpio_desc *reset; |
---|
| 123 | + struct gpio_desc *boot; |
---|
| 124 | + struct pinctrl *pinctrl; |
---|
| 125 | + struct pinctrl_state *pins_runtime; |
---|
| 126 | + struct pinctrl_state *pins_boot; |
---|
| 127 | + speed_t desired_speed; |
---|
| 128 | + speed_t curr_speed; |
---|
65 | 129 | |
---|
66 | 130 | struct work_struct tx_work; |
---|
67 | 131 | unsigned long tx_state; |
---|
68 | 132 | struct sk_buff_head txq; |
---|
69 | 133 | |
---|
70 | 134 | struct sk_buff *rx_skb; |
---|
| 135 | + struct sk_buff *evt_skb; |
---|
71 | 136 | |
---|
72 | 137 | u8 stp_pad[6]; |
---|
73 | 138 | u8 stp_cursor; |
---|
74 | 139 | u16 stp_dlen; |
---|
| 140 | + |
---|
| 141 | + const struct btmtkuart_data *data; |
---|
75 | 142 | }; |
---|
76 | 143 | |
---|
77 | | -static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, |
---|
78 | | - const void *param) |
---|
| 144 | +#define btmtkuart_is_standalone(bdev) \ |
---|
| 145 | + ((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) |
---|
| 146 | +#define btmtkuart_is_builtin_soc(bdev) \ |
---|
| 147 | + !((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) |
---|
| 148 | + |
---|
| 149 | +static int mtk_hci_wmt_sync(struct hci_dev *hdev, |
---|
| 150 | + struct btmtk_hci_wmt_params *wmt_params) |
---|
79 | 151 | { |
---|
80 | 152 | struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); |
---|
| 153 | + struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; |
---|
| 154 | + u32 hlen, status = BTMTK_WMT_INVALID; |
---|
| 155 | + struct btmtk_hci_wmt_evt *wmt_evt; |
---|
81 | 156 | struct mtk_hci_wmt_cmd wc; |
---|
82 | 157 | struct mtk_wmt_hdr *hdr; |
---|
83 | | - u32 hlen; |
---|
84 | 158 | int err; |
---|
85 | 159 | |
---|
86 | | - hlen = sizeof(*hdr) + plen; |
---|
87 | | - if (hlen > 255) |
---|
88 | | - return -EINVAL; |
---|
| 160 | + hlen = sizeof(*hdr) + wmt_params->dlen; |
---|
| 161 | + if (hlen > 255) { |
---|
| 162 | + err = -EINVAL; |
---|
| 163 | + goto err_free_skb; |
---|
| 164 | + } |
---|
89 | 165 | |
---|
90 | 166 | hdr = (struct mtk_wmt_hdr *)&wc; |
---|
91 | 167 | hdr->dir = 1; |
---|
92 | | - hdr->op = op; |
---|
93 | | - hdr->dlen = cpu_to_le16(plen + 1); |
---|
94 | | - hdr->flag = flag; |
---|
95 | | - memcpy(wc.data, param, plen); |
---|
| 168 | + hdr->op = wmt_params->op; |
---|
| 169 | + hdr->dlen = cpu_to_le16(wmt_params->dlen + 1); |
---|
| 170 | + hdr->flag = wmt_params->flag; |
---|
| 171 | + memcpy(wc.data, wmt_params->data, wmt_params->dlen); |
---|
96 | 172 | |
---|
97 | 173 | set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); |
---|
98 | 174 | |
---|
99 | 175 | err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); |
---|
100 | 176 | if (err < 0) { |
---|
101 | 177 | clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); |
---|
102 | | - return err; |
---|
| 178 | + goto err_free_skb; |
---|
103 | 179 | } |
---|
104 | 180 | |
---|
105 | 181 | /* The vendor specific WMT commands are all answered by a vendor |
---|
.. | .. |
---|
107 | 183 | * Complete as with usual HCI command flow control. |
---|
108 | 184 | * |
---|
109 | 185 | * After sending the command, wait for BTMTKUART_TX_WAIT_VND_EVT |
---|
110 | | - * state to be cleared. The driver speicfic event receive routine |
---|
| 186 | + * state to be cleared. The driver specific event receive routine |
---|
111 | 187 | * will clear that state and with that indicate completion of the |
---|
112 | 188 | * WMT command. |
---|
113 | 189 | */ |
---|
.. | .. |
---|
116 | 192 | if (err == -EINTR) { |
---|
117 | 193 | bt_dev_err(hdev, "Execution of wmt command interrupted"); |
---|
118 | 194 | clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); |
---|
119 | | - return err; |
---|
| 195 | + goto err_free_skb; |
---|
120 | 196 | } |
---|
121 | 197 | |
---|
122 | 198 | if (err) { |
---|
123 | 199 | bt_dev_err(hdev, "Execution of wmt command timed out"); |
---|
124 | 200 | clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); |
---|
125 | | - return -ETIMEDOUT; |
---|
| 201 | + err = -ETIMEDOUT; |
---|
| 202 | + goto err_free_skb; |
---|
126 | 203 | } |
---|
127 | 204 | |
---|
128 | | - return 0; |
---|
| 205 | + /* Parse and handle the return WMT event */ |
---|
| 206 | + wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data; |
---|
| 207 | + if (wmt_evt->whdr.op != hdr->op) { |
---|
| 208 | + bt_dev_err(hdev, "Wrong op received %d expected %d", |
---|
| 209 | + wmt_evt->whdr.op, hdr->op); |
---|
| 210 | + err = -EIO; |
---|
| 211 | + goto err_free_skb; |
---|
| 212 | + } |
---|
| 213 | + |
---|
| 214 | + switch (wmt_evt->whdr.op) { |
---|
| 215 | + case MTK_WMT_SEMAPHORE: |
---|
| 216 | + if (wmt_evt->whdr.flag == 2) |
---|
| 217 | + status = BTMTK_WMT_PATCH_UNDONE; |
---|
| 218 | + else |
---|
| 219 | + status = BTMTK_WMT_PATCH_DONE; |
---|
| 220 | + break; |
---|
| 221 | + case MTK_WMT_FUNC_CTRL: |
---|
| 222 | + wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; |
---|
| 223 | + if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) |
---|
| 224 | + status = BTMTK_WMT_ON_DONE; |
---|
| 225 | + else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420) |
---|
| 226 | + status = BTMTK_WMT_ON_PROGRESS; |
---|
| 227 | + else |
---|
| 228 | + status = BTMTK_WMT_ON_UNDONE; |
---|
| 229 | + break; |
---|
| 230 | + } |
---|
| 231 | + |
---|
| 232 | + if (wmt_params->status) |
---|
| 233 | + *wmt_params->status = status; |
---|
| 234 | + |
---|
| 235 | +err_free_skb: |
---|
| 236 | + kfree_skb(bdev->evt_skb); |
---|
| 237 | + bdev->evt_skb = NULL; |
---|
| 238 | + |
---|
| 239 | + return err; |
---|
129 | 240 | } |
---|
130 | 241 | |
---|
131 | | -static int mtk_setup_fw(struct hci_dev *hdev) |
---|
| 242 | +static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) |
---|
132 | 243 | { |
---|
| 244 | + struct btmtk_hci_wmt_params wmt_params; |
---|
133 | 245 | const struct firmware *fw; |
---|
134 | 246 | const u8 *fw_ptr; |
---|
135 | 247 | size_t fw_size; |
---|
136 | 248 | int err, dlen; |
---|
137 | 249 | u8 flag; |
---|
138 | 250 | |
---|
139 | | - err = request_firmware(&fw, FIRMWARE_MT7622, &hdev->dev); |
---|
| 251 | + err = request_firmware(&fw, fwname, &hdev->dev); |
---|
140 | 252 | if (err < 0) { |
---|
141 | 253 | bt_dev_err(hdev, "Failed to load firmware file (%d)", err); |
---|
142 | 254 | return err; |
---|
.. | .. |
---|
155 | 267 | fw_ptr += 30; |
---|
156 | 268 | flag = 1; |
---|
157 | 269 | |
---|
| 270 | + wmt_params.op = MTK_WMT_PATCH_DWNLD; |
---|
| 271 | + wmt_params.status = NULL; |
---|
| 272 | + |
---|
158 | 273 | while (fw_size > 0) { |
---|
159 | 274 | dlen = min_t(int, 250, fw_size); |
---|
160 | 275 | |
---|
.. | .. |
---|
164 | 279 | else if (fw_size < fw->size - 30) |
---|
165 | 280 | flag = 2; |
---|
166 | 281 | |
---|
167 | | - err = mtk_hci_wmt_sync(hdev, MTK_WMT_PATCH_DWNLD, flag, dlen, |
---|
168 | | - fw_ptr); |
---|
| 282 | + wmt_params.flag = flag; |
---|
| 283 | + wmt_params.dlen = dlen; |
---|
| 284 | + wmt_params.data = fw_ptr; |
---|
| 285 | + |
---|
| 286 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
169 | 287 | if (err < 0) { |
---|
170 | 288 | bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", |
---|
171 | 289 | err); |
---|
172 | | - break; |
---|
| 290 | + goto free_fw; |
---|
173 | 291 | } |
---|
174 | 292 | |
---|
175 | 293 | fw_size -= dlen; |
---|
176 | 294 | fw_ptr += dlen; |
---|
177 | 295 | } |
---|
| 296 | + |
---|
| 297 | + wmt_params.op = MTK_WMT_RST; |
---|
| 298 | + wmt_params.flag = 4; |
---|
| 299 | + wmt_params.dlen = 0; |
---|
| 300 | + wmt_params.data = NULL; |
---|
| 301 | + wmt_params.status = NULL; |
---|
| 302 | + |
---|
| 303 | + /* Activate funciton the firmware providing to */ |
---|
| 304 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
| 305 | + if (err < 0) { |
---|
| 306 | + bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); |
---|
| 307 | + goto free_fw; |
---|
| 308 | + } |
---|
| 309 | + |
---|
| 310 | + /* Wait a few moments for firmware activation done */ |
---|
| 311 | + usleep_range(10000, 12000); |
---|
178 | 312 | |
---|
179 | 313 | free_fw: |
---|
180 | 314 | release_firmware(fw); |
---|
.. | .. |
---|
194 | 328 | if (hdr->evt == 0xe4) |
---|
195 | 329 | hdr->evt = HCI_EV_VENDOR; |
---|
196 | 330 | |
---|
| 331 | + /* When someone waits for the WMT event, the skb is being cloned |
---|
| 332 | + * and being processed the events from there then. |
---|
| 333 | + */ |
---|
| 334 | + if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) { |
---|
| 335 | + bdev->evt_skb = skb_clone(skb, GFP_KERNEL); |
---|
| 336 | + if (!bdev->evt_skb) { |
---|
| 337 | + err = -ENOMEM; |
---|
| 338 | + goto err_out; |
---|
| 339 | + } |
---|
| 340 | + } |
---|
| 341 | + |
---|
197 | 342 | err = hci_recv_frame(hdev, skb); |
---|
| 343 | + if (err < 0) |
---|
| 344 | + goto err_free_skb; |
---|
198 | 345 | |
---|
199 | 346 | if (hdr->evt == HCI_EV_VENDOR) { |
---|
200 | 347 | if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, |
---|
.. | .. |
---|
205 | 352 | } |
---|
206 | 353 | } |
---|
207 | 354 | |
---|
| 355 | + return 0; |
---|
| 356 | + |
---|
| 357 | +err_free_skb: |
---|
| 358 | + kfree_skb(bdev->evt_skb); |
---|
| 359 | + bdev->evt_skb = NULL; |
---|
| 360 | + |
---|
| 361 | +err_out: |
---|
208 | 362 | return err; |
---|
209 | 363 | } |
---|
210 | 364 | |
---|
.. | .. |
---|
406 | 560 | goto err_open; |
---|
407 | 561 | } |
---|
408 | 562 | |
---|
| 563 | + if (btmtkuart_is_standalone(bdev)) { |
---|
| 564 | + if (bdev->curr_speed != bdev->desired_speed) |
---|
| 565 | + err = serdev_device_set_baudrate(bdev->serdev, |
---|
| 566 | + 115200); |
---|
| 567 | + else |
---|
| 568 | + err = serdev_device_set_baudrate(bdev->serdev, |
---|
| 569 | + bdev->desired_speed); |
---|
| 570 | + |
---|
| 571 | + if (err < 0) { |
---|
| 572 | + bt_dev_err(hdev, "Unable to set baudrate UART device %s", |
---|
| 573 | + dev_name(&bdev->serdev->dev)); |
---|
| 574 | + goto err_serdev_close; |
---|
| 575 | + } |
---|
| 576 | + |
---|
| 577 | + serdev_device_set_flow_control(bdev->serdev, false); |
---|
| 578 | + } |
---|
| 579 | + |
---|
409 | 580 | bdev->stp_cursor = 2; |
---|
410 | 581 | bdev->stp_dlen = 0; |
---|
411 | 582 | |
---|
.. | .. |
---|
429 | 600 | pm_runtime_put_sync(dev); |
---|
430 | 601 | err_disable_rpm: |
---|
431 | 602 | pm_runtime_disable(dev); |
---|
| 603 | +err_serdev_close: |
---|
| 604 | + serdev_device_close(bdev->serdev); |
---|
432 | 605 | err_open: |
---|
433 | 606 | return err; |
---|
434 | 607 | } |
---|
.. | .. |
---|
467 | 640 | return 0; |
---|
468 | 641 | } |
---|
469 | 642 | |
---|
470 | | -static int btmtkuart_setup(struct hci_dev *hdev) |
---|
| 643 | +static int btmtkuart_func_query(struct hci_dev *hdev) |
---|
471 | 644 | { |
---|
472 | | - u8 param = 0x1; |
---|
473 | | - int err = 0; |
---|
| 645 | + struct btmtk_hci_wmt_params wmt_params; |
---|
| 646 | + int status, err; |
---|
| 647 | + u8 param = 0; |
---|
474 | 648 | |
---|
475 | | - /* Setup a firmware which the device definitely requires */ |
---|
476 | | - err = mtk_setup_fw(hdev); |
---|
477 | | - if (err < 0) |
---|
478 | | - return err; |
---|
| 649 | + /* Query whether the function is enabled */ |
---|
| 650 | + wmt_params.op = MTK_WMT_FUNC_CTRL; |
---|
| 651 | + wmt_params.flag = 4; |
---|
| 652 | + wmt_params.dlen = sizeof(param); |
---|
| 653 | + wmt_params.data = ¶m; |
---|
| 654 | + wmt_params.status = &status; |
---|
479 | 655 | |
---|
480 | | - /* Activate function the firmware providing to */ |
---|
481 | | - err = mtk_hci_wmt_sync(hdev, MTK_WMT_RST, 0x4, 0, 0); |
---|
| 656 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
482 | 657 | if (err < 0) { |
---|
483 | | - bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); |
---|
| 658 | + bt_dev_err(hdev, "Failed to query function status (%d)", err); |
---|
484 | 659 | return err; |
---|
485 | 660 | } |
---|
486 | 661 | |
---|
| 662 | + return status; |
---|
| 663 | +} |
---|
| 664 | + |
---|
| 665 | +static int btmtkuart_change_baudrate(struct hci_dev *hdev) |
---|
| 666 | +{ |
---|
| 667 | + struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); |
---|
| 668 | + struct btmtk_hci_wmt_params wmt_params; |
---|
| 669 | + __le32 baudrate; |
---|
| 670 | + u8 param; |
---|
| 671 | + int err; |
---|
| 672 | + |
---|
| 673 | + /* Indicate the device to enter the probe state the host is |
---|
| 674 | + * ready to change a new baudrate. |
---|
| 675 | + */ |
---|
| 676 | + baudrate = cpu_to_le32(bdev->desired_speed); |
---|
| 677 | + wmt_params.op = MTK_WMT_HIF; |
---|
| 678 | + wmt_params.flag = 1; |
---|
| 679 | + wmt_params.dlen = 4; |
---|
| 680 | + wmt_params.data = &baudrate; |
---|
| 681 | + wmt_params.status = NULL; |
---|
| 682 | + |
---|
| 683 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
| 684 | + if (err < 0) { |
---|
| 685 | + bt_dev_err(hdev, "Failed to device baudrate (%d)", err); |
---|
| 686 | + return err; |
---|
| 687 | + } |
---|
| 688 | + |
---|
| 689 | + err = serdev_device_set_baudrate(bdev->serdev, |
---|
| 690 | + bdev->desired_speed); |
---|
| 691 | + if (err < 0) { |
---|
| 692 | + bt_dev_err(hdev, "Failed to set up host baudrate (%d)", |
---|
| 693 | + err); |
---|
| 694 | + return err; |
---|
| 695 | + } |
---|
| 696 | + |
---|
| 697 | + serdev_device_set_flow_control(bdev->serdev, false); |
---|
| 698 | + |
---|
| 699 | + /* Send a dummy byte 0xff to activate the new baudrate */ |
---|
| 700 | + param = 0xff; |
---|
| 701 | + err = serdev_device_write_buf(bdev->serdev, ¶m, sizeof(param)); |
---|
| 702 | + if (err < 0 || err < sizeof(param)) |
---|
| 703 | + return err; |
---|
| 704 | + |
---|
| 705 | + serdev_device_wait_until_sent(bdev->serdev, 0); |
---|
| 706 | + |
---|
| 707 | + /* Wait some time for the device changing baudrate done */ |
---|
| 708 | + usleep_range(20000, 22000); |
---|
| 709 | + |
---|
| 710 | + /* Test the new baudrate */ |
---|
| 711 | + wmt_params.op = MTK_WMT_TEST; |
---|
| 712 | + wmt_params.flag = 7; |
---|
| 713 | + wmt_params.dlen = 0; |
---|
| 714 | + wmt_params.data = NULL; |
---|
| 715 | + wmt_params.status = NULL; |
---|
| 716 | + |
---|
| 717 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
| 718 | + if (err < 0) { |
---|
| 719 | + bt_dev_err(hdev, "Failed to test new baudrate (%d)", |
---|
| 720 | + err); |
---|
| 721 | + return err; |
---|
| 722 | + } |
---|
| 723 | + |
---|
| 724 | + bdev->curr_speed = bdev->desired_speed; |
---|
| 725 | + |
---|
| 726 | + return 0; |
---|
| 727 | +} |
---|
| 728 | + |
---|
| 729 | +static int btmtkuart_setup(struct hci_dev *hdev) |
---|
| 730 | +{ |
---|
| 731 | + struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); |
---|
| 732 | + struct btmtk_hci_wmt_params wmt_params; |
---|
| 733 | + ktime_t calltime, delta, rettime; |
---|
| 734 | + struct btmtk_tci_sleep tci_sleep; |
---|
| 735 | + unsigned long long duration; |
---|
| 736 | + struct sk_buff *skb; |
---|
| 737 | + int err, status; |
---|
| 738 | + u8 param = 0x1; |
---|
| 739 | + |
---|
| 740 | + calltime = ktime_get(); |
---|
| 741 | + |
---|
| 742 | + /* Wakeup MCUSYS is required for certain devices before we start to |
---|
| 743 | + * do any setups. |
---|
| 744 | + */ |
---|
| 745 | + if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) { |
---|
| 746 | + wmt_params.op = MTK_WMT_WAKEUP; |
---|
| 747 | + wmt_params.flag = 3; |
---|
| 748 | + wmt_params.dlen = 0; |
---|
| 749 | + wmt_params.data = NULL; |
---|
| 750 | + wmt_params.status = NULL; |
---|
| 751 | + |
---|
| 752 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
| 753 | + if (err < 0) { |
---|
| 754 | + bt_dev_err(hdev, "Failed to wakeup the chip (%d)", err); |
---|
| 755 | + return err; |
---|
| 756 | + } |
---|
| 757 | + |
---|
| 758 | + clear_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); |
---|
| 759 | + } |
---|
| 760 | + |
---|
| 761 | + if (btmtkuart_is_standalone(bdev)) |
---|
| 762 | + btmtkuart_change_baudrate(hdev); |
---|
| 763 | + |
---|
| 764 | + /* Query whether the firmware is already download */ |
---|
| 765 | + wmt_params.op = MTK_WMT_SEMAPHORE; |
---|
| 766 | + wmt_params.flag = 1; |
---|
| 767 | + wmt_params.dlen = 0; |
---|
| 768 | + wmt_params.data = NULL; |
---|
| 769 | + wmt_params.status = &status; |
---|
| 770 | + |
---|
| 771 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
| 772 | + if (err < 0) { |
---|
| 773 | + bt_dev_err(hdev, "Failed to query firmware status (%d)", err); |
---|
| 774 | + return err; |
---|
| 775 | + } |
---|
| 776 | + |
---|
| 777 | + if (status == BTMTK_WMT_PATCH_DONE) { |
---|
| 778 | + bt_dev_info(hdev, "Firmware already downloaded"); |
---|
| 779 | + goto ignore_setup_fw; |
---|
| 780 | + } |
---|
| 781 | + |
---|
| 782 | + /* Setup a firmware which the device definitely requires */ |
---|
| 783 | + err = mtk_setup_firmware(hdev, bdev->data->fwname); |
---|
| 784 | + if (err < 0) |
---|
| 785 | + return err; |
---|
| 786 | + |
---|
| 787 | +ignore_setup_fw: |
---|
| 788 | + /* Query whether the device is already enabled */ |
---|
| 789 | + err = readx_poll_timeout(btmtkuart_func_query, hdev, status, |
---|
| 790 | + status < 0 || status != BTMTK_WMT_ON_PROGRESS, |
---|
| 791 | + 2000, 5000000); |
---|
| 792 | + /* -ETIMEDOUT happens */ |
---|
| 793 | + if (err < 0) |
---|
| 794 | + return err; |
---|
| 795 | + |
---|
| 796 | + /* The other errors happen in btusb_mtk_func_query */ |
---|
| 797 | + if (status < 0) |
---|
| 798 | + return status; |
---|
| 799 | + |
---|
| 800 | + if (status == BTMTK_WMT_ON_DONE) { |
---|
| 801 | + bt_dev_info(hdev, "function already on"); |
---|
| 802 | + goto ignore_func_on; |
---|
| 803 | + } |
---|
| 804 | + |
---|
487 | 805 | /* Enable Bluetooth protocol */ |
---|
488 | | - err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), |
---|
489 | | - ¶m); |
---|
| 806 | + wmt_params.op = MTK_WMT_FUNC_CTRL; |
---|
| 807 | + wmt_params.flag = 0; |
---|
| 808 | + wmt_params.dlen = sizeof(param); |
---|
| 809 | + wmt_params.data = ¶m; |
---|
| 810 | + wmt_params.status = NULL; |
---|
| 811 | + |
---|
| 812 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
490 | 813 | if (err < 0) { |
---|
491 | 814 | bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); |
---|
492 | 815 | return err; |
---|
493 | 816 | } |
---|
| 817 | + |
---|
| 818 | +ignore_func_on: |
---|
| 819 | + /* Apply the low power environment setup */ |
---|
| 820 | + tci_sleep.mode = 0x5; |
---|
| 821 | + tci_sleep.duration = cpu_to_le16(0x640); |
---|
| 822 | + tci_sleep.host_duration = cpu_to_le16(0x640); |
---|
| 823 | + tci_sleep.host_wakeup_pin = 0; |
---|
| 824 | + tci_sleep.time_compensation = 0; |
---|
| 825 | + |
---|
| 826 | + skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep, |
---|
| 827 | + HCI_INIT_TIMEOUT); |
---|
| 828 | + if (IS_ERR(skb)) { |
---|
| 829 | + err = PTR_ERR(skb); |
---|
| 830 | + bt_dev_err(hdev, "Failed to apply low power setting (%d)", err); |
---|
| 831 | + return err; |
---|
| 832 | + } |
---|
| 833 | + kfree_skb(skb); |
---|
| 834 | + |
---|
| 835 | + rettime = ktime_get(); |
---|
| 836 | + delta = ktime_sub(rettime, calltime); |
---|
| 837 | + duration = (unsigned long long)ktime_to_ns(delta) >> 10; |
---|
| 838 | + |
---|
| 839 | + bt_dev_info(hdev, "Device setup in %llu usecs", duration); |
---|
494 | 840 | |
---|
495 | 841 | return 0; |
---|
496 | 842 | } |
---|
497 | 843 | |
---|
498 | 844 | static int btmtkuart_shutdown(struct hci_dev *hdev) |
---|
499 | 845 | { |
---|
| 846 | + struct btmtk_hci_wmt_params wmt_params; |
---|
500 | 847 | u8 param = 0x0; |
---|
501 | 848 | int err; |
---|
502 | 849 | |
---|
503 | 850 | /* Disable the device */ |
---|
504 | | - err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), |
---|
505 | | - ¶m); |
---|
| 851 | + wmt_params.op = MTK_WMT_FUNC_CTRL; |
---|
| 852 | + wmt_params.flag = 0; |
---|
| 853 | + wmt_params.dlen = sizeof(param); |
---|
| 854 | + wmt_params.data = ¶m; |
---|
| 855 | + wmt_params.status = NULL; |
---|
| 856 | + |
---|
| 857 | + err = mtk_hci_wmt_sync(hdev, &wmt_params); |
---|
506 | 858 | if (err < 0) { |
---|
507 | 859 | bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); |
---|
508 | 860 | return err; |
---|
.. | .. |
---|
545 | 897 | return 0; |
---|
546 | 898 | } |
---|
547 | 899 | |
---|
| 900 | +static int btmtkuart_parse_dt(struct serdev_device *serdev) |
---|
| 901 | +{ |
---|
| 902 | + struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); |
---|
| 903 | + struct device_node *node = serdev->dev.of_node; |
---|
| 904 | + u32 speed = 921600; |
---|
| 905 | + int err; |
---|
| 906 | + |
---|
| 907 | + if (btmtkuart_is_standalone(bdev)) { |
---|
| 908 | + of_property_read_u32(node, "current-speed", &speed); |
---|
| 909 | + |
---|
| 910 | + bdev->desired_speed = speed; |
---|
| 911 | + |
---|
| 912 | + bdev->vcc = devm_regulator_get(&serdev->dev, "vcc"); |
---|
| 913 | + if (IS_ERR(bdev->vcc)) { |
---|
| 914 | + err = PTR_ERR(bdev->vcc); |
---|
| 915 | + return err; |
---|
| 916 | + } |
---|
| 917 | + |
---|
| 918 | + bdev->osc = devm_clk_get_optional(&serdev->dev, "osc"); |
---|
| 919 | + if (IS_ERR(bdev->osc)) { |
---|
| 920 | + err = PTR_ERR(bdev->osc); |
---|
| 921 | + return err; |
---|
| 922 | + } |
---|
| 923 | + |
---|
| 924 | + bdev->boot = devm_gpiod_get_optional(&serdev->dev, "boot", |
---|
| 925 | + GPIOD_OUT_LOW); |
---|
| 926 | + if (IS_ERR(bdev->boot)) { |
---|
| 927 | + err = PTR_ERR(bdev->boot); |
---|
| 928 | + return err; |
---|
| 929 | + } |
---|
| 930 | + |
---|
| 931 | + bdev->pinctrl = devm_pinctrl_get(&serdev->dev); |
---|
| 932 | + if (IS_ERR(bdev->pinctrl)) { |
---|
| 933 | + err = PTR_ERR(bdev->pinctrl); |
---|
| 934 | + return err; |
---|
| 935 | + } |
---|
| 936 | + |
---|
| 937 | + bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl, |
---|
| 938 | + "default"); |
---|
| 939 | + if (IS_ERR(bdev->pins_boot) && !bdev->boot) { |
---|
| 940 | + err = PTR_ERR(bdev->pins_boot); |
---|
| 941 | + dev_err(&serdev->dev, |
---|
| 942 | + "Should assign RXD to LOW at boot stage\n"); |
---|
| 943 | + return err; |
---|
| 944 | + } |
---|
| 945 | + |
---|
| 946 | + bdev->pins_runtime = pinctrl_lookup_state(bdev->pinctrl, |
---|
| 947 | + "runtime"); |
---|
| 948 | + if (IS_ERR(bdev->pins_runtime)) { |
---|
| 949 | + err = PTR_ERR(bdev->pins_runtime); |
---|
| 950 | + return err; |
---|
| 951 | + } |
---|
| 952 | + |
---|
| 953 | + bdev->reset = devm_gpiod_get_optional(&serdev->dev, "reset", |
---|
| 954 | + GPIOD_OUT_LOW); |
---|
| 955 | + if (IS_ERR(bdev->reset)) { |
---|
| 956 | + err = PTR_ERR(bdev->reset); |
---|
| 957 | + return err; |
---|
| 958 | + } |
---|
| 959 | + } else if (btmtkuart_is_builtin_soc(bdev)) { |
---|
| 960 | + bdev->clk = devm_clk_get(&serdev->dev, "ref"); |
---|
| 961 | + if (IS_ERR(bdev->clk)) |
---|
| 962 | + return PTR_ERR(bdev->clk); |
---|
| 963 | + } |
---|
| 964 | + |
---|
| 965 | + return 0; |
---|
| 966 | +} |
---|
| 967 | + |
---|
548 | 968 | static int btmtkuart_probe(struct serdev_device *serdev) |
---|
549 | 969 | { |
---|
550 | 970 | struct btmtkuart_dev *bdev; |
---|
551 | 971 | struct hci_dev *hdev; |
---|
| 972 | + int err; |
---|
552 | 973 | |
---|
553 | 974 | bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL); |
---|
554 | 975 | if (!bdev) |
---|
555 | 976 | return -ENOMEM; |
---|
556 | 977 | |
---|
557 | | - bdev->clk = devm_clk_get(&serdev->dev, "ref"); |
---|
558 | | - if (IS_ERR(bdev->clk)) |
---|
559 | | - return PTR_ERR(bdev->clk); |
---|
| 978 | + bdev->data = of_device_get_match_data(&serdev->dev); |
---|
| 979 | + if (!bdev->data) |
---|
| 980 | + return -ENODEV; |
---|
560 | 981 | |
---|
561 | 982 | bdev->serdev = serdev; |
---|
562 | 983 | serdev_device_set_drvdata(serdev, bdev); |
---|
563 | 984 | |
---|
564 | 985 | serdev_device_set_client_ops(serdev, &btmtkuart_client_ops); |
---|
| 986 | + |
---|
| 987 | + err = btmtkuart_parse_dt(serdev); |
---|
| 988 | + if (err < 0) |
---|
| 989 | + return err; |
---|
565 | 990 | |
---|
566 | 991 | INIT_WORK(&bdev->tx_work, btmtkuart_tx_work); |
---|
567 | 992 | skb_queue_head_init(&bdev->txq); |
---|
.. | .. |
---|
589 | 1014 | hdev->manufacturer = 70; |
---|
590 | 1015 | set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); |
---|
591 | 1016 | |
---|
592 | | - if (hci_register_dev(hdev) < 0) { |
---|
| 1017 | + if (btmtkuart_is_standalone(bdev)) { |
---|
| 1018 | + err = clk_prepare_enable(bdev->osc); |
---|
| 1019 | + if (err < 0) |
---|
| 1020 | + goto err_hci_free_dev; |
---|
| 1021 | + |
---|
| 1022 | + if (bdev->boot) { |
---|
| 1023 | + gpiod_set_value_cansleep(bdev->boot, 1); |
---|
| 1024 | + } else { |
---|
| 1025 | + /* Switch to the specific pin state for the booting |
---|
| 1026 | + * requires. |
---|
| 1027 | + */ |
---|
| 1028 | + pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); |
---|
| 1029 | + } |
---|
| 1030 | + |
---|
| 1031 | + /* Power on */ |
---|
| 1032 | + err = regulator_enable(bdev->vcc); |
---|
| 1033 | + if (err < 0) |
---|
| 1034 | + goto err_clk_disable_unprepare; |
---|
| 1035 | + |
---|
| 1036 | + /* Reset if the reset-gpios is available otherwise the board |
---|
| 1037 | + * -level design should be guaranteed. |
---|
| 1038 | + */ |
---|
| 1039 | + if (bdev->reset) { |
---|
| 1040 | + gpiod_set_value_cansleep(bdev->reset, 1); |
---|
| 1041 | + usleep_range(1000, 2000); |
---|
| 1042 | + gpiod_set_value_cansleep(bdev->reset, 0); |
---|
| 1043 | + } |
---|
| 1044 | + |
---|
| 1045 | + /* Wait some time until device got ready and switch to the pin |
---|
| 1046 | + * mode the device requires for UART transfers. |
---|
| 1047 | + */ |
---|
| 1048 | + msleep(50); |
---|
| 1049 | + |
---|
| 1050 | + if (bdev->boot) |
---|
| 1051 | + devm_gpiod_put(&serdev->dev, bdev->boot); |
---|
| 1052 | + |
---|
| 1053 | + pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime); |
---|
| 1054 | + |
---|
| 1055 | + /* A standalone device doesn't depends on power domain on SoC, |
---|
| 1056 | + * so mark it as no callbacks. |
---|
| 1057 | + */ |
---|
| 1058 | + pm_runtime_no_callbacks(&serdev->dev); |
---|
| 1059 | + |
---|
| 1060 | + set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); |
---|
| 1061 | + } |
---|
| 1062 | + |
---|
| 1063 | + err = hci_register_dev(hdev); |
---|
| 1064 | + if (err < 0) { |
---|
593 | 1065 | dev_err(&serdev->dev, "Can't register HCI device\n"); |
---|
594 | | - hci_free_dev(hdev); |
---|
595 | | - return -ENODEV; |
---|
| 1066 | + goto err_regulator_disable; |
---|
596 | 1067 | } |
---|
597 | 1068 | |
---|
598 | 1069 | return 0; |
---|
| 1070 | + |
---|
| 1071 | +err_regulator_disable: |
---|
| 1072 | + if (btmtkuart_is_standalone(bdev)) |
---|
| 1073 | + regulator_disable(bdev->vcc); |
---|
| 1074 | +err_clk_disable_unprepare: |
---|
| 1075 | + if (btmtkuart_is_standalone(bdev)) |
---|
| 1076 | + clk_disable_unprepare(bdev->osc); |
---|
| 1077 | +err_hci_free_dev: |
---|
| 1078 | + hci_free_dev(hdev); |
---|
| 1079 | + |
---|
| 1080 | + return err; |
---|
599 | 1081 | } |
---|
600 | 1082 | |
---|
601 | 1083 | static void btmtkuart_remove(struct serdev_device *serdev) |
---|
.. | .. |
---|
603 | 1085 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); |
---|
604 | 1086 | struct hci_dev *hdev = bdev->hdev; |
---|
605 | 1087 | |
---|
| 1088 | + if (btmtkuart_is_standalone(bdev)) { |
---|
| 1089 | + regulator_disable(bdev->vcc); |
---|
| 1090 | + clk_disable_unprepare(bdev->osc); |
---|
| 1091 | + } |
---|
| 1092 | + |
---|
606 | 1093 | hci_unregister_dev(hdev); |
---|
607 | 1094 | hci_free_dev(hdev); |
---|
608 | 1095 | } |
---|
609 | 1096 | |
---|
| 1097 | +static const struct btmtkuart_data mt7622_data = { |
---|
| 1098 | + .fwname = FIRMWARE_MT7622, |
---|
| 1099 | +}; |
---|
| 1100 | + |
---|
| 1101 | +static const struct btmtkuart_data mt7663_data = { |
---|
| 1102 | + .flags = BTMTKUART_FLAG_STANDALONE_HW, |
---|
| 1103 | + .fwname = FIRMWARE_MT7663, |
---|
| 1104 | +}; |
---|
| 1105 | + |
---|
| 1106 | +static const struct btmtkuart_data mt7668_data = { |
---|
| 1107 | + .flags = BTMTKUART_FLAG_STANDALONE_HW, |
---|
| 1108 | + .fwname = FIRMWARE_MT7668, |
---|
| 1109 | +}; |
---|
| 1110 | + |
---|
610 | 1111 | #ifdef CONFIG_OF |
---|
611 | 1112 | static const struct of_device_id mtk_of_match_table[] = { |
---|
612 | | - { .compatible = "mediatek,mt7622-bluetooth"}, |
---|
| 1113 | + { .compatible = "mediatek,mt7622-bluetooth", .data = &mt7622_data}, |
---|
| 1114 | + { .compatible = "mediatek,mt7663u-bluetooth", .data = &mt7663_data}, |
---|
| 1115 | + { .compatible = "mediatek,mt7668u-bluetooth", .data = &mt7668_data}, |
---|
613 | 1116 | { } |
---|
614 | 1117 | }; |
---|
615 | 1118 | MODULE_DEVICE_TABLE(of, mtk_of_match_table); |
---|
.. | .. |
---|
631 | 1134 | MODULE_VERSION(VERSION); |
---|
632 | 1135 | MODULE_LICENSE("GPL"); |
---|
633 | 1136 | MODULE_FIRMWARE(FIRMWARE_MT7622); |
---|
| 1137 | +MODULE_FIRMWARE(FIRMWARE_MT7663); |
---|
| 1138 | +MODULE_FIRMWARE(FIRMWARE_MT7668); |
---|