[PATCH 1/2] PCI: dw-rockchip: Power on devices below the RC using pwrctrl
Shawn Lin
shawn.lin at rock-chips.com
Tue Oct 27 00:55:19 PDT 2026
Devices below the Rockchip PCIe host controller may need resources
(regulators, clocks) enabled before they can be detected on the bus. So
far the driver only enabled a single vpcie3v3 supply described by the
controller node itself, which cannot express per-device or per-slot
supplies.
Use the PCI pwrctrl framework: before initializing the PHY, create the
pwrctrl devices for the DT nodes below the controller and power them on.
The supplies of the slot must be up before PHY init, so this has to run
ahead of rockchip_pcie_phy_init().
The controller node supply is kept for backward compatibility: boards
that still describe vpcie3v3 on the controller keep working, and boards
that move the supply into a child node get it enabled by pwrctrl.
Only the RC mode is affected, the endpoint does not own the supplies of
the devices below it.
Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 30 ++++++++++++++++---
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index bd86e32cc2b1..952b4c6cc4bf 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/phy/phy.h>
+#include <linux/pci-pwrctrl.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -841,16 +842,32 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;
+ /*
+ * Power on the devices described below this controller before the PHY
+ * is initialized: the slot supplies must be up before PHY init.
+ */
+ if (data->mode == DW_PCIE_RC_TYPE) {
+ ret = pci_pwrctrl_create_devices(dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to create pwrctrl devices\n");
+
+ ret = pci_pwrctrl_power_on_devices(dev);
+ if (ret) {
+ pci_pwrctrl_destroy_devices(dev);
+ return dev_err_probe(dev, ret,
+ "failed to power on pwrctrl devices\n");
+ }
+ }
+
/* DON'T MOVE ME: must be enable before PHY init */
ret = devm_regulator_get_enable_optional(dev, "vpcie3v3");
if (ret < 0 && ret != -ENODEV)
- return dev_err_probe(dev, ret,
- "failed to enable vpcie3v3 regulator\n");
+ goto err_pwrctrl_off;
ret = rockchip_pcie_phy_init(rockchip);
if (ret)
- return dev_err_probe(dev, ret,
- "failed to initialize the phy\n");
+ goto err_pwrctrl_off;
ret = reset_control_deassert(rockchip->rst);
if (ret)
@@ -883,6 +900,11 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks);
deinit_phy:
rockchip_pcie_phy_deinit(rockchip);
+err_pwrctrl_off:
+ if (data->mode == DW_PCIE_RC_TYPE) {
+ pci_pwrctrl_power_off_devices(dev);
+ pci_pwrctrl_destroy_devices(dev);
+ }
return ret;
}
--
2.25.1
More information about the Linux-rockchip
mailing list