diff options
author | Richard Zhu <Richard.Zhu@freescale.com> | 2014-12-18 14:02:37 +0800 |
---|---|---|
committer | Richard Zhu <Richard.Zhu@freescale.com> | 2014-12-22 08:58:22 +0800 |
commit | c0d12ce9fd7dbec07ec5f26f2ef830b9c385356f (patch) | |
tree | 5650692bd4fd32b362de0b8a61b675e97b0f52a7 /drivers | |
parent | 6adee22e7fbcad3ea39cf12b2bc3a534ff2f28f6 (diff) |
MLK-10017 PCI: save power when pcie is not used
In order to save power consumption, do the
following actions when pcie is not used.
- turn off clocks on imx6q/dl.
- turn off clocks and power on imx6sx
Signed-off-by: Richard Zhu <Richard.Zhu@freescale.com>
(cherry picked from commit e9796dfbae2a8b732022a6c96b3d7803099a70b5)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 29 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 9 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.h | 2 |
3 files changed, 33 insertions, 7 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 1d0c96120e9a..1d88f4201bef 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -422,7 +422,7 @@ static irqreturn_t imx_pcie_msi_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -static void imx6_pcie_host_init(struct pcie_port *pp) +static int imx6_pcie_host_init(struct pcie_port *pp) { int count = 0; struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); @@ -459,14 +459,37 @@ static void imx6_pcie_host_init(struct pcie_port *pp) "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)); - return; + clk_disable_unprepare(imx6_pcie->pcie_axi); + if (!IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS) + && !IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)) + clk_disable_unprepare(imx6_pcie->lvds_gate); + clk_disable_unprepare(imx6_pcie->pcie_ref_125m); + if (is_imx6sx_pcie(imx6_pcie)) { + /* Disable clks and power down PCIe PHY */ + clk_disable_unprepare(imx6_pcie->dis_axi); + release_bus_freq(BUS_FREQ_HIGH); + + /* Put PCIe PHY to be isolation */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, + IOMUXC_GPR0, BIT(6), 1 << 6); + + /* + * Power down PCIe PHY. + */ + regulator_disable(imx6_pcie->pcie_phy_reg); + regulator_disable(imx6_pcie->pcie_reg); + } else { + clk_disable_unprepare(imx6_pcie->sata_ref_100m); + release_bus_freq(BUS_FREQ_HIGH); + } + return -ENODEV; } } if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp); - return; + return 0; } static int imx6_pcie_link_up(struct pcie_port *pp) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 882c713145bb..a320e5a3d4f5 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -408,7 +408,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) struct of_pci_range range; struct of_pci_range_parser parser; u32 val; - int i; + int i, ret = 0; if (of_pci_range_parser_init(&parser, np)) { dev_err(pp->dev, "missing ranges property\n"); @@ -489,8 +489,11 @@ int __init dw_pcie_host_init(struct pcie_port *pp) irq_create_mapping(pp->irq_domain, i); } - 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 -ENODEV; + } 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 c3caa81ad85f..6396ecdb198f 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h @@ -107,7 +107,7 @@ struct pcie_host_ops { int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); int (*wr_own_conf)(struct pcie_port *pp, 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_data)(struct pcie_port *pp); |