summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Zhu <hongxing.zhu@nxp.com>2016-03-01 11:24:37 +0800
committerRichard Zhu <hongxing.zhu@nxp.com>2016-03-02 13:44:11 +0800
commit5fe540248b63601d3528680d01c710987dbbbca2 (patch)
tree822f494c86caef7b8dda26f87185c017a13f8bed
parent2837639c9279e2b81b80ce6fd6e6f0df29cea9f5 (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)
-rw-r--r--drivers/pci/host/pci-imx6.c31
-rw-r--r--drivers/pci/host/pcie-designware.c7
-rw-r--r--drivers/pci/host/pcie-designware.h2
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);