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]>
