Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support

The MediaTek MT7927 (Filogic 380) combo WiFi 7 + BT 5.4 module uses
hardware variant 0x6639 for its Bluetooth subsystem. Without this patch,
the chip fails with "Unsupported hardware variant (00006639)" or hangs
during firmware download.

Three changes are needed to support MT6639:

1. CHIPID workaround: On some boards the BT USB MMIO register reads
0x0000 for dev_id, causing the driver to skip the 0x6639 init path.
Force dev_id to 0x6639 only when the USB VID/PID matches a known
MT6639 device, avoiding misdetection if a future chip also reads
zero. This follows the WiFi-side pattern that uses PCI device IDs
to scope the same workaround.

2. Firmware naming: MT6639 uses firmware version prefix "2_1" instead of
"1_1" used by MT7925 and other variants. The firmware path is
mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin, using the mt7927
directory to match the WiFi firmware convention. The filename will
likely change to use MT7927 once MediaTek submits a dedicated
Linux firmware binary.

3. Section filtering: The MT6639 firmware binary contains 9 sections, but
only sections with (dlmodecrctype & 0xff) == 0x01 are Bluetooth-related.
Sending the remaining WiFi/other sections causes an irreversible BT
subsystem hang requiring a full power cycle. This matches the Windows
driver behavior observed via USB captures.

Also add 0x6639 to the reset register (CONNV3) and firmware setup switch
cases alongside the existing 0x7925 handling.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=221096
Link: https://github.com/openwrt/mt76/issues/927
Reported-by: Ryan Gilbert <xelnaga@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Javier Tia and committed by
Luiz Augusto von Dentz
28b7c5a6 5c7209a3

