diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2016-03-01 11:24:37 +0800 |
---|---|---|
committer | Richard Zhu <hongxing.zhu@nxp.com> | 2016-03-02 13:44:11 +0800 |
commit | 5fe540248b63601d3528680d01c710987dbbbca2 (patch) | |
tree | 822f494c86caef7b8dda26f87185c017a13f8bed /drivers | |
parent | 2837639c9279e2b81b80ce6fd6e6f0df29cea9f5 (diff) |
MLK-12481 pci: imx: turn off pcie clks when link down
In order to save power consumption, turn off pcie clks/regulators
if there is no pcie link at all.
Summit this patch, because of that MLK-12278
doesn't turn off the clks/regulators actually.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
(cherry picked from commit 841b5c2c6890deebda63ddc119d201b700302262)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 31 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 7 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.h | 2 |
3 files changed, 25 insertions, 15 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 58707e935986..75f15ce8c0e2 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -502,6 +502,7 @@ static void imx6_pcie_init_phy(struct pcie_port *pp) static int imx6_pcie_wait_for_link(struct pcie_port *pp) { int count = 20000; + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); while (!dw_pcie_link_up(pp)) { udelay(10); @@ -512,6 +513,17 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); + + if (!IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) { + clk_disable_unprepare(imx6_pcie->pcie); + clk_disable_unprepare(imx6_pcie->pcie_bus); + clk_disable_unprepare(imx6_pcie->pcie_phy); + if (is_imx6sx_pcie(imx6_pcie)) + clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); + release_bus_freq(BUS_FREQ_HIGH); + if (imx6_pcie->pcie_phy_regulator != NULL) + regulator_disable(imx6_pcie->pcie_phy_regulator); + } return -EINVAL; } @@ -585,16 +597,6 @@ static int imx6_pcie_start_link(struct pcie_port *pp) if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - if (!IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) { - clk_disable_unprepare(imx6_pcie->pcie); - clk_disable_unprepare(imx6_pcie->pcie_bus); - clk_disable_unprepare(imx6_pcie->pcie_phy); - if (is_imx6sx_pcie(imx6_pcie)) - clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); - release_bus_freq(BUS_FREQ_HIGH); - if (imx6_pcie->pcie_phy_regulator != NULL) - regulator_disable(imx6_pcie->pcie_phy_regulator); - } } else { tmp = readl(pp->dbi_base + 0x80); dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); @@ -603,8 +605,9 @@ static int imx6_pcie_start_link(struct pcie_port *pp) return ret; } -static void imx6_pcie_host_init(struct pcie_port *pp) +static int imx6_pcie_host_init(struct pcie_port *pp) { + int ret; struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); /* enable disp_mix power domain */ @@ -619,10 +622,14 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_setup_rc(pp); - imx6_pcie_start_link(pp); + ret = imx6_pcie_start_link(pp); + if (ret < 0) + return ret; if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp); + + return 0; } static void imx6_pcie_reset_phy(struct pcie_port *pp) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 12aa7ca33c8b..e179a7621cfa 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -512,8 +512,11 @@ int dw_pcie_host_init(struct pcie_port *pp) } } - if (pp->ops->host_init) - pp->ops->host_init(pp); + if (pp->ops->host_init) { + ret = pp->ops->host_init(pp); + if (ret < 0) + return ret; + } dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index 13b475869718..c55a1e75c1f0 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h @@ -68,7 +68,7 @@ struct pcie_host_ops { int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); int (*link_up)(struct pcie_port *pp); - void (*host_init)(struct pcie_port *pp); + int (*host_init)(struct pcie_port *pp); void (*msi_set_irq)(struct pcie_port *pp, int irq); void (*msi_clear_irq)(struct pcie_port *pp, int irq); u32 (*get_msi_addr)(struct pcie_port *pp); |