From patchwork Mon Oct 18 21:30:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568131 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2927BC433EF for ; Mon, 18 Oct 2021 21:37:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0464D60F11 for ; Mon, 18 Oct 2021 21:37:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229555AbhJRVjt (ORCPT ); Mon, 18 Oct 2021 17:39:49 -0400 Received: from mailgw02.mediatek.com ([216.200.240.185]:26640 "EHLO mailgw02.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232549AbhJRVjr (ORCPT ); Mon, 18 Oct 2021 17:39:47 -0400 X-UUID: eb5871de9be64c6bb285f517cd5b2737-20211018 X-UUID: eb5871de9be64c6bb285f517cd5b2737-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1459930928; Mon, 18 Oct 2021 14:37:31 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:29 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:27 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v2 01/10] Bluetooth: mediatek: add BT_MTK module Date: Tue, 19 Oct 2021 05:30:12 +0800 Message-ID: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang Add BT_MTK module that is a preliminary patch to introduce mt7921s support to share the logic betweem btusb and btmtksdio. Signed-off-by: Sean Wang --- drivers/bluetooth/Kconfig | 5 + drivers/bluetooth/Makefile | 1 + drivers/bluetooth/btmtk.c | 289 ++++++++++++++++++++++++++++++++ drivers/bluetooth/btmtk.h | 97 +++++++++++ drivers/bluetooth/btusb.c | 331 +------------------------------------ 5 files changed, 398 insertions(+), 325 deletions(-) create mode 100644 drivers/bluetooth/btmtk.c create mode 100644 drivers/bluetooth/btmtk.h diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 851842372c9b..24c3aea4a7d6 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -19,6 +19,10 @@ config BT_QCA tristate select FW_LOADER +config BT_MTK + tristate + select FW_LOADER + config BT_HCIBTUSB tristate "HCI USB driver" depends on USB @@ -55,6 +59,7 @@ config BT_HCIBTUSB_BCM config BT_HCIBTUSB_MTK bool "MediaTek protocol support" depends on BT_HCIBTUSB + select BT_MTK default n help The MediaTek protocol support enables firmware download diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 16286ea2655d..3321a8aea4a0 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o obj-$(CONFIG_BT_BCM) += btbcm.o obj-$(CONFIG_BT_RTL) += btrtl.o obj-$(CONFIG_BT_QCA) += btqca.o +obj-$(CONFIG_BT_MTK) += btmtk.o obj-$(CONFIG_BT_VIRTIO) += virtio_bt.o diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c new file mode 100644 index 000000000000..c2ee5c4b975a --- /dev/null +++ b/drivers/bluetooth/btmtk.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2021 MediaTek Inc. + * + */ +#include +#include + +#include +#include + +#include "btmtk.h" + +#define VERSION "0.1" + +/* It is for mt79xx download rom patch*/ +#define MTK_FW_ROM_PATCH_HEADER_SIZE 32 +#define MTK_FW_ROM_PATCH_GD_SIZE 64 +#define MTK_FW_ROM_PATCH_SEC_MAP_SIZE 64 +#define MTK_SEC_MAP_COMMON_SIZE 12 +#define MTK_SEC_MAP_NEED_SEND_SIZE 52 + +struct btmtk_patch_header { + u8 datetime[16]; + u8 platform[4]; + __le16 hwver; + __le16 swver; + __le32 magicnum; +} __packed; + +struct btmtk_global_desc { + __le32 patch_ver; + __le32 sub_sys; + __le32 feature_opt; + __le32 section_num; +} __packed; + +struct btmtk_section_map { + __le32 sectype; + __le32 secoffset; + __le32 secsize; + union { + __le32 u4SecSpec[13]; + struct { + __le32 dlAddr; + __le32 dlsize; + __le32 seckeyidx; + __le32 alignlen; + __le32 sectype; + __le32 dlmodecrctype; + __le32 crc; + __le32 reserved[6]; + } bin_info_spec; + }; +} __packed; + +int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync) +{ + struct btmtk_hci_wmt_params wmt_params; + struct btmtk_global_desc *globaldesc = NULL; + struct btmtk_section_map *sectionmap; + const struct firmware *fw; + const u8 *fw_ptr; + const u8 *fw_bin_ptr; + int err, dlen, i, status; + u8 flag, first_block, retry; + u32 section_num, dl_size, section_offset; + u8 cmd[64]; + + err = request_firmware(&fw, fwname, &hdev->dev); + if (err < 0) { + bt_dev_err(hdev, "Failed to load firmware file (%d)", err); + return err; + } + + fw_ptr = fw->data; + fw_bin_ptr = fw_ptr; + globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE); + section_num = le32_to_cpu(globaldesc->section_num); + + for (i = 0; i < section_num; i++) { + first_block = 1; + fw_ptr = fw_bin_ptr; + sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE + + MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i); + + section_offset = le32_to_cpu(sectionmap->secoffset); + dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize); + + if (dl_size > 0) { + retry = 20; + while (retry > 0) { + cmd[0] = 0; /* 0 means legacy dl mode. */ + memcpy(cmd + 1, + fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE + + MTK_FW_ROM_PATCH_GD_SIZE + + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i + + MTK_SEC_MAP_COMMON_SIZE, + MTK_SEC_MAP_NEED_SEND_SIZE + 1); + + wmt_params.op = BTMTK_WMT_PATCH_DWNLD; + wmt_params.status = &status; + wmt_params.flag = 0; + wmt_params.dlen = MTK_SEC_MAP_NEED_SEND_SIZE + 1; + wmt_params.data = &cmd; + + err = wmt_cmd_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", + err); + goto err_release_fw; + } + + if (status == BTMTK_WMT_PATCH_UNDONE) { + break; + } else if (status == BTMTK_WMT_PATCH_PROGRESS) { + msleep(100); + retry--; + } else if (status == BTMTK_WMT_PATCH_DONE) { + goto next_section; + } else { + bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)", + status); + goto err_release_fw; + } + } + + fw_ptr += section_offset; + wmt_params.op = BTMTK_WMT_PATCH_DWNLD; + wmt_params.status = NULL; + + while (dl_size > 0) { + dlen = min_t(int, 250, dl_size); + if (first_block == 1) { + flag = 1; + first_block = 0; + } else if (dl_size - dlen <= 0) { + flag = 3; + } else { + flag = 2; + } + + wmt_params.flag = flag; + wmt_params.dlen = dlen; + wmt_params.data = fw_ptr; + + err = wmt_cmd_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", + err); + goto err_release_fw; + } + + dl_size -= dlen; + fw_ptr += dlen; + } + } +next_section: + continue; + } + /* Wait a few moments for firmware activation done */ + usleep_range(100000, 120000); + +err_release_fw: + release_firmware(fw); + + return err; +} +EXPORT_SYMBOL_GPL(btmtk_setup_firmware_79xx); + +int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync) +{ + struct btmtk_hci_wmt_params wmt_params; + const struct firmware *fw; + const u8 *fw_ptr; + size_t fw_size; + int err, dlen; + u8 flag, param; + + err = request_firmware(&fw, fwname, &hdev->dev); + if (err < 0) { + bt_dev_err(hdev, "Failed to load firmware file (%d)", err); + return err; + } + + /* Power on data RAM the firmware relies on. */ + param = 1; + wmt_params.op = BTMTK_WMT_FUNC_CTRL; + wmt_params.flag = 3; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = wmt_cmd_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to power on data RAM (%d)", err); + goto err_release_fw; + } + + fw_ptr = fw->data; + fw_size = fw->size; + + /* The size of patch header is 30 bytes, should be skip */ + if (fw_size < 30) { + err = -EINVAL; + goto err_release_fw; + } + + fw_size -= 30; + fw_ptr += 30; + flag = 1; + + wmt_params.op = BTMTK_WMT_PATCH_DWNLD; + wmt_params.status = NULL; + + while (fw_size > 0) { + dlen = min_t(int, 250, fw_size); + + /* Tell device the position in sequence */ + if (fw_size - dlen <= 0) + flag = 3; + else if (fw_size < fw->size - 30) + flag = 2; + + wmt_params.flag = flag; + wmt_params.dlen = dlen; + wmt_params.data = fw_ptr; + + err = wmt_cmd_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", + err); + goto err_release_fw; + } + + fw_size -= dlen; + fw_ptr += dlen; + } + + wmt_params.op = BTMTK_WMT_RST; + wmt_params.flag = 4; + wmt_params.dlen = 0; + wmt_params.data = NULL; + wmt_params.status = NULL; + + /* Activate funciton the firmware providing to */ + err = wmt_cmd_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); + goto err_release_fw; + } + + /* Wait a few moments for firmware activation done */ + usleep_range(10000, 12000); + +err_release_fw: + release_firmware(fw); + + return err; +} +EXPORT_SYMBOL_GPL(btmtk_setup_firmware); + +int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + struct sk_buff *skb; + long ret; + + skb = __hci_cmd_sync(hdev, 0xfc1a, 6, bdaddr, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + bt_dev_err(hdev, "changing Mediatek device address failed (%ld)", + ret); + return ret; + } + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(btmtk_set_bdaddr); + +MODULE_AUTHOR("Sean Wang "); +MODULE_AUTHOR("Mark Chen "); +MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE_MT7663); +MODULE_FIRMWARE(FIRMWARE_MT7668); +MODULE_FIRMWARE(FIRMWARE_MT7961); diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h new file mode 100644 index 000000000000..87c25c6cf969 --- /dev/null +++ b/drivers/bluetooth/btmtk.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2021 MediaTek Inc. */ + +#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" +#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" +#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin" + +#define HCI_WMT_MAX_EVENT_SIZE 64 + +enum { + BTMTK_WMT_PATCH_DWNLD = 0x1, + BTMTK_WMT_FUNC_CTRL = 0x6, + BTMTK_WMT_RST = 0x7, + BTMTK_WMT_SEMAPHORE = 0x17, +}; + +enum { + BTMTK_WMT_INVALID, + BTMTK_WMT_PATCH_UNDONE, + BTMTK_WMT_PATCH_PROGRESS, + BTMTK_WMT_PATCH_DONE, + BTMTK_WMT_ON_UNDONE, + BTMTK_WMT_ON_DONE, + BTMTK_WMT_ON_PROGRESS, +}; + +struct btmtk_wmt_hdr { + u8 dir; + u8 op; + __le16 dlen; + u8 flag; +} __packed; + +struct btmtk_hci_wmt_cmd { + struct btmtk_wmt_hdr hdr; + u8 data[]; +} __packed; + +struct btmtk_hci_wmt_evt { + struct hci_event_hdr hhdr; + struct btmtk_wmt_hdr whdr; +} __packed; + +struct btmtk_hci_wmt_evt_funcc { + struct btmtk_hci_wmt_evt hwhdr; + __be16 status; +} __packed; + +struct btmtk_tci_sleep { + u8 mode; + __le16 duration; + __le16 host_duration; + u8 host_wakeup_pin; + u8 time_compensation; +} __packed; + +struct btmtk_hci_wmt_params { + u8 op; + u8 flag; + u16 dlen; + const void *data; + u32 *status; +}; + +typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *, + struct btmtk_hci_wmt_params *); + +#if IS_ENABLED(CONFIG_BT_MTK) + +int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); + +int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync); + +int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync); +#else + +static inline int btmtk_set_bdaddr(struct hci_dev *hdev, + const bdaddr_t *bdaddr) +{ + return -EOPNOTSUPP; +} + +static int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync) +{ + return -EOPNOTSUPP; +} + +static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, + wmt_cmd_sync_func_t wmt_cmd_sync) +{ + return -EOPNOTSUPP; +} + +#endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 87b71740fad8..88bfdf1347a7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -24,6 +24,7 @@ #include "btintel.h" #include "btbcm.h" #include "btrtl.h" +#include "btmtk.h" #define VERSION "0.8" @@ -2131,122 +2132,6 @@ static int btusb_send_frame_intel(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 FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" -#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" - -#define HCI_WMT_MAX_EVENT_SIZE 64 -/* It is for mt79xx download rom patch*/ -#define MTK_FW_ROM_PATCH_HEADER_SIZE 32 -#define MTK_FW_ROM_PATCH_GD_SIZE 64 -#define MTK_FW_ROM_PATCH_SEC_MAP_SIZE 64 -#define MTK_SEC_MAP_COMMON_SIZE 12 -#define MTK_SEC_MAP_NEED_SEND_SIZE 52 - -enum { - BTMTK_WMT_PATCH_DWNLD = 0x1, - BTMTK_WMT_FUNC_CTRL = 0x6, - BTMTK_WMT_RST = 0x7, - BTMTK_WMT_SEMAPHORE = 0x17, -}; - -enum { - BTMTK_WMT_INVALID, - BTMTK_WMT_PATCH_UNDONE, - BTMTK_WMT_PATCH_PROGRESS, - BTMTK_WMT_PATCH_DONE, - BTMTK_WMT_ON_UNDONE, - BTMTK_WMT_ON_DONE, - BTMTK_WMT_ON_PROGRESS, -}; - -struct btmtk_wmt_hdr { - u8 dir; - u8 op; - __le16 dlen; - u8 flag; -} __packed; - -struct btmtk_hci_wmt_cmd { - struct btmtk_wmt_hdr hdr; - u8 data[]; -} __packed; - -struct btmtk_hci_wmt_evt { - struct hci_event_hdr hhdr; - struct btmtk_wmt_hdr whdr; -} __packed; - -struct btmtk_hci_wmt_evt_funcc { - struct btmtk_hci_wmt_evt hwhdr; - __be16 status; -} __packed; - -struct btmtk_tci_sleep { - u8 mode; - __le16 duration; - __le16 host_duration; - u8 host_wakeup_pin; - u8 time_compensation; -} __packed; - -struct btmtk_hci_wmt_params { - u8 op; - u8 flag; - u16 dlen; - const void *data; - u32 *status; -}; - -struct btmtk_patch_header { - u8 datetime[16]; - u8 platform[4]; - __le16 hwver; - __le16 swver; - __le32 magicnum; -} __packed; - -struct btmtk_global_desc { - __le32 patch_ver; - __le32 sub_sys; - __le32 feature_opt; - __le32 section_num; -} __packed; - -struct btmtk_section_map { - __le32 sectype; - __le32 secoffset; - __le32 secsize; - union { - __le32 u4SecSpec[13]; - struct { - __le32 dlAddr; - __le32 dlsize; - __le32 seckeyidx; - __le32 alignlen; - __le32 sectype; - __le32 dlmodecrctype; - __le32 crc; - __le32 reserved[6]; - } bin_info_spec; - }; -} __packed; - -static int btusb_set_bdaddr_mtk(struct hci_dev *hdev, const bdaddr_t *bdaddr) -{ - struct sk_buff *skb; - long ret; - - skb = __hci_cmd_sync(hdev, 0xfc1a, 6, bdaddr, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - ret = PTR_ERR(skb); - bt_dev_err(hdev, "changing Mediatek device address failed (%ld)", - ret); - return ret; - } - kfree_skb(skb); - - return 0; -} static void btusb_mtk_wmt_recv(struct urb *urb) { @@ -2502,209 +2387,6 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, return err; } -static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname) -{ - struct btmtk_hci_wmt_params wmt_params; - struct btmtk_global_desc *globaldesc = NULL; - struct btmtk_section_map *sectionmap; - const struct firmware *fw; - const u8 *fw_ptr; - const u8 *fw_bin_ptr; - int err, dlen, i, status; - u8 flag, first_block, retry; - u32 section_num, dl_size, section_offset; - u8 cmd[64]; - - err = request_firmware(&fw, fwname, &hdev->dev); - if (err < 0) { - bt_dev_err(hdev, "Failed to load firmware file (%d)", err); - return err; - } - - fw_ptr = fw->data; - fw_bin_ptr = fw_ptr; - globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE); - section_num = le32_to_cpu(globaldesc->section_num); - - for (i = 0; i < section_num; i++) { - first_block = 1; - fw_ptr = fw_bin_ptr; - sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE + - MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i); - - section_offset = le32_to_cpu(sectionmap->secoffset); - dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize); - - if (dl_size > 0) { - retry = 20; - while (retry > 0) { - cmd[0] = 0; /* 0 means legacy dl mode. */ - memcpy(cmd + 1, - fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE + - MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i + - MTK_SEC_MAP_COMMON_SIZE, - MTK_SEC_MAP_NEED_SEND_SIZE + 1); - - wmt_params.op = BTMTK_WMT_PATCH_DWNLD; - wmt_params.status = &status; - wmt_params.flag = 0; - wmt_params.dlen = MTK_SEC_MAP_NEED_SEND_SIZE + 1; - wmt_params.data = &cmd; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", - err); - goto err_release_fw; - } - - if (status == BTMTK_WMT_PATCH_UNDONE) { - break; - } else if (status == BTMTK_WMT_PATCH_PROGRESS) { - msleep(100); - retry--; - } else if (status == BTMTK_WMT_PATCH_DONE) { - goto next_section; - } else { - bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)", - status); - goto err_release_fw; - } - } - - fw_ptr += section_offset; - wmt_params.op = BTMTK_WMT_PATCH_DWNLD; - wmt_params.status = NULL; - - while (dl_size > 0) { - dlen = min_t(int, 250, dl_size); - if (first_block == 1) { - flag = 1; - first_block = 0; - } else if (dl_size - dlen <= 0) { - flag = 3; - } else { - flag = 2; - } - - wmt_params.flag = flag; - wmt_params.dlen = dlen; - wmt_params.data = fw_ptr; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", - err); - goto err_release_fw; - } - - dl_size -= dlen; - fw_ptr += dlen; - } - } -next_section: - continue; - } - /* Wait a few moments for firmware activation done */ - usleep_range(100000, 120000); - -err_release_fw: - release_firmware(fw); - - return err; -} - -static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) -{ - struct btmtk_hci_wmt_params wmt_params; - const struct firmware *fw; - const u8 *fw_ptr; - size_t fw_size; - int err, dlen; - u8 flag, param; - - err = request_firmware(&fw, fwname, &hdev->dev); - if (err < 0) { - bt_dev_err(hdev, "Failed to load firmware file (%d)", err); - return err; - } - - /* Power on data RAM the firmware relies on. */ - param = 1; - wmt_params.op = BTMTK_WMT_FUNC_CTRL; - wmt_params.flag = 3; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = NULL; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to power on data RAM (%d)", err); - goto err_release_fw; - } - - fw_ptr = fw->data; - fw_size = fw->size; - - /* The size of patch header is 30 bytes, should be skip */ - if (fw_size < 30) { - err = -EINVAL; - goto err_release_fw; - } - - fw_size -= 30; - fw_ptr += 30; - flag = 1; - - wmt_params.op = BTMTK_WMT_PATCH_DWNLD; - wmt_params.status = NULL; - - while (fw_size > 0) { - dlen = min_t(int, 250, fw_size); - - /* Tell device the position in sequence */ - if (fw_size - dlen <= 0) - flag = 3; - else if (fw_size < fw->size - 30) - flag = 2; - - wmt_params.flag = flag; - wmt_params.dlen = dlen; - wmt_params.data = fw_ptr; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", - err); - goto err_release_fw; - } - - fw_size -= dlen; - fw_ptr += dlen; - } - - wmt_params.op = BTMTK_WMT_RST; - wmt_params.flag = 4; - wmt_params.dlen = 0; - wmt_params.data = NULL; - wmt_params.status = NULL; - - /* Activate funciton the firmware providing to */ - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); - goto err_release_fw; - } - - /* Wait a few moments for firmware activation done */ - usleep_range(10000, 12000); - -err_release_fw: - release_firmware(fw); - - return err; -} - static int btusb_mtk_func_query(struct hci_dev *hdev) { struct btmtk_hci_wmt_params wmt_params; @@ -2862,7 +2544,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev) 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 = btusb_mtk_setup_firmware_79xx(hdev, fw_bin_name); + err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, + btusb_mtk_hci_wmt_sync); /* It's Device EndPoint Reset Option Register */ btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); @@ -2908,7 +2591,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev) } /* Setup a firmware which the device definitely requires */ - err = btusb_mtk_setup_firmware(hdev, fwname); + err = btmtk_setup_firmware(hdev, fwname, + btusb_mtk_hci_wmt_sync); if (err < 0) return err; @@ -3069,9 +2753,6 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb) return hci_recv_frame(hdev, skb); } -MODULE_FIRMWARE(FIRMWARE_MT7663); -MODULE_FIRMWARE(FIRMWARE_MT7668); - #ifdef CONFIG_PM /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */ static int marvell_config_oob_wake(struct hci_dev *hdev) @@ -3873,7 +3554,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; hdev->cmd_timeout = btusb_mtk_cmd_timeout; - hdev->set_bdaddr = btusb_set_bdaddr_mtk; + hdev->set_bdaddr = btmtk_set_bdaddr; set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); data->recv_acl = btusb_recv_acl_mtk; } From patchwork Mon Oct 18 21:30:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568115 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64CDAC433EF for ; Mon, 18 Oct 2021 21:30:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 447FE6113D for ; Mon, 18 Oct 2021 21:30:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232815AbhJRVct (ORCPT ); Mon, 18 Oct 2021 17:32:49 -0400 Received: from mailgw02.mediatek.com ([216.200.240.185]:24721 "EHLO mailgw02.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbhJRVct (ORCPT ); Mon, 18 Oct 2021 17:32:49 -0400 X-UUID: 4caaa648d7ec4175b7851ca336735ebc-20211018 X-UUID: 4caaa648d7ec4175b7851ca336735ebc-20211018 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 730971796; Mon, 18 Oct 2021 14:30:35 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:33 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:32 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v2 02/10] Bluetooth: btmtksido: rely on BT_MTK module Date: Tue, 19 Oct 2021 05:30:13 +0800 Message-ID: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang Rely on btmtk module to reduce duplicated code Signed-off-by: Sean Wang --- drivers/bluetooth/Kconfig | 1 + drivers/bluetooth/btmtk.h | 3 + drivers/bluetooth/btmtksdio.c | 192 +++++----------------------------- 3 files changed, 28 insertions(+), 168 deletions(-) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 24c3aea4a7d6..36380e618ba4 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -388,6 +388,7 @@ config BT_ATH3K config BT_MTKSDIO tristate "MediaTek HCI SDIO driver" depends on MMC + select BT_MTK help MediaTek Bluetooth HCI SDIO driver. This driver is required if you want to use MediaTek Bluetooth diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 87c25c6cf969..18f43c641b3b 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -9,6 +9,9 @@ enum { BTMTK_WMT_PATCH_DWNLD = 0x1, + BTMTK_WMT_TEST = 0x2, + BTMTK_WMT_WAKEUP = 0x3, + BTMTK_WMT_HIF = 0x4, BTMTK_WMT_FUNC_CTRL = 0x6, BTMTK_WMT_RST = 0x7, BTMTK_WMT_SEMAPHORE = 0x17, diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 9872ef18f9fe..53682a4c2ced 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -28,12 +27,10 @@ #include #include "h4_recv.h" +#include "btmtk.h" #define VERSION "0.1" -#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" -#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" - #define MTKBTSDIO_AUTOSUSPEND_DELAY 8000 static bool enable_autosuspend; @@ -90,69 +87,12 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define BTMTKSDIO_TX_WAIT_VND_EVT 1 -enum { - MTK_WMT_PATCH_DWNLD = 0x1, - MTK_WMT_TEST = 0x2, - MTK_WMT_WAKEUP = 0x3, - MTK_WMT_HIF = 0x4, - MTK_WMT_FUNC_CTRL = 0x6, - MTK_WMT_RST = 0x7, - MTK_WMT_SEMAPHORE = 0x17, -}; - -enum { - BTMTK_WMT_INVALID, - BTMTK_WMT_PATCH_UNDONE, - BTMTK_WMT_PATCH_DONE, - BTMTK_WMT_ON_UNDONE, - BTMTK_WMT_ON_DONE, - BTMTK_WMT_ON_PROGRESS, -}; - struct mtkbtsdio_hdr { __le16 len; __le16 reserved; u8 bt_type; } __packed; -struct mtk_wmt_hdr { - u8 dir; - u8 op; - __le16 dlen; - u8 flag; -} __packed; - -struct mtk_hci_wmt_cmd { - struct mtk_wmt_hdr hdr; - u8 data[256]; -} __packed; - -struct btmtk_hci_wmt_evt { - struct hci_event_hdr hhdr; - struct mtk_wmt_hdr whdr; -} __packed; - -struct btmtk_hci_wmt_evt_funcc { - struct btmtk_hci_wmt_evt hwhdr; - __be16 status; -} __packed; - -struct btmtk_tci_sleep { - u8 mode; - __le16 duration; - __le16 host_duration; - u8 host_wakeup_pin; - u8 time_compensation; -} __packed; - -struct btmtk_hci_wmt_params { - u8 op; - u8 flag; - u16 dlen; - const void *data; - u32 *status; -}; - struct btmtksdio_dev { struct hci_dev *hdev; struct sdio_func *func; @@ -174,27 +114,32 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; u32 hlen, status = BTMTK_WMT_INVALID; struct btmtk_hci_wmt_evt *wmt_evt; - struct mtk_hci_wmt_cmd wc; - struct mtk_wmt_hdr *hdr; + struct btmtk_hci_wmt_cmd *wc; + struct btmtk_wmt_hdr *hdr; int err; + /* Send the WMT command and wait until the WMT event returns */ hlen = sizeof(*hdr) + wmt_params->dlen; if (hlen > 255) return -EINVAL; - hdr = (struct mtk_wmt_hdr *)&wc; + wc = kzalloc(hlen, GFP_KERNEL); + if (!wc) + return -ENOMEM; + + hdr = &wc->hdr; hdr->dir = 1; hdr->op = wmt_params->op; hdr->dlen = cpu_to_le16(wmt_params->dlen + 1); hdr->flag = wmt_params->flag; - memcpy(wc.data, wmt_params->data, wmt_params->dlen); + memcpy(wc->data, wmt_params->data, wmt_params->dlen); set_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state); - err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); + err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc); if (err < 0) { clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state); - return err; + goto err_free_wc; } /* The vendor specific WMT commands are all answered by a vendor @@ -211,13 +156,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, if (err == -EINTR) { bt_dev_err(hdev, "Execution of wmt command interrupted"); clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state); - return err; + goto err_free_wc; } if (err) { bt_dev_err(hdev, "Execution of wmt command timed out"); clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state); - return -ETIMEDOUT; + err = -ETIMEDOUT; + goto err_free_wc; } /* Parse and handle the return WMT event */ @@ -230,13 +176,13 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, } switch (wmt_evt->whdr.op) { - case MTK_WMT_SEMAPHORE: + case BTMTK_WMT_SEMAPHORE: if (wmt_evt->whdr.flag == 2) status = BTMTK_WMT_PATCH_UNDONE; else status = BTMTK_WMT_PATCH_DONE; break; - case MTK_WMT_FUNC_CTRL: + case BTMTK_WMT_FUNC_CTRL: wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) status = BTMTK_WMT_ON_DONE; @@ -253,6 +199,8 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, err_free_skb: kfree_skb(bdev->evt_skb); bdev->evt_skb = NULL; +err_free_wc: + kfree(wc); return err; } @@ -663,7 +611,7 @@ static int btmtksdio_func_query(struct hci_dev *hdev) u8 param = 0; /* Query whether the function is enabled */ - wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.op = BTMTK_WMT_FUNC_CTRL; wmt_params.flag = 4; wmt_params.dlen = sizeof(param); wmt_params.data = ¶m; @@ -678,96 +626,6 @@ static int btmtksdio_func_query(struct hci_dev *hdev) return status; } -static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) -{ - struct btmtk_hci_wmt_params wmt_params; - const struct firmware *fw; - const u8 *fw_ptr; - size_t fw_size; - int err, dlen; - u8 flag, param; - - err = request_firmware(&fw, fwname, &hdev->dev); - if (err < 0) { - bt_dev_err(hdev, "Failed to load firmware file (%d)", err); - return err; - } - - /* Power on data RAM the firmware relies on. */ - param = 1; - wmt_params.op = MTK_WMT_FUNC_CTRL; - wmt_params.flag = 3; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = NULL; - - err = mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to power on data RAM (%d)", err); - goto free_fw; - } - - fw_ptr = fw->data; - fw_size = fw->size; - - /* The size of patch header is 30 bytes, should be skip */ - if (fw_size < 30) { - err = -EINVAL; - goto free_fw; - } - - fw_size -= 30; - fw_ptr += 30; - flag = 1; - - wmt_params.op = MTK_WMT_PATCH_DWNLD; - wmt_params.status = NULL; - - while (fw_size > 0) { - dlen = min_t(int, 250, fw_size); - - /* Tell device the position in sequence */ - if (fw_size - dlen <= 0) - flag = 3; - else if (fw_size < fw->size - 30) - flag = 2; - - wmt_params.flag = flag; - wmt_params.dlen = dlen; - wmt_params.data = fw_ptr; - - err = mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", - err); - goto free_fw; - } - - fw_size -= dlen; - fw_ptr += dlen; - } - - wmt_params.op = MTK_WMT_RST; - wmt_params.flag = 4; - wmt_params.dlen = 0; - wmt_params.data = NULL; - wmt_params.status = NULL; - - /* Activate funciton the firmware providing to */ - err = mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); - goto free_fw; - } - - /* Wait a few moments for firmware activation done */ - usleep_range(10000, 12000); - -free_fw: - release_firmware(fw); - return err; -} - static int btmtksdio_setup(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); @@ -782,7 +640,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) calltime = ktime_get(); /* Query whether the firmware is already download */ - wmt_params.op = MTK_WMT_SEMAPHORE; + wmt_params.op = BTMTK_WMT_SEMAPHORE; wmt_params.flag = 1; wmt_params.dlen = 0; wmt_params.data = NULL; @@ -800,7 +658,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) } /* Setup a firmware which the device definitely requires */ - err = mtk_setup_firmware(hdev, bdev->data->fwname); + err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync); if (err < 0) return err; @@ -823,7 +681,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) } /* Enable Bluetooth protocol */ - wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.op = BTMTK_WMT_FUNC_CTRL; wmt_params.flag = 0; wmt_params.dlen = sizeof(param); wmt_params.data = ¶m; @@ -891,7 +749,7 @@ static int btmtksdio_shutdown(struct hci_dev *hdev) pm_runtime_get_sync(bdev->dev); /* Disable the device */ - wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.op = BTMTK_WMT_FUNC_CTRL; wmt_params.flag = 0; wmt_params.dlen = sizeof(param); wmt_params.data = ¶m; @@ -1112,5 +970,3 @@ MODULE_AUTHOR("Sean Wang "); MODULE_DESCRIPTION("MediaTek Bluetooth SDIO driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE_MT7663); -MODULE_FIRMWARE(FIRMWARE_MT7668); From patchwork Mon Oct 18 21:30:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568143 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43EFAC4332F for ; Mon, 18 Oct 2021 21:40:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2870461206 for ; Mon, 18 Oct 2021 21:40:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232682AbhJRVnA (ORCPT ); Mon, 18 Oct 2021 17:43:00 -0400 Received: from mailgw01.mediatek.com ([216.200.240.184]:25663 "EHLO mailgw01.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232286AbhJRVm6 (ORCPT ); Mon, 18 Oct 2021 17:42:58 -0400 X-UUID: b94b0f69a16147748635b631bf3cbbdc-20211018 X-UUID: b94b0f69a16147748635b631bf3cbbdc-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1100053958; Mon, 18 Oct 2021 14:40:39 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:37 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:36 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v2 03/10] Bluetooth: btmtksdio: add .set_bdaddr support Date: Tue, 19 Oct 2021 05:30:14 +0800 Message-ID: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang add .set_bdaddr support Signed-off-by: Sean Wang --- drivers/bluetooth/btmtksdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 53682a4c2ced..77d1c4ac582d 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -834,6 +834,8 @@ static int btmtksdio_probe(struct sdio_func *func, hdev->setup = btmtksdio_setup; hdev->shutdown = btmtksdio_shutdown; hdev->send = btmtksdio_send_frame; + hdev->set_bdaddr = btmtk_set_bdaddr; + SET_HCIDEV_DEV(hdev, &func->dev); hdev->manufacturer = 70; From patchwork Mon Oct 18 21:30:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568125 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9DCA9C433F5 for ; Mon, 18 Oct 2021 21:37:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7B6D960F11 for ; Mon, 18 Oct 2021 21:37:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232306AbhJRVjr (ORCPT ); Mon, 18 Oct 2021 17:39:47 -0400 Received: from mailgw02.mediatek.com ([216.200.240.185]:26640 "EHLO mailgw02.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229524AbhJRVjq (ORCPT ); Mon, 18 Oct 2021 17:39:46 -0400 X-UUID: b7dcc5d4df5d4d68801e6a6cef688f48-20211018 X-UUID: b7dcc5d4df5d4d68801e6a6cef688f48-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 968099260; Mon, 18 Oct 2021 14:37:31 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:40 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:39 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 04/10] Bluetooth: btmtksdio: explicitly set WHISR as write-1-clear Date: Tue, 19 Oct 2021 05:30:15 +0800 Message-ID: <2c1c5888c5c42f969a116563d03599efd2b6792d.1634592181.git.objelf@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang That is a preliminary patch to introduce mt7921s support. Explicitly set WHISR as write-1-clear method to all devices that is the expected behavior the driver rely on. Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- drivers/bluetooth/btmtksdio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 77d1c4ac582d..57126a95e292 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -487,8 +487,8 @@ 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; int err; - u32 status; sdio_claim_host(bdev->func); @@ -533,8 +533,13 @@ static int btmtksdio_open(struct hci_dev *hdev) if (err < 0) goto err_release_irq; - /* Setup write-1-clear for CHISR register */ - sdio_writel(bdev->func, C_INT_CLR_CTRL, MTK_REG_CHCR, &err); + /* Explitly set write-1-clear method */ + val = sdio_readl(bdev->func, MTK_REG_CHCR, &err); + if (err < 0) + goto err_release_irq; + + val |= C_INT_CLR_CTRL; + sdio_writel(bdev->func, val, MTK_REG_CHCR, &err); if (err < 0) goto err_release_irq; From patchwork Mon Oct 18 21:30:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568117 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13346C433F5 for ; Mon, 18 Oct 2021 21:30:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E596B6113D for ; Mon, 18 Oct 2021 21:30:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232894AbhJRVdA (ORCPT ); Mon, 18 Oct 2021 17:33:00 -0400 Received: from mailgw01.mediatek.com ([216.200.240.184]:36115 "EHLO mailgw01.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbhJRVc7 (ORCPT ); Mon, 18 Oct 2021 17:32:59 -0400 X-UUID: c30dd1dbf9904701b4e638f9c4041f17-20211018 X-UUID: c30dd1dbf9904701b4e638f9c4041f17-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 955275006; Mon, 18 Oct 2021 14:30:45 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:43 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:42 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 05/10] Bluetooth: btmtksdio: move interrupt service to work Date: Tue, 19 Oct 2021 05:30:16 +0800 Message-ID: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang btmtksdio belongs to WIFI/BT combo chip that would serve two radios in one sdio_irq so that we have to move interrupt service to worker to ensure ISR as short as possible. The worker would serve the both Tx and Rx in a batch to effectively reduce many interrupts to the host and to avoid excessive sdio lock contention between various context (even from WiFi driver) and help to be more efficient to complete command/event transation. Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- drivers/bluetooth/btmtksdio.c | 132 ++++++++++++++++------------------ 1 file changed, 63 insertions(+), 69 deletions(-) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 57126a95e292..f712b52e5797 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -98,7 +98,7 @@ struct btmtksdio_dev { struct sdio_func *func; struct device *dev; - struct work_struct tx_work; + struct work_struct txrx_work; unsigned long tx_state; struct sk_buff_head txq; @@ -249,32 +249,6 @@ static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev) return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL); } -static void btmtksdio_tx_work(struct work_struct *work) -{ - struct btmtksdio_dev *bdev = container_of(work, struct btmtksdio_dev, - tx_work); - struct sk_buff *skb; - int err; - - pm_runtime_get_sync(bdev->dev); - - sdio_claim_host(bdev->func); - - while ((skb = skb_dequeue(&bdev->txq))) { - err = btmtksdio_tx_packet(bdev, skb); - if (err < 0) { - bdev->hdev->stat.err_tx++; - skb_queue_head(&bdev->txq, skb); - break; - } - } - - sdio_release_host(bdev->func); - - pm_runtime_mark_last_busy(bdev->dev); - pm_runtime_put_autosuspend(bdev->dev); -} - static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); @@ -425,63 +399,81 @@ static int btmtksdio_rx_packet(struct btmtksdio_dev *bdev, u16 rx_size) return err; } -static void btmtksdio_interrupt(struct sdio_func *func) +static void btmtksdio_txrx_work(struct work_struct *work) { - struct btmtksdio_dev *bdev = sdio_get_drvdata(func); + struct btmtksdio_dev *bdev = container_of(work, struct btmtksdio_dev, + txrx_work); + unsigned long txrx_timeout; + struct sk_buff *skb; u32 int_status; u16 rx_size; - - /* It is required that the host gets ownership from the device before - * accessing any register, however, if SDIO host is not being released, - * a potential deadlock probably happens in a circular wait between SDIO - * IRQ work and PM runtime work. So, we have to explicitly release SDIO - * host here and claim again after the PM runtime work is all done. - */ - sdio_release_host(bdev->func); + int err; pm_runtime_get_sync(bdev->dev); sdio_claim_host(bdev->func); /* Disable interrupt */ - sdio_writel(func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL); + sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0); - int_status = sdio_readl(func, MTK_REG_CHISR, NULL); + while ((skb = skb_dequeue(&bdev->txq))) { + err = btmtksdio_tx_packet(bdev, skb); + if (err < 0) { + bdev->hdev->stat.err_tx++; + skb_queue_head(&bdev->txq, skb); + break; + } + } - /* Ack an interrupt as soon as possible before any operation on - * hardware. - * - * Note that we don't ack any status during operations to avoid race - * condition between the host and the device such as it's possible to - * mistakenly ack RX_DONE for the next packet and then cause interrupts - * not be raised again but there is still pending data in the hardware - * FIFO. - */ - sdio_writel(func, int_status, MTK_REG_CHISR, NULL); + txrx_timeout = jiffies + 5 * HZ; + + do { + int_status = sdio_readl(bdev->func, MTK_REG_CHISR, NULL); + + /* Ack an interrupt as soon as possible before any operation on + * hardware. + * + * Note that we don't ack any status during operations to avoid race + * condition between the host and the device such as it's possible to + * mistakenly ack RX_DONE for the next packet and then cause interrupts + * not be raised again but there is still pending data in the hardware + * FIFO. + */ + sdio_writel(bdev->func, int_status, MTK_REG_CHISR, NULL); + + if (int_status & FW_OWN_BACK_INT) + bt_dev_dbg(bdev->hdev, "Get fw own back"); + + if (int_status & TX_EMPTY) + schedule_work(&bdev->txrx_work); + else if (unlikely(int_status & TX_FIFO_OVERFLOW)) + bt_dev_warn(bdev->hdev, "Tx fifo overflow"); + + if (int_status & RX_DONE_INT) { + rx_size = (int_status & RX_PKT_LEN) >> 16; + if (btmtksdio_rx_packet(bdev, rx_size) < 0) + bdev->hdev->stat.err_rx++; + } - if (unlikely(!int_status)) - bt_dev_err(bdev->hdev, "CHISR is 0"); + } while (int_status || time_is_before_jiffies(txrx_timeout)); - if (int_status & FW_OWN_BACK_INT) - bt_dev_dbg(bdev->hdev, "Get fw own back"); + /* Enable interrupt */ + sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0); - if (int_status & TX_EMPTY) - schedule_work(&bdev->tx_work); - else if (unlikely(int_status & TX_FIFO_OVERFLOW)) - bt_dev_warn(bdev->hdev, "Tx fifo overflow"); + sdio_release_host(bdev->func); - if (int_status & RX_DONE_INT) { - rx_size = (int_status & RX_PKT_LEN) >> 16; + pm_runtime_mark_last_busy(bdev->dev); + pm_runtime_put_autosuspend(bdev->dev); +} - if (btmtksdio_rx_packet(bdev, rx_size) < 0) - bdev->hdev->stat.err_rx++; - } +static void btmtksdio_interrupt(struct sdio_func *func) +{ + struct btmtksdio_dev *bdev = sdio_get_drvdata(func); - /* Enable interrupt */ - sdio_writel(func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); + /* Disable interrupt */ + sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0); - pm_runtime_mark_last_busy(bdev->dev); - pm_runtime_put_autosuspend(bdev->dev); + schedule_work(&bdev->txrx_work); } static int btmtksdio_open(struct hci_dev *hdev) @@ -583,6 +575,8 @@ static int btmtksdio_close(struct hci_dev *hdev) sdio_release_irq(bdev->func); + cancel_work_sync(&bdev->txrx_work); + /* Return ownership to the device */ sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, NULL); @@ -604,7 +598,7 @@ static int btmtksdio_flush(struct hci_dev *hdev) skb_queue_purge(&bdev->txq); - cancel_work_sync(&bdev->tx_work); + cancel_work_sync(&bdev->txrx_work); return 0; } @@ -795,7 +789,7 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) skb_queue_tail(&bdev->txq, skb); - schedule_work(&bdev->tx_work); + schedule_work(&bdev->txrx_work); return 0; } @@ -818,7 +812,7 @@ static int btmtksdio_probe(struct sdio_func *func, bdev->dev = &func->dev; bdev->func = func; - INIT_WORK(&bdev->tx_work, btmtksdio_tx_work); + INIT_WORK(&bdev->txrx_work, btmtksdio_txrx_work); skb_queue_head_init(&bdev->txq); /* Initialize and register HCI device */ From patchwork Mon Oct 18 21:30:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568141 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC192C433FE for ; Mon, 18 Oct 2021 21:40:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8DA3061207 for ; Mon, 18 Oct 2021 21:40:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232450AbhJRVm7 (ORCPT ); Mon, 18 Oct 2021 17:42:59 -0400 Received: from mailgw01.mediatek.com ([216.200.240.184]:25663 "EHLO mailgw01.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229529AbhJRVm6 (ORCPT ); Mon, 18 Oct 2021 17:42:58 -0400 X-UUID: d7c0907f259d459e965111a81cbba3ce-20211018 X-UUID: d7c0907f259d459e965111a81cbba3ce-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1850810432; Mon, 18 Oct 2021 14:40:39 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:45 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:45 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 06/10] Bluetooth: btmtksdio: update register CSDIOCSR operation Date: Tue, 19 Oct 2021 05:30:17 +0800 Message-ID: <3d93b60ec30d43fbe906a96a33f86b8b98ee36f5.1634592181.git.objelf@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang That is a preliminary patch to introduce mt7921s support. Update register CSDIOCSR operation that is suggested from the vendor driver and is compatible to the all devices. Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- drivers/bluetooth/btmtksdio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index f712b52e5797..3381c8844902 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -520,8 +520,12 @@ static int btmtksdio_open(struct hci_dev *hdev) /* SDIO CMD 5 allows the SDIO device back to idle state an * synchronous interrupt is supported in SDIO 4-bit mode */ - sdio_writel(bdev->func, SDIO_INT_CTL | SDIO_RE_INIT_EN, - MTK_REG_CSDIOCSR, &err); + val = sdio_readl(bdev->func, MTK_REG_CSDIOCSR, &err); + if (err < 0) + goto err_release_irq; + + val |= SDIO_INT_CTL; + sdio_writel(bdev->func, val, MTK_REG_CSDIOCSR, &err); if (err < 0) goto err_release_irq; From patchwork Mon Oct 18 21:30:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568127 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3961BC433EF for ; Mon, 18 Oct 2021 21:37:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 17DAD61350 for ; Mon, 18 Oct 2021 21:37:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232682AbhJRVjr (ORCPT ); Mon, 18 Oct 2021 17:39:47 -0400 Received: from mailgw02.mediatek.com ([216.200.240.185]:26640 "EHLO mailgw02.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229555AbhJRVjr (ORCPT ); Mon, 18 Oct 2021 17:39:47 -0400 X-UUID: a98dfc76a83a4b59a229f271679046c5-20211018 X-UUID: a98dfc76a83a4b59a229f271679046c5-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 710041815; Mon, 18 Oct 2021 14:37:31 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:48 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:48 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 07/10] Bluetooth: btmtksdio: use register CRPLR to read packet length Date: Tue, 19 Oct 2021 05:30:18 +0800 Message-ID: <69d548d8fa18183069fa27f76e8bb919d881c78d.1634592181.git.objelf@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang That is a preliminary patch to introduce mt7921s support. Use the register CRPLR to read packet length to make all the devices share the common logic. Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- drivers/bluetooth/btmtksdio.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 3381c8844902..f816a7cb0a74 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -83,6 +83,8 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); #define MTK_REG_CRDR 0x1c +#define MTK_REG_CRPLR 0x24 + #define MTK_SDIO_BLOCK_SIZE 256 #define BTMTKSDIO_TX_WAIT_VND_EVT 1 @@ -404,9 +406,8 @@ static void btmtksdio_txrx_work(struct work_struct *work) struct btmtksdio_dev *bdev = container_of(work, struct btmtksdio_dev, txrx_work); unsigned long txrx_timeout; + u32 int_status, rx_size; struct sk_buff *skb; - u32 int_status; - u16 rx_size; int err; pm_runtime_get_sync(bdev->dev); @@ -450,11 +451,11 @@ static void btmtksdio_txrx_work(struct work_struct *work) bt_dev_warn(bdev->hdev, "Tx fifo overflow"); if (int_status & RX_DONE_INT) { - rx_size = (int_status & RX_PKT_LEN) >> 16; + rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL); + rx_size = (rx_size & RX_PKT_LEN) >> 16; if (btmtksdio_rx_packet(bdev, rx_size) < 0) bdev->hdev->stat.err_rx++; } - } while (int_status || time_is_before_jiffies(txrx_timeout)); /* Enable interrupt */ From patchwork Mon Oct 18 21:30:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568119 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A82D8C433F5 for ; Mon, 18 Oct 2021 21:30:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 890116113D for ; Mon, 18 Oct 2021 21:30:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232682AbhJRVdI (ORCPT ); Mon, 18 Oct 2021 17:33:08 -0400 Received: from mailgw01.mediatek.com ([216.200.240.184]:46672 "EHLO mailgw01.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233095AbhJRVdF (ORCPT ); Mon, 18 Oct 2021 17:33:05 -0400 X-UUID: 899a9a72d3d84c6a9b957b9f6df1ad73-20211018 X-UUID: 899a9a72d3d84c6a9b957b9f6df1ad73-20211018 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1499909244; Mon, 18 Oct 2021 14:30:53 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:51 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:50 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 08/10] Bluetooth: btmtksdio: transmit packet according to status TX_EMPTY Date: Tue, 19 Oct 2021 05:30:19 +0800 Message-ID: <3dccea770a3f656dffbae573b6d2b577af0ca324.1634592181.git.objelf@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Mark-yw Chen Each packet should be sent out until the device emits the TX_EMPTY signal to the host, that is firmware people suggested to add to meet the actual firmware behavior and that is compatible among all the devices. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Mark-yw Chen --- drivers/bluetooth/btmtksdio.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index f816a7cb0a74..3266c5d83cae 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -103,6 +103,7 @@ struct btmtksdio_dev { struct work_struct txrx_work; unsigned long tx_state; struct sk_buff_head txq; + bool hw_tx_ready; struct sk_buff *evt_skb; @@ -229,6 +230,7 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev, sdio_hdr->reserved = cpu_to_le16(0); sdio_hdr->bt_type = hci_skb_pkt_type(skb); + bdev->hw_tx_ready = false; err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, round_up(skb->len, MTK_SDIO_BLOCK_SIZE)); if (err < 0) @@ -417,15 +419,6 @@ static void btmtksdio_txrx_work(struct work_struct *work) /* Disable interrupt */ sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0); - while ((skb = skb_dequeue(&bdev->txq))) { - err = btmtksdio_tx_packet(bdev, skb); - if (err < 0) { - bdev->hdev->stat.err_tx++; - skb_queue_head(&bdev->txq, skb); - break; - } - } - txrx_timeout = jiffies + 5 * HZ; do { @@ -446,10 +439,21 @@ static void btmtksdio_txrx_work(struct work_struct *work) bt_dev_dbg(bdev->hdev, "Get fw own back"); if (int_status & TX_EMPTY) - schedule_work(&bdev->txrx_work); + bdev->hw_tx_ready = true; else if (unlikely(int_status & TX_FIFO_OVERFLOW)) bt_dev_warn(bdev->hdev, "Tx fifo overflow"); + if (bdev->hw_tx_ready) { + skb = skb_dequeue(&bdev->txq); + if (skb) { + err = btmtksdio_tx_packet(bdev, skb); + if (err < 0) { + bdev->hdev->stat.err_tx++; + skb_queue_head(&bdev->txq, skb); + } + } + } + if (int_status & RX_DONE_INT) { rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL); rx_size = (rx_size & RX_PKT_LEN) >> 16; @@ -642,6 +646,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) u8 param = 0x1; calltime = ktime_get(); + bdev->hw_tx_ready = true; /* Query whether the firmware is already download */ wmt_params.op = BTMTK_WMT_SEMAPHORE; From patchwork Mon Oct 18 21:30:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568139 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE389C433EF for ; Mon, 18 Oct 2021 21:40:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D2B7A6112D for ; Mon, 18 Oct 2021 21:40:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231920AbhJRVm6 (ORCPT ); Mon, 18 Oct 2021 17:42:58 -0400 Received: from mailgw01.mediatek.com ([216.200.240.184]:25663 "EHLO mailgw01.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229524AbhJRVm5 (ORCPT ); Mon, 18 Oct 2021 17:42:57 -0400 X-UUID: 2275a7247c0e403cb3b81efb8b7d4095-20211018 X-UUID: 2275a7247c0e403cb3b81efb8b7d4095-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 256072015; Mon, 18 Oct 2021 14:40:39 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:53 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:53 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 09/10] mmc: add MT7921 SDIO identifiers for MediaTek Bluetooth devices Date: Tue, 19 Oct 2021 05:30:20 +0800 Message-ID: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang The MT7961 SDIO identifier for MediaTek Bluetooth devices were being referred in the MediaTek Bluetooth driver. Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- include/linux/mmc/sdio_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index a85c9f0bd470..53f0efa0bccf 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -105,6 +105,7 @@ #define SDIO_VENDOR_ID_MEDIATEK 0x037a #define SDIO_DEVICE_ID_MEDIATEK_MT7663 0x7663 #define SDIO_DEVICE_ID_MEDIATEK_MT7668 0x7668 +#define SDIO_DEVICE_ID_MEDIATEK_MT7961 0x7961 #define SDIO_VENDOR_ID_MICROCHIP_WILC 0x0296 #define SDIO_DEVICE_ID_MICROCHIP_WILC1000 0x5347 From patchwork Mon Oct 18 21:30:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Wang X-Patchwork-Id: 12568129 X-Patchwork-Delegate: marcel@holtmann.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51FF1C4332F for ; Mon, 18 Oct 2021 21:37:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A1A76112D for ; Mon, 18 Oct 2021 21:37:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232790AbhJRVjs (ORCPT ); Mon, 18 Oct 2021 17:39:48 -0400 Received: from mailgw02.mediatek.com ([216.200.240.185]:28513 "EHLO mailgw02.mediatek.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232292AbhJRVjr (ORCPT ); Mon, 18 Oct 2021 17:39:47 -0400 X-UUID: 642754f1d0f04919831fc3fc92f4bcce-20211018 X-UUID: 642754f1d0f04919831fc3fc92f4bcce-20211018 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1042325873; Mon, 18 Oct 2021 14:37:31 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 18 Oct 2021 14:30:56 -0700 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 19 Oct 2021 05:30:55 +0800 From: To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Mark-yw Chen Subject: [PATCH v2 10/10] Bluetooth: btmtksdio: add MT7921s Bluetooth support Date: Tue, 19 Oct 2021 05:30:21 +0800 Message-ID: <4dd1fc16a9dbcb981ac4c0af538991d9ea42c969.1634592181.git.objelf@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sean Wang add MT7921s Bluetooth support Co-developed-by: Mark-yw Chen Signed-off-by: Mark-yw Chen Signed-off-by: Sean Wang --- drivers/bluetooth/btmtk.h | 11 +++ drivers/bluetooth/btmtksdio.c | 141 ++++++++++++++++++++++++++++++++-- 2 files changed, 144 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 18f43c641b3b..6e7b0c7567c0 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -7,6 +7,8 @@ #define HCI_WMT_MAX_EVENT_SIZE 64 +#define BTMTK_WMT_REG_READ 0x2 + enum { BTMTK_WMT_PATCH_DWNLD = 0x1, BTMTK_WMT_TEST = 0x2, @@ -14,6 +16,7 @@ enum { BTMTK_WMT_HIF = 0x4, BTMTK_WMT_FUNC_CTRL = 0x6, BTMTK_WMT_RST = 0x7, + BTMTK_WMT_REGISTER = 0x8, BTMTK_WMT_SEMAPHORE = 0x17, }; @@ -49,6 +52,14 @@ struct btmtk_hci_wmt_evt_funcc { __be16 status; } __packed; +struct btmtk_hci_wmt_evt_reg { + struct btmtk_hci_wmt_evt hwhdr; + u8 rsv[2]; + u8 num; + __le32 addr; + __le32 val; +} __packed; + struct btmtk_tci_sleep { u8 mode; __le16 duration; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 3266c5d83cae..ce6a6c00ff98 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -37,14 +37,22 @@ static bool enable_autosuspend; struct btmtksdio_data { const char *fwname; + u16 chipid; }; static const struct btmtksdio_data mt7663_data = { .fwname = FIRMWARE_MT7663, + .chipid = 0x7663, }; static const struct btmtksdio_data mt7668_data = { .fwname = FIRMWARE_MT7668, + .chipid = 0x7668, +}; + +static const struct btmtksdio_data mt7921_data = { + .fwname = FIRMWARE_MT7961, + .chipid = 0x7921, }; static const struct sdio_device_id btmtksdio_table[] = { @@ -52,6 +60,8 @@ static const struct sdio_device_id btmtksdio_table[] = { .driver_data = (kernel_ulong_t)&mt7663_data }, {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7668), .driver_data = (kernel_ulong_t)&mt7668_data }, + {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7961), + .driver_data = (kernel_ulong_t)&mt7921_data }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(sdio, btmtksdio_table); @@ -115,6 +125,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; + struct btmtk_hci_wmt_evt_reg *wmt_evt_reg; u32 hlen, status = BTMTK_WMT_INVALID; struct btmtk_hci_wmt_evt *wmt_evt; struct btmtk_hci_wmt_cmd *wc; @@ -194,6 +205,19 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, else status = BTMTK_WMT_ON_UNDONE; break; + case BTMTK_WMT_PATCH_DWNLD: + if (wmt_evt->whdr.flag == 2) + status = BTMTK_WMT_PATCH_DONE; + else if (wmt_evt->whdr.flag == 1) + status = BTMTK_WMT_PATCH_PROGRESS; + else + status = BTMTK_WMT_PATCH_UNDONE; + break; + case BTMTK_WMT_REGISTER: + wmt_evt_reg = (struct btmtk_hci_wmt_evt_reg *)wmt_evt; + if (le16_to_cpu(wmt_evt->whdr.dlen) == 12) + status = le32_to_cpu(wmt_evt_reg->val); + break; } if (wmt_params->status) @@ -634,20 +658,14 @@ static int btmtksdio_func_query(struct hci_dev *hdev) return status; } -static int btmtksdio_setup(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; - ktime_t calltime, delta, rettime; struct btmtk_tci_sleep tci_sleep; - unsigned long long duration; struct sk_buff *skb; int err, status; u8 param = 0x1; - calltime = ktime_get(); - bdev->hw_tx_ready = true; - /* Query whether the firmware is already download */ wmt_params.op = BTMTK_WMT_SEMAPHORE; wmt_params.flag = 1; @@ -667,7 +685,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) } /* Setup a firmware which the device definitely requires */ - err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync); + err = btmtk_setup_firmware(hdev, fwname, mtk_hci_wmt_sync); if (err < 0) return err; @@ -719,6 +737,113 @@ static int btmtksdio_setup(struct hci_dev *hdev) } kfree_skb(skb); + return 0; +} + +static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) +{ + struct btmtk_hci_wmt_params wmt_params; + u8 param = 0x1; + int err; + + err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync); + if (err < 0) { + bt_dev_err(hdev, "Failed to setup 79xx firmware (%d)", err); + return err; + } + + /* Enable Bluetooth protocol */ + wmt_params.op = BTMTK_WMT_FUNC_CTRL; + wmt_params.flag = 0; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); + return err; + } + + return err; +} + +static int btsdio_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 = { + .type = 1, + .num = 1, + }; + u32 status; + int err; + + reg_read.addr = cpu_to_le32(reg); + wmt_params.op = BTMTK_WMT_REGISTER; + wmt_params.flag = BTMTK_WMT_REG_READ; + wmt_params.dlen = sizeof(reg_read); + wmt_params.data = ®_read; + wmt_params.status = &status; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to read reg(%d)", err); + return err; + } + + *val = status; + + return err; +} + +static int btmtksdio_setup(struct hci_dev *hdev) +{ + struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); + ktime_t calltime, delta, rettime; + unsigned long long duration; + char fwname[64]; + int err, dev_id; + u32 fw_version = 0; + + calltime = ktime_get(); + bdev->hw_tx_ready = true; + + switch (bdev->data->chipid) { + case 0x7921: + err = btsdio_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); + if (err < 0) { + bt_dev_err(hdev, "Failed to get fw version (%d)", err); + return err; + } + + snprintf(fwname, sizeof(fwname), + "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", + dev_id & 0xffff, (fw_version & 0xff) + 1); + err = mt79xx_setup(hdev, fwname); + if (err < 0) + return err; + break; + case 0x7663: + case 0x7668: + err = mt76xx_setup(hdev, bdev->data->fwname); + if (err < 0) + return err; + break; + default: + return -ENODEV; + } + rettime = ktime_get(); delta = ktime_sub(rettime, calltime); duration = (unsigned long long)ktime_to_ns(delta) >> 10;