Skip to content

Commit

Permalink
Bluetooth: btnxpuart: Enable flow control before checking boot signature
Browse files Browse the repository at this point in the history
This enables flow control before checking for bootloader signature and
deciding whether FW download is needed or not. In case of V1 bootloader
chips w8987 and w8997, it is observed that if WLAN FW is downloaded first
and power save is enabled in wlan core, bootloader signatures are not
emitted by the BT core when the chip is put to sleep. As a result, the
driver skips FW download and subsequent HCI commands get timeout errors
in dmesg as shown below:

[  112.898867] Bluetooth: hci0: Opcode 0x c03 failed: -110
[  114.914865] Bluetooth: hci0: Setting baudrate failed (-110)
[  116.930856] Bluetooth: hci0: Setting wake-up method failed (-110)

By enabling the flow control, the host enables its RTS pin, and an
interrupt in chip's UART peripheral causes the bootloader to wake up,
enabling the bootloader signatures, which then helps in downloading
the bluetooth FW file.

This changes all instances of 0/1 for serdev_device_set_flow_control()
to false/true.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Neeraj Sanjay Kale authored and Luiz Augusto von Dentz committed Apr 24, 2023
1 parent f419863 commit b0310d6
Showing 1 changed file with 6 additions and 7 deletions.
13 changes: 6 additions & 7 deletions drivers/bluetooth/btnxpuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ static int nxp_download_firmware(struct hci_dev *hdev)
nxpdev->helper_downloaded = false;

serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, 0);
serdev_device_set_flow_control(nxpdev->serdev, false);
nxpdev->current_baudrate = HCI_NXP_PRI_BAUDRATE;

/* Wait till FW is downloaded and CTS becomes low */
Expand All @@ -548,7 +548,7 @@ static int nxp_download_firmware(struct hci_dev *hdev)
return -ETIMEDOUT;
}

serdev_device_set_flow_control(nxpdev->serdev, 1);
serdev_device_set_flow_control(nxpdev->serdev, true);
err = serdev_device_wait_for_cts(nxpdev->serdev, 1, 60000);
if (err < 0) {
bt_dev_err(hdev, "CTS is still high. FW Download failed.");
Expand Down Expand Up @@ -740,7 +740,7 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
if (nxpdev->baudrate_changed) {
serdev_device_set_baudrate(nxpdev->serdev,
HCI_NXP_SEC_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, 1);
serdev_device_set_flow_control(nxpdev->serdev, true);
nxpdev->current_baudrate = HCI_NXP_SEC_BAUDRATE;
}
goto free_skb;
Expand All @@ -763,7 +763,7 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
serdev_device_wait_until_sent(nxpdev->serdev, 0);
serdev_device_set_baudrate(nxpdev->serdev,
HCI_NXP_SEC_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, 1);
serdev_device_set_flow_control(nxpdev->serdev, true);
} else {
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
Expand Down Expand Up @@ -880,7 +880,7 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
if (nxpdev->baudrate_changed) {
serdev_device_set_baudrate(nxpdev->serdev,
HCI_NXP_SEC_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, 1);
serdev_device_set_flow_control(nxpdev->serdev, true);
nxpdev->current_baudrate = HCI_NXP_SEC_BAUDRATE;
}
goto free_skb;
Expand Down Expand Up @@ -984,7 +984,7 @@ static int nxp_set_ind_reset(struct hci_dev *hdev, void *data)
static int nxp_check_boot_sign(struct btnxpuart_dev *nxpdev)
{
serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, 0);
serdev_device_set_flow_control(nxpdev->serdev, true);
set_bit(BTNXPUART_CHECK_BOOT_SIGNATURE, &nxpdev->tx_state);

return wait_event_interruptible_timeout(nxpdev->check_boot_sign_wait_q,
Expand Down Expand Up @@ -1012,7 +1012,6 @@ static int nxp_setup(struct hci_dev *hdev)
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
}

serdev_device_set_flow_control(nxpdev->serdev, 1);
device_property_read_u32(&nxpdev->serdev->dev, "fw-init-baudrate",
&nxpdev->fw_init_baudrate);
if (!nxpdev->fw_init_baudrate)
Expand Down

0 comments on commit b0310d6

Please sign in to comment.