+61 -8
+55 -5
drivers/bluetooth/btmtk.c
··· 25 25 /* It is for mt79xx iso data transmission setting */ 26 26 #define MTK_ISO_THRESHOLD 264 27 27 28 + /* Known MT6639 (MT7927) Bluetooth USB devices. 29 + * Used to scope the zero-CHIPID workaround to real MT6639 hardware, 30 + * since some boards return 0x0000 from the MMIO chip ID register. 31 + */ 32 + static const struct { 33 + u16 vendor; 34 + u16 product; 35 + } btmtk_mt6639_devs[] = { 36 + { 0x0489, 0xe13a }, /* ASUS ROG Crosshair X870E Hero */ 37 + { 0x0489, 0xe0fa }, /* Lenovo Legion Pro 7 16ARX9 */ 38 + { 0x0489, 0xe10f }, /* Gigabyte Z790 AORUS MASTER X */ 39 + { 0x0489, 0xe110 }, /* MSI X870E Ace Max */ 40 + { 0x0489, 0xe116 }, /* TP-Link Archer TBE550E */ 41 + { 0x13d3, 0x3588 }, /* ASUS ROG STRIX X870E-E */ 42 + }; 43 + 28 44 struct btmtk_patch_header { 29 45 u8 datetime[16]; 30 46 u8 platform[4]; ··· 128 112 void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, 129 113 u32 fw_flavor) 130 114 { 131 - if (dev_id == 0x7925) 115 + if (dev_id == 0x6639) 116 + snprintf(buf, size, 117 + "mediatek/mt7927/BT_RAM_CODE_MT%04x_2_%x_hdr.bin", 118 + dev_id & 0xffff, (fw_ver & 0xff) + 1); 119 + else if (dev_id == 0x7925) 132 120 snprintf(buf, size, 133 121 "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", 134 122 dev_id & 0xffff, dev_id & 0xffff, (fw_ver & 0xff) + 1); ··· 148 128 EXPORT_SYMBOL_GPL(btmtk_fw_get_filename); 149 129 150 130 int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, 151 - wmt_cmd_sync_func_t wmt_cmd_sync) 131 + wmt_cmd_sync_func_t wmt_cmd_sync, 132 + u32 dev_id) 152 133 { 153 134 struct btmtk_hci_wmt_params wmt_params; 154 135 struct btmtk_patch_header *hdr; ··· 186 165 187 166 section_offset = le32_to_cpu(sectionmap->secoffset); 188 167 dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize); 168 + 169 + /* MT6639: only download sections where dlmode byte0 == 0x01, 170 + * matching the Windows driver behavior which skips WiFi/other 171 + * sections that would cause the chip to hang. 172 + */ 173 + if (dev_id == 0x6639 && dl_size > 0 && 174 + (le32_to_cpu(sectionmap->bin_info_spec.dlmodecrctype) & 0xff) != 0x01) 175 + continue; 189 176 190 177 if (dl_size > 0) { 191 178 retry = 20; ··· 881 852 if (err < 0) 882 853 return err; 883 854 msleep(100); 884 - } else if (dev_id == 0x7925) { 855 + } else if (dev_id == 0x7925 || dev_id == 0x6639) { 885 856 err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val); 886 857 if (err < 0) 887 858 return err; ··· 967 938 } 968 939 969 940 err = btmtk_usb_id_get(hdev, 0x70010200, &val); 970 - if (err < 0 || !val) 941 + if (err < 0 || (!val && dev_id != 0x6639)) 971 942 bt_dev_err(hdev, "Can't get device id, subsys reset fail."); 972 943 973 944 return err; ··· 1332 1303 fw_flavor = (fw_flavor & 0x00000080) >> 7; 1333 1304 } 1334 1305 1306 + if (!dev_id) { 1307 + u16 vid = le16_to_cpu(btmtk_data->udev->descriptor.idVendor); 1308 + u16 pid = le16_to_cpu(btmtk_data->udev->descriptor.idProduct); 1309 + int i; 1310 + 1311 + for (i = 0; i < ARRAY_SIZE(btmtk_mt6639_devs); i++) { 1312 + if (vid == btmtk_mt6639_devs[i].vendor && 1313 + pid == btmtk_mt6639_devs[i].product) { 1314 + dev_id = 0x6639; 1315 + break; 1316 + } 1317 + } 1318 + 1319 + if (dev_id) 1320 + bt_dev_info(hdev, "MT6639: CHIPID=0x0000 with VID=%04x PID=%04x, using 0x6639", 1321 + vid, pid); 1322 + } 1323 + 1335 1324 btmtk_data->dev_id = dev_id; 1336 1325 1337 1326 err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version); ··· 1367 1320 case 0x7925: 1368 1321 case 0x7961: 1369 1322 case 0x7902: 1323 + case 0x6639: 1370 1324 btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, 1371 1325 fw_version, fw_flavor); 1372 1326 1373 1327 err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, 1374 - btmtk_usb_hci_wmt_sync); 1328 + btmtk_usb_hci_wmt_sync, 1329 + dev_id); 1375 1330 if (err < 0) { 1376 1331 /* retry once if setup firmware error */ 1377 1332 if (!test_and_set_bit(BTMTK_FIRMWARE_DL_RETRY, &btmtk_data->flags)) ··· 1546 1497 MODULE_FIRMWARE(FIRMWARE_MT7922); 1547 1498 MODULE_FIRMWARE(FIRMWARE_MT7961); 1548 1499 MODULE_FIRMWARE(FIRMWARE_MT7925); 1500 + MODULE_FIRMWARE(FIRMWARE_MT7927);
+5 -2
drivers/bluetooth/btmtk.h
··· 8 8 #define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin" 9 9 #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin" 10 10 #define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin" 11 + #define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin" 11 12 12 13 #define HCI_EV_WMT 0xe4 13 14 #define HCI_WMT_MAX_EVENT_SIZE 64 ··· 190 189 int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); 191 190 192 191 int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, 193 - wmt_cmd_sync_func_t wmt_cmd_sync); 192 + wmt_cmd_sync_func_t wmt_cmd_sync, 193 + u32 dev_id); 194 194 195 195 int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, 196 196 wmt_cmd_sync_func_t wmt_cmd_sync); ··· 230 228 231 229 static inline int btmtk_setup_firmware_79xx(struct hci_dev *hdev, 232 230 const char *fwname, 233 - wmt_cmd_sync_func_t wmt_cmd_sync) 231 + wmt_cmd_sync_func_t wmt_cmd_sync, 232 + u32 dev_id) 234 233 { 235 234 return -EOPNOTSUPP; 236 235 }
+1 -1
drivers/bluetooth/btmtksdio.c
··· 883 883 u8 param = 0x1; 884 884 int err; 885 885 886 - err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync); 886 + err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync, 0); 887 887 if (err < 0) { 888 888 bt_dev_err(hdev, "Failed to setup 79xx firmware (%d)", err); 889 889 return err;