Skip to content

Commit f4e833b

Browse files
cdleonardLorenzo Pieralisi
authored andcommitted
PCI: imx: Add PME_Turn_Off support
When the root complex suspends it must send a PME_Turn_Off TLP. Implement this by asserting the "turnoff" reset. On imx7d this functionality is part of the System Reset Controller (SRC) and is exposed through the linux reset-controller subsystem. On imx6 equivalent bits are in the IOMUXC pinmux controller General Purpose Register (GPR) area which the imx6-pcie driver accesses directly. This is only for imx7d right now but it's deliberately implemented as an optional reset, ignoring the chip variant: * Older dtbs won't have this reset so it will be ignored. * Future chips might also expose this as a reset controller. For example imx8m (not yet supported) has the exact same PCIE_CTRL_APPS_TURNOFF bit in the same location. Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
1 parent 3aedf7e commit f4e833b

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

drivers/pci/controller/dwc/pci-imx6.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct imx6_pcie {
5050
struct regmap *iomuxc_gpr;
5151
struct reset_control *pciephy_reset;
5252
struct reset_control *apps_reset;
53+
struct reset_control *turnoff_reset;
5354
enum imx6_pcie_variants variant;
5455
u32 tx_deemph_gen1;
5556
u32 tx_deemph_gen2_3p5db;
@@ -770,6 +771,21 @@ static void imx6_pcie_ltssm_disable(struct device *dev)
770771
}
771772
}
772773

774+
static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
775+
{
776+
reset_control_assert(imx6_pcie->turnoff_reset);
777+
reset_control_deassert(imx6_pcie->turnoff_reset);
778+
779+
/*
780+
* Components with an upstream port must respond to
781+
* PME_Turn_Off with PME_TO_Ack but we can't check.
782+
*
783+
* The standard recommends a 1-10ms timeout after which to
784+
* proceed anyway as if acks were received.
785+
*/
786+
usleep_range(1000, 10000);
787+
}
788+
773789
static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
774790
{
775791
clk_disable_unprepare(imx6_pcie->pcie);
@@ -790,6 +806,7 @@ static int imx6_pcie_suspend_noirq(struct device *dev)
790806
if (imx6_pcie->variant != IMX7D)
791807
return 0;
792808

809+
imx6_pcie_pm_turnoff(imx6_pcie);
793810
imx6_pcie_clk_disable(imx6_pcie);
794811
imx6_pcie_ltssm_disable(dev);
795812

@@ -917,6 +934,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
917934
break;
918935
}
919936

937+
/* Grab turnoff reset */
938+
imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
939+
if (IS_ERR(imx6_pcie->turnoff_reset)) {
940+
dev_err(dev, "Failed to get TURNOFF reset control\n");
941+
return PTR_ERR(imx6_pcie->turnoff_reset);
942+
}
943+
920944
/* Grab GPR config register range */
921945
imx6_pcie->iomuxc_gpr =
922946
syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");

0 commit comments

Comments
 (0)