diff options
author | Peter Tsao <peter.tsao@mediatek.com> | 2023-06-20 16:27:50 +0800 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2023-08-11 11:39:39 -0700 |
commit | 4c92ae75ea7d41b6bafe10ee6f4c12ec12624786 (patch) | |
tree | f65caab3ab9cb1ac98f2239ab72d9124b967b401 /drivers/bluetooth/btusb.c | |
parent | 8f0a3786f56d9fa4b308bdbd54757a51145dbb7a (diff) |
Bluetooth: btusb: Add support Mediatek MT7925
This patch is added support Mediatek MT7925.
1. The firmware location of MT7925 will set to
/lib/firmware/mediatek/mt7925
2. Add Mediatek private data in hdev
to record the device for handle MT7925 flow.
3. Use the recoreded dev_id to condition chip reset flow.
The information in /sys/kernel/debug/usb/devices about the MT7925U
Bluetooth device is listed as the below
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 27 Spd=480 MxCh= 0
D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0e8d ProdID=7925 Rev= 1.00
S: Manufacturer=MediaTek Inc.
S: Product=Wireless_Device
S: SerialNumber=000000000
C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=100mA
A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
I:* If#= 0 Alt= 0 #EPs= 5 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=8f(I) Atr=03(Int.) MxPS= 2 Ivl=125us
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
I:* If#= 3 Alt= 0 #EPs= 9 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=09(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=86(I) Atr=03(Int.) MxPS= 2 Ivl=125us
Signed-off-by: Peter Tsao <peter.tsao@mediatek.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f99ce34abb9f..e1e271e0437d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2659,6 +2659,9 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) #define MTK_BT_RST_DONE 0x00000100 #define MTK_BT_RESET_WAIT_MS 100 #define MTK_BT_RESET_NUM_TRIES 10 +#define MTK_BT_RESET_REG_CONNV3 0x70028610 +#define MTK_BT_READ_DEV_ID 0x70010200 + static void btusb_mtk_wmt_recv(struct urb *urb) { @@ -3039,10 +3042,11 @@ static int btusb_mtk_setup(struct hci_dev *hdev) struct sk_buff *skb; const char *fwname; int err, status; - u32 dev_id; + u32 dev_id = 0; char fw_bin_name[64]; u32 fw_version = 0; u8 param; + struct btmediatek_data *mediatek; calltime = ktime_get(); @@ -3052,7 +3056,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev) return err; } - if (!dev_id) { + if (!dev_id || dev_id != 0x7663) { err = btusb_mtk_id_get(data, 0x70010200, &dev_id); if (err < 0) { bt_dev_err(hdev, "Failed to get device id (%d)", err); @@ -3065,6 +3069,9 @@ static int btusb_mtk_setup(struct hci_dev *hdev) } } + mediatek = hci_get_priv(hdev); + mediatek->dev_id = dev_id; + switch (dev_id) { case 0x7663: fwname = FIRMWARE_MT7663; @@ -3074,9 +3081,16 @@ static int btusb_mtk_setup(struct hci_dev *hdev) break; case 0x7922: case 0x7961: - snprintf(fw_bin_name, sizeof(fw_bin_name), - "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", - dev_id & 0xffff, (fw_version & 0xff) + 1); + case 0x7925: + if (dev_id == 0x7925) + snprintf(fw_bin_name, sizeof(fw_bin_name), + "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", + dev_id & 0xffff, dev_id & 0xffff, (fw_version & 0xff) + 1); + else + snprintf(fw_bin_name, sizeof(fw_bin_name), + "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", + dev_id & 0xffff, (fw_version & 0xff) + 1); + err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, btusb_mtk_hci_wmt_sync); if (err < 0) { @@ -3219,6 +3233,7 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev) struct btusb_data *data = hci_get_drvdata(hdev); u32 val; int err, retry = 0; + struct btmediatek_data *mediatek; /* It's MediaTek specific bluetooth reset mechanism via USB */ if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { @@ -3232,22 +3247,42 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev) btusb_stop_traffic(data); usb_kill_anchored_urbs(&data->tx_anchor); + mediatek = hci_get_priv(hdev); + + if (mediatek->dev_id == 0x7925) { + btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); + val |= (1 << 5); + btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); + btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); + val &= 0xFFFF00FF; + val |= (1 << 13); + btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); + btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); + val |= (1 << 0); + btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); + msleep(100); + } else { + /* It's Device EndPoint Reset Option Register */ + bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); + btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); - /* It's Device EndPoint Reset Option Register */ - bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); - btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); - btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); - - /* Reset the bluetooth chip via USB interface. */ - btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); - btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); - btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); - btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); - btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); - /* MT7921 need to delay 20ms between toggle reset bit */ - msleep(20); - btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); - btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); + /* Reset the bluetooth chip via USB interface. */ + btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); + /* MT7921 need to delay 20ms between toggle reset bit */ + msleep(20); + btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); + btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); + } /* Poll the register until reset is completed */ do { @@ -4289,6 +4324,9 @@ static int btusb_probe(struct usb_interface *intf, priv_size += sizeof(struct btrealtek_data); data->recv_event = btusb_recv_event_realtek; + } else if (id->driver_info & BTUSB_MEDIATEK) { + /* Allocate extra space for Mediatek device */ + priv_size += sizeof(struct btmediatek_data); } data->recv_acl = hci_recv_frame; |