linux-mediatek.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] Bluetooth: btusb: Record debug log for Mediatek Chip.
@ 2021-07-01 19:42 mark-yw.chen
  2021-07-01 19:42 ` [PATCH v4 2/2] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921) mark-yw.chen
  0 siblings, 1 reply; 3+ messages in thread
From: mark-yw.chen @ 2021-07-01 19:42 UTC (permalink / raw)
  To: marcel, johan.hedberg
  Cc: chris.lu, will-cy.lee, sean.wang, linux-bluetooth,
	linux-mediatek, linux-kernel, michaelfsun, shawnku, jemele,
	apusaka, mark-yw.chen

From: "mark-yw.chen" <mark-yw.chen@mediatek.com>

Mediatek Bluetooth Controller send the fw log via EP2, this patch
create callback(data->recv_acl) for processing acl packet.

1. create callback(data->recv_acl) for processing acl packet.
2. Add btusb_recv_acl_mtk to dispatch firmware debug log and firmware
   dump, the debug log is for LMP/LL tracing and Connection quality.
3. The upper layerd can use hci_channel_minitor to receive
   these packets.

Example btmon: firmware debug log.
1. Enable firmware debug log.
< HCI Command: Vendor (0x3f|0x005d) plen 4
        00 00 02 02                                      ....
> HCI Event: Command Complete (0x0e) plen 8
      Vendor (0x3f|0x005d) ncmd 1
        Status: Success (0x00)
        00 00 02 02                                      ....
2. Diagnostic packet from controller
= Vendor Diagnostic (len 500)
          ff 05 f0 01 fd ff 02 0e 08 01 5d fc 00 00 00 02
          02 aa aa aa cb e3 f0 15 b0 0c 5f 01 00 d1 0f 33
          01 7f 00 08 57 61 0c 00 00 00 00 00 23 37 17 00
          fd ff 00 00 29 60 ff ff b1 56 e8 00 57 40 0a 40
          39 95 f2 00 47 40 43 00 fc f0 16 00 57 61 0c 00
          00 00 00 00 23 37 17 00 fd ff 00 00 29 60 ff ff
          65 95 f2 00 57 40 0a 40 ec d3 fc 00 47 40 3b 00
          2c f1 17 00 57 61 0c 00 00 00 00 00 23 37 17 00
          fd ff 00 00 29 60 ff ff 19 d4 fc 00 57 40 76 1c
          b2 61 01 01 47 40 b3 04 0b 63 18 00 fe ff 02 01
          04 05 33 8b 9e 08 00 aa aa aa aa aa 27 38 01 02
          01 00 00 00 02 e0 10 00 20 00 20 00 2a 08 40 00
          20 00 20 08 2a 08 02 00 40 00 00 01 2e 08 40 00
          01 67 b0 c2 2e 08 3e 07 ff ff ff ff 40 08 01 00
          02 00 00 00 34 08 a3 00 00 00 00 00 34 08 a3 00
          00 00 00 00 35 08 45 01 00 00 00 00 2e 08 40 00
          01 67 b0 c2 30 35 01 02 00 00 00 00 2c 31 01 00
          02 00 00 40 2d 19 03 00 00 40 00 00 fd ff 02 0f
          04 00 01 01 04 aa aa aa aa aa aa aa 57 61 0c 00
          00 00 00 00 23 46 32 00 01 00 00 00 2f 35 00 02
          00 00 00 00 29 35 ff 02 00 22 00 00 2d 31 a6 02
          02 00 00 00 31 6c 40 00 14 63 18 1b 31 6c 40 00
          14 63 18 23 51 08 53 00 12 63 18 00 2c 35 12 01
          fe 00 00 00 2b 35 fe 02 02 00 00 00 2f 31 21 00
          00 00 02 00 75 61 01 00 4c 1b 93 00 79 61 01 00
          00 00 00 00 12 e3 63 18 20 31 86 01 74 61 68 03
          00 00 04 00 a1 73 ff 00 b9 01 00 00 a1 73 04 00
          00 00 00 00 a1 73 00 00 00 00 00 00 a1 73 00 00
          02 00 00 00 31 6c 40 00 16 63 18 0c 31 6c 40 00
          16 63 18 1c 77 61 40 00 48 33 40 00 14 e3 63 18
          40 31 86 01 00 d1 02 c5 07 23 a1 34 73 61 37 02
          02 00 00 a1

Signed-off-by: mark-yw.chen <mark-yw.chen@mediatek.com>
---
 drivers/bluetooth/btusb.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b015dcecfb13..b1249b664981 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -569,6 +569,7 @@ struct btusb_data {
 	int suspend_count;
 
 	int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
+	int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
 	int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
 
 	int (*setup_on_usb)(struct hci_dev *hdev);
@@ -776,7 +777,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
 
 		if (!hci_skb_expect(skb)) {
 			/* Complete frame */
-			hci_recv_frame(data->hdev, skb);
+			data->recv_acl(data->hdev, skb);
 			skb = NULL;
 		}
 	}
@@ -3851,6 +3852,25 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
 	return 0;
 }
 
+static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
+
+	switch (handle) {
+	case 0xfc6f:		/* Firmware dump from device */
+		/* When the firmware hangs, the device can no longer
+		 * suspend and thus disable auto-suspend.
+		 */
+		usb_disable_autosuspend(data->udev);
+	case 0x05ff:		/* Firmware debug logging 1 */
+	case 0x05fe:		/* Firmware debug logging 2 */
+		return hci_recv_diag(hdev, skb);
+	}
+
+	return hci_recv_frame(hdev, skb);
+}
+
 MODULE_FIRMWARE(FIRMWARE_MT7663);
 MODULE_FIRMWARE(FIRMWARE_MT7668);
 
@@ -4543,6 +4563,8 @@ static int btusb_probe(struct usb_interface *intf,
 		data->recv_bulk = btusb_recv_bulk;
 	}
 
+	data->recv_acl = hci_recv_frame;
+
 	hdev = hci_alloc_dev();
 	if (!hdev)
 		return -ENOMEM;
@@ -4670,6 +4692,7 @@ static int btusb_probe(struct usb_interface *intf,
 		hdev->shutdown = btusb_mtk_shutdown;
 		hdev->manufacturer = 70;
 		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+		data->recv_acl = btusb_recv_acl_mtk;
 	}
 
 	if (id->driver_info & BTUSB_SWAVE) {
-- 
2.18.0
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v4 2/2] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921)
  2021-07-01 19:42 [PATCH v4 1/2] Bluetooth: btusb: Record debug log for Mediatek Chip mark-yw.chen
@ 2021-07-01 19:42 ` mark-yw.chen
  2021-07-22 14:03   ` Marcel Holtmann
  0 siblings, 1 reply; 3+ messages in thread
From: mark-yw.chen @ 2021-07-01 19:42 UTC (permalink / raw)
  To: marcel, johan.hedberg
  Cc: chris.lu, will-cy.lee, sean.wang, linux-bluetooth,
	linux-mediatek, linux-kernel, michaelfsun, shawnku, jemele,
	apusaka, mark-yw.chen

From: "mark-yw.chen" <mark-yw.chen@mediatek.com>

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 <mark-yw.chen@mediatek.com>
---
 drivers/bluetooth/btusb.c | 127 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b1249b664981..122a928ebcb5 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3076,6 +3076,17 @@ static int btusb_shutdown_intel_new(struct hci_dev *hdev)
 	return 0;
 }
 
+/* UHW CR mapping */
+#define BT_MISC			0x70002510
+#define BT_SUBSYS_RST		0x70002610
+#define UDMA_INT_STA_BT		0x74000024
+#define UDMA_INT_STA_BT1	0x74000308
+#define BT_WDT_STATUS		0x740003A0
+#define EP_RST_OPT		0x74011890
+#define EP_RST_IN_OUT_OPT	0x00010001
+#define BT_RST_DONE		0x00000100
+#define BT_RESET_WAIT_MS	100
+#define BT_RESET_NUM_TRIES	10
 #define FIRMWARE_MT7663		"mediatek/mt7663pr2h.bin"
 #define FIRMWARE_MT7668		"mediatek/mt7668pr2h.bin"
 
@@ -3650,6 +3661,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);
@@ -3729,6 +3797,9 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 			 dev_id & 0xffff, (fw_version & 0xff) + 1);
 		err = btusb_mtk_setup_firmware_79xx(hdev, fw_bin_name);
 
+		/* It's Device EndPoint Reset Option Register */
+		btusb_mtk_uhw_reg_write(data, EP_RST_OPT, EP_RST_IN_OUT_OPT);
+
 		/* Enable Bluetooth protocol */
 		param = 1;
 		wmt_params.op = BTMTK_WMT_FUNC_CTRL;
@@ -3852,6 +3923,61 @@ 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, EP_RST_OPT, EP_RST_IN_OUT_OPT);
+	btusb_mtk_uhw_reg_read(data, BT_WDT_STATUS, &val);
+
+	/* Reset the bluetooth chip via USB interface. */
+	btusb_mtk_uhw_reg_write(data, BT_SUBSYS_RST, 1);
+	btusb_mtk_uhw_reg_write(data, UDMA_INT_STA_BT, 0x000000FF);
+	btusb_mtk_uhw_reg_read(data, UDMA_INT_STA_BT, &val);
+	btusb_mtk_uhw_reg_write(data, UDMA_INT_STA_BT1, 0x000000FF);
+	btusb_mtk_uhw_reg_read(data, UDMA_INT_STA_BT1, &val);
+	msleep(20);
+	btusb_mtk_uhw_reg_write(data, BT_SUBSYS_RST, 0);
+	btusb_mtk_uhw_reg_read(data, BT_SUBSYS_RST, &val);
+
+	/* Poll the register until reset is completed */
+	do {
+		btusb_mtk_uhw_reg_read(data, BT_MISC, &val);
+		if ((val & 0x00000100) == BT_RST_DONE) {
+			bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
+			break;
+		}
+
+		bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
+		retry++;
+		msleep(BT_RESET_WAIT_MS);
+	} while (retry < BT_RESET_NUM_TRIES);
+
+	btusb_mtk_id_get(data, 0x70010200, &val);
+	bt_dev_info(hdev, "device id (%x)", val);
+
+	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);
@@ -4691,6 +4817,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;
 	}
-- 
2.18.0
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v4 2/2] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921)
  2021-07-01 19:42 ` [PATCH v4 2/2] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921) mark-yw.chen
