Skip to content

Commit 3f7ccee

Browse files
cdleonardLorenzo Pieralisi
authored andcommitted
PCI: imx: Add multi-pd support
On some chips the PCIe and PCIE_PHY blocks are in separate power domains which can be power-gated independently. The PCI driver needs to handle this by keeping both domain active. This is intended for imx6sx where PCIe is in DISPLAY and PCIE_PHY in its own domain. Defining the DISPLAY domain requires a way for PCIe to keep it active or it will break when displays are off. The power-domains on imx6sx are meant to look like this: power-domains = <&pd_disp>, <&pd_pci>; power-domain-names = "pcie", "pcie_phy"; Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent e24b6b5 commit 3f7ccee

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

drivers/pci/controller/dwc/pci-imx6.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <linux/types.h>
2828
#include <linux/interrupt.h>
2929
#include <linux/reset.h>
30+
#include <linux/pm_domain.h>
31+
#include <linux/pm_runtime.h>
3032

3133
#include "pcie-designware.h"
3234

@@ -59,6 +61,11 @@ struct imx6_pcie {
5961
u32 tx_swing_low;
6062
int link_gen;
6163
struct regulator *vpcie;
64+
65+
/* power domain for pcie */
66+
struct device *pd_pcie;
67+
/* power domain for pcie phy */
68+
struct device *pd_pcie_phy;
6269
};
6370

6471
/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
@@ -292,6 +299,43 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
292299
return 1;
293300
}
294301

302+
static int imx6_pcie_attach_pd(struct device *dev)
303+
{
304+
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
305+
struct device_link *link;
306+
307+
/* Do nothing when in a single power domain */
308+
if (dev->pm_domain)
309+
return 0;
310+
311+
imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
312+
if (IS_ERR(imx6_pcie->pd_pcie))
313+
return PTR_ERR(imx6_pcie->pd_pcie);
314+
link = device_link_add(dev, imx6_pcie->pd_pcie,
315+
DL_FLAG_STATELESS |
316+
DL_FLAG_PM_RUNTIME |
317+
DL_FLAG_RPM_ACTIVE);
318+
if (!link) {
319+
dev_err(dev, "Failed to add device_link to pcie pd.\n");
320+
return -EINVAL;
321+
}
322+
323+
imx6_pcie->pd_pcie_phy = dev_pm_domain_attach_by_name(dev, "pcie_phy");
324+
if (IS_ERR(imx6_pcie->pd_pcie_phy))
325+
return PTR_ERR(imx6_pcie->pd_pcie_phy);
326+
327+
device_link_add(dev, imx6_pcie->pd_pcie_phy,
328+
DL_FLAG_STATELESS |
329+
DL_FLAG_PM_RUNTIME |
330+
DL_FLAG_RPM_ACTIVE);
331+
if (IS_ERR(link)) {
332+
dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link));
333+
return PTR_ERR(link);
334+
}
335+
336+
return 0;
337+
}
338+
295339
static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
296340
{
297341
struct device *dev = imx6_pcie->pci->dev;
@@ -985,6 +1029,10 @@ static int imx6_pcie_probe(struct platform_device *pdev)
9851029

9861030
platform_set_drvdata(pdev, imx6_pcie);
9871031

1032+
ret = imx6_pcie_attach_pd(dev);
1033+
if (ret)
1034+
return ret;
1035+
9881036
ret = imx6_add_pcie_port(imx6_pcie, pdev);
9891037
if (ret < 0)
9901038
return ret;

0 commit comments

Comments
 (0)