From nobody Fri Sep 25 07:23:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AAAF3B2FE7; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; cv=none; b=ZSsBhjY7Hw3L3OarnETWkeNwcwtAtN9THyzcJEfdN8Cx2ga6tFoCi0U5DJQiH7ka78+81Y7uOqxG3GQgGCYyyyImuidyxnWuWVIfh7tuQttDrj68KyHqxYEGLrAbzFIIT7GfvR6sHEhlmoL6CNA6vx/HupyRo/29tQCYSg6XibU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; c=relaxed/simple; bh=QJutd9AAev9I1G0SJJsB4M4M+253o3CNxmEwUMtsGnw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qKOzB6yYZtdffIOyJIqmyEnbjDyRy//XBdXFK8+tKTAw+9m/RkYPZyZjIQOcraKh4iZqXl08jZy2lPJ0d7iG4v6WsnijqMQsWABDvitSpCqU+sX2CU5H8ltgGlk+hXFm4kHMtCDUKmZQdfI0XTeq0Z2e2ImE6M07dKExNuTaZlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=si7i2Nr/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="si7i2Nr/" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0F543C2BCB8; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789482262; bh=QJutd9AAev9I1G0SJJsB4M4M+253o3CNxmEwUMtsGnw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=si7i2Nr/Yam+UpqppnIB+Sydm5mrdonbip1gC1AFmQawmtRs2Vy5PTkcFygrxleDO S+jgG7e9PaLkbQZtNyiIiwujcj6LrIgR+CzSFvOwbGYL/93vH20Dabi9HDRc3Fs+of n74RbN1RDBRFNUq9Ct1iDaixc5FJErJTiskY8IybdYHlCQsClOeHFRFt13O37FzJoR 1gFcShg8qHRrIPTO3Vajjzqd8o3GmMnTRzzMjoTfCvudoItWAMGgFEsepc1qWZeu5D H2w0xUY5RMZ9+2qDYAe0ePBB+H/B8wCi7T3cJAHAnhLtfr5jCYfGFbyiTSsuhDAY0D dfBjakQndYXeA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECF1DC88E75; Tue, 15 Sep 2026 14:24:21 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Sep 2026 16:24:02 +0200 Subject: [PATCH 1/5] Bluetooth: hci_qca: Add auxiliary driver for PCIe M.2 modules Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-pci-m2-bt-rework-v1-1-3c7d9cf9c010@oss.qualcomm.com> References: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> In-Reply-To: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> To: Marcel Holtmann , Luiz Augusto von Dentz , Bartosz Golaszewski , Manivannan Sadhasivam , Amitkumar Karwar , Neeraj Kale , Philipp Zabel Cc: linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-pci@vger.kernel.org, linux-pm@vger.kernel.org, Rahul Samana , Wei Deng , Loic Poulain , Andy Shevchenko , Manivannan Sadhasivam X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7624; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=RMNCxswJp2WMqpIWCHfQMEALDdHbbIwauyM6oCpia9Q=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBqqVUSgiOVkUYUycnwFsQ0RDjbkuR3M10PNZJ5Q VoUo7dYsH+JATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaqlVEgAKCRBVnxHm/pHO 9T0YB/9WMjOjLkW2yfbn8QC3FaGPBFsKWeYd7evMln8bkscPdLhaBFKe8KVkC1heBCbXJsVuxYN Wsfh02l+Ck1Xi9NTA6MHckPK1AXKNY6bVq2NJVc8f93gSURmSkoEcmhR2+Df4/mn+vIYaZjkDPj bkDcLW1j4YHKMGjJVe4lADtFMSKjQLQWT9IvT/6/Up7M1nGZJbwdEeHuSScQfqvG2bD4wXkqOZN 67W2Ic8OOvx65b1dwKX8r+I0UWP9nN/AJ3eNYgRZuKLK+/W1GkOWO/VxJ8zn+OwbhjhABf6Tl5U xPp8ojRto4RatUQasU20PDEY9+/Kqm7FDx2LMOa4Asjlq778 X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam The QCA2066, WCN6855 and WCN7850 combo modules expose Bluetooth over UART. Since these modules are attached over PCIe, these are not described in firmware like devicetree. So these modules are discovered at runtime over PCIe by the power sequencing driver, which allocates the UART serdev and creates an auxiliary device carrying that transport and the power sequencing target to power up the Bluetooth function. Add an auxiliary driver that binds to this device. It reuses the serdev provided by the producer, brings up the controller through the existing UART transport with hci_uart_register_device() and drives power through the sequencer obtained with devm_pwrseq_get(). Add a shared header describing the auxiliary device so that the power sequencing driver and hci_qca agree on its layout. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Bartosz Golaszewski Tested-by: Sherry Sun --- MAINTAINERS | 1 + drivers/bluetooth/Kconfig | 1 + drivers/bluetooth/hci_qca.c | 101 ++++++++++++++++++++++++++++++++++= ++++ include/linux/pwrseq/pcie-m2-bt.h | 38 ++++++++++++++ 4 files changed, 141 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..ed0c622fa83f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21750,6 +21750,7 @@ S: Maintained F: Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml F: Documentation/devicetree/bindings/connector/pcie-m2-m-connector.yaml F: drivers/power/sequencing/pwrseq-pcie-m2.c +F: include/linux/pwrseq/pcie-m2-bt.h =20 POWER STATE COORDINATION INTERFACE (PSCI) M: Mark Rutland diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 4e8c24d757e9..3acaec6f90ac 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -244,6 +244,7 @@ config BT_HCIUART_QCA depends on BT_HCIUART_SERDEV select BT_HCIUART_H4 select BT_QCA + select AUXILIARY_BUS help The Qualcomm Atheros protocol supports HCI In-Band Sleep feature over serial port interface(H4) between controller and host. diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index cfefa8b72e25..15cc6cca9057 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -15,6 +15,7 @@ * by Maxim Krasnyansky and Marcel Holtmann. */ =20 +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -2850,15 +2852,114 @@ static struct serdev_device_driver qca_serdev_driv= er =3D { }, }; =20 +static int qca_bt_aux_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct pcie_m2_bt_auxdev *bt_auxdev =3D to_pcie_m2_bt_auxdev(adev); + struct serdev_device *serdev =3D bt_auxdev->serdev; + const struct qca_device_data *data; + struct qca_serdev *qcadev; + struct hci_dev *hdev; + bool controllable; + int err; + + data =3D (const struct qca_device_data *)id->driver_data; + if (!data) + return -ENODEV; + + qcadev =3D devm_kzalloc(&adev->dev, sizeof(*qcadev), GFP_KERNEL); + if (!qcadev) + return -ENOMEM; + + qcadev->serdev_hu.serdev =3D serdev; + qcadev->btsoc_type =3D data->soc_type; + serdev_device_set_drvdata(serdev, qcadev); + + qcadev->pwrseq =3D devm_pwrseq_get(&adev->dev, bt_auxdev->pwrseq_target); + if (IS_ERR(qcadev->pwrseq)) + return dev_err_probe(&adev->dev, PTR_ERR(qcadev->pwrseq), + "failed to acquire power sequencer\n"); + + /* + * When the host cannot gate the BT power individually, treat it as + * always-on. + */ + controllable =3D pwrseq_is_controllable(qcadev->pwrseq); + if (!controllable) { + pwrseq_enable(qcadev->pwrseq); + qcadev->pwrseq =3D NULL; + } + + err =3D hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); + if (err) + return dev_err_probe(&adev->dev, err, + "failed to register hci_uart device\n"); + + hdev =3D qcadev->serdev_hu.hdev; + + if (controllable) { + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); + hdev->shutdown =3D qca_hci_shutdown; + } + + if (data->capabilities & QCA_CAP_WIDEBAND_SPEECH) + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); + + if (!(data->capabilities & QCA_CAP_VALID_LE_STATES)) + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); + + if (data->capabilities & QCA_CAP_HFP_HW_OFFLOAD) + qcadev->support_hfp_hw_offload =3D true; + + auxiliary_set_drvdata(adev, qcadev); + + return 0; +} + +static void qca_bt_aux_remove(struct auxiliary_device *adev) +{ + struct qca_serdev *qcadev =3D auxiliary_get_drvdata(adev); + + hci_uart_unregister_device(&qcadev->serdev_hu); +} + +static const struct auxiliary_device_id qca_bt_aux_id_table[] =3D { + { + .name =3D "pwrseq_pcie_m2.qca2066-bt", + .driver_data =3D (kernel_ulong_t)&qca_soc_data_qca2066, + }, + { + .name =3D "pwrseq_pcie_m2.wcn6855-bt", + .driver_data =3D (kernel_ulong_t)&qca_soc_data_wcn6855, + }, + { + .name =3D "pwrseq_pcie_m2.wcn7850-bt", + .driver_data =3D (kernel_ulong_t)&qca_soc_data_wcn7850, + }, + { } +}; +MODULE_DEVICE_TABLE(auxiliary, qca_bt_aux_id_table); + +static struct auxiliary_driver qca_bt_aux_driver =3D { + .name =3D "qca_bt", + .probe =3D qca_bt_aux_probe, + .remove =3D qca_bt_aux_remove, + .id_table =3D qca_bt_aux_id_table, +}; + int __init qca_init(void) { serdev_device_driver_register(&qca_serdev_driver); =20 + auxiliary_driver_register(&qca_bt_aux_driver); + return hci_uart_register_proto(&qca_proto); } =20 int __exit qca_deinit(void) { + auxiliary_driver_unregister(&qca_bt_aux_driver); + serdev_device_driver_unregister(&qca_serdev_driver); =20 return hci_uart_unregister_proto(&qca_proto); diff --git a/include/linux/pwrseq/pcie-m2-bt.h b/include/linux/pwrseq/pcie-= m2-bt.h new file mode 100644 index 000000000000..39e7475d7962 --- /dev/null +++ b/include/linux/pwrseq/pcie-m2-bt.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * Author: Manivannan Sadhasivam + */ + +#ifndef __POWER_SEQUENCING_PCIE_M2_BT_H__ +#define __POWER_SEQUENCING_PCIE_M2_BT_H__ + +#include +#include + +struct serdev_device; + +/** + * struct pcie_m2_bt_auxdev - Auxiliary device for the Bluetooth function = of a + * PCIe M.2 module. + * @adev: Auxiliary device. + * @serdev: Serdev device representing the UART transport. Allocated and o= wned + * by the producer (power sequencing driver). + * @pwrseq_target: Power sequencing target the consumer requests to power = up the + * Bluetooth function. + * + * On M.2 modules exposing Bluetooth over UART, the controller is not desc= ribed + * in firmware. The power sequencing driver detects the module over PCIe a= nd + * publishes this auxiliary device so that the Bluetooth driver can bind t= o the + * pre-allocated serdev transport and drive power sequencing. + */ +struct pcie_m2_bt_auxdev { + struct auxiliary_device adev; + struct serdev_device *serdev; + const char *pwrseq_target; +}; + +#define to_pcie_m2_bt_auxdev(_adev) \ + container_of(_adev, struct pcie_m2_bt_auxdev, adev) + +#endif /* __POWER_SEQUENCING_PCIE_M2_BT_H__ */ --=20 2.43.0 From nobody Fri Sep 25 07:23:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A97A38E5E9; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; cv=none; b=fD5cFez08IDIIGroQujfM7DR/+XGYPwYXtIWjEfJReAzfYfi+OiHRk1a1Zv6j1d4ZlCbxWRyfy3VPfA9OejrRMb1sZ3N1lc3z4IyqM1eFyNzEVTQ2f8ZvSwDvA8/wKev8Ac/JbHuln/vj2vbBXQBn4inZmxqYSjiSwE1oAOk5is= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; c=relaxed/simple; bh=5m0BATPMZrX7gMf8KfVfoRFTgv2tzwvXCXMnN+LCn84=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dAqUGkcEDhX7nVIWJNkpfek4s4sE5HfNoo+5XfbhvjEyVdYv6N1L9pfPc980Cg5heP5BySxAP6kf7zNZWf112GZzSYYubb6tLQ/+JRXLRl48r5Fm/lODMvZhcNWpUiRb9xY0KGTWnM31cYjruh0BMrRyAks3s3V7/aPY1DoQOww= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bvQqSXrM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bvQqSXrM" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1FAABC4AF09; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789482262; bh=5m0BATPMZrX7gMf8KfVfoRFTgv2tzwvXCXMnN+LCn84=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=bvQqSXrMiD9QvQCyuvBj377p72a3LsJE967rv3/4sjzJ9VfZGwNlfTH2vV/OAqFKb s0e6lgSfxMfFeUTVeWaVRdOkuRTSPW+LJSNWxRj/eSKnQf+g48Q0OU1Y4MaRfBrUrv 3I5jei4wusekZkdQ9YBw8rALfFEWX0ikVeYgM/eHCSReEiDrm6FRaojX/4C3B1rWss ZygyNJb7sYVpB7ku64JT9BM4cPNN5r6kfBDfWhmbHNkcVDuy6nZMmRoR51eFuE4zYL RNV6RO9rw8nX2isuY4fCwy50E/fsp6iZtDWkKnM06iT4983tvdAuhozYwkbWJA4upY XGlD6xDIXWmmg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 099ECC88E7F; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Sep 2026 16:24:03 +0200 Subject: [PATCH 2/5] Bluetooth: btnxpuart: Add auxiliary driver for PCIe M.2 modules Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-pci-m2-bt-rework-v1-2-3c7d9cf9c010@oss.qualcomm.com> References: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> In-Reply-To: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> To: Marcel Holtmann , Luiz Augusto von Dentz , Bartosz Golaszewski , Manivannan Sadhasivam , Amitkumar Karwar , Neeraj Kale , Philipp Zabel Cc: linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-pci@vger.kernel.org, linux-pm@vger.kernel.org, Rahul Samana , Wei Deng , Loic Poulain , Andy Shevchenko , Manivannan Sadhasivam X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9263; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=7K0wcp3nNpEPO5o8mNQzwNVqWyirfaYgXDqIo4bzR5Q=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBqqVUS2pxxHoNixyL/9U7DgyQwmVwge6LQUfwyC LWe0AGfW42JATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaqlVEgAKCRBVnxHm/pHO 9bPPCACJcgH6EUBoOGFfvp+muG3R//l4bMey4PrU72tB5LlCIoXJf+YO8IpRiuuEYpxvhUSoTqT 76CMvodhayYyuvym53u/5XWF3RPqhIAySPxlQWDFGrgOx8fs4Bc3HnrreFUtYCS+qlU4MnfqEkL KLmVfiL0X8NfiDqRMYHRIskgmOUtuAGnOCs2Nok8B2t5TqHdDmhxxVLWsDlDXpfXuWtWDhk1U0C Jccaq85Lw7YaAkWwrl740Xe6oW90s3VGexjaEqORvTpxpjNGWV8vi5jbvqdRUG0ES/12trt2Rwk pw+gkBCAdNi4u0qbZfBN1rRJs2cuTlAY3SeYkkGfq40n6AhS X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam The 88W8987 combo module exposes Bluetooth over UART. Since this module is attached over PCIe, it is not described in firmware like devicetree. So it is discovered at runtime over PCIe by the power sequencing driver, which allocates the UART serdev and creates an auxiliary device carrying that transport and the power sequencing target to power up the Bluetooth function. Add an auxiliary driver that binds to this device. It reuses the serdev provided by the producer, brings up the controller through the existing UART transport with nxp_register_dev() and drives power through the sequencer obtained with pwrseq_get(). Factor the HCI device setup and teardown shared with the serdev probe into helpers so both paths register the same controller. Signed-off-by: Manivannan Sadhasivam Tested-by: Sherry Sun --- drivers/bluetooth/Kconfig | 1 + drivers/bluetooth/btnxpuart.c | 187 +++++++++++++++++++++++++++++++++-----= ---- 2 files changed, 147 insertions(+), 41 deletions(-) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 3acaec6f90ac..ce0cf50b663b 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -454,6 +454,7 @@ config BT_NXPUART select BT_HCIUART_H4 select CRC32 select CRC8 + select AUXILIARY_BUS help NXP is serial driver required for NXP Bluetooth devices with UART interface. diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index 25e7b41b349f..2672e481ef15 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -7,10 +7,12 @@ #include #include =20 +#include #include #include #include #include +#include #include #include #include @@ -1840,20 +1842,13 @@ static bool nxp_m2_connector_is_available(struct de= vice *dev) return remote && of_device_is_available(remote); } =20 -static int nxp_serdev_probe(struct serdev_device *serdev) +static int nxp_register_dev(struct btnxpuart_dev *nxpdev) { + struct serdev_device *serdev =3D nxpdev->serdev; struct hci_dev *hdev; - struct btnxpuart_dev *nxpdev; bdaddr_t ba =3D {0}; int err; =20 - nxpdev =3D devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL); - if (!nxpdev) - return -ENOMEM; - - nxpdev->nxp_data =3D (struct btnxpuart_data *)device_get_match_data(&serd= ev->dev); - - nxpdev->serdev =3D serdev; serdev_device_set_drvdata(serdev, nxpdev); =20 serdev_device_set_client_ops(serdev, &btnxpuart_client_ops); @@ -1864,12 +1859,12 @@ static int nxp_serdev_probe(struct serdev_device *s= erdev) init_waitqueue_head(&nxpdev->fw_dnld_done_wait_q); init_waitqueue_head(&nxpdev->check_boot_sign_wait_q); =20 - device_property_read_u32(&nxpdev->serdev->dev, "fw-init-baudrate", + device_property_read_u32(&serdev->dev, "fw-init-baudrate", &nxpdev->fw_init_baudrate); if (!nxpdev->fw_init_baudrate) nxpdev->fw_init_baudrate =3D FW_INIT_BAUDRATE; =20 - device_property_read_u32(&nxpdev->serdev->dev, "max-speed", + device_property_read_u32(&serdev->dev, "max-speed", &nxpdev->secondary_baudrate); if (!nxpdev->secondary_baudrate || (nxpdev->secondary_baudrate !=3D HCI_NXP_SEC_BAUDRATE_3M && @@ -1884,36 +1879,11 @@ static int nxp_serdev_probe(struct serdev_device *s= erdev) =20 crc8_populate_msb(crc8_table, POLYNOMIAL8); =20 - nxpdev->pdn =3D devm_reset_control_get_optional_shared(&serdev->dev, NULL= ); - if (IS_ERR(nxpdev->pdn)) - return PTR_ERR(nxpdev->pdn); - - err =3D devm_regulator_get_enable(&serdev->dev, "vcc"); - if (err) { - dev_err(&serdev->dev, "Failed to enable vcc regulator\n"); - return err; - } - - if (nxp_m2_connector_is_available(&serdev->ctrl->dev)) { - struct pwrseq_desc *pwrseq; - - pwrseq =3D pwrseq_get(&serdev->ctrl->dev, "uart"); - if (IS_ERR(pwrseq)) - return dev_err_probe(&serdev->dev, PTR_ERR(pwrseq), - "failed to get pwrseq\n"); - - nxpdev->pwrseq =3D pwrseq; - err =3D pwrseq_enable(pwrseq); - if (err) - goto err_pwrseq_put; - } - /* Initialize and register HCI device */ hdev =3D hci_alloc_dev(); if (!hdev) { dev_err(&serdev->dev, "Can't allocate HCI device\n"); - err =3D -ENOMEM; - goto err_pwrseq_put; + return -ENOMEM; } =20 reset_control_deassert(nxpdev->pdn); @@ -1938,7 +1908,7 @@ static int nxp_serdev_probe(struct serdev_device *ser= dev) hdev->set_bdaddr =3D nxp_set_bdaddr; SET_HCIDEV_DEV(hdev, &serdev->dev); =20 - device_property_read_u8_array(&nxpdev->serdev->dev, + device_property_read_u8_array(&serdev->dev, "local-bd-address", (u8 *)&ba, sizeof(ba)); if (bacmp(&ba, BDADDR_ANY)) @@ -1965,15 +1935,61 @@ static int nxp_serdev_probe(struct serdev_device *s= erdev) probe_fail: reset_control_assert(nxpdev->pdn); hci_free_dev(hdev); + + return err; +} + +static int nxp_serdev_probe(struct serdev_device *serdev) +{ + struct btnxpuart_dev *nxpdev; + int err; + + nxpdev =3D devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL); + if (!nxpdev) + return -ENOMEM; + + nxpdev->nxp_data =3D (struct btnxpuart_data *)device_get_match_data(&serd= ev->dev); + + nxpdev->serdev =3D serdev; + + nxpdev->pdn =3D devm_reset_control_get_optional_shared(&serdev->dev, NULL= ); + if (IS_ERR(nxpdev->pdn)) + return PTR_ERR(nxpdev->pdn); + + err =3D devm_regulator_get_enable(&serdev->dev, "vcc"); + if (err) { + dev_err(&serdev->dev, "Failed to enable vcc regulator\n"); + return err; + } + + if (nxp_m2_connector_is_available(&serdev->ctrl->dev)) { + struct pwrseq_desc *pwrseq; + + pwrseq =3D pwrseq_get(&serdev->ctrl->dev, "uart"); + if (IS_ERR(pwrseq)) + return dev_err_probe(&serdev->dev, PTR_ERR(pwrseq), + "failed to get pwrseq\n"); + + nxpdev->pwrseq =3D pwrseq; + err =3D pwrseq_enable(pwrseq); + if (err) + goto err_pwrseq_put; + } + + err =3D nxp_register_dev(nxpdev); + if (err) + goto err_pwrseq_put; + + return 0; + err_pwrseq_put: if (nxpdev->pwrseq) pwrseq_put(nxpdev->pwrseq); return err; } =20 -static void nxp_serdev_remove(struct serdev_device *serdev) +static void __nxp_remove(struct btnxpuart_dev *nxpdev) { - struct btnxpuart_dev *nxpdev =3D serdev_device_get_drvdata(serdev); struct hci_dev *hdev =3D nxpdev->hdev; =20 if (is_fw_downloading(nxpdev)) { @@ -2000,6 +2016,58 @@ static void nxp_serdev_remove(struct serdev_device *= serdev) hci_free_dev(hdev); } =20 +static void nxp_serdev_remove(struct serdev_device *serdev) +{ + struct btnxpuart_dev *nxpdev =3D serdev_device_get_drvdata(serdev); + + __nxp_remove(nxpdev); +} + +static int nxp_bt_aux_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct pcie_m2_bt_auxdev *bt_auxdev =3D to_pcie_m2_bt_auxdev(adev); + struct btnxpuart_dev *nxpdev; + struct pwrseq_desc *pwrseq; + int err; + + nxpdev =3D devm_kzalloc(&adev->dev, sizeof(*nxpdev), GFP_KERNEL); + if (!nxpdev) + return -ENOMEM; + + nxpdev->nxp_data =3D (struct btnxpuart_data *)id->driver_data; + nxpdev->serdev =3D bt_auxdev->serdev; + + pwrseq =3D pwrseq_get(&adev->dev, bt_auxdev->pwrseq_target); + if (IS_ERR(pwrseq)) + return dev_err_probe(&adev->dev, PTR_ERR(pwrseq), + "failed to get pwrseq\n"); + + nxpdev->pwrseq =3D pwrseq; + err =3D pwrseq_enable(pwrseq); + if (err) + goto err_pwrseq_put; + + err =3D nxp_register_dev(nxpdev); + if (err) + goto err_pwrseq_put; + + auxiliary_set_drvdata(adev, nxpdev); + + return 0; + +err_pwrseq_put: + pwrseq_put(nxpdev->pwrseq); + return err; +} + +static void nxp_bt_aux_remove(struct auxiliary_device *adev) +{ + struct btnxpuart_dev *nxpdev =3D auxiliary_get_drvdata(adev); + + __nxp_remove(nxpdev); +} + static int __maybe_unused nxp_serdev_suspend(struct device *dev) { struct btnxpuart_dev *nxpdev =3D dev_get_drvdata(dev); @@ -2075,7 +2143,44 @@ static struct serdev_device_driver nxp_serdev_driver= =3D { }, }; =20 -module_serdev_device_driver(nxp_serdev_driver); +static const struct auxiliary_device_id nxp_bt_aux_id_table[] =3D { + { + .name =3D "pwrseq_pcie_m2.88w8987-bt", + .driver_data =3D (kernel_ulong_t)&w8987_data, + }, + { } +}; +MODULE_DEVICE_TABLE(auxiliary, nxp_bt_aux_id_table); + +static struct auxiliary_driver nxp_bt_aux_driver =3D { + .name =3D "nxp_bt", + .probe =3D nxp_bt_aux_probe, + .remove =3D nxp_bt_aux_remove, + .id_table =3D nxp_bt_aux_id_table, +}; + +static int __init nxp_bt_init(void) +{ + int err; + + err =3D serdev_device_driver_register(&nxp_serdev_driver); + if (err) + return err; + + err =3D auxiliary_driver_register(&nxp_bt_aux_driver); + if (err) + serdev_device_driver_unregister(&nxp_serdev_driver); + + return err; +} +module_init(nxp_bt_init); + +static void __exit nxp_bt_exit(void) +{ + auxiliary_driver_unregister(&nxp_bt_aux_driver); + serdev_device_driver_unregister(&nxp_serdev_driver); +} +module_exit(nxp_bt_exit); =20 MODULE_AUTHOR("Neeraj Sanjay Kale "); MODULE_DESCRIPTION("NXP Bluetooth Serial driver"); --=20 2.43.0 From nobody Fri Sep 25 07:23:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6CB7E3B38B1; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; cv=none; b=fCJmp3q+8yIr4XQS3BmmK406Gz/USic5pJt8Ueh8XCHORg2GaVv3FfR3b0eez2Jsad3tEhip7PRod4dVRJRW1RFQwWvEXnZj6kR35AR73//4cpzEK942bbX1wBXCEGMRyrtf4tKMFHs9XnVH/Lw/4z3ggPNCkDHlqT0RLnXu3iA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; c=relaxed/simple; bh=Hnopdr7WA9U8EE7N/nJoCFi8vbeDzNHxhN6zZO8yiBg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ohBGSDpkOIs7akGLHBRgqUJHlr+5Uu1cZwhJ9aP41D8c8FXMBT4UgRc3ujDjGuSkbfTaPMXuVVGfKrWGfa7D9htF5S/fPidhks3TYhnnqK29WXTsMKOtGGLJ8yWPzvpg6abspEWss3RS7HlebYklDAvI3AQU6Y2Yi+HmhLWLWxc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y/8ta70r; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Y/8ta70r" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2D946C2BCFC; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789482262; bh=Hnopdr7WA9U8EE7N/nJoCFi8vbeDzNHxhN6zZO8yiBg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Y/8ta70rcaO6avZlbT9MuJYT5Ejjg0NwfsrKXOB7zZQud8lBvoEHKyj5PdhD+nVHb wklF9T+4rpiezAC5m8mVbCm+Wxmdv6jzYkK2cvPcCQfBZSCBgDC71CjAG3IFUIBgQC B9QgIlr0D/o7QVIkWGCt09AwHTXG2Z3PBlDnQHhJgY9xF0NsymcQbwg/d8z51GPcw7 WsMA3oW8/wTDPKkMZBmGs9x7jG/upNnVZJjP1K2NWWnI99q2PXNFrYha1JRU/amRQk 3v9dq7oXCOxUGBdJ+ISpbj76SgvK3VCrgcB2qqK11b/MWwHGCLLtrs0A2rfwlieCgh mCQk9fLM1wPVg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B527C88E53; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Sep 2026 16:24:04 +0200 Subject: [PATCH 3/5] power: sequencing: pcie-m2: Create auxiliary device for the M.2 BT interface Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-pci-m2-bt-rework-v1-3-3c7d9cf9c010@oss.qualcomm.com> References: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> In-Reply-To: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> To: Marcel Holtmann , Luiz Augusto von Dentz , Bartosz Golaszewski , Manivannan Sadhasivam , Amitkumar Karwar , Neeraj Kale , Philipp Zabel Cc: linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-pci@vger.kernel.org, linux-pm@vger.kernel.org, Rahul Samana , Wei Deng , Loic Poulain , Andy Shevchenko , Manivannan Sadhasivam X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9879; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=ysdYQzQTS6vV5RimaY4+yjdKUGeSc5gOn2WXxQ/9ltg=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBqqVUSc4FVnWW9dvtIIVeOclToM1k8bzAypjESU i2EyBGGkQ6JATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaqlVEgAKCRBVnxHm/pHO 9Q5GB/wNCfs5K5guix1U95aAVoWht4Lu1gHZBDY3WjE5+zxFf9nOqf578hPwLgJtKGy0BjYTi3b Jmfg8Kcx8nzV7E0GZdbTvynVtw/PQtv9lTyzWYNBT0zPtg3+SDRYmy6GgPn/Zee90SX04SaJYRr MGrEtN1q7oYKLQ8O7nW5mphnUcyEet5/KXygAQYVOQUtJukxtIw9bYpoq+P/WUnXmoCp9FHe2yf SPI16DfUgHVosjZeF6OVH8sZoYpBKvrJxB6Zd/VAdM1mrbVqAqZt1S/Sv4jpgsgnBpX13nDXWTT MubVjkOVSatWDHA8Fi3wLNPn8wUI59WH36EQy5BPgS8x0tej X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam Currently, the driver instantiates the BT interface of the WCN6855 and WCN7850 combo modules by creating a devicetree node at runtime using an of_changeset, with the compatible passed through the PCI ID table. But this method of creating a devicetree node just for matching with the driver is not recommended. So create an auxiliary device for the BT interface instead. The serdev transport is still allocated here and handed over to the Bluetooth driver through the auxiliary device, along with the power sequencing target used to power up the controller. Also extend the provider match so that the auxiliary device created for this connector is matched as its power sequencing consumer. Since the runtime node creation is now gone, select AUXILIARY_BUS in place of OF_DYNAMIC. Signed-off-by: Manivannan Sadhasivam Tested-by: Sherry Sun --- drivers/power/sequencing/Kconfig | 2 +- drivers/power/sequencing/pwrseq-pcie-m2.c | 137 ++++++++++++++++----------= ---- 2 files changed, 75 insertions(+), 64 deletions(-) diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kc= onfig index 1c5f5820f5b7..2943af5db135 100644 --- a/drivers/power/sequencing/Kconfig +++ b/drivers/power/sequencing/Kconfig @@ -40,7 +40,7 @@ config POWER_SEQUENCING_PCIE_M2 depends on OF depends on PCI depends on SERIAL_DEV_BUS - select OF_DYNAMIC + select AUXILIARY_BUS help Say Y here to enable the power sequencing driver for PCIe M.2 connectors. This driver handles the power sequencing for the M.2 diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequ= encing/pwrseq-pcie-m2.c index bee1aa0e077d..9e485641695c 100644 --- a/drivers/power/sequencing/pwrseq-pcie-m2.c +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c @@ -4,16 +4,18 @@ * Author: Manivannan Sadhasivam */ =20 +#include #include #include #include +#include #include #include #include #include -#include #include #include +#include #include #include #include @@ -21,7 +23,7 @@ =20 struct pwrseq_pci_dev { struct serdev_device *serdev; - struct of_changeset *ocs; + struct pcie_m2_bt_auxdev *bt; struct pci_dev *pdev; struct list_head list; }; @@ -196,6 +198,14 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *= pwrseq, struct pwrseq_pcie_m2_ctx *ctx =3D pwrseq_device_get_drvdata(pwrseq); struct device_node *endpoint __free(device_node) =3D NULL; =20 + /* + * The Bluetooth function is represented by an auxiliary device created + * by this driver. It has no OF node, so match it by verifying that it + * is a child of this connector. + */ + if (dev_is_auxiliary(dev) && dev->parent =3D=3D ctx->dev) + return PWRSEQ_MATCH_OK; + /* * Traverse the 'remote-endpoint' nodes and check if the remote node's * parent matches the OF node of 'dev'. @@ -210,78 +220,86 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device = *pwrseq, return PWRSEQ_NO_MATCH; } =20 +/* + * The Bluetooth interface of a supported module is exposed as an auxiliary + * device. Its name (combined with this driver's module name) is matched by + * the Bluetooth driver. Store that name as the PCI ID driver data. + */ static const struct pci_device_id pwrseq_m2_pci_ids[] =3D { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x2b43), - .driver_data =3D (kernel_ulong_t)"nxp,88w8987-bt" }, + .driver_data =3D (kernel_ulong_t)"88w8987-bt" }, { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, 0x3003), - .driver_data =3D (kernel_ulong_t)"nxp,88w8987-bt" }, + .driver_data =3D (kernel_ulong_t)"88w8987-bt" }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_QCOM, 0x0108), - .driver_data =3D (kernel_ulong_t)"qcom,qca2066-bt" }, + .driver_data =3D (kernel_ulong_t)"qca2066-bt" }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_FOXCONN, 0xe10= 5), - .driver_data =3D (kernel_ulong_t)"qcom,wcn6855-bt" }, + .driver_data =3D (kernel_ulong_t)"wcn6855-bt" }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_QCOM, 0x337e), - .driver_data =3D (kernel_ulong_t)"qcom,wcn6855-bt" }, + .driver_data =3D (kernel_ulong_t)"wcn6855-bt" }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1107, PCI_VENDOR_ID_QCOM, 0x337c), - .driver_data =3D (kernel_ulong_t)"qcom,wcn7850-bt" }, + .driver_data =3D (kernel_ulong_t)"wcn7850-bt" }, { } /* Sentinel */ }; =20 -static int pwrseq_pcie_m2_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx, +static DEFINE_IDA(pwrseq_pcie_m2_bt_ida); + +static void pwrseq_pcie_m2_bt_release(struct device *dev) +{ + struct pcie_m2_bt_auxdev *bt =3D + to_pcie_m2_bt_auxdev(to_auxiliary_dev(dev)); + + ida_free(&pwrseq_pcie_m2_bt_ida, bt->adev.id); + kfree(bt); +} + +static int pwrseq_pcie_m2_create_bt_aux(struct pwrseq_pcie_m2_ctx *ctx, struct pwrseq_pci_dev *pci_dev, - struct device_node *parent, struct pci_dev *pdev) { const struct pci_device_id *id; struct device *dev =3D ctx->dev; - const char *compatible; - struct device_node *np; + struct pcie_m2_bt_auxdev *bt; int ret; =20 id =3D pci_match_id(pwrseq_m2_pci_ids, pdev); if (WARN_ON_ONCE(!id)) /* Shouldn't happen */ return -ENODEV; =20 - compatible =3D (const char *)id->driver_data; - - pci_dev->ocs =3D kzalloc_obj(*pci_dev->ocs); - if (!pci_dev->ocs) + bt =3D kzalloc_obj(*bt); + if (!bt) return -ENOMEM; =20 - of_changeset_init(pci_dev->ocs); + ret =3D ida_alloc(&pwrseq_pcie_m2_bt_ida, GFP_KERNEL); + if (ret < 0) + goto err_free_bt; =20 - np =3D of_changeset_create_node(pci_dev->ocs, parent, "bluetooth"); - if (!np) { - dev_err(dev, "Failed to create bluetooth node\n"); - ret =3D -ENODEV; - goto err_destroy_changeset; - } + bt->serdev =3D pci_dev->serdev; + bt->pwrseq_target =3D "uart"; + bt->adev.id =3D ret; + bt->adev.name =3D (const char *)id->driver_data; + bt->adev.dev.parent =3D dev; + bt->adev.dev.release =3D pwrseq_pcie_m2_bt_release; =20 - ret =3D of_changeset_add_prop_string(pci_dev->ocs, np, "compatible", comp= atible); - if (ret) { - dev_err(dev, "Failed to add bluetooth compatible: %d\n", ret); - goto err_destroy_changeset; - } + ret =3D auxiliary_device_init(&bt->adev); + if (ret) + goto err_free_ida; =20 - ret =3D of_changeset_apply(pci_dev->ocs); + ret =3D auxiliary_device_add(&bt->adev); if (ret) { - dev_err(dev, "Failed to apply changeset: %d\n", ret); - goto err_destroy_changeset; + dev_err(dev, "Failed to add bluetooth auxiliary device: %d\n", + ret); + auxiliary_device_uninit(&bt->adev); + return ret; } =20 - ret =3D device_add_of_node(&pci_dev->serdev->dev, np); - if (ret) { - dev_err(dev, "Failed to add OF node: %d\n", ret); - goto err_revert_changeset; - } + pci_dev->bt =3D bt; =20 return 0; =20 -err_revert_changeset: - of_changeset_revert(pci_dev->ocs); -err_destroy_changeset: - of_changeset_destroy(pci_dev->ocs); - kfree(pci_dev->ocs); - pci_dev->ocs =3D NULL; +err_free_ida: + ida_free(&pwrseq_pcie_m2_bt_ida, bt->adev.id); +err_free_bt: + kfree(bt); =20 return ret; } @@ -329,17 +347,17 @@ static int pwrseq_pcie_m2_create_serdev_one(struct pw= rseq_pcie_m2_ctx *ctx, goto err_free_pci_dev; } =20 - ret =3D pwrseq_pcie_m2_create_bt_node(ctx, pci_dev, serdev_parent, pdev); - if (ret) - goto err_free_serdev; - ret =3D serdev_device_add(pci_dev->serdev); if (ret) { dev_err(dev, "Failed to add serdev for PCI device (%s): %d\n", pci_name(pdev), ret); - goto err_free_dt_node; + goto err_free_serdev; } =20 + ret =3D pwrseq_pcie_m2_create_bt_aux(ctx, pci_dev, pdev); + if (ret) + goto err_remove_serdev; + serdev_controller_put(serdev_ctrl); =20 pci_dev->pdev =3D pci_dev_get(pdev); @@ -350,15 +368,11 @@ static int pwrseq_pcie_m2_create_serdev_one(struct pw= rseq_pcie_m2_ctx *ctx, =20 return 0; =20 -err_free_dt_node: - device_remove_of_node(&pci_dev->serdev->dev); - of_changeset_revert(pci_dev->ocs); - of_changeset_destroy(pci_dev->ocs); - kfree(pci_dev->ocs); - pci_dev->ocs =3D NULL; +err_remove_serdev: + serdev_device_remove(pci_dev->serdev); + goto err_free_pci_dev; err_free_serdev: serdev_device_put(pci_dev->serdev); - pci_dev->serdev =3D NULL; err_free_pci_dev: kfree(pci_dev); err_put_ctrl: @@ -370,16 +384,13 @@ static int pwrseq_pcie_m2_create_serdev_one(struct pw= rseq_pcie_m2_ctx *ctx, static void __pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx, struct pwrseq_pci_dev *pci_dev) { - if (pci_dev->serdev) { - device_remove_of_node(&pci_dev->serdev->dev); - serdev_device_remove(pci_dev->serdev); + if (pci_dev->bt) { + auxiliary_device_delete(&pci_dev->bt->adev); + auxiliary_device_uninit(&pci_dev->bt->adev); } =20 - if (pci_dev->ocs) { - of_changeset_revert(pci_dev->ocs); - of_changeset_destroy(pci_dev->ocs); - kfree(pci_dev->ocs); - } + if (pci_dev->serdev) + serdev_device_remove(pci_dev->serdev); =20 pci_dev_put(pci_dev->pdev); list_del(&pci_dev->list); @@ -526,6 +537,7 @@ static int pwrseq_pcie_m2_probe(struct platform_device = *pdev) return -ENOMEM; =20 platform_set_drvdata(pdev, ctx); + ctx->dev =3D dev; ctx->of_node =3D dev_of_node(dev); ctx->pdata =3D device_get_match_data(dev); if (!ctx->pdata) @@ -573,7 +585,6 @@ static int pwrseq_pcie_m2_probe(struct platform_device = *pdev) =20 mutex_init(&ctx->list_lock); INIT_LIST_HEAD(&ctx->pci_devices); - ctx->dev =3D dev; =20 /* Create serdev for available PCI devices (if required) */ ret =3D pwrseq_pcie_m2_create_serdev(ctx); --=20 2.43.0 From nobody Fri Sep 25 07:23:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 777213B42D1; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; cv=none; b=s93WK+Y3IuVgF0aBWInpJyP7V7sr+c7qc0PVNI+N7x7W0IR/HLbpDPurMaQyy9eChFOLwaCZfAuiLOti7qGTL9rZmNaAbT5bBiSDIt06G1NBjLpMhKQaRn2ccqufoNDRglOWK+ZAnaVQBJDiXYRT4faLRh0eruXcfoBKE88JgCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; c=relaxed/simple; bh=+R5FG39SnHg6KZDOCqgXHNXuEhhxnh8leOY9t30V47w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cRGiGLpQn335YB6IjFX24uca9DkMJl4keYNa5A8FHi0WqYI0OyStabOgNU6e1XlCVGuNYw51Q5C9t/4a3XeuWhPTVRKlVAXkWDJViTcmWwPdc6czIU9Ez0sgWyXvgtKjSV50woI/fzYeFyVnGcHN2Ca4I+LySfcCwzwKI9MeDCs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CULVrXyl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CULVrXyl" Received: by smtp.kernel.org (Postfix) with ESMTPS id 42293C2BCFD; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789482262; bh=+R5FG39SnHg6KZDOCqgXHNXuEhhxnh8leOY9t30V47w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=CULVrXylUvPqH2F+BxTIYpIOvTptIftYRurNXLXtqVGSgzNOqFyOWcJ4HuPS8MsaM TCf9UP838Zo4vgix1uMKLIq2RpLAQ3SfVPcOZuFDnim6KJzkY0A7xZPNUXqzWYCQLw beIRro/KrpXE05q+Xhqfj6rEdD+9h9iHa/AnpapeX9wKYtg1AU+/MNCcibjk1W/kCT Orrz3P/ihh8UpYIm1MdpGuHbJxPQpAXujXcIr8L0GfkqFxi/EEx3QUMtVMRHDXC3vd ej1WRvQcFOprq4+0RZYky673ybju2CzOVoqg51ljwsENxUPI1KXAlPKfEWSYi5LTug jhIheGKt2s8Yg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B4ACC982C3; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Sep 2026 16:24:05 +0200 Subject: [PATCH 4/5] Bluetooth: hci_qca: Drop serdev based M.2 power sequencing code Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-pci-m2-bt-rework-v1-4-3c7d9cf9c010@oss.qualcomm.com> References: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> In-Reply-To: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> To: Marcel Holtmann , Luiz Augusto von Dentz , Bartosz Golaszewski , Manivannan Sadhasivam , Amitkumar Karwar , Neeraj Kale , Philipp Zabel Cc: linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-pci@vger.kernel.org, linux-pm@vger.kernel.org, Rahul Samana , Wei Deng , Loic Poulain , Andy Shevchenko , Manivannan Sadhasivam X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3169; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=/fJwYLZay9p/+8hufmw3DfTVYzGPwzb16kQvam8A42M=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBqqVUTtZ7RZSsKXdDqzaK7jO9pzNTf8LCLVIz5F nkkNJaC+JGJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaqlVEwAKCRBVnxHm/pHO 9fdpB/9rTOAZq0xBDkNYCJ0LlmndHPbMZKMOfVyx+tex1e181mCFYrUNoHkz0G2eNZXoaQEQdqK Ssz/T9RxMt/DGALf7xE1ovoDcIZoAeesXw7nmwwEJNjb1vIDVbZ2xhX9tLD6Nq8WSDC19AZuLuj uHcJbXwYS54NunvDxeTZtFxJmc3krM4m9ltNLSemmowAXeLMzZhqOXX+vNWKSwzc+WPfHQbGxS1 K23L7/UQwmJaTMb3vN3mz35bEpNF3Qa5BrPumgZzOfGTufyVZ8u/p/3jvxBLEA44T5tuE+x7UPN OIOQMOsFjbiNW/GpXpSrj1fkbZhhtMvEpv9AtUGChwSfQ1c7 X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam Bluetooth interface in M.2 modules is now enumerated using an auxiliary device instead of serdev. The power sequencing driver now allocates an auxiliary device for the Bluetooth interface whenever a compatible M.2 module shows up over PCIe. And the auxiliary device gets bind to this hci_qca driver using the existing auxiliary driver matching logic. Earlier the same modules were brought up by fabricating a bluetooth node under the UART controller, so that the serdev bus matched this driver, and qca_serdev_probe grabbed the "uart" sequencer when the M.2 connector was reachable over the OF graph. That node is no longer created, so the serdev driver never binds for an M.2 module. Hence, remove the serdev based M.2 power sequencing code. Signed-off-by: Manivannan Sadhasivam Tested-by: Sherry Sun --- drivers/bluetooth/hci_qca.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 15cc6cca9057..3a348f4153e7 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -2384,34 +2383,6 @@ static int qca_init_regulators(struct qca_serdev *qc= adev, return 0; } =20 -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 =3D 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 =3D pwrseq_get(&serdev->ctrl->dev, "uart"); - if (IS_ERR(pwrseq)) - return PTR_ERR(pwrseq); - - qcadev->pwrseq =3D pwrseq; - - return devm_add_action_or_reset(&serdev->dev, qca_serdev_put_pwrseq, pwrs= eq); -} - static int qca_serdev_probe(struct serdev_device *serdev) { struct qca_serdev *qcadev; @@ -2442,10 +2413,6 @@ static int qca_serdev_probe(struct serdev_device *se= rdev) else qcadev->btsoc_type =3D QCA_ROME; =20 - err =3D qca_serdev_get_m2_pwrseq(qcadev); - if (err) - return err; - switch (qcadev->btsoc_type) { case QCA_WCN3950: case QCA_WCN3988: @@ -2455,10 +2422,6 @@ static int qca_serdev_probe(struct serdev_device *se= rdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - /* M.2 connector modules are powered by the pwrseq acquired above. */ - if (qcadev->pwrseq) - break; - if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the --=20 2.43.0 From nobody Fri Sep 25 07:23:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D53F3B5314; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; cv=none; b=tg4+ofXhF6mzMYAkNx2tmwSukk0OlOF0zW9y17dFwu+/2e4BNDbca+pDQrf9tNgW0JQqvfcYWHS9bx3Y6zgsuBTqIcuKnxrsfc3eX9+fTkURosFqCGq1qckWHVArsXPxLyMJanQlpeiX6wafm6sG72MWzokXQsrgKbcY1Xep8jg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789482262; c=relaxed/simple; bh=ebDqYY4U9FVWlZxckUTVJvTup8qiCi+YooN49jm+VUQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VcvfryLtSKKI8EuQ44Rg3l6X3mkCHmlj5sHkHXgaFMjHjaw5hT6gvQVkj7fKhIvuz5fRoSF+DtuiGn4OVrhJRI2xnamljT8IvNGs6c8fkxRA4R9FQJYdw9j53Ms+FHBwQPI1lJ6ar7GNPmUX9DViZwMLTEQg5c5zUv0Dn3CxArc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LoSxpRDj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LoSxpRDj" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4C6E5C2BD05; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789482262; bh=ebDqYY4U9FVWlZxckUTVJvTup8qiCi+YooN49jm+VUQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LoSxpRDjYddJV0ZD7sucgELhV123tPEU5jN9AkoLM2hnytdslTz0U6V5UiPyzzWMF 4HJz7ZEfPdJaQblN97CgRlzwz/S11BsK4lISXrGSl0tPDvKQOHkE28tcJtaUHRhr/0 mSMHOkud4EW/BncTi19wmxFx9MUn1S99OEsSD+sLFpDSH4nFqeu73lJsk6aFhLxBCg 2zFR+GebFLUcMWjHfT9Nh05kFyNQjdwrk/1z+VIVLQhufXREqMkNEkeboHNldxCGoc j4mQIejUOF8P3vyeYJVJRqgW1bROvFbd1+40MEu0TvFtz6jW+3oVAf8BU9aeaI5NNd pnlQudZX3XEJA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A4A9C982C4; Tue, 15 Sep 2026 14:24:22 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Sep 2026 16:24:06 +0200 Subject: [PATCH 5/5] Bluetooth: btnxpuart: Drop serdev based M.2 power sequencing code Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260915-pci-m2-bt-rework-v1-5-3c7d9cf9c010@oss.qualcomm.com> References: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> In-Reply-To: <20260915-pci-m2-bt-rework-v1-0-3c7d9cf9c010@oss.qualcomm.com> To: Marcel Holtmann , Luiz Augusto von Dentz , Bartosz Golaszewski , Manivannan Sadhasivam , Amitkumar Karwar , Neeraj Kale , Philipp Zabel Cc: linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-pci@vger.kernel.org, linux-pm@vger.kernel.org, Rahul Samana , Wei Deng , Loic Poulain , Andy Shevchenko , Manivannan Sadhasivam X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3237; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=+YzVex5t/UFDNNH6FtEmazomhrj+PormXoK6KhBhZYo=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBqqVUTH7YYitnfHOUyQSnpkRPlZLBO68tqUNH23 AuTotDAoamJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaqlVEwAKCRBVnxHm/pHO 9QuzCACee6+MFgwP7AqcyjVGPJ49iNhWnNA/QQBP5XWHvZIRUwkSM9nGmJOKCNtA6/Rt5EbBtJS QjXcjGxZZGH+a/wVnKK3hj/HYljm3l32CScy14+i8qa6htukWCXBA/F215lEJ/IjrTYEp7X7+RJ TJGqOFj1oDtT44KMkBhXxcnxlucOpaXC/9rg9pvFIpaehY6LwshJdkFRHd1wHMXl1vzjtQ6hcj8 6NxYgrSMZFhX+cIkd5tusO4VcLBJsyZrxLuiY5Q+8oievV4bU5OzMSLOiZbt/gaOrxxT9TA6IQZ 5KoARp+qth/nE6Gd3c4jr4S9I6cYoIa5UIJKbm3A4dnTKq7v X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam Bluetooth interface in M.2 modules is now enumerated using an auxiliary device instead of serdev. The power sequencing driver now allocates an auxiliary device for the Bluetooth interface whenever a compatible M.2 module shows up over PCIe. And the auxiliary device gets bind to this btnxpuart driver using the existing auxiliary driver matching logic. Earlier the same modules were brought up by fabricating a bluetooth node under the UART controller, so that the serdev bus matched this driver, and nxp_serdev_probe grabbed the "uart" sequencer when the M.2 connector was reachable over the OF graph. That node is no longer created, so the serdev driver never binds for an M.2 module. Hence, remove the connector helper and the serdev power sequencing code. Signed-off-by: Manivannan Sadhasivam Tested-by: Sherry Sun --- drivers/bluetooth/btnxpuart.c | 48 +--------------------------------------= ---- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index 2672e481ef15..eaa82cc6444f 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -1820,28 +1819,6 @@ static void nxp_coredump_notify(struct hci_dev *hdev= , int state) kobject_uevent_env(&serdev->dev.kobj, KOBJ_CHANGE, envp); } =20 -/* - * Check if the remote M.2 connector device linked via OF graph is present - * and available. This is used to determine whether the pwrseq path should - * be taken. When the remote connector node is disabled (e.g., by a DT - * overlay switching from PCIe WiFi to SDIO WiFi), the pwrseq path is - * skipped, allowing the BT driver to use a direct bluetooth child node - * instead. - */ -static bool nxp_m2_connector_is_available(struct device *dev) -{ - struct device_node *ep __free(device_node) =3D - of_graph_get_next_endpoint(dev_of_node(dev), NULL); - - if (!ep) - return false; - - struct device_node *remote __free(device_node) =3D - of_graph_get_remote_port_parent(ep); - - return remote && of_device_is_available(remote); -} - static int nxp_register_dev(struct btnxpuart_dev *nxpdev) { struct serdev_device *serdev =3D nxpdev->serdev; @@ -1962,30 +1939,7 @@ static int nxp_serdev_probe(struct serdev_device *se= rdev) return err; } =20 - if (nxp_m2_connector_is_available(&serdev->ctrl->dev)) { - struct pwrseq_desc *pwrseq; - - pwrseq =3D pwrseq_get(&serdev->ctrl->dev, "uart"); - if (IS_ERR(pwrseq)) - return dev_err_probe(&serdev->dev, PTR_ERR(pwrseq), - "failed to get pwrseq\n"); - - nxpdev->pwrseq =3D pwrseq; - err =3D pwrseq_enable(pwrseq); - if (err) - goto err_pwrseq_put; - } - - err =3D nxp_register_dev(nxpdev); - if (err) - goto err_pwrseq_put; - - return 0; - -err_pwrseq_put: - if (nxpdev->pwrseq) - pwrseq_put(nxpdev->pwrseq); - return err; + return nxp_register_dev(nxpdev); } =20 static void __nxp_remove(struct btnxpuart_dev *nxpdev) --=20 2.43.0