Re: [PATCH v5 08/11] Bluetooth: hci_qca: Support QCA2066 on M.2 connector via pwrseq

From: Dmitry Baryshkov

Date: Wed Jul 22 2026 - 09:27:31 EST


On Mon, Jul 20, 2026 at 10:04:10AM +0200, Loic Poulain wrote:
> For QCA2066 (and other QCA chips) on M.2 connectors, the UART enable is
> controlled by the W_DISABLE2# signal managed by the pcie-m2 power sequencer
> rather than a dedicated BT enable GPIO.
>
> When the serdev controller has an OF graph (indicating it is connected to
> an M.2 connector), acquire the 'uart' pwrseq target from the connector's
> power sequencer and use it to control BT power instead of the bt-enable
> GPIO. This is factored out into qca_serdev_get_m2_pwrseq().
>
> Reviewed-by: Manivannan Sadhasivam <mani@xxxxxxxxxx>
> Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>
> ---
> drivers/bluetooth/hci_qca.c | 47 +++++++++++++++++++++++++++++++++++----------
> 1 file changed, 37 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
> index 7e4cb03d3db0722e5f9fa2e7a5a9a0894bf4f18c..8496bd428602c48d093bc76f9810abb9b1c43cfa 100644
> --- a/drivers/bluetooth/hci_qca.c
> +++ b/drivers/bluetooth/hci_qca.c
> @@ -1872,6 +1872,9 @@ static int qca_power_on(struct hci_dev *hdev)
> /* Controller needs time to bootup. */
> msleep(150);
> }
> +
> + if (qcadev->bt_power.pwrseq)
> + pwrseq_power_on(qcadev->bt_power.pwrseq);
> }
>
> clear_bit(QCA_BT_OFF, &qca->flags);
> @@ -2387,6 +2390,34 @@ static int qca_init_regulators(struct qca_power *qca,
> return 0;
> }
>
> +static void qca_serdev_put_pwrseq(void *data)
> +{
> + pwrseq_put(data);
> +}
> +
> +static int qca_serdev_get_m2_pwrseq(struct qca_serdev *qcadev)
> +{
> + struct serdev_device *serdev = qcadev->serdev_hu.serdev;
> + struct pwrseq_desc *pwrseq;
> +
> + if (!of_graph_is_present(dev_of_node(&serdev->ctrl->dev)))
> + return 0;
> +
> + /* The pwrseq is looked up on the serdev controller (which holds the
> + * OF graph to the M.2 connector), but its lifetime must follow this
> + * serdev consumer device, not the controller. So acquire it with the
> + * non-devres pwrseq_get() and release it via a devres action bound to
> + * &serdev->dev instead of using devm_pwrseq_get(&serdev->ctrl->dev).
> + */
> + pwrseq = pwrseq_get(&serdev->ctrl->dev, "uart");
> + if (IS_ERR(pwrseq))
> + return PTR_ERR(pwrseq);

We really need to add devm_pwrseq_get().


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>



--
With best wishes
Dmitry