diff mbox series

[v4,1/3] Bluetooth: hci_qca: Add QCA Rome power off support to the qca_power_shutdown()

Message ID 20200115085552.11483-1-rjliao@codeaurora.org
State Accepted
Commit 5559904ccc0867a0ce796761681e40defe4a5f44
Headers show
Series [v4,1/3] Bluetooth: hci_qca: Add QCA Rome power off support to the qca_power_shutdown() | expand

Commit Message

Rocky Liao Jan. 15, 2020, 8:55 a.m. UTC
Current qca_power_shutdown() only supports wcn399x, this patch adds Rome
power off support to it. For Rome it just needs to pull down the bt_en
GPIO to power off it. This patch also replaces all the power off operation
in qca_close() with the unified qca_power_shutdown() call.

Signed-off-by: Rocky Liao <rjliao@codeaurora.org>
---

Changes in v2: None
Changes in v3: None
Changes in v4:
  -rebased the patch with latest code base
  -moved the change from qca_power_off() to qca_power_shutdown()
  -replaced all the power off operation in qca_close() with
   qca_power_shutdown()
  -updated commit message

 drivers/bluetooth/hci_qca.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

Comments

Matthias Kaehlcke Jan. 15, 2020, 5:33 p.m. UTC | #1
On Wed, Jan 15, 2020 at 04:55:51PM +0800, Rocky Liao wrote:
> This patch adds the retry of btsoc initialization when it fails. There are
> reports that the btsoc initialization may fail on some platforms but the
> repro ratio is very low. The symptoms is the firmware downloading failed
> due to the UART write timed out. The failure may be caused by UART,
> platform HW or the btsoc itself but it's very difficlut to root cause,
> given the repro ratio is very low. Add a retry for the btsoc initialization
> can work around most of the failures and make Bluetooth finally works.
> 
> Signed-off-by: Rocky Liao <rjliao@codeaurora.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> Changes in v4:
>   -rebased the patch with latet code
>   -refined macro and variable name
>   -updated commit message
> 
>  drivers/bluetooth/hci_qca.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
> index ecb74965be10..1139142e8eed 100644
> --- a/drivers/bluetooth/hci_qca.c
> +++ b/drivers/bluetooth/hci_qca.c
> @@ -55,6 +55,9 @@
>  /* Controller debug log header */
>  #define QCA_DEBUG_HANDLE	0x2EDC
>  
> +/* max retry count when init fails */
> +#define MAX_INIT_RETRIES 3
> +
>  /* Controller dump header */
>  #define QCA_SSR_DUMP_HANDLE		0x0108
>  #define QCA_DUMP_PACKET_SIZE		255
> @@ -1539,6 +1542,7 @@ static int qca_setup(struct hci_uart *hu)
>  	struct hci_dev *hdev = hu->hdev;
>  	struct qca_data *qca = hu->priv;
>  	unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
> +	unsigned int retries = 0;
>  	enum qca_btsoc_type soc_type = qca_soc_type(hu);
>  	const char *firmware_name = qca_get_firmware_name(hu);
>  	int ret;
> @@ -1559,6 +1563,7 @@ static int qca_setup(struct hci_uart *hu)
>  	bt_dev_info(hdev, "setting up %s",
>  		qca_is_wcn399x(soc_type) ? "wcn399x" : "ROME");
>  
> +retry:
>  	ret = qca_power_on(hdev);
>  	if (ret)
>  		return ret;
> @@ -1613,6 +1618,20 @@ static int qca_setup(struct hci_uart *hu)
>  		 * patch/nvm-config is found, so run with original fw/config.
>  		 */
>  		ret = 0;
> +	} else {
> +		if (retries < MAX_INIT_RETRIES) {
> +			qca_power_shutdown(hu);
> +			if (hu->serdev) {
> +				serdev_device_close(hu->serdev);
> +				ret = serdev_device_open(hu->serdev);
> +				if (ret) {
> +					bt_dev_err(hdev, "failed to open port");
> +					return ret;
> +				}
> +			}
> +			retries++;
> +			goto retry;
> +		}
>  	}
>  
>  	/* Setup bdaddr */
> -- 

Assuming that this is really a rare condition:

Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Marcel Holtmann Jan. 15, 2020, 9:37 p.m. UTC | #2
Hi Rocky,

> Current qca_power_shutdown() only supports wcn399x, this patch adds Rome
> power off support to it. For Rome it just needs to pull down the bt_en
> GPIO to power off it. This patch also replaces all the power off operation
> in qca_close() with the unified qca_power_shutdown() call.
> 
> Signed-off-by: Rocky Liao <rjliao@codeaurora.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> Changes in v4:
>  -rebased the patch with latest code base
>  -moved the change from qca_power_off() to qca_power_shutdown()
>  -replaced all the power off operation in qca_close() with
>   qca_power_shutdown()
>  -updated commit message
> 
> drivers/bluetooth/hci_qca.c | 28 ++++++++++++++++------------
> 1 file changed, 16 insertions(+), 12 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel
diff mbox series

Patch

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 992622dc1263..ecb74965be10 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -663,7 +663,6 @@  static int qca_flush(struct hci_uart *hu)
 /* Close protocol */
 static int qca_close(struct hci_uart *hu)
 {
-	struct qca_serdev *qcadev;
 	struct qca_data *qca = hu->priv;
 
 	BT_DBG("hu %p qca close", hu);
@@ -679,14 +678,7 @@  static int qca_close(struct hci_uart *hu)
 	destroy_workqueue(qca->workqueue);
 	qca->hu = NULL;
 
-	if (hu->serdev) {
-		qcadev = serdev_device_get_drvdata(hu->serdev);
-		if (qca_is_wcn399x(qcadev->btsoc_type))
-			qca_power_shutdown(hu);
-		else
-			gpiod_set_value_cansleep(qcadev->bt_en, 0);
-
-	}
+	qca_power_shutdown(hu);
 
 	kfree_skb(qca->rx_skb);
 
@@ -1685,6 +1677,7 @@  static void qca_power_shutdown(struct hci_uart *hu)
 	struct qca_serdev *qcadev;
 	struct qca_data *qca = hu->priv;
 	unsigned long flags;
+	enum qca_btsoc_type soc_type = qca_soc_type(hu);
 
 	qcadev = serdev_device_get_drvdata(hu->serdev);
 
@@ -1697,11 +1690,22 @@  static void qca_power_shutdown(struct hci_uart *hu)
 	qca_flush(hu);
 	spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
 
-	host_set_baudrate(hu, 2400);
-	qca_send_power_pulse(hu, false);
-	qca_regulator_disable(qcadev);
 	hu->hdev->hw_error = NULL;
 	hu->hdev->cmd_timeout = NULL;
+
+	/* Non-serdev device usually is powered by external power
+	 * and don't need additional action in driver for power down
+	 */
+	if (!hu->serdev)
+		return;
+
+	if (qca_is_wcn399x(soc_type)) {
+		host_set_baudrate(hu, 2400);
+		qca_send_power_pulse(hu, false);
+		qca_regulator_disable(qcadev);
+	} else {
+		gpiod_set_value_cansleep(qcadev->bt_en, 0);
+	}
 }
 
 static int qca_power_off(struct hci_dev *hdev)