lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20260110-pci-m2-e-v3-14-4faee7d0d5ae@oss.qualcomm.com>
Date: Sat, 10 Jan 2026 12:26:32 +0530
From: Manivannan Sadhasivam via B4 Relay <devnull+manivannan.sadhasivam.oss.qualcomm.com@...nel.org>
To: Rob Herring <robh@...nel.org>, 
 Greg Kroah-Hartman <gregkh@...uxfoundation.org>, 
 Jiri Slaby <jirislaby@...nel.org>, Nathan Chancellor <nathan@...nel.org>, 
 Nicolas Schier <nicolas.schier@...ux.dev>, Hans de Goede <hansg@...nel.org>, 
 Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>, 
 Mark Pearson <mpearson-lenovo@...ebb.ca>, 
 "Derek J. Clark" <derekjohn.clark@...il.com>, 
 Manivannan Sadhasivam <mani@...nel.org>, 
 Krzysztof Kozlowski <krzk+dt@...nel.org>, 
 Conor Dooley <conor+dt@...nel.org>, Marcel Holtmann <marcel@...tmann.org>, 
 Luiz Augusto von Dentz <luiz.dentz@...il.com>, 
 Bartosz Golaszewski <brgl@...ev.pl>, 
 Andy Shevchenko <andriy.shevchenko@...ux.intel.com>, 
 Daniel Scally <djrscally@...il.com>, 
 Heikki Krogerus <heikki.krogerus@...ux.intel.com>, 
 Sakari Ailus <sakari.ailus@...ux.intel.com>, 
 "Rafael J. Wysocki" <rafael@...nel.org>, Danilo Krummrich <dakr@...nel.org>, 
 Bartosz Golaszewski <brgl@...nel.org>
Cc: linux-serial@...r.kernel.org, linux-kernel@...r.kernel.org, 
 linux-kbuild@...r.kernel.org, platform-driver-x86@...r.kernel.org, 
 linux-pci@...r.kernel.org, devicetree@...r.kernel.org, 
 linux-arm-msm@...r.kernel.org, linux-bluetooth@...r.kernel.org, 
 linux-pm@...r.kernel.org, Stephan Gerhold <stephan.gerhold@...aro.org>, 
 Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>, 
 linux-acpi@...r.kernel.org, 
 Manivannan Sadhasivam <manivannan.sadhasivam@....qualcomm.com>
Subject: [PATCH v3 14/14] power: sequencing: pcie-m2: Create serdev device
 for WCN7850 bluetooth

From: Manivannan Sadhasivam <manivannan.sadhasivam@....qualcomm.com>

For supporting bluetooth over the non-discoverable UART interface of
WCN7850, create the serdev device after enumerating the PCIe interface.
This is mandatory since the device ID is only known after the PCIe
enumeration and the ID is used for creating the serdev device.

Since there is no OF or ACPI table for the created serdev, a software node
is created with the 'compatible' property. This property will be used to
match the existing OF device id in the bluetooth driver.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@....qualcomm.com>
---
 drivers/power/sequencing/pwrseq-pcie-m2.c | 125 +++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index ad94090bbdb2..7c7bde563341 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/pwrseq/provider.h>
 #include <linux/regulator/consumer.h>
