Power supply for PCI inbound/outbound window registers is off when system
go to deep-sleep state. We save the values of registers before suspend
and restore to registers after resume.

Signed-off-by: Jiang Yutang <b14...@freescale.com>
Signed-off-by: Jia Hongtao <b38...@freescale.com>
Signed-off-by: Li Yang <le...@freescale.com>
---
Changes for V4:
We just rebase the patch upon following patch:
powerpc/fsl-pci: Unify pci/pcie initialization code

 arch/powerpc/include/asm/pci-bridge.h |    2 +-
 arch/powerpc/sysdev/fsl_pci.c         |  121 +++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h 
b/arch/powerpc/include/asm/pci-bridge.h
index ac39e6a..823e000 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -89,9 +89,9 @@ struct pci_controller {
 
 #ifdef CONFIG_PPC64
        unsigned long buid;
+#endif /* CONFIG_PPC64 */
 
        void *private_data;
-#endif /* CONFIG_PPC64 */
 };
 
 /* These are used for config access before all the PCI probing
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index e577cb5..8c15177 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -887,12 +887,133 @@ static int __devinit fsl_pci_probe(struct 
platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_SUSPEND
+
+#define PCI_POW_PIW_OFFSET     0xc00
+#define PCI_POW_PIW_SIZE       0x200
+#define PCI_POW_NUMBER         5
+
+static int fsl_pci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct pci_controller *hose;
+       struct pci_outbound_window_regs *pci_saved_pow;
+       struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+       struct resource pci_rsrc;
+       unsigned int i;
+       struct fsl_pci_private_data *sus_info;
+
+       hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+       of_address_to_resource(pdev->dev.of_node, 0, &pci_rsrc);
+
+       sus_info = kmalloc(
+                       sizeof(struct fsl_pci_private_data), GFP_KERNEL);
+       if (!sus_info)
+               return -ENOMEM;
+
+       hose->private_data = sus_info;
+
+       sus_info->pci_pow = ioremap(pci_rsrc.start + PCI_POW_PIW_OFFSET,
+                       PCI_POW_PIW_SIZE);
+       if (!sus_info->pci_pow) {
+               dev_err(&pdev->dev, "pci outbound/inbound windows ioremap 
error!\n");
+               goto err1;
+       }
+
+       sus_info->pci_piw = (struct pci_inbound_window_regs *)
+               ((void *)sus_info->pci_pow + PCI_POW_PIW_SIZE) - 1;
+
+       if (of_device_is_compatible(pdev->dev.of_node, "fsl,qoriq-pcie-v2.2"))
+               sus_info->inbound_num = 4;
+       else
+               sus_info->inbound_num = 3;
+
+       sus_info->saved_regs = kmalloc(
+               sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER +
+               sizeof(struct pci_inbound_window_regs) * sus_info->inbound_num,
+               GFP_KERNEL);
+       if (!sus_info->saved_regs)
+               goto err2;
+
+       pci_saved_pow = sus_info->saved_regs;
+       for (i = 0; i < PCI_POW_NUMBER; i++) {
+               pci_saved_pow[i].potar = in_be32(&sus_info->pci_pow[i].potar);
+               pci_saved_pow[i].potear = in_be32(&sus_info->pci_pow[i].potear);
+               pci_saved_pow[i].powbar = in_be32(&sus_info->pci_pow[i].powbar);
+               pci_saved_pow[i].powar = in_be32(&sus_info->pci_pow[i].powar);
+       }
+
+       pci_saved_piw = (struct pci_inbound_window_regs *)
+               (pci_saved_pow + PCI_POW_NUMBER);
+       temp_piw = sus_info->pci_piw;
+       for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+               pci_saved_piw[i].pitar = in_be32(&temp_piw->pitar);
+               pci_saved_piw[i].piwbar = in_be32(&temp_piw->piwbar);
+               pci_saved_piw[i].piwbear = in_be32(&temp_piw->piwbear);
+               pci_saved_piw[i].piwar = in_be32(&temp_piw->piwar);
+       }
+
+       return 0;
+
+err2:
+       iounmap(sus_info->pci_pow);
+
+err1:
+       kfree(sus_info);
+       return -ENOMEM;
+}
+
+static int fsl_pci_resume(struct platform_device *pdev)
+{
+       struct pci_controller *hose;
+       struct pci_outbound_window_regs *pci_saved_pow;
+       struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+       unsigned int i;
+       struct fsl_pci_private_data *sus_info;
+
+       hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+       sus_info = (struct fsl_pci_private_data *)hose->private_data;
+
+       if (!sus_info->pci_pow || !sus_info->pci_piw || !sus_info->saved_regs)
+               return 0;
+
+       pci_saved_pow = sus_info->saved_regs;
+       for (i = 0; i < PCI_POW_NUMBER; i++) {
+               out_be32(&sus_info->pci_pow[i].potar, pci_saved_pow[i].potar);
+               out_be32(&sus_info->pci_pow[i].potear, pci_saved_pow[i].potear);
+               out_be32(&sus_info->pci_pow[i].powbar, pci_saved_pow[i].powbar);
+               out_be32(&sus_info->pci_pow[i].powar, pci_saved_pow[i].powar);
+       }
+
+       pci_saved_piw = (struct pci_inbound_window_regs *)
+               (pci_saved_pow + PCI_POW_NUMBER);
+       temp_piw = sus_info->pci_piw;
+       for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+               out_be32(&temp_piw->pitar, pci_saved_piw[i].pitar);
+               out_be32(&temp_piw->piwbar, pci_saved_piw[i].piwbar);
+               out_be32(&temp_piw->piwbear, pci_saved_piw[i].piwbear);
+               out_be32(&temp_piw->piwar, pci_saved_piw[i].piwar);
+       }
+       iounmap(sus_info->pci_pow);
+       kfree(sus_info->saved_regs);
+       sus_info->saved_regs = NULL;
+       kfree(sus_info);
+       sus_info = NULL;
+       hose->private_data = NULL;
+
+       return 0;
+}
+#endif
+
 static struct platform_driver fsl_pci_driver = {
        .driver = {
                .name = "fsl-pci",
                .of_match_table = pci_ids,
        },
        .probe = fsl_pci_probe,
+#ifdef CONFIG_SUSPEND
+       .suspend        = fsl_pci_suspend,
+       .resume         = fsl_pci_resume,
+#endif
 };
 
 static int __init fsl_pci_init(void)
-- 
1.7.5.1


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to