Commit c0d12ce9fd7dbec07ec5f26f2ef830b9c385356f
1 parent
6adee22e7f
Exists in
smarc-l5.0.0_1.0.0-ga
and in
2 other branches
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)
Showing 3 changed files with 33 additions and 7 deletions Side-by-side Diff
drivers/pci/host/pci-imx6.c
... | ... | @@ -422,7 +422,7 @@ |
422 | 422 | return IRQ_HANDLED; |
423 | 423 | } |
424 | 424 | |
425 | -static void imx6_pcie_host_init(struct pcie_port *pp) | |
425 | +static int imx6_pcie_host_init(struct pcie_port *pp) | |
426 | 426 | { |
427 | 427 | int count = 0; |
428 | 428 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); |
429 | 429 | |
... | ... | @@ -459,14 +459,37 @@ |
459 | 459 | "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", |
460 | 460 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), |
461 | 461 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); |
462 | - return; | |
462 | + clk_disable_unprepare(imx6_pcie->pcie_axi); | |
463 | + if (!IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS) | |
464 | + && !IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)) | |
465 | + clk_disable_unprepare(imx6_pcie->lvds_gate); | |
466 | + clk_disable_unprepare(imx6_pcie->pcie_ref_125m); | |
467 | + if (is_imx6sx_pcie(imx6_pcie)) { | |
468 | + /* Disable clks and power down PCIe PHY */ | |
469 | + clk_disable_unprepare(imx6_pcie->dis_axi); | |
470 | + release_bus_freq(BUS_FREQ_HIGH); | |
471 | + | |
472 | + /* Put PCIe PHY to be isolation */ | |
473 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, | |
474 | + IOMUXC_GPR0, BIT(6), 1 << 6); | |
475 | + | |
476 | + /* | |
477 | + * Power down PCIe PHY. | |
478 | + */ | |
479 | + regulator_disable(imx6_pcie->pcie_phy_reg); | |
480 | + regulator_disable(imx6_pcie->pcie_reg); | |
481 | + } else { | |
482 | + clk_disable_unprepare(imx6_pcie->sata_ref_100m); | |
483 | + release_bus_freq(BUS_FREQ_HIGH); | |
484 | + } | |
485 | + return -ENODEV; | |
463 | 486 | } |
464 | 487 | } |
465 | 488 | |
466 | 489 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
467 | 490 | dw_pcie_msi_init(pp); |
468 | 491 | |
469 | - return; | |
492 | + return 0; | |
470 | 493 | } |
471 | 494 | |
472 | 495 | static int imx6_pcie_link_up(struct pcie_port *pp) |
drivers/pci/host/pcie-designware.c
... | ... | @@ -408,7 +408,7 @@ |
408 | 408 | struct of_pci_range range; |
409 | 409 | struct of_pci_range_parser parser; |
410 | 410 | u32 val; |
411 | - int i; | |
411 | + int i, ret = 0; | |
412 | 412 | |
413 | 413 | if (of_pci_range_parser_init(&parser, np)) { |
414 | 414 | dev_err(pp->dev, "missing ranges property\n"); |
... | ... | @@ -489,8 +489,11 @@ |
489 | 489 | irq_create_mapping(pp->irq_domain, i); |
490 | 490 | } |
491 | 491 | |
492 | - if (pp->ops->host_init) | |
493 | - pp->ops->host_init(pp); | |
492 | + if (pp->ops->host_init) { | |
493 | + ret = pp->ops->host_init(pp); | |
494 | + if (ret < 0) | |
495 | + return -ENODEV; | |
496 | + } | |
494 | 497 | |
495 | 498 | dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); |
496 | 499 |
drivers/pci/host/pcie-designware.h
... | ... | @@ -107,7 +107,7 @@ |
107 | 107 | int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); |
108 | 108 | int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val); |
109 | 109 | int (*link_up)(struct pcie_port *pp); |
110 | - void (*host_init)(struct pcie_port *pp); | |
110 | + int (*host_init)(struct pcie_port *pp); | |
111 | 111 | void (*msi_set_irq)(struct pcie_port *pp, int irq); |
112 | 112 | void (*msi_clear_irq)(struct pcie_port *pp, int irq); |
113 | 113 | u32 (*get_msi_data)(struct pcie_port *pp); |