From nobody Mon Feb 9 14:38:23 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 1CF21372B28; Thu, 22 Jan 2026 17:16:58 +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=1769102219; cv=none; b=jGUPg4KQ+uuEJ8T3pdY7hALHkTRoEf5cBabZLgW6aiAWt8G6LrqxVtWcAfIZwdR3vtb2nARNpLYyfY5ENI70E64lGAT/sF+kOj406n7C+WQ+5skxe3cJ2w1jr6bJwrh9GIewVxv+0AKh4k8nDi5DqAADXIh2o/OUlESntkSFHNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769102219; c=relaxed/simple; bh=czhrt6qU9W53d83wWXZNXSUrEG4WPODCrM75X7CHTjM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=L0fdesjo6o1W38FzD6EJWGDuY74qz55CmOFJuHdxCjacJdpP1VqA2yu2Rv6OxmLtdot0xZf8l0fH4IdFLb3gRS7GUNFPi3Zo0Ukc1weaGXBH+zM7ttVL1qBMZr3e8EzxPN4MnMsITPiKJ5HetEGjeqs+onQGR9FrXVlQgr9Hn6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h1WWek2/; 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="h1WWek2/" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9378FC2BCB2; Thu, 22 Jan 2026 17:16:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1769102217; bh=czhrt6qU9W53d83wWXZNXSUrEG4WPODCrM75X7CHTjM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=h1WWek2/5jcqZdn4fVlQo+m553ZImFYTaqn5kLRgxSQX6oo++iB4VyfP6Y8qpOkYP Y6fwm/MRHOrWfJfP1ZSqXGmkSH5ejzDH92uvu4KKKDNMww27LnmBuzU8jRzkENek+M Stskzhu3YcfqOc8Se6ClFNe43jpfu4XTJb7EYYuEb9A4oearHzXQBJ0lj/LLgBzXGu YjzbXx68tMCm2n0/NvZ6sAPGt5cN0SZ0LuaDZe4tzQ1H68bpc4bJWWfbeKBKSMTv4S vlUTk7Yo2s4NnODexudSr4YRL3TAF9Ti4jiZruQhQDEwaG2k/63SYi3dUHAji+5F99 LzsAt5TFhwVEw== 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 86BA9D3EE9E; Thu, 22 Jan 2026 17:16:57 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Thu, 22 Jan 2026 22:46:54 +0530 Subject: [PATCH v6 4/4] power: sequencing: Add the Power Sequencing driver for the PCIe M.2 connectors 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: <20260122-pci-m2-v6-4-575da9f97239@oss.qualcomm.com> References: <20260122-pci-m2-v6-0-575da9f97239@oss.qualcomm.com> In-Reply-To: <20260122-pci-m2-v6-0-575da9f97239@oss.qualcomm.com> To: Bjorn Helgaas , Manivannan Sadhasivam , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bartosz Golaszewski , Damien Le Moal , Niklas Cassel , Linus Walleij , Bartosz Golaszewski Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, Stephan Gerhold , Dmitry Baryshkov , linux-pm@vger.kernel.org, linux-ide@vger.kernel.org, Manivannan Sadhasivam X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7812; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=MrmblrG2JUxLhRhHQkVgoN7g+pVLmcvg9aZ9Ii+xtN8=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBpcluHN3RueTwQ/o3zdxZcr6aj+Ny3g+qnSPyCX RI/5CTvL0mJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaXJbhwAKCRBVnxHm/pHO 9WbiB/98lvib3si3lbW+GSz8HT/YeqkOOxmZfVBQZ2VIxZe5fqwxu7ryxWOngkDxAMsySUSb6Jd umwrPa3RVCWhilEs3rP1K6OFK5Opiwu9746mIHpYXYC3rMgqZ6J8mhJji9Ml4nLF64/AKwc9Sos g4agtEoXH1O0CisnLMg8QhxWOo5G7oq46Dz9RieyxkZ1cLaG2jJrSZHH+PRaVJ91YKXHPBylRKk jjOsZzrm66NzL6aNZ+WixH0KlDgcHROC7HRW5V7pDjg1C7S/mQBKMKnRLqaRajlwp3oeY86pVyC ROOl7IUCPjuafsjqJfZIcBPYmDKZ3xpu14AHmvZPiYKx1LOZ 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 This driver is used to control the PCIe M.2 connectors of different Mechanical Keys attached to the host machines and supporting different interfaces like PCIe/SATA, USB/UART etc... Currently, this driver supports only the Mechanical Key M connectors with PCIe interface. The driver also only supports driving the mandatory 3.3v and optional 1.8v power supplies. The optional signals of the Key M connectors are not currently supported. Signed-off-by: Manivannan Sadhasivam --- MAINTAINERS | 7 ++ drivers/power/sequencing/Kconfig | 8 ++ drivers/power/sequencing/Makefile | 1 + drivers/power/sequencing/pwrseq-pcie-m2.c | 168 ++++++++++++++++++++++++++= ++++ 4 files changed, 184 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5b11839cba9d..2eb7b6d26573 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20791,6 +20791,13 @@ F: Documentation/driver-api/pwrseq.rst F: drivers/power/sequencing/ F: include/linux/pwrseq/ =20 +PCIE M.2 POWER SEQUENCING +M: Manivannan Sadhasivam +L: linux-pci@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/connector/pcie-m2-m-connector.yaml +F: drivers/power/sequencing/pwrseq-pcie-m2.c + POWER STATE COORDINATION INTERFACE (PSCI) M: Mark Rutland M: Lorenzo Pieralisi diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kc= onfig index 280f92beb5d0..f5fff84566ba 100644 --- a/drivers/power/sequencing/Kconfig +++ b/drivers/power/sequencing/Kconfig @@ -35,4 +35,12 @@ config POWER_SEQUENCING_TH1520_GPU GPU. This driver handles the complex clock and reset sequence required to power on the Imagination BXM GPU on this platform. =20 +config POWER_SEQUENCING_PCIE_M2 + tristate "PCIe M.2 connector power sequencing driver" + depends on OF || COMPILE_TEST + 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 + connectors exposing multiple interfaces like PCIe, SATA, UART, etc... + endif diff --git a/drivers/power/sequencing/Makefile b/drivers/power/sequencing/M= akefile index 96c1cf0a98ac..0911d4618298 100644 --- a/drivers/power/sequencing/Makefile +++ b/drivers/power/sequencing/Makefile @@ -5,3 +5,4 @@ pwrseq-core-y :=3D core.o =20 obj-$(CONFIG_POWER_SEQUENCING_QCOM_WCN) +=3D pwrseq-qcom-wcn.o obj-$(CONFIG_POWER_SEQUENCING_TH1520_GPU) +=3D pwrseq-thead-gpu.o +obj-$(CONFIG_POWER_SEQUENCING_PCIE_M2) +=3D pwrseq-pcie-m2.o diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequ= encing/pwrseq-pcie-m2.c new file mode 100644 index 000000000000..96ea4adc9d22 --- /dev/null +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * Author: Manivannan Sadhasivam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pwrseq_pcie_m2_pdata { + const struct pwrseq_target_data **targets; +}; + +struct pwrseq_pcie_m2_ctx { + struct pwrseq_device *pwrseq; + struct device_node *of_node; + const struct pwrseq_pcie_m2_pdata *pdata; + struct regulator_bulk_data *regs; + size_t num_vregs; + struct notifier_block nb; +}; + +static int pwrseq_pcie_m2_m_vregs_enable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_pcie_m2_ctx *ctx =3D pwrseq_device_get_drvdata(pwrseq); + + return regulator_bulk_enable(ctx->num_vregs, ctx->regs); +} + +static int pwrseq_pcie_m2_m_vregs_disable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_pcie_m2_ctx *ctx =3D pwrseq_device_get_drvdata(pwrseq); + + return regulator_bulk_disable(ctx->num_vregs, ctx->regs); +} + +static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data =3D { + .name =3D "regulators-enable", + .enable =3D pwrseq_pcie_m2_m_vregs_enable, + .disable =3D pwrseq_pcie_m2_m_vregs_disable, +}; + +static const struct pwrseq_unit_data *pwrseq_pcie_m2_m_unit_deps[] =3D { + &pwrseq_pcie_m2_vregs_unit_data, + NULL +}; + +static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data =3D { + .name =3D "pcie-enable", + .deps =3D pwrseq_pcie_m2_m_unit_deps, +}; + +static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = =3D { + .name =3D "pcie", + .unit =3D &pwrseq_pcie_m2_m_pcie_unit_data, +}; + +static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] =3D { + &pwrseq_pcie_m2_m_pcie_target_data, + NULL +}; + +static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data =3D { + .targets =3D pwrseq_pcie_m2_m_targets, +}; + +static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq, + struct device *dev) +{ + struct pwrseq_pcie_m2_ctx *ctx =3D pwrseq_device_get_drvdata(pwrseq); + struct device_node *endpoint __free(device_node) =3D NULL; + + /* + * Traverse the 'remote-endpoint' nodes and check if the remote node's + * parent matches the OF node of 'dev'. + */ + for_each_endpoint_of_node(ctx->of_node, endpoint) { + struct device_node *remote __free(device_node) =3D + of_graph_get_remote_port_parent(endpoint); + if (remote && (remote =3D=3D dev_of_node(dev))) + return PWRSEQ_MATCH_OK; + } + + return PWRSEQ_NO_MATCH; +} + +static void pwrseq_pcie_m2_free_resources(void *data) +{ + struct pwrseq_pcie_m2_ctx *ctx =3D data; + + regulator_bulk_free(ctx->num_vregs, ctx->regs); +} + +static int pwrseq_pcie_m2_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct pwrseq_pcie_m2_ctx *ctx; + struct pwrseq_config config =3D {}; + int ret; + + ctx =3D devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->of_node =3D of_node_get(dev->of_node); + ctx->pdata =3D device_get_match_data(dev); + if (!ctx->pdata) + return dev_err_probe(dev, -ENODEV, + "Failed to obtain platform data\n"); + + /* + * Currently, of_regulator_bulk_get_all() is the only regulator API that + * allows to get all supplies in the devicetree node without manually + * specifying them. + */ + ret =3D of_regulator_bulk_get_all(dev, dev_of_node(dev), &ctx->regs); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to get all regulators\n"); + + ctx->num_vregs =3D ret; + + ret =3D devm_add_action_or_reset(dev, pwrseq_pcie_m2_free_resources, ctx); + if (ret) + return ret; + + config.parent =3D dev; + config.owner =3D THIS_MODULE; + config.drvdata =3D ctx; + config.match =3D pwrseq_pcie_m2_match; + config.targets =3D ctx->pdata->targets; + + ctx->pwrseq =3D devm_pwrseq_device_register(dev, &config); + if (IS_ERR(ctx->pwrseq)) + return dev_err_probe(dev, PTR_ERR(ctx->pwrseq), + "Failed to register the power sequencer\n"); + + return 0; +} + +static const struct of_device_id pwrseq_pcie_m2_of_match[] =3D { + { + .compatible =3D "pcie-m2-m-connector", + .data =3D &pwrseq_pcie_m2_m_of_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match); + +static struct platform_driver pwrseq_pcie_m2_driver =3D { + .driver =3D { + .name =3D "pwrseq-pcie-m2", + .of_match_table =3D pwrseq_pcie_m2_of_match, + }, + .probe =3D pwrseq_pcie_m2_probe, +}; +module_platform_driver(pwrseq_pcie_m2_driver); + +MODULE_AUTHOR("Manivannan Sadhasivam "); +MODULE_DESCRIPTION("Power Sequencing driver for PCIe M.2 connector"); +MODULE_LICENSE("GPL"); --=20 2.51.0