From patchwork Fri Mar 18 02:15:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AceLan Kao X-Patchwork-Id: 1606861 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=Kh7r1xg5; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KKSKc5xS2z9s8s for ; Fri, 18 Mar 2022 13:15:47 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1nV29U-0004Ki-39; Fri, 18 Mar 2022 02:15:40 +0000 Received: from mail-pj1-f53.google.com ([209.85.216.53]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1nV29O-0004Ix-Tr for kernel-team@lists.ubuntu.com; Fri, 18 Mar 2022 02:15:35 +0000 Received: by mail-pj1-f53.google.com with SMTP id q1-20020a17090a4f8100b001c6575ae105so4768515pjh.0 for ; Thu, 17 Mar 2022 19:15:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2KugZONHNl42YbIkLpjIM3iyRl9KsLx3F5NbQ3hheJE=; b=Kh7r1xg5KmB15hZQfbe/MtIEwe8IskvxrrqJpega0uMZ2Ts3Gm6NGaITdFDR2/Wcxz HX3uF7JNoTfrKJmgBAY7KURo3DcyEKuYycaxGhAwNf9LXNDuuSMVPAk94q7WUo/OcSJF IGzmWmW9V6ikmyPrqiQD+ygwinAYqdt4aJLh2xsfxPkJiMjOT2825WcwUqW7sRydh8pg UP5EhGT4XDB4jKeLJTE1OhudwG4ZJj/SIdzp5Ijvns94vtCMo0Fgnkgb5RkVgjb91cRJ dm7/aKMHvJKAnZ9SGGpo46BRsmYdix2neN4R9kKDo8llwt8mPghVmYobTOTbCM+gGvQt TZMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=2KugZONHNl42YbIkLpjIM3iyRl9KsLx3F5NbQ3hheJE=; b=U+9NQnS+qUi5Z9NQ/XbPJdvGtr/Ius7RU0WHnQBMGCF6JJQPqsakrI2nmvcxwfxJrP z2eeb1w11RqA1WEksuGggGf+XuBtfUbWsZMcLK3aZ7EY3XZqqANJbMuFn50a7GtkM9gA bH1ZqLkyOLS02yyXORX5xjg/VaedQRSaktQR7CofoISWIOQ0pDdZlCR1LSEoH5Q6ZZzD BsS/sYdNoUQlERnfiqWQAbvjmR9hXmUXSeRMVtSIYYU+UxInqGTJurmrRZBJsliFkg0O QgrZ89ZSUNmFtVuXOML/Fvhm6m/hqgArMveBviFp1JJAEhImemPzC/9LO7x5otB31tFr BCMQ== X-Gm-Message-State: AOAM5303118N22eCcYoSlKXq03A/1KyLOR8/L3Y0jdEzQLXZTxO6eaiW +Hhsx+hbKlTy7eXCeN1BARvfVGtu3ME= X-Google-Smtp-Source: ABdhPJyUZs3xeHvGLRbChzj3QfENPj3n/WbL29SxrVLqhS9yzxATSEnR7vFoz9g9Vmn75PENbzEmnw== X-Received: by 2002:a17:903:18c:b0:154:9ee:cedc with SMTP id z12-20020a170903018c00b0015409eecedcmr1714884plg.123.1647569732789; Thu, 17 Mar 2022 19:15:32 -0700 (PDT) Received: from localhost (220-135-95-34.hinet-ip.hinet.net. [220.135.95.34]) by smtp.gmail.com with ESMTPSA id o1-20020a637e41000000b003804d0e2c9esm6287184pgn.35.2022.03.17.19.15.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Mar 2022 19:15:32 -0700 (PDT) From: AceLan Kao To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2][SRU][OEM-5.14] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921) Date: Fri, 18 Mar 2022 10:15:26 +0800 Message-Id: <20220318021526.59259-3-acelan.kao@canonical.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220318021526.59259-1-acelan.kao@canonical.com> References: <20220318021526.59259-1-acelan.kao@canonical.com> MIME-Version: 1.0 Received-SPF: pass client-ip=209.85.216.53; envelope-from=acelan@gmail.com; helo=mail-pj1-f53.google.com X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: "mark-yw.chen" BugLink: https://bugs.launchpad.net/bugs/1965467 When the firmware hang or command no response, driver can reset the bluetooth mcu via USB to recovery it. The reset steps as follows. 1. Cancel USB transfer requests before reset. 2. It use speicific USB HW Register to reset Bluetooth MCU, at the same time, the USB Endpoint0 still keep alive. 3. Poll the USB HW register until reset is completed by Endpoint0. 4. To recovery unexpected USB state and behavior during resetting the Bluetooth MCU, the driver need to reset the USB device for MT7921. 5. After the reset is completed, the Bluetooth MCU need to re-setup, such as download patch, power-on sequence and etc. Signed-off-by: mark-yw.chen Reviewed-by: Michael Sun Reviewed-by: Archie Pusaka Signed-off-by: Marcel Holtmann (cherry picked from commit e947802657cb6f540ba04f498dfd4938ed6c569e) Signed-off-by: Chia-Lin Kao (AceLan) --- drivers/bluetooth/btusb.c | 129 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 8e0999ba6c0c7..6363583eeba33 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3182,6 +3182,17 @@ static int btusb_shutdown_intel_new(struct hci_dev *hdev) return 0; } +/* UHW CR mapping */ +#define MTK_BT_MISC 0x70002510 +#define MTK_BT_SUBSYS_RST 0x70002610 +#define MTK_UDMA_INT_STA_BT 0x74000024 +#define MTK_UDMA_INT_STA_BT1 0x74000308 +#define MTK_BT_WDT_STATUS 0x740003A0 +#define MTK_EP_RST_OPT 0x74011890 +#define MTK_EP_RST_IN_OUT_OPT 0x00010001 +#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" @@ -3762,6 +3773,63 @@ static int btusb_mtk_func_query(struct hci_dev *hdev) return status; } +static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val) +{ + struct hci_dev *hdev = data->hdev; + int pipe, err; + void *buf; + + buf = kzalloc(4, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + put_unaligned_le32(val, buf); + + pipe = usb_sndctrlpipe(data->udev, 0); + err = usb_control_msg(data->udev, pipe, 0x02, + 0x5E, + reg >> 16, reg & 0xffff, + buf, 4, USB_CTRL_SET_TIMEOUT); + if (err < 0) { + bt_dev_err(hdev, "Failed to write uhw reg(%d)", err); + goto err_free_buf; + } + +err_free_buf: + kfree(buf); + + return err; +} + +static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val) +{ + struct hci_dev *hdev = data->hdev; + int pipe, err; + void *buf; + + buf = kzalloc(4, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + pipe = usb_rcvctrlpipe(data->udev, 0); + err = usb_control_msg(data->udev, pipe, 0x01, + 0xDE, + reg >> 16, reg & 0xffff, + buf, 4, USB_CTRL_SET_TIMEOUT); + if (err < 0) { + bt_dev_err(hdev, "Failed to read uhw reg(%d)", err); + goto err_free_buf; + } + + *val = get_unaligned_le32(buf); + bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val); + +err_free_buf: + kfree(buf); + + return err; +} + static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val) { int pipe, err, size = sizeof(u32); @@ -3846,6 +3914,9 @@ static int btusb_mtk_setup(struct hci_dev *hdev) return err; } + /* It's Device EndPoint Reset Option Register */ + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); + /* Enable Bluetooth protocol */ param = 1; wmt_params.op = BTMTK_WMT_FUNC_CTRL; @@ -3969,6 +4040,63 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev) return 0; } +static void btusb_mtk_cmd_timeout(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + u32 val; + int err, retry = 0; + + /* It's MediaTek specific bluetooth reset mechanism via USB */ + if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { + bt_dev_err(hdev, "last reset failed? Not resetting again"); + return; + } + + err = usb_autopm_get_interface(data->intf); + if (err < 0) + return; + + btusb_stop_traffic(data); + usb_kill_anchored_urbs(&data->tx_anchor); + + /* It's Device EndPoint Reset Option Register */ + bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); + btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); + + /* Reset the bluetooth chip via USB interface. */ + btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); + btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); + btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); + /* MT7921 need to delay 20ms between toggle reset bit */ + msleep(20); + btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); + btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); + + /* Poll the register until reset is completed */ + do { + btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val); + if (val & MTK_BT_RST_DONE) { + bt_dev_dbg(hdev, "Bluetooth Reset Successfully"); + break; + } + + bt_dev_dbg(hdev, "Polling Bluetooth Reset CR"); + retry++; + msleep(MTK_BT_RESET_WAIT_MS); + } while (retry < MTK_BT_RESET_NUM_TRIES); + + btusb_mtk_id_get(data, 0x70010200, &val); + if (!val) + bt_dev_err(hdev, "Can't get device id, subsys reset fail."); + + usb_queue_reset_device(data->intf); + + clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags); +} + static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb) { struct btusb_data *data = hci_get_drvdata(hdev); @@ -4876,6 +5004,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->setup = btusb_mtk_setup; hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; + hdev->cmd_timeout = btusb_mtk_cmd_timeout; set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); data->recv_acl = btusb_recv_acl_mtk; }