aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2018-10-20 12:45:49 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-10-20 12:45:49 -0400
commit525fde0750394dd3874937361570764f6a368e33 (patch)
tree77aa31712a9957d935c50f504e98a455bbb72816 /drivers/pci/controller/dwc
parentb7c18dc06ad12059abc0961522d446553f8a755b (diff)
parentf4e833ba2a955bc15c1ccaa5b0b3c2a0d7989bca (diff)
Merge branch 'remotes/lorenzo/pci/dwc'
- Support 100MHz/200MHz refclocks for i.MX6 (Lucas Stach) - Add initial power management for i.MX7 (Leonard Crestez) - Add PME_Turn_Off support for i.MX7 (Leonard Crestez) - Fix qcom runtime power management error handling (Bjorn Andersson) - Update TI dra7xx unaligned access errata workaround for host mode as well as endpoint mode (Vignesh R) - Fix kirin section mismatch warning (Nathan Chancellor) * remotes/lorenzo/pci/dwc: PCI: imx: Add PME_Turn_Off support ARM: dts: imx7d: Add turnoff reset dt-bindings: imx6q-pcie: Add turnoff reset for imx7d reset: imx7: Add PCIE_CTRL_APPS_TURNOFF PCI: kirin: Fix section mismatch warning PCI: dwc: pci-dra7xx: Enable errata i870 for both EP and RC mode dt-bindings: PCI: dra7xx: Add bindings for unaligned access in host mode PCI: qcom: Fix error handling in runtime PM support PCI: imx: Initial imx7d pm support PCI: imx6: Support MPLL reconfiguration for 100MHz and 200MHz refclock
Diffstat (limited to 'drivers/pci/controller/dwc')
-rw-r--r--drivers/pci/controller/dwc/pci-dra7xx.c11
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c176
-rw-r--r--drivers/pci/controller/dwc/pcie-kirin.c4
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c56
4 files changed, 220 insertions, 27 deletions
diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index ce9224a36f62..a32d6dde7a57 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -542,7 +542,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
542}; 542};
543 543
544/* 544/*
545 * dra7xx_pcie_ep_unaligned_memaccess: workaround for AM572x/AM571x Errata i870 545 * dra7xx_pcie_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
546 * @dra7xx: the dra7xx device where the workaround should be applied 546 * @dra7xx: the dra7xx device where the workaround should be applied
547 * 547 *
548 * Access to the PCIe slave port that are not 32-bit aligned will result 548 * Access to the PCIe slave port that are not 32-bit aligned will result
@@ -552,7 +552,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
552 * 552 *
553 * To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1. 553 * To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1.
554 */ 554 */
555static int dra7xx_pcie_ep_unaligned_memaccess(struct device *dev) 555static int dra7xx_pcie_unaligned_memaccess(struct device *dev)
556{ 556{
557 int ret; 557 int ret;
558 struct device_node *np = dev->of_node; 558 struct device_node *np = dev->of_node;
@@ -704,6 +704,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
704 704
705 dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, 705 dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
706 DEVICE_TYPE_RC); 706 DEVICE_TYPE_RC);
707
708 ret = dra7xx_pcie_unaligned_memaccess(dev);
709 if (ret)
710 dev_err(dev, "WA for Errata i870 not applied\n");
711
707 ret = dra7xx_add_pcie_port(dra7xx, pdev); 712 ret = dra7xx_add_pcie_port(dra7xx, pdev);
708 if (ret < 0) 713 if (ret < 0)
709 goto err_gpio; 714 goto err_gpio;
@@ -717,7 +722,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
717 dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, 722 dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
718 DEVICE_TYPE_EP); 723 DEVICE_TYPE_EP);
719 724
720 ret = dra7xx_pcie_ep_unaligned_memaccess(dev); 725 ret = dra7xx_pcie_unaligned_memaccess(dev);
721 if (ret) 726 if (ret)
722 goto err_gpio; 727 goto err_gpio;
723 728
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 4a9a673b4777..2cbef2d7c207 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -50,6 +50,7 @@ struct imx6_pcie {
50 struct regmap *iomuxc_gpr; 50 struct regmap *iomuxc_gpr;
51 struct reset_control *pciephy_reset; 51 struct reset_control *pciephy_reset;
52 struct reset_control *apps_reset; 52 struct reset_control *apps_reset;
53 struct reset_control *turnoff_reset;
53 enum imx6_pcie_variants variant; 54 enum imx6_pcie_variants variant;
54 u32 tx_deemph_gen1; 55 u32 tx_deemph_gen1;
55 u32 tx_deemph_gen2_3p5db; 56 u32 tx_deemph_gen2_3p5db;
@@ -97,6 +98,16 @@ struct imx6_pcie {
97#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) 98#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
98 99
99/* PHY registers (not memory-mapped) */ 100/* PHY registers (not memory-mapped) */
101#define PCIE_PHY_ATEOVRD 0x10
102#define PCIE_PHY_ATEOVRD_EN (0x1 << 2)
103#define PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT 0
104#define PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK 0x1
105
106#define PCIE_PHY_MPLL_OVRD_IN_LO 0x11
107#define PCIE_PHY_MPLL_MULTIPLIER_SHIFT 2
108#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f
109#define PCIE_PHY_MPLL_MULTIPLIER_OVRD (0x1 << 9)
110
100#define PCIE_PHY_RX_ASIC_OUT 0x100D 111#define PCIE_PHY_RX_ASIC_OUT 0x100D
101#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) 112#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
102 113
@@ -508,6 +519,50 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
508 IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); 519 IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
509} 520}
510 521
522static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
523{
524 unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);
525 int mult, div;
526 u32 val;
527
528 switch (phy_rate) {
529 case 125000000:
530 /*
531 * The default settings of the MPLL are for a 125MHz input
532 * clock, so no need to reconfigure anything in that case.
533 */
534 return 0;
535 case 100000000:
536 mult = 25;
537 div = 0;
538 break;
539 case 200000000:
540 mult = 25;
541 div = 1;
542 break;
543 default:
544 dev_err(imx6_pcie->pci->dev,
545 "Unsupported PHY reference clock rate %lu\n", phy_rate);
546 return -EINVAL;
547 }
548
549 pcie_phy_read(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, &val);
550 val &= ~(PCIE_PHY_MPLL_MULTIPLIER_MASK <<
551 PCIE_PHY_MPLL_MULTIPLIER_SHIFT);
552 val |= mult << PCIE_PHY_MPLL_MULTIPLIER_SHIFT;
553 val |= PCIE_PHY_MPLL_MULTIPLIER_OVRD;
554 pcie_phy_write(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, val);
555
556 pcie_phy_read(imx6_pcie, PCIE_PHY_ATEOVRD, &val);
557 val &= ~(PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK <<
558 PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT);
559 val |= div << PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT;
560 val |= PCIE_PHY_ATEOVRD_EN;
561 pcie_phy_write(imx6_pcie, PCIE_PHY_ATEOVRD, val);
562
563 return 0;
564}
565
511static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) 566static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
512{ 567{
513 struct dw_pcie *pci = imx6_pcie->pci; 568 struct dw_pcie *pci = imx6_pcie->pci;
@@ -542,6 +597,24 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
542 return -EINVAL; 597 return -EINVAL;
543} 598}
544 599
600static void imx6_pcie_ltssm_enable(struct device *dev)
601{
602 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
603
604 switch (imx6_pcie->variant) {
605 case IMX6Q:
606 case IMX6SX:
607 case IMX6QP:
608 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
609 IMX6Q_GPR12_PCIE_CTL_2,
610 IMX6Q_GPR12_PCIE_CTL_2);
611 break;
612 case IMX7D:
613 reset_control_deassert(imx6_pcie->apps_reset);
614 break;
615 }
616}
617
545static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) 618static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
546{ 619{
547 struct dw_pcie *pci = imx6_pcie->pci; 620 struct dw_pcie *pci = imx6_pcie->pci;
@@ -560,11 +633,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
560 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); 633 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
561 634
562 /* Start LTSSM. */ 635 /* Start LTSSM. */
563 if (imx6_pcie->variant == IMX7D) 636 imx6_pcie_ltssm_enable(dev);
564 reset_control_deassert(imx6_pcie->apps_reset);
565 else
566 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
567 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
568 637
569 ret = imx6_pcie_wait_for_link(imx6_pcie); 638 ret = imx6_pcie_wait_for_link(imx6_pcie);
570 if (ret) 639 if (ret)
@@ -632,6 +701,7 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
632 imx6_pcie_assert_core_reset(imx6_pcie); 701 imx6_pcie_assert_core_reset(imx6_pcie);
633 imx6_pcie_init_phy(imx6_pcie); 702 imx6_pcie_init_phy(imx6_pcie);
634 imx6_pcie_deassert_core_reset(imx6_pcie); 703 imx6_pcie_deassert_core_reset(imx6_pcie);
704 imx6_setup_phy_mpll(imx6_pcie);
635 dw_pcie_setup_rc(pp); 705 dw_pcie_setup_rc(pp);
636 imx6_pcie_establish_link(imx6_pcie); 706 imx6_pcie_establish_link(imx6_pcie);
637 707
@@ -682,6 +752,94 @@ static const struct dw_pcie_ops dw_pcie_ops = {
682 .link_up = imx6_pcie_link_up, 752 .link_up = imx6_pcie_link_up,
683}; 753};
684 754
755#ifdef CONFIG_PM_SLEEP
756static void imx6_pcie_ltssm_disable(struct device *dev)
757{
758 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
759
760 switch (imx6_pcie->variant) {
761 case IMX6SX:
762 case IMX6QP:
763 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
764 IMX6Q_GPR12_PCIE_CTL_2, 0);
765 break;
766 case IMX7D:
767 reset_control_assert(imx6_pcie->apps_reset);
768 break;
769 default:
770 dev_err(dev, "ltssm_disable not supported\n");
771 }
772}
773
774static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
775{
776 reset_control_assert(imx6_pcie->turnoff_reset);
777 reset_control_deassert(imx6_pcie->turnoff_reset);
778
779 /*
780 * Components with an upstream port must respond to
781 * PME_Turn_Off with PME_TO_Ack but we can't check.
782 *
783 * The standard recommends a 1-10ms timeout after which to
784 * proceed anyway as if acks were received.
785 */
786 usleep_range(1000, 10000);
787}
788
789static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
790{
791 clk_disable_unprepare(imx6_pcie->pcie);
792 clk_disable_unprepare(imx6_pcie->pcie_phy);
793 clk_disable_unprepare(imx6_pcie->pcie_bus);
794
795 if (imx6_pcie->variant == IMX7D) {
796 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
797 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,
798 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
799 }
800}
801
802static int imx6_pcie_suspend_noirq(struct device *dev)
803{
804 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
805
806 if (imx6_pcie->variant != IMX7D)
807 return 0;
808
809 imx6_pcie_pm_turnoff(imx6_pcie);
810 imx6_pcie_clk_disable(imx6_pcie);
811 imx6_pcie_ltssm_disable(dev);
812
813 return 0;
814}
815
816static int imx6_pcie_resume_noirq(struct device *dev)
817{
818 int ret;
819 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
820 struct pcie_port *pp = &imx6_pcie->pci->pp;
821
822 if (imx6_pcie->variant != IMX7D)
823 return 0;
824
825 imx6_pcie_assert_core_reset(imx6_pcie);
826 imx6_pcie_init_phy(imx6_pcie);
827 imx6_pcie_deassert_core_reset(imx6_pcie);
828 dw_pcie_setup_rc(pp);
829
830 ret = imx6_pcie_establish_link(imx6_pcie);
831 if (ret < 0)
832 dev_info(dev, "pcie link is down after resume.\n");
833
834 return 0;
835}
836#endif
837
838static const struct dev_pm_ops imx6_pcie_pm_ops = {
839 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend_noirq,
840 imx6_pcie_resume_noirq)
841};
842
685static int imx6_pcie_probe(struct platform_device *pdev) 843static int imx6_pcie_probe(struct platform_device *pdev)
686{ 844{
687 struct device *dev = &pdev->dev; 845 struct device *dev = &pdev->dev;
@@ -776,6 +934,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
776 break; 934 break;
777 } 935 }
778 936
937 /* Grab turnoff reset */
938 imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
939 if (IS_ERR(imx6_pcie->turnoff_reset)) {
940 dev_err(dev, "Failed to get TURNOFF reset control\n");
941 return PTR_ERR(imx6_pcie->turnoff_reset);
942 }
943
779 /* Grab GPR config register range */ 944 /* Grab GPR config register range */
780 imx6_pcie->iomuxc_gpr = 945 imx6_pcie->iomuxc_gpr =
781 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); 946 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
@@ -848,6 +1013,7 @@ static struct platform_driver imx6_pcie_driver = {
848 .name = "imx6q-pcie", 1013 .name = "imx6q-pcie",
849 .of_match_table = imx6_pcie_of_match, 1014 .of_match_table = imx6_pcie_of_match,
850 .suppress_bind_attrs = true, 1015 .suppress_bind_attrs = true,
1016 .pm = &imx6_pcie_pm_ops,
851 }, 1017 },
852 .probe = imx6_pcie_probe, 1018 .probe = imx6_pcie_probe,
853 .shutdown = imx6_pcie_shutdown, 1019 .shutdown = imx6_pcie_shutdown,
diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c
index 5352e0c3be82..9b599296205d 100644
--- a/drivers/pci/controller/dwc/pcie-kirin.c
+++ b/drivers/pci/controller/dwc/pcie-kirin.c
@@ -467,8 +467,8 @@ static int kirin_pcie_add_msi(struct dw_pcie *pci,
467 return 0; 467 return 0;
468} 468}
469 469
470static int __init kirin_add_pcie_port(struct dw_pcie *pci, 470static int kirin_add_pcie_port(struct dw_pcie *pci,
471 struct platform_device *pdev) 471 struct platform_device *pdev)
472{ 472{
473 int ret; 473 int ret;
474 474
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 4352c1cb926d..d185ea5fe996 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1089,7 +1089,6 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
1089 struct qcom_pcie *pcie = to_qcom_pcie(pci); 1089 struct qcom_pcie *pcie = to_qcom_pcie(pci);
1090 int ret; 1090 int ret;
1091 1091
1092 pm_runtime_get_sync(pci->dev);
1093 qcom_ep_reset_assert(pcie); 1092 qcom_ep_reset_assert(pcie);
1094 1093
1095 ret = pcie->ops->init(pcie); 1094 ret = pcie->ops->init(pcie);
@@ -1126,7 +1125,6 @@ err_disable_phy:
1126 phy_power_off(pcie->phy); 1125 phy_power_off(pcie->phy);
1127err_deinit: 1126err_deinit:
1128 pcie->ops->deinit(pcie); 1127 pcie->ops->deinit(pcie);
1129 pm_runtime_put(pci->dev);
1130 1128
1131 return ret; 1129 return ret;
1132} 1130}
@@ -1216,6 +1214,12 @@ static int qcom_pcie_probe(struct platform_device *pdev)
1216 return -ENOMEM; 1214 return -ENOMEM;
1217 1215
1218 pm_runtime_enable(dev); 1216 pm_runtime_enable(dev);
1217 ret = pm_runtime_get_sync(dev);
1218 if (ret < 0) {
1219 pm_runtime_disable(dev);
1220 return ret;
1221 }
1222
1219 pci->dev = dev; 1223 pci->dev = dev;
1220 pci->ops = &dw_pcie_ops; 1224 pci->ops = &dw_pcie_ops;
1221 pp = &pci->pp; 1225 pp = &pci->pp;
@@ -1225,44 +1229,56 @@ static int qcom_pcie_probe(struct platform_device *pdev)
1225 pcie->ops = of_device_get_match_data(dev); 1229 pcie->ops = of_device_get_match_data(dev);
1226 1230
1227 pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); 1231 pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW);
1228 if (IS_ERR(pcie->reset)) 1232 if (IS_ERR(pcie->reset)) {
1229 return PTR_ERR(pcie->reset); 1233 ret = PTR_ERR(pcie->reset);
1234 goto err_pm_runtime_put;
1235 }
1230 1236
1231 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); 1237 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
1232 pcie->parf = devm_ioremap_resource(dev, res); 1238 pcie->parf = devm_ioremap_resource(dev, res);
1233 if (IS_ERR(pcie->parf)) 1239 if (IS_ERR(pcie->parf)) {
1234 return PTR_ERR(pcie->parf); 1240 ret = PTR_ERR(pcie->parf);
1241 goto err_pm_runtime_put;
1242 }
1235 1243
1236 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); 1244 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
1237 pci->dbi_base = devm_pci_remap_cfg_resource(dev, res); 1245 pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
1238 if (IS_ERR(pci->dbi_base)) 1246 if (IS_ERR(pci->dbi_base)) {
1239 return PTR_ERR(pci->dbi_base); 1247 ret = PTR_ERR(pci->dbi_base);
1248 goto err_pm_runtime_put;
1249 }
1240 1250
1241 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); 1251 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
1242 pcie->elbi = devm_ioremap_resource(dev, res); 1252 pcie->elbi = devm_ioremap_resource(dev, res);
1243 if (IS_ERR(pcie->elbi)) 1253 if (IS_ERR(pcie->elbi)) {
1244 return PTR_ERR(pcie->elbi); 1254 ret = PTR_ERR(pcie->elbi);
1255 goto err_pm_runtime_put;
1256 }
1245 1257
1246 pcie->phy = devm_phy_optional_get(dev, "pciephy"); 1258 pcie->phy = devm_phy_optional_get(dev, "pciephy");
1247 if (IS_ERR(pcie->phy)) 1259 if (IS_ERR(pcie->phy)) {
1248 return PTR_ERR(pcie->phy); 1260 ret = PTR_ERR(pcie->phy);
1261 goto err_pm_runtime_put;
1262 }
1249 1263
1250 ret = pcie->ops->get_resources(pcie); 1264 ret = pcie->ops->get_resources(pcie);
1251 if (ret) 1265 if (ret)
1252 return ret; 1266 goto err_pm_runtime_put;
1253 1267
1254 pp->ops = &qcom_pcie_dw_ops; 1268 pp->ops = &qcom_pcie_dw_ops;
1255 1269
1256 if (IS_ENABLED(CONFIG_PCI_MSI)) { 1270 if (IS_ENABLED(CONFIG_PCI_MSI)) {
1257 pp->msi_irq = platform_get_irq_byname(pdev, "msi"); 1271 pp->msi_irq = platform_get_irq_byname(pdev, "msi");
1258 if (pp->msi_irq < 0) 1272 if (pp->msi_irq < 0) {
1259 return pp->msi_irq; 1273 ret = pp->msi_irq;
1274 goto err_pm_runtime_put;
1275 }
1260 } 1276 }
1261 1277
1262 ret = phy_init(pcie->phy); 1278 ret = phy_init(pcie->phy);
1263 if (ret) { 1279 if (ret) {
1264 pm_runtime_disable(&pdev->dev); 1280 pm_runtime_disable(&pdev->dev);
1265 return ret; 1281 goto err_pm_runtime_put;
1266 } 1282 }
1267 1283
1268 platform_set_drvdata(pdev, pcie); 1284 platform_set_drvdata(pdev, pcie);
@@ -1271,10 +1287,16 @@ static int qcom_pcie_probe(struct platform_device *pdev)
1271 if (ret) { 1287 if (ret) {
1272 dev_err(dev, "cannot initialize host\n"); 1288 dev_err(dev, "cannot initialize host\n");
1273 pm_runtime_disable(&pdev->dev); 1289 pm_runtime_disable(&pdev->dev);
1274 return ret; 1290 goto err_pm_runtime_put;
1275 } 1291 }
1276 1292
1277 return 0; 1293 return 0;
1294
1295err_pm_runtime_put:
1296 pm_runtime_put(dev);
1297 pm_runtime_disable(dev);
1298
1299 return ret;
1278} 1300}
1279 1301
1280static const struct of_device_id qcom_pcie_match[] = { 1302static const struct of_device_id qcom_pcie_match[] = {