@@ -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;
}
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 <DaveWK225@protonmail.com> --- drivers/pci/pcie_dw_spacemit.c | 72 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 37 deletions(-)