aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_qca.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/hci_qca.c')
-rw-r--r--drivers/bluetooth/hci_qca.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 5e03504c4e0c..237aea34b69f 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -59,8 +59,7 @@
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_TX_IDLE_TIMEOUT_MS 2000
-#define BAUDRATE_SETTLE_TIMEOUT_MS 300
-#define POWER_PULSE_TRANS_TIMEOUT_MS 100
+#define CMD_TRANS_TIMEOUT_MS 100
/* susclk rate */
#define SUSCLK_RATE_32KHZ 32768
@@ -964,6 +963,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
+ struct qca_serdev *qcadev;
struct sk_buff *skb;
u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 };
@@ -985,13 +985,21 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
skb_queue_tail(&qca->txq, skb);
hci_uart_tx_wakeup(hu);
- /* wait 300ms to change new baudrate on controller side
- * controller will come back after they receive this HCI command
- * then host can communicate with new baudrate to controller
- */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS));
- set_current_state(TASK_RUNNING);
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+
+ /* Wait for the baudrate change request to be sent */
+
+ while (!skb_queue_empty(&qca->txq))
+ usleep_range(100, 200);
+
+ serdev_device_wait_until_sent(hu->serdev,
+ msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
+
+ /* Give the controller time to process the request */
+ if (qcadev->btsoc_type == QCA_WCN3990)
+ msleep(10);
+ else
+ msleep(300);
return 0;
}
@@ -1004,10 +1012,11 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
hci_uart_set_baudrate(hu, speed);
}
-static int qca_send_power_pulse(struct hci_uart *hu, u8 cmd)
+static int qca_send_power_pulse(struct hci_uart *hu, bool on)
{
int ret;
- int timeout = msecs_to_jiffies(POWER_PULSE_TRANS_TIMEOUT_MS);
+ int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
+ u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE;
/* These power pulses are single byte command which are sent
* at required baudrate to wcn3990. On wcn3990, we have an external
@@ -1030,11 +1039,14 @@ static int qca_send_power_pulse(struct hci_uart *hu, u8 cmd)
}
serdev_device_wait_until_sent(hu->serdev, timeout);
-
- /* Wait for 100 uS for SoC to settle down */
- usleep_range(100, 200);
hci_uart_set_flow_control(hu, false);
+ /* Give to controller time to boot/shutdown */
+ if (on)
+ msleep(100);
+ else
+ msleep(10);
+
return 0;
}
@@ -1138,18 +1150,15 @@ static int qca_wcn3990_init(struct hci_uart *hu)
/* Forcefully enable wcn3990 to enter in to boot mode. */
host_set_baudrate(hu, 2400);
- ret = qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE);
+ ret = qca_send_power_pulse(hu, false);
if (ret)
return ret;
qca_set_speed(hu, QCA_INIT_SPEED);
- ret = qca_send_power_pulse(hu, QCA_WCN3990_POWERON_PULSE);
+ ret = qca_send_power_pulse(hu, true);
if (ret)
return ret;
- /* Wait for 100 ms for SoC to boot */
- msleep(100);
-
/* Now the device is in ready state to communicate with host.
* To sync host with device we need to reopen port.
* Without this, we will have RTS and CTS synchronization
@@ -1192,6 +1201,7 @@ static int qca_setup(struct hci_uart *hu)
* setup for every hci up.
*/
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
hu->hdev->shutdown = qca_power_off;
ret = qca_wcn3990_init(hu);
if (ret)
@@ -1289,7 +1299,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
host_set_baudrate(hu, 2400);
- qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE);
+ qca_send_power_pulse(hu, false);
qca_power_setup(hu, false);
}