Re: [PATCH v3 04/11] power: sequencing: pcie-m2: Report power controllability
From: Loic Poulain
Date: Thu Jul 16 2026 - 12:11:41 EST
On Thu, Jul 16, 2026 at 4:27 PM Manivannan Sadhasivam <mani@xxxxxxxxxx> wrote:
>
> On Fri, Jul 10, 2026 at 11:57:30AM +0200, Loic Poulain wrote:
> > The M.2 Key E connector gates its functions through the W_DISABLE1#
> > (PCIe/WiFi) and W_DISABLE2# (Bluetooth) signals. When a signal is not
> > routed to a host GPIO, the corresponding enable/disable callbacks are
> > no-ops, so the host cannot gate that function's power on its own.
> >
>
> I think it is misleading to say that if W_DISABLE{1/2}# signals are not
> available then we cannot control the function's power. Power to the function
> only comes from the core 3.3v regulator, and these signals only enable/disable
> the radio (WLAN/BT) as per the spec.
Yes, though in reality vendors often use it as a reset/power-enable
for the functions, not only for their RF part, effectively powering
off the Bluetooth or WiFi subsystem (and the spec says that when the
Bluetooth radio is disabled it may reset the Bluetooth feature). I
guess that is why it's part of pwrseq in the first place. But right,
here the control isn't fine-grained enough to gate the Bluetooth and
WiFi functions independently, but power/3v3 can still be powered-off
as a whole when controllable.
Also, in pwrseq the targets are named 'pcie' and 'uart', but per spec
I think they should really be 'wifi' and 'bluetooth', especially as
Bluetooth can also be connected over USB while still controlled via
the same W_DISABLE2# pin, though we don't handle that case yet. But
that's another story.
Regards,
Loic
>
> - Mani
>
> > Implement the per-unit .is_controllable() callback on the "uart-enable"
> > and "pcie-enable" units so that consumers can query this per instance
> > (based on the runtime presence of the W_DISABLE2#/W_DISABLE1# GPIOs) via
> > pwrseq_power_is_controllable().
> >
> > Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>
> > ---
> > drivers/power/sequencing/pwrseq-pcie-m2.c | 26 ++++++++++++++++++++++++++
> > 1 file changed, 26 insertions(+)
> >
> > diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
> > index e3ba9169144dabbf0c553c0a4302c3b511fcaaa1..4bcd5078609da1be966ab30c73cffae5e578934f 100644
> > --- a/drivers/power/sequencing/pwrseq-pcie-m2.c
> > +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
> > @@ -84,11 +84,24 @@ static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
> > return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
> > }
> >
> > +static bool pwrseq_pci_m2_e_uart_is_controllable(struct pwrseq_device *pwrseq)
> > +{
> > + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> > +
> > + /*
> > + * The UART enable is driven through the W_DISABLE2# line. When it is not
> > + * wired up on this connector the enable/disable callbacks are no-ops, so
> > + * the host cannot gate the Bluetooth function on its own.
> > + */
> > + return !!ctx->w_disable2_gpio;
> > +}
> > +
> > 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,
> > + .is_controllable = pwrseq_pci_m2_e_uart_is_controllable,
> > };
> >
> > static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq)
> > @@ -105,11 +118,24 @@ static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
> > return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
> > }
> >
> > +static bool pwrseq_pci_m2_e_pcie_is_controllable(struct pwrseq_device *pwrseq)
> > +{
> > + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
> > +
> > + /*
> > + * The PCIe/WiFi enable is driven through the W_DISABLE1# line. When it
> > + * is not wired up on this connector the enable/disable callbacks are
> > + * no-ops, so the host cannot gate the PCIe/WiFi function on its own.
> > + */
> > + return !!ctx->w_disable1_gpio;
> > +}
> > +
> > 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,
> > + .is_controllable = pwrseq_pci_m2_e_pcie_is_controllable,
> > };
> >
> > static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
> >
> > --
> > 2.34.1
> >
>
> --
> மணிவண்ணன் சதாசிவம்