summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorManikanta Maddireddy2019-06-18 20:01:41 +0200
committerLorenzo Pieralisi2019-06-20 18:12:45 +0200
commit1056dda8a8d662622fee123c4cc1845c8a8ea4bf (patch)
tree700e8a259b541adcde7f1b5c47b6679400da4f70 /drivers/pci
parentsoc/tegra: pmc: Export tegra_powergate_power_on() (diff)
downloadkernel-qcow2-linux-1056dda8a8d662622fee123c4cc1845c8a8ea4bf.tar.gz
kernel-qcow2-linux-1056dda8a8d662622fee123c4cc1845c8a8ea4bf.tar.xz
kernel-qcow2-linux-1056dda8a8d662622fee123c4cc1845c8a8ea4bf.zip
PCI: tegra: Handle failure cases in tegra_pcie_power_on()
Unroll the PCIe power on sequence if any one of the steps fails in tegra_pcie_power_on(). Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Acked-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/controller/pci-tegra.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index 464ba2538d52..85c5e6a1e529 100644
--- a/drivers/pci/controller/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
@@ -1052,7 +1052,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
err = clk_prepare_enable(pcie->pex_clk);
if (err) {
dev_err(dev, "failed to enable PEX clock: %d\n", err);
- return err;
+ goto regulator_disable;
}
reset_control_deassert(pcie->pex_rst);
} else {
@@ -1061,7 +1061,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
pcie->pex_rst);
if (err) {
dev_err(dev, "powerup sequence failed: %d\n", err);
- return err;
+ goto regulator_disable;
}
}
@@ -1070,24 +1070,40 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
err = clk_prepare_enable(pcie->afi_clk);
if (err < 0) {
dev_err(dev, "failed to enable AFI clock: %d\n", err);
- return err;
+ goto powergate;
}
if (soc->has_cml_clk) {
err = clk_prepare_enable(pcie->cml_clk);
if (err < 0) {
dev_err(dev, "failed to enable CML clock: %d\n", err);
- return err;
+ goto disable_afi_clk;
}
}
err = clk_prepare_enable(pcie->pll_e);
if (err < 0) {
dev_err(dev, "failed to enable PLLE clock: %d\n", err);
- return err;
+ goto disable_cml_clk;
}
return 0;
+
+disable_cml_clk:
+ if (soc->has_cml_clk)
+ clk_disable_unprepare(pcie->cml_clk);
+disable_afi_clk:
+ clk_disable_unprepare(pcie->afi_clk);
+powergate:
+ reset_control_assert(pcie->afi_rst);
+ reset_control_assert(pcie->pex_rst);
+ clk_disable_unprepare(pcie->pex_clk);
+ if (!dev->pm_domain)
+ tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+regulator_disable:
+ regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
+
+ return err;
}
static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)