diff options
Diffstat (limited to 'drivers/bluetooth/btmtkuart.c')
-rw-r--r-- | drivers/bluetooth/btmtkuart.c | 281 |
1 files changed, 271 insertions, 10 deletions
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index e73b1013ba73..b0b680dd69f4 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c | |||
@@ -12,11 +12,15 @@ | |||
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/gpio/consumer.h> | ||
15 | #include <linux/iopoll.h> | 16 | #include <linux/iopoll.h> |
16 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_device.h> | ||
21 | #include <linux/pinctrl/consumer.h> | ||
19 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
23 | #include <linux/regulator/consumer.h> | ||
20 | #include <linux/serdev.h> | 24 | #include <linux/serdev.h> |
21 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
22 | 26 | ||
@@ -25,18 +29,26 @@ | |||
25 | 29 | ||
26 | #include "h4_recv.h" | 30 | #include "h4_recv.h" |
27 | 31 | ||
28 | #define VERSION "0.1" | 32 | #define VERSION "0.2" |
29 | 33 | ||
30 | #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin" | 34 | #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin" |
35 | #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" | ||
36 | #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" | ||
31 | 37 | ||
32 | #define MTK_STP_TLR_SIZE 2 | 38 | #define MTK_STP_TLR_SIZE 2 |
33 | 39 | ||
34 | #define BTMTKUART_TX_STATE_ACTIVE 1 | 40 | #define BTMTKUART_TX_STATE_ACTIVE 1 |
35 | #define BTMTKUART_TX_STATE_WAKEUP 2 | 41 | #define BTMTKUART_TX_STATE_WAKEUP 2 |
36 | #define BTMTKUART_TX_WAIT_VND_EVT 3 | 42 | #define BTMTKUART_TX_WAIT_VND_EVT 3 |
43 | #define BTMTKUART_REQUIRED_WAKEUP 4 | ||
44 | |||
45 | #define BTMTKUART_FLAG_STANDALONE_HW BIT(0) | ||
37 | 46 | ||
38 | enum { | 47 | enum { |
39 | MTK_WMT_PATCH_DWNLD = 0x1, | 48 | MTK_WMT_PATCH_DWNLD = 0x1, |
49 | MTK_WMT_TEST = 0x2, | ||
50 | MTK_WMT_WAKEUP = 0x3, | ||
51 | MTK_WMT_HIF = 0x4, | ||
40 | MTK_WMT_FUNC_CTRL = 0x6, | 52 | MTK_WMT_FUNC_CTRL = 0x6, |
41 | MTK_WMT_RST = 0x7, | 53 | MTK_WMT_RST = 0x7, |
42 | MTK_WMT_SEMAPHORE = 0x17, | 54 | MTK_WMT_SEMAPHORE = 0x17, |
@@ -57,6 +69,11 @@ struct mtk_stp_hdr { | |||
57 | u8 cs; | 69 | u8 cs; |
58 | } __packed; | 70 | } __packed; |
59 | 71 | ||
72 | struct btmtkuart_data { | ||
73 | unsigned int flags; | ||
74 | const char *fwname; | ||
75 | }; | ||
76 | |||
60 | struct mtk_wmt_hdr { | 77 | struct mtk_wmt_hdr { |
61 | u8 dir; | 78 | u8 dir; |
62 | u8 op; | 79 | u8 op; |
@@ -100,6 +117,14 @@ struct btmtkuart_dev { | |||
100 | struct serdev_device *serdev; | 117 | struct serdev_device *serdev; |
101 | struct clk *clk; | 118 | struct clk *clk; |
102 | 119 | ||
120 | struct regulator *vcc; | ||
121 | struct gpio_desc *reset; | ||
122 | struct pinctrl *pinctrl; | ||
123 | struct pinctrl_state *pins_runtime; | ||
124 | struct pinctrl_state *pins_boot; | ||
125 | speed_t desired_speed; | ||
126 | speed_t curr_speed; | ||
127 | |||
103 | struct work_struct tx_work; | 128 | struct work_struct tx_work; |
104 | unsigned long tx_state; | 129 | unsigned long tx_state; |
105 | struct sk_buff_head txq; | 130 | struct sk_buff_head txq; |
@@ -110,8 +135,15 @@ struct btmtkuart_dev { | |||
110 | u8 stp_pad[6]; | 135 | u8 stp_pad[6]; |
111 | u8 stp_cursor; | 136 | u8 stp_cursor; |
112 | u16 stp_dlen; | 137 | u16 stp_dlen; |
138 | |||
139 | const struct btmtkuart_data *data; | ||
113 | }; | 140 | }; |
114 | 141 | ||
142 | #define btmtkuart_is_standalone(bdev) \ | ||
143 | ((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) | ||
144 | #define btmtkuart_is_builtin_soc(bdev) \ | ||
145 | !((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) | ||
146 | |||
115 | static int mtk_hci_wmt_sync(struct hci_dev *hdev, | 147 | static int mtk_hci_wmt_sync(struct hci_dev *hdev, |
116 | struct btmtk_hci_wmt_params *wmt_params) | 148 | struct btmtk_hci_wmt_params *wmt_params) |
117 | { | 149 | { |
@@ -202,7 +234,7 @@ err_free_skb: | |||
202 | return err; | 234 | return err; |
203 | } | 235 | } |
204 | 236 | ||
205 | static int mtk_setup_fw(struct hci_dev *hdev) | 237 | static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) |
206 | { | 238 | { |
207 | struct btmtk_hci_wmt_params wmt_params; | 239 | struct btmtk_hci_wmt_params wmt_params; |
208 | const struct firmware *fw; | 240 | const struct firmware *fw; |
@@ -211,7 +243,7 @@ static int mtk_setup_fw(struct hci_dev *hdev) | |||
211 | int err, dlen; | 243 | int err, dlen; |
212 | u8 flag; | 244 | u8 flag; |
213 | 245 | ||
214 | err = request_firmware(&fw, FIRMWARE_MT7622, &hdev->dev); | 246 | err = request_firmware(&fw, fwname, &hdev->dev); |
215 | if (err < 0) { | 247 | if (err < 0) { |
216 | bt_dev_err(hdev, "Failed to load firmware file (%d)", err); | 248 | bt_dev_err(hdev, "Failed to load firmware file (%d)", err); |
217 | return err; | 249 | return err; |
@@ -523,6 +555,23 @@ static int btmtkuart_open(struct hci_dev *hdev) | |||
523 | goto err_open; | 555 | goto err_open; |
524 | } | 556 | } |
525 | 557 | ||
558 | if (btmtkuart_is_standalone(bdev)) { | ||
559 | if (bdev->curr_speed != bdev->desired_speed) | ||
560 | err = serdev_device_set_baudrate(bdev->serdev, | ||
561 | 115200); | ||
562 | else | ||
563 | err = serdev_device_set_baudrate(bdev->serdev, | ||
564 | bdev->desired_speed); | ||
565 | |||
566 | if (err < 0) { | ||
567 | bt_dev_err(hdev, "Unable to set baudrate UART device %s", | ||
568 | dev_name(&bdev->serdev->dev)); | ||
569 | goto err_serdev_close; | ||
570 | } | ||
571 | |||
572 | serdev_device_set_flow_control(bdev->serdev, false); | ||
573 | } | ||
574 | |||
526 | bdev->stp_cursor = 2; | 575 | bdev->stp_cursor = 2; |
527 | bdev->stp_dlen = 0; | 576 | bdev->stp_dlen = 0; |
528 | 577 | ||
@@ -546,6 +595,8 @@ err_put_rpm: | |||
546 | pm_runtime_put_sync(dev); | 595 | pm_runtime_put_sync(dev); |
547 | err_disable_rpm: | 596 | err_disable_rpm: |
548 | pm_runtime_disable(dev); | 597 | pm_runtime_disable(dev); |
598 | err_serdev_close: | ||
599 | serdev_device_close(bdev->serdev); | ||
549 | err_open: | 600 | err_open: |
550 | return err; | 601 | return err; |
551 | } | 602 | } |
@@ -606,8 +657,74 @@ static int btmtkuart_func_query(struct hci_dev *hdev) | |||
606 | return status; | 657 | return status; |
607 | } | 658 | } |
608 | 659 | ||
660 | static int btmtkuart_change_baudrate(struct hci_dev *hdev) | ||
661 | { | ||
662 | struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); | ||
663 | struct btmtk_hci_wmt_params wmt_params; | ||
664 | u32 baudrate; | ||
665 | u8 param; | ||
666 | int err; | ||
667 | |||
668 | /* Indicate the device to enter the probe state the host is | ||
669 | * ready to change a new baudrate. | ||
670 | */ | ||
671 | baudrate = cpu_to_le32(bdev->desired_speed); | ||
672 | wmt_params.op = MTK_WMT_HIF; | ||
673 | wmt_params.flag = 1; | ||
674 | wmt_params.dlen = 4; | ||
675 | wmt_params.data = &baudrate; | ||
676 | wmt_params.status = NULL; | ||
677 | |||
678 | err = mtk_hci_wmt_sync(hdev, &wmt_params); | ||
679 | if (err < 0) { | ||
680 | bt_dev_err(hdev, "Failed to device baudrate (%d)", err); | ||
681 | return err; | ||
682 | } | ||
683 | |||
684 | err = serdev_device_set_baudrate(bdev->serdev, | ||
685 | bdev->desired_speed); | ||
686 | if (err < 0) { | ||
687 | bt_dev_err(hdev, "Failed to set up host baudrate (%d)", | ||
688 | err); | ||
689 | return err; | ||
690 | } | ||
691 | |||
692 | serdev_device_set_flow_control(bdev->serdev, false); | ||
693 | |||
694 | /* Send a dummy byte 0xff to activate the new baudrate */ | ||
695 | param = 0xff; | ||
696 | err = serdev_device_write(bdev->serdev, ¶m, sizeof(param), | ||
697 | MAX_SCHEDULE_TIMEOUT); | ||
698 | if (err < 0 || err < sizeof(param)) | ||
699 | return err; | ||
700 | |||
701 | serdev_device_wait_until_sent(bdev->serdev, 0); | ||
702 | |||
703 | /* Wait some time for the device changing baudrate done */ | ||
704 | usleep_range(20000, 22000); | ||
705 | |||
706 | /* Test the new baudrate */ | ||
707 | wmt_params.op = MTK_WMT_TEST; | ||
708 | wmt_params.flag = 7; | ||
709 | wmt_params.dlen = 0; | ||
710 | wmt_params.data = NULL; | ||
711 | wmt_params.status = NULL; | ||
712 | |||
713 | err = mtk_hci_wmt_sync(hdev, &wmt_params); | ||
714 | if (err < 0) { | ||
715 | bt_dev_err(hdev, "Failed to test new baudrate (%d)", | ||
716 | err); | ||
717 | return err; | ||
718 | } | ||
719 | |||
720 | bdev->curr_speed = bdev->desired_speed; | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
609 | static int btmtkuart_setup(struct hci_dev *hdev) | 725 | static int btmtkuart_setup(struct hci_dev *hdev) |
610 | { | 726 | { |
727 | struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); | ||
611 | struct btmtk_hci_wmt_params wmt_params; | 728 | struct btmtk_hci_wmt_params wmt_params; |
612 | ktime_t calltime, delta, rettime; | 729 | ktime_t calltime, delta, rettime; |
613 | struct btmtk_tci_sleep tci_sleep; | 730 | struct btmtk_tci_sleep tci_sleep; |
@@ -618,6 +735,28 @@ static int btmtkuart_setup(struct hci_dev *hdev) | |||
618 | 735 | ||
619 | calltime = ktime_get(); | 736 | calltime = ktime_get(); |
620 | 737 | ||
738 | /* Wakeup MCUSYS is required for certain devices before we start to | ||
739 | * do any setups. | ||
740 | */ | ||
741 | if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) { | ||
742 | wmt_params.op = MTK_WMT_WAKEUP; | ||
743 | wmt_params.flag = 3; | ||
744 | wmt_params.dlen = 0; | ||
745 | wmt_params.data = NULL; | ||
746 | wmt_params.status = NULL; | ||
747 | |||
748 | err = mtk_hci_wmt_sync(hdev, &wmt_params); | ||
749 | if (err < 0) { | ||
750 | bt_dev_err(hdev, "Failed to wakeup the chip (%d)", err); | ||
751 | return err; | ||
752 | } | ||
753 | |||
754 | clear_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); | ||
755 | } | ||
756 | |||
757 | if (btmtkuart_is_standalone(bdev)) | ||
758 | btmtkuart_change_baudrate(hdev); | ||
759 | |||
621 | /* Query whether the firmware is already download */ | 760 | /* Query whether the firmware is already download */ |
622 | wmt_params.op = MTK_WMT_SEMAPHORE; | 761 | wmt_params.op = MTK_WMT_SEMAPHORE; |
623 | wmt_params.flag = 1; | 762 | wmt_params.flag = 1; |
@@ -637,7 +776,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) | |||
637 | } | 776 | } |
638 | 777 | ||
639 | /* Setup a firmware which the device definitely requires */ | 778 | /* Setup a firmware which the device definitely requires */ |
640 | err = mtk_setup_fw(hdev); | 779 | err = mtk_setup_firmware(hdev, bdev->data->fwname); |
641 | if (err < 0) | 780 | if (err < 0) |
642 | return err; | 781 | return err; |
643 | 782 | ||
@@ -754,24 +893,82 @@ static int btmtkuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
754 | return 0; | 893 | return 0; |
755 | } | 894 | } |
756 | 895 | ||
896 | static int btmtkuart_parse_dt(struct serdev_device *serdev) | ||
897 | { | ||
898 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); | ||
899 | struct device_node *node = serdev->dev.of_node; | ||
900 | u32 speed = 921600; | ||
901 | int err; | ||
902 | |||
903 | if (btmtkuart_is_standalone(bdev)) { | ||
904 | of_property_read_u32(node, "current-speed", &speed); | ||
905 | |||
906 | bdev->desired_speed = speed; | ||
907 | |||
908 | bdev->vcc = devm_regulator_get(&serdev->dev, "vcc"); | ||
909 | if (IS_ERR(bdev->vcc)) { | ||
910 | err = PTR_ERR(bdev->vcc); | ||
911 | return err; | ||
912 | } | ||
913 | |||
914 | bdev->pinctrl = devm_pinctrl_get(&serdev->dev); | ||
915 | if (IS_ERR(bdev->pinctrl)) { | ||
916 | err = PTR_ERR(bdev->pinctrl); | ||
917 | return err; | ||
918 | } | ||
919 | |||
920 | bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl, | ||
921 | "default"); | ||
922 | if (IS_ERR(bdev->pins_boot)) { | ||
923 | err = PTR_ERR(bdev->pins_boot); | ||
924 | return err; | ||
925 | } | ||
926 | |||
927 | bdev->pins_runtime = pinctrl_lookup_state(bdev->pinctrl, | ||
928 | "runtime"); | ||
929 | if (IS_ERR(bdev->pins_runtime)) { | ||
930 | err = PTR_ERR(bdev->pins_runtime); | ||
931 | return err; | ||
932 | } | ||
933 | |||
934 | bdev->reset = devm_gpiod_get_optional(&serdev->dev, "reset", | ||
935 | GPIOD_OUT_LOW); | ||
936 | if (IS_ERR(bdev->reset)) { | ||
937 | err = PTR_ERR(bdev->reset); | ||
938 | return err; | ||
939 | } | ||
940 | } else if (btmtkuart_is_builtin_soc(bdev)) { | ||
941 | bdev->clk = devm_clk_get(&serdev->dev, "ref"); | ||
942 | if (IS_ERR(bdev->clk)) | ||
943 | return PTR_ERR(bdev->clk); | ||
944 | } | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
757 | static int btmtkuart_probe(struct serdev_device *serdev) | 949 | static int btmtkuart_probe(struct serdev_device *serdev) |
758 | { | 950 | { |
759 | struct btmtkuart_dev *bdev; | 951 | struct btmtkuart_dev *bdev; |
760 | struct hci_dev *hdev; | 952 | struct hci_dev *hdev; |
953 | int err; | ||
761 | 954 | ||
762 | bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL); | 955 | bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL); |
763 | if (!bdev) | 956 | if (!bdev) |
764 | return -ENOMEM; | 957 | return -ENOMEM; |
765 | 958 | ||
766 | bdev->clk = devm_clk_get(&serdev->dev, "ref"); | 959 | bdev->data = of_device_get_match_data(&serdev->dev); |
767 | if (IS_ERR(bdev->clk)) | 960 | if (!bdev->data) |
768 | return PTR_ERR(bdev->clk); | 961 | return -ENODEV; |
769 | 962 | ||
770 | bdev->serdev = serdev; | 963 | bdev->serdev = serdev; |
771 | serdev_device_set_drvdata(serdev, bdev); | 964 | serdev_device_set_drvdata(serdev, bdev); |
772 | 965 | ||
773 | serdev_device_set_client_ops(serdev, &btmtkuart_client_ops); | 966 | serdev_device_set_client_ops(serdev, &btmtkuart_client_ops); |
774 | 967 | ||
968 | err = btmtkuart_parse_dt(serdev); | ||
969 | if (err < 0) | ||
970 | return err; | ||
971 | |||
775 | INIT_WORK(&bdev->tx_work, btmtkuart_tx_work); | 972 | INIT_WORK(&bdev->tx_work, btmtkuart_tx_work); |
776 | skb_queue_head_init(&bdev->txq); | 973 | skb_queue_head_init(&bdev->txq); |
777 | 974 | ||
@@ -798,13 +995,54 @@ static int btmtkuart_probe(struct serdev_device *serdev) | |||
798 | hdev->manufacturer = 70; | 995 | hdev->manufacturer = 70; |
799 | set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); | 996 | set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); |
800 | 997 | ||
801 | if (hci_register_dev(hdev) < 0) { | 998 | if (btmtkuart_is_standalone(bdev)) { |
999 | /* Switch to the specific pin state for the booting requires */ | ||
1000 | pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); | ||
1001 | |||
1002 | /* Power on */ | ||
1003 | err = regulator_enable(bdev->vcc); | ||
1004 | if (err < 0) | ||
1005 | return err; | ||
1006 | |||
1007 | /* Reset if the reset-gpios is available otherwise the board | ||
1008 | * -level design should be guaranteed. | ||
1009 | */ | ||
1010 | if (bdev->reset) { | ||
1011 | gpiod_set_value_cansleep(bdev->reset, 1); | ||
1012 | usleep_range(1000, 2000); | ||
1013 | gpiod_set_value_cansleep(bdev->reset, 0); | ||
1014 | } | ||
1015 | |||
1016 | /* Wait some time until device got ready and switch to the pin | ||
1017 | * mode the device requires for UART transfers. | ||
1018 | */ | ||
1019 | msleep(50); | ||
1020 | pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime); | ||
1021 | |||
1022 | /* A standalone device doesn't depends on power domain on SoC, | ||
1023 | * so mark it as no callbacks. | ||
1024 | */ | ||
1025 | pm_runtime_no_callbacks(&serdev->dev); | ||
1026 | |||
1027 | set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); | ||
1028 | } | ||
1029 | |||
1030 | err = hci_register_dev(hdev); | ||
1031 | if (err < 0) { | ||
802 | dev_err(&serdev->dev, "Can't register HCI device\n"); | 1032 | dev_err(&serdev->dev, "Can't register HCI device\n"); |
803 | hci_free_dev(hdev); | 1033 | hci_free_dev(hdev); |
804 | return -ENODEV; | 1034 | goto err_regulator_disable; |
805 | } | 1035 | } |
806 | 1036 | ||
807 | return 0; | 1037 | return 0; |
1038 | |||
1039 | err_regulator_disable: | ||
1040 | if (btmtkuart_is_standalone(bdev)) { | ||
1041 | pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); | ||
1042 | regulator_disable(bdev->vcc); | ||
1043 | } | ||
1044 | |||
1045 | return err; | ||
808 | } | 1046 | } |
809 | 1047 | ||
810 | static void btmtkuart_remove(struct serdev_device *serdev) | 1048 | static void btmtkuart_remove(struct serdev_device *serdev) |
@@ -812,13 +1050,34 @@ static void btmtkuart_remove(struct serdev_device *serdev) | |||
812 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); | 1050 | struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); |
813 | struct hci_dev *hdev = bdev->hdev; | 1051 | struct hci_dev *hdev = bdev->hdev; |
814 | 1052 | ||
1053 | if (btmtkuart_is_standalone(bdev)) { | ||
1054 | pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); | ||
1055 | regulator_disable(bdev->vcc); | ||
1056 | } | ||
1057 | |||
815 | hci_unregister_dev(hdev); | 1058 | hci_unregister_dev(hdev); |
816 | hci_free_dev(hdev); | 1059 | hci_free_dev(hdev); |
817 | } | 1060 | } |
818 | 1061 | ||
1062 | static const struct btmtkuart_data mt7622_data = { | ||
1063 | .fwname = FIRMWARE_MT7622, | ||
1064 | }; | ||
1065 | |||
1066 | static const struct btmtkuart_data mt7663_data = { | ||
1067 | .flags = BTMTKUART_FLAG_STANDALONE_HW, | ||
1068 | .fwname = FIRMWARE_MT7663, | ||
1069 | }; | ||
1070 | |||
1071 | static const struct btmtkuart_data mt7668_data = { | ||
1072 | .flags = BTMTKUART_FLAG_STANDALONE_HW, | ||
1073 | .fwname = FIRMWARE_MT7668, | ||
1074 | }; | ||
1075 | |||
819 | #ifdef CONFIG_OF | 1076 | #ifdef CONFIG_OF |
820 | static const struct of_device_id mtk_of_match_table[] = { | 1077 | static const struct of_device_id mtk_of_match_table[] = { |
821 | { .compatible = "mediatek,mt7622-bluetooth"}, | 1078 | { .compatible = "mediatek,mt7622-bluetooth", .data = &mt7622_data}, |
1079 | { .compatible = "mediatek,mt7663u-bluetooth", .data = &mt7663_data}, | ||
1080 | { .compatible = "mediatek,mt7668u-bluetooth", .data = &mt7668_data}, | ||
822 | { } | 1081 | { } |
823 | }; | 1082 | }; |
824 | MODULE_DEVICE_TABLE(of, mtk_of_match_table); | 1083 | MODULE_DEVICE_TABLE(of, mtk_of_match_table); |
@@ -840,3 +1099,5 @@ MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION); | |||
840 | MODULE_VERSION(VERSION); | 1099 | MODULE_VERSION(VERSION); |
841 | MODULE_LICENSE("GPL"); | 1100 | MODULE_LICENSE("GPL"); |
842 | MODULE_FIRMWARE(FIRMWARE_MT7622); | 1101 | MODULE_FIRMWARE(FIRMWARE_MT7622); |
1102 | MODULE_FIRMWARE(FIRMWARE_MT7663); | ||
1103 | MODULE_FIRMWARE(FIRMWARE_MT7668); | ||