aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc
diff options
context:
space:
mode:
authorLeonard Crestez <leonard.crestez@nxp.com>2018-10-08 14:06:21 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-12-18 07:01:08 -0500
commit3f7cceeab895fcc17ac8db0d9a5e8ca2954b4661 (patch)
tree9db4a171779ee9f9c15633ca221a943d64154293 /drivers/pci/controller/dwc
parente24b6b513e747727ee56b77ad46f04dff36cee53 (diff)
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>
Diffstat (limited to 'drivers/pci/controller/dwc')
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 2cbef2d7c207..4a307cdf20c8 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -27,6 +27,8 @@
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/reset.h> 29#include <linux/reset.h>
30#include <linux/pm_domain.h>
31#include <linux/pm_runtime.h>
30 32
31#include "pcie-designware.h" 33#include "pcie-designware.h"
32 34
@@ -59,6 +61,11 @@ struct imx6_pcie {
59 u32 tx_swing_low; 61 u32 tx_swing_low;
60 int link_gen; 62 int link_gen;
61 struct regulator *vpcie; 63 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;
62}; 69};
63 70
64/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ 71/* 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,
292 return 1; 299 return 1;
293} 300}
294 301
302static 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
295static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) 339static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
296{ 340{
297 struct device *dev = imx6_pcie->pci->dev; 341 struct device *dev = imx6_pcie->pci->dev;
@@ -985,6 +1029,10 @@ static int imx6_pcie_probe(struct platform_device *pdev)
985 1029
986 platform_set_drvdata(pdev, imx6_pcie); 1030 platform_set_drvdata(pdev, imx6_pcie);
987 1031
1032 ret = imx6_pcie_attach_pd(dev);
1033 if (ret)
1034 return ret;
1035
988 ret = imx6_add_pcie_port(imx6_pcie, pdev); 1036 ret = imx6_add_pcie_port(imx6_pcie, pdev);
989 if (ret < 0) 1037 if (ret < 0)
990 return ret; 1038 return ret;