PCI: mvebu: add suspend/resume support
PATCH 1/1 PCI: mvebu: add suspend/resume support
This commit implements suspend/resume support for the mvebu PCIe host driver. Without this commit, the system will panic at resume time when PCIe devices are connected.
Note that we have to use the ->suspend_noirq() and ->resume_noirq() hooks, because at resume time, the PCI fixups are done at ->resume_noirq() time, so the PCIe controller has to be ready at this point.
--- drivers/pci/host/pci-mvebu.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
drivers/pci/host/pci-mvebu.c +38 -0
@@ -129,6 +129,7 @@ struct mvebu_pcie_port {size_t memwin_size;phys_addr_t iowin_base;size_t iowin_size; +u32 saved_pcie_stat; };static inline void mvebu_writel (struct mvebu_pcie_port *port,u32 val,u32 reg)
@@ -899,6 +900,35 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) pcie->msi->dev = &pcie->pdev->dev; } +static int mvebu_pcie_suspend (struct device *dev) +{ +struct mvebu_pcie *pcie; +int i; + + pcie =dev_get_drvdata (dev); +for (i =0 ; i < pcie->nports; i++) { +struct mvebu_pcie_port *port = pcie->ports + i; + port->saved_pcie_stat =mvebu_readl (port,PCIE_STAT_OFF ); + } + +return 0 ; +} + +static int mvebu_pcie_resume (struct device *dev) +{ +struct mvebu_pcie *pcie; +int i; + + pcie =dev_get_drvdata (dev); +for (i =0 ; i < pcie->nports; i++) { +struct mvebu_pcie_port *port = pcie->ports + i; +mvebu_writel (port, port->saved_pcie_stat,PCIE_STAT_OFF ); +mvebu_pcie_setup_hw (port); + } + +return 0 ; +} +static int mvebu_pcie_probe (struct platform_device *pdev) {struct mvebu_pcie *pcie;
@@ -1056,6 +1086,8 @@ static int mvebu_pcie_probe(struct platform_device *pdev)mvebu_pcie_msi_enable (pcie);mvebu_pcie_enable (pcie); +platform_set_drvdata (pdev, pcie); +return 0 ; }
@@ -1068,12 +1100,18 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = { };MODULE_DEVICE_TABLE (of, mvebu_pcie_of_match_table); +static struct dev_pm_ops mvebu_pcie_pm_ops = { + .suspend_noirq = mvebu_pcie_suspend, + .resume_noirq = mvebu_pcie_resume, +}; +static struct platform_driver mvebu_pcie_driver = { .driver = { .name ="mvebu-pcie" , .of_match_table = mvebu_pcie_of_match_table,/* driver unloading/unbinding currently not supported */ .suppress_bind_attrs = true, + .pm = &mvebu_pcie_pm_ops, }, .probe = mvebu_pcie_probe, };
Signature · 1 line
2.1.0
PATCH 1/1 PCI: mvebu: add suspend/resume support
Hey Thomas,
Quoted 19 lines · Thomas Petazzoni
This commit implements suspend/resume support for the mvebu PCIe host driver. Without this commit, the system will panic at resume time when PCIe devices are connected.
Note that we have to use the ->suspend_noirq() and ->resume_noirq() hooks, because at resume time, the PCI fixups are done at ->resume_noirq() time, so the PCIe controller has to be ready at this point.
Signed-off-by Thomas Petazzoni <[email protected]>--- drivers/pci/host/pci-mvebu.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)drivers/pci/host/pci-mvebu.c +0
-0
drivers/pci/host/pci-mvebu.c struct mvebu_pcie_port { · line 132
Quoted 4 lines
drivers/pci/host/pci-mvebu.c +1
-0@@ -129,6 +129,7 @@ struct mvebu_pcie_port {size_t memwin_size;phys_addr_t iowin_base;size_t iowin_size; +u32 saved_pcie_stat;
nit: It's already in the pcie port struct, why not just call it saved_state?
Either way,
thx,
Jason.
PATCH 1/1 PCI: mvebu: add suspend/resume support
Dear Jason Cooper,
Quoted 11 lines · Jason Cooper
drivers/pci/host/pci-mvebu.c struct mvebu_pcie_port { · line 132
Quoted 9 lines
drivers/pci/host/pci-mvebu.c +1
-0@@ -129,6 +129,7 @@ struct mvebu_pcie_port {size_t memwin_size;phys_addr_t iowin_base;size_t iowin_size; +u32 saved_pcie_stat;nit: It's already in the pcie port struct, why not just call it
saved_state?
Well the "stat" does not mean "state", but refers to the register being saved in this field. The register is called: PCIE_STAT_OFF. Hence the name saved_pcie_stat. But I'm fine with changing this to some other name, I really don't care :)
Quoted 3 lines
Either way,
Acked-by Jason Cooper <[email protected]>
Thanks!
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
Bjorn Helgaas
maintainerPATCH 1/1 PCI: mvebu: add suspend/resume support
In reply to Thomas PetazzoniQuoted 10 lines · Thomas Petazzoni
This commit implements suspend/resume support for the mvebu PCIe host driver. Without this commit, the system will panic at resume time when PCIe devices are connected.
Note that we have to use the ->suspend_noirq() and ->resume_noirq() hooks, because at resume time, the PCI fixups are done at ->resume_noirq() time, so the PCIe controller has to be ready at this point.
Signed-off-by Thomas Petazzoni <[email protected]>
Applied with Jason's ack to pci/host-mvebu for v4.1, thanks!
Quoted 83 lines
--- drivers/pci/host/pci-mvebu.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)drivers/pci/host/pci-mvebu.c +38
-0@@ -129,6 +129,7 @@ struct mvebu_pcie_port {size_t memwin_size;phys_addr_t iowin_base;size_t iowin_size; +u32 saved_pcie_stat; };static inline void mvebu_writel (struct mvebu_pcie_port *port,u32 val,u32 reg)@@ -899,6 +900,35 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) pcie->msi->dev = &pcie->pdev->dev; } +static int mvebu_pcie_suspend (struct device *dev) +{ +struct mvebu_pcie *pcie; +int i; + + pcie =dev_get_drvdata (dev); +for (i =0 ; i < pcie->nports; i++) { +struct mvebu_pcie_port *port = pcie->ports + i; + port->saved_pcie_stat =mvebu_readl (port,PCIE_STAT_OFF ); + } + +return 0 ; +} + +static int mvebu_pcie_resume (struct device *dev) +{ +struct mvebu_pcie *pcie; +int i; + + pcie =dev_get_drvdata (dev); +for (i =0 ; i < pcie->nports; i++) { +struct mvebu_pcie_port *port = pcie->ports + i; +mvebu_writel (port, port->saved_pcie_stat,PCIE_STAT_OFF ); +mvebu_pcie_setup_hw (port); + } + +return 0 ; +} +static int mvebu_pcie_probe (struct platform_device *pdev) {struct mvebu_pcie *pcie;@@ -1056,6 +1086,8 @@ static int mvebu_pcie_probe(struct platform_device *pdev)mvebu_pcie_msi_enable (pcie);mvebu_pcie_enable (pcie); +platform_set_drvdata (pdev, pcie); +return 0 ; }@@ -1068,12 +1100,18 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = { };MODULE_DEVICE_TABLE (of, mvebu_pcie_of_match_table); +static struct dev_pm_ops mvebu_pcie_pm_ops = { + .suspend_noirq = mvebu_pcie_suspend, + .resume_noirq = mvebu_pcie_resume, +}; +static struct platform_driver mvebu_pcie_driver = { .driver = { .name ="mvebu-pcie" , .of_match_table = mvebu_pcie_of_match_table,/* driver unloading/unbinding currently not supported */ .suppress_bind_attrs = true, + .pm = &mvebu_pcie_pm_ops, }, .probe = mvebu_pcie_probe, };Signature · 1 line
2.1.0