#include <linux/of_device.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
+#include <linux/pci-pwrctrl.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
static int mtk_pcie_devices_power_up(struct mtk_gen3_pcie *pcie)
{
+ int err;
u32 val;
/*
val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
PCIE_PE_RSTB;
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
+ }
+
+ err = pci_pwrctrl_power_on_devices(pcie->dev);
+ if (err) {
+ dev_err(pcie->dev, "Failed to power on devices: %pe\n", ERR_PTR(err));
+ return err;
+ }
- /*
- * Described in PCIe CEM specification revision 6.0.
- *
- * The deassertion of PERST# should be delayed 100ms (TPVPERL)
- * for the power and clock to become stable.
- */
- msleep(PCIE_T_PVPERL_MS);
+ /*
+ * Described in PCIe CEM specification revision 6.0.
+ *
+ * The deassertion of PERST# should be delayed 100ms (TPVPERL)
+ * for the power and clock to become stable.
+ */
+ msleep(PCIE_T_PVPERL_MS);
+ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
/* De-assert reset signals */
val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
PCIE_PE_RSTB);
val |= PCIE_PE_RSTB;
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
}
+
+ pci_pwrctrl_power_off_devices(pcie->dev);
}
static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
if (err)
return dev_err_probe(dev, err, "Failed to setup IRQ domains\n");
+ err = pci_pwrctrl_create_devices(pcie->dev);
+ if (err) {
+ goto err_tear_down_irq;
+ dev_err_probe(dev, err, "failed to create pwrctrl devices\n");
+ }
+
err = mtk_pcie_setup(pcie);
if (err)
- goto err_tear_down_irq;
+ goto err_destroy_pwrctrl;
host->ops = &mtk_pcie_ops;
host->sysdata = pcie;
err_power_down_pcie:
mtk_pcie_devices_power_down(pcie);
mtk_pcie_power_down(pcie);
+err_destroy_pwrctrl:
+ if (err != -EPROBE_DEFER)
+ pci_pwrctrl_destroy_devices(pcie->dev);
err_tear_down_irq:
mtk_pcie_irq_teardown(pcie);
return err;
pci_remove_root_bus(host->bus);
pci_unlock_rescan_remove();
+ pci_pwrctrl_power_off_devices(pcie->dev);
mtk_pcie_power_down(pcie);
+ pci_pwrctrl_destroy_devices(pcie->dev);
mtk_pcie_irq_teardown(pcie);
}