diff options
Diffstat (limited to 'drivers/pci/controller/dwc')
| -rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 616c42932faa..6cf9106cce69 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -180,8 +180,12 @@ struct imx_pcie { struct imx_lut_data luts[IMX95_MAX_LUT]; /* power domain for pcie */ struct device *pd_pcie; + /* device link for pcie power domain */ + struct device_link *pd_link; /* power domain for pcie phy */ struct device *pd_pcie_phy; + /* device link for pcie phy power domain */ + struct device_link *pd_phy_link; struct phy *phy; const struct imx_pcie_drvdata *drvdata; @@ -639,10 +643,34 @@ static int imx6q_pcie_abort_handler(unsigned long addr, } #endif +static void imx_pcie_detach_pd_action(void *data) +{ + struct imx_pcie *imx_pcie = data; + + if (!IS_ERR_OR_NULL(imx_pcie->pd_phy_link)) { + device_link_del(imx_pcie->pd_phy_link); + imx_pcie->pd_phy_link = NULL; + } + + if (!IS_ERR_OR_NULL(imx_pcie->pd_link)) { + device_link_del(imx_pcie->pd_link); + imx_pcie->pd_link = NULL; + } + + if (!IS_ERR_OR_NULL(imx_pcie->pd_pcie_phy)) { + dev_pm_domain_detach(imx_pcie->pd_pcie_phy, true); + imx_pcie->pd_pcie_phy = NULL; + } + + if (!IS_ERR_OR_NULL(imx_pcie->pd_pcie)) { + dev_pm_domain_detach(imx_pcie->pd_pcie, true); + imx_pcie->pd_pcie = NULL; + } +} + static int imx_pcie_attach_pd(struct device *dev) { struct imx_pcie *imx_pcie = dev_get_drvdata(dev); - struct device_link *link; /* Do nothing when in a single power domain */ if (dev->pm_domain) @@ -654,11 +682,11 @@ static int imx_pcie_attach_pd(struct device *dev) /* Do nothing when power domain missing */ if (!imx_pcie->pd_pcie) return 0; - link = device_link_add(dev, imx_pcie->pd_pcie, - DL_FLAG_STATELESS | - DL_FLAG_PM_RUNTIME | - DL_FLAG_RPM_ACTIVE); - if (!link) { + imx_pcie->pd_link = device_link_add(dev, imx_pcie->pd_pcie, + DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); + if (!imx_pcie->pd_link) { dev_err(dev, "Failed to add device_link to pcie pd\n"); return -EINVAL; } @@ -667,11 +695,11 @@ static int imx_pcie_attach_pd(struct device *dev) if (IS_ERR(imx_pcie->pd_pcie_phy)) return PTR_ERR(imx_pcie->pd_pcie_phy); - link = device_link_add(dev, imx_pcie->pd_pcie_phy, - DL_FLAG_STATELESS | - DL_FLAG_PM_RUNTIME | - DL_FLAG_RPM_ACTIVE); - if (!link) { + imx_pcie->pd_phy_link = device_link_add(dev, imx_pcie->pd_pcie_phy, + DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); + if (!imx_pcie->pd_phy_link) { dev_err(dev, "Failed to add device_link to pcie_phy pd\n"); return -EINVAL; } @@ -1951,6 +1979,10 @@ static int imx_pcie_probe(struct platform_device *pdev) platform_set_drvdata(pdev, imx_pcie); + ret = devm_add_action_or_reset(dev, imx_pcie_detach_pd_action, imx_pcie); + if (ret) + return ret; + ret = imx_pcie_attach_pd(dev); if (ret) return ret; |