@ 2021-07-22 14:03   ` Marcel Holtmann
  0 siblings, 0 replies; 3+ messages in thread
From: Marcel Holtmann @ 2021-07-22 14:03 UTC (permalink / raw)
  To: "Mark-YW Chen (陳揚文)"
  Cc: Johan Hedberg, chris.lu, will-cy.lee, Sean Wang,
	Bluetooth Kernel Mailing List, linux-mediatek, open list,
	michaelfsun, shawnku, jemele, apusaka

Hi Mark,

> 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 <mark-yw.chen@mediatek.com>
> ---
> drivers/bluetooth/btusb.c | 127 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 127 insertions(+)
> 
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index b1249b664981..122a928ebcb5 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -3076,6 +3076,17 @@ static int btusb_shutdown_intel_new(struct hci_dev *hdev)
> 	return 0;
> }
> 
> +/* UHW CR mapping */
> +#define BT_MISC			0x70002510
> +#define BT_SUBSYS_RST		0x70002610
> +#define UDMA_INT_STA_BT		0x74000024
> +#define UDMA_INT_STA_BT1	0x74000308
> +#define BT_WDT_STATUS		0x740003A0
> +#define EP_RST_OPT		0x74011890
> +#define EP_RST_IN_OUT_OPT	0x00010001
> +#define BT_RST_DONE		0x00000100
> +#define BT_RESET_WAIT_MS	100
> +#define BT_RESET_NUM_TRIES	10

you need to prefix these with MTK since otherwise we get confused.

And we need to work towards abstracting the vendor specific position out of btusb.c (and I include the Intel part here as well). The btusb.c is getting overloaded with vendor stuff.

Regards

Marcel


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-22 14:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-01 19:42 [PATCH v4 1/2] Bluetooth: btusb: Record debug log for Mediatek Chip mark-yw.chen
2021-07-01 19:42 ` [PATCH v4 2/2] Bluetooth: btusb: Support Bluetooth Reset for Mediatek Chip(MT7921) mark-yw.chen
2021-07-22 14:03   ` Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).