diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 1d0c961..1d88f42 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 882c713..a320e5a 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 c3caa81a..6396ecd 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);