From 4b6858797229fc787d1b737cace469ad146aaaf0 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 10 Jan 2022 03:23:57 +0800 Subject: Bluetooth: btmtksdio: rename btsdio_mtk_reg_read Using "btmtksdio" as the prefix instead of "btsdio" Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index b5ea8d3bffaa..891e34b50e44 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -797,7 +797,7 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) return err; } -static int btsdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) +static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) { struct btmtk_hci_wmt_params wmt_params; struct reg_read_cmd { @@ -844,13 +844,13 @@ static int btmtksdio_setup(struct hci_dev *hdev) switch (bdev->data->chipid) { case 0x7921: - err = btsdio_mtk_reg_read(hdev, 0x70010200, &dev_id); + err = btmtksdio_mtk_reg_read(hdev, 0x70010200, &dev_id); if (err < 0) { bt_dev_err(hdev, "Failed to get device id (%d)", err); return err; } - err = btsdio_mtk_reg_read(hdev, 0x80021004, &fw_version); + err = btmtksdio_mtk_reg_read(hdev, 0x80021004, &fw_version); if (err < 0) { bt_dev_err(hdev, "Failed to get fw version (%d)", err); return err; -- cgit v1.2.3 From ce64b3e949195768361b0e4111e0837e5e46930d Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Mon, 10 Jan 2022 03:23:58 +0800 Subject: Bluetooth: mt7921s: Support wake on bluetooth Enable wake on bluetooth on mt7921s that can be supported since the firmware with version 20211129211059 was added, and the patch would not cause any harm even when the old firmware is applied. The patch was tested by setting up an HID or HOGP profile to connect a Bluetooth keyboard and mouse, then putting the system to suspend, then trying to wake up the system by moving the Bluetooth keyboard or mouse, and then checking if the system can wake up and be brought back to the normal state. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtk.h | 8 ++++++++ drivers/bluetooth/btmtksdio.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 6e7b0c7567c0..2be1d2680ad8 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -68,6 +68,14 @@ struct btmtk_tci_sleep { u8 time_compensation; } __packed; +struct btmtk_wakeon { + u8 mode; + u8 gpo; + u8 active_high; + __le16 enable_delay; + __le16 wakeup_delay; +} __packed; + struct btmtk_hci_wmt_params { u8 op; u8 flag; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 891e34b50e44..a8273874e29f 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -958,6 +958,32 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } +static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev) +{ + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); + bool may_wakeup = device_may_wakeup(bdev->dev); + const struct btmtk_wakeon bt_awake = { + .mode = 0x1, + .gpo = 0, + .active_high = 0x1, + .enable_delay = cpu_to_le16(0xc80), + .wakeup_delay = cpu_to_le16(0x20), + }; + + if (may_wakeup && bdev->data->chipid == 0x7921) { + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake), + &bt_awake, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) + may_wakeup = false; + + kfree_skb(skb); + } + + return may_wakeup; +} + static int btmtksdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -997,6 +1023,7 @@ static int btmtksdio_probe(struct sdio_func *func, hdev->setup = btmtksdio_setup; hdev->shutdown = btmtksdio_shutdown; hdev->send = btmtksdio_send_frame; + hdev->wakeup = btmtksdio_sdio_wakeup; hdev->set_bdaddr = btmtk_set_bdaddr; SET_HCIDEV_DEV(hdev, &func->dev); @@ -1032,7 +1059,11 @@ static int btmtksdio_probe(struct sdio_func *func, */ pm_runtime_put_noidle(bdev->dev); - return 0; + err = device_init_wakeup(bdev->dev, true); + if (err) + bt_dev_err(hdev, "failed to initialize device wakeup"); + + return err; } static void btmtksdio_remove(struct sdio_func *func) -- cgit v1.2.3 From 191c872308f6a175324bc33807852b10363066cb Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Mon, 10 Jan 2022 03:23:59 +0800 Subject: Bluetooth: mt7921s: Enable SCO over I2S The driver has to issue the specific command to enable Bluetooth SCO over the I2S/PCM interface on mt7921s, that is supported since the firmware with version 20211222191101 was added, and the patch would not cause any harm even when the old firmware is applied. The SCO profile with the patch was tested by setting up a VOIP application, connected to HFP device, checked telephony function can work normally. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtk.h | 20 +++++++++++++ drivers/bluetooth/btmtksdio.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 2be1d2680ad8..fc57ef09d132 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -7,8 +7,12 @@ #define HCI_WMT_MAX_EVENT_SIZE 64 +#define BTMTK_WMT_REG_WRITE 0x1 #define BTMTK_WMT_REG_READ 0x2 +#define MT7921_PINMUX_0 0x70005050 +#define MT7921_PINMUX_1 0x70005054 + enum { BTMTK_WMT_PATCH_DWNLD = 0x1, BTMTK_WMT_TEST = 0x2, @@ -76,6 +80,22 @@ struct btmtk_wakeon { __le16 wakeup_delay; } __packed; +struct btmtk_sco { + u8 clock_config; + u8 transmit_format_config; + u8 channel_format_config; + u8 channel_select_config; +} __packed; + +struct reg_write_cmd { + u8 type; + u8 rsv; + u8 num; + __le32 addr; + __le32 data; + __le32 mask; +} __packed; + struct btmtk_hci_wmt_params { u8 op; u8 flag; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index a8273874e29f..a41b5f65e7a9 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -830,6 +830,66 @@ static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) return err; } +static int btmtksdio_mtk_reg_write(struct hci_dev *hdev, u32 reg, u32 val, u32 mask) +{ + struct btmtk_hci_wmt_params wmt_params; + const struct reg_write_cmd reg_write = { + .type = 1, + .num = 1, + .addr = cpu_to_le32(reg), + .data = cpu_to_le32(val), + .mask = cpu_to_le32(mask), + }; + int err, status; + + wmt_params.op = BTMTK_WMT_REGISTER; + wmt_params.flag = BTMTK_WMT_REG_WRITE; + wmt_params.dlen = sizeof(reg_write); + wmt_params.data = ®_write; + wmt_params.status = &status; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) + bt_dev_err(hdev, "Failed to write reg (%d)", err); + + return err; +} + +static int btmtksdio_sco_setting(struct hci_dev *hdev) +{ + const struct btmtk_sco sco_setting = { + .clock_config = 0x49, + .channel_format_config = 0x80, + }; + struct sk_buff *skb; + u32 val; + int err; + + /* Enable SCO over I2S/PCM for MediaTek chipset */ + skb = __hci_cmd_sync(hdev, 0xfc72, sizeof(sco_setting), + &sco_setting, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + kfree_skb(skb); + + err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_0, &val); + if (err < 0) + return err; + + val |= 0x11000000; + err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_0, val, ~0); + if (err < 0) + return err; + + err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_1, &val); + if (err < 0) + return err; + + val |= 0x00000101; + return btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0); +} + static int btmtksdio_setup(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); @@ -862,6 +922,14 @@ static int btmtksdio_setup(struct hci_dev *hdev) err = mt79xx_setup(hdev, fwname); if (err < 0) return err; + + /* Enable SCO over I2S/PCM */ + err = btmtksdio_sco_setting(hdev); + if (err < 0) { + bt_dev_err(hdev, "Failed to enable SCO setting (%d)", err); + return err; + } + break; case 0x7663: case 0x7668: -- cgit v1.2.3 From 5677bcf6d8ff645d90c422ab035030c6aeec9296 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 10 Jan 2022 03:24:00 +0800 Subject: Bluetooth: btmtksdio: move struct reg_read_cmd to common file move struct reg_read_cmd to btmtk.h to allow other mtk drivers refer to. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtk.h | 7 +++++++ drivers/bluetooth/btmtksdio.c | 7 +------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index fc57ef09d132..fb76d9765ce0 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -87,6 +87,13 @@ struct btmtk_sco { u8 channel_select_config; } __packed; +struct reg_read_cmd { + u8 type; + u8 rsv; + u8 num; + __le32 addr; +} __packed; + struct reg_write_cmd { u8 type; u8 rsv; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index a41b5f65e7a9..d82ba9d71fb8 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -800,12 +800,7 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) { struct btmtk_hci_wmt_params wmt_params; - struct reg_read_cmd { - u8 type; - u8 rsv; - u8 num; - __le32 addr; - } __packed reg_read = { + struct reg_read_cmd reg_read = { .type = 1, .num = 1, }; -- cgit v1.2.3 From 386f626adda81d224f7229e31ebdefcd616b2ff2 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 10 Jan 2022 03:24:01 +0800 Subject: Bluetooth: btmtksdio: clean up inconsistent error message in btmtksdio_mtk_reg_read Have "..reg (%d)" to be consistent with the other similar error messages. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index d82ba9d71fb8..25fb9c79b1f4 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -816,7 +816,7 @@ static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { - bt_dev_err(hdev, "Failed to read reg(%d)", err); + bt_dev_err(hdev, "Failed to read reg (%d)", err); return err; } -- cgit v1.2.3 From 55235304c2560d4a94ccfff2a47ea927b4114064 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Thu, 20 Jan 2022 11:44:18 -0800 Subject: Bluetooth: btintel: Fix WBS setting for Intel legacy ROM products This patch adds the flag to identify the Intel legacy ROM products that don't support WBS like WP and StP. Fixes: 3df4dfbec0f29 ("Bluetooth: btintel: Move hci quirks to setup routine") Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btintel.c | 11 ++++++++--- drivers/bluetooth/btintel.h | 1 + drivers/bluetooth/btusb.c | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 1a4f8b227eac..06514ed66022 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2428,10 +2428,15 @@ static int btintel_setup_combined(struct hci_dev *hdev) /* Apply the device specific HCI quirks * - * WBS for SdP - SdP and Stp have a same hw_varaint but - * different fw_variant + * WBS for SdP - For the Legacy ROM products, only SdP + * supports the WBS. But the version information is not + * enough to use here because the StP2 and SdP have same + * hw_variant and fw_variant. So, this flag is set by + * the transport driver (btusb) based on the HW info + * (idProduct) */ - if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22) + if (!btintel_test_flag(hdev, + INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index c9b24e9299e2..e0060e58573c 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -152,6 +152,7 @@ enum { INTEL_BROKEN_INITIAL_NCMD, INTEL_BROKEN_SHUTDOWN_LED, INTEL_ROM_LEGACY, + INTEL_ROM_LEGACY_NO_WBS_SUPPORT, __INTEL_NUM_FLAGS, }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c30d131da784..cbd0eaa05e17 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -62,6 +62,7 @@ static struct usb_driver btusb_driver; #define BTUSB_QCA_WCN6855 0x1000000 #define BTUSB_INTEL_BROKEN_SHUTDOWN_LED 0x2000000 #define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000 +#define BTUSB_INTEL_NO_WBS_SUPPORT 0x8000000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -385,9 +386,11 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_NO_WBS_SUPPORT | BTUSB_INTEL_BROKEN_INITIAL_NCMD | BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_NO_WBS_SUPPORT | BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | @@ -3737,6 +3740,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->send = btusb_send_frame_intel; hdev->cmd_timeout = btusb_intel_cmd_timeout; + if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT) + btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT); + if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD) btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD); -- cgit v1.2.3 From 2e7b4a328ed6ea57d22853939e69bc86c560996d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 19 Jan 2022 14:18:37 -0600 Subject: Bluetooth: btusb: Add one more Bluetooth part for the Realtek RTL8852AE This Realtek device has both wifi and BT components. The latter reports a USB ID of 0bda:2852, which is not in the table. BT device description in /sys/kernel/debug/usb/devices contains the following entries: T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=2852 Rev= 0.00 S: Manufacturer=Realtek S: Product=Bluetooth Radio S: SerialNumber=00e04c000001 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) 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=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) 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=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) 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=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) 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=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) 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=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms The missing USB_ID was reported by user trius65 at https://github.com/lwfinger/rtw89/issues/122 Signed-off-by: Larry Finger Cc: stable@vger.kernel.org Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cbd0eaa05e17..06effcae0e3f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -408,6 +408,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, /* Realtek 8852AE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK | -- cgit v1.2.3 From aa17e8ce1c20619af46fc2b472aa2d1c5e50c3cc Mon Sep 17 00:00:00 2001 From: Ismael Ferreras Morezuelas Date: Tue, 18 Jan 2022 09:04:19 +0100 Subject: Bluetooth: btusb: Whitespace fixes for btusb_setup_csr() Properly align the list items of the quirk for readability. No functional changes intended. Trivial stuff. Fixes: 0671c0662383e ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers") Signed-off-by: Ismael Ferreras Morezuelas Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 06effcae0e3f..aefa0ee293f3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2062,10 +2062,10 @@ static int btusb_setup_csr(struct hci_dev *hdev) * These controllers are really messed-up. * * 1. Their bulk RX endpoint will never report any data unless - * the device was suspended at least once (yes, really). + * the device was suspended at least once (yes, really). * 2. They will not wakeup when autosuspended and receiving data - * on their bulk RX endpoint from e.g. a keyboard or mouse - * (IOW remote-wakeup support is broken for the bulk endpoint). + * on their bulk RX endpoint from e.g. a keyboard or mouse + * (IOW remote-wakeup support is broken for the bulk endpoint). * * To fix 1. enable runtime-suspend, force-suspend the * HCI and then wake-it up by disabling runtime-suspend. -- cgit v1.2.3 From a86974f75e8806bc357a9be02f9bde083f40b4ae Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Fri, 14 Jan 2022 17:03:29 -0800 Subject: Bluetooth: Remove kernel-doc style comment block This patch changes the kernel-doc style comment block to common comment block. These files don't support kernel-doc style so no need to use the kernel-doc style. Also, they cause the warning when W=1 option is used as below. drivers/bluetooth/hci_ll.c:518: warning: Function parameter or member 'lldev' not described in 'download_firmware' drivers/bluetooth/btmrvl_debugfs.c:29: warning: cannot understand function prototype: 'struct btmrvl_debugfs_data ' drivers/bluetooth/btmrvl_sdio.c:36: warning: expecting prototype for Marvell BT-over-SDIO driver(). Prototype was for VERSION() instead Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_debugfs.c | 2 +- drivers/bluetooth/btmrvl_sdio.c | 2 +- drivers/bluetooth/hci_ll.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index c4867576be00..db35b917aecf 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -1,4 +1,4 @@ -/** +/* * Marvell Bluetooth driver: debugfs related functions * * Copyright (C) 2009, Marvell International Ltd. diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 68378b42ea7f..b8ef66f89fc1 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -1,4 +1,4 @@ -/** +/* * Marvell BT-over-SDIO driver: SDIO interface related functions. * * Copyright (C) 2009, Marvell International Ltd. diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index eb1e736efeeb..4eb420a9ed04 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -509,7 +509,7 @@ static int send_command_from_firmware(struct ll_device *lldev, return 0; } -/** +/* * download_firmware - * internal function which parses through the .bts firmware * script file intreprets SEND, DELAY actions only as of now -- cgit v1.2.3 From 9d7cbe2b9cf5f650067df4f402fdd799d4bbb4e1 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 13 Jan 2022 16:27:04 +0300 Subject: Bluetooth: hci_serdev: call init_rwsem() before p->open() kvartet reported, that hci_uart_tx_wakeup() uses uninitialized rwsem. The problem was in wrong place for percpu_init_rwsem() call. hci_uart_proto::open() may register a timer whose callback may call hci_uart_tx_wakeup(). There is a chance, that hci_uart_register_device() thread won't be fast enough to call percpu_init_rwsem(). Fix it my moving percpu_init_rwsem() call before p->open(). INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator. CPU: 2 PID: 18524 Comm: syz-executor.5 Not tainted 5.16.0-rc6 #9 ... Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 assign_lock_key kernel/locking/lockdep.c:951 [inline] register_lock_class+0x148d/0x1950 kernel/locking/lockdep.c:1263 __lock_acquire+0x106/0x57e0 kernel/locking/lockdep.c:4906 lock_acquire kernel/locking/lockdep.c:5637 [inline] lock_acquire+0x1ab/0x520 kernel/locking/lockdep.c:5602 percpu_down_read_trylock include/linux/percpu-rwsem.h:92 [inline] hci_uart_tx_wakeup+0x12e/0x490 drivers/bluetooth/hci_ldisc.c:124 h5_timed_event+0x32f/0x6a0 drivers/bluetooth/hci_h5.c:188 call_timer_fn+0x1a5/0x6b0 kernel/time/timer.c:1421 Fixes: d73e17281665 ("Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops") Reported-by: Yiru Xu Signed-off-by: Pavel Skripkin Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 3b00d82d36cf..4cda890ce647 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -305,6 +305,8 @@ int hci_uart_register_device(struct hci_uart *hu, if (err) return err; + percpu_init_rwsem(&hu->proto_lock); + err = p->open(hu); if (err) goto err_open; @@ -327,7 +329,6 @@ int hci_uart_register_device(struct hci_uart *hu, INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); - percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the -- cgit v1.2.3 From 2fc967cc0dadad6735448cfbcbc77fe0ea30203d Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Wed, 12 Jan 2022 15:39:11 +0800 Subject: Bluetooth: mt7921s: fix firmware coredump retrieve According to the MCU firmware behavior, as the driver is aware of the notification of the interrupt source FW_MAILBOX_INT that shows the MCU completed delivered a core dump piece to the host, the driver must acknowledge the MCU with the register PH2DSM0R bit PH2DSM0R_DRIVER_OWN to notify the MCU to handle the next core dump piece. Fixes: db57b625912a ("Bluetooth: btmtksdio: add support of processing firmware coredump and log") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 25fb9c79b1f4..784e65c3fddd 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -87,8 +87,12 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define RX_DONE_INT BIT(1) #define TX_EMPTY BIT(2) #define TX_FIFO_OVERFLOW BIT(8) +#define FW_MAILBOX_INT BIT(15) #define RX_PKT_LEN GENMASK(31, 16) +#define MTK_REG_PH2DSM0R 0xc4 +#define PH2DSM0R_DRIVER_OWN BIT(0) + #define MTK_REG_CTDR 0x18 #define MTK_REG_CRDR 0x1c @@ -481,6 +485,12 @@ static void btmtksdio_txrx_work(struct work_struct *work) */ sdio_writel(bdev->func, int_status, MTK_REG_CHISR, NULL); + if ((int_status & FW_MAILBOX_INT) && + bdev->data->chipid == 0x7921) { + sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN, + MTK_REG_PH2DSM0R, 0); + } + if (int_status & FW_OWN_BACK_INT) bt_dev_dbg(bdev->hdev, "Get fw own back"); -- cgit v1.2.3 From c7e301d7c85544607ccc52ca5f26d20c59485342 Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Wed, 12 Jan 2022 15:39:12 +0800 Subject: Bluetooth: btmtksdio: refactor btmtksdio_runtime_[suspend|resume]() Refactor btmtksdio_runtime_[suspend|resume]() to create the common funcitons btmtksdio_[fw|drv]_pmctrl() shared with btmtksdio_[open|close]() to avoid the redundant code as well. This is also a prerequisite patch for the incoming patches. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 94 ++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 41 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 784e65c3fddd..8cbd49013d86 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -282,6 +282,54 @@ static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev) return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL); } +static int btmtksdio_fw_pmctrl(struct btmtksdio_dev *bdev) +{ + u32 status; + int err; + + sdio_claim_host(bdev->func); + + /* Return ownership to the device */ + sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err); + if (err < 0) + goto out; + + err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, + !(status & C_COM_DRV_OWN), 2000, 1000000); + +out: + sdio_release_host(bdev->func); + + if (err < 0) + bt_dev_err(bdev->hdev, "Cannot return ownership to device"); + + return err; +} + +static int btmtksdio_drv_pmctrl(struct btmtksdio_dev *bdev) +{ + u32 status; + int err; + + sdio_claim_host(bdev->func); + + /* Get ownership from the device */ + sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err); + if (err < 0) + goto out; + + err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, + status & C_COM_DRV_OWN, 2000, 1000000); + +out: + sdio_release_host(bdev->func); + + if (err < 0) + bt_dev_err(bdev->hdev, "Cannot get ownership from device"); + + return err; +} + static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); @@ -541,7 +589,7 @@ static void btmtksdio_interrupt(struct sdio_func *func) static int btmtksdio_open(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); - u32 status, val; + u32 val; int err; sdio_claim_host(bdev->func); @@ -552,18 +600,10 @@ static int btmtksdio_open(struct hci_dev *hdev) set_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state); - /* Get ownership from the device */ - sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err); + err = btmtksdio_drv_pmctrl(bdev); if (err < 0) goto err_disable_func; - err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, - status & C_COM_DRV_OWN, 2000, 1000000); - if (err < 0) { - bt_dev_err(bdev->hdev, "Cannot get ownership from device"); - goto err_disable_func; - } - /* Disable interrupt & mask out all interrupt sources */ sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, &err); if (err < 0) @@ -633,8 +673,6 @@ err_release_host: static int btmtksdio_close(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); - u32 status; - int err; sdio_claim_host(bdev->func); @@ -645,13 +683,7 @@ static int btmtksdio_close(struct hci_dev *hdev) cancel_work_sync(&bdev->txrx_work); - /* Return ownership to the device */ - sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, NULL); - - err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, - !(status & C_COM_DRV_OWN), 2000, 1000000); - if (err < 0) - bt_dev_err(bdev->hdev, "Cannot return ownership to device"); + btmtksdio_fw_pmctrl(bdev); clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state); sdio_disable_func(bdev->func); @@ -1162,7 +1194,6 @@ static int btmtksdio_runtime_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmtksdio_dev *bdev; - u32 status; int err; bdev = sdio_get_drvdata(func); @@ -1174,19 +1205,10 @@ static int btmtksdio_runtime_suspend(struct device *dev) sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - sdio_claim_host(bdev->func); - - sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err); - if (err < 0) - goto out; + err = btmtksdio_fw_pmctrl(bdev); - err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, - !(status & C_COM_DRV_OWN), 2000, 1000000); -out: bt_dev_info(bdev->hdev, "status (%d) return ownership to device", err); - sdio_release_host(bdev->func); - return err; } @@ -1194,7 +1216,6 @@ static int btmtksdio_runtime_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmtksdio_dev *bdev; - u32 status; int err; bdev = sdio_get_drvdata(func); @@ -1204,19 +1225,10 @@ static int btmtksdio_runtime_resume(struct device *dev) if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) return 0; - sdio_claim_host(bdev->func); - - sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err); - if (err < 0) - goto out; + err = btmtksdio_drv_pmctrl(bdev); - err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, - status & C_COM_DRV_OWN, 2000, 1000000); -out: bt_dev_info(bdev->hdev, "status (%d) get ownership from device", err); - sdio_release_host(bdev->func); - return err; } -- cgit v1.2.3 From 752aea58489fd42f5c54dc50cb098d19e486ae61 Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Wed, 12 Jan 2022 15:39:13 +0800 Subject: Bluetooth: mt7921s: fix bus hang with wrong privilege According to chip hw flow, mt7921s need to re-acquire privilege again before normal running. Otherwise, the bus may be stuck in an abnormal status. Fixes: c603bf1f94d0 ("Bluetooth: btmtksdio: add MT7921s Bluetooth support") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 8cbd49013d86..0951bb10d117 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -960,6 +960,14 @@ static int btmtksdio_setup(struct hci_dev *hdev) if (err < 0) return err; + err = btmtksdio_fw_pmctrl(bdev); + if (err < 0) + return err; + + err = btmtksdio_drv_pmctrl(bdev); + if (err < 0) + return err; + /* Enable SCO over I2S/PCM */ err = btmtksdio_sco_setting(hdev); if (err < 0) { -- cgit v1.2.3 From 01ecc177b7d7ba055b79645e60e89385736ef2fc Mon Sep 17 00:00:00 2001 From: Mark Chen Date: Wed, 12 Jan 2022 15:39:14 +0800 Subject: Bluetooth: mt7921s: fix btmtksdio_[drv|fw]_pmctrl() According to the firmware behavior (even the oldest one in linux-firmware) If the firmware is downloaded, MT7921S must rely on the additional mailbox mechanism that resides in firmware to check if the device is the right state for btmtksdio_mcu_[drv|fw]_pmctrl(). Otherwise, we still apply the old way for that. That is a necessary patch before we enable runtime pm for mt7921s as default. Fixes: c603bf1f94d0 ("Bluetooth: btmtksdio: add MT7921s Bluetooth support") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark Chen Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 0951bb10d117..b0aae4143037 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -38,21 +38,25 @@ static bool enable_autosuspend; struct btmtksdio_data { const char *fwname; u16 chipid; + bool lp_mbox_supported; }; static const struct btmtksdio_data mt7663_data = { .fwname = FIRMWARE_MT7663, .chipid = 0x7663, + .lp_mbox_supported = false, }; static const struct btmtksdio_data mt7668_data = { .fwname = FIRMWARE_MT7668, .chipid = 0x7668, + .lp_mbox_supported = false, }; static const struct btmtksdio_data mt7921_data = { .fwname = FIRMWARE_MT7961, .chipid = 0x7921, + .lp_mbox_supported = true, }; static const struct sdio_device_id btmtksdio_table[] = { @@ -90,8 +94,12 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define FW_MAILBOX_INT BIT(15) #define RX_PKT_LEN GENMASK(31, 16) +#define MTK_REG_CSICR 0xc0 +#define CSICR_CLR_MBOX_ACK BIT(0) #define MTK_REG_PH2DSM0R 0xc4 #define PH2DSM0R_DRIVER_OWN BIT(0) +#define MTK_REG_PD2HRM0R 0xdc +#define PD2HRM0R_DRV_OWN BIT(0) #define MTK_REG_CTDR 0x18 @@ -104,6 +112,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define BTMTKSDIO_TX_WAIT_VND_EVT 1 #define BTMTKSDIO_HW_TX_READY 2 #define BTMTKSDIO_FUNC_ENABLED 3 +#define BTMTKSDIO_PATCH_ENABLED 4 struct mtkbtsdio_hdr { __le16 len; @@ -282,6 +291,11 @@ static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev) return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL); } +static u32 btmtksdio_drv_own_query_79xx(struct btmtksdio_dev *bdev) +{ + return sdio_readl(bdev->func, MTK_REG_PD2HRM0R, NULL); +} + static int btmtksdio_fw_pmctrl(struct btmtksdio_dev *bdev) { u32 status; @@ -289,6 +303,19 @@ static int btmtksdio_fw_pmctrl(struct btmtksdio_dev *bdev) sdio_claim_host(bdev->func); + if (bdev->data->lp_mbox_supported && + test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state)) { + sdio_writel(bdev->func, CSICR_CLR_MBOX_ACK, MTK_REG_CSICR, + &err); + err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev, + status, !(status & PD2HRM0R_DRV_OWN), + 2000, 1000000); + if (err < 0) { + bt_dev_err(bdev->hdev, "mailbox ACK not cleared"); + goto out; + } + } + /* Return ownership to the device */ sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err); if (err < 0) @@ -321,6 +348,12 @@ static int btmtksdio_drv_pmctrl(struct btmtksdio_dev *bdev) err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status, status & C_COM_DRV_OWN, 2000, 1000000); + if (!err && bdev->data->lp_mbox_supported && + test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state)) + err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev, + status, status & PD2HRM0R_DRV_OWN, + 2000, 1000000); + out: sdio_release_host(bdev->func); @@ -728,6 +761,7 @@ static int btmtksdio_func_query(struct hci_dev *hdev) static int mt76xx_setup(struct hci_dev *hdev, const char *fwname) { + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); struct btmtk_hci_wmt_params wmt_params; struct btmtk_tci_sleep tci_sleep; struct sk_buff *skb; @@ -788,6 +822,8 @@ ignore_setup_fw: return err; } + set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state); + ignore_func_on: /* Apply the low power environment setup */ tci_sleep.mode = 0x5; @@ -810,6 +846,7 @@ ignore_func_on: static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) { + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); struct btmtk_hci_wmt_params wmt_params; u8 param = 0x1; int err; @@ -835,6 +872,7 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) hci_set_msft_opcode(hdev, 0xFD30); hci_set_aosp_capable(hdev); + set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state); return err; } -- cgit v1.2.3 From 095519de2debef7666d519208ac2e7bc96cfa6bf Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 12 Jan 2022 15:39:15 +0800 Subject: Bluetooth: btmtksdio: lower log level in btmtksdio_runtime_[resume|suspend]() Lower its log level from INFO to DEBUG prior to we enable runtime pm for mt7921s with the smaller idle time as default. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index b0aae4143037..3e8f19556e2c 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -1253,7 +1253,7 @@ static int btmtksdio_runtime_suspend(struct device *dev) err = btmtksdio_fw_pmctrl(bdev); - bt_dev_info(bdev->hdev, "status (%d) return ownership to device", err); + bt_dev_dbg(bdev->hdev, "status (%d) return ownership to device", err); return err; } @@ -1273,7 +1273,7 @@ static int btmtksdio_runtime_resume(struct device *dev) err = btmtksdio_drv_pmctrl(bdev); - bt_dev_info(bdev->hdev, "status (%d) get ownership from device", err); + bt_dev_dbg(bdev->hdev, "status (%d) get ownership from device", err); return err; } -- cgit v1.2.3 From e98aa38cafec489ec025572c529dfb3d64559718 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 12 Jan 2022 15:39:16 +0800 Subject: Bluetooth: btmtksdio: run sleep mode by default Apply sleep mode by default and a smaller idle time to reduce power consumption further. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 3e8f19556e2c..491f029452ca 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -31,9 +31,9 @@ #define VERSION "0.1" -#define MTKBTSDIO_AUTOSUSPEND_DELAY 8000 +#define MTKBTSDIO_AUTOSUSPEND_DELAY 1000 -static bool enable_autosuspend; +static bool enable_autosuspend = true; struct btmtksdio_data { const char *fwname; -- cgit v1.2.3 From db3f1f9b5d88d8d7f9eaa486f71784dd319285ff Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 12 Jan 2022 15:39:17 +0800 Subject: Bluetooth: btmtksdio: mask out interrupt status Currently, there is a loop in btmtksdio_txrx_work() which iteratively executes until the variable int_status is zero. But the variable int_status should be masked out with the actual interrupt sources (MTK_REG_CHISR bit 0-15) before we check the loop condition. Otherwise, RX_PKT_LEN (MTK_REG_CHISR bit 16-31) which is read-only and unclearable would cause the loop to get stuck on some chipsets like MT7663s. Fixes: 26270bc189ea ("Bluetooth: btmtksdio: move interrupt service to work") Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtksdio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 491f029452ca..8be763ab3bf4 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -92,6 +92,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define TX_EMPTY BIT(2) #define TX_FIFO_OVERFLOW BIT(8) #define FW_MAILBOX_INT BIT(15) +#define INT_MASK GENMASK(15, 0) #define RX_PKT_LEN GENMASK(31, 16) #define MTK_REG_CSICR 0xc0 @@ -565,6 +566,7 @@ static void btmtksdio_txrx_work(struct work_struct *work) * FIFO. */ sdio_writel(bdev->func, int_status, MTK_REG_CHISR, NULL); + int_status &= INT_MASK; if ((int_status & FW_MAILBOX_INT) && bdev->data->chipid == 0x7921) { -- cgit v1.2.3 From b050c5bbbccfb9e6cbf29c8ee7a41c1bba972bdf Mon Sep 17 00:00:00 2001 From: Vyacheslav Bocharov Date: Wed, 26 Jan 2022 10:39:04 +0300 Subject: Bluetooth: btrtl: Add support for RTL8822C hci_ver 0x08 Add a variation of RTL8822CS with hci_ver = 0x08. This is fully similar to RTL8822CS with hci_ver = 0x0a observed on the Tanix TX6 Android set-top box and JetHome JetHub H1. Signed-off-by: Vyacheslav Bocharov Signed-off-by: Rudi Heitbaum Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index c2bdd1e6060e..c2030f7e25b4 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -148,6 +148,14 @@ static const struct id_table ic_id_table[] = { .fw_name = "rtl_bt/rtl8761bu_fw.bin", .cfg_name = "rtl_bt/rtl8761bu_config" }, + /* 8822C with UART interface */ + { IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0x8, HCI_UART), + .config_needed = true, + .has_rom_version = true, + .has_msft_ext = true, + .fw_name = "rtl_bt/rtl8822cs_fw.bin", + .cfg_name = "rtl_bt/rtl8822cs_config" }, + /* 8822C with UART interface */ { IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART), .config_needed = true, -- cgit v1.2.3 From adce573b927adf827f2f8627f05c2ba90031ebc9 Mon Sep 17 00:00:00 2001 From: Vyacheslav Bocharov Date: Wed, 26 Jan 2022 10:39:05 +0300 Subject: Bluetooth: hci_h5: Add power reset via gpio in h5_btrtl_open Add power reset for bluetooth via enable-gpios in h5_btrtl_open function. While testing the RTL8822CS SDIO WiFi/BT adapter, it was found that in some cases the kernel could not initialize BT firmware. However, manually resetting the adapter via gpio (off/on sequence) allows it to start correctly. Apparently, when the system starts, the adapter is in an undefined state (including unknown gpio state after starting uboot). A forced reset helps to initialize the adapter in most cases. It has been found experimentally that 100 ms is sufficient for a reset. Signed-off-by: Vyacheslav Bocharov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_h5.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 34286ffe0568..fdf504b0d265 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -966,6 +966,11 @@ static void h5_btrtl_open(struct h5 *h5) pm_runtime_enable(&h5->hu->serdev->dev); } + /* The controller needs reset to startup */ + gpiod_set_value_cansleep(h5->enable_gpio, 0); + gpiod_set_value_cansleep(h5->device_wake_gpio, 0); + msleep(100); + /* The controller needs up to 500ms to wakeup */ gpiod_set_value_cansleep(h5->enable_gpio, 1); gpiod_set_value_cansleep(h5->device_wake_gpio, 1); -- cgit v1.2.3