Skip to content

Commit 24d48e0

Browse files
committed
WORKAROUND: Bluetooth: support Bluetooth over both USB and UART
This is a temporary workaround. On Hamoa boards, a single M.2 slot may host either a UART-based Bluetooth card or a USB-based Bluetooth card. As a result, the UART controller node is always present in the device tree, while the USB Bluetooth path is hot-pluggable. When Bluetooth is actually used over USB, the hci_qca UART driver still probes due to the DT node being present. During probe and power sequencing, it drives BT_EN low (either directly or via the WCN power sequencer), which can cut power to the shared Bluetooth device and cause the USB Bluetooth interface to disconnect. Model BT_EN as an always-on fixed regulator and ensure that the UART path does not claim power control when BT_EN is not described for that consumer: - Describe BT_EN as a fixed regulator (GPIO 116) that is boot-on and always-on, so it cannot be inadvertently deasserted by the UART probe. - Remove bt-enable-gpios from the WCN7850 power sequencer node and drop its BT pinctrl entry. - Wire the Bluetooth DT supplies to the always-on 3.3V rail so the UART driver can acquire its regulators without depending on the WCN PMU regulators in this dual-path configuration. - Treat WCN7850 like WCN6750/WCN6855 in hci_qca: if no bt_en GPIO is provided for the UART device, disable power control for that instance. - In pwrseq-qcom-wcn, do not match a "bluetooth" consumer if the sequencer has no bt-enable GPIO configured. This prevents the sequencer from binding to a Bluetooth consumer node in the "BT_EN tied high / absent from DT" case and allows the consumer to fall back accordingly. With these changes, probing the UART path no longer deasserts BT_EN when Bluetooth is operating over USB, avoiding unexpected USB disconnects. Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
1 parent 18e0821 commit 24d48e0

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,23 @@
470470
vin-supply = <&vreg_wcn_3p3>;
471471
};
472472

473+
vreg_wcn_bt_en: regulator-wcn-bt-en {
474+
compatible = "regulator-fixed";
475+
476+
regulator-name = "VREG_WCN_BT_EN";
477+
regulator-min-microvolt = <1800000>;
478+
regulator-max-microvolt = <1800000>;
479+
480+
gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>;
481+
enable-active-high;
482+
483+
pinctrl-0 = <&wcn_bt_en>;
484+
pinctrl-names = "default";
485+
486+
regulator-always-on;
487+
regulator-boot-on;
488+
};
489+
473490
vreg_wcn_3p3: regulator-wcn-3p3 {
474491
compatible = "regulator-fixed";
475492

@@ -1330,12 +1347,11 @@
13301347
output-low;
13311348
};
13321349

1333-
wcn_bt_en_hog: wcn-bt-en-state-hog {
1334-
gpio-hog;
1335-
gpios = <116 GPIO_ACTIVE_HIGH>;
1336-
output-high;
1337-
input-disable;
1338-
line-name = "BT_EN";
1350+
wcn_bt_en: wcn-bt-en-state {
1351+
pins = "gpio116";
1352+
function = "gpio";
1353+
drive-strength = <2>;
1354+
bias-disable;
13391355
};
13401356

13411357
wcn_wlan_en: wcn-wlan-en-state {
@@ -1376,13 +1392,13 @@
13761392
compatible = "qcom,wcn7850-bt";
13771393
max-speed = <3200000>;
13781394

1379-
vddaon-supply = <&vreg_pmu_aon_0p59>;
1380-
vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
1381-
vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
1382-
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
1383-
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
1384-
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
1385-
vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
1395+
vddrfacmn-supply = <&vreg_wcn_3p3>;
1396+
vddaon-supply = <&vreg_wcn_3p3>;
1397+
vddwlcx-supply = <&vreg_wcn_3p3>;
1398+
vddwlmx-supply = <&vreg_wcn_3p3>;
1399+
vddrfa0p8-supply = <&vreg_wcn_3p3>;
1400+
vddrfa1p2-supply = <&vreg_wcn_3p3>;
1401+
vddrfa1p8-supply = <&vreg_wcn_3p3>;
13861402
};
13871403
};
13881404

drivers/bluetooth/hci_qca.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2467,7 +2467,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)
24672467

24682468
if (!qcadev->bt_en &&
24692469
(data->soc_type == QCA_WCN6750 ||
2470-
data->soc_type == QCA_WCN6855))
2470+
data->soc_type == QCA_WCN6855 ||
2471+
data->soc_type == QCA_WCN7850))
24712472
power_ctrl_enabled = false;
24722473

24732474
qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",

drivers/power/sequencing/pwrseq-qcom-wcn.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,20 @@ static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
357357
reg_node->parent->parent != ctx->of_node)
358358
return PWRSEQ_NO_MATCH;
359359

360+
/*
361+
* If this is a Bluetooth consumer device but the bt-enable GPIO is not
362+
* configured in the power sequencer (e.g. BT_EN is tied high via a
363+
* hardware pull-up and therefore absent from the DT), don't match.
364+
* The consumer driver will fall back to its legacy power control path
365+
* and correctly set power_ctrl_enabled to false.
366+
*
367+
* BT device nodes are conventionally named "bluetooth" in the DT,
368+
* so use of_node_name_eq() as a generic check rather than enumerating
369+
* specific compatible strings.
370+
*/
371+
if (!ctx->bt_gpio && of_node_name_eq(dev_node, "bluetooth"))
372+
return PWRSEQ_NO_MATCH;
373+
360374
return PWRSEQ_MATCH_OK;
361375
}
362376

0 commit comments

Comments
 (0)