From: Sean Anderson <sean.anderson@linux.dev>
To: manivannan.sadhasivam@oss.qualcomm.com,
"Rob Herring" <robh@kernel.org>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Jiri Slaby" <jirislaby@kernel.org>,
"Nathan Chancellor" <nathan@kernel.org>,
"Nicolas Schier" <nicolas.schier@linux.dev>,
"Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Mark Pearson" <mpearson-lenovo@squebb.ca>,
"Derek J. Clark" <derekjohn.clark@gmail.com>,
"Manivannan Sadhasivam" <mani@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Marcel Holtmann" <marcel@holtmann.org>,
"Luiz Augusto von Dentz" <luiz.dentz@gmail.com>,
"Bartosz Golaszewski" <brgl@bgdev.pl>,
"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
"Bartosz Golaszewski" <brgl@kernel.org>
Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kbuild@vger.kernel.org,
platform-driver-x86@vger.kernel.org, linux-pci@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-bluetooth@vger.kernel.org, linux-pm@vger.kernel.org,
Stephan Gerhold <stephan.gerhold@linaro.org>,
Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>,
linux-acpi@vger.kernel.org
Subject: Re: [PATCH v4 8/9] power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors
Date: Tue, 13 Jan 2026 10:26:04 -0500 [thread overview]
Message-ID: <2432dafc-4101-4b23-90b2-85ea5459435c@linux.dev> (raw)
In-Reply-To: <20260112-pci-m2-e-v4-8-eff84d2c6d26@oss.qualcomm.com>
On 1/12/26 11:26, Manivannan Sadhasivam via B4 Relay wrote:
> From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
>
> Add support for handling the power sequence of the PCIe M.2 Key E
> connectors. These connectors are used to attach the Wireless Connectivity
> devices to the host machine including combinations of WiFi, BT, NFC using
> interfaces such as PCIe/SDIO for WiFi, USB/UART for BT and I2C for NFC.
>
> Currently, this driver supports only the PCIe interface for WiFi and UART
> interface for BT. The driver also only supports driving the 3.3v/1.8v power
> supplies and W_DISABLE{1/2}# GPIOs. The optional signals of the Key E
> connectors are not currently supported.
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
> drivers/power/sequencing/Kconfig | 1 +
> drivers/power/sequencing/pwrseq-pcie-m2.c | 110 ++++++++++++++++++++++++++++--
> 2 files changed, 104 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
> index f5fff84566ba..29bd204319cc 100644
> --- a/drivers/power/sequencing/Kconfig
> +++ b/drivers/power/sequencing/Kconfig
> @@ -38,6 +38,7 @@ config POWER_SEQUENCING_TH1520_GPU
> config POWER_SEQUENCING_PCIE_M2
> tristate "PCIe M.2 connector power sequencing driver"
> depends on OF || COMPILE_TEST
> + depends on PCI
> 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/sequencing/pwrseq-pcie-m2.c
> index e01e19123415..4b85a40d7692 100644
> --- a/drivers/power/sequencing/pwrseq-pcie-m2.c
> +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
> @@ -4,12 +4,16 @@
> * Author: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> */
>
> +#include <linux/err.h>
> #include <linux/device.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/mod_devicetable.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_graph.h>
> #include <linux/of_platform.h>
> +#include <linux/pci.h>
> #include <linux/platform_device.h>
> #include <linux/pwrseq/provider.h>
> #include <linux/regulator/consumer.h>
> @@ -25,17 +29,19 @@ struct pwrseq_pcie_m2_ctx {
> const struct pwrseq_pcie_m2_pdata *pdata;
> struct regulator_bulk_data *regs;
> size_t num_vregs;
> - struct notifier_block nb;
> + struct gpio_desc *w_disable1_gpio;
> + struct gpio_desc *w_disable2_gpio;
> + struct device *dev;
> };
>
> -static int pwrseq_pcie_m2_m_vregs_enable(struct pwrseq_device *pwrseq)
> +static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq)
> {
> struct pwrseq_pcie_m2_ctx *ctx = 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)
> +static int pwrseq_pcie_m2_vregs_disable(struct pwrseq_device *pwrseq)
> {
> struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
>
> @@ -44,18 +50,84 @@ static int pwrseq_pcie_m2_m_vregs_disable(struct pwrseq_device *pwrseq)
>
> static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data = {
> .name = "regulators-enable",
> - .enable = pwrseq_pcie_m2_m_vregs_enable,
> - .disable = pwrseq_pcie_m2_m_vregs_disable,
> + .enable = pwrseq_pcie_m2_vregs_enable,
> + .disable = pwrseq_pcie_m2_vregs_disable,
> };
>
> -static const struct pwrseq_unit_data *pwrseq_pcie_m2_m_unit_deps[] = {
> +static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = {
> &pwrseq_pcie_m2_vregs_unit_data,
> NULL
> };
>
> +static int pwrseq_pci_m2_e_uart_enable(struct pwrseq_device *pwrseq)
> +{
> + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> +
> + return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0);
> +}
> +
> +static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
> +{
> + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> +
> + return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
> +}
> +
> +static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
> + .name = "uart-enable",
> + .deps = pwrseq_pcie_m2_unit_deps,
> + .enable = pwrseq_pci_m2_e_uart_enable,
> + .disable = pwrseq_pci_m2_e_uart_disable,
> +};
> +
> +static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq)
> +{
> + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> +
> + return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0);
> +}
> +
> +static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
> +{
> + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> +
> + return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
> +}
> +
> +static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
> + .name = "pcie-enable",
> + .deps = pwrseq_pcie_m2_unit_deps,
> + .enable = pwrseq_pci_m2_e_pcie_enable,
> + .disable = pwrseq_pci_m2_e_pcie_disable,
> +};
> +
> static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
> .name = "pcie-enable",
> - .deps = pwrseq_pcie_m2_m_unit_deps,
> + .deps = pwrseq_pcie_m2_unit_deps,
> +};
> +
> +static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq)
> +{
> + /*
> + * FIXME: This delay is only required for some Qcom WLAN/BT cards like
> + * WCN7850 and not for all devices. But currently, there is no way to
> + * identify the device model before enumeration.
> + */
> + msleep(50);
Section 3.1.4 of the M.2 spec says that "Power Valid to PERST# input
inactive" (T_PVPGL) is "Implementation specific recommended 50 ms." So I
think we should delay for at least 50 ms for all M.2 cards.
Additionally, the PCIe CEM specifies that "Power stable to PERST#
inactive" (T_PVPERL) must be at least 100 ms. So I think we should just
delay for 100 ms regardless of the slot, perhaps making this
configurable in the devicetree if e.g. the system integrator knows the
soldered-down M.2 requires less initialization time. This is exactly
what I proposed in [1].
--Sean
[1] https://lore.kernel.org/linux-pci/20251219172222.2808195-2-sean.anderson@linux.dev/
> + return 0;
> +}
> +
> +static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
> + .name = "uart",
> + .unit = &pwrseq_pcie_m2_e_uart_unit_data,
> + .post_enable = pwrseq_pcie_m2_e_pwup_delay,
> +};
> +
> +static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
> + .name = "pcie",
> + .unit = &pwrseq_pcie_m2_e_pcie_unit_data,
> + .post_enable = pwrseq_pcie_m2_e_pwup_delay,
> };
>
> static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
> @@ -63,11 +135,21 @@ static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
> .unit = &pwrseq_pcie_m2_m_pcie_unit_data,
> };
>
> +static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = {
> + &pwrseq_pcie_m2_e_pcie_target_data,
> + &pwrseq_pcie_m2_e_uart_target_data,
> + NULL
> +};
> +
> static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] = {
> &pwrseq_pcie_m2_m_pcie_target_data,
> NULL
> };
>
> +static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = {
> + .targets = pwrseq_pcie_m2_e_targets,
> +};
> +
> static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = {
> .targets = pwrseq_pcie_m2_m_targets,
> };
> @@ -126,6 +208,16 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
> return dev_err_probe(dev, ret,
> "Failed to get all regulators\n");
>
> + ctx->w_disable1_gpio = devm_gpiod_get_optional(dev, "w-disable1", GPIOD_OUT_HIGH);
> + if (IS_ERR(ctx->w_disable1_gpio))
> + return dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio),
> + "Failed to get the W_DISABLE_1# GPIO\n");
> +
> + ctx->w_disable2_gpio = devm_gpiod_get_optional(dev, "w-disable2", GPIOD_OUT_HIGH);
> + if (IS_ERR(ctx->w_disable2_gpio))
> + return dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio),
> + "Failed to get the W_DISABLE_2# GPIO\n");
> +
> ctx->num_vregs = ret;
>
> ret = devm_add_action_or_reset(dev, pwrseq_pcie_free_resources, ctx);
> @@ -151,6 +243,10 @@ static const struct of_device_id pwrseq_pcie_m2_of_match[] = {
> .compatible = "pcie-m2-m-connector",
> .data = &pwrseq_pcie_m2_m_of_data,
> },
> + {
> + .compatible = "pcie-m2-e-connector",
> + .data = &pwrseq_pcie_m2_e_of_data,
> + },
> { }
> };
> MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match);
>
next prev parent reply other threads:[~2026-01-13 15:26 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-12 16:25 [PATCH v4 0/9] Add support for handling PCIe M.2 Key E connectors in devicetree Manivannan Sadhasivam
2026-01-12 16:25 ` Manivannan Sadhasivam via B4 Relay
2026-01-12 16:26 ` [PATCH v4 1/9] serdev: Convert to_serdev_*() helpers to macros and use container_of_const() Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-12 16:26 ` [PATCH v4 2/9] serdev: Add an API to find the serdev controller associated with the devicetree node Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 13:54 ` Bartosz Golaszewski
2026-01-14 15:57 ` Manivannan Sadhasivam
2026-01-14 14:01 ` Hans de Goede
2026-01-14 16:00 ` Manivannan Sadhasivam
2026-01-12 16:26 ` [PATCH v4 3/9] serdev: Do not return -ENODEV from of_serdev_register_devices() if external connector is used Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-12 19:23 ` Andy Shevchenko
2026-01-14 16:02 ` Manivannan Sadhasivam
2026-01-12 16:26 ` [PATCH v4 4/9] dt-bindings: serial: Document the graph port Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 13:55 ` Bartosz Golaszewski
2026-01-13 16:43 ` Rob Herring (Arm)
2026-01-12 16:26 ` [PATCH v4 5/9] dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 17:14 ` Rob Herring
2026-01-14 16:14 ` Manivannan Sadhasivam
2026-01-14 17:45 ` Rob Herring
2026-01-15 10:42 ` Manivannan Sadhasivam
2026-01-16 14:19 ` Rob Herring
2026-01-16 14:42 ` Manivannan Sadhasivam
2026-01-16 17:30 ` Rob Herring
2026-01-13 17:16 ` Rob Herring
2026-01-15 10:44 ` Manivannan Sadhasivam
2026-01-12 16:26 ` [PATCH v4 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 17:25 ` Rob Herring
2026-01-15 10:43 ` Manivannan Sadhasivam
2026-01-12 16:26 ` [PATCH v4 7/9] Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 13:56 ` Bartosz Golaszewski
2026-01-12 16:26 ` [PATCH v4 8/9] power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-13 14:00 ` Bartosz Golaszewski
2026-01-13 15:26 ` Sean Anderson [this message]
2026-01-13 16:34 ` Manivannan Sadhasivam
2026-01-12 16:26 ` [PATCH v4 9/9] power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth Manivannan Sadhasivam
2026-01-12 16:26 ` Manivannan Sadhasivam via B4 Relay
2026-01-12 16:43 ` [PATCH v3 03/14] software node: Implement device_get_match_data fwnode callback Manivannan Sadhasivam
2026-01-12 19:22 ` [PATCH v4 9/9] power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth Andy Shevchenko
2026-01-13 14:11 ` Bartosz Golaszewski
2026-01-12 19:29 ` [PATCH v4 0/9] Add support for handling PCIe M.2 Key E connectors in devicetree Andy Shevchenko
2026-01-15 10:30 ` Hans de Goede
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=2432dafc-4101-4b23-90b2-85ea5459435c@linux.dev \
--to=sean.anderson@linux.dev \
--cc=andriy.shevchenko@linux.intel.com \
--cc=brgl@bgdev.pl \
--cc=brgl@kernel.org \
--cc=conor+dt@kernel.org \
--cc=derekjohn.clark@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.baryshkov@oss.qualcomm.com \
--cc=gregkh@linuxfoundation.org \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jirislaby@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=mani@kernel.org \
--cc=manivannan.sadhasivam@oss.qualcomm.com \
--cc=marcel@holtmann.org \
--cc=mpearson-lenovo@squebb.ca \
--cc=nathan@kernel.org \
--cc=nicolas.schier@linux.dev \
--cc=platform-driver-x86@vger.kernel.org \
--cc=robh@kernel.org \
--cc=stephan.gerhold@linaro.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.