+#include <linux/serdev.h>
 #include <linux/slab.h>
 
 struct pwrseq_pcie_m2_pdata {
@@ -26,11 +27,14 @@ struct pwrseq_pcie_m2_pdata {
 struct pwrseq_pcie_m2_ctx {
 	struct pwrseq_device *pwrseq;
 	struct device_node *of_node;
+	struct fwnode_handle *fwnode;
+	struct serdev_device *serdev;
 	const struct pwrseq_pcie_m2_pdata *pdata;
 	struct regulator_bulk_data *regs;
 	size_t num_vregs;
 	struct gpio_desc *w_disable1_gpio;
 	struct gpio_desc *w_disable2_gpio;
+	struct notifier_block nb;
 	struct device *dev;
 
 };
@@ -179,9 +183,124 @@ static void pwrseq_pcie_free_resources(void *data)
 {
 	struct pwrseq_pcie_m2_ctx *ctx = data;
 
+	fwnode_handle_put(ctx->fwnode);
+	serdev_device_put(ctx->serdev);
+	bus_unregister_notifier(&pci_bus_type, &ctx->nb);
 	regulator_bulk_free(ctx->num_vregs, ctx->regs);
 }
 
+static const struct property_entry wcn7850_bt_props[] = {
+	PROPERTY_ENTRY_STRING("compatible", "qcom,wcn7850-bt"),
+};
+
+static int pwrseq_m2_pcie_notify(struct notifier_block *nb, unsigned long action,
+			      void *data)
+{
+	struct pwrseq_pcie_m2_ctx *ctx = container_of(nb, struct pwrseq_pcie_m2_ctx, nb);
+	struct pci_dev *pdev = to_pci_dev(data);
+	struct serdev_controller *serdev_ctrl;
+	struct device *dev = ctx->dev;
+	struct device_node *remote;
+	int ret;
+
+	/*
+	 * Check whether the PCI device is associated with this M.2 connector or
+	 * not, by comparing the OF node of the PCI device parent and the Port 0
+	 * (PCIe) remote node parent OF node.
+	 */
+	remote = of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0);
+	if (!remote || (remote != pdev->dev.parent->of_node)) {
+		of_node_put(remote);
+		return NOTIFY_DONE;
+	}
+	of_node_put(remote);
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		/* Create serdev device for WCN7850 */
+		if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) {
+			remote = of_graph_get_remote_node(dev_of_node(ctx->dev), 1, 1);
+			if (!remote) {
+				of_node_put(remote);
+				return NOTIFY_DONE;
+			}
+
+			serdev_ctrl = of_find_serdev_controller_by_node(remote);
+			of_node_put(remote);
+			if (!serdev_ctrl)
+				return NOTIFY_DONE;
+
+			ctx->serdev = serdev_device_alloc(serdev_ctrl);
+			if (!ctx->serdev)
+				return NOTIFY_BAD;
+
+			ctx->fwnode = fwnode_create_software_node(wcn7850_bt_props, NULL);
+			if (IS_ERR(ctx->fwnode))
+				return notifier_from_errno(PTR_ERR(ctx->fwnode));
+
+			device_set_node(&ctx->serdev->dev, ctx->fwnode);
+
+			ret = serdev_device_add(ctx->serdev);
+			if (ret) {
+				dev_err(dev, "Failed to add serdev for WCN7850: %d\n", ret);
+				fwnode_handle_put(ctx->fwnode);
+				serdev_device_put(ctx->serdev);
+				return notifier_from_errno(ret);
+			}
+		}
+		break;
+	case BUS_NOTIFY_REMOVED_DEVICE:
+		/* Destroy serdev device for WCN7850 */
+		if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) {
+			fwnode_handle_put(ctx->fwnode);
+			serdev_device_put(ctx->serdev);
+		}
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static bool pwrseq_pcie_m2_check_remote_node(struct device *dev, u8 port, u8 endpoint,
+					     const char *node)
+{
+	struct device_node *remote __free(device_node) =
+			of_graph_get_remote_node(dev_of_node(dev), port, endpoint);
+
+	if (remote && of_node_name_eq(remote, node))
+		return true;
+
+	return false;
+}
+
+/*
+ * If the connector exposes a non-discoverable bus like UART, the respective
+ * protocol device needs to be created manually with the help of the notifier
+ * of the discoverable bus like PCIe.
+ */
+static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx, struct device *dev)
+{
+	int ret;
+
+	/*
+	 * Register a PCI notifier for Key E connector that has PCIe as Port
+	 * 0/Endpoint 0 interface and Serial as Port 1/Endpoint 1 interface.
+	 */
+	if (pwrseq_pcie_m2_check_remote_node(dev, 1, 1, "serial")) {
+		if (pwrseq_pcie_m2_check_remote_node(dev, 0, 0, "pcie")) {
+			ctx->dev = dev;
+			ctx->nb.notifier_call = pwrseq_m2_pcie_notify;
+			ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
+			if (ret) {
+				dev_err_probe(dev, ret, "Failed to register notifier for serdev\n");
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -236,7 +355,11 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
 				     "Failed to register the power sequencer\n");
 
-	return 0;
+	/*
+	 * Register a notifier for creating protocol devices for
+	 * non-discoverable busses like UART.
+	 */
+	return pwrseq_pcie_m2_register_notifier(ctx, dev);
 }
 
 static const struct of_device_id pwrseq_pcie_m2_of_match[] = {

-- 
2.48.1



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