On Sat, Oct 3, 2026 at 5:30 AM Dave Klotz <[email protected]> wrote:
>
> The driver takes the slot power switch from a "k1x,pwr_on" GPIO and a
> "power-on-status" polarity flag. Those are vendor properties: neither
> the spacemit,k1-pcie binding nor any upstream device tree has them. The
> binding describes the 3.3 V slot supply as a regulator, vpcie3v3-supply,
> on the root port node, and that is ignored. On boards whose M.2 slot
> sits behind a GPIO-switched regulator, such as the OrangePi RV2
> (GPIO 116), the slot is never powered and the link cannot train.
>
> Look up vpcie3v3-supply on the root port, falling back to the host
> bridge node where some board device trees also put it and where Linux's
> pcie-spacemit-k1 driver reads it, and enable it in place of the GPIO.
> PERST# is still held for 100 ms after the supply is turned on. Drop the
> vendor GPIO properties.
>
> Unlike Linux, only warn when the supply is described but cannot be
> found: the Banana Pi F3 and MUSE Pi Pro describe always-on fixed
> supplies, and spacemit_k1_defconfig does not build the fixed regulator
> driver, so failing the probe would break ports that work today.
>
> Signed-off-by: Dave Klotz <[email protected]>
> ---
>  drivers/pci/pcie_dw_spacemit.c | 72 +++++++++++++++++-----------------
>  1 file changed, 35 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/pci/pcie_dw_spacemit.c b/drivers/pci/pcie_dw_spacemit.c
> index 09c56d8a4c..7ca5a5ad1a 100644
> --- a/drivers/pci/pcie_dw_spacemit.c
> +++ b/drivers/pci/pcie_dw_spacemit.c
> @@ -8,7 +8,6 @@
>   */
>  #include <asm/global_data.h>
>  #include <asm/io.h>
> -#include <asm-generic/gpio.h>
>  #include <clk.h>
>  #include <dm.h>
>  #include <dm/device_compat.h>
> @@ -21,6 +20,7 @@
>  #include <log.h>
>  #include <pci.h>
>  #include <power-domain.h>
> +#include <power/regulator.h>
>  #include <reset.h>
>
>  #include "pcie_dw_common.h"
> @@ -39,8 +39,7 @@ struct pcie_dw_spacemit {
>         /* reset, clock resources */
>         struct clk_bulk         clks;
>         struct reset_ctl_bulk   rsts;
> -       struct gpio_desc                pwr_on_gpio;
> -       int                     power_on_status;
> +       struct udevice          *vpcie3v3;      /* slot supply, if described 
> */
>  };
>
>  static inline u32 spacemit_pcie_readl(struct pcie_dw_spacemit *pcie, u32 
> offset)
> @@ -185,30 +184,26 @@ static int pcie_dw_init_id(struct pcie_dw_spacemit *pci)
>         return 0;
>  }
>
> -static int k1x_power_on(struct pcie_dw_spacemit *pci, int on)
> +/*
> + * The binding describes the 3.3 V slot supply on the root port node. Some
> + * board device trees also, or only, put it on the host bridge node, which
> + * is where Linux's driver looks for it.
> + */
> +static int spacemit_pcie_get_vpcie3v3(struct udevice *dev, ofnode port,
> +                                     struct udevice **supplyp)
>  {
> -       struct pcie_dw *dwp = &pci->dw;
> -       int gpio_val = 0;
> -
> -       if (on) {
> -               if (pci->power_on_status)
> -                       gpio_val = 1;
> -               else
> -                       gpio_val = 0;
> -       } else {
> -               if (pci->power_on_status)
> -                       gpio_val = 0;
> -               else
> -                       gpio_val = 1;
> -       }
> -
> -       if (dm_gpio_is_valid(&pci->pwr_on_gpio)) {
> -               dev_info(dwp->dev, "PCIe interface power %s, set gpio %d to 
> %d\n",
> -                        on ? "on" : "off", pci->pwr_on_gpio.offset, 
> gpio_val);
> -               dm_gpio_set_value(&pci->pwr_on_gpio, gpio_val);
> +       ofnode supply;
> +
> +       supply = ofnode_parse_phandle(port, "vpcie3v3-supply", 0);
> +       if (!ofnode_valid(supply))
> +               supply = ofnode_parse_phandle(dev_ofnode(dev),
> +                                             "vpcie3v3-supply", 0);
> +       if (!ofnode_valid(supply)) {
> +               *supplyp = NULL;
> +               return 0;
>         }
>
> -       return 0;
> +       return uclass_get_device_by_ofnode(UCLASS_REGULATOR, supply, supplyp);
>  }
>
>  static int pcie_dw_spacemit_probe(struct udevice *dev)
> @@ -241,6 +236,13 @@ static int pcie_dw_spacemit_probe(struct udevice *dev)
>                 return -ENODEV;
>         }
>
> +       ret = spacemit_pcie_get_vpcie3v3(dev, port, &pci->vpcie3v3);
> +       if (ret) {
> +               /* e.g. an always-on fixed supply with no driver built in */
> +               dev_warn(dev, "vpcie3v3 supply not available: %d\n", ret);
> +               pci->vpcie3v3 = NULL;
> +       }
> +
>         ret = generic_phy_get_by_index_nodev(port, 0, &phy0);
>         if (!ret) {
>                 reg = spacemit_pcie_readl(pci, PCIECTRL_K1X_CONF_DEVICE_CMD);
> @@ -271,8 +273,15 @@ static int pcie_dw_spacemit_probe(struct udevice *dev)
>
>         pcie_set_mode(pci, DW_PCIE_RC_TYPE);
>
> -       /* power on the interface */
> -       k1x_power_on(pci, 1);
> +       /* Power the slot; PERST# stays asserted for 100 ms after this */
> +       if (pci->vpcie3v3) {
> +               ret = regulator_set_enable_if_allowed(pci->vpcie3v3, true);
> +               if (ret) {
> +                       dev_err(dev, "failed to enable vpcie3v3 supply: %d\n",
> +                               ret);
> +                       return ret;
> +               }
> +       }
>
>         spacemit_pcie_host_init(pci);
>         pcie_dw_setup_host(&pci->dw);
> @@ -356,17 +365,6 @@ static int pcie_dw_spacemit_of_to_plat(struct udevice 
> *dev)
>                 return ret;
>         }
>
> -       gpio_request_by_name(dev, "k1x,pwr_on", 0, &pcie->pwr_on_gpio,
> -                            GPIOD_IS_OUT);
> -       if (!dm_gpio_is_valid(&pcie->pwr_on_gpio))
> -               dev_info(dev, "has no power on gpio.\n");
> -
> -       ret = dev_read_u32(dev, "power-on-status", &pcie->power_on_status);
> -       if (ret) {
> -               dev_info(dev, "has no power-on-status flag, use default.\n");
> -               pcie->power_on_status = 1;
> -       }
> -
>         return 0;
>  }
>
> --
> 2.55.0
>
>

Reviewed-by: Eric Chung <[email protected]>

Reply via email to