Re: [PATCH v4 08/11] Bluetooth: hci_qca: Support QCA2066 on M.2 connector via pwrseq
From: Bartosz Golaszewski
Date: Fri Jul 17 2026 - 08:41:38 EST
On Fri, 17 Jul 2026 14:32:27 +0200, Loic Poulain
<loic.poulain@xxxxxxxxxxxxxxxx> said:
> Hi Bartosz,
>
> On Fri, Jul 17, 2026 at 11:35 AM Bartosz Golaszewski <brgl@xxxxxxxxxx> wrote:
>>
>> On Thu, 16 Jul 2026 18:18:25 +0200, Loic Poulain
>> <loic.poulain@xxxxxxxxxxxxxxxx> said:
>> > 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 | 41 +++++++++++++++++++++++++++++++----------
>> > 1 file changed, 31 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
>> > index 25c4387136245fca25e375951f960d7240116781..22f6185a946ef04c45e41b2b34126e3f58d603ca 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,28 @@ 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;
>> > +
>> > + pwrseq = pwrseq_get(&serdev->ctrl->dev, "uart");
>>
>> There's devm_pwrseq_get() you can use instead of scheduling your own action.
>
> The reason is discussed here:
> https://lore.kernel.org/all/20260716083141.GA4101439@xxxxxxxxxx/
>
> We want the lifetime of the pwrseq descriptor to be tied to the serdev
> consumer device rather than the underlying serdev controller.
> Maybe a short comment explaining this relationship would be helpful.
>
Ah, subtle. Yeah a comment would be helpful.
Bart