From: Loic Poulain <loic.poulain@oss.qualcomm.com>
To: Manivannan Sadhasivam <mani@kernel.org>,
Bartosz Golaszewski <brgl@kernel.org>,
Marcel Holtmann <marcel@holtmann.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>,
Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konradybcio@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>
Cc: linux-pci@vger.kernel.org, linux-pm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org,
Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>,
Loic Poulain <loic.poulain@oss.qualcomm.com>
Subject: [PATCH v2 3/4] Bluetooth: hci_qca: Support QCA2066 on M.2 connector via pwrseq
Date: Thu, 02 Jul 2026 12:46:15 +0200 [thread overview]
Message-ID: <20260702-monza-wireless-v2-3-7b56e2a6a6d4@oss.qualcomm.com> (raw)
In-Reply-To: <20260702-monza-wireless-v2-0-7b56e2a6a6d4@oss.qualcomm.com>
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.
Also allocate bt_power unconditionally for all SOC types since the
pwrseq path is independent of the SOC type switch.
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
drivers/bluetooth/hci_qca.c | 81 ++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 38 deletions(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index e09debdb00a1b8e74ccd5de6147e240e533b4594..b04593a96e14ac9e87ae76fa00eda308e81dea25 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);
@@ -2256,7 +2259,7 @@ static void qca_power_off(struct hci_uart *hu)
break;
}
- if (power && power->pwrseq) {
+ if (power->pwrseq) {
pwrseq_power_off(power->pwrseq);
set_bit(QCA_BT_OFF, &qca->flags);
return;
@@ -2387,6 +2390,35 @@ static int qca_init_regulators(struct qca_power *qca,
return 0;
}
+/*
+ * Acquire the M.2 connector power sequencer.
+ *
+ * An OF graph link on the serdev controller is only present when the BT
+ * device is attached through an M.2 Key E connector. In that case the UART
+ * enable (W_DISABLE2#) is driven by the pcie-m2 power sequencer instead of a
+ * dedicated BT enable GPIO, so grab the "uart" pwrseq target from it.
+ *
+ * Returns 0 if no M.2 connector is present (nothing to do), a negative errno
+ * on error, otherwise 0 with qcadev->bt_power->pwrseq populated.
+ */
+static int qca_serdev_get_m2_pwrseq(struct qca_serdev *qcadev, bool *bt_en_available)
+{
+ struct serdev_device *serdev = qcadev->serdev_hu.serdev;
+ struct device *dev;
+
+ if (!of_graph_is_present(dev_of_node(&serdev->ctrl->dev)))
+ return 0;
+
+ qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, "uart");
+ if (IS_ERR(qcadev->bt_power->pwrseq))
+ return PTR_ERR(qcadev->bt_power->pwrseq);
+
+ dev = pwrseq_to_device(qcadev->bt_power->pwrseq);
+ *bt_en_available = device_property_present(dev, "w-disable2-gpios");
+
+ return 0;
+}
+
static int qca_serdev_probe(struct serdev_device *serdev)
{
struct qca_serdev *qcadev;
@@ -2417,25 +2449,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
else
qcadev->btsoc_type = QCA_ROME;
- switch (qcadev->btsoc_type) {
- case QCA_QCA6390:
- case QCA_WCN3950:
- case QCA_WCN3988:
- case QCA_WCN3990:
- case QCA_WCN3991:
- case QCA_WCN3998:
- case QCA_WCN6750:
- case QCA_WCN6855:
- case QCA_WCN7850:
- qcadev->bt_power = devm_kzalloc(&serdev->dev,
- sizeof(struct qca_power),
- GFP_KERNEL);
- if (!qcadev->bt_power)
- return -ENOMEM;
- break;
- default:
- break;
- }
+ qcadev->bt_power = devm_kzalloc(&serdev->dev, sizeof(struct qca_power), GFP_KERNEL);
+ if (!qcadev->bt_power)
+ return -ENOMEM;
+
+ err = qca_serdev_get_m2_pwrseq(qcadev, &bt_en_available);
+ if (err)
+ return err;
switch (qcadev->btsoc_type) {
case QCA_WCN3950:
@@ -2446,24 +2466,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
- /*
- * OF graph link is only present for BT devices attached through
- * the M.2 Key E connector.
- */
- if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) {
- struct device *dev;
-
- qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev,
- "uart");
- if (IS_ERR(qcadev->bt_power->pwrseq))
- return PTR_ERR(qcadev->bt_power->pwrseq);
-
- dev = pwrseq_to_device(qcadev->bt_power->pwrseq);
- if (!device_property_present(dev, "w-disable2-gpios"))
- bt_en_available = false;
-
+ /* M.2 connector modules are powered by the pwrseq acquired above. */
+ if (qcadev->bt_power->pwrseq)
break;
- }
if (!device_property_present(&serdev->dev, "enable-gpios")) {
/*
@@ -2545,7 +2550,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
return PTR_ERR(qcadev->bt_en);
}
- if (!qcadev->bt_en)
+ if (!qcadev->bt_en && !qcadev->bt_power->pwrseq)
bt_en_available = false;
qcadev->susclk = devm_clk_get_optional_enabled_with_rate(
--
2.34.1
next prev parent reply other threads:[~2026-07-02 10:46 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 10:46 [PATCH v2 0/4] arm64: dts: monaco-arduino-monza: Add support for LGA WiFi/BT module Loic Poulain
2026-07-02 10:46 ` [PATCH v2 1/4] dt-bindings: connector: pcie-m2-e: Add vendor LGA connector compatible Loic Poulain
2026-07-02 12:29 ` arm64: dts: monaco-arduino-monza: Add support for LGA WiFi/BT module bluez.test.bot
2026-07-02 13:17 ` [PATCH v2 1/4] dt-bindings: connector: pcie-m2-e: Add vendor LGA connector compatible Manivannan Sadhasivam
2026-07-03 7:11 ` Krzysztof Kozlowski
2026-07-03 8:41 ` Loic Poulain
2026-07-02 10:46 ` [PATCH v2 2/4] power: sequencing: pcie-m2: Add QCA2066 (QCNFA765) BT serdev ID Loic Poulain
2026-07-02 11:57 ` Dmitry Baryshkov
2026-07-03 8:30 ` (subset) " Bartosz Golaszewski
2026-07-02 10:46 ` Loic Poulain [this message]
2026-07-02 12:14 ` [PATCH v2 3/4] Bluetooth: hci_qca: Support QCA2066 on M.2 connector via pwrseq Dmitry Baryshkov
2026-07-02 14:17 ` Manivannan Sadhasivam
2026-07-02 14:34 ` Dmitry Baryshkov
2026-07-02 15:08 ` Manivannan Sadhasivam
2026-07-03 8:14 ` Loic Poulain
2026-07-04 0:11 ` Dmitry Baryshkov
2026-07-02 14:20 ` Manivannan Sadhasivam
2026-07-02 10:46 ` [PATCH v2 4/4] arm64: dts: qcom: monaco-arduino-monza: Add QCA2066 M.2 WiFi/BT support Loic Poulain
2026-07-02 12:15 ` Dmitry Baryshkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260702-monza-wireless-v2-3-7b56e2a6a6d4@oss.qualcomm.com \
--to=loic.poulain@oss.qualcomm.com \
--cc=andersson@kernel.org \
--cc=brgl@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=konradybcio@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=mani@kernel.org \
--cc=manivannan.sadhasivam@oss.qualcomm.com \
--cc=marcel@holtmann.org \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox